diff options
Diffstat (limited to 'toxcore/network.c')
-rw-r--r-- | toxcore/network.c | 128 |
1 files changed, 99 insertions, 29 deletions
diff --git a/toxcore/network.c b/toxcore/network.c index 5980abe3..a8ed4294 100644 --- a/toxcore/network.c +++ b/toxcore/network.c | |||
@@ -29,13 +29,17 @@ | |||
29 | #include "config.h" | 29 | #include "config.h" |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #define LOGGING | ||
33 | #include "logger.h" | 32 | #include "logger.h" |
34 | 33 | ||
35 | #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) | 34 | #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) |
36 | #include <errno.h> | 35 | #include <errno.h> |
37 | #endif | 36 | #endif |
38 | 37 | ||
38 | #ifdef __APPLE__ | ||
39 | #include <mach/clock.h> | ||
40 | #include <mach/mach.h> | ||
41 | #endif | ||
42 | |||
39 | #include "network.h" | 43 | #include "network.h" |
40 | #include "util.h" | 44 | #include "util.h" |
41 | 45 | ||
@@ -153,6 +157,21 @@ int set_socket_nonblock(sock_t sock) | |||
153 | #endif | 157 | #endif |
154 | } | 158 | } |
155 | 159 | ||
160 | /* Set socket to not emit SIGPIPE | ||
161 | * | ||
162 | * return 1 on success | ||
163 | * return 0 on failure | ||
164 | */ | ||
165 | int set_socket_nosigpipe(sock_t sock) | ||
166 | { | ||
167 | #if defined(__MACH__) | ||
168 | int set = 1; | ||
169 | return (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)) == 0); | ||
170 | #else | ||
171 | return 1; | ||
172 | #endif | ||
173 | } | ||
174 | |||
156 | /* Set socket to dual (IPv4 + IPv6 socket) | 175 | /* Set socket to dual (IPv4 + IPv6 socket) |
157 | * | 176 | * |
158 | * return 1 on success | 177 | * return 1 on success |
@@ -160,7 +179,7 @@ int set_socket_nonblock(sock_t sock) | |||
160 | */ | 179 | */ |
161 | int set_socket_dualstack(sock_t sock) | 180 | int set_socket_dualstack(sock_t sock) |
162 | { | 181 | { |
163 | char ipv6only = 0; | 182 | int ipv6only = 0; |
164 | socklen_t optsize = sizeof(ipv6only); | 183 | socklen_t optsize = sizeof(ipv6only); |
165 | int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize); | 184 | int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize); |
166 | 185 | ||
@@ -171,8 +190,9 @@ int set_socket_dualstack(sock_t sock) | |||
171 | return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0); | 190 | return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0); |
172 | } | 191 | } |
173 | 192 | ||
193 | |||
174 | /* return current UNIX time in microseconds (us). */ | 194 | /* return current UNIX time in microseconds (us). */ |
175 | uint64_t current_time(void) | 195 | static uint64_t current_time_actual(void) |
176 | { | 196 | { |
177 | uint64_t time; | 197 | uint64_t time; |
178 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | 198 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) |
@@ -192,29 +212,52 @@ uint64_t current_time(void) | |||
192 | #endif | 212 | #endif |
193 | } | 213 | } |
194 | 214 | ||
195 | /* return a random number. | ||
196 | */ | ||
197 | uint32_t random_int(void) | ||
198 | { | ||
199 | uint32_t randnum; | ||
200 | randombytes((uint8_t *)&randnum , sizeof(randnum)); | ||
201 | return randnum; | ||
202 | } | ||
203 | 215 | ||
204 | uint64_t random_64b(void) | 216 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) |
217 | static uint64_t last_monotime; | ||
218 | static uint64_t add_monotime; | ||
219 | #endif | ||
220 | |||
221 | /* return current monotonic time in milliseconds (ms). */ | ||
222 | uint64_t current_time_monotonic(void) | ||
205 | { | 223 | { |
206 | uint64_t randnum; | 224 | uint64_t time; |
207 | randombytes((uint8_t *)&randnum, sizeof(randnum)); | 225 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) |
208 | return randnum; | 226 | time = (uint64_t)GetTickCount() + add_monotime; |
227 | |||
228 | if (time < last_monotime) { /* Prevent time from ever decreasing because of 32 bit wrap. */ | ||
229 | uint32_t add = ~0; | ||
230 | add_monotime += add; | ||
231 | time += add; | ||
232 | } | ||
233 | |||
234 | last_monotime = time; | ||
235 | #else | ||
236 | struct timespec monotime; | ||
237 | #if defined(__linux__) | ||
238 | clock_gettime(CLOCK_MONOTONIC_RAW, &monotime); | ||
239 | #elif defined(__APPLE__) | ||
240 | clock_serv_t muhclock; | ||
241 | mach_timespec_t machtime; | ||
242 | |||
243 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); | ||
244 | clock_get_time(muhclock, &machtime); | ||
245 | mach_port_deallocate(mach_task_self(), muhclock); | ||
246 | |||
247 | monotime.tv_sec = machtime.tv_sec; | ||
248 | monotime.tv_nsec = machtime.tv_nsec; | ||
249 | #else | ||
250 | clock_gettime(CLOCK_MONOTONIC, &monotime); | ||
251 | #endif | ||
252 | time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL); | ||
253 | #endif | ||
254 | return time; | ||
209 | } | 255 | } |
210 | 256 | ||
211 | /* In case no logging */ | 257 | /* In case no logging */ |
212 | #ifndef LOGGING | 258 | #ifndef LOGGING |
213 | |||
214 | #define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) | 259 | #define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) |
215 | 260 | #else | |
216 | #else | ||
217 | |||
218 | #define data_0(__buflen__, __buffer__) __buflen__ > 4 ? ntohl(*(uint32_t *)&__buffer__[1]) : 0 | 261 | #define data_0(__buflen__, __buffer__) __buflen__ > 4 ? ntohl(*(uint32_t *)&__buffer__[1]) : 0 |
219 | #define data_1(__buflen__, __buffer__) __buflen__ > 7 ? ntohl(*(uint32_t *)&__buffer__[5]) : 0 | 262 | #define data_1(__buflen__, __buffer__) __buflen__ > 7 ? ntohl(*(uint32_t *)&__buffer__[5]) : 0 |
220 | 263 | ||
@@ -299,7 +342,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le | |||
299 | if ((res >= 0) && ((uint32_t)res == length)) | 342 | if ((res >= 0) && ((uint32_t)res == length)) |
300 | net->send_fail_eagain = 0; | 343 | net->send_fail_eagain = 0; |
301 | else if ((res < 0) && (errno == EWOULDBLOCK)) | 344 | else if ((res < 0) && (errno == EWOULDBLOCK)) |
302 | net->send_fail_eagain = current_time(); | 345 | net->send_fail_eagain = current_time_monotonic(); |
303 | 346 | ||
304 | return res; | 347 | return res; |
305 | } | 348 | } |
@@ -308,7 +351,6 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le | |||
308 | * ip and port of sender is put into ip_port. | 351 | * ip and port of sender is put into ip_port. |
309 | * Packet data is put into data. | 352 | * Packet data is put into data. |
310 | * Packet length is put into length. | 353 | * Packet length is put into length. |
311 | * Dump all empty packets. | ||
312 | */ | 354 | */ |
313 | static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) | 355 | static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) |
314 | { | 356 | { |
@@ -322,7 +364,7 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t | |||
322 | *length = 0; | 364 | *length = 0; |
323 | int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); | 365 | int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); |
324 | 366 | ||
325 | if (fail_or_len <= 0) { | 367 | if (fail_or_len < 0) { |
326 | 368 | ||
327 | LOGGER_SCOPE( if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) | 369 | LOGGER_SCOPE( if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) |
328 | LOGGER_ERROR("Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); ); | 370 | LOGGER_ERROR("Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); ); |
@@ -438,13 +480,13 @@ int networking_wait_execute(uint8_t *data, long seconds, long microseconds) | |||
438 | * that code) | 480 | * that code) |
439 | */ | 481 | */ |
440 | if (s->send_fail_eagain != 0) { | 482 | if (s->send_fail_eagain != 0) { |
441 | // current_time(): microseconds | 483 | // current_time(): milliseconds |
442 | uint64_t now = current_time(); | 484 | uint64_t now = current_time_monotonic(); |
443 | 485 | ||
444 | /* s->sendqueue_length: might be used to guess how long we keep checking */ | 486 | /* s->sendqueue_length: might be used to guess how long we keep checking */ |
445 | /* for now, threshold is hardcoded to 250ms, too long for a really really | 487 | /* for now, threshold is hardcoded to 250ms, too long for a really really |
446 | * fast link, but too short for a sloooooow link... */ | 488 | * fast link, but too short for a sloooooow link... */ |
447 | if (now - s->send_fail_eagain < 250000) { | 489 | if (now - s->send_fail_eagain < 250) { |
448 | writefds_add = 1; | 490 | writefds_add = 1; |
449 | } | 491 | } |
450 | } | 492 | } |
@@ -508,6 +550,11 @@ int networking_wait_cleanup(Networking_Core *net, uint8_t *data) | |||
508 | return 1; | 550 | return 1; |
509 | } | 551 | } |
510 | 552 | ||
553 | #ifndef VANILLA_NACL | ||
554 | /* Used for sodium_init() */ | ||
555 | #include <sodium.h> | ||
556 | #endif | ||
557 | |||
511 | uint8_t at_startup_ran = 0; | 558 | uint8_t at_startup_ran = 0; |
512 | int networking_at_startup(void) | 559 | int networking_at_startup(void) |
513 | { | 560 | { |
@@ -531,9 +578,9 @@ int networking_at_startup(void) | |||
531 | return -1; | 578 | return -1; |
532 | 579 | ||
533 | #else | 580 | #else |
534 | srandom((uint32_t)current_time()); | 581 | srandom((uint32_t)current_time_actual()); |
535 | #endif | 582 | #endif |
536 | srand((uint32_t)current_time()); | 583 | srand((uint32_t)current_time_actual()); |
537 | at_startup_ran = 1; | 584 | at_startup_ran = 1; |
538 | return 0; | 585 | return 0; |
539 | } | 586 | } |
@@ -637,7 +684,6 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
637 | } | 684 | } |
638 | 685 | ||
639 | if (ip.family == AF_INET6) { | 686 | if (ip.family == AF_INET6) { |
640 | |||
641 | #ifdef LOGGING | 687 | #ifdef LOGGING |
642 | int is_dualstack = | 688 | int is_dualstack = |
643 | #endif /* LOGGING */ | 689 | #endif /* LOGGING */ |
@@ -650,7 +696,6 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
650 | mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02; | 696 | mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02; |
651 | mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01; | 697 | mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01; |
652 | mreq.ipv6mr_interface = 0; | 698 | mreq.ipv6mr_interface = 0; |
653 | |||
654 | #ifdef LOGGING | 699 | #ifdef LOGGING |
655 | int res = | 700 | int res = |
656 | #endif /* LOGGING */ | 701 | #endif /* LOGGING */ |
@@ -829,6 +874,31 @@ void ipport_copy(IP_Port *target, IP_Port *source) | |||
829 | memcpy(target, source, sizeof(IP_Port)); | 874 | memcpy(target, source, sizeof(IP_Port)); |
830 | }; | 875 | }; |
831 | 876 | ||
877 | /* packing and unpacking functions */ | ||
878 | void ip_pack(uint8_t *data, IP *source) | ||
879 | { | ||
880 | data[0] = source->family; | ||
881 | memcpy(data + 1, &source->ip6, SIZE_IP6); | ||
882 | } | ||
883 | |||
884 | void ip_unpack(IP *target, uint8_t *data) | ||
885 | { | ||
886 | target->family = data[0]; | ||
887 | memcpy(&target->ip6, data + 1, SIZE_IP6); | ||
888 | } | ||
889 | |||
890 | void ipport_pack(uint8_t *data, IP_Port *source) | ||
891 | { | ||
892 | ip_pack(data, &source->ip); | ||
893 | memcpy(data + SIZE_IP, &source->port, SIZE_PORT); | ||
894 | } | ||
895 | |||
896 | void ipport_unpack(IP_Port *target, uint8_t *data) | ||
897 | { | ||
898 | ip_unpack(&target->ip, data); | ||
899 | memcpy(&target->port, data + SIZE_IP, SIZE_PORT); | ||
900 | } | ||
901 | |||
832 | /* ip_ntoa | 902 | /* ip_ntoa |
833 | * converts ip into a string | 903 | * converts ip into a string |
834 | * uses a static buffer, so mustn't used multiple times in the same output | 904 | * uses a static buffer, so mustn't used multiple times in the same output |