summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/network_test.c11
-rw-r--r--testing/DHT_test.c10
-rw-r--r--toxcore/DHT.c46
-rw-r--r--toxcore/LAN_discovery.c56
-rw-r--r--toxcore/Messenger.c50
-rw-r--r--toxcore/Messenger.h2
-rw-r--r--toxcore/network.c65
-rw-r--r--toxcore/network.h8
-rw-r--r--toxcore/util.c2
9 files changed, 172 insertions, 78 deletions
diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c
index ca918778..2ce6d0b5 100644
--- a/auto_tests/network_test.c
+++ b/auto_tests/network_test.c
@@ -36,7 +36,8 @@ START_TEST(test_addr_resolv_localhost)
36 36
37 if (res > 0) { 37 if (res > 0) {
38 ck_assert_msg(ip.family == AF_INET, "Expected family AF_INET, got %u.", ip.family); 38 ck_assert_msg(ip.family == AF_INET, "Expected family AF_INET, got %u.", ip.family);
39 ck_assert_msg(ip.ip4.uint32 == htonl(0x7F000001), "Expected 127.0.0.1, got %s.", inet_ntoa(ip.ip4.in_addr)); 39 ck_assert_msg(ip.ip4.uint32 == htonl(0x7F000001), "Expected 127.0.0.1, got %s.",
40 inet_ntoa(ip.ip4.in_addr));
40 } 41 }
41 42
42 ip_init(&ip, 1); // ipv6enabled = 1 43 ip_init(&ip, 1); // ipv6enabled = 1
@@ -50,8 +51,10 @@ START_TEST(test_addr_resolv_localhost)
50 ck_assert_msg(res > 0, "Resolver failed: %u, %s (%x, %x)", errno, strerror(errno)); 51 ck_assert_msg(res > 0, "Resolver failed: %u, %s (%x, %x)", errno, strerror(errno));
51 52
52 if (res > 0) { 53 if (res > 0) {
54 char ip_str[IP_NTOA_LEN];
53 ck_assert_msg(ip.family == AF_INET6, "Expected family AF_INET6 (%u), got %u.", AF_INET6, ip.family); 55 ck_assert_msg(ip.family == AF_INET6, "Expected family AF_INET6 (%u), got %u.", AF_INET6, ip.family);
54 ck_assert_msg(!memcmp(&ip.ip6, &in6addr_loopback, sizeof(IP6)), "Expected ::1, got %s.", ip_ntoa(&ip)); 56 ck_assert_msg(!memcmp(&ip.ip6, &in6addr_loopback, sizeof(IP6)), "Expected ::1, got %s.",
57 ip_ntoa(&ip, ip_str, sizeof(ip_str)));
55 } 58 }
56 59
57 if (!localhost_split) { 60 if (!localhost_split) {
@@ -63,8 +66,10 @@ START_TEST(test_addr_resolv_localhost)
63 ck_assert_msg(res > 0, "Resolver failed: %u, %s (%x, %x)", errno, strerror(errno)); 66 ck_assert_msg(res > 0, "Resolver failed: %u, %s (%x, %x)", errno, strerror(errno));
64 67
65 if (res > 0) { 68 if (res > 0) {
69 char ip_str[IP_NTOA_LEN];
66 ck_assert_msg(ip.family == AF_INET6, "Expected family AF_INET6 (%u), got %u.", AF_INET6, ip.family); 70 ck_assert_msg(ip.family == AF_INET6, "Expected family AF_INET6 (%u), got %u.", AF_INET6, ip.family);
67 ck_assert_msg(!memcmp(&ip.ip6, &in6addr_loopback, sizeof(IP6)), "Expected ::1, got %s.", ip_ntoa(&ip)); 71 ck_assert_msg(!memcmp(&ip.ip6, &in6addr_loopback, sizeof(IP6)), "Expected ::1, got %s.",
72 ip_ntoa(&ip, ip_str, sizeof(ip_str)));
68 73
69 ck_assert_msg(extra.family == AF_INET, "Expected family AF_INET (%u), got %u.", AF_INET, extra.family); 74 ck_assert_msg(extra.family == AF_INET, "Expected family AF_INET (%u), got %u.", AF_INET, extra.family);
70 ck_assert_msg(extra.ip4.uint32 == htonl(0x7F000001), "Expected 127.0.0.1, got %s.", inet_ntoa(extra.ip4.in_addr)); 75 ck_assert_msg(extra.ip4.uint32 == htonl(0x7F000001), "Expected 127.0.0.1, got %s.", inet_ntoa(extra.ip4.in_addr));
diff --git a/testing/DHT_test.c b/testing/DHT_test.c
index 1fbe6def..c42dc053 100644
--- a/testing/DHT_test.c
+++ b/testing/DHT_test.c
@@ -87,16 +87,17 @@ static void print_hardening(Hardening *h)
87static void print_assoc(IPPTsPng *assoc, uint8_t ours) 87static void print_assoc(IPPTsPng *assoc, uint8_t ours)
88{ 88{
89 IP_Port *ipp = &assoc->ip_port; 89 IP_Port *ipp = &assoc->ip_port;
90 printf("\nIP: %s Port: %u", ip_ntoa(&ipp->ip), ntohs(ipp->port)); 90 char ip_str[IP_NTOA_LEN];
91 printf("\nIP: %s Port: %u", ip_ntoa(&ipp->ip, ip_str, sizeof(ip_str)), ntohs(ipp->port));
91 printf("\nTimestamp: %llu", (long long unsigned int) assoc->timestamp); 92 printf("\nTimestamp: %llu", (long long unsigned int) assoc->timestamp);
92 printf("\nLast pinged: %llu\n", (long long unsigned int) assoc->last_pinged); 93 printf("\nLast pinged: %llu\n", (long long unsigned int) assoc->last_pinged);
93 94
94 ipp = &assoc->ret_ip_port; 95 ipp = &assoc->ret_ip_port;
95 96
96 if (ours) { 97 if (ours) {
97 printf("OUR IP: %s Port: %u\n", ip_ntoa(&ipp->ip), ntohs(ipp->port)); 98 printf("OUR IP: %s Port: %u\n", ip_ntoa(&ipp->ip, ip_str, sizeof(ip_str)), ntohs(ipp->port));
98 } else { 99 } else {
99 printf("RET IP: %s Port: %u\n", ip_ntoa(&ipp->ip), ntohs(ipp->port)); 100 printf("RET IP: %s Port: %u\n", ip_ntoa(&ipp->ip, ip_str, sizeof(ip_str)), ntohs(ipp->port));
100 } 101 }
101 102
102 printf("Timestamp: %llu\n", (long long unsigned int) assoc->ret_timestamp); 103 printf("Timestamp: %llu\n", (long long unsigned int) assoc->ret_timestamp);
@@ -136,7 +137,8 @@ static void print_friendlist(DHT *dht)
136 print_client_id(dht->friends_list[k].public_key); 137 print_client_id(dht->friends_list[k].public_key);
137 138
138 int friendok = DHT_getfriendip(dht, dht->friends_list[k].public_key, &p_ip); 139 int friendok = DHT_getfriendip(dht, dht->friends_list[k].public_key, &p_ip);
139 printf("\nIP: %s:%u (%d)", ip_ntoa(&p_ip.ip), ntohs(p_ip.port), friendok); 140 char ip_str[IP_NTOA_LEN];
141 printf("\nIP: %s:%u (%d)", ip_ntoa(&p_ip.ip, ip_str, sizeof(ip_str)), ntohs(p_ip.port), friendok);
140 142
141 printf("\nCLIENTS IN LIST:\n\n"); 143 printf("\nCLIENTS IN LIST:\n\n");
142 144
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 776313ca..f82c1061 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -538,9 +538,12 @@ static int client_or_ip_port_in_list(Logger *log, Client_data *list, uint16_t le
538 if (ip_port.ip.family == AF_INET) { 538 if (ip_port.ip.family == AF_INET) {
539 539
540 if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { 540 if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) {
541 char ip_str[IP_NTOA_LEN];
541 LOGGER_TRACE(log, "coipil[%u]: switching ipv4 from %s:%u to %s:%u", i, 542 LOGGER_TRACE(log, "coipil[%u]: switching ipv4 from %s:%u to %s:%u", i,
542 ip_ntoa(&list[i].assoc4.ip_port.ip), ntohs(list[i].assoc4.ip_port.port), 543 ip_ntoa(&list[i].assoc4.ip_port.ip, ip_str, sizeof(ip_str)),
543 ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); 544 ntohs(list[i].assoc4.ip_port.port),
545 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)),
546 ntohs(ip_port.port));
544 } 547 }
545 548
546 if (LAN_ip(list[i].assoc4.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) { 549 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
552 } else if (ip_port.ip.family == AF_INET6) { 555 } else if (ip_port.ip.family == AF_INET6) {
553 556
554 if (!ipport_equal(&list[i].assoc6.ip_port, &ip_port)) { 557 if (!ipport_equal(&list[i].assoc6.ip_port, &ip_port)) {
558 char ip_str[IP_NTOA_LEN];
555 LOGGER_TRACE(log, "coipil[%u]: switching ipv6 from %s:%u to %s:%u", i, 559 LOGGER_TRACE(log, "coipil[%u]: switching ipv6 from %s:%u to %s:%u", i,
556 ip_ntoa(&list[i].assoc6.ip_port.ip), ntohs(list[i].assoc6.ip_port.port), 560 ip_ntoa(&list[i].assoc6.ip_port.ip, ip_str, sizeof(ip_str)),
557 ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); 561 ntohs(list[i].assoc6.ip_port.port),
562 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)),
563 ntohs(ip_port.port));
558 } 564 }
559 565
560 if (LAN_ip(list[i].assoc6.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) { 566 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
785 return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good); 791 return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good);
786} 792}
787 793
788static uint8_t cmp_public_key[CRYPTO_PUBLIC_KEY_SIZE]; 794typedef struct {
795 const uint8_t *base_public_key;
796 Client_data entry;
797} Cmp_data;
798
789static int cmp_dht_entry(const void *a, const void *b) 799static int cmp_dht_entry(const void *a, const void *b)
790{ 800{
791 Client_data entry1, entry2; 801 Cmp_data cmp1, cmp2;
792 memcpy(&entry1, a, sizeof(Client_data)); 802 memcpy(&cmp1, a, sizeof(Cmp_data));
793 memcpy(&entry2, b, sizeof(Client_data)); 803 memcpy(&cmp2, b, sizeof(Cmp_data));
804 Client_data entry1 = cmp1.entry;
805 Client_data entry2 = cmp2.entry;
806 const uint8_t *cmp_public_key = cmp1.base_public_key;
807
794 int t1 = is_timeout(entry1.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry1.assoc6.timestamp, BAD_NODE_TIMEOUT); 808 int t1 = is_timeout(entry1.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry1.assoc6.timestamp, BAD_NODE_TIMEOUT);
795 int t2 = is_timeout(entry2.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry2.assoc6.timestamp, BAD_NODE_TIMEOUT); 809 int t2 = is_timeout(entry2.assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(entry2.assoc6.timestamp, BAD_NODE_TIMEOUT);
796 810
@@ -851,8 +865,20 @@ static unsigned int store_node_ok(const Client_data *client, const uint8_t *publ
851 865
852static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) 866static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key)
853{ 867{
854 memcpy(cmp_public_key, comp_public_key, CRYPTO_PUBLIC_KEY_SIZE); 868 // Pass comp_public_key to qsort with each Client_data entry, so the
855 qsort(list, length, sizeof(Client_data), cmp_dht_entry); 869 // comparison function cmp_dht_entry can use it as the base of comparison.
870 Cmp_data cmp_list[length];
871
872 for (uint32_t i = 0; i < length; i++) {
873 cmp_list[i].base_public_key = comp_public_key;
874 cmp_list[i].entry = list[i];
875 }
876
877 qsort(cmp_list, length, sizeof(Cmp_data), cmp_dht_entry);
878
879 for (uint32_t i = 0; i < length; i++) {
880 list[i] = cmp_list[i].entry;
881 }
856} 882}
857 883
858/* Replace a first bad (or empty) node with this one 884/* Replace a first bad (or empty) node with this one
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index 75dca605..40c64cda 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -39,8 +39,10 @@
39#define MAX_INTERFACES 16 39#define MAX_INTERFACES 16
40 40
41 41
42/* TODO: multiple threads might concurrently try to set these, and it isn't clear that this couldn't lead to undesirable
43 * behaviour. Consider storing the data in per-instance variables instead. */
42static int broadcast_count = -1; 44static int broadcast_count = -1;
43static IP_Port broadcast_ip_port[MAX_INTERFACES]; 45static IP_Port broadcast_ip_ports[MAX_INTERFACES];
44 46
45#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 47#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
46 48
@@ -48,8 +50,6 @@ static IP_Port broadcast_ip_port[MAX_INTERFACES];
48 50
49static void fetch_broadcast_info(uint16_t port) 51static void fetch_broadcast_info(uint16_t port)
50{ 52{
51 broadcast_count = 0;
52
53 IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); 53 IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
54 unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO); 54 unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO);
55 55
@@ -66,6 +66,13 @@ static void fetch_broadcast_info(uint16_t port)
66 } 66 }
67 } 67 }
68 68
69 /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info().
70 * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid
71 * interfaces will be set to be broadcast to.
72 * */
73 int count = 0;
74 IP_Port ip_ports[MAX_INTERFACES];
75
69 int ret; 76 int ret;
70 77
71 if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { 78 if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
@@ -77,16 +84,16 @@ static void fetch_broadcast_info(uint16_t port)
77 if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask) 84 if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask)
78 && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) { 85 && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) {
79 if (gateway.family == AF_INET && subnet_mask.family == AF_INET) { 86 if (gateway.family == AF_INET && subnet_mask.family == AF_INET) {
80 IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; 87 IP_Port *ip_port = &ip_ports[count];
81 ip_port->ip.family = AF_INET; 88 ip_port->ip.family = AF_INET;
82 uint32_t gateway_ip = ntohl(gateway.ip4.uint32), subnet_ip = ntohl(subnet_mask.ip4.uint32); 89 uint32_t gateway_ip = ntohl(gateway.ip4.uint32), subnet_ip = ntohl(subnet_mask.ip4.uint32);
83 uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1; 90 uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1;
84 ip_port->ip.ip4.uint32 = htonl(broadcast_ip); 91 ip_port->ip.ip4.uint32 = htonl(broadcast_ip);
85 ip_port->port = port; 92 ip_port->port = port;
86 broadcast_count++; 93 count++;
87 94
88 if (broadcast_count >= MAX_INTERFACES) { 95 if (count >= MAX_INTERFACES) {
89 return; 96 break;
90 } 97 }
91 } 98 }
92 } 99 }
@@ -98,6 +105,12 @@ static void fetch_broadcast_info(uint16_t port)
98 if (pAdapterInfo) { 105 if (pAdapterInfo) {
99 free(pAdapterInfo); 106 free(pAdapterInfo);
100 } 107 }
108
109 broadcast_count = count;
110
111 for (uint32_t i = 0; i < count; i++) {
112 broadcast_ip_ports[i] = ip_ports[i];
113 }
101} 114}
102 115
103#elif defined(__linux__) 116#elif defined(__linux__)
@@ -108,7 +121,6 @@ static void fetch_broadcast_info(uint16_t port)
108 * so it's wrapped in __linux for now. 121 * so it's wrapped in __linux for now.
109 * Definitely won't work like this on Windows... 122 * Definitely won't work like this on Windows...
110 */ 123 */
111 broadcast_count = 0;
112 sock_t sock = 0; 124 sock_t sock = 0;
113 125
114 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 126 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
@@ -128,14 +140,21 @@ static void fetch_broadcast_info(uint16_t port)
128 return; 140 return;
129 } 141 }
130 142
143 /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info().
144 * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid
145 * interfaces will be set to be broadcast to.
146 * */
147 int count = 0;
148 IP_Port ip_ports[MAX_INTERFACES];
149
131 /* ifconf.ifc_len is set by the ioctl() to the actual length used; 150 /* ifconf.ifc_len is set by the ioctl() to the actual length used;
132 * on usage of the complete array the call should be repeated with 151 * on usage of the complete array the call should be repeated with
133 * a larger array, not done (640kB and 16 interfaces shall be 152 * a larger array, not done (640kB and 16 interfaces shall be
134 * enough, for everybody!) 153 * enough, for everybody!)
135 */ 154 */
136 int i, count = ifconf.ifc_len / sizeof(struct ifreq); 155 int i, n = ifconf.ifc_len / sizeof(struct ifreq);
137 156
138 for (i = 0; i < count; i++) { 157 for (i = 0; i < n; i++) {
139 /* there are interfaces with are incapable of broadcast */ 158 /* there are interfaces with are incapable of broadcast */
140 if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) { 159 if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) {
141 continue; 160 continue;
@@ -148,12 +167,11 @@ static void fetch_broadcast_info(uint16_t port)
148 167
149 struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; 168 struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
150 169
151 if (broadcast_count >= MAX_INTERFACES) { 170 if (count >= MAX_INTERFACES) {
152 close(sock); 171 break;
153 return;
154 } 172 }
155 173
156 IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; 174 IP_Port *ip_port = &ip_ports[count];
157 ip_port->ip.family = AF_INET; 175 ip_port->ip.family = AF_INET;
158 ip_port->ip.ip4.in_addr = sock4->sin_addr; 176 ip_port->ip.ip4.in_addr = sock4->sin_addr;
159 177
@@ -162,10 +180,16 @@ static void fetch_broadcast_info(uint16_t port)
162 } 180 }
163 181
164 ip_port->port = port; 182 ip_port->port = port;
165 broadcast_count++; 183 count++;
166 } 184 }
167 185
168 close(sock); 186 close(sock);
187
188 broadcast_count = count;
189
190 for (uint32_t i = 0; i < count; i++) {
191 broadcast_ip_ports[i] = ip_ports[i];
192 }
169} 193}
170 194
171#else // TODO(irungentoo): Other platforms? 195#else // TODO(irungentoo): Other platforms?
@@ -196,7 +220,7 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8
196 int i; 220 int i;
197 221
198 for (i = 0; i < broadcast_count; i++) { 222 for (i = 0; i < broadcast_count; i++) {
199 sendpacket(net, broadcast_ip_port[i], data, length); 223 sendpacket(net, broadcast_ip_ports[i], data, length);
200 } 224 }
201 225
202 return 1; 226 return 1;
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index db5b484d..8291fab0 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -2024,6 +2024,8 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
2024 set_nospam(&(m->fr), random_int()); 2024 set_nospam(&(m->fr), random_int());
2025 set_filter_function(&(m->fr), &friend_already_added, m); 2025 set_filter_function(&(m->fr), &friend_already_added, m);
2026 2026
2027 m->lastdump = 0;
2028
2027 if (error) { 2029 if (error) {
2028 *error = MESSENGER_ERROR_NONE; 2030 *error = MESSENGER_ERROR_NONE;
2029 } 2031 }
@@ -2471,18 +2473,22 @@ static void connection_status_cb(Messenger *m, void *userdata)
2471 2473
2472 2474
2473#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL 2475#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL
2474static time_t lastdump = 0; 2476
2475static char IDString[CRYPTO_PUBLIC_KEY_SIZE * 2 + 1]; 2477#define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1)
2476static char *ID2String(const uint8_t *pk) 2478/* id_str should be of length at least IDSTRING_LEN */
2479static char *id_to_string(const uint8_t *pk, char *id_str, size_t length)
2477{ 2480{
2478 uint32_t i; 2481 if (length < IDSTRING_LEN) {
2482 snprintf(id_str, length, "Bad buf length");
2483 return id_str;
2484 }
2479 2485
2480 for (i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) { 2486 for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) {
2481 sprintf(&IDString[i * 2], "%02X", pk[i]); 2487 sprintf(&id_str[i * 2], "%02X", pk[i]);
2482 } 2488 }
2483 2489
2484 IDString[CRYPTO_PUBLIC_KEY_SIZE * 2] = 0; 2490 id_str[CRYPTO_PUBLIC_KEY_SIZE * 2] = 0;
2485 return IDString; 2491 return id_str;
2486} 2492}
2487 2493
2488/* Minimum messenger run interval in ms 2494/* Minimum messenger run interval in ms
@@ -2546,8 +2552,8 @@ void do_messenger(Messenger *m, void *userdata)
2546 do_friends(m, userdata); 2552 do_friends(m, userdata);
2547 connection_status_cb(m, userdata); 2553 connection_status_cb(m, userdata);
2548 2554
2549 if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { 2555 if (unix_time() > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
2550 lastdump = unix_time(); 2556 m->lastdump = unix_time();
2551 uint32_t client, last_pinged; 2557 uint32_t client, last_pinged;
2552 2558
2553 for (client = 0; client < LCLIENT_LIST; client++) { 2559 for (client = 0; client < LCLIENT_LIST; client++) {
@@ -2557,15 +2563,18 @@ void do_messenger(Messenger *m, void *userdata)
2557 2563
2558 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) { 2564 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) {
2559 if (ip_isset(&assoc->ip_port.ip)) { 2565 if (ip_isset(&assoc->ip_port.ip)) {
2560 last_pinged = lastdump - assoc->last_pinged; 2566 last_pinged = m->lastdump - assoc->last_pinged;
2561 2567
2562 if (last_pinged > 999) { 2568 if (last_pinged > 999) {
2563 last_pinged = 999; 2569 last_pinged = 999;
2564 } 2570 }
2565 2571
2572 char ip_str[IP_NTOA_LEN];
2573 char id_str[IDSTRING_LEN];
2566 LOGGER_TRACE(m->log, "C[%2u] %s:%u [%3u] %s", 2574 LOGGER_TRACE(m->log, "C[%2u] %s:%u [%3u] %s",
2567 client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port), 2575 client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
2568 last_pinged, ID2String(cptr->public_key)); 2576 ntohs(assoc->ip_port.port), last_pinged,
2577 id_to_string(cptr->public_key, id_str, sizeof(id_str)));
2569 } 2578 }
2570 } 2579 }
2571 } 2580 }
@@ -2617,11 +2626,14 @@ void do_messenger(Messenger *m, void *userdata)
2617 dhtfptr = &m->dht->friends_list[friend_idx]; 2626 dhtfptr = &m->dht->friends_list[friend_idx];
2618 2627
2619 if (msgfptr) { 2628 if (msgfptr) {
2629 char id_str[IDSTRING_LEN];
2620 LOGGER_TRACE(m->log, "F[%2u:%2u] <%s> %s", 2630 LOGGER_TRACE(m->log, "F[%2u:%2u] <%s> %s",
2621 dht2m[friend_idx], friend_idx, msgfptr->name, 2631 dht2m[friend_idx], friend_idx, msgfptr->name,
2622 ID2String(msgfptr->real_pk)); 2632 id_to_string(msgfptr->real_pk, id_str, sizeof(id_str)));
2623 } else { 2633 } else {
2624 LOGGER_TRACE(m->log, "F[--:%2u] %s", friend_idx, ID2String(dhtfptr->public_key)); 2634 char id_str[IDSTRING_LEN];
2635 LOGGER_TRACE(m->log, "F[--:%2u] %s", friend_idx,
2636 id_to_string(dhtfptr->public_key, id_str, sizeof(id_str)));
2625 } 2637 }
2626 2638
2627 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { 2639 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) {
@@ -2631,16 +2643,18 @@ void do_messenger(Messenger *m, void *userdata)
2631 2643
2632 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) { 2644 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) {
2633 if (ip_isset(&assoc->ip_port.ip)) { 2645 if (ip_isset(&assoc->ip_port.ip)) {
2634 last_pinged = lastdump - assoc->last_pinged; 2646 last_pinged = m->lastdump - assoc->last_pinged;
2635 2647
2636 if (last_pinged > 999) { 2648 if (last_pinged > 999) {
2637 last_pinged = 999; 2649 last_pinged = 999;
2638 } 2650 }
2639 2651
2652 char ip_str[IP_NTOA_LEN];
2653 char id_str[IDSTRING_LEN];
2640 LOGGER_TRACE(m->log, "F[%2u] => C[%2u] %s:%u [%3u] %s", 2654 LOGGER_TRACE(m->log, "F[%2u] => C[%2u] %s:%u [%3u] %s",
2641 friend_idx, client, ip_ntoa(&assoc->ip_port.ip), 2655 friend_idx, client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
2642 ntohs(assoc->ip_port.port), last_pinged, 2656 ntohs(assoc->ip_port.port), last_pinged,
2643 ID2String(cptr->public_key)); 2657 id_to_string(cptr->public_key, id_str, sizeof(id_str)));
2644 } 2658 }
2645 } 2659 }
2646 } 2660 }
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 218ec18b..e1dba698 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -240,6 +240,8 @@ struct Messenger {
240 Friend *friendlist; 240 Friend *friendlist;
241 uint32_t numfriends; 241 uint32_t numfriends;
242 242
243 time_t lastdump;
244
243 uint8_t has_added_relays; // If the first connection has occurred in do_messenger 245 uint8_t has_added_relays; // If the first connection has occurred in do_messenger
244 Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config 246 Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config
245 247
diff --git a/toxcore/network.c b/toxcore/network.c
index e869350f..d267a216 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -242,11 +242,16 @@ uint64_t current_time_monotonic(void)
242{ 242{
243 uint64_t time; 243 uint64_t time;
244#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 244#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
245 uint64_t old_add_monotime = add_monotime;
245 time = (uint64_t)GetTickCount() + add_monotime; 246 time = (uint64_t)GetTickCount() + add_monotime;
246 247
247 if (time < last_monotime) { /* Prevent time from ever decreasing because of 32 bit wrap. */ 248 /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race
249 * conditions when multiple threads call this function at once */
250 if (time + 0x10000 < last_monotime) {
248 uint32_t add = ~0; 251 uint32_t add = ~0;
249 add_monotime += add; 252 /* use old_add_monotime rather than simply incrementing add_monotime, to handle the case that many threads
253 * simultaneously detect an overflow */
254 add_monotime = old_add_monotime + add;
250 time += add; 255 time += add;
251 } 256 }
252 257
@@ -285,21 +290,23 @@ static uint32_t data_1(uint16_t buflen, const uint8_t *buffer)
285static void loglogdata(Logger *log, const char *message, const uint8_t *buffer, 290static void loglogdata(Logger *log, const char *message, const uint8_t *buffer,
286 uint16_t buflen, IP_Port ip_port, int res) 291 uint16_t buflen, IP_Port ip_port, int res)
287{ 292{
293 char ip_str[IP_NTOA_LEN];
294
288 if (res < 0) { /* Windows doesn't necessarily know %zu */ 295 if (res < 0) { /* Windows doesn't necessarily know %zu */
289 LOGGER_TRACE(log, "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x", 296 LOGGER_TRACE(log, "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x",
290 buffer[0], message, (buflen < 999 ? (uint16_t)buflen : 999), 'E', 297 buffer[0], message, (buflen < 999 ? (uint16_t)buflen : 999), 'E',
291 ip_ntoa(&ip_port.ip), ntohs(ip_port.port), errno, strerror(errno), data_0(buflen, buffer), 298 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), ntohs(ip_port.port), errno,
292 data_1(buflen, buffer)); 299 strerror(errno), data_0(buflen, buffer), data_1(buflen, buffer));
293 } else if ((res > 0) && ((size_t)res <= buflen)) { 300 } else if ((res > 0) && ((size_t)res <= buflen)) {
294 LOGGER_TRACE(log, "[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x", 301 LOGGER_TRACE(log, "[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x",
295 buffer[0], message, (res < 999 ? (size_t)res : 999), ((size_t)res < buflen ? '<' : '='), 302 buffer[0], message, (res < 999 ? (size_t)res : 999), ((size_t)res < buflen ? '<' : '='),
296 ip_ntoa(&ip_port.ip), ntohs(ip_port.port), 0, "OK", data_0(buflen, buffer), data_1(buflen, 303 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), ntohs(ip_port.port), 0, "OK",
297 buffer)); 304 data_0(buflen, buffer), data_1(buflen, buffer));
298 } else { /* empty or overwrite */ 305 } else { /* empty or overwrite */
299 LOGGER_TRACE(log, "[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x", 306 LOGGER_TRACE(log, "[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x",
300 buffer[0], message, (size_t)res, (!res ? '!' : '>'), buflen, 307 buffer[0], message, (size_t)res, (!res ? '!' : '>'), buflen,
301 ip_ntoa(&ip_port.ip), ntohs(ip_port.port), 0, "OK", data_0(buflen, buffer), data_1(buflen, 308 ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), ntohs(ip_port.port), 0, "OK",
302 buffer)); 309 data_0(buflen, buffer), data_1(buflen, buffer));
303 } 310 }
304} 311}
305 312
@@ -690,7 +697,9 @@ Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint1
690 if (!res) { 697 if (!res) {
691 temp->port = *portptr; 698 temp->port = *portptr;
692 699
693 LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip), ntohs(temp->port)); 700 char ip_str[IP_NTOA_LEN];
701 LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip, ip_str, sizeof(ip_str)),
702 ntohs(temp->port));
694 703
695 /* errno isn't reset on success, only set on failure, the failed 704 /* errno isn't reset on success, only set on failure, the failed
696 * binds with parallel clients yield a -EPERM to the outside if 705 * binds with parallel clients yield a -EPERM to the outside if
@@ -715,8 +724,9 @@ Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint1
715 *portptr = htons(port_to_try); 724 *portptr = htons(port_to_try);
716 } 725 }
717 726
727 char ip_str[IP_NTOA_LEN];
718 LOGGER_ERROR(log, "Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno), 728 LOGGER_ERROR(log, "Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno),
719 ip_ntoa(&ip), port_from, port_to); 729 ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to);
720 730
721 kill_networking(temp); 731 kill_networking(temp);
722 732
@@ -867,41 +877,46 @@ void ipport_copy(IP_Port *target, const IP_Port *source)
867 877
868/* ip_ntoa 878/* ip_ntoa
869 * converts ip into a string 879 * converts ip into a string
870 * uses a static buffer, so mustn't used multiple times in the same output 880 * ip_str must be of length at least IP_NTOA_LEN
871 * 881 *
872 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]" 882 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
873 * writes error message into the buffer on error 883 * writes error message into the buffer on error
884 *
885 * returns ip_str
874 */ 886 */
875/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */ 887const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)
876static char addresstext[96]; // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?
877const char *ip_ntoa(const IP *ip)
878{ 888{
889 if (length < IP_NTOA_LEN) {
890 snprintf(ip_str, length, "Bad buf length");
891 return ip_str;
892 }
893
879 if (ip) { 894 if (ip) {
880 if (ip->family == AF_INET) { 895 if (ip->family == AF_INET) {
881 /* returns standard quad-dotted notation */ 896 /* returns standard quad-dotted notation */
882 const struct in_addr *addr = (const struct in_addr *)&ip->ip4; 897 const struct in_addr *addr = (const struct in_addr *)&ip->ip4;
883 898
884 addresstext[0] = 0; 899 ip_str[0] = 0;
885 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext)); 900 inet_ntop(ip->family, addr, ip_str, length);
886 } else if (ip->family == AF_INET6) { 901 } else if (ip->family == AF_INET6) {
887 /* returns hex-groups enclosed into square brackets */ 902 /* returns hex-groups enclosed into square brackets */
888 const struct in6_addr *addr = (const struct in6_addr *)&ip->ip6; 903 const struct in6_addr *addr = (const struct in6_addr *)&ip->ip6;
889 904
890 addresstext[0] = '['; 905 ip_str[0] = '[';
891 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3); 906 inet_ntop(ip->family, addr, &ip_str[1], length - 3);
892 size_t len = strlen(addresstext); 907 size_t len = strlen(ip_str);
893 addresstext[len] = ']'; 908 ip_str[len] = ']';
894 addresstext[len + 1] = 0; 909 ip_str[len + 1] = 0;
895 } else { 910 } else {
896 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family); 911 snprintf(ip_str, length, "(IP invalid, family %u)", ip->family);
897 } 912 }
898 } else { 913 } else {
899 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)"); 914 snprintf(ip_str, length, "(IP invalid: NULL)");
900 } 915 }
901 916
902 /* brute force protection against lacking termination */ 917 /* brute force protection against lacking termination */
903 addresstext[sizeof(addresstext) - 1] = 0; 918 ip_str[length - 1] = 0;
904 return addresstext; 919 return ip_str;
905} 920}
906 921
907/* 922/*
diff --git a/toxcore/network.h b/toxcore/network.h
index 45a63e2e..e0122b5d 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -193,12 +193,16 @@ IP_Port;
193 193
194/* ip_ntoa 194/* ip_ntoa
195 * converts ip into a string 195 * converts ip into a string
196 * uses a static buffer, so mustn't used multiple times in the same output 196 * ip_str must be of length at least IP_NTOA_LEN
197 * 197 *
198 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]" 198 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
199 * writes error message into the buffer on error 199 * writes error message into the buffer on error
200 *
201 * returns ip_str
200 */ 202 */
201const char *ip_ntoa(const IP *ip); 203/* this would be INET6_ADDRSTRLEN, but it might be too short for the error message */
204#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?
205const char *ip_ntoa(const IP *ip, char *ip_str, size_t length);
202 206
203/* 207/*
204 * ip_parse_addr 208 * ip_parse_addr
diff --git a/toxcore/util.c b/toxcore/util.c
index e1bbf4db..22fa0fc9 100644
--- a/toxcore/util.c
+++ b/toxcore/util.c
@@ -41,6 +41,8 @@
41static uint64_t unix_time_value; 41static uint64_t unix_time_value;
42static uint64_t unix_base_time_value; 42static uint64_t unix_base_time_value;
43 43
44/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of
45 * unix_time() may fail to increase monotonically with increasing time */
44void unix_time_update(void) 46void unix_time_update(void)
45{ 47{
46 if (unix_base_time_value == 0) { 48 if (unix_base_time_value == 0) {