From 3a8314270818241d161c5738ded2638e3b94c18a Mon Sep 17 00:00:00 2001 From: Dmytro Vorobiov Date: Mon, 6 Mar 2017 22:25:37 +0100 Subject: [PATCH] Updating toxcore to 0.1.6 --- toxcore-git | 2 +- toxcore.podspec | 2 +- toxcore/toxav/bwcontroller.m | 1 + toxcore/toxav/rtp.m | 1 + toxcore/toxav/toxav.m | 1 + toxcore/toxcore/DHT.m | 92 +++++++++++------ toxcore/toxcore/LAN_discovery.m | 59 ++++++++--- toxcore/toxcore/Messenger.h | 2 + toxcore/toxcore/Messenger.m | 50 +++++---- toxcore/toxcore/TCP_client.h | 2 +- toxcore/toxcore/TCP_client.m | 8 +- toxcore/toxcore/TCP_server.h | 10 +- toxcore/toxcore/TCP_server.m | 36 ++++--- toxcore/toxcore/network.h | 78 ++++++-------- toxcore/toxcore/network.m | 176 ++++++++++++++++++++++---------- toxcore/toxcore/tox.api.h | 2 +- toxcore/toxcore/tox.m | 12 ++- toxcore/toxcore/util.m | 2 + 18 files changed, 335 insertions(+), 201 deletions(-) diff --git a/toxcore-git b/toxcore-git index 995578f..895de7e 160000 --- a/toxcore-git +++ b/toxcore-git @@ -1 +1 @@ -Subproject commit 995578f1038842288c1ff552fd796ab2377db6e1 +Subproject commit 895de7ef26e7617769f2271345e414545c2581f8 diff --git a/toxcore.podspec b/toxcore.podspec index 872de6b..232d0e5 100644 --- a/toxcore.podspec +++ b/toxcore.podspec @@ -9,7 +9,7 @@ Pod::Spec.new do |s| s.name = "toxcore" - s.version = "0.1.5" + s.version = "0.1.6" s.summary = "Cocoapods wrapper for toxcore" s.homepage = "https://github.com/Antidote-for-Tox/toxcore" s.license = 'GPLv3' diff --git a/toxcore/toxav/bwcontroller.m b/toxcore/toxav/bwcontroller.m index 19d9c71..397cebf 100644 --- a/toxcore/toxav/bwcontroller.m +++ b/toxcore/toxav/bwcontroller.m @@ -29,6 +29,7 @@ #include "../toxcore/util.h" #include +#include #define BWC_PACKET_ID 196 #define BWC_SEND_INTERVAL_MS 1000 diff --git a/toxcore/toxav/rtp.m b/toxcore/toxav/rtp.m index 5aff6af..9b7b1bf 100644 --- a/toxcore/toxav/rtp.m +++ b/toxcore/toxav/rtp.m @@ -30,6 +30,7 @@ #include "../toxcore/util.h" #include +#include #include diff --git a/toxcore/toxav/toxav.m b/toxcore/toxav/toxav.m index 0b95365..1710f2a 100644 --- a/toxcore/toxav/toxav.m +++ b/toxcore/toxav/toxav.m @@ -31,6 +31,7 @@ #include "../toxcore/util.h" #include +#include #include #include diff --git a/toxcore/toxcore/DHT.m b/toxcore/toxcore/DHT.m index 776313c..5f3a1d0 100644 --- a/toxcore/toxcore/DHT.m +++ b/toxcore/toxcore/DHT.m @@ -538,9 +538,12 @@ static int client_or_ip_port_in_list(Logger *log, Client_data *list, uint16_t le if (ip_port.ip.family == AF_INET) { if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { + char ip_str[IP_NTOA_LEN]; LOGGER_TRACE(log, "coipil[%u]: switching ipv4 from %s:%u to %s:%u", i, - ip_ntoa(&list[i].assoc4.ip_port.ip), ntohs(list[i].assoc4.ip_port.port), - ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); + ip_ntoa(&list[i].assoc4.ip_port.ip, ip_str, sizeof(ip_str)), + ntohs(list[i].assoc4.ip_port.port), + ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), + ntohs(ip_port.port)); } if (LAN_ip(list[i].assoc4.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) { @@ -552,9 +555,12 @@ static int client_or_ip_port_in_list(Logger *log, Client_data *list, uint16_t le } else if (ip_port.ip.family == AF_INET6) { if (!ipport_equal(&list[i].assoc6.ip_port, &ip_port)) { + char ip_str[IP_NTOA_LEN]; LOGGER_TRACE(log, "coipil[%u]: switching ipv6 from %s:%u to %s:%u", i, - ip_ntoa(&list[i].assoc6.ip_port.ip), ntohs(list[i].assoc6.ip_port.port), - ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); + ip_ntoa(&list[i].assoc6.ip_port.ip, ip_str, sizeof(ip_str)), + ntohs(list[i].assoc6.ip_port.port), + ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), + ntohs(ip_port.port)); } if (LAN_ip(list[i].assoc6.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) { @@ -785,12 +791,20 @@ int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *node return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good); } -static uint8_t cmp_public_key[CRYPTO_PUBLIC_KEY_SIZE]; +typedef struct { + const uint8_t *base_public_key; + Client_data entry; +} Cmp_data; + static int cmp_dht_entry(const void *a, const void *b) { - Client_data entry1, entry2; - memcpy(&entry1, a, sizeof(Client_data)); - memcpy(&entry2, b, sizeof(Client_data)); + Cmp_data cmp1, cmp2; + memcpy(&cmp1, a, sizeof(Cmp_data)); + memcpy(&cmp2, b, sizeof(Cmp_data)); + Client_data entry1 = cmp1.entry; + Client_data entry2 = cmp2.entry; + const uint8_t *cmp_public_key = cmp1.base_public_key; + int t1 = is_timeout(entry1.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry1.assoc6.timestamp, BAD_NODE_TIMEOUT); int t2 = is_timeout(entry2.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry2.assoc6.timestamp, BAD_NODE_TIMEOUT); @@ -851,8 +865,20 @@ static unsigned int store_node_ok(const Client_data *client, const uint8_t *publ static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) { - memcpy(cmp_public_key, comp_public_key, CRYPTO_PUBLIC_KEY_SIZE); - qsort(list, length, sizeof(Client_data), cmp_dht_entry); + // Pass comp_public_key to qsort with each Client_data entry, so the + // comparison function cmp_dht_entry can use it as the base of comparison. + Cmp_data cmp_list[length]; + + for (uint32_t i = 0; i < length; i++) { + cmp_list[i].base_public_key = comp_public_key; + cmp_list[i].entry = list[i]; + } + + qsort(cmp_list, length, sizeof(Cmp_data), cmp_dht_entry); + + for (uint32_t i = 0; i < length; i++) { + list[i] = cmp_list[i].entry; + } } /* Replace a first bad (or empty) node with this one @@ -2533,36 +2559,36 @@ static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *pack { DHT *dht = (DHT *)object; - if (packet[0] == NET_PACKET_CRYPTO) { - if (length <= CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE + 1 + CRYPTO_MAC_SIZE || - length > MAX_CRYPTO_REQUEST_SIZE + CRYPTO_MAC_SIZE) { - return 1; - } + assert(packet[0] == NET_PACKET_CRYPTO); - if (public_key_cmp(packet + 1, dht->self_public_key) == 0) { // Check if request is for us. - uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; - uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; - uint8_t number; - int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); + if (length <= CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE + 1 + CRYPTO_MAC_SIZE || + length > MAX_CRYPTO_REQUEST_SIZE + CRYPTO_MAC_SIZE) { + return 1; + } - if (len == -1 || len == 0) { - return 1; - } + if (public_key_cmp(packet + 1, dht->self_public_key) == 0) { // Check if request is for us. + uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; + uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; + uint8_t number; + int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); - if (!dht->cryptopackethandlers[number].function) { - return 1; - } + if (len == -1 || len == 0) { + return 1; + } - return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key, - data, len, userdata); + if (!dht->cryptopackethandlers[number].function) { + return 1; } - /* If request is not for us, try routing it. */ - int retval = route_packet(dht, packet + 1, packet, length); + return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key, + data, len, userdata); + } - if ((unsigned int)retval == length) { - return 0; - } + /* If request is not for us, try routing it. */ + int retval = route_packet(dht, packet + 1, packet, length); + + if ((unsigned int)retval == length) { + return 0; } return 1; diff --git a/toxcore/toxcore/LAN_discovery.m b/toxcore/toxcore/LAN_discovery.m index 75dca60..e26f7ee 100644 --- a/toxcore/toxcore/LAN_discovery.m +++ b/toxcore/toxcore/LAN_discovery.m @@ -39,8 +39,10 @@ #define MAX_INTERFACES 16 +/* TODO: multiple threads might concurrently try to set these, and it isn't clear that this couldn't lead to undesirable + * behaviour. Consider storing the data in per-instance variables instead. */ static int broadcast_count = -1; -static IP_Port broadcast_ip_port[MAX_INTERFACES]; +static IP_Port broadcast_ip_ports[MAX_INTERFACES]; #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) @@ -48,8 +50,6 @@ static void fetch_broadcast_info(uint16_t port) { - broadcast_count = 0; - IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO); @@ -66,6 +66,13 @@ static void fetch_broadcast_info(uint16_t port) } } + /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info(). + * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid + * interfaces will be set to be broadcast to. + * */ + int count = 0; + IP_Port ip_ports[MAX_INTERFACES]; + int ret; if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { @@ -77,16 +84,16 @@ static void fetch_broadcast_info(uint16_t port) if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask) && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) { if (gateway.family == AF_INET && subnet_mask.family == AF_INET) { - IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; + IP_Port *ip_port = &ip_ports[count]; ip_port->ip.family = AF_INET; uint32_t gateway_ip = ntohl(gateway.ip4.uint32), subnet_ip = ntohl(subnet_mask.ip4.uint32); uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1; ip_port->ip.ip4.uint32 = htonl(broadcast_ip); ip_port->port = port; - broadcast_count++; + count++; - if (broadcast_count >= MAX_INTERFACES) { - return; + if (count >= MAX_INTERFACES) { + break; } } } @@ -98,6 +105,12 @@ static void fetch_broadcast_info(uint16_t port) if (pAdapterInfo) { free(pAdapterInfo); } + + broadcast_count = count; + + for (uint32_t i = 0; i < count; i++) { + broadcast_ip_ports[i] = ip_ports[i]; + } } #elif defined(__linux__) @@ -109,7 +122,7 @@ static void fetch_broadcast_info(uint16_t port) * Definitely won't work like this on Windows... */ broadcast_count = 0; - sock_t sock = 0; + Socket sock = 0; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { return; @@ -128,14 +141,21 @@ static void fetch_broadcast_info(uint16_t port) return; } + /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info(). + * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid + * interfaces will be set to be broadcast to. + * */ + int count = 0; + IP_Port ip_ports[MAX_INTERFACES]; + /* ifconf.ifc_len is set by the ioctl() to the actual length used; * on usage of the complete array the call should be repeated with * a larger array, not done (640kB and 16 interfaces shall be * enough, for everybody!) */ - int i, count = ifconf.ifc_len / sizeof(struct ifreq); + int i, n = ifconf.ifc_len / sizeof(struct ifreq); - for (i = 0; i < count; i++) { + for (i = 0; i < n; i++) { /* there are interfaces with are incapable of broadcast */ if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) { continue; @@ -148,24 +168,29 @@ static void fetch_broadcast_info(uint16_t port) struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; - if (broadcast_count >= MAX_INTERFACES) { - close(sock); - return; + if (count >= MAX_INTERFACES) { + break; } - IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; + IP_Port *ip_port = &ip_ports[count]; ip_port->ip.family = AF_INET; - ip_port->ip.ip4.in_addr = sock4->sin_addr; + get_ip4(&ip_port->ip.ip4, &sock4->sin_addr); if (ip_port->ip.ip4.uint32 == 0) { continue; } ip_port->port = port; - broadcast_count++; + count++; } close(sock); + + broadcast_count = count; + + for (uint32_t i = 0; i < count; i++) { + broadcast_ip_ports[i] = ip_ports[i]; + } } #else // TODO(irungentoo): Other platforms? @@ -196,7 +221,7 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8 int i; for (i = 0; i < broadcast_count; i++) { - sendpacket(net, broadcast_ip_port[i], data, length); + sendpacket(net, broadcast_ip_ports[i], data, length); } return 1; diff --git a/toxcore/toxcore/Messenger.h b/toxcore/toxcore/Messenger.h index 218ec18..e1dba69 100644 --- a/toxcore/toxcore/Messenger.h +++ b/toxcore/toxcore/Messenger.h @@ -240,6 +240,8 @@ struct Messenger { Friend *friendlist; uint32_t numfriends; + time_t lastdump; + uint8_t has_added_relays; // If the first connection has occurred in do_messenger Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config diff --git a/toxcore/toxcore/Messenger.m b/toxcore/toxcore/Messenger.m index db5b484..8291fab 100644 --- a/toxcore/toxcore/Messenger.m +++ b/toxcore/toxcore/Messenger.m @@ -2024,6 +2024,8 @@ static int friend_already_added(const uint8_t *real_pk, void *data) set_nospam(&(m->fr), random_int()); set_filter_function(&(m->fr), &friend_already_added, m); + m->lastdump = 0; + if (error) { *error = MESSENGER_ERROR_NONE; } @@ -2471,18 +2473,22 @@ static void connection_status_cb(Messenger *m, void *userdata) #define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL -static time_t lastdump = 0; -static char IDString[CRYPTO_PUBLIC_KEY_SIZE * 2 + 1]; -static char *ID2String(const uint8_t *pk) + +#define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1) +/* id_str should be of length at least IDSTRING_LEN */ +static char *id_to_string(const uint8_t *pk, char *id_str, size_t length) { - uint32_t i; + if (length < IDSTRING_LEN) { + snprintf(id_str, length, "Bad buf length"); + return id_str; + } - for (i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) { - sprintf(&IDString[i * 2], "%02X", pk[i]); + for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) { + sprintf(&id_str[i * 2], "%02X", pk[i]); } - IDString[CRYPTO_PUBLIC_KEY_SIZE * 2] = 0; - return IDString; + id_str[CRYPTO_PUBLIC_KEY_SIZE * 2] = 0; + return id_str; } /* Minimum messenger run interval in ms @@ -2546,8 +2552,8 @@ void do_messenger(Messenger *m, void *userdata) do_friends(m, userdata); connection_status_cb(m, userdata); - if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { - lastdump = unix_time(); + if (unix_time() > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { + m->lastdump = unix_time(); uint32_t client, last_pinged; for (client = 0; client < LCLIENT_LIST; client++) { @@ -2557,15 +2563,18 @@ void do_messenger(Messenger *m, void *userdata) for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) { if (ip_isset(&assoc->ip_port.ip)) { - last_pinged = lastdump - assoc->last_pinged; + last_pinged = m->lastdump - assoc->last_pinged; if (last_pinged > 999) { last_pinged = 999; } + char ip_str[IP_NTOA_LEN]; + char id_str[IDSTRING_LEN]; LOGGER_TRACE(m->log, "C[%2u] %s:%u [%3u] %s", - client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port), - last_pinged, ID2String(cptr->public_key)); + client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)), + ntohs(assoc->ip_port.port), last_pinged, + id_to_string(cptr->public_key, id_str, sizeof(id_str))); } } } @@ -2617,11 +2626,14 @@ void do_messenger(Messenger *m, void *userdata) dhtfptr = &m->dht->friends_list[friend_idx]; if (msgfptr) { + char id_str[IDSTRING_LEN]; LOGGER_TRACE(m->log, "F[%2u:%2u] <%s> %s", dht2m[friend_idx], friend_idx, msgfptr->name, - ID2String(msgfptr->real_pk)); + id_to_string(msgfptr->real_pk, id_str, sizeof(id_str))); } else { - LOGGER_TRACE(m->log, "F[--:%2u] %s", friend_idx, ID2String(dhtfptr->public_key)); + char id_str[IDSTRING_LEN]; + LOGGER_TRACE(m->log, "F[--:%2u] %s", friend_idx, + id_to_string(dhtfptr->public_key, id_str, sizeof(id_str))); } for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { @@ -2631,16 +2643,18 @@ void do_messenger(Messenger *m, void *userdata) for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) { if (ip_isset(&assoc->ip_port.ip)) { - last_pinged = lastdump - assoc->last_pinged; + last_pinged = m->lastdump - assoc->last_pinged; if (last_pinged > 999) { last_pinged = 999; } + char ip_str[IP_NTOA_LEN]; + char id_str[IDSTRING_LEN]; LOGGER_TRACE(m->log, "F[%2u] => C[%2u] %s:%u [%3u] %s", - friend_idx, client, ip_ntoa(&assoc->ip_port.ip), + friend_idx, client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)), ntohs(assoc->ip_port.port), last_pinged, - ID2String(cptr->public_key)); + id_to_string(cptr->public_key, id_str, sizeof(id_str))); } } } diff --git a/toxcore/toxcore/TCP_client.h b/toxcore/toxcore/TCP_client.h index 5e912d2..2125431 100644 --- a/toxcore/toxcore/TCP_client.h +++ b/toxcore/toxcore/TCP_client.h @@ -52,7 +52,7 @@ enum { }; typedef struct { uint8_t status; - sock_t sock; + Socket sock; uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */ IP_Port ip_port; /* The ip and port of the server */ diff --git a/toxcore/toxcore/TCP_client.m b/toxcore/toxcore/TCP_client.m index e6d8e3b..3d65415 100644 --- a/toxcore/toxcore/TCP_client.m +++ b/toxcore/toxcore/TCP_client.m @@ -36,7 +36,7 @@ /* return 1 on success * return 0 on failure */ -static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info) +static int connect_sock_to(Socket sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info) { if (proxy_info->proxy_type != TCP_PROXY_NONE) { ip_port = proxy_info->ip_port; @@ -51,14 +51,14 @@ static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_i addrsize = sizeof(struct sockaddr_in); addr4->sin_family = AF_INET; - addr4->sin_addr = ip_port.ip.ip4.in_addr; + fill_addr4(ip_port.ip.ip4, &addr4->sin_addr); addr4->sin_port = ip_port.port; } else if (ip_port.ip.family == AF_INET6) { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; addrsize = sizeof(struct sockaddr_in6); addr6->sin6_family = AF_INET6; - addr6->sin6_addr = ip_port.ip.ip6.in6_addr; + fill_addr6(ip_port.ip.ip6, &addr6->sin6_addr); addr6->sin6_port = ip_port.port; } else { return 0; @@ -653,7 +653,7 @@ void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(vo family = proxy_info->ip_port.ip.family; } - sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP); + Socket sock = socket(family, SOCK_STREAM, IPPROTO_TCP); if (!sock_valid(sock)) { return NULL; diff --git a/toxcore/toxcore/TCP_server.h b/toxcore/toxcore/TCP_server.h index b1c4295..7c1db65 100644 --- a/toxcore/toxcore/TCP_server.h +++ b/toxcore/toxcore/TCP_server.h @@ -90,7 +90,7 @@ struct TCP_Priority_List { }; typedef struct TCP_Secure_Connection { - sock_t sock; + Socket sock; uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */ uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */ @@ -137,7 +137,7 @@ void kill_TCP_server(TCP_Server *TCP_server); /* return the amount of data in the tcp recv buffer. * return 0 on failure. */ -unsigned int TCP_socket_data_recv_buffer(sock_t sock); +unsigned int TCP_socket_data_recv_buffer(Socket sock); /* Read the next two bytes in TCP stream then convert them to * length (host byte order). @@ -146,20 +146,20 @@ unsigned int TCP_socket_data_recv_buffer(sock_t sock); * return 0 if nothing has been read from socket. * return ~0 on failure. */ -uint16_t read_TCP_length(sock_t sock); +uint16_t read_TCP_length(Socket sock); /* Read length bytes from socket. * * return length on success * return -1 on failure/no data in buffer. */ -int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length); +int read_TCP_packet(Socket sock, uint8_t *data, uint16_t length); /* return length of received packet on success. * return 0 if could not read any packet. * return -1 on failure (connection must be killed). */ -int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, const uint8_t *shared_key, +int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len); diff --git a/toxcore/toxcore/TCP_server.m b/toxcore/toxcore/TCP_server.m index 5ea198a..47ad993 100644 --- a/toxcore/toxcore/TCP_server.m +++ b/toxcore/toxcore/TCP_server.m @@ -40,7 +40,7 @@ int efd; uint64_t last_run_pinged; #endif - sock_t *socks_listening; + Socket *socks_listening; unsigned int num_listening_socks; uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; @@ -69,10 +69,16 @@ size_t tcp_server_listen_count(const TCP_Server *tcp_server) return tcp_server->num_listening_socks; } +/* this is needed to compile on Android below API 21 +*/ +#ifndef EPOLLRDHUP +#define EPOLLRDHUP 0x2000 +#endif + /* return 1 on success * return 0 on failure */ -static int bind_to_port(sock_t sock, int family, uint16_t port) +static int bind_to_port(Socket sock, int family, uint16_t port) { struct sockaddr_storage addr = {0}; size_t addrsize; @@ -226,7 +232,7 @@ static int del_accepted(TCP_Server *TCP_server, int index) /* return the amount of data in the tcp recv buffer. * return 0 on failure. */ -unsigned int TCP_socket_data_recv_buffer(sock_t sock) +unsigned int TCP_socket_data_recv_buffer(Socket sock) { #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) unsigned long count = 0; @@ -246,7 +252,7 @@ unsigned int TCP_socket_data_recv_buffer(sock_t sock) * return 0 if nothing has been read from socket. * return ~0 on failure. */ -uint16_t read_TCP_length(sock_t sock) +uint16_t read_TCP_length(Socket sock) { unsigned int count = TCP_socket_data_recv_buffer(sock); @@ -276,7 +282,7 @@ uint16_t read_TCP_length(sock_t sock) * return length on success * return -1 on failure/no data in buffer. */ -int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length) +int read_TCP_packet(Socket sock, uint8_t *data, uint16_t length) { unsigned int count = TCP_socket_data_recv_buffer(sock); @@ -298,7 +304,7 @@ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length) * return 0 if could not read any packet. * return -1 on failure (connection must be killed). */ -int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, const uint8_t *shared_key, +int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) { if (*next_packet_length == 0) { @@ -523,7 +529,7 @@ static int kill_accepted(TCP_Server *TCP_server, int index) rm_connection_index(TCP_server, &TCP_server->accepted_connection_array[index], i); } - sock_t sock = TCP_server->accepted_connection_array[index].sock; + Socket sock = TCP_server->accepted_connection_array[index].sock; if (del_accepted(TCP_server, index) != 0) { return -1; @@ -965,7 +971,7 @@ static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection /* return index on success * return -1 on failure */ -static int accept_connection(TCP_Server *TCP_server, sock_t sock) +static int accept_connection(TCP_Server *TCP_server, Socket sock) { if (!sock_valid(sock)) { return -1; @@ -997,9 +1003,9 @@ static int accept_connection(TCP_Server *TCP_server, sock_t sock) return index; } -static sock_t new_listening_TCP_socket(int family, uint16_t port) +static Socket new_listening_TCP_socket(int family, uint16_t port) { - sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP); + Socket sock = socket(family, SOCK_STREAM, IPPROTO_TCP); if (!sock_valid(sock)) { return ~0; @@ -1042,7 +1048,7 @@ static sock_t new_listening_TCP_socket(int family, uint16_t port) return NULL; } - temp->socks_listening = (sock_t *)calloc(num_sockets, sizeof(sock_t)); + temp->socks_listening = (Socket *)calloc(num_sockets, sizeof(Socket)); if (temp->socks_listening == NULL) { free(temp); @@ -1074,7 +1080,7 @@ static sock_t new_listening_TCP_socket(int family, uint16_t port) #endif for (i = 0; i < num_sockets; ++i) { - sock_t sock = new_listening_TCP_socket(family, ports[i]); + Socket sock = new_listening_TCP_socket(family, ports[i]); if (sock_valid(sock)) { #ifdef TCP_SERVER_USE_EPOLL @@ -1118,7 +1124,7 @@ static void do_TCP_accept_new(TCP_Server *TCP_server) for (i = 0; i < TCP_server->num_listening_socks; ++i) { struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); - sock_t sock; + Socket sock; do { sock = accept(TCP_server->socks_listening[i], (struct sockaddr *)&addr, &addrlen); @@ -1286,7 +1292,7 @@ static void do_TCP_epoll(TCP_Server *TCP_server) int n; for (n = 0; n < nfds; ++n) { - sock_t sock = events[n].data.u64 & 0xFFFFFFFF; + Socket sock = events[n].data.u64 & 0xFFFFFFFF; int status = (events[n].data.u64 >> 32) & 0xFF, index = (events[n].data.u64 >> 40); if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP) || (events[n].events & EPOLLRDHUP)) { @@ -1327,7 +1333,7 @@ static void do_TCP_epoll(TCP_Server *TCP_server) socklen_t addrlen = sizeof(addr); while (1) { - sock_t sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen); + Socket sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen); if (!sock_valid(sock_new)) { break; diff --git a/toxcore/toxcore/network.h b/toxcore/toxcore/network.h index 45a63e2..a3b746c 100644 --- a/toxcore/toxcore/network.h +++ b/toxcore/toxcore/network.h @@ -24,6 +24,12 @@ #ifndef NETWORK_H #define NETWORK_H +#if defined(__GNUC__) +#define GNU_EXTENSION __extension__ +#else +#define GNU_EXTENSION +#endif + #ifdef PLAN9 #include // Plan 9 requires this is imported first // Comment line here to avoid reordering by source code formatters. @@ -52,53 +58,21 @@ #include #include -#ifndef IPV6_V6ONLY -#define IPV6_V6ONLY 27 -#endif - -typedef unsigned int sock_t; /* sa_family_t is the sockaddr_in / sockaddr_in6 family field */ typedef short sa_family_t; -#ifndef EWOULDBLOCK -#define EWOULDBLOCK WSAEWOULDBLOCK -#endif - #else // Linux includes #include -#include -#include #include -#include -#include -#include -#include #include -typedef int sock_t; - -#endif - -#if defined(__AIX__) -# define _XOPEN_SOURCE 1 #endif -#if defined(__sun__) -#define __EXTENSIONS__ 1 // SunOS! -#if defined(__SunOS5_6__) || defined(__SunOS5_7__) || defined(__SunOS5_8__) || defined(__SunOS5_9__) || defined(__SunOS5_10__) -//Nothing needed -#else -#define __MAKECONTEXT_V2_SOURCE 1 -#endif -#endif +struct in_addr; +struct in6_addr; -#ifndef IPV6_ADD_MEMBERSHIP -#ifdef IPV6_JOIN_GROUP -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -#endif -#endif +typedef int Socket; #define MAX_UDP_PACKET_SIZE 2048 @@ -148,7 +122,6 @@ typedef union { uint8_t uint8[4]; uint16_t uint16[2]; uint32_t uint32; - struct in_addr in_addr; } IP4; @@ -157,13 +130,12 @@ typedef union { uint16_t uint16[8]; uint32_t uint32[4]; uint64_t uint64[2]; - struct in6_addr in6_addr; } IP6; typedef struct { uint8_t family; - __extension__ union { + GNU_EXTENSION union { IP4 ip4; IP6 ip6; }; @@ -176,6 +148,14 @@ typedef struct { } IP_Port; +/* Convert in_addr to IP */ +void get_ip4(IP4 *ip, const struct in_addr *addr); +void get_ip6(IP6 *ip, const struct in6_addr *addr); + +/* Conevrt IP to in_addr */ +void fill_addr4(IP4 ip, struct in_addr *addr); +void fill_addr6(IP6 ip, struct in6_addr *addr); + /* Does the IP6 struct a contain an IPv4 address in an IPv6 one? */ #define IPV6_IPV4_IN_V6(a) ((a.uint64[0] == 0) && (a.uint32[2] == htonl (0xffff))) @@ -193,12 +173,16 @@ IP_Port; /* ip_ntoa * converts ip into a string - * uses a static buffer, so mustn't used multiple times in the same output + * ip_str must be of length at least IP_NTOA_LEN * * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]" * writes error message into the buffer on error + * + * returns ip_str */ -const char *ip_ntoa(const IP *ip); +/* this would be INET6_ADDRSTRLEN, but it might be too short for the error message */ +#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ? +const char *ip_ntoa(const IP *ip, char *ip_str, size_t length); /* * ip_parse_addr @@ -316,7 +300,7 @@ typedef struct { sa_family_t family; uint16_t port; /* Our UDP socket. */ - sock_t sock; + Socket sock; } Networking_Core; /* Run this before creating sockets. @@ -331,39 +315,39 @@ int networking_at_startup(void); * return 1 if valid * return 0 if not valid */ -int sock_valid(sock_t sock); +int sock_valid(Socket sock); /* Close the socket. */ -void kill_sock(sock_t sock); +void kill_sock(Socket sock); /* Set socket as nonblocking * * return 1 on success * return 0 on failure */ -int set_socket_nonblock(sock_t sock); +int set_socket_nonblock(Socket sock); /* Set socket to not emit SIGPIPE * * return 1 on success * return 0 on failure */ -int set_socket_nosigpipe(sock_t sock); +int set_socket_nosigpipe(Socket sock); /* Enable SO_REUSEADDR on socket. * * return 1 on success * return 0 on failure */ -int set_socket_reuseaddr(sock_t sock); +int set_socket_reuseaddr(Socket sock); /* Set socket to dual (IPv4 + IPv6 socket) * * return 1 on success * return 0 on failure */ -int set_socket_dualstack(sock_t sock); +int set_socket_dualstack(Socket sock); /* return current monotonic time in milliseconds (ms). */ uint64_t current_time_monotonic(void); diff --git a/toxcore/toxcore/network.m b/toxcore/toxcore/network.m index 49fb047..e7407a6 100644 --- a/toxcore/toxcore/network.m +++ b/toxcore/toxcore/network.m @@ -37,16 +37,38 @@ #include "logger.h" #include "util.h" -#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) -#include -#endif - +#include #ifdef __APPLE__ #include #include #endif -#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) +#ifndef IPV6_ADD_MEMBERSHIP +#ifdef IPV6_JOIN_GROUP +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#endif +#endif + +#if !(defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) + +#include +#include +#include +#include +#include +#include +#include + +#else + +#ifndef IPV6_V6ONLY +#define IPV6_V6ONLY 27 +#endif + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif static const char *inet_ntop(sa_family_t family, const void *addr, char *buf, size_t bufsize) { @@ -123,7 +145,7 @@ static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf) * return 1 if valid * return 0 if not valid */ -int sock_valid(sock_t sock) +int sock_valid(Socket sock) { #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) @@ -140,7 +162,7 @@ int sock_valid(sock_t sock) /* Close the socket. */ -void kill_sock(sock_t sock) +void kill_sock(Socket sock) { #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) closesocket(sock); @@ -154,7 +176,7 @@ void kill_sock(sock_t sock) * return 1 on success * return 0 on failure */ -int set_socket_nonblock(sock_t sock) +int set_socket_nonblock(Socket sock) { #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) u_long mode = 1; @@ -169,7 +191,7 @@ int set_socket_nonblock(sock_t sock) * return 1 on success * return 0 on failure */ -int set_socket_nosigpipe(sock_t sock) +int set_socket_nosigpipe(Socket sock) { #if defined(__MACH__) int set = 1; @@ -184,7 +206,7 @@ int set_socket_nosigpipe(sock_t sock) * return 1 on success * return 0 on failure */ -int set_socket_reuseaddr(sock_t sock) +int set_socket_reuseaddr(Socket sock) { int set = 1; return (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&set, sizeof(set)) == 0); @@ -195,7 +217,7 @@ int set_socket_reuseaddr(sock_t sock) * return 1 on success * return 0 on failure */ -int set_socket_dualstack(sock_t sock) +int set_socket_dualstack(Socket sock) { int ipv6only = 0; socklen_t optsize = sizeof(ipv6only); @@ -242,11 +264,16 @@ uint64_t current_time_monotonic(void) { uint64_t time; #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) + uint64_t old_add_monotime = add_monotime; time = (uint64_t)GetTickCount() + add_monotime; - if (time < last_monotime) { /* Prevent time from ever decreasing because of 32 bit wrap. */ + /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race + * conditions when multiple threads call this function at once */ + if (time + 0x10000 < last_monotime) { uint32_t add = ~0; - add_monotime += add; + /* use old_add_monotime rather than simply incrementing add_monotime, to handle the case that many threads + * simultaneously detect an overflow */ + add_monotime = old_add_monotime + add; time += add; } @@ -285,24 +312,48 @@ static uint32_t data_1(uint16_t buflen, const uint8_t *buffer) static void loglogdata(Logger *log, const char *message, const uint8_t *buffer, uint16_t buflen, IP_Port ip_port, int res) { + char ip_str[IP_NTOA_LEN]; + if (res < 0) { /* Windows doesn't necessarily know %zu */ LOGGER_TRACE(log, "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x", buffer[0], message, (buflen < 999 ? (uint16_t)buflen : 999), 'E', - ip_ntoa(&ip_port.ip), ntohs(ip_port.port), errno, strerror(errno), data_0(buflen, buffer), - data_1(buflen, buffer)); + ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), ntohs(ip_port.port), errno, + strerror(errno), data_0(buflen, buffer), data_1(buflen, buffer)); } else if ((res > 0) && ((size_t)res <= buflen)) { LOGGER_TRACE(log, "[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x", buffer[0], message, (res < 999 ? (size_t)res : 999), ((size_t)res < buflen ? '<' : '='), - ip_ntoa(&ip_port.ip), ntohs(ip_port.port), 0, "OK", data_0(buflen, buffer), data_1(buflen, - buffer)); + ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), ntohs(ip_port.port), 0, "OK", + data_0(buflen, buffer), data_1(buflen, buffer)); } else { /* empty or overwrite */ LOGGER_TRACE(log, "[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x", buffer[0], message, (size_t)res, (!res ? '!' : '>'), buflen, - ip_ntoa(&ip_port.ip), ntohs(ip_port.port), 0, "OK", data_0(buflen, buffer), data_1(buflen, - buffer)); + ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), ntohs(ip_port.port), 0, "OK", + data_0(buflen, buffer), data_1(buflen, buffer)); } } +void get_ip4(IP4 *result, const struct in_addr *addr) +{ + result->uint32 = addr->s_addr; +} + +void get_ip6(IP6 *result, const struct in6_addr *addr) +{ + assert(sizeof(result->uint8) == sizeof(addr->s6_addr)); + memcpy(result->uint8, addr->s6_addr, sizeof(result->uint8)); +} + + +void fill_addr4(IP4 ip, struct in_addr *addr) +{ + addr->s_addr = ip.uint32; +} + +void fill_addr6(IP6 ip, struct in6_addr *addr) +{ + assert(sizeof(ip.uint8) == sizeof(addr->s6_addr)); + memcpy(addr->s6_addr, ip.uint8, sizeof(ip.uint8)); +} /* Basic network functions: * Function to send packet(data) of length length to ip_port. @@ -339,7 +390,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1 ip6.uint32[1] = 0; ip6.uint32[2] = htonl(0xFFFF); ip6.uint32[3] = ip_port.ip.ip4.uint32; - addr6->sin6_addr = ip6.in6_addr; + fill_addr6(ip6, &addr6->sin6_addr); addr6->sin6_flowinfo = 0; addr6->sin6_scope_id = 0; @@ -348,7 +399,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1 addrsize = sizeof(struct sockaddr_in); addr4->sin_family = AF_INET; - addr4->sin_addr = ip_port.ip.ip4.in_addr; + fill_addr4(ip_port.ip.ip4, &addr4->sin_addr); addr4->sin_port = ip_port.port; } } else if (ip_port.ip.family == AF_INET6) { @@ -357,7 +408,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1 addrsize = sizeof(struct sockaddr_in6); addr6->sin6_family = AF_INET6; addr6->sin6_port = ip_port.port; - addr6->sin6_addr = ip_port.ip.ip6.in6_addr; + fill_addr6(ip_port.ip.ip6, &addr6->sin6_addr); addr6->sin6_flowinfo = 0; addr6->sin6_scope_id = 0; @@ -378,7 +429,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1 * Packet data is put into data. * Packet length is put into length. */ -static int receivepacket(Logger *log, sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) +static int receivepacket(Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) { memset(ip_port, 0, sizeof(IP_Port)); struct sockaddr_storage addr; @@ -405,12 +456,12 @@ static int receivepacket(Logger *log, sock_t sock, IP_Port *ip_port, uint8_t *da struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; ip_port->ip.family = addr_in->sin_family; - ip_port->ip.ip4.in_addr = addr_in->sin_addr; + get_ip4(&ip_port->ip.ip4, &addr_in->sin_addr); ip_port->port = addr_in->sin_port; } else if (addr.ss_family == AF_INET6) { struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr; ip_port->ip.family = addr_in6->sin6_family; - ip_port->ip.ip6.in6_addr = addr_in6->sin6_addr; + get_ip6(&ip_port->ip.ip6, &addr_in6->sin6_addr); ip_port->port = addr_in6->sin6_port; if (IPV6_IPV4_IN_V6(ip_port->ip.ip6)) { @@ -627,7 +678,7 @@ static void at_shutdown(void) addrsize = sizeof(struct sockaddr_in); addr4->sin_family = AF_INET; addr4->sin_port = 0; - addr4->sin_addr = ip.ip4.in_addr; + fill_addr4(ip.ip4, &addr4->sin_addr); portptr = &addr4->sin_port; } else if (temp->family == AF_INET6) { @@ -636,7 +687,7 @@ static void at_shutdown(void) addrsize = sizeof(struct sockaddr_in6); addr6->sin6_family = AF_INET6; addr6->sin6_port = 0; - addr6->sin6_addr = ip.ip6.in6_addr; + fill_addr6(ip.ip6, &addr6->sin6_addr); addr6->sin6_flowinfo = 0; addr6->sin6_scope_id = 0; @@ -690,7 +741,9 @@ static void at_shutdown(void) if (!res) { temp->port = *portptr; - LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip), ntohs(temp->port)); + char ip_str[IP_NTOA_LEN]; + LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip, ip_str, sizeof(ip_str)), + ntohs(temp->port)); /* errno isn't reset on success, only set on failure, the failed * binds with parallel clients yield a -EPERM to the outside if @@ -715,8 +768,9 @@ static void at_shutdown(void) *portptr = htons(port_to_try); } + char ip_str[IP_NTOA_LEN]; LOGGER_ERROR(log, "Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno), - ip_ntoa(&ip), port_from, port_to); + ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to); kill_networking(temp); @@ -757,11 +811,16 @@ int ip_equal(const IP *a, const IP *b) /* same family */ if (a->family == b->family) { if (a->family == AF_INET) { - return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr); + struct in_addr addr_a; + struct in_addr addr_b; + fill_addr4(a->ip4, &addr_a); + fill_addr4(b->ip4, &addr_b); + return addr_a.s_addr == addr_b.s_addr; } if (a->family == AF_INET6) { - return a->ip6.uint64[0] == b->ip6.uint64[0] && a->ip6.uint64[1] == b->ip6.uint64[1]; + return a->ip6.uint64[0] == b->ip6.uint64[0] && + a->ip6.uint64[1] == b->ip6.uint64[1]; } return 0; @@ -770,11 +829,15 @@ int ip_equal(const IP *a, const IP *b) /* different family: check on the IPv6 one if it is the IPv4 one embedded */ if ((a->family == AF_INET) && (b->family == AF_INET6)) { if (IPV6_IPV4_IN_V6(b->ip6)) { - return (a->ip4.in_addr.s_addr == b->ip6.uint32[3]); + struct in_addr addr_a; + fill_addr4(a->ip4, &addr_a); + return addr_a.s_addr == b->ip6.uint32[3]; } } else if ((a->family == AF_INET6) && (b->family == AF_INET)) { if (IPV6_IPV4_IN_V6(a->ip6)) { - return (a->ip6.uint32[3] == b->ip4.in_addr.s_addr); + struct in_addr addr_b; + fill_addr4(b->ip4, &addr_b); + return a->ip6.uint32[3] == addr_b.s_addr; } } @@ -867,41 +930,46 @@ void ipport_copy(IP_Port *target, const IP_Port *source) /* ip_ntoa * converts ip into a string - * uses a static buffer, so mustn't used multiple times in the same output + * ip_str must be of length at least IP_NTOA_LEN * * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]" * writes error message into the buffer on error + * + * returns ip_str */ -/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */ -static char addresstext[96]; // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ? -const char *ip_ntoa(const IP *ip) +const char *ip_ntoa(const IP *ip, char *ip_str, size_t length) { + if (length < IP_NTOA_LEN) { + snprintf(ip_str, length, "Bad buf length"); + return ip_str; + } + if (ip) { if (ip->family == AF_INET) { /* returns standard quad-dotted notation */ const struct in_addr *addr = (const struct in_addr *)&ip->ip4; - addresstext[0] = 0; - inet_ntop(ip->family, addr, addresstext, sizeof(addresstext)); + ip_str[0] = 0; + inet_ntop(ip->family, addr, ip_str, length); } else if (ip->family == AF_INET6) { /* returns hex-groups enclosed into square brackets */ const struct in6_addr *addr = (const struct in6_addr *)&ip->ip6; - addresstext[0] = '['; - inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3); - size_t len = strlen(addresstext); - addresstext[len] = ']'; - addresstext[len + 1] = 0; + ip_str[0] = '['; + inet_ntop(ip->family, addr, &ip_str[1], length - 3); + size_t len = strlen(ip_str); + ip_str[len] = ']'; + ip_str[len + 1] = 0; } else { - snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family); + snprintf(ip_str, length, "(IP invalid, family %u)", ip->family); } } else { - snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)"); + snprintf(ip_str, length, "(IP invalid: NULL)"); } /* brute force protection against lacking termination */ - addresstext[sizeof(addresstext) - 1] = 0; - return addresstext; + ip_str[length - 1] = 0; + return ip_str; } /* @@ -961,7 +1029,7 @@ int addr_parse_ip(const char *address, IP *to) if (1 == inet_pton(AF_INET, address, &addr4)) { to->family = AF_INET; - to->ip4.in_addr = addr4; + get_ip4(&to->ip4, &addr4); return 1; } @@ -969,7 +1037,7 @@ int addr_parse_ip(const char *address, IP *to) if (1 == inet_pton(AF_INET6, address, &addr6)) { to->family = AF_INET6; - to->ip6.in6_addr = addr6; + get_ip6(&to->ip6, &addr6); return 1; } @@ -1033,12 +1101,12 @@ int addr_resolve(const char *address, IP *to, IP *extra) case AF_INET: if (walker->ai_family == family) { /* AF_INET requested, done */ struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; - to->ip4.in_addr = addr->sin_addr; + get_ip4(&to->ip4, &addr->sin_addr); result = TOX_ADDR_RESOLVE_INET; done = 1; } else if (!(result & TOX_ADDR_RESOLVE_INET)) { /* AF_UNSPEC requested, store away */ struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; - ip4.ip4.in_addr = addr->sin_addr; + get_ip4(&ip4.ip4, &addr->sin_addr); result |= TOX_ADDR_RESOLVE_INET; } @@ -1048,14 +1116,14 @@ int addr_resolve(const char *address, IP *to, IP *extra) if (walker->ai_family == family) { /* AF_INET6 requested, done */ if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; - to->ip6.in6_addr = addr->sin6_addr; + get_ip6(&to->ip6, &addr->sin6_addr); result = TOX_ADDR_RESOLVE_INET6; done = 1; } } else if (!(result & TOX_ADDR_RESOLVE_INET6)) { /* AF_UNSPEC requested, store away */ if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr; - ip6.ip6.in6_addr = addr->sin6_addr; + get_ip6(&ip6.ip6, &addr->sin6_addr); result |= TOX_ADDR_RESOLVE_INET6; } } diff --git a/toxcore/toxcore/tox.api.h b/toxcore/toxcore/tox.api.h index 20cdc2b..da86d01 100644 --- a/toxcore/toxcore/tox.api.h +++ b/toxcore/toxcore/tox.api.h @@ -179,7 +179,7 @@ const VERSION_MINOR = 1; * The patch or revision number. Incremented when bugfixes are applied without * changing any functionality or API or ABI. */ -const VERSION_PATCH = 5; +const VERSION_PATCH = 6; /** * A macro to check at preprocessing time whether the client code is compatible diff --git a/toxcore/toxcore/tox.m b/toxcore/toxcore/tox.m index 0acd551..adc5375 100644 --- a/toxcore/toxcore/tox.m +++ b/toxcore/toxcore/tox.m @@ -254,9 +254,11 @@ bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t * } if (info->ai_family == AF_INET) { - ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)info->ai_addr; + get_ip4(&ip_port.ip.ip4, &addr->sin_addr); } else if (info->ai_family == AF_INET6) { - ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr; + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)info->ai_addr; + get_ip6(&ip_port.ip.ip6, &addr->sin6_addr); } else { continue; } @@ -312,9 +314,11 @@ bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8 } if (info->ai_family == AF_INET) { - ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr; + struct sockaddr_in *addr = (struct sockaddr_in *)info->ai_addr; + get_ip4(&ip_port.ip.ip4, &addr->sin_addr); } else if (info->ai_family == AF_INET6) { - ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr; + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)info->ai_addr; + get_ip6(&ip_port.ip.ip6, &addr->sin6_addr); } else { continue; } diff --git a/toxcore/toxcore/util.m b/toxcore/toxcore/util.m index e1bbf4d..22fa0fc 100644 --- a/toxcore/toxcore/util.m +++ b/toxcore/toxcore/util.m @@ -41,6 +41,8 @@ static uint64_t unix_time_value; static uint64_t unix_base_time_value; +/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of + * unix_time() may fail to increase monotonically with increasing time */ void unix_time_update(void) { if (unix_base_time_value == 0) {