summaryrefslogtreecommitdiff
path: root/toxcore/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/network.c')
-rw-r--r--toxcore/network.c128
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 */
165int 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 */
161int set_socket_dualstack(sock_t sock) 180int 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). */
175uint64_t current_time(void) 195static 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 */
197uint32_t random_int(void)
198{
199 uint32_t randnum;
200 randombytes((uint8_t *)&randnum , sizeof(randnum));
201 return randnum;
202}
203 215
204uint64_t random_64b(void) 216#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
217static uint64_t last_monotime;
218static uint64_t add_monotime;
219#endif
220
221/* return current monotonic time in milliseconds (ms). */
222uint64_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 */
313static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) 355static 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
511uint8_t at_startup_ran = 0; 558uint8_t at_startup_ran = 0;
512int networking_at_startup(void) 559int 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 */
878void ip_pack(uint8_t *data, IP *source)
879{
880 data[0] = source->family;
881 memcpy(data + 1, &source->ip6, SIZE_IP6);
882}
883
884void ip_unpack(IP *target, uint8_t *data)
885{
886 target->family = data[0];
887 memcpy(&target->ip6, data + 1, SIZE_IP6);
888}
889
890void 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
896void 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