diff options
-rw-r--r-- | auto_tests/network_test.c | 11 | ||||
-rw-r--r-- | testing/DHT_test.c | 10 | ||||
-rw-r--r-- | toxcore/DHT.c | 46 | ||||
-rw-r--r-- | toxcore/LAN_discovery.c | 56 | ||||
-rw-r--r-- | toxcore/Messenger.c | 50 | ||||
-rw-r--r-- | toxcore/Messenger.h | 2 | ||||
-rw-r--r-- | toxcore/network.c | 65 | ||||
-rw-r--r-- | toxcore/network.h | 8 | ||||
-rw-r--r-- | toxcore/util.c | 2 |
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) | |||
87 | static void print_assoc(IPPTsPng *assoc, uint8_t ours) | 87 | static 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 | ||
788 | static uint8_t cmp_public_key[CRYPTO_PUBLIC_KEY_SIZE]; | 794 | typedef struct { |
795 | const uint8_t *base_public_key; | ||
796 | Client_data entry; | ||
797 | } Cmp_data; | ||
798 | |||
789 | static int cmp_dht_entry(const void *a, const void *b) | 799 | static 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 | ||
852 | static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) | 866 | static 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. */ | ||
42 | static int broadcast_count = -1; | 44 | static int broadcast_count = -1; |
43 | static IP_Port broadcast_ip_port[MAX_INTERFACES]; | 45 | static 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 | ||
49 | static void fetch_broadcast_info(uint16_t port) | 51 | static 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 |
2474 | static time_t lastdump = 0; | 2476 | |
2475 | static char IDString[CRYPTO_PUBLIC_KEY_SIZE * 2 + 1]; | 2477 | #define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1) |
2476 | static char *ID2String(const uint8_t *pk) | 2478 | /* id_str should be of length at least IDSTRING_LEN */ |
2479 | static 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) | |||
285 | static void loglogdata(Logger *log, const char *message, const uint8_t *buffer, | 290 | static 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 */ | 887 | const char *ip_ntoa(const IP *ip, char *ip_str, size_t length) |
876 | static char addresstext[96]; // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ? | ||
877 | const 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 | */ |
201 | const 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 ? | ||
205 | const 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 @@ | |||
41 | static uint64_t unix_time_value; | 41 | static uint64_t unix_time_value; |
42 | static uint64_t unix_base_time_value; | 42 | static 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 */ | ||
44 | void unix_time_update(void) | 46 | void unix_time_update(void) |
45 | { | 47 | { |
46 | if (unix_base_time_value == 0) { | 48 | if (unix_base_time_value == 0) { |