/* network.h
*
* Datatypes, functions and includes for the core networking.
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* Tox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tox. If not, see .
*
*/
#ifndef NETWORK_H
#define NETWORK_H
#include
#include
#include
#include
#include
#ifdef WIN32 /* Put win32 includes here */
#ifndef WINVER
//Windows XP
#define WINVER 0x0501
#endif
#include
#include
#include
typedef unsigned int sock_t;
/* sa_family_t is the sockaddr_in / sockaddr_in6 family field */
typedef short sa_family_t;
#ifndef IN6_ARE_ADDR_EQUAL
#ifdef IN6_ADDR_EQUAL
#define IN6_ARE_ADDR_EQUAL(a,b) IN6_ADDR_EQUAL(a,b)
#else
#define IN6_ARE_ADDR_EQUAL(a,b) \
((((__const uint32_t *) (a))[0] == ((__const uint32_t *) (b))[0]) \
&& (((__const uint32_t *) (a))[1] == ((__const uint32_t *) (b))[1]) \
&& (((__const uint32_t *) (a))[2] == ((__const uint32_t *) (b))[2]) \
&& (((__const uint32_t *) (a))[3] == ((__const uint32_t *) (b))[3]))
#endif
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#endif
#else // Linux includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef int sock_t;
#endif
#ifndef VANILLA_NACL
/* We use libsodium by default. */
#include
#else
#include
#include
#include
#include
#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
#endif
#ifndef crypto_secretbox_MACBYTES
#define crypto_secretbox_MACBYTES (crypto_secretbox_ZEROBYTES - crypto_secretbox_BOXZEROBYTES)
#endif
#ifndef IPV6_ADD_MEMBERSHIP
#ifdef IPV6_JOIN_GROUP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
#endif
#endif
#define MAX_UDP_PACKET_SIZE 65507
#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */
#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */
#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */
#define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID for IPv4 addresses. */
#define NET_PACKET_SEND_NODES_IPV6 4 /* Send nodes response packet ID for other addresses. */
#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */
#define NET_PACKET_SYNC 17 /* SYNC packet ID. */
#define NET_PACKET_DATA 18 /* Data packet ID. */
#define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */
#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */
#define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */
#define TOX_PORTRANGE_FROM 33445
#define TOX_PORTRANGE_TO 33545
#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM
typedef union {
uint8_t uint8[4];
uint16_t uint16[2];
uint32_t uint32;
struct in_addr in_addr;
} IP4;
typedef union {
uint8_t uint8[16];
uint16_t uint16[8];
uint32_t uint32[4];
struct in6_addr in6_addr;
} IP6;
typedef struct {
uint8_t family;
/* Not used for anything right now. */
uint8_t padding[3];
union {
IP4 ip4;
IP6 ip6;
};
} IP;
typedef union {
struct {
IP4 ip;
uint16_t port;
/* Not used for anything right now. */
uint16_t padding;
};
uint8_t uint8[8];
} IP4_Port;
typedef struct IP_Port {
IP ip;
uint16_t port;
} IP_Port;
#define TOX_ENABLE_IPV6_DEFAULT 1
/* ip_ntoa
* converts ip into a string
* uses a static buffer, so mustn't used multiple times in the same output
*/
const char *ip_ntoa(IP *ip);
/* ip_equal
* compares two IPAny structures
* unset means unequal
*
* returns 0 when not equal or when uninitialized
*/
int ip_equal(IP *a, IP *b);
/* ipport_equal
* compares two IPAny_Port structures
* unset means unequal
*
* returns 0 when not equal or when uninitialized
*/
int ipport_equal(IP_Port *a, IP_Port *b);
/* nulls out ip */
void ip_reset(IP *ip);
/* nulls out ip, sets family according to flag */
void ip_init(IP *ip, uint8_t ipv6enabled);
/* checks if ip is valid */
int ip_isset(IP *ip);
/* checks if ip is valid */
int ipport_isset(IP_Port *ipport);
/* copies an ip structure */
void ip_copy(IP *target, IP *source);
/* copies an ip_port structure */
void ipport_copy(IP_Port *target, IP_Port *source);
/*
* addr_resolve():
* uses getaddrinfo to resolve an address into an IP address
* uses the first IPv4/IPv6 addresses returned by getaddrinfo
*
* input
* address: a hostname (or something parseable to an IP address)
* to: to.family MUST be initialized, either set to a specific IP version
* (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
* IP versions are acceptable
* extra can be NULL and is only set in special circumstances, see returns
*
* returns in *to a valid IPAny (v4/v6),
* prefers v6 if ip.family was AF_UNSPEC and both available
* returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6
* returns 0 on failure
*/
int addr_resolve(const char *address, IP *to, IP *extra);
/*
* addr_resolve_or_parse_ip
* resolves string into an IP address
*
* address: a hostname (or something parseable to an IP address)
* to: to.family MUST be initialized, either set to a specific IP version
* (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
* IP versions are acceptable
* extra can be NULL and is only set in special circumstances, see returns
*
* returns in *tro a matching address (IPv6 or IPv4)
* returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC
* returns 1 on success
* returns 0 on failure
*/
int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra);
/* Function to receive data, ip and port of sender is put into ip_port.
* Packet data is put into data.
* Packet length is put into length.
*/
typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, uint8_t *data, uint32_t len);
typedef struct {
packet_handler_callback function;
void *object;
} Packet_Handles;
typedef struct {
Packet_Handles packethandlers[256];
sa_family_t family;
uint16_t port;
/* Our UDP socket. */
sock_t sock;
uint64_t send_fail_eagain;
} Networking_Core;
/* return current time in milleseconds since the epoch. */
uint64_t current_time(void);
/* return a random number.
*/
uint32_t random_int(void);
uint64_t random_64b(void);
/* Basic network functions: */
/* Function to send packet(data) of length length to ip_port. */
int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length);
/* Function to call when packet beginning with byte is received. */
void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object);
/* Call this several times a second. */
void networking_poll(Networking_Core *net);
/*
* functions to avoid excessive polling
*/
int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data, uint16_t *lenptr);
int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds);
void networking_wait_cleanup(Networking_Core *net, uint8_t *data, uint16_t len);
/* Initialize networking.
* bind to ip and port.
* ip must be in network order EX: 127.0.0.1 = (7F000001).
* port is in host byte order (this means don't worry about it).
*
* return 0 if no problems.
* return -1 if there were problems.
*/
Networking_Core *new_networking(IP ip, uint16_t port);
/* Function to cleanup networking stuff (doesn't do much right now). */
void kill_networking(Networking_Core *net);
#endif