summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/TCP_test.c152
-rw-r--r--auto_tests/dht_test.c71
-rw-r--r--auto_tests/messenger_test.c5
-rw-r--r--auto_tests/onion_test.c76
-rw-r--r--other/DHT_bootstrap.c17
-rwxr-xr-xother/astyle/format-source4
-rw-r--r--other/bootstrap_daemon/src/tox-bootstrapd.c33
-rw-r--r--testing/DHT_test.c8
-rw-r--r--testing/Messenger_test.c11
-rw-r--r--toxav/groupav.c12
-rw-r--r--toxcore/DHT.c201
-rw-r--r--toxcore/DHT.h7
-rw-r--r--toxcore/Messenger.c24
-rw-r--r--toxcore/Messenger.h3
-rw-r--r--toxcore/TCP_client.c20
-rw-r--r--toxcore/TCP_client.h6
-rw-r--r--toxcore/TCP_connection.c26
-rw-r--r--toxcore/TCP_connection.h2
-rw-r--r--toxcore/TCP_server.c55
-rw-r--r--toxcore/TCP_server.h2
-rw-r--r--toxcore/friend_connection.c27
-rw-r--r--toxcore/friend_connection.h3
-rw-r--r--toxcore/group.c14
-rw-r--r--toxcore/group.h4
-rw-r--r--toxcore/mono_time.c23
-rw-r--r--toxcore/mono_time.h37
-rw-r--r--toxcore/mono_time_test.cc28
-rw-r--r--toxcore/net_crypto.c42
-rw-r--r--toxcore/net_crypto.h2
-rw-r--r--toxcore/onion.c18
-rw-r--r--toxcore/onion.h6
-rw-r--r--toxcore/onion_announce.c29
-rw-r--r--toxcore/onion_announce.h2
-rw-r--r--toxcore/onion_client.c146
-rw-r--r--toxcore/onion_client.h2
-rw-r--r--toxcore/ping.api.h3
-rw-r--r--toxcore/ping.c19
-rw-r--r--toxcore/ping.h7
-rw-r--r--toxcore/ping_array.api.h6
-rw-r--r--toxcore/ping_array.c14
-rw-r--r--toxcore/ping_array.h11
-rw-r--r--toxcore/tox.c21
42 files changed, 681 insertions, 518 deletions
diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c
index 52ecad77..3c5d56b9 100644
--- a/auto_tests/TCP_test.c
+++ b/auto_tests/TCP_test.c
@@ -36,17 +36,19 @@ static inline IP get_loopback()
36 return ip; 36 return ip;
37} 37}
38 38
39static void do_TCP_server_delay(TCP_Server *tcp_s, int delay) 39static void do_TCP_server_delay(TCP_Server *tcp_s, Mono_Time *mono_time, int delay)
40{ 40{
41 c_sleep(delay); 41 c_sleep(delay);
42 unix_time_update(); 42 mono_time_update(mono_time);
43 do_TCP_server(tcp_s); 43 do_TCP_server(tcp_s, mono_time);
44 c_sleep(delay); 44 c_sleep(delay);
45} 45}
46static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643}; 46static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643};
47 47
48START_TEST(test_basic) 48START_TEST(test_basic)
49{ 49{
50 Mono_Time *mono_time = mono_time_new();
51
50 // Attempt to create a new TCP_Server instance. 52 // Attempt to create a new TCP_Server instance.
51 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; 53 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
52 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; 54 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
@@ -99,12 +101,12 @@ START_TEST(test_basic)
99 ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1) == TCP_CLIENT_HANDSHAKE_SIZE - 1, 101 ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1) == TCP_CLIENT_HANDSHAKE_SIZE - 1,
100 "An attempt to send the initial handshake minus last byte failed."); 102 "An attempt to send the initial handshake minus last byte failed.");
101 103
102 do_TCP_server_delay(tcp_s, 50); 104 do_TCP_server_delay(tcp_s, mono_time, 50);
103 105
104 ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1) == 1, 106 ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1) == 1,
105 "The attempt to send the last byte of handshake failed."); 107 "The attempt to send the last byte of handshake failed.");
106 108
107 do_TCP_server_delay(tcp_s, 50); 109 do_TCP_server_delay(tcp_s, mono_time, 50);
108 110
109 // Receiving server response and decrypting it 111 // Receiving server response and decrypting it
110 uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; 112 uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
@@ -142,8 +144,8 @@ START_TEST(test_basic)
142 i += msg_length; 144 i += msg_length;
143 145
144 c_sleep(50); 146 c_sleep(50);
145 unix_time_update(); 147 mono_time_update(mono_time);
146 do_TCP_server(tcp_s); 148 do_TCP_server(tcp_s, mono_time);
147 } 149 }
148 150
149 // Receiving the second response and verifying its validity 151 // Receiving the second response and verifying its validity
@@ -167,6 +169,8 @@ START_TEST(test_basic)
167 // Closing connections. 169 // Closing connections.
168 kill_sock(sock); 170 kill_sock(sock);
169 kill_TCP_server(tcp_s); 171 kill_TCP_server(tcp_s);
172
173 mono_time_free(mono_time);
170} 174}
171END_TEST 175END_TEST
172 176
@@ -178,7 +182,7 @@ struct sec_TCP_con {
178 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; 182 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
179}; 183};
180 184
181static struct sec_TCP_con *new_TCP_con(TCP_Server *tcp_s) 185static struct sec_TCP_con *new_TCP_con(TCP_Server *tcp_s, Mono_Time *mono_time)
182{ 186{
183 struct sec_TCP_con *sec_c = (struct sec_TCP_con *)malloc(sizeof(struct sec_TCP_con)); 187 struct sec_TCP_con *sec_c = (struct sec_TCP_con *)malloc(sizeof(struct sec_TCP_con));
184 Socket sock = net_socket(net_family_ipv6, TOX_SOCK_STREAM, TOX_PROTO_TCP); 188 Socket sock = net_socket(net_family_ipv6, TOX_SOCK_STREAM, TOX_PROTO_TCP);
@@ -210,12 +214,12 @@ static struct sec_TCP_con *new_TCP_con(TCP_Server *tcp_s)
210 ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1) == TCP_CLIENT_HANDSHAKE_SIZE - 1, 214 ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1) == TCP_CLIENT_HANDSHAKE_SIZE - 1,
211 "Failed to send the first portion of the handshake to the TCP relay server."); 215 "Failed to send the first portion of the handshake to the TCP relay server.");
212 216
213 do_TCP_server_delay(tcp_s, 50); 217 do_TCP_server_delay(tcp_s, mono_time, 50);
214 218
215 ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1) == 1, 219 ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1) == 1,
216 "Failed to send last byte of handshake."); 220 "Failed to send last byte of handshake.");
217 221
218 do_TCP_server_delay(tcp_s, 50); 222 do_TCP_server_delay(tcp_s, mono_time, 50);
219 223
220 uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; 224 uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
221 uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE]; 225 uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE];
@@ -266,6 +270,8 @@ static int read_packet_sec_TCP(struct sec_TCP_con *con, uint8_t *data, uint16_t
266 270
267START_TEST(test_some) 271START_TEST(test_some)
268{ 272{
273 Mono_Time *mono_time = mono_time_new();
274
269 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; 275 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
270 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; 276 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
271 crypto_new_keypair(self_public_key, self_secret_key); 277 crypto_new_keypair(self_public_key, self_secret_key);
@@ -273,9 +279,9 @@ START_TEST(test_some)
273 ck_assert_msg(tcp_s != nullptr, "Failed to create TCP relay server"); 279 ck_assert_msg(tcp_s != nullptr, "Failed to create TCP relay server");
274 ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind to all ports."); 280 ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind to all ports.");
275 281
276 struct sec_TCP_con *con1 = new_TCP_con(tcp_s); 282 struct sec_TCP_con *con1 = new_TCP_con(tcp_s, mono_time);
277 struct sec_TCP_con *con2 = new_TCP_con(tcp_s); 283 struct sec_TCP_con *con2 = new_TCP_con(tcp_s, mono_time);
278 struct sec_TCP_con *con3 = new_TCP_con(tcp_s); 284 struct sec_TCP_con *con3 = new_TCP_con(tcp_s, mono_time);
279 285
280 uint8_t requ_p[1 + CRYPTO_PUBLIC_KEY_SIZE]; 286 uint8_t requ_p[1 + CRYPTO_PUBLIC_KEY_SIZE];
281 requ_p[0] = 0; 287 requ_p[0] = 0;
@@ -286,7 +292,7 @@ START_TEST(test_some)
286 memcpy(requ_p + 1, con1->public_key, CRYPTO_PUBLIC_KEY_SIZE); 292 memcpy(requ_p + 1, con1->public_key, CRYPTO_PUBLIC_KEY_SIZE);
287 write_packet_TCP_secure_connection(con3, requ_p, sizeof(requ_p)); 293 write_packet_TCP_secure_connection(con3, requ_p, sizeof(requ_p));
288 294
289 do_TCP_server_delay(tcp_s, 50); 295 do_TCP_server_delay(tcp_s, mono_time, 50);
290 296
291 // Testing response from connection 1 297 // Testing response from connection 1
292 uint8_t data[2048]; 298 uint8_t data[2048];
@@ -309,7 +315,7 @@ START_TEST(test_some)
309 write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet)); 315 write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet));
310 write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet)); 316 write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet));
311 317
312 do_TCP_server_delay(tcp_s, 50); 318 do_TCP_server_delay(tcp_s, mono_time, 50);
313 319
314 len = read_packet_sec_TCP(con1, data, 2 + 2 + CRYPTO_MAC_SIZE); 320 len = read_packet_sec_TCP(con1, data, 2 + 2 + CRYPTO_MAC_SIZE);
315 ck_assert_msg(len == 2, "wrong len %d", len); 321 ck_assert_msg(len == 2, "wrong len %d", len);
@@ -334,7 +340,7 @@ START_TEST(test_some)
334 write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); 340 write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet));
335 write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); 341 write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet));
336 write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); 342 write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet));
337 do_TCP_server_delay(tcp_s, 50); 343 do_TCP_server_delay(tcp_s, mono_time, 50);
338 len = read_packet_sec_TCP(con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); 344 len = read_packet_sec_TCP(con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE);
339 ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); 345 ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len);
340 ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1], 346 ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1],
@@ -351,7 +357,7 @@ START_TEST(test_some)
351 uint8_t ping_packet[1 + sizeof(uint64_t)] = {4, 8, 6, 9, 67}; 357 uint8_t ping_packet[1 + sizeof(uint64_t)] = {4, 8, 6, 9, 67};
352 write_packet_TCP_secure_connection(con1, ping_packet, sizeof(ping_packet)); 358 write_packet_TCP_secure_connection(con1, ping_packet, sizeof(ping_packet));
353 359
354 do_TCP_server_delay(tcp_s, 50); 360 do_TCP_server_delay(tcp_s, mono_time, 50);
355 361
356 len = read_packet_sec_TCP(con1, data, 2 + sizeof(ping_packet) + CRYPTO_MAC_SIZE); 362 len = read_packet_sec_TCP(con1, data, 2 + sizeof(ping_packet) + CRYPTO_MAC_SIZE);
357 ck_assert_msg(len == sizeof(ping_packet), "wrong len %d", len); 363 ck_assert_msg(len == sizeof(ping_packet), "wrong len %d", len);
@@ -363,6 +369,8 @@ START_TEST(test_some)
363 kill_TCP_con(con1); 369 kill_TCP_con(con1);
364 kill_TCP_con(con2); 370 kill_TCP_con(con2);
365 kill_TCP_con(con3); 371 kill_TCP_con(con3);
372
373 mono_time_free(mono_time);
366} 374}
367END_TEST 375END_TEST
368 376
@@ -449,7 +457,8 @@ static int oob_data_callback(void *object, const uint8_t *public_key, const uint
449 457
450START_TEST(test_client) 458START_TEST(test_client)
451{ 459{
452 unix_time_update(); 460 Mono_Time *mono_time = mono_time_new();
461
453 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; 462 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
454 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; 463 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
455 crypto_new_keypair(self_public_key, self_secret_key); 464 crypto_new_keypair(self_public_key, self_secret_key);
@@ -465,8 +474,9 @@ START_TEST(test_client)
465 ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]); 474 ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]);
466 ip_port_tcp_s.ip = get_loopback(); 475 ip_port_tcp_s.ip = get_loopback();
467 476
468 TCP_Client_Connection *conn = new_TCP_connection(ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr); 477 TCP_Client_Connection *conn = new_TCP_connection(mono_time, ip_port_tcp_s, self_public_key, f_public_key, f_secret_key,
469 do_TCP_connection(conn, nullptr); 478 nullptr);
479 do_TCP_connection(mono_time, conn, nullptr);
470 c_sleep(50); 480 c_sleep(50);
471 481
472 // The connection status should be unconfirmed here because we have finished 482 // The connection status should be unconfirmed here because we have finished
@@ -474,13 +484,13 @@ START_TEST(test_client)
474 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_UNCONFIRMED, "Wrong connection status. Expected: %d, is: %d.", 484 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_UNCONFIRMED, "Wrong connection status. Expected: %d, is: %d.",
475 TCP_CLIENT_UNCONFIRMED, tcp_con_status(conn)); 485 TCP_CLIENT_UNCONFIRMED, tcp_con_status(conn));
476 486
477 do_TCP_server_delay(tcp_s, 50); // Now let the server handle requests... 487 do_TCP_server_delay(tcp_s, mono_time, 50); // Now let the server handle requests...
478 488
479 const uint8_t LOOP_SIZE = 3; 489 const uint8_t LOOP_SIZE = 3;
480 490
481 for (uint8_t i = 0; i < LOOP_SIZE; i++) { 491 for (uint8_t i = 0; i < LOOP_SIZE; i++) {
482 unix_time_update(); 492 mono_time_update(mono_time);
483 do_TCP_connection(conn, nullptr); // Run the connection loop. 493 do_TCP_connection(mono_time, conn, nullptr); // Run the connection loop.
484 494
485 // The status of the connection should continue to be TCP_CLIENT_CONFIRMED after multiple subsequent do_TCP_connection() calls. 495 // The status of the connection should continue to be TCP_CLIENT_CONFIRMED after multiple subsequent do_TCP_connection() calls.
486 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONFIRMED, "Wrong connection status. Expected: %d, is: %d", 496 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONFIRMED, "Wrong connection status. Expected: %d, is: %d",
@@ -489,7 +499,7 @@ START_TEST(test_client)
489 c_sleep(i == LOOP_SIZE - 1 ? 0 : 500); // Sleep for 500ms on all except third loop. 499 c_sleep(i == LOOP_SIZE - 1 ? 0 : 500); // Sleep for 500ms on all except third loop.
490 } 500 }
491 501
492 do_TCP_server_delay(tcp_s, 50); 502 do_TCP_server_delay(tcp_s, mono_time, 50);
493 503
494 // And still after the server runs again. 504 // And still after the server runs again.
495 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %d, is: %d", TCP_CLIENT_CONFIRMED, 505 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %d, is: %d", TCP_CLIENT_CONFIRMED,
@@ -499,8 +509,8 @@ START_TEST(test_client)
499 uint8_t f2_secret_key[CRYPTO_SECRET_KEY_SIZE]; 509 uint8_t f2_secret_key[CRYPTO_SECRET_KEY_SIZE];
500 crypto_new_keypair(f2_public_key, f2_secret_key); 510 crypto_new_keypair(f2_public_key, f2_secret_key);
501 ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]); 511 ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]);
502 TCP_Client_Connection *conn2 = new_TCP_connection( 512 TCP_Client_Connection *conn2 = new_TCP_connection(mono_time, ip_port_tcp_s, self_public_key, f2_public_key,
503 ip_port_tcp_s, self_public_key, f2_public_key, f2_secret_key, nullptr); 513 f2_secret_key, nullptr);
504 514
505 // The client should call this function (defined earlier) during the routing process. 515 // The client should call this function (defined earlier) during the routing process.
506 routing_response_handler(conn, response_callback, (char *)conn + 2); 516 routing_response_handler(conn, response_callback, (char *)conn + 2);
@@ -514,13 +524,13 @@ START_TEST(test_client)
514 // These integers will increment per successful callback. 524 // These integers will increment per successful callback.
515 oob_data_callback_good = response_callback_good = status_callback_good = data_callback_good = 0; 525 oob_data_callback_good = response_callback_good = status_callback_good = data_callback_good = 0;
516 526
517 do_TCP_connection(conn, nullptr); 527 do_TCP_connection(mono_time, conn, nullptr);
518 do_TCP_connection(conn2, nullptr); 528 do_TCP_connection(mono_time, conn2, nullptr);
519 529
520 do_TCP_server_delay(tcp_s, 50); 530 do_TCP_server_delay(tcp_s, mono_time, 50);
521 531
522 do_TCP_connection(conn, nullptr); 532 do_TCP_connection(mono_time, conn, nullptr);
523 do_TCP_connection(conn2, nullptr); 533 do_TCP_connection(mono_time, conn2, nullptr);
524 c_sleep(50); 534 c_sleep(50);
525 535
526 uint8_t data[5] = {1, 2, 3, 4, 5}; 536 uint8_t data[5] = {1, 2, 3, 4, 5};
@@ -529,10 +539,10 @@ START_TEST(test_client)
529 send_routing_request(conn, f2_public_key); 539 send_routing_request(conn, f2_public_key);
530 send_routing_request(conn2, f_public_key); 540 send_routing_request(conn2, f_public_key);
531 541
532 do_TCP_server_delay(tcp_s, 50); 542 do_TCP_server_delay(tcp_s, mono_time, 50);
533 543
534 do_TCP_connection(conn, nullptr); 544 do_TCP_connection(mono_time, conn, nullptr);
535 do_TCP_connection(conn2, nullptr); 545 do_TCP_connection(mono_time, conn2, nullptr);
536 546
537 // All callback methods save data should have run during the above network prodding. 547 // All callback methods save data should have run during the above network prodding.
538 ck_assert_msg(oob_data_callback_good == 1, "OOB callback not called"); 548 ck_assert_msg(oob_data_callback_good == 1, "OOB callback not called");
@@ -543,22 +553,22 @@ START_TEST(test_client)
543 ck_assert_msg(status_callback_connection_id == response_callback_connection_id, 553 ck_assert_msg(status_callback_connection_id == response_callback_connection_id,
544 "Status and response callback connection IDs are not equal."); 554 "Status and response callback connection IDs are not equal.");
545 555
546 do_TCP_server_delay(tcp_s, 50); 556 do_TCP_server_delay(tcp_s, mono_time, 50);
547 557
548 ck_assert_msg(send_data(conn2, 0, data, 5) == 1, "Failed a send_data() call."); 558 ck_assert_msg(send_data(conn2, 0, data, 5) == 1, "Failed a send_data() call.");
549 559
550 do_TCP_server_delay(tcp_s, 50); 560 do_TCP_server_delay(tcp_s, mono_time, 50);
551 561
552 do_TCP_connection(conn, nullptr); 562 do_TCP_connection(mono_time, conn, nullptr);
553 do_TCP_connection(conn2, nullptr); 563 do_TCP_connection(mono_time, conn2, nullptr);
554 ck_assert_msg(data_callback_good == 1, "Data callback was not called."); 564 ck_assert_msg(data_callback_good == 1, "Data callback was not called.");
555 status_callback_good = 0; 565 status_callback_good = 0;
556 send_disconnect_request(conn2, 0); 566 send_disconnect_request(conn2, 0);
557 567
558 do_TCP_server_delay(tcp_s, 50); 568 do_TCP_server_delay(tcp_s, mono_time, 50);
559 569
560 do_TCP_connection(conn, nullptr); 570 do_TCP_connection(mono_time, conn, nullptr);
561 do_TCP_connection(conn2, nullptr); 571 do_TCP_connection(mono_time, conn2, nullptr);
562 ck_assert_msg(status_callback_good == 1, "Status callback not called"); 572 ck_assert_msg(status_callback_good == 1, "Status callback not called");
563 ck_assert_msg(status_callback_status == 1, "Wrong status callback status."); 573 ck_assert_msg(status_callback_status == 1, "Wrong status callback status.");
564 574
@@ -566,13 +576,16 @@ START_TEST(test_client)
566 kill_TCP_server(tcp_s); 576 kill_TCP_server(tcp_s);
567 kill_TCP_connection(conn); 577 kill_TCP_connection(conn);
568 kill_TCP_connection(conn2); 578 kill_TCP_connection(conn2);
579
580 mono_time_free(mono_time);
569} 581}
570END_TEST 582END_TEST
571 583
572// Test how the client handles servers that don't respond. 584// Test how the client handles servers that don't respond.
573START_TEST(test_client_invalid) 585START_TEST(test_client_invalid)
574{ 586{
575 unix_time_update(); 587 Mono_Time *mono_time = mono_time_new();
588
576 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; 589 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
577 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; 590 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
578 crypto_new_keypair(self_public_key, self_secret_key); 591 crypto_new_keypair(self_public_key, self_secret_key);
@@ -584,11 +597,12 @@ START_TEST(test_client_invalid)
584 597
585 ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]); 598 ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]);
586 ip_port_tcp_s.ip = get_loopback(); 599 ip_port_tcp_s.ip = get_loopback();
587 TCP_Client_Connection *conn = new_TCP_connection(ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr); 600 TCP_Client_Connection *conn = new_TCP_connection(mono_time, ip_port_tcp_s, self_public_key, f_public_key, f_secret_key,
601 nullptr);
588 602
589 // Run the client's main loop but not the server. 603 // Run the client's main loop but not the server.
590 unix_time_update(); 604 mono_time_update(mono_time);
591 do_TCP_connection(conn, nullptr); 605 do_TCP_connection(mono_time, conn, nullptr);
592 c_sleep(50); 606 c_sleep(50);
593 607
594 // After 50ms of no response... 608 // After 50ms of no response...
@@ -596,18 +610,20 @@ START_TEST(test_client_invalid)
596 TCP_CLIENT_CONNECTING, tcp_con_status(conn)); 610 TCP_CLIENT_CONNECTING, tcp_con_status(conn));
597 // After 5s... 611 // After 5s...
598 c_sleep(5000); 612 c_sleep(5000);
599 unix_time_update(); 613 mono_time_update(mono_time);
600 do_TCP_connection(conn, nullptr); 614 do_TCP_connection(mono_time, conn, nullptr);
601 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONNECTING, "Wrong status. Expected: %d, is: %d.", 615 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONNECTING, "Wrong status. Expected: %d, is: %d.",
602 TCP_CLIENT_CONNECTING, tcp_con_status(conn)); 616 TCP_CLIENT_CONNECTING, tcp_con_status(conn));
603 // 11s... (Should wait for 10 before giving up.) 617 // 11s... (Should wait for 10 before giving up.)
604 c_sleep(6000); 618 c_sleep(6000);
605 unix_time_update(); 619 mono_time_update(mono_time);
606 do_TCP_connection(conn, nullptr); 620 do_TCP_connection(mono_time, conn, nullptr);
607 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %d, is: %d.", 621 ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %d, is: %d.",
608 TCP_CLIENT_DISCONNECTED, tcp_con_status(conn)); 622 TCP_CLIENT_DISCONNECTED, tcp_con_status(conn));
609 623
610 kill_TCP_connection(conn); 624 kill_TCP_connection(conn);
625
626 mono_time_free(mono_time);
611} 627}
612END_TEST 628END_TEST
613 629
@@ -639,8 +655,9 @@ static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t
639 655
640START_TEST(test_tcp_connection) 656START_TEST(test_tcp_connection)
641{ 657{
658 Mono_Time *mono_time = mono_time_new();
659
642 tcp_data_callback_called = 0; 660 tcp_data_callback_called = 0;
643 unix_time_update();
644 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; 661 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
645 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; 662 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
646 crypto_new_keypair(self_public_key, self_secret_key); 663 crypto_new_keypair(self_public_key, self_secret_key);
@@ -650,11 +667,11 @@ START_TEST(test_tcp_connection)
650 TCP_Proxy_Info proxy_info; 667 TCP_Proxy_Info proxy_info;
651 proxy_info.proxy_type = TCP_PROXY_NONE; 668 proxy_info.proxy_type = TCP_PROXY_NONE;
652 crypto_new_keypair(self_public_key, self_secret_key); 669 crypto_new_keypair(self_public_key, self_secret_key);
653 TCP_Connections *tc_1 = new_tcp_connections(self_secret_key, &proxy_info); 670 TCP_Connections *tc_1 = new_tcp_connections(mono_time, self_secret_key, &proxy_info);
654 ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_1), self_public_key) == 0, "Wrong public key"); 671 ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_1), self_public_key) == 0, "Wrong public key");
655 672
656 crypto_new_keypair(self_public_key, self_secret_key); 673 crypto_new_keypair(self_public_key, self_secret_key);
657 TCP_Connections *tc_2 = new_tcp_connections(self_secret_key, &proxy_info); 674 TCP_Connections *tc_2 = new_tcp_connections(mono_time, self_secret_key, &proxy_info);
658 ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_2), self_public_key) == 0, "Wrong public key"); 675 ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_2), self_public_key) == 0, "Wrong public key");
659 676
660 IP_Port ip_port_tcp_s; 677 IP_Port ip_port_tcp_s;
@@ -676,17 +693,17 @@ START_TEST(test_tcp_connection)
676 ck_assert_msg(new_tcp_connection_to(tc_2, tcp_connections_public_key(tc_1), 123) == -1, 693 ck_assert_msg(new_tcp_connection_to(tc_2, tcp_connections_public_key(tc_1), 123) == -1,
677 "Managed to readd same connection\n"); 694 "Managed to readd same connection\n");
678 695
679 do_TCP_server_delay(tcp_s, 50); 696 do_TCP_server_delay(tcp_s, mono_time, 50);
680 697
681 do_tcp_connections(tc_1, nullptr); 698 do_tcp_connections(tc_1, nullptr);
682 do_tcp_connections(tc_2, nullptr); 699 do_tcp_connections(tc_2, nullptr);
683 700
684 do_TCP_server_delay(tcp_s, 50); 701 do_TCP_server_delay(tcp_s, mono_time, 50);
685 702
686 do_tcp_connections(tc_1, nullptr); 703 do_tcp_connections(tc_1, nullptr);
687 do_tcp_connections(tc_2, nullptr); 704 do_tcp_connections(tc_2, nullptr);
688 705
689 do_TCP_server_delay(tcp_s, 50); 706 do_TCP_server_delay(tcp_s, mono_time, 50);
690 707
691 do_tcp_connections(tc_1, nullptr); 708 do_tcp_connections(tc_1, nullptr);
692 do_tcp_connections(tc_2, nullptr); 709 do_tcp_connections(tc_2, nullptr);
@@ -695,7 +712,7 @@ START_TEST(test_tcp_connection)
695 ck_assert_msg(ret == 0, "could not send packet."); 712 ck_assert_msg(ret == 0, "could not send packet.");
696 set_packet_tcp_connection_callback(tc_2, &tcp_data_callback, (void *) 120397); 713 set_packet_tcp_connection_callback(tc_2, &tcp_data_callback, (void *) 120397);
697 714
698 do_TCP_server_delay(tcp_s, 50); 715 do_TCP_server_delay(tcp_s, mono_time, 50);
699 716
700 do_tcp_connections(tc_1, nullptr); 717 do_tcp_connections(tc_1, nullptr);
701 do_tcp_connections(tc_2, nullptr); 718 do_tcp_connections(tc_2, nullptr);
@@ -704,7 +721,7 @@ START_TEST(test_tcp_connection)
704 ck_assert_msg(tcp_connection_to_online_tcp_relays(tc_1, 0) == 1, "Wrong number of connected relays"); 721 ck_assert_msg(tcp_connection_to_online_tcp_relays(tc_1, 0) == 1, "Wrong number of connected relays");
705 ck_assert_msg(kill_tcp_connection_to(tc_1, 0) == 0, "could not kill connection to\n"); 722 ck_assert_msg(kill_tcp_connection_to(tc_1, 0) == 0, "could not kill connection to\n");
706 723
707 do_TCP_server_delay(tcp_s, 50); 724 do_TCP_server_delay(tcp_s, mono_time, 50);
708 725
709 do_tcp_connections(tc_1, nullptr); 726 do_tcp_connections(tc_1, nullptr);
710 do_tcp_connections(tc_2, nullptr); 727 do_tcp_connections(tc_2, nullptr);
@@ -715,6 +732,8 @@ START_TEST(test_tcp_connection)
715 kill_TCP_server(tcp_s); 732 kill_TCP_server(tcp_s);
716 kill_tcp_connections(tc_1); 733 kill_tcp_connections(tc_1);
717 kill_tcp_connections(tc_2); 734 kill_tcp_connections(tc_2);
735
736 mono_time_free(mono_time);
718} 737}
719END_TEST 738END_TEST
720 739
@@ -741,10 +760,11 @@ static int tcp_oobdata_callback(void *object, const uint8_t *public_key, unsigne
741 760
742START_TEST(test_tcp_connection2) 761START_TEST(test_tcp_connection2)
743{ 762{
763 Mono_Time *mono_time = mono_time_new();
764
744 tcp_oobdata_callback_called = 0; 765 tcp_oobdata_callback_called = 0;
745 tcp_data_callback_called = 0; 766 tcp_data_callback_called = 0;
746 767
747 unix_time_update();
748 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; 768 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
749 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; 769 uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
750 crypto_new_keypair(self_public_key, self_secret_key); 770 crypto_new_keypair(self_public_key, self_secret_key);
@@ -754,11 +774,11 @@ START_TEST(test_tcp_connection2)
754 TCP_Proxy_Info proxy_info; 774 TCP_Proxy_Info proxy_info;
755 proxy_info.proxy_type = TCP_PROXY_NONE; 775 proxy_info.proxy_type = TCP_PROXY_NONE;
756 crypto_new_keypair(self_public_key, self_secret_key); 776 crypto_new_keypair(self_public_key, self_secret_key);
757 TCP_Connections *tc_1 = new_tcp_connections(self_secret_key, &proxy_info); 777 TCP_Connections *tc_1 = new_tcp_connections(mono_time, self_secret_key, &proxy_info);
758 ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_1), self_public_key) == 0, "Wrong public key"); 778 ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_1), self_public_key) == 0, "Wrong public key");
759 779
760 crypto_new_keypair(self_public_key, self_secret_key); 780 crypto_new_keypair(self_public_key, self_secret_key);
761 TCP_Connections *tc_2 = new_tcp_connections(self_secret_key, &proxy_info); 781 TCP_Connections *tc_2 = new_tcp_connections(mono_time, self_secret_key, &proxy_info);
762 ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_2), self_public_key) == 0, "Wrong public key"); 782 ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_2), self_public_key) == 0, "Wrong public key");
763 783
764 IP_Port ip_port_tcp_s; 784 IP_Port ip_port_tcp_s;
@@ -774,17 +794,17 @@ START_TEST(test_tcp_connection2)
774 ck_assert_msg(add_tcp_relay_global(tc_2, ip_port_tcp_s, tcp_server_public_key(tcp_s)) == 0, 794 ck_assert_msg(add_tcp_relay_global(tc_2, ip_port_tcp_s, tcp_server_public_key(tcp_s)) == 0,
775 "Could not add global relay"); 795 "Could not add global relay");
776 796
777 do_TCP_server_delay(tcp_s, 50); 797 do_TCP_server_delay(tcp_s, mono_time, 50);
778 798
779 do_tcp_connections(tc_1, nullptr); 799 do_tcp_connections(tc_1, nullptr);
780 do_tcp_connections(tc_2, nullptr); 800 do_tcp_connections(tc_2, nullptr);
781 801
782 do_TCP_server_delay(tcp_s, 50); 802 do_TCP_server_delay(tcp_s, mono_time, 50);
783 803
784 do_tcp_connections(tc_1, nullptr); 804 do_tcp_connections(tc_1, nullptr);
785 do_tcp_connections(tc_2, nullptr); 805 do_tcp_connections(tc_2, nullptr);
786 806
787 do_TCP_server_delay(tcp_s, 50); 807 do_TCP_server_delay(tcp_s, mono_time, 50);
788 808
789 do_tcp_connections(tc_1, nullptr); 809 do_tcp_connections(tc_1, nullptr);
790 do_tcp_connections(tc_2, nullptr); 810 do_tcp_connections(tc_2, nullptr);
@@ -794,14 +814,14 @@ START_TEST(test_tcp_connection2)
794 set_oob_packet_tcp_connection_callback(tc_2, &tcp_oobdata_callback, tc_2); 814 set_oob_packet_tcp_connection_callback(tc_2, &tcp_oobdata_callback, tc_2);
795 set_packet_tcp_connection_callback(tc_1, &tcp_data_callback, (void *) 120397); 815 set_packet_tcp_connection_callback(tc_1, &tcp_data_callback, (void *) 120397);
796 816
797 do_TCP_server_delay(tcp_s, 50); 817 do_TCP_server_delay(tcp_s, mono_time, 50);
798 818
799 do_tcp_connections(tc_1, nullptr); 819 do_tcp_connections(tc_1, nullptr);
800 do_tcp_connections(tc_2, nullptr); 820 do_tcp_connections(tc_2, nullptr);
801 821
802 ck_assert_msg(tcp_oobdata_callback_called, "could not recv packet."); 822 ck_assert_msg(tcp_oobdata_callback_called, "could not recv packet.");
803 823
804 do_TCP_server_delay(tcp_s, 50); 824 do_TCP_server_delay(tcp_s, mono_time, 50);
805 825
806 do_tcp_connections(tc_1, nullptr); 826 do_tcp_connections(tc_1, nullptr);
807 do_tcp_connections(tc_2, nullptr); 827 do_tcp_connections(tc_2, nullptr);
@@ -812,6 +832,8 @@ START_TEST(test_tcp_connection2)
812 kill_TCP_server(tcp_s); 832 kill_TCP_server(tcp_s);
813 kill_tcp_connections(tc_1); 833 kill_tcp_connections(tc_1);
814 kill_tcp_connections(tc_2); 834 kill_tcp_connections(tc_2);
835
836 mono_time_free(mono_time);
815} 837}
816END_TEST 838END_TEST
817 839
diff --git a/auto_tests/dht_test.c b/auto_tests/dht_test.c
index 2f273727..009c0bbd 100644
--- a/auto_tests/dht_test.c
+++ b/auto_tests/dht_test.c
@@ -32,39 +32,39 @@ static inline IP get_loopback()
32 return ip; 32 return ip;
33} 33}
34 34
35static void mark_bad(IPPTsPng *ipptp) 35static void mark_bad(const Mono_Time *mono_time, IPPTsPng *ipptp)
36{ 36{
37 ipptp->timestamp = unix_time() - 2 * BAD_NODE_TIMEOUT; 37 ipptp->timestamp = mono_time_get(mono_time) - 2 * BAD_NODE_TIMEOUT;
38 ipptp->hardening.routes_requests_ok = 0; 38 ipptp->hardening.routes_requests_ok = 0;
39 ipptp->hardening.send_nodes_ok = 0; 39 ipptp->hardening.send_nodes_ok = 0;
40 ipptp->hardening.testing_requests = 0; 40 ipptp->hardening.testing_requests = 0;
41} 41}
42 42
43static void mark_possible_bad(IPPTsPng *ipptp) 43static void mark_possible_bad(const Mono_Time *mono_time, IPPTsPng *ipptp)
44{ 44{
45 ipptp->timestamp = unix_time(); 45 ipptp->timestamp = mono_time_get(mono_time);
46 ipptp->hardening.routes_requests_ok = 0; 46 ipptp->hardening.routes_requests_ok = 0;
47 ipptp->hardening.send_nodes_ok = 0; 47 ipptp->hardening.send_nodes_ok = 0;
48 ipptp->hardening.testing_requests = 0; 48 ipptp->hardening.testing_requests = 0;
49} 49}
50 50
51static void mark_good(IPPTsPng *ipptp) 51static void mark_good(const Mono_Time *mono_time, IPPTsPng *ipptp)
52{ 52{
53 ipptp->timestamp = unix_time(); 53 ipptp->timestamp = mono_time_get(mono_time);
54 ipptp->hardening.routes_requests_ok = (HARDENING_ALL_OK >> 0) & 1; 54 ipptp->hardening.routes_requests_ok = (HARDENING_ALL_OK >> 0) & 1;
55 ipptp->hardening.send_nodes_ok = (HARDENING_ALL_OK >> 1) & 1; 55 ipptp->hardening.send_nodes_ok = (HARDENING_ALL_OK >> 1) & 1;
56 ipptp->hardening.testing_requests = (HARDENING_ALL_OK >> 2) & 1; 56 ipptp->hardening.testing_requests = (HARDENING_ALL_OK >> 2) & 1;
57} 57}
58 58
59static void mark_all_good(Client_data *list, uint32_t length, uint8_t ipv6) 59static void mark_all_good(const Mono_Time *mono_time, Client_data *list, uint32_t length, uint8_t ipv6)
60{ 60{
61 uint32_t i; 61 uint32_t i;
62 62
63 for (i = 0; i < length; ++i) { 63 for (i = 0; i < length; ++i) {
64 if (ipv6) { 64 if (ipv6) {
65 mark_good(&list[i].assoc6); 65 mark_good(mono_time, &list[i].assoc6);
66 } else { 66 } else {
67 mark_good(&list[i].assoc4); 67 mark_good(mono_time, &list[i].assoc4);
68 } 68 }
69 } 69 }
70} 70}
@@ -183,7 +183,7 @@ static void test_addto_lists_bad(DHT *dht,
183 uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0; 183 uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0;
184 184
185 random_bytes(public_key, sizeof(public_key)); 185 random_bytes(public_key, sizeof(public_key));
186 mark_all_good(list, length, ipv6); 186 mark_all_good(dht->mono_time, list, length, ipv6);
187 187
188 test1 = random_u32() % (length / 3); 188 test1 = random_u32() % (length / 3);
189 test2 = random_u32() % (length / 3) + length / 3; 189 test2 = random_u32() % (length / 3) + length / 3;
@@ -196,13 +196,13 @@ static void test_addto_lists_bad(DHT *dht,
196 196
197 // mark nodes as "bad" 197 // mark nodes as "bad"
198 if (ipv6) { 198 if (ipv6) {
199 mark_bad(&list[test1].assoc6); 199 mark_bad(dht->mono_time, &list[test1].assoc6);
200 mark_bad(&list[test2].assoc6); 200 mark_bad(dht->mono_time, &list[test2].assoc6);
201 mark_bad(&list[test3].assoc6); 201 mark_bad(dht->mono_time, &list[test3].assoc6);
202 } else { 202 } else {
203 mark_bad(&list[test1].assoc4); 203 mark_bad(dht->mono_time, &list[test1].assoc4);
204 mark_bad(&list[test2].assoc4); 204 mark_bad(dht->mono_time, &list[test2].assoc4);
205 mark_bad(&list[test3].assoc4); 205 mark_bad(dht->mono_time, &list[test3].assoc4);
206 } 206 }
207 207
208 ip_port->port += 1; 208 ip_port->port += 1;
@@ -227,7 +227,7 @@ static void test_addto_lists_possible_bad(DHT *dht,
227 uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0; 227 uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0;
228 228
229 random_bytes(public_key, sizeof(public_key)); 229 random_bytes(public_key, sizeof(public_key));
230 mark_all_good(list, length, ipv6); 230 mark_all_good(dht->mono_time, list, length, ipv6);
231 231
232 test1 = random_u32() % (length / 3); 232 test1 = random_u32() % (length / 3);
233 test2 = random_u32() % (length / 3) + length / 3; 233 test2 = random_u32() % (length / 3) + length / 3;
@@ -240,13 +240,13 @@ static void test_addto_lists_possible_bad(DHT *dht,
240 240
241 // mark nodes as "possibly bad" 241 // mark nodes as "possibly bad"
242 if (ipv6) { 242 if (ipv6) {
243 mark_possible_bad(&list[test1].assoc6); 243 mark_possible_bad(dht->mono_time, &list[test1].assoc6);
244 mark_possible_bad(&list[test2].assoc6); 244 mark_possible_bad(dht->mono_time, &list[test2].assoc6);
245 mark_possible_bad(&list[test3].assoc6); 245 mark_possible_bad(dht->mono_time, &list[test3].assoc6);
246 } else { 246 } else {
247 mark_possible_bad(&list[test1].assoc4); 247 mark_possible_bad(dht->mono_time, &list[test1].assoc4);
248 mark_possible_bad(&list[test2].assoc4); 248 mark_possible_bad(dht->mono_time, &list[test2].assoc4);
249 mark_possible_bad(&list[test3].assoc4); 249 mark_possible_bad(dht->mono_time, &list[test3].assoc4);
250 } 250 }
251 251
252 ip_port->port += 1; 252 ip_port->port += 1;
@@ -288,7 +288,7 @@ static void test_addto_lists_good(DHT *dht,
288 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; 288 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
289 uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0; 289 uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0;
290 290
291 mark_all_good(list, length, ipv6); 291 mark_all_good(dht->mono_time, list, length, ipv6);
292 292
293 // check "good" client id replacement 293 // check "good" client id replacement
294 do { 294 do {
@@ -319,10 +319,13 @@ static void test_addto_lists(IP ip)
319 uint32_t index = 1; 319 uint32_t index = 1;
320 logger_callback_log(log, (logger_cb *)print_debug_log, nullptr, &index); 320 logger_callback_log(log, (logger_cb *)print_debug_log, nullptr, &index);
321 321
322 Mono_Time *mono_time = mono_time_new();
323 ck_assert_msg(mono_time != nullptr, "Failed to create Mono_Time");
324
322 Networking_Core *net = new_networking(log, ip, TOX_PORT_DEFAULT); 325 Networking_Core *net = new_networking(log, ip, TOX_PORT_DEFAULT);
323 ck_assert_msg(net != nullptr, "Failed to create Networking_Core"); 326 ck_assert_msg(net != nullptr, "Failed to create Networking_Core");
324 327
325 DHT *dht = new_dht(log, net, true); 328 DHT *dht = new_dht(log, mono_time, net, true);
326 ck_assert_msg(dht != nullptr, "Failed to create DHT"); 329 ck_assert_msg(dht != nullptr, "Failed to create DHT");
327 330
328 IP_Port ip_port; 331 IP_Port ip_port;
@@ -451,6 +454,7 @@ static void test_list_main(void)
451{ 454{
452 DHT *dhts[NUM_DHT]; 455 DHT *dhts[NUM_DHT];
453 Logger *logs[NUM_DHT]; 456 Logger *logs[NUM_DHT];
457 Mono_Time *mono_times[NUM_DHT];
454 uint32_t index[NUM_DHT]; 458 uint32_t index[NUM_DHT];
455 459
456 uint8_t cmp_list1[NUM_DHT][MAX_FRIEND_CLIENTS][CRYPTO_PUBLIC_KEY_SIZE + 1]; 460 uint8_t cmp_list1[NUM_DHT][MAX_FRIEND_CLIENTS][CRYPTO_PUBLIC_KEY_SIZE + 1];
@@ -466,7 +470,9 @@ static void test_list_main(void)
466 index[i] = i + 1; 470 index[i] = i + 1;
467 logger_callback_log(logs[i], (logger_cb *)print_debug_log, nullptr, &index[i]); 471 logger_callback_log(logs[i], (logger_cb *)print_debug_log, nullptr, &index[i]);
468 472
469 dhts[i] = new_dht(logs[i], new_networking(logs[i], ip, DHT_DEFAULT_PORT + i), true); 473 mono_times[i] = mono_time_new();
474
475 dhts[i] = new_dht(logs[i], mono_times[i], new_networking(logs[i], ip, DHT_DEFAULT_PORT + i), true);
470 ck_assert_msg(dhts[i] != nullptr, "Failed to create dht instances %u", i); 476 ck_assert_msg(dhts[i] != nullptr, "Failed to create dht instances %u", i);
471 ck_assert_msg(net_port(dhts[i]->net) != DHT_DEFAULT_PORT + i, 477 ck_assert_msg(net_port(dhts[i]->net) != DHT_DEFAULT_PORT + i,
472 "Bound to wrong port: %d", net_port(dhts[i]->net)); 478 "Bound to wrong port: %d", net_port(dhts[i]->net));
@@ -573,6 +579,7 @@ static void test_list_main(void)
573 Networking_Core *n = dhts[i]->net; 579 Networking_Core *n = dhts[i]->net;
574 kill_dht(dhts[i]); 580 kill_dht(dhts[i]);
575 kill_networking(n); 581 kill_networking(n);
582 mono_time_free(mono_times[i]);
576 logger_kill(logs[i]); 583 logger_kill(logs[i]);
577 } 584 }
578} 585}
@@ -598,10 +605,9 @@ static void test_DHT_test(void)
598 uint32_t to_comp = 8394782; 605 uint32_t to_comp = 8394782;
599 DHT *dhts[NUM_DHT]; 606 DHT *dhts[NUM_DHT];
600 Logger *logs[NUM_DHT]; 607 Logger *logs[NUM_DHT];
608 Mono_Time *mono_times[NUM_DHT];
601 uint32_t index[NUM_DHT]; 609 uint32_t index[NUM_DHT];
602 610
603 unix_time_update();
604
605 uint32_t i, j; 611 uint32_t i, j;
606 612
607 for (i = 0; i < NUM_DHT; ++i) { 613 for (i = 0; i < NUM_DHT; ++i) {
@@ -612,7 +618,9 @@ static void test_DHT_test(void)
612 index[i] = i + 1; 618 index[i] = i + 1;
613 logger_callback_log(logs[i], (logger_cb *)print_debug_log, nullptr, &index[i]); 619 logger_callback_log(logs[i], (logger_cb *)print_debug_log, nullptr, &index[i]);
614 620
615 dhts[i] = new_dht(logs[i], new_networking(logs[i], ip, DHT_DEFAULT_PORT + i), true); 621 mono_times[i] = mono_time_new();
622
623 dhts[i] = new_dht(logs[i], mono_times[i], new_networking(logs[i], ip, DHT_DEFAULT_PORT + i), true);
616 ck_assert_msg(dhts[i] != nullptr, "Failed to create dht instances %u", i); 624 ck_assert_msg(dhts[i] != nullptr, "Failed to create dht instances %u", i);
617 ck_assert_msg(net_port(dhts[i]->net) != DHT_DEFAULT_PORT + i, "Bound to wrong port"); 625 ck_assert_msg(net_port(dhts[i]->net) != DHT_DEFAULT_PORT + i, "Bound to wrong port");
618 } 626 }
@@ -663,7 +671,7 @@ loop_top:
663 } 671 }
664 672
665 for (i = 0; i < NUM_DHT; ++i) { 673 for (i = 0; i < NUM_DHT; ++i) {
666 unix_time_update(); 674 mono_time_update(mono_times[i]);
667 networking_poll(dhts[i]->net, nullptr); 675 networking_poll(dhts[i]->net, nullptr);
668 do_dht(dhts[i]); 676 do_dht(dhts[i]);
669 } 677 }
@@ -675,6 +683,7 @@ loop_top:
675 Networking_Core *n = dhts[i]->net; 683 Networking_Core *n = dhts[i]->net;
676 kill_dht(dhts[i]); 684 kill_dht(dhts[i]);
677 kill_networking(n); 685 kill_networking(n);
686 mono_time_free(mono_times[i]);
678 logger_kill(logs[i]); 687 logger_kill(logs[i]);
679 } 688 }
680} 689}
@@ -792,8 +801,6 @@ int main(void)
792{ 801{
793 setvbuf(stdout, nullptr, _IONBF, 0); 802 setvbuf(stdout, nullptr, _IONBF, 0);
794 803
795 unix_time_update();
796
797 test_dht_create_packet(); 804 test_dht_create_packet();
798 test_dht_node_packing(); 805 test_dht_node_packing();
799 806
diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c
index b8fbbc1f..dd644e50 100644
--- a/auto_tests/messenger_test.c
+++ b/auto_tests/messenger_test.c
@@ -341,13 +341,15 @@ int main(void)
341 good_id = hex_string_to_bin(good_id_str); 341 good_id = hex_string_to_bin(good_id_str);
342 bad_id = hex_string_to_bin(bad_id_str); 342 bad_id = hex_string_to_bin(bad_id_str);
343 343
344 Mono_Time *mono_time = mono_time_new();
345
344 /* IPv6 status from global define */ 346 /* IPv6 status from global define */
345 Messenger_Options options = {0}; 347 Messenger_Options options = {0};
346 options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; 348 options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
347 options.port_range[0] = 41234; 349 options.port_range[0] = 41234;
348 options.port_range[1] = 44234; 350 options.port_range[1] = 44234;
349 options.log_callback = (logger_cb *)print_debug_log; 351 options.log_callback = (logger_cb *)print_debug_log;
350 m = new_messenger(&options, nullptr); 352 m = new_messenger(mono_time, &options, nullptr);
351 353
352 /* setup a default friend and friendnum */ 354 /* setup a default friend and friendnum */
353 if (m_addfriend_norequest(m, friend_id) < 0) { 355 if (m_addfriend_norequest(m, friend_id) < 0) {
@@ -375,6 +377,7 @@ int main(void)
375 free(bad_id); 377 free(bad_id);
376 378
377 kill_messenger(m); 379 kill_messenger(m);
380 mono_time_free(mono_time);
378 381
379 return number_failed; 382 return number_failed;
380} 383}
diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c
index 0a9a0577..a11fb807 100644
--- a/auto_tests/onion_test.c
+++ b/auto_tests/onion_test.c
@@ -31,7 +31,7 @@ static inline IP get_loopback()
31} 31}
32static void do_onion(Onion *onion) 32static void do_onion(Onion *onion)
33{ 33{
34 unix_time_update(); 34 mono_time_update(onion->mono_time);
35 35
36 networking_poll(onion->net, nullptr); 36 networking_poll(onion->net, nullptr);
37 do_dht(onion->dht); 37 do_dht(onion->dht);
@@ -152,7 +152,7 @@ static int handle_test_4(void *object, IP_Port source, const uint8_t *packet, ui
152 return 0; 152 return 0;
153} 153}
154 154
155START_TEST(test_basic) 155static void test_basic(void)
156{ 156{
157 uint32_t index[] = { 1, 2, 3 }; 157 uint32_t index[] = { 1, 2, 3 };
158 Logger *log1 = logger_new(); 158 Logger *log1 = logger_new();
@@ -160,9 +160,12 @@ START_TEST(test_basic)
160 Logger *log2 = logger_new(); 160 Logger *log2 = logger_new();
161 logger_callback_log(log2, (logger_cb *)print_debug_log, nullptr, &index[1]); 161 logger_callback_log(log2, (logger_cb *)print_debug_log, nullptr, &index[1]);
162 162
163 Mono_Time *mono_time1 = mono_time_new();
164 Mono_Time *mono_time2 = mono_time_new();
165
163 IP ip = get_loopback(); 166 IP ip = get_loopback();
164 Onion *onion1 = new_onion(new_dht(log1, new_networking(log1, ip, 36567), true)); 167 Onion *onion1 = new_onion(mono_time1, new_dht(log1, mono_time1, new_networking(log1, ip, 36567), true));
165 Onion *onion2 = new_onion(new_dht(log2, new_networking(log2, ip, 36568), true)); 168 Onion *onion2 = new_onion(mono_time2, new_dht(log2, mono_time2, new_networking(log2, ip, 36568), true));
166 ck_assert_msg((onion1 != nullptr) && (onion2 != nullptr), "Onion failed initializing."); 169 ck_assert_msg((onion1 != nullptr) && (onion2 != nullptr), "Onion failed initializing.");
167 networking_registerhandler(onion2->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_test_1, onion2); 170 networking_registerhandler(onion2->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_test_1, onion2);
168 171
@@ -202,8 +205,8 @@ START_TEST(test_basic)
202 do_onion(onion2); 205 do_onion(onion2);
203 } 206 }
204 207
205 Onion_Announce *onion1_a = new_onion_announce(onion1->dht); 208 Onion_Announce *onion1_a = new_onion_announce(mono_time1, onion1->dht);
206 Onion_Announce *onion2_a = new_onion_announce(onion2->dht); 209 Onion_Announce *onion2_a = new_onion_announce(mono_time2, onion2->dht);
207 networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1); 210 networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1);
208 ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing."); 211 ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing.");
209 uint8_t zeroes[64] = {0}; 212 uint8_t zeroes[64] = {0};
@@ -229,7 +232,7 @@ START_TEST(test_basic)
229 random_bytes(sb_data, sizeof(sb_data)); 232 random_bytes(sb_data, sizeof(sb_data));
230 memcpy(&s, sb_data, sizeof(uint64_t)); 233 memcpy(&s, sb_data, sizeof(uint64_t));
231 memcpy(onion_announce_entry_public_key(onion2_a, 1), dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE); 234 memcpy(onion_announce_entry_public_key(onion2_a, 1), dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE);
232 onion_announce_entry_set_time(onion2_a, 1, unix_time()); 235 onion_announce_entry_set_time(onion2_a, 1, mono_time_get(mono_time2));
233 networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); 236 networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1);
234 send_announce_request(onion1->net, &path, nodes[3], 237 send_announce_request(onion1->net, &path, nodes[3],
235 dht_get_self_public_key(onion1->dht), 238 dht_get_self_public_key(onion1->dht),
@@ -250,7 +253,9 @@ START_TEST(test_basic)
250 Logger *log3 = logger_new(); 253 Logger *log3 = logger_new();
251 logger_callback_log(log3, (logger_cb *)print_debug_log, nullptr, &index[2]); 254 logger_callback_log(log3, (logger_cb *)print_debug_log, nullptr, &index[2]);
252 255
253 Onion *onion3 = new_onion(new_dht(log3, new_networking(log3, ip, 36569), true)); 256 Mono_Time *mono_time3 = mono_time_new();
257
258 Onion *onion3 = new_onion(mono_time3, new_dht(log3, mono_time3, new_networking(log3, ip, 36569), true));
254 ck_assert_msg((onion3 != nullptr), "Onion failed initializing."); 259 ck_assert_msg((onion3 != nullptr), "Onion failed initializing.");
255 260
256 random_nonce(nonce); 261 random_nonce(nonce);
@@ -278,6 +283,7 @@ START_TEST(test_basic)
278 kill_onion(onion); 283 kill_onion(onion);
279 kill_dht(dht); 284 kill_dht(dht);
280 kill_networking(net); 285 kill_networking(net);
286 mono_time_free(mono_time3);
281 logger_kill(log3); 287 logger_kill(log3);
282 } 288 }
283 289
@@ -289,6 +295,7 @@ START_TEST(test_basic)
289 kill_onion(onion); 295 kill_onion(onion);
290 kill_dht(dht); 296 kill_dht(dht);
291 kill_networking(net); 297 kill_networking(net);
298 mono_time_free(mono_time2);
292 logger_kill(log2); 299 logger_kill(log2);
293 } 300 }
294 301
@@ -300,13 +307,14 @@ START_TEST(test_basic)
300 kill_onion(onion); 307 kill_onion(onion);
301 kill_dht(dht); 308 kill_dht(dht);
302 kill_networking(net); 309 kill_networking(net);
310 mono_time_free(mono_time1);
303 logger_kill(log1); 311 logger_kill(log1);
304 } 312 }
305} 313}
306END_TEST
307 314
308typedef struct { 315typedef struct {
309 Logger *log; 316 Logger *log;
317 Mono_Time *mono_time;
310 Onion *onion; 318 Onion *onion;
311 Onion_Announce *onion_a; 319 Onion_Announce *onion_a;
312 Onion_Client *onion_c; 320 Onion_Client *onion_c;
@@ -329,56 +337,67 @@ static Onions *new_onions(uint16_t port, uint32_t *index)
329 return nullptr; 337 return nullptr;
330 } 338 }
331 339
332 unix_time_update();
333
334 logger_callback_log(on->log, (logger_cb *)print_debug_log, nullptr, index); 340 logger_callback_log(on->log, (logger_cb *)print_debug_log, nullptr, index);
335 341
342 on->mono_time = mono_time_new();
343
344 if (!on->mono_time) {
345 logger_kill(on->log);
346 free(on);
347 return nullptr;
348 }
349
336 Networking_Core *net = new_networking(on->log, ip, port); 350 Networking_Core *net = new_networking(on->log, ip, port);
337 351
338 if (!net) { 352 if (!net) {
353 mono_time_free(on->mono_time);
339 logger_kill(on->log); 354 logger_kill(on->log);
340 free(on); 355 free(on);
341 return nullptr; 356 return nullptr;
342 } 357 }
343 358
344 DHT *dht = new_dht(on->log, net, true); 359 DHT *dht = new_dht(on->log, on->mono_time, net, true);
345 360
346 if (!dht) { 361 if (!dht) {
347 kill_networking(net); 362 kill_networking(net);
363 mono_time_free(on->mono_time);
348 logger_kill(on->log); 364 logger_kill(on->log);
349 free(on); 365 free(on);
350 return nullptr; 366 return nullptr;
351 } 367 }
352 368
353 on->onion = new_onion(dht); 369 on->onion = new_onion(on->mono_time, dht);
354 370
355 if (!on->onion) { 371 if (!on->onion) {
356 kill_dht(dht); 372 kill_dht(dht);
357 kill_networking(net); 373 kill_networking(net);
374 mono_time_free(on->mono_time);
358 logger_kill(on->log); 375 logger_kill(on->log);
359 free(on); 376 free(on);
360 return nullptr; 377 return nullptr;
361 } 378 }
362 379
363 on->onion_a = new_onion_announce(dht); 380 on->onion_a = new_onion_announce(on->mono_time, dht);
364 381
365 if (!on->onion_a) { 382 if (!on->onion_a) {
366 kill_onion(on->onion); 383 kill_onion(on->onion);
367 kill_dht(dht); 384 kill_dht(dht);
368 kill_networking(net); 385 kill_networking(net);
386 mono_time_free(on->mono_time);
369 logger_kill(on->log); 387 logger_kill(on->log);
370 free(on); 388 free(on);
371 return nullptr; 389 return nullptr;
372 } 390 }
373 391
374 TCP_Proxy_Info inf = {{{{0}}}}; 392 TCP_Proxy_Info inf = {{{{0}}}};
375 on->onion_c = new_onion_client(new_net_crypto(on->log, dht, &inf)); 393 on->onion_c = new_onion_client(on->mono_time, new_net_crypto(on->log, on->mono_time, dht, &inf));
376 394
377 if (!on->onion_c) { 395 if (!on->onion_c) {
378 kill_onion_announce(on->onion_a); 396 kill_onion_announce(on->onion_a);
379 kill_onion(on->onion); 397 kill_onion(on->onion);
380 kill_dht(dht); 398 kill_dht(dht);
381 kill_networking(net); 399 kill_networking(net);
400 mono_time_free(on->mono_time);
382 logger_kill(on->log); 401 logger_kill(on->log);
383 free(on); 402 free(on);
384 return nullptr; 403 return nullptr;
@@ -389,7 +408,7 @@ static Onions *new_onions(uint16_t port, uint32_t *index)
389 408
390static void do_onions(Onions *on) 409static void do_onions(Onions *on)
391{ 410{
392 unix_time_update(); 411 mono_time_update(on->mono_time);
393 412
394 networking_poll(on->onion->net, nullptr); 413 networking_poll(on->onion->net, nullptr);
395 do_dht(on->onion->dht); 414 do_dht(on->onion->dht);
@@ -407,6 +426,7 @@ static void kill_onions(Onions *on)
407 kill_net_crypto(c); 426 kill_net_crypto(c);
408 kill_dht(dht); 427 kill_dht(dht);
409 kill_networking(net); 428 kill_networking(net);
429 mono_time_free(on->mono_time);
410 logger_kill(on->log); 430 logger_kill(on->log);
411 free(on); 431 free(on);
412} 432}
@@ -468,7 +488,7 @@ static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_pub
468 } 488 }
469} 489}
470 490
471START_TEST(test_announce) 491static void test_announce(void)
472{ 492{
473 uint32_t i, j; 493 uint32_t i, j;
474 uint32_t index[NUM_ONIONS]; 494 uint32_t index[NUM_ONIONS];
@@ -553,29 +573,13 @@ START_TEST(test_announce)
553 kill_onions(onions[i]); 573 kill_onions(onions[i]);
554 } 574 }
555} 575}
556END_TEST
557
558static Suite *onion_suite(void)
559{
560 Suite *s = suite_create("Onion");
561
562 DEFTESTCASE_SLOW(basic, 5);
563 DEFTESTCASE_SLOW(announce, 70);
564 return s;
565}
566 576
567int main(void) 577int main(void)
568{ 578{
569 setvbuf(stdout, nullptr, _IONBF, 0); 579 setvbuf(stdout, nullptr, _IONBF, 0);
570 580
571 Suite *onion = onion_suite(); 581 test_basic();
572 SRunner *test_runner = srunner_create(onion); 582 test_announce();
573
574 int number_failed = 0;
575 srunner_run_all(test_runner, CK_NORMAL);
576 number_failed = srunner_ntests_failed(test_runner);
577 583
578 srunner_free(test_runner); 584 return 0;
579
580 return number_failed;
581} 585}
diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c
index fc1bba47..6af042ac 100644
--- a/other/DHT_bootstrap.c
+++ b/other/DHT_bootstrap.c
@@ -115,12 +115,11 @@ int main(int argc, char *argv[])
115 IP ip; 115 IP ip;
116 ip_init(&ip, ipv6enabled); 116 ip_init(&ip, ipv6enabled);
117 117
118 unix_time_update();
119
120 Logger *logger = logger_new(); 118 Logger *logger = logger_new();
121 DHT *dht = new_dht(logger, new_networking(logger, ip, PORT), true); 119 Mono_Time *mono_time = mono_time_new();
122 Onion *onion = new_onion(dht); 120 DHT *dht = new_dht(logger, mono_time, new_networking(logger, ip, PORT), true);
123 Onion_Announce *onion_a = new_onion_announce(dht); 121 Onion *onion = new_onion(mono_time, dht);
122 Onion_Announce *onion_a = new_onion_announce(mono_time, dht);
124 123
125#ifdef DHT_NODE_EXTRA_PACKETS 124#ifdef DHT_NODE_EXTRA_PACKETS
126 bootstrap_set_callbacks(dht_get_net(dht), DHT_VERSION_NUMBER, DHT_MOTD, sizeof(DHT_MOTD)); 125 bootstrap_set_callbacks(dht_get_net(dht), DHT_VERSION_NUMBER, DHT_MOTD, sizeof(DHT_MOTD));
@@ -188,7 +187,7 @@ int main(int argc, char *argv[])
188 lan_discovery_init(dht); 187 lan_discovery_init(dht);
189 188
190 while (1) { 189 while (1) {
191 unix_time_update(); 190 mono_time_update(mono_time);
192 191
193 if (is_waiting_for_dht_connection && dht_isconnected(dht)) { 192 if (is_waiting_for_dht_connection && dht_isconnected(dht)) {
194 printf("Connected to other bootstrap node successfully.\n"); 193 printf("Connected to other bootstrap node successfully.\n");
@@ -197,13 +196,13 @@ int main(int argc, char *argv[])
197 196
198 do_dht(dht); 197 do_dht(dht);
199 198
200 if (is_timeout(last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) { 199 if (mono_time_is_timeout(mono_time, last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) {
201 lan_discovery_send(net_htons(PORT), dht); 200 lan_discovery_send(net_htons(PORT), dht);
202 last_LANdiscovery = unix_time(); 201 last_LANdiscovery = mono_time_get(mono_time);
203 } 202 }
204 203
205#ifdef TCP_RELAY_ENABLED 204#ifdef TCP_RELAY_ENABLED
206 do_TCP_server(tcp_s); 205 do_TCP_server(tcp_s, mono_time);
207#endif 206#endif
208 networking_poll(dht_get_net(dht), nullptr); 207 networking_poll(dht_get_net(dht), nullptr);
209 208
diff --git a/other/astyle/format-source b/other/astyle/format-source
index 5b560622..5e139d89 100755
--- a/other/astyle/format-source
+++ b/other/astyle/format-source
@@ -36,11 +36,13 @@ apidsl_curl() {
36 36
37# Check if apidsl generated sources are up to date. 37# Check if apidsl generated sources are up to date.
38$APIDSL toxcore/crypto_core.api.h > toxcore/crypto_core.h & 38$APIDSL toxcore/crypto_core.api.h > toxcore/crypto_core.h &
39$APIDSL toxcore/ping.api.h > toxcore/ping.h &
40$APIDSL toxcore/ping_array.api.h > toxcore/ping_array.h &
39$APIDSL toxcore/tox.api.h > toxcore/tox.h & 41$APIDSL toxcore/tox.api.h > toxcore/tox.h &
40$APIDSL toxav/toxav.api.h > toxav/toxav.h & 42$APIDSL toxav/toxav.api.h > toxav/toxav.h &
41$APIDSL toxencryptsave/toxencryptsave.api.h > toxencryptsave/toxencryptsave.h & 43$APIDSL toxencryptsave/toxencryptsave.api.h > toxencryptsave/toxencryptsave.h &
42 44
43wait; wait; wait; wait 45wait; wait; wait; wait; wait; wait
44 46
45if grep '<unresolved>' */*.h; then 47if grep '<unresolved>' */*.h; then
46 echo "error: some apidsl references were unresolved" 48 echo "error: some apidsl references were unresolved"
diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c
index d75018d8..807e1100 100644
--- a/other/bootstrap_daemon/src/tox-bootstrapd.c
+++ b/other/bootstrap_daemon/src/tox-bootstrapd.c
@@ -230,8 +230,6 @@ int main(int argc, char *argv[])
230 IP ip; 230 IP ip;
231 ip_init(&ip, enable_ipv6); 231 ip_init(&ip, enable_ipv6);
232 232
233 unix_time_update();
234
235 Logger *logger = logger_new(); 233 Logger *logger = logger_new();
236 234
237 Networking_Core *net = new_networking(logger, ip, port); 235 Networking_Core *net = new_networking(logger, ip, port);
@@ -255,19 +253,31 @@ int main(int argc, char *argv[])
255 } 253 }
256 } 254 }
257 255
258 DHT *dht = new_dht(logger, net, true); 256 Mono_Time *const mono_time = mono_time_new();
257
258 if (mono_time == nullptr) {
259 log_write(LOG_LEVEL_ERROR, "Couldn't initialize monotonic timer. Exiting.\n");
260 logger_kill(logger);
261 return 1;
262 }
263
264 mono_time_update(mono_time);
265
266 DHT *const dht = new_dht(logger, mono_time, net, true);
259 267
260 if (dht == nullptr) { 268 if (dht == nullptr) {
261 log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n"); 269 log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n");
270 mono_time_free(mono_time);
262 logger_kill(logger); 271 logger_kill(logger);
263 return 1; 272 return 1;
264 } 273 }
265 274
266 Onion *onion = new_onion(dht); 275 Onion *onion = new_onion(mono_time, dht);
267 Onion_Announce *onion_a = new_onion_announce(dht); 276 Onion_Announce *onion_a = new_onion_announce(mono_time, dht);
268 277
269 if (!(onion && onion_a)) { 278 if (!(onion && onion_a)) {
270 log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion. Exiting.\n"); 279 log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion. Exiting.\n");
280 mono_time_free(mono_time);
271 logger_kill(logger); 281 logger_kill(logger);
272 return 1; 282 return 1;
273 } 283 }
@@ -277,6 +287,7 @@ int main(int argc, char *argv[])
277 log_write(LOG_LEVEL_INFO, "Set MOTD successfully.\n"); 287 log_write(LOG_LEVEL_INFO, "Set MOTD successfully.\n");
278 } else { 288 } else {
279 log_write(LOG_LEVEL_ERROR, "Couldn't set MOTD: %s. Exiting.\n", motd); 289 log_write(LOG_LEVEL_ERROR, "Couldn't set MOTD: %s. Exiting.\n", motd);
290 mono_time_free(mono_time);
280 logger_kill(logger); 291 logger_kill(logger);
281 return 1; 292 return 1;
282 } 293 }
@@ -288,6 +299,7 @@ int main(int argc, char *argv[])
288 log_write(LOG_LEVEL_INFO, "Keys are managed successfully.\n"); 299 log_write(LOG_LEVEL_INFO, "Keys are managed successfully.\n");
289 } else { 300 } else {
290 log_write(LOG_LEVEL_ERROR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); 301 log_write(LOG_LEVEL_ERROR, "Couldn't read/write: %s. Exiting.\n", keys_file_path);
302 mono_time_free(mono_time);
291 logger_kill(logger); 303 logger_kill(logger);
292 return 1; 304 return 1;
293 } 305 }
@@ -299,6 +311,7 @@ int main(int argc, char *argv[])
299 if (enable_tcp_relay) { 311 if (enable_tcp_relay) {
300 if (tcp_relay_port_count == 0) { 312 if (tcp_relay_port_count == 0) {
301 log_write(LOG_LEVEL_ERROR, "No TCP relay ports read. Exiting.\n"); 313 log_write(LOG_LEVEL_ERROR, "No TCP relay ports read. Exiting.\n");
314 mono_time_free(mono_time);
302 logger_kill(logger); 315 logger_kill(logger);
303 return 1; 316 return 1;
304 } 317 }
@@ -312,6 +325,7 @@ int main(int argc, char *argv[])
312 log_write(LOG_LEVEL_INFO, "Initialized Tox TCP server successfully.\n"); 325 log_write(LOG_LEVEL_INFO, "Initialized Tox TCP server successfully.\n");
313 } else { 326 } else {
314 log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox TCP server. Exiting.\n"); 327 log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox TCP server. Exiting.\n");
328 mono_time_free(mono_time);
315 logger_kill(logger); 329 logger_kill(logger);
316 return 1; 330 return 1;
317 } 331 }
@@ -321,6 +335,7 @@ int main(int argc, char *argv[])
321 log_write(LOG_LEVEL_INFO, "List of bootstrap nodes read successfully.\n"); 335 log_write(LOG_LEVEL_INFO, "List of bootstrap nodes read successfully.\n");
322 } else { 336 } else {
323 log_write(LOG_LEVEL_ERROR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); 337 log_write(LOG_LEVEL_ERROR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path);
338 mono_time_free(mono_time);
324 logger_kill(logger); 339 logger_kill(logger);
325 return 1; 340 return 1;
326 } 341 }
@@ -338,17 +353,17 @@ int main(int argc, char *argv[])
338 } 353 }
339 354
340 while (1) { 355 while (1) {
341 unix_time_update(); 356 mono_time_update(mono_time);
342 357
343 do_dht(dht); 358 do_dht(dht);
344 359
345 if (enable_lan_discovery && is_timeout(last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) { 360 if (enable_lan_discovery && mono_time_is_timeout(mono_time, last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) {
346 lan_discovery_send(net_htons_port, dht); 361 lan_discovery_send(net_htons_port, dht);
347 last_LANdiscovery = unix_time(); 362 last_LANdiscovery = mono_time_get(mono_time);
348 } 363 }
349 364
350 if (enable_tcp_relay) { 365 if (enable_tcp_relay) {
351 do_TCP_server(tcp_server); 366 do_TCP_server(tcp_server, mono_time);
352 } 367 }
353 368
354 networking_poll(dht_get_net(dht), nullptr); 369 networking_poll(dht_get_net(dht), nullptr);
diff --git a/testing/DHT_test.c b/testing/DHT_test.c
index 1d01f0a2..5e5f6834 100644
--- a/testing/DHT_test.c
+++ b/testing/DHT_test.c
@@ -190,11 +190,11 @@ int main(int argc, char *argv[])
190 IP ip; 190 IP ip;
191 ip_init(&ip, ipv6enabled); 191 ip_init(&ip, ipv6enabled);
192 192
193 DHT *dht = new_dht(nullptr, new_networking(nullptr, ip, PORT), true); 193 Mono_Time *const mono_time = mono_time_new();
194 DHT *dht = new_dht(nullptr, mono_time, new_networking(nullptr, ip, PORT), true);
194 printf("OUR ID: "); 195 printf("OUR ID: ");
195 uint32_t i;
196 196
197 for (i = 0; i < 32; i++) { 197 for (uint32_t i = 0; i < 32; i++) {
198 const uint8_t *const self_public_key = dht_get_self_public_key(dht); 198 const uint8_t *const self_public_key = dht_get_self_public_key(dht);
199 199
200 if (self_public_key[i] < 16) { 200 if (self_public_key[i] < 16) {
@@ -238,7 +238,7 @@ int main(int argc, char *argv[])
238#endif 238#endif
239 239
240 while (1) { 240 while (1) {
241 unix_time_update(); 241 mono_time_update(mono_time);
242 242
243 do_dht(dht); 243 do_dht(dht);
244 244
diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c
index a5abfda0..880fc514 100644
--- a/testing/Messenger_test.c
+++ b/testing/Messenger_test.c
@@ -107,11 +107,16 @@ int main(int argc, char *argv[])
107 exit(0); 107 exit(0);
108 } 108 }
109 109
110 unix_time_update(); 110 Mono_Time *const mono_time = mono_time_new();
111
112 if (mono_time == nullptr) {
113 fputs("Failed to allocate monotonic timer datastructure\n", stderr);
114 exit(0);
115 }
111 116
112 Messenger_Options options = {0}; 117 Messenger_Options options = {0};
113 options.ipv6enabled = ipv6enabled; 118 options.ipv6enabled = ipv6enabled;
114 m = new_messenger(&options, nullptr); 119 m = new_messenger(mono_time, &options, nullptr);
115 120
116 if (!m) { 121 if (!m) {
117 fputs("Failed to allocate messenger datastructure\n", stderr); 122 fputs("Failed to allocate messenger datastructure\n", stderr);
@@ -180,7 +185,7 @@ int main(int argc, char *argv[])
180 perror("Initialization"); 185 perror("Initialization");
181 186
182 while (1) { 187 while (1) {
183 unix_time_update(); 188 mono_time_update(mono_time);
184 189
185 uint8_t name[128]; 190 uint8_t name[128];
186 const char *const filename = "Save.bak"; 191 const char *const filename = "Save.bak";
diff --git a/toxav/groupav.c b/toxav/groupav.c
index b10a7f8e..40338fb8 100644
--- a/toxav/groupav.c
+++ b/toxav/groupav.c
@@ -97,13 +97,13 @@ static void terminate_queue(Group_JitterBuffer *q)
97 97
98/* Return 0 if packet was queued, -1 if it wasn't. 98/* Return 0 if packet was queued, -1 if it wasn't.
99 */ 99 */
100static int queue(Group_JitterBuffer *q, Group_Audio_Packet *pk) 100static int queue(Group_JitterBuffer *q, const Mono_Time *mono_time, Group_Audio_Packet *pk)
101{ 101{
102 uint16_t sequnum = pk->sequnum; 102 uint16_t sequnum = pk->sequnum;
103 103
104 unsigned int num = sequnum % q->size; 104 unsigned int num = sequnum % q->size;
105 105
106 if (!is_timeout(q->last_queued_time, GROUP_JBUF_DEAD_SECONDS)) { 106 if (!mono_time_is_timeout(mono_time, q->last_queued_time, GROUP_JBUF_DEAD_SECONDS)) {
107 if ((uint32_t)(sequnum - q->bottom) > (1 << 15)) { 107 if ((uint32_t)(sequnum - q->bottom) > (1 << 15)) {
108 /* Drop old packet. */ 108 /* Drop old packet. */
109 return -1; 109 return -1;
@@ -115,7 +115,7 @@ static int queue(Group_JitterBuffer *q, Group_Audio_Packet *pk)
115 q->bottom = sequnum - q->capacity; 115 q->bottom = sequnum - q->capacity;
116 q->queue[num] = pk; 116 q->queue[num] = pk;
117 q->top = sequnum + 1; 117 q->top = sequnum + 1;
118 q->last_queued_time = unix_time(); 118 q->last_queued_time = mono_time_get(mono_time);
119 return 0; 119 return 0;
120 } 120 }
121 121
@@ -129,7 +129,7 @@ static int queue(Group_JitterBuffer *q, Group_Audio_Packet *pk)
129 q->top = sequnum + 1; 129 q->top = sequnum + 1;
130 } 130 }
131 131
132 q->last_queued_time = unix_time(); 132 q->last_queued_time = mono_time_get(mono_time);
133 return 0; 133 return 0;
134} 134}
135 135
@@ -178,6 +178,7 @@ typedef struct Group_AV {
178} Group_AV; 178} Group_AV;
179 179
180typedef struct Group_Peer_AV { 180typedef struct Group_Peer_AV {
181 const Mono_Time *mono_time;
181 Group_JitterBuffer *buffer; 182 Group_JitterBuffer *buffer;
182 183
183 OpusDecoder *audio_decoder; 184 OpusDecoder *audio_decoder;
@@ -264,6 +265,7 @@ static void group_av_peer_new(void *object, uint32_t groupnumber, uint32_t frien
264 return; 265 return;
265 } 266 }
266 267
268 peer_av->mono_time = group_av->g_c->mono_time;
267 peer_av->buffer = create_queue(GROUP_JBUF_SIZE); 269 peer_av->buffer = create_queue(GROUP_JBUF_SIZE);
268 270
269 if (group_peer_set_object(group_av->g_c, groupnumber, friendgroupnumber, peer_av) == -1) { 271 if (group_peer_set_object(group_av->g_c, groupnumber, friendgroupnumber, peer_av) == -1) {
@@ -419,7 +421,7 @@ static int handle_group_audio_packet(void *object, uint32_t groupnumber, uint32_
419 pk->length = length - sizeof(uint16_t); 421 pk->length = length - sizeof(uint16_t);
420 memcpy(pk->data, packet + sizeof(uint16_t), pk->length); 422 memcpy(pk->data, packet + sizeof(uint16_t), pk->length);
421 423
422 if (queue(peer_av->buffer, pk) == -1) { 424 if (queue(peer_av->buffer, peer_av->mono_time, pk) == -1) {
423 free(pk); 425 free(pk);
424 return -1; 426 return -1;
425 } 427 }
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 94928b75..46db6e76 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -93,6 +93,7 @@ typedef struct Cryptopacket_Handler {
93 93
94struct DHT { 94struct DHT {
95 const Logger *log; 95 const Logger *log;
96 Mono_Time *mono_time;
96 Networking_Core *net; 97 Networking_Core *net;
97 98
98 bool hole_punching_enabled; 99 bool hole_punching_enabled;
@@ -243,7 +244,8 @@ static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
243 * If shared key is already in shared_keys, copy it to shared_key. 244 * If shared key is already in shared_keys, copy it to shared_key.
244 * else generate it into shared_key and copy it to shared_keys 245 * else generate it into shared_key and copy it to shared_keys
245 */ 246 */
246void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key) 247void get_shared_key(const Mono_Time *mono_time, Shared_Keys *shared_keys, uint8_t *shared_key,
248 const uint8_t *secret_key, const uint8_t *public_key)
247{ 249{
248 uint32_t num = ~0; 250 uint32_t num = ~0;
249 uint32_t curr = 0; 251 uint32_t curr = 0;
@@ -256,12 +258,12 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t
256 if (id_equal(public_key, key->public_key)) { 258 if (id_equal(public_key, key->public_key)) {
257 memcpy(shared_key, key->shared_key, CRYPTO_SHARED_KEY_SIZE); 259 memcpy(shared_key, key->shared_key, CRYPTO_SHARED_KEY_SIZE);
258 ++key->times_requested; 260 ++key->times_requested;
259 key->time_last_requested = unix_time(); 261 key->time_last_requested = mono_time_get(mono_time);
260 return; 262 return;
261 } 263 }
262 264
263 if (num != 0) { 265 if (num != 0) {
264 if (is_timeout(key->time_last_requested, KEYS_TIMEOUT)) { 266 if (mono_time_is_timeout(mono_time, key->time_last_requested, KEYS_TIMEOUT)) {
265 num = 0; 267 num = 0;
266 curr = index; 268 curr = index;
267 } else if (num > key->times_requested) { 269 } else if (num > key->times_requested) {
@@ -283,7 +285,7 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t
283 key->times_requested = 1; 285 key->times_requested = 1;
284 memcpy(key->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); 286 memcpy(key->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
285 memcpy(key->shared_key, shared_key, CRYPTO_SHARED_KEY_SIZE); 287 memcpy(key->shared_key, shared_key, CRYPTO_SHARED_KEY_SIZE);
286 key->time_last_requested = unix_time(); 288 key->time_last_requested = mono_time_get(mono_time);
287 } 289 }
288} 290}
289 291
@@ -292,7 +294,7 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t
292 */ 294 */
293void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key) 295void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)
294{ 296{
295 get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key); 297 get_shared_key(dht->mono_time, &dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key);
296} 298}
297 299
298/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key 300/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
@@ -300,7 +302,7 @@ void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *publi
300 */ 302 */
301void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key) 303void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)
302{ 304{
303 get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key); 305 get_shared_key(dht->mono_time, &dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key);
304} 306}
305 307
306#define CRYPTO_SIZE 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE 308#define CRYPTO_SIZE 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE
@@ -667,7 +669,8 @@ static uint32_t index_of_client_ip_port(const Client_data *array, uint32_t size,
667 669
668/* Update ip_port of client if it's needed. 670/* Update ip_port of client if it's needed.
669 */ 671 */
670static void update_client(const Logger *log, int index, Client_data *client, IP_Port ip_port) 672static void update_client(const Logger *log, const Mono_Time *mono_time, int index, Client_data *client,
673 IP_Port ip_port)
671{ 674{
672 IPPTsPng *assoc; 675 IPPTsPng *assoc;
673 int ip_version; 676 int ip_version;
@@ -697,7 +700,7 @@ static void update_client(const Logger *log, int index, Client_data *client, IP_
697 } 700 }
698 701
699 assoc->ip_port = ip_port; 702 assoc->ip_port = ip_port;
700 assoc->timestamp = unix_time(); 703 assoc->timestamp = mono_time_get(mono_time);
701} 704}
702 705
703/* Check if client with public_key is already in list of length length. 706/* Check if client with public_key is already in list of length length.
@@ -707,15 +710,15 @@ static void update_client(const Logger *log, int index, Client_data *client, IP_
707 * 710 *
708 * return True(1) or False(0) 711 * return True(1) or False(0)
709 */ 712 */
710static int client_or_ip_port_in_list(const Logger *log, Client_data *list, uint16_t length, const uint8_t *public_key, 713static int client_or_ip_port_in_list(const Logger *log, const Mono_Time *mono_time, Client_data *list, uint16_t length,
711 IP_Port ip_port) 714 const uint8_t *public_key, IP_Port ip_port)
712{ 715{
713 const uint64_t temp_time = unix_time(); 716 const uint64_t temp_time = mono_time_get(mono_time);
714 uint32_t index = index_of_client_pk(list, length, public_key); 717 uint32_t index = index_of_client_pk(list, length, public_key);
715 718
716 /* if public_key is in list, find it and maybe overwrite ip_port */ 719 /* if public_key is in list, find it and maybe overwrite ip_port */
717 if (index != UINT32_MAX) { 720 if (index != UINT32_MAX) {
718 update_client(log, index, &list[index], ip_port); 721 update_client(log, mono_time, index, &list[index], ip_port);
719 return 1; 722 return 1;
720 } 723 }
721 724
@@ -793,7 +796,7 @@ static uint8_t hardening_correct(const Hardening *h)
793/* 796/*
794 * helper for get_close_nodes(). argument list is a monster :D 797 * helper for get_close_nodes(). argument list is a monster :D
795 */ 798 */
796static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list, 799static void get_close_nodes_inner(const Mono_Time *mono_time, const uint8_t *public_key, Node_format *nodes_list,
797 Family sa_family, const Client_data *client_list, uint32_t client_list_length, 800 Family sa_family, const Client_data *client_list, uint32_t client_list_length,
798 uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) 801 uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good)
799{ 802{
@@ -824,7 +827,7 @@ static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_
824 } 827 }
825 828
826 /* node not in a good condition? */ 829 /* node not in a good condition? */
827 if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) { 830 if (mono_time_is_timeout(mono_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) {
828 continue; 831 continue;
829 } 832 }
830 833
@@ -862,14 +865,14 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N
862 Family sa_family, uint8_t is_LAN, uint8_t want_good) 865 Family sa_family, uint8_t is_LAN, uint8_t want_good)
863{ 866{
864 uint32_t num_nodes = 0; 867 uint32_t num_nodes = 0;
865 get_close_nodes_inner(public_key, nodes_list, sa_family, 868 get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,
866 dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0); 869 dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0);
867 870
868 /* TODO(irungentoo): uncomment this when hardening is added to close friend clients */ 871 /* TODO(irungentoo): uncomment this when hardening is added to close friend clients */
869#if 0 872#if 0
870 873
871 for (uint32_t i = 0; i < dht->num_friends; ++i) { 874 for (uint32_t i = 0; i < dht->num_friends; ++i) {
872 get_close_nodes_inner(dht, public_key, nodes_list, sa_family, 875 get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,
873 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 876 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
874 &num_nodes, is_LAN, want_good); 877 &num_nodes, is_LAN, want_good);
875 } 878 }
@@ -877,7 +880,7 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N
877#endif 880#endif
878 881
879 for (uint32_t i = 0; i < dht->num_friends; ++i) { 882 for (uint32_t i = 0; i < dht->num_friends; ++i) {
880 get_close_nodes_inner(public_key, nodes_list, sa_family, 883 get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,
881 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 884 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
882 &num_nodes, is_LAN, 0); 885 &num_nodes, is_LAN, 0);
883 } 886 }
@@ -893,13 +896,14 @@ int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *node
893} 896}
894 897
895typedef struct DHT_Cmp_data { 898typedef struct DHT_Cmp_data {
899 const Mono_Time *mono_time;
896 const uint8_t *base_public_key; 900 const uint8_t *base_public_key;
897 Client_data entry; 901 Client_data entry;
898} DHT_Cmp_data; 902} DHT_Cmp_data;
899 903
900static bool assoc_timeout(const IPPTsPng *assoc) 904static bool assoc_timeout(const Mono_Time *mono_time, const IPPTsPng *assoc)
901{ 905{
902 return is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT); 906 return mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT);
903} 907}
904 908
905static bool incorrect_hardening(const IPPTsPng *assoc) 909static bool incorrect_hardening(const IPPTsPng *assoc)
@@ -916,8 +920,8 @@ static int cmp_dht_entry(const void *a, const void *b)
916 const Client_data entry2 = cmp2.entry; 920 const Client_data entry2 = cmp2.entry;
917 const uint8_t *cmp_public_key = cmp1.base_public_key; 921 const uint8_t *cmp_public_key = cmp1.base_public_key;
918 922
919 bool t1 = assoc_timeout(&entry1.assoc4) && assoc_timeout(&entry1.assoc6); 923 bool t1 = assoc_timeout(cmp1.mono_time, &entry1.assoc4) && assoc_timeout(cmp1.mono_time, &entry1.assoc6);
920 bool t2 = assoc_timeout(&entry2.assoc4) && assoc_timeout(&entry2.assoc6); 924 bool t2 = assoc_timeout(cmp2.mono_time, &entry2.assoc4) && assoc_timeout(cmp2.mono_time, &entry2.assoc6);
921 925
922 if (t1 && t2) { 926 if (t1 && t2) {
923 return 0; 927 return 0;
@@ -960,20 +964,23 @@ static int cmp_dht_entry(const void *a, const void *b)
960 * return 0 if node can't be stored. 964 * return 0 if node can't be stored.
961 * return 1 if it can. 965 * return 1 if it can.
962 */ 966 */
963static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key) 967static unsigned int store_node_ok(const Client_data *client, const Mono_Time *mono_time, const uint8_t *public_key,
968 const uint8_t *comp_public_key)
964{ 969{
965 return (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) 970 return (mono_time_is_timeout(mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT)
966 && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) 971 && mono_time_is_timeout(mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT))
967 || id_closest(comp_public_key, client->public_key, public_key) == 2; 972 || id_closest(comp_public_key, client->public_key, public_key) == 2;
968} 973}
969 974
970static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) 975static void sort_client_list(Client_data *list, const Mono_Time *mono_time, unsigned int length,
976 const uint8_t *comp_public_key)
971{ 977{
972 // Pass comp_public_key to qsort with each Client_data entry, so the 978 // Pass comp_public_key to qsort with each Client_data entry, so the
973 // comparison function can use it as the base of comparison. 979 // comparison function can use it as the base of comparison.
974 VLA(DHT_Cmp_data, cmp_list, length); 980 VLA(DHT_Cmp_data, cmp_list, length);
975 981
976 for (uint32_t i = 0; i < length; ++i) { 982 for (uint32_t i = 0; i < length; ++i) {
983 cmp_list[i].mono_time = mono_time;
977 cmp_list[i].base_public_key = comp_public_key; 984 cmp_list[i].base_public_key = comp_public_key;
978 cmp_list[i].entry = list[i]; 985 cmp_list[i].entry = list[i];
979 } 986 }
@@ -985,7 +992,7 @@ static void sort_client_list(Client_data *list, unsigned int length, const uint8
985 } 992 }
986} 993}
987 994
988static void update_client_with_reset(Client_data *client, const IP_Port *ip_port) 995static void update_client_with_reset(const Mono_Time *mono_time, Client_data *client, const IP_Port *ip_port)
989{ 996{
990 IPPTsPng *ipptp_write = nullptr; 997 IPPTsPng *ipptp_write = nullptr;
991 IPPTsPng *ipptp_clear = nullptr; 998 IPPTsPng *ipptp_clear = nullptr;
@@ -999,7 +1006,7 @@ static void update_client_with_reset(Client_data *client, const IP_Port *ip_port
999 } 1006 }
1000 1007
1001 ipptp_write->ip_port = *ip_port; 1008 ipptp_write->ip_port = *ip_port;
1002 ipptp_write->timestamp = unix_time(); 1009 ipptp_write->timestamp = mono_time_get(mono_time);
1003 1010
1004 ip_reset(&ipptp_write->ret_ip_port.ip); 1011 ip_reset(&ipptp_write->ret_ip_port.ip);
1005 ipptp_write->ret_ip_port.port = 0; 1012 ipptp_write->ret_ip_port.port = 0;
@@ -1022,7 +1029,8 @@ static void update_client_with_reset(Client_data *client, const IP_Port *ip_port
1022 * than public_key. 1029 * than public_key.
1023 * 1030 *
1024 * returns true when the item was stored, false otherwise */ 1031 * returns true when the item was stored, false otherwise */
1025static bool replace_all(Client_data *list, 1032static bool replace_all(const Mono_Time *mono_time,
1033 Client_data *list,
1026 uint16_t length, 1034 uint16_t length,
1027 const uint8_t *public_key, 1035 const uint8_t *public_key,
1028 IP_Port ip_port, 1036 IP_Port ip_port,
@@ -1032,17 +1040,17 @@ static bool replace_all(Client_data *list,
1032 return false; 1040 return false;
1033 } 1041 }
1034 1042
1035 if (!store_node_ok(&list[1], public_key, comp_public_key) && 1043 if (!store_node_ok(&list[1], mono_time, public_key, comp_public_key) &&
1036 !store_node_ok(&list[0], public_key, comp_public_key)) { 1044 !store_node_ok(&list[0], mono_time, public_key, comp_public_key)) {
1037 return false; 1045 return false;
1038 } 1046 }
1039 1047
1040 sort_client_list(list, length, comp_public_key); 1048 sort_client_list(list, mono_time, length, comp_public_key);
1041 1049
1042 Client_data *const client = &list[0]; 1050 Client_data *const client = &list[0];
1043 id_copy(client->public_key, public_key); 1051 id_copy(client->public_key, public_key);
1044 1052
1045 update_client_with_reset(client, &ip_port); 1053 update_client_with_reset(mono_time, client, &ip_port);
1046 return true; 1054 return true;
1047} 1055}
1048 1056
@@ -1066,8 +1074,8 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bo
1066 * index is left as >= LCLIENT_LENGTH */ 1074 * index is left as >= LCLIENT_LENGTH */
1067 Client_data *const client = &dht->close_clientlist[(index * LCLIENT_NODES) + i]; 1075 Client_data *const client = &dht->close_clientlist[(index * LCLIENT_NODES) + i];
1068 1076
1069 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || 1077 if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
1070 !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { 1078 !mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
1071 continue; 1079 continue;
1072 } 1080 }
1073 1081
@@ -1076,7 +1084,7 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bo
1076 } 1084 }
1077 1085
1078 id_copy(client->public_key, public_key); 1086 id_copy(client->public_key, public_key);
1079 update_client_with_reset(client, &ip_port); 1087 update_client_with_reset(dht->mono_time, client, &ip_port);
1080 return 0; 1088 return 0;
1081 } 1089 }
1082 1090
@@ -1090,8 +1098,8 @@ bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_
1090 return add_to_close(dht, public_key, ip_port, 1) == 0; 1098 return add_to_close(dht, public_key, ip_port, 1) == 0;
1091} 1099}
1092 1100
1093static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, const uint8_t *public_key, 1101static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, const Mono_Time *mono_time,
1094 IP_Port ip_port) 1102 const uint8_t *public_key, IP_Port ip_port)
1095{ 1103{
1096 const uint32_t index = index_of_client_pk(list, client_list_length, public_key); 1104 const uint32_t index = index_of_client_pk(list, client_list_length, public_key);
1097 1105
@@ -1103,7 +1111,7 @@ static bool is_pk_in_client_list(const Client_data *list, unsigned int client_li
1103 ? &list[index].assoc4 1111 ? &list[index].assoc4
1104 : &list[index].assoc6; 1112 : &list[index].assoc6;
1105 1113
1106 return !is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT); 1114 return !mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT);
1107} 1115}
1108 1116
1109static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port) 1117static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
@@ -1114,7 +1122,8 @@ static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_
1114 index = LCLIENT_LENGTH - 1; 1122 index = LCLIENT_LENGTH - 1;
1115 } 1123 }
1116 1124
1117 return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, public_key, ip_port); 1125 return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->mono_time, public_key,
1126 ip_port);
1118} 1127}
1119 1128
1120/* Check if the node obtained with a get_nodes with public_key should be pinged. 1129/* Check if the node obtained with a get_nodes with public_key should be pinged.
@@ -1153,17 +1162,18 @@ static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_P
1153 1162
1154 bool store_ok = false; 1163 bool store_ok = false;
1155 1164
1156 if (store_node_ok(&dht_friend->client_list[1], public_key, dht_friend->public_key)) { 1165 if (store_node_ok(&dht_friend->client_list[1], dht->mono_time, public_key, dht_friend->public_key)) {
1157 store_ok = true; 1166 store_ok = true;
1158 } 1167 }
1159 1168
1160 if (store_node_ok(&dht_friend->client_list[0], public_key, dht_friend->public_key)) { 1169 if (store_node_ok(&dht_friend->client_list[0], dht->mono_time, public_key, dht_friend->public_key)) {
1161 store_ok = true; 1170 store_ok = true;
1162 } 1171 }
1163 1172
1164 unsigned int *const friend_num = &dht_friend->num_to_bootstrap; 1173 unsigned int *const friend_num = &dht_friend->num_to_bootstrap;
1165 const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key); 1174 const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key);
1166 const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, public_key, ip_port); 1175 const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->mono_time, public_key,
1176 ip_port);
1167 1177
1168 if (store_ok && index == UINT32_MAX && !pk_in_list) { 1178 if (store_ok && index == UINT32_MAX && !pk_in_list) {
1169 if (*friend_num < MAX_SENT_NODES) { 1179 if (*friend_num < MAX_SENT_NODES) {
@@ -1200,8 +1210,8 @@ uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
1200 /* NOTE: Current behavior if there are two clients with the same id is 1210 /* NOTE: Current behavior if there are two clients with the same id is
1201 * to replace the first ip by the second. 1211 * to replace the first ip by the second.
1202 */ 1212 */
1203 const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->close_clientlist, 1213 const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->close_clientlist, LCLIENT_LIST,
1204 LCLIENT_LIST, public_key, ip_port); 1214 public_key, ip_port);
1205 1215
1206 /* add_to_close should be called only if !in_list (don't extract to variable) */ 1216 /* add_to_close should be called only if !in_list (don't extract to variable) */
1207 if (in_close_list || add_to_close(dht, public_key, ip_port, 0)) { 1217 if (in_close_list || add_to_close(dht, public_key, ip_port, 0)) {
@@ -1211,12 +1221,13 @@ uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
1211 DHT_Friend *friend_foundip = nullptr; 1221 DHT_Friend *friend_foundip = nullptr;
1212 1222
1213 for (uint32_t i = 0; i < dht->num_friends; ++i) { 1223 for (uint32_t i = 0; i < dht->num_friends; ++i) {
1214 const bool in_list = client_or_ip_port_in_list(dht->log, dht->friends_list[i].client_list, 1224 const bool in_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->friends_list[i].client_list,
1215 MAX_FRIEND_CLIENTS, public_key, ip_port); 1225 MAX_FRIEND_CLIENTS, public_key, ip_port);
1216 1226
1217 /* replace_all should be called only if !in_list (don't extract to variable) */ 1227 /* replace_all should be called only if !in_list (don't extract to variable) */
1218 if (in_list || replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, 1228 if (in_list
1219 ip_port, dht->friends_list[i].public_key)) { 1229 || replace_all(dht->mono_time, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, ip_port,
1230 dht->friends_list[i].public_key)) {
1220 DHT_Friend *dht_friend = &dht->friends_list[i]; 1231 DHT_Friend *dht_friend = &dht->friends_list[i];
1221 1232
1222 if (id_equal(public_key, dht_friend->public_key)) { 1233 if (id_equal(public_key, dht_friend->public_key)) {
@@ -1241,9 +1252,10 @@ uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
1241 return used; 1252 return used;
1242} 1253}
1243 1254
1244static bool update_client_data(Client_data *array, size_t size, IP_Port ip_port, const uint8_t *pk) 1255static bool update_client_data(const Mono_Time *mono_time, Client_data *array, size_t size, IP_Port ip_port,
1256 const uint8_t *pk)
1245{ 1257{
1246 const uint64_t temp_time = unix_time(); 1258 const uint64_t temp_time = mono_time_get(mono_time);
1247 const uint32_t index = index_of_client_pk(array, size, pk); 1259 const uint32_t index = index_of_client_pk(array, size, pk);
1248 1260
1249 if (index == UINT32_MAX) { 1261 if (index == UINT32_MAX) {
@@ -1278,7 +1290,7 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_ke
1278 } 1290 }
1279 1291
1280 if (id_equal(public_key, dht->self_public_key)) { 1292 if (id_equal(public_key, dht->self_public_key)) {
1281 update_client_data(dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key); 1293 update_client_data(dht->mono_time, dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key);
1282 return; 1294 return;
1283 } 1295 }
1284 1296
@@ -1286,7 +1298,7 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_ke
1286 if (id_equal(public_key, dht->friends_list[i].public_key)) { 1298 if (id_equal(public_key, dht->friends_list[i].public_key)) {
1287 Client_data *const client_list = dht->friends_list[i].client_list; 1299 Client_data *const client_list = dht->friends_list[i].client_list;
1288 1300
1289 if (update_client_data(client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) { 1301 if (update_client_data(dht->mono_time, client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) {
1290 return; 1302 return;
1291 } 1303 }
1292 } 1304 }
@@ -1314,9 +1326,9 @@ static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const
1314 1326
1315 if (sendback_node != nullptr) { 1327 if (sendback_node != nullptr) {
1316 memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format)); 1328 memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format));
1317 ping_id = ping_array_add(dht->dht_harden_ping_array, plain_message, sizeof(plain_message)); 1329 ping_id = ping_array_add(dht->dht_harden_ping_array, dht->mono_time, plain_message, sizeof(plain_message));
1318 } else { 1330 } else {
1319 ping_id = ping_array_add(dht->dht_ping_array, plain_message, sizeof(receiver)); 1331 ping_id = ping_array_add(dht->dht_ping_array, dht->mono_time, plain_message, sizeof(receiver));
1320 } 1332 }
1321 1333
1322 if (ping_id == 0) { 1334 if (ping_id == 0) {
@@ -1433,9 +1445,9 @@ static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port no
1433{ 1445{
1434 uint8_t data[sizeof(Node_format) * 2]; 1446 uint8_t data[sizeof(Node_format) * 2];
1435 1447
1436 if (ping_array_check(dht->dht_ping_array, data, sizeof(data), ping_id) == sizeof(Node_format)) { 1448 if (ping_array_check(dht->dht_ping_array, dht->mono_time, data, sizeof(data), ping_id) == sizeof(Node_format)) {
1437 memset(sendback_node, 0, sizeof(Node_format)); 1449 memset(sendback_node, 0, sizeof(Node_format));
1438 } else if (ping_array_check(dht->dht_harden_ping_array, data, sizeof(data), ping_id) == sizeof(data)) { 1450 } else if (ping_array_check(dht->dht_harden_ping_array, dht->mono_time, data, sizeof(data), ping_id) == sizeof(data)) {
1439 memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format)); 1451 memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format));
1440 } else { 1452 } else {
1441 return false; 1453 return false;
@@ -1678,7 +1690,7 @@ int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
1678 for (const IPPTsPng * const *it = assocs; *it; ++it) { 1690 for (const IPPTsPng * const *it = assocs; *it; ++it) {
1679 const IPPTsPng *const assoc = *it; 1691 const IPPTsPng *const assoc = *it;
1680 1692
1681 if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { 1693 if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {
1682 *ip_port = assoc->ip_port; 1694 *ip_port = assoc->ip_port;
1683 return 1; 1695 return 1;
1684 } 1696 }
@@ -1692,7 +1704,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
1692 Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable) 1704 Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable)
1693{ 1705{
1694 uint8_t not_kill = 0; 1706 uint8_t not_kill = 0;
1695 const uint64_t temp_time = unix_time(); 1707 const uint64_t temp_time = mono_time_get(dht->mono_time);
1696 1708
1697 uint32_t num_nodes = 0; 1709 uint32_t num_nodes = 0;
1698 VLA(Client_data *, client_list, list_count * 2); 1710 VLA(Client_data *, client_list, list_count * 2);
@@ -1709,17 +1721,17 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
1709 for (uint32_t j = 0; j < sizeof(assocs) / sizeof(assocs[0]); ++j) { 1721 for (uint32_t j = 0; j < sizeof(assocs) / sizeof(assocs[0]); ++j) {
1710 IPPTsPng *const assoc = assocs[j]; 1722 IPPTsPng *const assoc = assocs[j];
1711 1723
1712 if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) { 1724 if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, KILL_NODE_TIMEOUT)) {
1713 sort = 0; 1725 sort = 0;
1714 ++not_kill; 1726 ++not_kill;
1715 1727
1716 if (is_timeout(assoc->last_pinged, PING_INTERVAL)) { 1728 if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) {
1717 getnodes(dht, assoc->ip_port, client->public_key, public_key, nullptr); 1729 getnodes(dht, assoc->ip_port, client->public_key, public_key, nullptr);
1718 assoc->last_pinged = temp_time; 1730 assoc->last_pinged = temp_time;
1719 } 1731 }
1720 1732
1721 /* If node is good. */ 1733 /* If node is good. */
1722 if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { 1734 if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {
1723 client_list[num_nodes] = client; 1735 client_list[num_nodes] = client;
1724 assoc_list[num_nodes] = assoc; 1736 assoc_list[num_nodes] = assoc;
1725 ++num_nodes; 1737 ++num_nodes;
@@ -1736,10 +1748,11 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
1736 } 1748 }
1737 1749
1738 if (sortable && sort_ok) { 1750 if (sortable && sort_ok) {
1739 sort_client_list(list, list_count, public_key); 1751 sort_client_list(list, dht->mono_time, list_count, public_key);
1740 } 1752 }
1741 1753
1742 if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) { 1754 if ((num_nodes != 0) && (mono_time_is_timeout(dht->mono_time, *lastgetnode, GET_NODE_INTERVAL)
1755 || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
1743 uint32_t rand_node = random_u32() % num_nodes; 1756 uint32_t rand_node = random_u32() % num_nodes;
1744 1757
1745 if ((num_nodes - 1) != rand_node) { 1758 if ((num_nodes - 1) != rand_node) {
@@ -1801,7 +1814,7 @@ static void do_Close(DHT *dht)
1801 * 1814 *
1802 * so: reset all nodes to be BAD_NODE_TIMEOUT, but not 1815 * so: reset all nodes to be BAD_NODE_TIMEOUT, but not
1803 * KILL_NODE_TIMEOUT, so we at least keep trying pings */ 1816 * KILL_NODE_TIMEOUT, so we at least keep trying pings */
1804 const uint64_t badonly = unix_time() - BAD_NODE_TIMEOUT; 1817 const uint64_t badonly = mono_time_get(dht->mono_time) - BAD_NODE_TIMEOUT;
1805 1818
1806 for (size_t i = 0; i < LCLIENT_LIST; ++i) { 1819 for (size_t i = 0; i < LCLIENT_LIST; ++i) {
1807 Client_data *const client = &dht->close_clientlist[i]; 1820 Client_data *const client = &dht->close_clientlist[i];
@@ -1906,19 +1919,21 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
1906 const Client_data *const client = &dht_friend->client_list[i]; 1919 const Client_data *const client = &dht_friend->client_list[i];
1907 1920
1908 /* If ip is not zero and node is good. */ 1921 /* If ip is not zero and node is good. */
1909 if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) { 1922 if (ip_isset(&client->assoc4.ret_ip_port.ip)
1923 && !mono_time_is_timeout(dht->mono_time, client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) {
1910 ipv4s[num_ipv4s] = client->assoc4.ret_ip_port; 1924 ipv4s[num_ipv4s] = client->assoc4.ret_ip_port;
1911 ++num_ipv4s; 1925 ++num_ipv4s;
1912 } 1926 }
1913 1927
1914 if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) { 1928 if (ip_isset(&client->assoc6.ret_ip_port.ip)
1929 && !mono_time_is_timeout(dht->mono_time, client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) {
1915 ipv6s[num_ipv6s] = client->assoc6.ret_ip_port; 1930 ipv6s[num_ipv6s] = client->assoc6.ret_ip_port;
1916 ++num_ipv6s; 1931 ++num_ipv6s;
1917 } 1932 }
1918 1933
1919 if (id_equal(client->public_key, dht_friend->public_key)) { 1934 if (id_equal(client->public_key, dht_friend->public_key)) {
1920 if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) 1935 if (!mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)
1921 || !is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)) { 1936 || !mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT)) {
1922 return 0; /* direct connectivity */ 1937 return 0; /* direct connectivity */
1923 } 1938 }
1924 } 1939 }
@@ -1997,7 +2012,7 @@ int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *pack
1997 const IPPTsPng *const assoc = *it; 2012 const IPPTsPng *const assoc = *it;
1998 2013
1999 /* If ip is not zero and node is good. */ 2014 /* If ip is not zero and node is good. */
2000 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 2015 if (ip_isset(&assoc->ret_ip_port.ip) && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
2001 const int retval = sendpacket(dht->net, assoc->ip_port, packet, length); 2016 const int retval = sendpacket(dht->net, assoc->ip_port, packet, length);
2002 2017
2003 if ((unsigned int)retval == length) { 2018 if ((unsigned int)retval == length) {
@@ -2039,7 +2054,7 @@ static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *
2039 const IPPTsPng *const assoc = *it; 2054 const IPPTsPng *const assoc = *it;
2040 2055
2041 /* If ip is not zero and node is good. */ 2056 /* If ip is not zero and node is good. */
2042 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 2057 if (ip_isset(&assoc->ret_ip_port.ip) && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
2043 ip_list[n] = assoc->ip_port; 2058 ip_list[n] = assoc->ip_port;
2044 ++n; 2059 ++n;
2045 } 2060 }
@@ -2116,7 +2131,7 @@ static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pu
2116 if (packet[0] == NAT_PING_REQUEST) { 2131 if (packet[0] == NAT_PING_REQUEST) {
2117 /* 1 is reply */ 2132 /* 1 is reply */
2118 send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); 2133 send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
2119 dht_friend->nat.recv_nat_ping_timestamp = unix_time(); 2134 dht_friend->nat.recv_nat_ping_timestamp = mono_time_get(dht->mono_time);
2120 return 0; 2135 return 0;
2121 } 2136 }
2122 2137
@@ -2243,7 +2258,7 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
2243 2258
2244static void do_NAT(DHT *dht) 2259static void do_NAT(DHT *dht)
2245{ 2260{
2246 const uint64_t temp_time = unix_time(); 2261 const uint64_t temp_time = mono_time_get(dht->mono_time);
2247 2262
2248 for (uint32_t i = 0; i < dht->num_friends; ++i) { 2263 for (uint32_t i = 0; i < dht->num_friends; ++i) {
2249 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 2264 IP_Port ip_list[MAX_FRIEND_CLIENTS];
@@ -2393,7 +2408,7 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
2393 const IPPTsPng *const temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family); 2408 const IPPTsPng *const temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family);
2394 2409
2395 if (temp) { 2410 if (temp) {
2396 if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) { 2411 if (!mono_time_is_timeout(dht->mono_time, temp->timestamp, BAD_NODE_TIMEOUT)) {
2397 ++counter; 2412 ++counter;
2398 } 2413 }
2399 } 2414 }
@@ -2464,7 +2479,7 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_
2464 return 1; 2479 return 1;
2465 } 2480 }
2466 2481
2467 if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { 2482 if (mono_time_is_timeout(dht->mono_time, temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
2468 return 1; 2483 return 1;
2469 } 2484 }
2470 2485
@@ -2512,7 +2527,8 @@ static Node_format random_node(DHT *dht, Family sa_family)
2512 * 2527 *
2513 * return the number of nodes. 2528 * return the number of nodes.
2514 */ 2529 */
2515static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes, uint16_t max_num) 2530static uint16_t list_nodes(Client_data *list, size_t length, const Mono_Time *mono_time, Node_format *nodes,
2531 uint16_t max_num)
2516{ 2532{
2517 if (max_num == 0) { 2533 if (max_num == 0) {
2518 return 0; 2534 return 0;
@@ -2523,11 +2539,11 @@ static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes,
2523 for (size_t i = length; i != 0; --i) { 2539 for (size_t i = length; i != 0; --i) {
2524 const IPPTsPng *assoc = nullptr; 2540 const IPPTsPng *assoc = nullptr;
2525 2541
2526 if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) { 2542 if (!mono_time_is_timeout(mono_time, list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) {
2527 assoc = &list[i - 1].assoc4; 2543 assoc = &list[i - 1].assoc4;
2528 } 2544 }
2529 2545
2530 if (!is_timeout(list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) { 2546 if (!mono_time_is_timeout(mono_time, list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) {
2531 if (assoc == nullptr) { 2547 if (assoc == nullptr) {
2532 assoc = &list[i - 1].assoc6; 2548 assoc = &list[i - 1].assoc6;
2533 } else if (random_u08() % 2) { 2549 } else if (random_u08() % 2) {
@@ -2563,8 +2579,8 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2563 const uint32_t r = random_u32(); 2579 const uint32_t r = random_u32();
2564 2580
2565 for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { 2581 for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
2566 count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, nodes + count, 2582 count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, dht->mono_time,
2567 max_num - count); 2583 nodes + count, max_num - count);
2568 2584
2569 if (count >= max_num) { 2585 if (count >= max_num) {
2570 break; 2586 break;
@@ -2580,7 +2596,7 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2580 */ 2596 */
2581uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) 2597uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2582{ 2598{
2583 return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num); 2599 return list_nodes(dht->close_clientlist, LCLIENT_LIST, dht->mono_time, nodes, max_num);
2584} 2600}
2585 2601
2586#if DHT_HARDENING 2602#if DHT_HARDENING
@@ -2599,12 +2615,12 @@ static void do_hardening(DHT *dht)
2599 sa_family = net_family_ipv6; 2615 sa_family = net_family_ipv6;
2600 } 2616 }
2601 2617
2602 if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) { 2618 if (mono_time_is_timeout(dht->mono_time, cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) {
2603 continue; 2619 continue;
2604 } 2620 }
2605 2621
2606 if (cur_iptspng->hardening.send_nodes_ok == 0) { 2622 if (cur_iptspng->hardening.send_nodes_ok == 0) {
2607 if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { 2623 if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
2608 Node_format rand_node = random_node(dht, sa_family); 2624 Node_format rand_node = random_node(dht, sa_family);
2609 2625
2610 if (!ipport_isset(&rand_node.ip_port)) { 2626 if (!ipport_isset(&rand_node.ip_port)) {
@@ -2622,11 +2638,11 @@ static void do_hardening(DHT *dht)
2622 // TODO(irungentoo): The search id should maybe not be ours? 2638 // TODO(irungentoo): The search id should maybe not be ours?
2623 if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) { 2639 if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) {
2624 memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, CRYPTO_PUBLIC_KEY_SIZE); 2640 memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, CRYPTO_PUBLIC_KEY_SIZE);
2625 cur_iptspng->hardening.send_nodes_timestamp = unix_time(); 2641 cur_iptspng->hardening.send_nodes_timestamp = mono_time_get(dht->mono_time);
2626 } 2642 }
2627 } 2643 }
2628 } else { 2644 } else {
2629 if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) { 2645 if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) {
2630 cur_iptspng->hardening.send_nodes_ok = 0; 2646 cur_iptspng->hardening.send_nodes_ok = 0;
2631 } 2647 }
2632 } 2648 }
@@ -2688,7 +2704,7 @@ static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *pack
2688 2704
2689/*----------------------------------------------------------------------------------*/ 2705/*----------------------------------------------------------------------------------*/
2690 2706
2691DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled) 2707DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool holepunching_enabled)
2692{ 2708{
2693 if (net == nullptr) { 2709 if (net == nullptr) {
2694 return nullptr; 2710 return nullptr;
@@ -2700,12 +2716,13 @@ DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled)
2700 return nullptr; 2716 return nullptr;
2701 } 2717 }
2702 2718
2719 dht->mono_time = mono_time;
2703 dht->log = log; 2720 dht->log = log;
2704 dht->net = net; 2721 dht->net = net;
2705 2722
2706 dht->hole_punching_enabled = holepunching_enabled; 2723 dht->hole_punching_enabled = holepunching_enabled;
2707 2724
2708 dht->ping = ping_new(dht); 2725 dht->ping = ping_new(mono_time, dht);
2709 2726
2710 if (dht->ping == nullptr) { 2727 if (dht->ping == nullptr) {
2711 kill_dht(dht); 2728 kill_dht(dht);
@@ -2738,7 +2755,7 @@ DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled)
2738 2755
2739void do_dht(DHT *dht) 2756void do_dht(DHT *dht)
2740{ 2757{
2741 if (dht->last_run == unix_time()) { 2758 if (dht->last_run == mono_time_get(dht->mono_time)) {
2742 return; 2759 return;
2743 } 2760 }
2744 2761
@@ -2754,7 +2771,7 @@ void do_dht(DHT *dht)
2754#if DHT_HARDENING 2771#if DHT_HARDENING
2755 do_hardening(dht); 2772 do_hardening(dht);
2756#endif 2773#endif
2757 dht->last_run = unix_time(); 2774 dht->last_run = mono_time_get(dht->mono_time);
2758} 2775}
2759 2776
2760void kill_dht(DHT *dht) 2777void kill_dht(DHT *dht)
@@ -2961,8 +2978,8 @@ bool dht_isconnected(const DHT *dht)
2961 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) { 2978 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2962 const Client_data *const client = &dht->close_clientlist[i]; 2979 const Client_data *const client = &dht->close_clientlist[i];
2963 2980
2964 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || 2981 if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
2965 !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { 2982 !mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
2966 return true; 2983 return true;
2967 } 2984 }
2968 } 2985 }
@@ -2978,11 +2995,13 @@ bool dht_non_lan_connected(const DHT *dht)
2978 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) { 2995 for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2979 const Client_data *const client = &dht->close_clientlist[i]; 2996 const Client_data *const client = &dht->close_clientlist[i];
2980 2997
2981 if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && ip_is_lan(client->assoc4.ip_port.ip) == -1) { 2998 if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT)
2999 && ip_is_lan(client->assoc4.ip_port.ip) == -1) {
2982 return true; 3000 return true;
2983 } 3001 }
2984 3002
2985 if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) && ip_is_lan(client->assoc6.ip_port.ip) == -1) { 3003 if (!mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)
3004 && ip_is_lan(client->assoc6.ip_port.ip) == -1) {
2986 return true; 3005 return true;
2987 } 3006 }
2988 } 3007 }
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index 0852827c..4219bf47 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -26,6 +26,7 @@
26 26
27#include "crypto_core.h" 27#include "crypto_core.h"
28#include "logger.h" 28#include "logger.h"
29#include "mono_time.h"
29#include "network.h" 30#include "network.h"
30#include "ping_array.h" 31#include "ping_array.h"
31 32
@@ -240,8 +241,8 @@ const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num);
240 * If shared key is already in shared_keys, copy it to shared_key. 241 * If shared key is already in shared_keys, copy it to shared_key.
241 * else generate it into shared_key and copy it to shared_keys 242 * else generate it into shared_key and copy it to shared_keys
242 */ 243 */
243void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, 244void get_shared_key(const Mono_Time *mono_time, Shared_Keys *shared_keys, uint8_t *shared_key,
244 const uint8_t *public_key); 245 const uint8_t *secret_key, const uint8_t *public_key);
245 246
246/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key 247/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
247 * for packets that we receive. 248 * for packets that we receive.
@@ -401,7 +402,7 @@ void dht_save(const DHT *dht, uint8_t *data);
401int dht_load(DHT *dht, const uint8_t *data, uint32_t length); 402int dht_load(DHT *dht, const uint8_t *data, uint32_t length);
402 403
403/* Initialize DHT. */ 404/* Initialize DHT. */
404DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled); 405DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool holepunching_enabled);
405 406
406void kill_dht(DHT *dht); 407void kill_dht(DHT *dht);
407 408
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index ab341e61..dacd662b 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1949,7 +1949,7 @@ static int friend_already_added(const uint8_t *real_pk, void *data)
1949} 1949}
1950 1950
1951/* Run this at startup. */ 1951/* Run this at startup. */
1952Messenger *new_messenger(Messenger_Options *options, unsigned int *error) 1952Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsigned int *error)
1953{ 1953{
1954 if (!options) { 1954 if (!options) {
1955 return nullptr; 1955 return nullptr;
@@ -1965,6 +1965,8 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
1965 return nullptr; 1965 return nullptr;
1966 } 1966 }
1967 1967
1968 m->mono_time = mono_time;
1969
1968 m->fr = friendreq_new(); 1970 m->fr = friendreq_new();
1969 1971
1970 if (!m->fr) { 1972 if (!m->fr) {
@@ -2010,7 +2012,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
2010 return nullptr; 2012 return nullptr;
2011 } 2013 }
2012 2014
2013 m->dht = new_dht(m->log, m->net, options->hole_punching_enabled); 2015 m->dht = new_dht(m->log, m->mono_time, m->net, options->hole_punching_enabled);
2014 2016
2015 if (m->dht == nullptr) { 2017 if (m->dht == nullptr) {
2016 kill_networking(m->net); 2018 kill_networking(m->net);
@@ -2020,7 +2022,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
2020 return nullptr; 2022 return nullptr;
2021 } 2023 }
2022 2024
2023 m->net_crypto = new_net_crypto(m->log, m->dht, &options->proxy_info); 2025 m->net_crypto = new_net_crypto(m->log, m->mono_time, m->dht, &options->proxy_info);
2024 2026
2025 if (m->net_crypto == nullptr) { 2027 if (m->net_crypto == nullptr) {
2026 kill_networking(m->net); 2028 kill_networking(m->net);
@@ -2031,10 +2033,10 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
2031 return nullptr; 2033 return nullptr;
2032 } 2034 }
2033 2035
2034 m->onion = new_onion(m->dht); 2036 m->onion = new_onion(m->mono_time, m->dht);
2035 m->onion_a = new_onion_announce(m->dht); 2037 m->onion_a = new_onion_announce(m->mono_time, m->dht);
2036 m->onion_c = new_onion_client(m->net_crypto); 2038 m->onion_c = new_onion_client(m->mono_time, m->net_crypto);
2037 m->fr_c = new_friend_connections(m->onion_c, options->local_discovery_enabled); 2039 m->fr_c = new_friend_connections(m->mono_time, m->onion_c, options->local_discovery_enabled);
2038 2040
2039 if (!(m->onion && m->onion_a && m->onion_c)) { 2041 if (!(m->onion && m->onion_a && m->onion_c)) {
2040 kill_friend_connections(m->fr_c); 2042 kill_friend_connections(m->fr_c);
@@ -2468,7 +2470,7 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le
2468static void do_friends(Messenger *m, void *userdata) 2470static void do_friends(Messenger *m, void *userdata)
2469{ 2471{
2470 uint32_t i; 2472 uint32_t i;
2471 uint64_t temp_time = unix_time(); 2473 uint64_t temp_time = mono_time_get(m->mono_time);
2472 2474
2473 for (i = 0; i < m->numfriends; ++i) { 2475 for (i = 0; i < m->numfriends; ++i) {
2474 if (m->friendlist[i].status == FRIEND_ADDED) { 2476 if (m->friendlist[i].status == FRIEND_ADDED) {
@@ -2609,7 +2611,7 @@ void do_messenger(Messenger *m, void *userdata)
2609 } 2611 }
2610 2612
2611 if (m->tcp_server) { 2613 if (m->tcp_server) {
2612 do_TCP_server(m->tcp_server); 2614 do_TCP_server(m->tcp_server, m->mono_time);
2613 } 2615 }
2614 2616
2615 do_net_crypto(m->net_crypto, userdata); 2617 do_net_crypto(m->net_crypto, userdata);
@@ -2618,8 +2620,8 @@ void do_messenger(Messenger *m, void *userdata)
2618 do_friends(m, userdata); 2620 do_friends(m, userdata);
2619 connection_status_callback(m, userdata); 2621 connection_status_callback(m, userdata);
2620 2622
2621 if (unix_time() > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { 2623 if (mono_time_get(m->mono_time) > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
2622 m->lastdump = unix_time(); 2624 m->lastdump = mono_time_get(m->mono_time);
2623 uint32_t client, last_pinged; 2625 uint32_t client, last_pinged;
2624 2626
2625 for (client = 0; client < LCLIENT_LIST; ++client) { 2627 for (client = 0; client < LCLIENT_LIST; ++client) {
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 6fc4df02..0bb230cf 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -233,6 +233,7 @@ typedef struct Friend {
233 233
234struct Messenger { 234struct Messenger {
235 Logger *log; 235 Logger *log;
236 Mono_Time *mono_time;
236 237
237 Networking_Core *net; 238 Networking_Core *net;
238 Net_Crypto *net_crypto; 239 Net_Crypto *net_crypto;
@@ -738,7 +739,7 @@ typedef enum Messenger_Error {
738 * 739 *
739 * if error is not NULL it will be set to one of the values in the enum above. 740 * if error is not NULL it will be set to one of the values in the enum above.
740 */ 741 */
741Messenger *new_messenger(Messenger_Options *options, unsigned int *error); 742Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsigned int *error);
742 743
743/* Run this before closing shop 744/* Run this before closing shop
744 * Free all datastructures. 745 * Free all datastructures.
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c
index d6a27c95..a6beac4d 100644
--- a/toxcore/TCP_client.c
+++ b/toxcore/TCP_client.c
@@ -688,8 +688,8 @@ void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *o
688 688
689/* Create new TCP connection to ip_port/public_key 689/* Create new TCP connection to ip_port/public_key
690 */ 690 */
691TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key, 691TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip_port, const uint8_t *public_key,
692 const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info) 692 const uint8_t *self_public_key, const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info)
693{ 693{
694 if (networking_at_startup() != 0) { 694 if (networking_at_startup() != 0) {
695 return nullptr; 695 return nullptr;
@@ -765,7 +765,7 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
765 break; 765 break;
766 } 766 }
767 767
768 temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT; 768 temp->kill_at = mono_time_get(mono_time) + TCP_CONNECTION_TIMEOUT;
769 769
770 return temp; 770 return temp;
771} 771}
@@ -949,13 +949,13 @@ static bool tcp_process_packet(TCP_Client_Connection *conn, void *userdata)
949 return true; 949 return true;
950} 950}
951 951
952static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata) 952static int do_confirmed_TCP(TCP_Client_Connection *conn, const Mono_Time *mono_time, void *userdata)
953{ 953{
954 client_send_pending_data(conn); 954 client_send_pending_data(conn);
955 tcp_send_ping_response(conn); 955 tcp_send_ping_response(conn);
956 tcp_send_ping_request(conn); 956 tcp_send_ping_request(conn);
957 957
958 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { 958 if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) {
959 uint64_t ping_id = random_u64(); 959 uint64_t ping_id = random_u64();
960 960
961 if (!ping_id) { 961 if (!ping_id) {
@@ -965,10 +965,10 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
965 conn->ping_request_id = ping_id; 965 conn->ping_request_id = ping_id;
966 conn->ping_id = ping_id; 966 conn->ping_id = ping_id;
967 tcp_send_ping_request(conn); 967 tcp_send_ping_request(conn);
968 conn->last_pinged = unix_time(); 968 conn->last_pinged = mono_time_get(mono_time);
969 } 969 }
970 970
971 if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { 971 if (conn->ping_id && mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_TIMEOUT)) {
972 conn->status = TCP_CLIENT_DISCONNECTED; 972 conn->status = TCP_CLIENT_DISCONNECTED;
973 return 0; 973 return 0;
974 } 974 }
@@ -983,7 +983,7 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
983 983
984/* Run the TCP connection 984/* Run the TCP connection
985 */ 985 */
986void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata) 986void do_TCP_connection(Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, void *userdata)
987{ 987{
988 if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) { 988 if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) {
989 return; 989 return;
@@ -1059,10 +1059,10 @@ void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata)
1059 } 1059 }
1060 1060
1061 if (tcp_connection->status == TCP_CLIENT_CONFIRMED) { 1061 if (tcp_connection->status == TCP_CLIENT_CONFIRMED) {
1062 do_confirmed_TCP(tcp_connection, userdata); 1062 do_confirmed_TCP(tcp_connection, mono_time, userdata);
1063 } 1063 }
1064 1064
1065 if (tcp_connection->kill_at <= unix_time()) { 1065 if (tcp_connection->kill_at <= mono_time_get(mono_time)) {
1066 tcp_connection->status = TCP_CLIENT_DISCONNECTED; 1066 tcp_connection->status = TCP_CLIENT_DISCONNECTED;
1067 } 1067 }
1068} 1068}
diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h
index 6d1cbb3b..38c6e01e 100644
--- a/toxcore/TCP_client.h
+++ b/toxcore/TCP_client.h
@@ -64,12 +64,12 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value);
64 64
65/* Create new TCP connection to ip_port/public_key 65/* Create new TCP connection to ip_port/public_key
66 */ 66 */
67TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key, 67TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip_port, const uint8_t *public_key,
68 const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info); 68 const uint8_t *self_public_key, const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info);
69 69
70/* Run the TCP connection 70/* Run the TCP connection
71 */ 71 */
72void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata); 72void do_TCP_connection(Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, void *userdata);
73 73
74/* Kill the TCP connection 74/* Kill the TCP connection
75 */ 75 */
diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c
index 6763328d..0c388a39 100644
--- a/toxcore/TCP_connection.c
+++ b/toxcore/TCP_connection.c
@@ -36,6 +36,7 @@
36 36
37 37
38struct TCP_Connections { 38struct TCP_Connections {
39 Mono_Time *mono_time;
39 DHT *dht; 40 DHT *dht;
40 41
41 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; 42 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
@@ -794,8 +795,8 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec
794 uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE]; 795 uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
795 memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE); 796 memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
796 kill_TCP_connection(tcp_con->connection); 797 kill_TCP_connection(tcp_con->connection);
797 tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, 798 tcp_con->connection = new_TCP_connection(tcp_c->mono_time, ip_port, relay_pk, tcp_c->self_public_key,
798 &tcp_c->proxy_info); 799 tcp_c->self_secret_key, &tcp_c->proxy_info);
799 800
800 if (!tcp_con->connection) { 801 if (!tcp_con->connection) {
801 kill_tcp_relay_connection(tcp_c, tcp_connections_number); 802 kill_tcp_relay_connection(tcp_c, tcp_connections_number);
@@ -884,7 +885,7 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti
884 return -1; 885 return -1;
885 } 886 }
886 887
887 tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key, 888 tcp_con->connection = new_TCP_connection(tcp_c->mono_time, tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key,
888 tcp_c->self_secret_key, &tcp_c->proxy_info); 889 tcp_c->self_secret_key, &tcp_c->proxy_info);
889 890
890 if (!tcp_con->connection) { 891 if (!tcp_con->connection) {
@@ -1122,7 +1123,7 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe
1122 1123
1123 /* If this connection isn't used by any connection, we don't need to wait for them to come online. */ 1124 /* If this connection isn't used by any connection, we don't need to wait for them to come online. */
1124 if (sent) { 1125 if (sent) {
1125 tcp_con->connected_time = unix_time(); 1126 tcp_con->connected_time = mono_time_get(tcp_c->mono_time);
1126 } else { 1127 } else {
1127 tcp_con->connected_time = 0; 1128 tcp_con->connected_time = 0;
1128 } 1129 }
@@ -1155,8 +1156,8 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const
1155 1156
1156 TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number]; 1157 TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number];
1157 1158
1158 tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, 1159 tcp_con->connection = new_TCP_connection(tcp_c->mono_time, ip_port, relay_pk, tcp_c->self_public_key,
1159 &tcp_c->proxy_info); 1160 tcp_c->self_secret_key, &tcp_c->proxy_info);
1160 1161
1161 if (!tcp_con->connection) { 1162 if (!tcp_con->connection) {
1162 return -1; 1163 return -1;
@@ -1216,7 +1217,7 @@ int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_numb
1216 1217
1217 if (tcp_con->status == TCP_CONN_CONNECTED) { 1218 if (tcp_con->status == TCP_CONN_CONNECTED) {
1218 if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) { 1219 if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
1219 tcp_con->connected_time = unix_time(); 1220 tcp_con->connected_time = mono_time_get(tcp_c->mono_time);
1220 } 1221 }
1221 } 1222 }
1222 1223
@@ -1391,7 +1392,7 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
1391 * 1392 *
1392 * Returns NULL on failure. 1393 * Returns NULL on failure.
1393 */ 1394 */
1394TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info) 1395TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret_key, TCP_Proxy_Info *proxy_info)
1395{ 1396{
1396 if (secret_key == nullptr) { 1397 if (secret_key == nullptr) {
1397 return nullptr; 1398 return nullptr;
@@ -1403,6 +1404,8 @@ TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *
1403 return nullptr; 1404 return nullptr;
1404 } 1405 }
1405 1406
1407 temp->mono_time = mono_time;
1408
1406 memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE); 1409 memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
1407 crypto_derive_public_key(temp->self_public_key, temp->self_secret_key); 1410 crypto_derive_public_key(temp->self_public_key, temp->self_secret_key);
1408 temp->proxy_info = *proxy_info; 1411 temp->proxy_info = *proxy_info;
@@ -1419,7 +1422,7 @@ static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata)
1419 1422
1420 if (tcp_con) { 1423 if (tcp_con) {
1421 if (tcp_con->status != TCP_CONN_SLEEPING) { 1424 if (tcp_con->status != TCP_CONN_SLEEPING) {
1422 do_TCP_connection(tcp_con->connection, userdata); 1425 do_TCP_connection(tcp_c->mono_time, tcp_con->connection, userdata);
1423 1426
1424 /* callbacks can change TCP connection address. */ 1427 /* callbacks can change TCP connection address. */
1425 tcp_con = get_tcp_connection(tcp_c, i); 1428 tcp_con = get_tcp_connection(tcp_c, i);
@@ -1443,7 +1446,7 @@ static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata)
1443 1446
1444 if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count 1447 if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count
1445 && tcp_con->lock_count == tcp_con->sleep_count 1448 && tcp_con->lock_count == tcp_con->sleep_count
1446 && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { 1449 && mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
1447 sleep_tcp_relay_connection(tcp_c, i); 1450 sleep_tcp_relay_connection(tcp_c, i);
1448 } 1451 }
1449 } 1452 }
@@ -1471,7 +1474,8 @@ static void kill_nonused_tcp(TCP_Connections *tcp_c)
1471 1474
1472 if (tcp_con) { 1475 if (tcp_con) {
1473 if (tcp_con->status == TCP_CONN_CONNECTED) { 1476 if (tcp_con->status == TCP_CONN_CONNECTED) {
1474 if (!tcp_con->onion && !tcp_con->lock_count && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { 1477 if (!tcp_con->onion && !tcp_con->lock_count
1478 && mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
1475 to_kill[num_kill] = i; 1479 to_kill[num_kill] = i;
1476 ++num_kill; 1480 ++num_kill;
1477 } 1481 }
diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h
index 2d99e122..06b35829 100644
--- a/toxcore/TCP_connection.h
+++ b/toxcore/TCP_connection.h
@@ -219,7 +219,7 @@ uint32_t tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_rela
219 * 219 *
220 * Returns NULL on failure. 220 * Returns NULL on failure.
221 */ 221 */
222TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info); 222TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret_key, TCP_Proxy_Info *proxy_info);
223 223
224void do_tcp_connections(TCP_Connections *tcp_c, void *userdata); 224void do_tcp_connections(TCP_Connections *tcp_c, void *userdata);
225void kill_tcp_connections(TCP_Connections *tcp_c); 225void kill_tcp_connections(TCP_Connections *tcp_c);
diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c
index 207a5107..7fe17434 100644
--- a/toxcore/TCP_server.c
+++ b/toxcore/TCP_server.c
@@ -177,7 +177,7 @@ static int kill_accepted(TCP_Server *tcp_server, int index);
177 * return index on success 177 * return index on success
178 * return -1 on failure 178 * return -1 on failure
179 */ 179 */
180static int add_accepted(TCP_Server *tcp_server, const TCP_Secure_Connection *con) 180static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, const TCP_Secure_Connection *con)
181{ 181{
182 int index = get_TCP_connection_index(tcp_server, con->public_key); 182 int index = get_TCP_connection_index(tcp_server, con->public_key);
183 183
@@ -216,7 +216,7 @@ static int add_accepted(TCP_Server *tcp_server, const TCP_Secure_Connection *con
216 tcp_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED; 216 tcp_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED;
217 ++tcp_server->num_accepted_connections; 217 ++tcp_server->num_accepted_connections;
218 tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter; 218 tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter;
219 tcp_server->accepted_connection_array[index].last_pinged = unix_time(); 219 tcp_server->accepted_connection_array[index].last_pinged = mono_time_get(mono_time);
220 tcp_server->accepted_connection_array[index].ping_id = 0; 220 tcp_server->accepted_connection_array[index].ping_id = 0;
221 221
222 return index; 222 return index;
@@ -954,10 +954,11 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint
954} 954}
955 955
956 956
957static int confirm_TCP_connection(TCP_Server *tcp_server, TCP_Secure_Connection *con, const uint8_t *data, 957static int confirm_TCP_connection(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_Secure_Connection *con,
958 const uint8_t *data,
958 uint16_t length) 959 uint16_t length)
959{ 960{
960 int index = add_accepted(tcp_server, con); 961 int index = add_accepted(tcp_server, mono_time, con);
961 962
962 if (index == -1) { 963 if (index == -1) {
963 kill_TCP_secure_connection(con); 964 kill_TCP_secure_connection(con);
@@ -1161,7 +1162,7 @@ static int do_incoming(TCP_Server *tcp_server, uint32_t i)
1161 return -1; 1162 return -1;
1162} 1163}
1163 1164
1164static int do_unconfirmed(TCP_Server *tcp_server, uint32_t i) 1165static int do_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time, uint32_t i)
1165{ 1166{
1166 TCP_Secure_Connection *conn = &tcp_server->unconfirmed_connection_queue[i]; 1167 TCP_Secure_Connection *conn = &tcp_server->unconfirmed_connection_queue[i];
1167 1168
@@ -1182,7 +1183,7 @@ static int do_unconfirmed(TCP_Server *tcp_server, uint32_t i)
1182 return -1; 1183 return -1;
1183 } 1184 }
1184 1185
1185 return confirm_TCP_connection(tcp_server, conn, packet, len); 1186 return confirm_TCP_connection(tcp_server, mono_time, conn, packet, len);
1186} 1187}
1187 1188
1188static bool tcp_process_secure_packet(TCP_Server *tcp_server, uint32_t i) 1189static bool tcp_process_secure_packet(TCP_Server *tcp_server, uint32_t i)
@@ -1221,32 +1222,28 @@ static void do_confirmed_recv(TCP_Server *tcp_server, uint32_t i)
1221#ifndef TCP_SERVER_USE_EPOLL 1222#ifndef TCP_SERVER_USE_EPOLL
1222static void do_TCP_incoming(TCP_Server *tcp_server) 1223static void do_TCP_incoming(TCP_Server *tcp_server)
1223{ 1224{
1224 uint32_t i; 1225 for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
1225
1226 for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
1227 do_incoming(tcp_server, i); 1226 do_incoming(tcp_server, i);
1228 } 1227 }
1229} 1228}
1230 1229
1231static void do_TCP_unconfirmed(TCP_Server *tcp_server) 1230static void do_TCP_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
1232{ 1231{
1233 uint32_t i; 1232 for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
1234 1233 do_unconfirmed(tcp_server, mono_time, i);
1235 for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
1236 do_unconfirmed(tcp_server, i);
1237 } 1234 }
1238} 1235}
1239#endif 1236#endif
1240 1237
1241static void do_TCP_confirmed(TCP_Server *tcp_server) 1238static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time)
1242{ 1239{
1243#ifdef TCP_SERVER_USE_EPOLL 1240#ifdef TCP_SERVER_USE_EPOLL
1244 1241
1245 if (tcp_server->last_run_pinged == unix_time()) { 1242 if (tcp_server->last_run_pinged == mono_time_get(mono_time)) {
1246 return; 1243 return;
1247 } 1244 }
1248 1245
1249 tcp_server->last_run_pinged = unix_time(); 1246 tcp_server->last_run_pinged = mono_time_get(mono_time);
1250#endif 1247#endif
1251 uint32_t i; 1248 uint32_t i;
1252 1249
@@ -1257,7 +1254,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server)
1257 continue; 1254 continue;
1258 } 1255 }
1259 1256
1260 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { 1257 if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) {
1261 uint8_t ping[1 + sizeof(uint64_t)]; 1258 uint8_t ping[1 + sizeof(uint64_t)];
1262 ping[0] = TCP_PACKET_PING; 1259 ping[0] = TCP_PACKET_PING;
1263 uint64_t ping_id = random_u64(); 1260 uint64_t ping_id = random_u64();
@@ -1270,17 +1267,17 @@ static void do_TCP_confirmed(TCP_Server *tcp_server)
1270 int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); 1267 int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1);
1271 1268
1272 if (ret == 1) { 1269 if (ret == 1) {
1273 conn->last_pinged = unix_time(); 1270 conn->last_pinged = mono_time_get(mono_time);
1274 conn->ping_id = ping_id; 1271 conn->ping_id = ping_id;
1275 } else { 1272 } else {
1276 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { 1273 if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) {
1277 kill_accepted(tcp_server, i); 1274 kill_accepted(tcp_server, i);
1278 continue; 1275 continue;
1279 } 1276 }
1280 } 1277 }
1281 } 1278 }
1282 1279
1283 if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { 1280 if (conn->ping_id && mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_TIMEOUT)) {
1284 kill_accepted(tcp_server, i); 1281 kill_accepted(tcp_server, i);
1285 continue; 1282 continue;
1286 } 1283 }
@@ -1296,7 +1293,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server)
1296} 1293}
1297 1294
1298#ifdef TCP_SERVER_USE_EPOLL 1295#ifdef TCP_SERVER_USE_EPOLL
1299static bool tcp_epoll_process(TCP_Server *tcp_server) 1296static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time)
1300{ 1297{
1301#define MAX_EVENTS 16 1298#define MAX_EVENTS 16
1302 struct epoll_event events[MAX_EVENTS]; 1299 struct epoll_event events[MAX_EVENTS];
@@ -1387,7 +1384,7 @@ static bool tcp_epoll_process(TCP_Server *tcp_server)
1387 } 1384 }
1388 1385
1389 case TCP_SOCKET_UNCONFIRMED: { 1386 case TCP_SOCKET_UNCONFIRMED: {
1390 const int index_new = do_unconfirmed(tcp_server, index); 1387 const int index_new = do_unconfirmed(tcp_server, mono_time, index);
1391 1388
1392 if (index_new != -1) { 1389 if (index_new != -1) {
1393 events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP; 1390 events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
@@ -1413,27 +1410,27 @@ static bool tcp_epoll_process(TCP_Server *tcp_server)
1413 return nfds > 0; 1410 return nfds > 0;
1414} 1411}
1415 1412
1416static void do_TCP_epoll(TCP_Server *tcp_server) 1413static void do_TCP_epoll(TCP_Server *tcp_server, const Mono_Time *mono_time)
1417{ 1414{
1418 while (tcp_epoll_process(tcp_server)) { 1415 while (tcp_epoll_process(tcp_server, mono_time)) {
1419 // Keep processing packets until there are no more FDs ready for reading. 1416 // Keep processing packets until there are no more FDs ready for reading.
1420 continue; 1417 continue;
1421 } 1418 }
1422} 1419}
1423#endif 1420#endif
1424 1421
1425void do_TCP_server(TCP_Server *tcp_server) 1422void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time)
1426{ 1423{
1427#ifdef TCP_SERVER_USE_EPOLL 1424#ifdef TCP_SERVER_USE_EPOLL
1428 do_TCP_epoll(tcp_server); 1425 do_TCP_epoll(tcp_server, mono_time);
1429 1426
1430#else 1427#else
1431 do_TCP_accept_new(tcp_server); 1428 do_TCP_accept_new(tcp_server);
1432 do_TCP_incoming(tcp_server); 1429 do_TCP_incoming(tcp_server);
1433 do_TCP_unconfirmed(tcp_server); 1430 do_TCP_unconfirmed(tcp_server, mono_time);
1434#endif 1431#endif
1435 1432
1436 do_TCP_confirmed(tcp_server); 1433 do_TCP_confirmed(tcp_server, mono_time);
1437} 1434}
1438 1435
1439void kill_TCP_server(TCP_Server *tcp_server) 1436void kill_TCP_server(TCP_Server *tcp_server)
diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h
index 632a5e79..77ffd539 100644
--- a/toxcore/TCP_server.h
+++ b/toxcore/TCP_server.h
@@ -87,7 +87,7 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uin
87 87
88/* Run the TCP_server 88/* Run the TCP_server
89 */ 89 */
90void do_TCP_server(TCP_Server *tcp_server); 90void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time);
91 91
92/* Kill the TCP server 92/* Kill the TCP server
93 */ 93 */
diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c
index 4d245871..f8b0ccf1 100644
--- a/toxcore/friend_connection.c
+++ b/toxcore/friend_connection.c
@@ -74,6 +74,7 @@ typedef struct Friend_Conn {
74 74
75 75
76struct Friend_Connections { 76struct Friend_Connections {
77 const Mono_Time *mono_time;
77 Net_Crypto *net_crypto; 78 Net_Crypto *net_crypto;
78 DHT *dht; 79 DHT *dht;
79 Onion_Client *onion_c; 80 Onion_Client *onion_c;
@@ -298,7 +299,7 @@ static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)
298 ++length; 299 ++length;
299 300
300 if (write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, data, length, 0) != -1) { 301 if (write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, data, length, 0) != -1) {
301 friend_con->share_relays_lastsent = unix_time(); 302 friend_con->share_relays_lastsent = mono_time_get(fr_c->mono_time);
302 return 1; 303 return 1;
303 } 304 }
304 305
@@ -339,7 +340,7 @@ static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
339 340
340 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1); 341 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1);
341 friend_con->dht_ip_port = ip_port; 342 friend_con->dht_ip_port = ip_port;
342 friend_con->dht_ip_port_lastrecv = unix_time(); 343 friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time);
343 344
344 if (friend_con->hosting_tcp_relay) { 345 if (friend_con->hosting_tcp_relay) {
345 friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk); 346 friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk);
@@ -355,7 +356,7 @@ static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint
355 return; 356 return;
356 } 357 }
357 358
358 friend_con->dht_pk_lastrecv = unix_time(); 359 friend_con->dht_pk_lastrecv = mono_time_get(fr_c->mono_time);
359 360
360 if (friend_con->dht_lock) { 361 if (friend_con->dht_lock) {
361 if (dht_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) { 362 if (dht_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) {
@@ -384,13 +385,13 @@ static int handle_status(void *object, int number, uint8_t status, void *userdat
384 if (status) { /* Went online. */ 385 if (status) { /* Went online. */
385 status_changed = 1; 386 status_changed = 1;
386 friend_con->status = FRIENDCONN_STATUS_CONNECTED; 387 friend_con->status = FRIENDCONN_STATUS_CONNECTED;
387 friend_con->ping_lastrecv = unix_time(); 388 friend_con->ping_lastrecv = mono_time_get(fr_c->mono_time);
388 friend_con->share_relays_lastsent = 0; 389 friend_con->share_relays_lastsent = 0;
389 onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); 390 onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
390 } else { /* Went offline. */ 391 } else { /* Went offline. */
391 if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) { 392 if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) {
392 status_changed = 1; 393 status_changed = 1;
393 friend_con->dht_pk_lastrecv = unix_time(); 394 friend_con->dht_pk_lastrecv = mono_time_get(fr_c->mono_time);
394 onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); 395 onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
395 } 396 }
396 397
@@ -463,7 +464,7 @@ static int handle_packet(void *object, int number, const uint8_t *data, uint16_t
463 } 464 }
464 465
465 if (data[0] == PACKET_ID_ALIVE) { 466 if (data[0] == PACKET_ID_ALIVE) {
466 friend_con->ping_lastrecv = unix_time(); 467 friend_con->ping_lastrecv = mono_time_get(fr_c->mono_time);
467 return 0; 468 return 0;
468 } 469 }
469 470
@@ -558,7 +559,7 @@ static int handle_new_connections(void *object, New_Connection *n_c)
558 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0); 559 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
559 } else { 560 } else {
560 friend_con->dht_ip_port = n_c->source; 561 friend_con->dht_ip_port = n_c->source;
561 friend_con->dht_ip_port_lastrecv = unix_time(); 562 friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time);
562 } 563 }
563 564
564 if (public_key_cmp(friend_con->dht_temp_pk, n_c->dht_public_key) != 0) { 565 if (public_key_cmp(friend_con->dht_temp_pk, n_c->dht_public_key) != 0) {
@@ -613,7 +614,7 @@ static int send_ping(const Friend_Connections *fr_c, int friendcon_id)
613 const int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0); 614 const int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0);
614 615
615 if (ret != -1) { 616 if (ret != -1) {
616 friend_con->ping_lastsent = unix_time(); 617 friend_con->ping_lastsent = mono_time_get(fr_c->mono_time);
617 return 0; 618 return 0;
618 } 619 }
619 620
@@ -850,7 +851,8 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3
850} 851}
851 852
852/* Create new friend_connections instance. */ 853/* Create new friend_connections instance. */
853Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled) 854Friend_Connections *new_friend_connections(const Mono_Time *mono_time, Onion_Client *onion_c,
855 bool local_discovery_enabled)
854{ 856{
855 if (onion_c == nullptr) { 857 if (onion_c == nullptr) {
856 return nullptr; 858 return nullptr;
@@ -862,6 +864,7 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_dis
862 return nullptr; 864 return nullptr;
863 } 865 }
864 866
867 temp->mono_time = mono_time;
865 temp->dht = onion_get_dht(onion_c); 868 temp->dht = onion_get_dht(onion_c);
866 temp->net_crypto = onion_get_net_crypto(onion_c); 869 temp->net_crypto = onion_get_net_crypto(onion_c);
867 temp->onion_c = onion_c; 870 temp->onion_c = onion_c;
@@ -881,7 +884,7 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_dis
881/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ 884/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
882static void lan_discovery(Friend_Connections *fr_c) 885static void lan_discovery(Friend_Connections *fr_c)
883{ 886{
884 if (fr_c->last_lan_discovery + LAN_DISCOVERY_INTERVAL < unix_time()) { 887 if (fr_c->last_lan_discovery + LAN_DISCOVERY_INTERVAL < mono_time_get(fr_c->mono_time)) {
885 const uint16_t first = fr_c->next_lan_port; 888 const uint16_t first = fr_c->next_lan_port;
886 uint16_t last = first + PORTS_PER_DISCOVERY; 889 uint16_t last = first + PORTS_PER_DISCOVERY;
887 last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last; 890 last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last;
@@ -896,14 +899,14 @@ static void lan_discovery(Friend_Connections *fr_c)
896 899
897 // Don't include default port in port range 900 // Don't include default port in port range
898 fr_c->next_lan_port = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1; 901 fr_c->next_lan_port = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1;
899 fr_c->last_lan_discovery = unix_time(); 902 fr_c->last_lan_discovery = mono_time_get(fr_c->mono_time);
900 } 903 }
901} 904}
902 905
903/* main friend_connections loop. */ 906/* main friend_connections loop. */
904void do_friend_connections(Friend_Connections *fr_c, void *userdata) 907void do_friend_connections(Friend_Connections *fr_c, void *userdata)
905{ 908{
906 const uint64_t temp_time = unix_time(); 909 const uint64_t temp_time = mono_time_get(fr_c->mono_time);
907 910
908 for (uint32_t i = 0; i < fr_c->num_cons; ++i) { 911 for (uint32_t i = 0; i < fr_c->num_cons; ++i) {
909 Friend_Conn *const friend_con = get_conn(fr_c, i); 912 Friend_Conn *const friend_con = get_conn(fr_c, i);
diff --git a/toxcore/friend_connection.h b/toxcore/friend_connection.h
index 024befee..06d7a123 100644
--- a/toxcore/friend_connection.h
+++ b/toxcore/friend_connection.h
@@ -158,7 +158,8 @@ typedef int fr_request_cb(void *object, const uint8_t *source_pubkey, const uint
158void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_request_callback, void *object); 158void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_request_callback, void *object);
159 159
160/* Create new friend_connections instance. */ 160/* Create new friend_connections instance. */
161Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled); 161Friend_Connections *new_friend_connections(const Mono_Time *mono_time, Onion_Client *onion_c,
162 bool local_discovery_enabled);
162 163
163/* main friend_connections loop. */ 164/* main friend_connections loop. */
164void do_friend_connections(Friend_Connections *fr_c, void *userdata); 165void do_friend_connections(Friend_Connections *fr_c, void *userdata);
diff --git a/toxcore/group.c b/toxcore/group.c
index 20075c8b..11467605 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -497,7 +497,7 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p
497 id_copy(g->group[g->numpeers].temp_pk, temp_pk); 497 id_copy(g->group[g->numpeers].temp_pk, temp_pk);
498 g->group[g->numpeers].peer_number = peer_number; 498 g->group[g->numpeers].peer_number = peer_number;
499 499
500 g->group[g->numpeers].last_recv = unix_time(); 500 g->group[g->numpeers].last_recv = mono_time_get(g_c->mono_time);
501 ++g->numpeers; 501 ++g->numpeers;
502 502
503 add_to_closest(g_c, groupnumber, real_pk, temp_pk); 503 add_to_closest(g_c, groupnumber, real_pk, temp_pk);
@@ -2158,7 +2158,7 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
2158 return; 2158 return;
2159 } 2159 }
2160 2160
2161 g->group[index].last_recv = unix_time(); 2161 g->group[index].last_recv = mono_time_get(g_c->mono_time);
2162 } 2162 }
2163 break; 2163 break;
2164 2164
@@ -2508,9 +2508,9 @@ static int ping_groupchat(Group_Chats *g_c, uint32_t groupnumber)
2508 return -1; 2508 return -1;
2509 } 2509 }
2510 2510
2511 if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) { 2511 if (mono_time_is_timeout(g_c->mono_time, g->last_sent_ping, GROUP_PING_INTERVAL)) {
2512 if (group_ping_send(g_c, groupnumber) != -1) { /* Ping */ 2512 if (group_ping_send(g_c, groupnumber) != -1) { /* Ping */
2513 g->last_sent_ping = unix_time(); 2513 g->last_sent_ping = mono_time_get(g_c->mono_time);
2514 } 2514 }
2515 } 2515 }
2516 2516
@@ -2526,7 +2526,8 @@ static int groupchat_clear_timedout(Group_Chats *g_c, uint32_t groupnumber, void
2526 } 2526 }
2527 2527
2528 for (uint32_t i = 0; i < g->numpeers; ++i) { 2528 for (uint32_t i = 0; i < g->numpeers; ++i) {
2529 if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) { 2529 if (g->peer_number != g->group[i].peer_number
2530 && mono_time_is_timeout(g_c->mono_time, g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) {
2530 delpeer(g_c, groupnumber, i, userdata); 2531 delpeer(g_c, groupnumber, i, userdata);
2531 } 2532 }
2532 2533
@@ -2556,7 +2557,7 @@ void send_name_all_groups(Group_Chats *g_c)
2556} 2557}
2557 2558
2558/* Create new groupchat instance. */ 2559/* Create new groupchat instance. */
2559Group_Chats *new_groupchats(Messenger *m) 2560Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m)
2560{ 2561{
2561 if (!m) { 2562 if (!m) {
2562 return nullptr; 2563 return nullptr;
@@ -2568,6 +2569,7 @@ Group_Chats *new_groupchats(Messenger *m)
2568 return nullptr; 2569 return nullptr;
2569 } 2570 }
2570 2571
2572 temp->mono_time = mono_time;
2571 temp->m = m; 2573 temp->m = m;
2572 temp->fr_c = m->fr_c; 2574 temp->fr_c = m->fr_c;
2573 m->conferences_object = temp; 2575 m->conferences_object = temp;
diff --git a/toxcore/group.h b/toxcore/group.h
index 175999ae..90e7e924 100644
--- a/toxcore/group.h
+++ b/toxcore/group.h
@@ -172,6 +172,8 @@ typedef struct Group_Lossy_Handler {
172} Group_Lossy_Handler; 172} Group_Lossy_Handler;
173 173
174typedef struct Group_Chats { 174typedef struct Group_Chats {
175 const Mono_Time *mono_time;
176
175 Messenger *m; 177 Messenger *m;
176 Friend_Connections *fr_c; 178 Friend_Connections *fr_c;
177 179
@@ -433,7 +435,7 @@ int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_
433int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function); 435int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function);
434 436
435/* Create new groupchat instance. */ 437/* Create new groupchat instance. */
436Group_Chats *new_groupchats(Messenger *m); 438Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m);
437 439
438/* main groupchats loop. */ 440/* main groupchats loop. */
439void do_groupchats(Group_Chats *g_c, void *userdata); 441void do_groupchats(Group_Chats *g_c, void *userdata);
diff --git a/toxcore/mono_time.c b/toxcore/mono_time.c
index 0beb7254..3c415420 100644
--- a/toxcore/mono_time.c
+++ b/toxcore/mono_time.c
@@ -41,6 +41,8 @@ Mono_Time *mono_time_new(void)
41 monotime->time = 0; 41 monotime->time = 0;
42 monotime->base_time = 0; 42 monotime->base_time = 0;
43 43
44 mono_time_update(monotime);
45
44 return monotime; 46 return monotime;
45} 47}
46 48
@@ -71,27 +73,6 @@ bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_
71 73
72//!TOKSTYLE- 74//!TOKSTYLE-
73// No global mutable state in Tokstyle. 75// No global mutable state in Tokstyle.
74static Mono_Time global_time;
75//!TOKSTYLE+
76
77/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of
78 * unix_time() may fail to increase monotonically with increasing time */
79void unix_time_update(void)
80{
81 mono_time_update(&global_time);
82}
83uint64_t unix_time(void)
84{
85 return mono_time_get(&global_time);
86}
87int is_timeout(uint64_t timestamp, uint64_t timeout)
88{
89 return mono_time_is_timeout(&global_time, timestamp, timeout);
90}
91
92
93//!TOKSTYLE-
94// No global mutable state in Tokstyle.
95#ifdef OS_WIN32 76#ifdef OS_WIN32
96static uint64_t last_monotime; 77static uint64_t last_monotime;
97static uint64_t add_monotime; 78static uint64_t add_monotime;
diff --git a/toxcore/mono_time.h b/toxcore/mono_time.h
index 97759560..1d2dd539 100644
--- a/toxcore/mono_time.h
+++ b/toxcore/mono_time.h
@@ -8,7 +8,39 @@
8extern "C" { 8extern "C" {
9#endif 9#endif
10 10
11#ifndef MONO_TIME_DEFINED
12#define MONO_TIME_DEFINED
13/**
14 * The timer portion of the toxcore event loop.
15 *
16 * We update the time exactly once per tox_iterate call. Programs built on lower
17 * level APIs such as the DHT bootstrap node must update the time manually in
18 * each iteration.
19 *
20 * Time is kept per Tox instance, not globally, even though "time" as a concept
21 * is global. This is because by definition `mono_time` represents the time at
22 * the start of an iteration, and also by definition the time when all network
23 * events for the current iteration occurred. This affects mainly two situations:
24 *
25 * 1. Two timers started in the same iteration: e.g. two timers set to expire in
26 * 10 seconds will both expire at the same time, i.e. about 10 seconds later.
27 * If the time were global, `mono_time` would be a random number that is
28 * either the time at the start of an iteration, or 1 second later (since the
29 * timer resolution is 1 second). This can happen when one update happens at
30 * e.g. 10:00:00.995 and a few milliseconds later a concurrently running
31 * instance updates the time at 10:00:01.005, making one timer expire a
32 * second after the other.
33 * 2. One timer based on an event: if we want to encode a behaviour of a timer
34 * expiring e.g. 10 seconds after a network event occurred, we simply start a
35 * timer in the event handler. If a concurrent instance updates the time
36 * underneath us, it may instead expire 9 seconds after the event.
37 *
38 * Both these situations cause incorrect behaviour randomly. In practice,
39 * toxcore is somewhat robust against strange timer behaviour, but the
40 * implementation should at least theoretically match the specification.
41 */
11typedef struct Mono_Time Mono_Time; 42typedef struct Mono_Time Mono_Time;
43#endif /* MONO_TIME_DEFINED */
12 44
13Mono_Time *mono_time_new(void); 45Mono_Time *mono_time_new(void);
14void mono_time_free(Mono_Time *monotime); 46void mono_time_free(Mono_Time *monotime);
@@ -17,11 +49,6 @@ void mono_time_update(Mono_Time *monotime);
17uint64_t mono_time_get(const Mono_Time *monotime); 49uint64_t mono_time_get(const Mono_Time *monotime);
18bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_t timeout); 50bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_t timeout);
19 51
20// TODO(#405): Use per-tox monotime, delete these functions.
21void unix_time_update(void);
22uint64_t unix_time(void);
23int is_timeout(uint64_t timestamp, uint64_t timeout);
24
25/* return current monotonic time in milliseconds (ms). */ 52/* return current monotonic time in milliseconds (ms). */
26uint64_t current_time_monotonic(void); 53uint64_t current_time_monotonic(void);
27 54
diff --git a/toxcore/mono_time_test.cc b/toxcore/mono_time_test.cc
index 5ad91322..3e241b17 100644
--- a/toxcore/mono_time_test.cc
+++ b/toxcore/mono_time_test.cc
@@ -5,26 +5,34 @@
5namespace { 5namespace {
6 6
7TEST(Util, UnixTimeIncreasesOverTime) { 7TEST(Util, UnixTimeIncreasesOverTime) {
8 unix_time_update(); 8 Mono_Time *mono_time = mono_time_new();
9 uint64_t const start = unix_time();
10 9
11 while (start == unix_time()) { 10 mono_time_update(mono_time);
12 unix_time_update(); 11 uint64_t const start = mono_time_get(mono_time);
12
13 while (start == mono_time_get(mono_time)) {
14 mono_time_update(mono_time);
13 } 15 }
14 16
15 uint64_t const end = unix_time(); 17 uint64_t const end = mono_time_get(mono_time);
16 EXPECT_GT(end, start); 18 EXPECT_GT(end, start);
19
20 mono_time_free(mono_time);
17} 21}
18 22
19TEST(Util, IsTimeout) { 23TEST(Util, IsTimeout) {
20 uint64_t const start = unix_time(); 24 Mono_Time *mono_time = mono_time_new();
21 EXPECT_FALSE(is_timeout(start, 1));
22 25
23 while (start == unix_time()) { 26 uint64_t const start = mono_time_get(mono_time);
24 unix_time_update(); 27 EXPECT_FALSE(mono_time_is_timeout(mono_time, start, 1));
28
29 while (start == mono_time_get(mono_time)) {
30 mono_time_update(mono_time);
25 } 31 }
26 32
27 EXPECT_TRUE(is_timeout(start, 1)); 33 EXPECT_TRUE(mono_time_is_timeout(mono_time, start, 1));
34
35 mono_time_free(mono_time);
28} 36}
29 37
30} // namespace 38} // namespace
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index bd214b91..a577b6c7 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -134,6 +134,7 @@ typedef struct Crypto_Connection {
134 134
135struct Net_Crypto { 135struct Net_Crypto {
136 const Logger *log; 136 const Logger *log;
137 Mono_Time *mono_time;
137 138
138 DHT *dht; 139 DHT *dht;
139 TCP_Connections *tcp_c; 140 TCP_Connections *tcp_c;
@@ -248,10 +249,11 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, uint8_t *
248 * return -1 on failure. 249 * return -1 on failure.
249 * return 0 on success. 250 * return 0 on success.
250 */ 251 */
251static int create_cookie(const Logger *log, uint8_t *cookie, const uint8_t *bytes, const uint8_t *encryption_key) 252static int create_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes,
253 const uint8_t *encryption_key)
252{ 254{
253 uint8_t contents[COOKIE_CONTENTS_LENGTH]; 255 uint8_t contents[COOKIE_CONTENTS_LENGTH];
254 const uint64_t temp_time = unix_time(); 256 const uint64_t temp_time = mono_time_get(mono_time);
255 memcpy(contents, &temp_time, sizeof(temp_time)); 257 memcpy(contents, &temp_time, sizeof(temp_time));
256 memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH); 258 memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH);
257 random_nonce(cookie); 259 random_nonce(cookie);
@@ -269,7 +271,8 @@ static int create_cookie(const Logger *log, uint8_t *cookie, const uint8_t *byte
269 * return -1 on failure. 271 * return -1 on failure.
270 * return 0 on success. 272 * return 0 on success.
271 */ 273 */
272static int open_cookie(const Logger *log, uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key) 274static int open_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie,
275 const uint8_t *encryption_key)
273{ 276{
274 uint8_t contents[COOKIE_CONTENTS_LENGTH]; 277 uint8_t contents[COOKIE_CONTENTS_LENGTH];
275 const int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE, 278 const int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE,
@@ -281,7 +284,7 @@ static int open_cookie(const Logger *log, uint8_t *bytes, const uint8_t *cookie,
281 284
282 uint64_t cookie_time; 285 uint64_t cookie_time;
283 memcpy(&cookie_time, contents, sizeof(cookie_time)); 286 memcpy(&cookie_time, contents, sizeof(cookie_time));
284 const uint64_t temp_time = unix_time(); 287 const uint64_t temp_time = mono_time_get(mono_time);
285 288
286 if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) { 289 if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) {
287 return -1; 290 return -1;
@@ -307,7 +310,7 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui
307 memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE); 310 memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
308 uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; 311 uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
309 312
310 if (create_cookie(c->log, plain, cookie_plain, c->secret_symmetric_key) != 0) { 313 if (create_cookie(c->log, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) {
311 return -1; 314 return -1;
312 } 315 }
313 316
@@ -475,8 +478,8 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u
475 memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); 478 memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE);
476 memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); 479 memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
477 480
478 if (create_cookie(c->log, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, cookie_plain, 481 if (create_cookie(c->log, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE,
479 c->secret_symmetric_key) != 0) { 482 cookie_plain, c->secret_symmetric_key) != 0) {
480 return -1; 483 return -1;
481 } 484 }
482 485
@@ -521,7 +524,7 @@ static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t
521 524
522 uint8_t cookie_plain[COOKIE_DATA_LENGTH]; 525 uint8_t cookie_plain[COOKIE_DATA_LENGTH];
523 526
524 if (open_cookie(c->log, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { 527 if (open_cookie(c->log, c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {
525 return -1; 528 return -1;
526 } 529 }
527 530
@@ -620,7 +623,7 @@ static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)
620 return empty; 623 return empty;
621 } 624 }
622 625
623 uint64_t current_time = unix_time(); 626 const uint64_t current_time = mono_time_get(c->mono_time);
624 bool v6 = 0, v4 = 0; 627 bool v6 = 0, v4 = 0;
625 628
626 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) { 629 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
@@ -681,13 +684,13 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t
681 } 684 }
682 685
683 // TODO(irungentoo): a better way of sending packets directly to confirm the others ip. 686 // TODO(irungentoo): a better way of sending packets directly to confirm the others ip.
684 uint64_t current_time = unix_time(); 687 const uint64_t current_time = mono_time_get(c->mono_time);
685 688
686 if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) > current_time && length < 96) 689 if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) > current_time && length < 96)
687 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { 690 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) {
688 if ((uint32_t)sendpacket(dht_get_net(c->dht), ip_port, data, length) == length) { 691 if ((uint32_t)sendpacket(dht_get_net(c->dht), ip_port, data, length) == length) {
689 direct_send_attempt = 1; 692 direct_send_attempt = 1;
690 conn->direct_send_attempt_time = unix_time(); 693 conn->direct_send_attempt_time = mono_time_get(c->mono_time);
691 } 694 }
692 } 695 }
693 } 696 }
@@ -1841,9 +1844,9 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id,
1841 } 1844 }
1842 1845
1843 if (net_family_is_ipv4(source.ip.family)) { 1846 if (net_family_is_ipv4(source.ip.family)) {
1844 conn->direct_lastrecv_timev4 = unix_time(); 1847 conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time);
1845 } else { 1848 } else {
1846 conn->direct_lastrecv_timev6 = unix_time(); 1849 conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time);
1847 } 1850 }
1848 1851
1849 return 0; 1852 return 0;
@@ -2069,7 +2072,7 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,
2069 return -1; 2072 return -1;
2070 } 2073 }
2071 2074
2072 const uint64_t direct_lastrecv_time = connected ? unix_time() : 0; 2075 const uint64_t direct_lastrecv_time = connected ? mono_time_get(c->mono_time) : 0;
2073 2076
2074 if (net_family_is_ipv4(ip_port.ip.family)) { 2077 if (net_family_is_ipv4(ip_port.ip.family)) {
2075 conn->direct_lastrecv_timev4 = direct_lastrecv_time; 2078 conn->direct_lastrecv_timev4 = direct_lastrecv_time;
@@ -2409,9 +2412,9 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet
2409 pthread_mutex_lock(&conn->mutex); 2412 pthread_mutex_lock(&conn->mutex);
2410 2413
2411 if (net_family_is_ipv4(source.ip.family)) { 2414 if (net_family_is_ipv4(source.ip.family)) {
2412 conn->direct_lastrecv_timev4 = unix_time(); 2415 conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time);
2413 } else { 2416 } else {
2414 conn->direct_lastrecv_timev6 = unix_time(); 2417 conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time);
2415 } 2418 }
2416 2419
2417 pthread_mutex_unlock(&conn->mutex); 2420 pthread_mutex_unlock(&conn->mutex);
@@ -2877,7 +2880,7 @@ Crypto_Conn_State crypto_connection_status(const Net_Crypto *c, int crypt_connec
2877 if (direct_connected) { 2880 if (direct_connected) {
2878 *direct_connected = 0; 2881 *direct_connected = 0;
2879 2882
2880 uint64_t current_time = unix_time(); 2883 const uint64_t current_time = mono_time_get(c->mono_time);
2881 2884
2882 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) { 2885 if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
2883 *direct_connected = 1; 2886 *direct_connected = 1;
@@ -2923,7 +2926,7 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk)
2923/* Run this to (re)initialize net_crypto. 2926/* Run this to (re)initialize net_crypto.
2924 * Sets all the global connection variables to their default values. 2927 * Sets all the global connection variables to their default values.
2925 */ 2928 */
2926Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info) 2929Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TCP_Proxy_Info *proxy_info)
2927{ 2930{
2928 if (dht == nullptr) { 2931 if (dht == nullptr) {
2929 return nullptr; 2932 return nullptr;
@@ -2936,8 +2939,9 @@ Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_in
2936 } 2939 }
2937 2940
2938 temp->log = log; 2941 temp->log = log;
2942 temp->mono_time = mono_time;
2939 2943
2940 temp->tcp_c = new_tcp_connections(dht_get_self_secret_key(dht), proxy_info); 2944 temp->tcp_c = new_tcp_connections(mono_time, dht_get_self_secret_key(dht), proxy_info);
2941 2945
2942 if (temp->tcp_c == nullptr) { 2946 if (temp->tcp_c == nullptr) {
2943 free(temp); 2947 free(temp);
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index e40b7bfd..4a1d7f2c 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -343,7 +343,7 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk);
343/* Create new instance of Net_Crypto. 343/* Create new instance of Net_Crypto.
344 * Sets all the global connection variables to their default values. 344 * Sets all the global connection variables to their default values.
345 */ 345 */
346Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info); 346Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TCP_Proxy_Info *proxy_info);
347 347
348/* return the optimal interval in ms for running do_net_crypto. 348/* return the optimal interval in ms for running do_net_crypto.
349 */ 349 */
diff --git a/toxcore/onion.c b/toxcore/onion.c
index 5ba716fd..eceeb9f8 100644
--- a/toxcore/onion.c
+++ b/toxcore/onion.c
@@ -46,9 +46,9 @@
46#define KEY_REFRESH_INTERVAL (2 * 60 * 60) 46#define KEY_REFRESH_INTERVAL (2 * 60 * 60)
47static void change_symmetric_key(Onion *onion) 47static void change_symmetric_key(Onion *onion)
48{ 48{
49 if (is_timeout(onion->timestamp, KEY_REFRESH_INTERVAL)) { 49 if (mono_time_is_timeout(onion->mono_time, onion->timestamp, KEY_REFRESH_INTERVAL)) {
50 new_symmetric_key(onion->secret_symmetric_key); 50 new_symmetric_key(onion->secret_symmetric_key);
51 onion->timestamp = unix_time(); 51 onion->timestamp = mono_time_get(onion->mono_time);
52 } 52 }
53} 53}
54 54
@@ -343,7 +343,8 @@ static int handle_send_initial(void *object, IP_Port source, const uint8_t *pack
343 343
344 uint8_t plain[ONION_MAX_PACKET_SIZE]; 344 uint8_t plain[ONION_MAX_PACKET_SIZE];
345 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; 345 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
346 get_shared_key(&onion->shared_keys_1, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); 346 get_shared_key(onion->mono_time, &onion->shared_keys_1, shared_key, dht_get_self_secret_key(onion->dht),
347 packet + 1 + CRYPTO_NONCE_SIZE);
347 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, 348 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
348 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain); 349 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain);
349 350
@@ -412,7 +413,8 @@ static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, ui
412 413
413 uint8_t plain[ONION_MAX_PACKET_SIZE]; 414 uint8_t plain[ONION_MAX_PACKET_SIZE];
414 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; 415 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
415 get_shared_key(&onion->shared_keys_2, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); 416 get_shared_key(onion->mono_time, &onion->shared_keys_2, shared_key, dht_get_self_secret_key(onion->dht),
417 packet + 1 + CRYPTO_NONCE_SIZE);
416 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, 418 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
417 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain); 419 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain);
418 420
@@ -468,7 +470,8 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui
468 470
469 uint8_t plain[ONION_MAX_PACKET_SIZE]; 471 uint8_t plain[ONION_MAX_PACKET_SIZE];
470 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; 472 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
471 get_shared_key(&onion->shared_keys_3, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); 473 get_shared_key(onion->mono_time, &onion->shared_keys_3, shared_key, dht_get_self_secret_key(onion->dht),
474 packet + 1 + CRYPTO_NONCE_SIZE);
472 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, 475 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
473 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain); 476 length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain);
474 477
@@ -662,7 +665,7 @@ void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *o
662 onion->callback_object = object; 665 onion->callback_object = object;
663} 666}
664 667
665Onion *new_onion(DHT *dht) 668Onion *new_onion(Mono_Time *mono_time, DHT *dht)
666{ 669{
667 if (dht == nullptr) { 670 if (dht == nullptr) {
668 return nullptr; 671 return nullptr;
@@ -676,8 +679,9 @@ Onion *new_onion(DHT *dht)
676 679
677 onion->dht = dht; 680 onion->dht = dht;
678 onion->net = dht_get_net(dht); 681 onion->net = dht_get_net(dht);
682 onion->mono_time = mono_time;
679 new_symmetric_key(onion->secret_symmetric_key); 683 new_symmetric_key(onion->secret_symmetric_key);
680 onion->timestamp = unix_time(); 684 onion->timestamp = mono_time_get(onion->mono_time);
681 685
682 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion); 686 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion);
683 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion); 687 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion);
diff --git a/toxcore/onion.h b/toxcore/onion.h
index 0e025a1c..ea177c70 100644
--- a/toxcore/onion.h
+++ b/toxcore/onion.h
@@ -25,11 +25,13 @@
25#define ONION_H 25#define ONION_H
26 26
27#include "DHT.h" 27#include "DHT.h"
28#include "mono_time.h"
28 29
29typedef int onion_recv_1_cb(void *object, IP_Port dest, const uint8_t *data, uint16_t length); 30typedef int onion_recv_1_cb(void *object, IP_Port dest, const uint8_t *data, uint16_t length);
30 31
31typedef struct Onion { 32typedef struct Onion {
32 DHT *dht; 33 Mono_Time *mono_time;
34 DHT *dht;
33 Networking_Core *net; 35 Networking_Core *net;
34 uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE]; 36 uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
35 uint64_t timestamp; 37 uint64_t timestamp;
@@ -158,7 +160,7 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port
158 */ 160 */
159void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *object); 161void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *object);
160 162
161Onion *new_onion(DHT *dht); 163Onion *new_onion(Mono_Time *mono_time, DHT *dht);
162 164
163void kill_onion(Onion *onion); 165void kill_onion(Onion *onion);
164 166
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c
index d368face..f7f06681 100644
--- a/toxcore/onion_announce.c
+++ b/toxcore/onion_announce.c
@@ -50,6 +50,7 @@ typedef struct Onion_Announce_Entry {
50} Onion_Announce_Entry; 50} Onion_Announce_Entry;
51 51
52struct Onion_Announce { 52struct Onion_Announce {
53 Mono_Time *mono_time;
53 DHT *dht; 54 DHT *dht;
54 Networking_Core *net; 55 Networking_Core *net;
55 Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES]; 56 Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES];
@@ -256,7 +257,7 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)
256 unsigned int i; 257 unsigned int i;
257 258
258 for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) { 259 for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {
259 if (!is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT) 260 if (!mono_time_is_timeout(onion_a->mono_time, onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)
260 && public_key_cmp(onion_a->entries[i].public_key, public_key) == 0) { 261 && public_key_cmp(onion_a->entries[i].public_key, public_key) == 0) {
261 return i; 262 return i;
262 } 263 }
@@ -266,6 +267,7 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)
266} 267}
267 268
268typedef struct Cmp_data { 269typedef struct Cmp_data {
270 const Mono_Time *mono_time;
269 const uint8_t *base_public_key; 271 const uint8_t *base_public_key;
270 Onion_Announce_Entry entry; 272 Onion_Announce_Entry entry;
271} Cmp_data; 273} Cmp_data;
@@ -279,8 +281,8 @@ static int cmp_entry(const void *a, const void *b)
279 Onion_Announce_Entry entry2 = cmp2.entry; 281 Onion_Announce_Entry entry2 = cmp2.entry;
280 const uint8_t *cmp_public_key = cmp1.base_public_key; 282 const uint8_t *cmp_public_key = cmp1.base_public_key;
281 283
282 int t1 = is_timeout(entry1.time, ONION_ANNOUNCE_TIMEOUT); 284 int t1 = mono_time_is_timeout(cmp1.mono_time, entry1.time, ONION_ANNOUNCE_TIMEOUT);
283 int t2 = is_timeout(entry2.time, ONION_ANNOUNCE_TIMEOUT); 285 int t2 = mono_time_is_timeout(cmp1.mono_time, entry2.time, ONION_ANNOUNCE_TIMEOUT);
284 286
285 if (t1 && t2) { 287 if (t1 && t2) {
286 return 0; 288 return 0;
@@ -307,13 +309,15 @@ static int cmp_entry(const void *a, const void *b)
307 return 0; 309 return 0;
308} 310}
309 311
310static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const uint8_t *comp_public_key) 312static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const Mono_Time *mono_time,
313 const uint8_t *comp_public_key)
311{ 314{
312 // Pass comp_public_key to qsort with each Client_data entry, so the 315 // Pass comp_public_key to qsort with each Client_data entry, so the
313 // comparison function can use it as the base of comparison. 316 // comparison function can use it as the base of comparison.
314 VLA(Cmp_data, cmp_list, length); 317 VLA(Cmp_data, cmp_list, length);
315 318
316 for (uint32_t i = 0; i < length; ++i) { 319 for (uint32_t i = 0; i < length; ++i) {
320 cmp_list[i].mono_time = mono_time;
317 cmp_list[i].base_public_key = comp_public_key; 321 cmp_list[i].base_public_key = comp_public_key;
318 cmp_list[i].entry = list[i]; 322 cmp_list[i].entry = list[i];
319 } 323 }
@@ -338,7 +342,7 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui
338 342
339 if (pos == -1) { 343 if (pos == -1) {
340 for (unsigned i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) { 344 for (unsigned i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {
341 if (is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) { 345 if (mono_time_is_timeout(onion_a->mono_time, onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) {
342 pos = i; 346 pos = i;
343 } 347 }
344 } 348 }
@@ -358,9 +362,10 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui
358 onion_a->entries[pos].ret_ip_port = ret_ip_port; 362 onion_a->entries[pos].ret_ip_port = ret_ip_port;
359 memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3); 363 memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3);
360 memcpy(onion_a->entries[pos].data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE); 364 memcpy(onion_a->entries[pos].data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
361 onion_a->entries[pos].time = unix_time(); 365 onion_a->entries[pos].time = mono_time_get(onion_a->mono_time);
362 366
363 sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, dht_get_self_public_key(onion_a->dht)); 367 sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, onion_a->mono_time,
368 dht_get_self_public_key(onion_a->dht));
364 return in_entries(onion_a, public_key); 369 return in_entries(onion_a, public_key);
365} 370}
366 371
@@ -374,7 +379,8 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *
374 379
375 const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE; 380 const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE;
376 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; 381 uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
377 get_shared_key(&onion_a->shared_keys_recv, shared_key, dht_get_self_secret_key(onion_a->dht), packet_public_key); 382 get_shared_key(onion_a->mono_time, &onion_a->shared_keys_recv, shared_key, dht_get_self_secret_key(onion_a->dht),
383 packet_public_key);
378 384
379 uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + 385 uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +
380 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; 386 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
@@ -387,10 +393,10 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t *
387 } 393 }
388 394
389 uint8_t ping_id1[ONION_PING_ID_SIZE]; 395 uint8_t ping_id1[ONION_PING_ID_SIZE];
390 generate_ping_id(onion_a, unix_time(), packet_public_key, source, ping_id1); 396 generate_ping_id(onion_a, mono_time_get(onion_a->mono_time), packet_public_key, source, ping_id1);
391 397
392 uint8_t ping_id2[ONION_PING_ID_SIZE]; 398 uint8_t ping_id2[ONION_PING_ID_SIZE];
393 generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet_public_key, source, ping_id2); 399 generate_ping_id(onion_a, mono_time_get(onion_a->mono_time) + PING_ID_TIMEOUT, packet_public_key, source, ping_id2);
394 400
395 int index; 401 int index;
396 402
@@ -493,7 +499,7 @@ static int handle_data_request(void *object, IP_Port source, const uint8_t *pack
493 return 0; 499 return 0;
494} 500}
495 501
496Onion_Announce *new_onion_announce(DHT *dht) 502Onion_Announce *new_onion_announce(Mono_Time *mono_time, DHT *dht)
497{ 503{
498 if (dht == nullptr) { 504 if (dht == nullptr) {
499 return nullptr; 505 return nullptr;
@@ -505,6 +511,7 @@ Onion_Announce *new_onion_announce(DHT *dht)
505 return nullptr; 511 return nullptr;
506 } 512 }
507 513
514 onion_a->mono_time = mono_time;
508 onion_a->dht = dht; 515 onion_a->dht = dht;
509 onion_a->net = dht_get_net(dht); 516 onion_a->net = dht_get_net(dht);
510 new_symmetric_key(onion_a->secret_bytes); 517 new_symmetric_key(onion_a->secret_bytes);
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h
index 84e76a38..628dc002 100644
--- a/toxcore/onion_announce.h
+++ b/toxcore/onion_announce.h
@@ -120,7 +120,7 @@ int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest
120 const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); 120 const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
121 121
122 122
123Onion_Announce *new_onion_announce(DHT *dht); 123Onion_Announce *new_onion_announce(Mono_Time *mono_time, DHT *dht);
124 124
125void kill_onion_announce(Onion_Announce *onion_a); 125void kill_onion_announce(Onion_Announce *onion_a);
126 126
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index 819bd23f..d3b5cefc 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -113,6 +113,8 @@ typedef struct Onion_Data_Handler {
113} Onion_Data_Handler; 113} Onion_Data_Handler;
114 114
115struct Onion_Client { 115struct Onion_Client {
116 Mono_Time *mono_time;
117
116 DHT *dht; 118 DHT *dht;
117 Net_Crypto *c; 119 Net_Crypto *c;
118 Networking_Core *net; 120 Networking_Core *net;
@@ -316,16 +318,16 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format
316 * return -1 if nodes are suitable for creating a new path. 318 * return -1 if nodes are suitable for creating a new path.
317 * return path number of already existing similar path if one already exists. 319 * return path number of already existing similar path if one already exists.
318 */ 320 */
319static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format *nodes) 321static int is_path_used(const Mono_Time *mono_time, const Onion_Client_Paths *onion_paths, const Node_format *nodes)
320{ 322{
321 unsigned int i; 323 unsigned int i;
322 324
323 for (i = 0; i < NUMBER_ONION_PATHS; ++i) { 325 for (i = 0; i < NUMBER_ONION_PATHS; ++i) {
324 if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) { 326 if (mono_time_is_timeout(mono_time, onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) {
325 continue; 327 continue;
326 } 328 }
327 329
328 if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) { 330 if (mono_time_is_timeout(mono_time, onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) {
329 continue; 331 continue;
330 } 332 }
331 333
@@ -339,7 +341,7 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format
339} 341}
340 342
341/* is path timed out */ 343/* is path timed out */
342static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum) 344static bool path_timed_out(const Mono_Time *mono_time, Onion_Client_Paths *onion_paths, uint32_t pathnum)
343{ 345{
344 pathnum = pathnum % NUMBER_ONION_PATHS; 346 pathnum = pathnum % NUMBER_ONION_PATHS;
345 347
@@ -347,16 +349,16 @@ static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum)
347 uint64_t timeout = is_new ? ONION_PATH_FIRST_TIMEOUT : ONION_PATH_TIMEOUT; 349 uint64_t timeout = is_new ? ONION_PATH_FIRST_TIMEOUT : ONION_PATH_TIMEOUT;
348 350
349 return ((onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES 351 return ((onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES
350 && is_timeout(onion_paths->last_path_used[pathnum], timeout)) 352 && mono_time_is_timeout(mono_time, onion_paths->last_path_used[pathnum], timeout))
351 || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)); 353 || mono_time_is_timeout(mono_time, onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME));
352} 354}
353 355
354/* should node be considered to have timed out */ 356/* should node be considered to have timed out */
355static bool onion_node_timed_out(const Onion_Node *node) 357static bool onion_node_timed_out(const Onion_Node *node, const Mono_Time *mono_time)
356{ 358{
357 return (node->timestamp == 0 359 return (node->timestamp == 0
358 || (node->unsuccessful_pings >= ONION_NODE_MAX_PINGS 360 || (node->unsuccessful_pings >= ONION_NODE_MAX_PINGS
359 && is_timeout(node->last_pinged, ONION_NODE_TIMEOUT))); 361 && mono_time_is_timeout(mono_time, node->last_pinged, ONION_NODE_TIMEOUT)));
360} 362}
361 363
362/* Create a new path or use an old suitable one (if pathnum is valid) 364/* Create a new path or use an old suitable one (if pathnum is valid)
@@ -376,21 +378,21 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
376 pathnum = pathnum % NUMBER_ONION_PATHS; 378 pathnum = pathnum % NUMBER_ONION_PATHS;
377 } 379 }
378 380
379 if (path_timed_out(onion_paths, pathnum)) { 381 if (path_timed_out(onion_c->mono_time, onion_paths, pathnum)) {
380 Node_format nodes[ONION_PATH_LENGTH]; 382 Node_format nodes[ONION_PATH_LENGTH];
381 383
382 if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) { 384 if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) {
383 return -1; 385 return -1;
384 } 386 }
385 387
386 int n = is_path_used(onion_paths, nodes); 388 int n = is_path_used(onion_c->mono_time, onion_paths, nodes);
387 389
388 if (n == -1) { 390 if (n == -1) {
389 if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) { 391 if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) {
390 return -1; 392 return -1;
391 } 393 }
392 394
393 onion_paths->path_creation_time[pathnum] = unix_time(); 395 onion_paths->path_creation_time[pathnum] = mono_time_get(onion_c->mono_time);
394 onion_paths->last_path_success[pathnum] = onion_paths->path_creation_time[pathnum]; 396 onion_paths->last_path_success[pathnum] = onion_paths->path_creation_time[pathnum];
395 onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2; 397 onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2;
396 398
@@ -406,7 +408,7 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
406 } 408 }
407 409
408 if (onion_paths->last_path_used_times[pathnum] < ONION_PATH_MAX_NO_RESPONSE_USES) { 410 if (onion_paths->last_path_used_times[pathnum] < ONION_PATH_MAX_NO_RESPONSE_USES) {
409 onion_paths->last_path_used[pathnum] = unix_time(); 411 onion_paths->last_path_used[pathnum] = mono_time_get(onion_c->mono_time);
410 } 412 }
411 413
412 ++onion_paths->last_path_used_times[pathnum]; 414 ++onion_paths->last_path_used_times[pathnum];
@@ -415,9 +417,9 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
415} 417}
416 418
417/* Does path with path_num exist. */ 419/* Does path with path_num exist. */
418static bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num) 420static bool path_exists(const Mono_Time *mono_time, Onion_Client_Paths *onion_paths, uint32_t path_num)
419{ 421{
420 if (path_timed_out(onion_paths, path_num)) { 422 if (path_timed_out(mono_time, onion_paths, path_num)) {
421 return 0; 423 return 0;
422 } 424 }
423 425
@@ -442,7 +444,7 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t
442 } 444 }
443 445
444 if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) { 446 if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) {
445 onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time(); 447 onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = mono_time_get(onion_c->mono_time);
446 onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0; 448 onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0;
447 449
448 Node_format nodes[ONION_PATH_LENGTH]; 450 Node_format nodes[ONION_PATH_LENGTH];
@@ -521,7 +523,7 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *publ
521 memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE); 523 memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE);
522 memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, &ip_port, sizeof(IP_Port)); 524 memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, &ip_port, sizeof(IP_Port));
523 memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t)); 525 memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));
524 *sendback = ping_array_add(onion_c->announce_ping_array, data, sizeof(data)); 526 *sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data));
525 527
526 if (*sendback == 0) { 528 if (*sendback == 0) {
527 return -1; 529 return -1;
@@ -547,7 +549,7 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u
547 memcpy(&sback, sendback, sizeof(uint64_t)); 549 memcpy(&sback, sendback, sizeof(uint64_t));
548 uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)]; 550 uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
549 551
550 if (ping_array_check(onion_c->announce_ping_array, data, sizeof(data), sback) != sizeof(data)) { 552 if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) {
551 return ~0; 553 return ~0;
552 } 554 }
553 555
@@ -611,6 +613,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
611} 613}
612 614
613typedef struct Onion_Client_Cmp_data { 615typedef struct Onion_Client_Cmp_data {
616 const Mono_Time *mono_time;
614 const uint8_t *base_public_key; 617 const uint8_t *base_public_key;
615 Onion_Node entry; 618 Onion_Node entry;
616} Onion_Client_Cmp_data; 619} Onion_Client_Cmp_data;
@@ -624,8 +627,8 @@ static int onion_client_cmp_entry(const void *a, const void *b)
624 Onion_Node entry2 = cmp2.entry; 627 Onion_Node entry2 = cmp2.entry;
625 const uint8_t *cmp_public_key = cmp1.base_public_key; 628 const uint8_t *cmp_public_key = cmp1.base_public_key;
626 629
627 int t1 = onion_node_timed_out(&entry1); 630 int t1 = onion_node_timed_out(&entry1, cmp1.mono_time);
628 int t2 = onion_node_timed_out(&entry2); 631 int t2 = onion_node_timed_out(&entry2, cmp2.mono_time);
629 632
630 if (t1 && t2) { 633 if (t1 && t2) {
631 return 0; 634 return 0;
@@ -652,13 +655,15 @@ static int onion_client_cmp_entry(const void *a, const void *b)
652 return 0; 655 return 0;
653} 656}
654 657
655static void sort_onion_node_list(Onion_Node *list, unsigned int length, const uint8_t *comp_public_key) 658static void sort_onion_node_list(Onion_Node *list, unsigned int length, const Mono_Time *mono_time,
659 const uint8_t *comp_public_key)
656{ 660{
657 // Pass comp_public_key to qsort with each Client_data entry, so the 661 // Pass comp_public_key to qsort with each Client_data entry, so the
658 // comparison function can use it as the base of comparison. 662 // comparison function can use it as the base of comparison.
659 VLA(Onion_Client_Cmp_data, cmp_list, length); 663 VLA(Onion_Client_Cmp_data, cmp_list, length);
660 664
661 for (uint32_t i = 0; i < length; ++i) { 665 for (uint32_t i = 0; i < length; ++i) {
666 cmp_list[i].mono_time = mono_time;
662 cmp_list[i].base_public_key = comp_public_key; 667 cmp_list[i].base_public_key = comp_public_key;
663 cmp_list[i].entry = list[i]; 668 cmp_list[i].entry = list[i];
664 } 669 }
@@ -695,7 +700,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
695 } 700 }
696 701
697 if (is_stored == 1) { 702 if (is_stored == 1) {
698 onion_c->friends_list[num - 1].last_reported_announced = unix_time(); 703 onion_c->friends_list[num - 1].last_reported_announced = mono_time_get(onion_c->mono_time);
699 } 704 }
700 705
701 list_nodes = onion_c->friends_list[num - 1].clients_list; 706 list_nodes = onion_c->friends_list[num - 1].clients_list;
@@ -703,12 +708,12 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
703 list_length = MAX_ONION_CLIENTS; 708 list_length = MAX_ONION_CLIENTS;
704 } 709 }
705 710
706 sort_onion_node_list(list_nodes, list_length, reference_id); 711 sort_onion_node_list(list_nodes, list_length, onion_c->mono_time, reference_id);
707 712
708 int index = -1, stored = 0; 713 int index = -1, stored = 0;
709 unsigned int i; 714 unsigned int i;
710 715
711 if (onion_node_timed_out(&list_nodes[0]) 716 if (onion_node_timed_out(&list_nodes[0], onion_c->mono_time)
712 || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) { 717 || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) {
713 index = 0; 718 index = 0;
714 } 719 }
@@ -738,24 +743,25 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
738 } 743 }
739 744
740 list_nodes[index].is_stored = is_stored; 745 list_nodes[index].is_stored = is_stored;
741 list_nodes[index].timestamp = unix_time(); 746 list_nodes[index].timestamp = mono_time_get(onion_c->mono_time);
742 list_nodes[index].unsuccessful_pings = 0; 747 list_nodes[index].unsuccessful_pings = 0;
743 748
744 if (!stored) { 749 if (!stored) {
745 list_nodes[index].last_pinged = 0; 750 list_nodes[index].last_pinged = 0;
746 list_nodes[index].added_time = unix_time(); 751 list_nodes[index].added_time = mono_time_get(onion_c->mono_time);
747 } 752 }
748 753
749 list_nodes[index].path_used = path_used; 754 list_nodes[index].path_used = path_used;
750 return 0; 755 return 0;
751} 756}
752 757
753static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *public_key) 758static int good_to_ping(Mono_Time *mono_time, Last_Pinged *last_pinged, uint8_t *last_pinged_index,
759 const uint8_t *public_key)
754{ 760{
755 unsigned int i; 761 unsigned int i;
756 762
757 for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) { 763 for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) {
758 if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME)) { 764 if (!mono_time_is_timeout(mono_time, last_pinged[i].timestamp, MIN_NODE_PING_TIME)) {
759 if (public_key_cmp(last_pinged[i].public_key, public_key) == 0) { 765 if (public_key_cmp(last_pinged[i].public_key, public_key) == 0) {
760 return 0; 766 return 0;
761 } 767 }
@@ -763,7 +769,7 @@ static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, co
763 } 769 }
764 770
765 memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); 771 memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
766 last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time(); 772 last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = mono_time_get(mono_time);
767 ++*last_pinged_index; 773 ++*last_pinged_index;
768 return 1; 774 return 1;
769} 775}
@@ -811,9 +817,9 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for
811 } 817 }
812 } 818 }
813 819
814 if (onion_node_timed_out(&list_nodes[0]) 820 if (onion_node_timed_out(&list_nodes[0], onion_c->mono_time)
815 || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2 821 || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2
816 || onion_node_timed_out(&list_nodes[1]) 822 || onion_node_timed_out(&list_nodes[1], onion_c->mono_time)
817 || id_closest(reference_id, list_nodes[1].public_key, nodes[i].public_key) == 2) { 823 || id_closest(reference_id, list_nodes[1].public_key, nodes[i].public_key) == 2) {
818 /* check if node is already in list. */ 824 /* check if node is already in list. */
819 for (j = 0; j < list_length; ++j) { 825 for (j = 0; j < list_length; ++j) {
@@ -822,7 +828,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for
822 } 828 }
823 } 829 }
824 830
825 if (j == list_length && good_to_ping(last_pinged, last_pinged_index, nodes[i].public_key)) { 831 if (j == list_length && good_to_ping(onion_c->mono_time, last_pinged, last_pinged_index, nodes[i].public_key)) {
826 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, nullptr, ~0); 832 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, nullptr, ~0);
827 } 833 }
828 } 834 }
@@ -894,7 +900,7 @@ static int handle_announce_response(void *object, IP_Port source, const uint8_t
894 } 900 }
895 901
896 // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline? 902 // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
897 onion_c->last_packet_recv = unix_time(); 903 onion_c->last_packet_recv = mono_time_get(onion_c->mono_time);
898 return 0; 904 return 0;
899} 905}
900 906
@@ -975,7 +981,7 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con
975 } 981 }
976 982
977 onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t)); 983 onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t));
978 onion_c->friends_list[friend_num].last_seen = unix_time(); 984 onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time);
979 985
980 uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH; 986 uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH;
981 987
@@ -1054,7 +1060,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
1054 Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list; 1060 Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
1055 1061
1056 for (i = 0; i < MAX_ONION_CLIENTS; ++i) { 1062 for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
1057 if (onion_node_timed_out(&list_nodes[i])) { 1063 if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) {
1058 continue; 1064 continue;
1059 } 1065 }
1060 1066
@@ -1196,7 +1202,7 @@ static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8
1196 1202
1197 uint8_t data[DHTPK_DATA_MAX_LENGTH]; 1203 uint8_t data[DHTPK_DATA_MAX_LENGTH];
1198 data[0] = ONION_DATA_DHTPK; 1204 data[0] = ONION_DATA_DHTPK;
1199 uint64_t no_replay = unix_time(); 1205 uint64_t no_replay = mono_time_get(onion_c->mono_time);
1200 host_to_net((uint8_t *)&no_replay, sizeof(no_replay)); 1206 host_to_net((uint8_t *)&no_replay, sizeof(no_replay));
1201 memcpy(data + 1, &no_replay, sizeof(no_replay)); 1207 memcpy(data + 1, &no_replay, sizeof(no_replay));
1202 memcpy(data + 1 + sizeof(uint64_t), dht_get_self_public_key(onion_c->dht), CRYPTO_PUBLIC_KEY_SIZE); 1208 memcpy(data + 1 + sizeof(uint64_t), dht_get_self_public_key(onion_c->dht), CRYPTO_PUBLIC_KEY_SIZE);
@@ -1420,7 +1426,7 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin
1420 onion_c->friends_list[friend_num].know_dht_public_key = 0; 1426 onion_c->friends_list[friend_num].know_dht_public_key = 0;
1421 } 1427 }
1422 1428
1423 onion_c->friends_list[friend_num].last_seen = unix_time(); 1429 onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time);
1424 onion_c->friends_list[friend_num].know_dht_public_key = 1; 1430 onion_c->friends_list[friend_num].know_dht_public_key = 1;
1425 memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, CRYPTO_PUBLIC_KEY_SIZE); 1431 memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, CRYPTO_PUBLIC_KEY_SIZE);
1426 1432
@@ -1485,7 +1491,7 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
1485 } 1491 }
1486 1492
1487 if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1) { 1493 if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1) {
1488 onion_c->friends_list[friend_num].last_seen = unix_time(); 1494 onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time);
1489 } 1495 }
1490 1496
1491 onion_c->friends_list[friend_num].is_online = is_online; 1497 onion_c->friends_list[friend_num].is_online = is_online;
@@ -1548,10 +1554,11 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1548 interval = ANNOUNCE_FRIEND_BEGINNING; 1554 interval = ANNOUNCE_FRIEND_BEGINNING;
1549 } else { 1555 } else {
1550 if (onion_c->friends_list[friendnum].last_reported_announced == 0) { 1556 if (onion_c->friends_list[friendnum].last_reported_announced == 0) {
1551 onion_c->friends_list[friendnum].last_reported_announced = unix_time(); 1557 onion_c->friends_list[friendnum].last_reported_announced = mono_time_get(onion_c->mono_time);
1552 } 1558 }
1553 1559
1554 uint64_t backoff_interval = (unix_time() - onion_c->friends_list[friendnum].last_reported_announced) 1560 uint64_t backoff_interval = (mono_time_get(onion_c->mono_time) -
1561 onion_c->friends_list[friendnum].last_reported_announced)
1555 / ONION_FRIEND_BACKOFF_FACTOR; 1562 / ONION_FRIEND_BACKOFF_FACTOR;
1556 1563
1557 if (backoff_interval > ONION_FRIEND_MAX_PING_INTERVAL) { 1564 if (backoff_interval > ONION_FRIEND_MAX_PING_INTERVAL) {
@@ -1572,15 +1579,15 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1572 bool ping_random = true; 1579 bool ping_random = true;
1573 1580
1574 for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) { 1581 for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) {
1575 if (!(is_timeout(list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS) 1582 if (!(mono_time_is_timeout(onion_c->mono_time, list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS)
1576 && is_timeout(list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) { 1583 && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) {
1577 ping_random = false; 1584 ping_random = false;
1578 break; 1585 break;
1579 } 1586 }
1580 } 1587 }
1581 1588
1582 for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) { 1589 for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) {
1583 if (onion_node_timed_out(&list_nodes[i])) { 1590 if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) {
1584 continue; 1591 continue;
1585 } 1592 }
1586 1593
@@ -1588,7 +1595,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1588 1595
1589 1596
1590 if (list_nodes[i].last_pinged == 0) { 1597 if (list_nodes[i].last_pinged == 0) {
1591 list_nodes[i].last_pinged = unix_time(); 1598 list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time);
1592 continue; 1599 continue;
1593 } 1600 }
1594 1601
@@ -1596,11 +1603,11 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1596 continue; 1603 continue;
1597 } 1604 }
1598 1605
1599 if (is_timeout(list_nodes[i].last_pinged, interval) 1606 if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, interval)
1600 || (ping_random && random_u32() % (MAX_ONION_CLIENTS - i) == 0)) { 1607 || (ping_random && random_u32() % (MAX_ONION_CLIENTS - i) == 0)) {
1601 if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, 1608 if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port,
1602 list_nodes[i].public_key, nullptr, ~0) == 0) { 1609 list_nodes[i].public_key, nullptr, ~0) == 0) {
1603 list_nodes[i].last_pinged = unix_time(); 1610 list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time);
1604 ++list_nodes[i].unsuccessful_pings; 1611 ++list_nodes[i].unsuccessful_pings;
1605 ping_random = false; 1612 ping_random = false;
1606 } 1613 }
@@ -1634,15 +1641,17 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1634 } 1641 }
1635 1642
1636 /* send packets to friend telling them our DHT public key. */ 1643 /* send packets to friend telling them our DHT public key. */
1637 if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_onion_sent, ONION_DHTPK_SEND_INTERVAL)) { 1644 if (mono_time_is_timeout(onion_c->mono_time, onion_c->friends_list[friendnum].last_dht_pk_onion_sent,
1645 ONION_DHTPK_SEND_INTERVAL)) {
1638 if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) { 1646 if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) {
1639 onion_c->friends_list[friendnum].last_dht_pk_onion_sent = unix_time(); 1647 onion_c->friends_list[friendnum].last_dht_pk_onion_sent = mono_time_get(onion_c->mono_time);
1640 } 1648 }
1641 } 1649 }
1642 1650
1643 if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_dht_sent, DHT_DHTPK_SEND_INTERVAL)) { 1651 if (mono_time_is_timeout(onion_c->mono_time, onion_c->friends_list[friendnum].last_dht_pk_dht_sent,
1652 DHT_DHTPK_SEND_INTERVAL)) {
1644 if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) { 1653 if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) {
1645 onion_c->friends_list[friendnum].last_dht_pk_dht_sent = unix_time(); 1654 onion_c->friends_list[friendnum].last_dht_pk_dht_sent = mono_time_get(onion_c->mono_time);
1646 } 1655 }
1647 } 1656 }
1648 } 1657 }
@@ -1668,7 +1677,7 @@ static void do_announce(Onion_Client *onion_c)
1668 Onion_Node *list_nodes = onion_c->clients_announce_list; 1677 Onion_Node *list_nodes = onion_c->clients_announce_list;
1669 1678
1670 for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) { 1679 for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
1671 if (onion_node_timed_out(&list_nodes[i])) { 1680 if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) {
1672 continue; 1681 continue;
1673 } 1682 }
1674 1683
@@ -1687,7 +1696,7 @@ static void do_announce(Onion_Client *onion_c)
1687 1696
1688 unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; 1697 unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
1689 1698
1690 if (list_nodes[i].is_stored && path_exists(&onion_c->onion_paths_self, list_nodes[i].path_used)) { 1699 if (list_nodes[i].is_stored && path_exists(onion_c->mono_time, &onion_c->onion_paths_self, list_nodes[i].path_used)) {
1691 interval = ANNOUNCE_INTERVAL_ANNOUNCED; 1700 interval = ANNOUNCE_INTERVAL_ANNOUNCED;
1692 1701
1693 uint32_t pathnum = list_nodes[i].path_used % NUMBER_ONION_PATHS; 1702 uint32_t pathnum = list_nodes[i].path_used % NUMBER_ONION_PATHS;
@@ -1696,32 +1705,32 @@ static void do_announce(Onion_Client *onion_c)
1696 * aggressively, if it has survived for at least TIME_TO_STABLE 1705 * aggressively, if it has survived for at least TIME_TO_STABLE
1697 * and the latest packets sent to it are not timing out. 1706 * and the latest packets sent to it are not timing out.
1698 */ 1707 */
1699 if (is_timeout(list_nodes[i].added_time, TIME_TO_STABLE) 1708 if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].added_time, TIME_TO_STABLE)
1700 && !(list_nodes[i].unsuccessful_pings > 0 1709 && !(list_nodes[i].unsuccessful_pings > 0
1701 && is_timeout(list_nodes[i].last_pinged, ONION_NODE_TIMEOUT)) 1710 && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, ONION_NODE_TIMEOUT))
1702 && is_timeout(onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE) 1711 && mono_time_is_timeout(onion_c->mono_time, onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE)
1703 && !(onion_c->onion_paths_self.last_path_used_times[pathnum] > 0 1712 && !(onion_c->onion_paths_self.last_path_used_times[pathnum] > 0
1704 && is_timeout(onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) { 1713 && mono_time_is_timeout(onion_c->mono_time, onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) {
1705 interval = ANNOUNCE_INTERVAL_STABLE; 1714 interval = ANNOUNCE_INTERVAL_STABLE;
1706 } 1715 }
1707 } 1716 }
1708 1717
1709 if (is_timeout(list_nodes[i].last_pinged, interval) 1718 if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, interval)
1710 || (is_timeout(onion_c->last_announce, ONION_NODE_PING_INTERVAL) 1719 || (mono_time_is_timeout(onion_c->mono_time, onion_c->last_announce, ONION_NODE_PING_INTERVAL)
1711 && random_u32() % (MAX_ONION_CLIENTS_ANNOUNCE - i) == 0)) { 1720 && random_u32() % (MAX_ONION_CLIENTS_ANNOUNCE - i) == 0)) {
1712 uint32_t path_to_use = list_nodes[i].path_used; 1721 uint32_t path_to_use = list_nodes[i].path_used;
1713 1722
1714 if (list_nodes[i].unsuccessful_pings == ONION_NODE_MAX_PINGS - 1 1723 if (list_nodes[i].unsuccessful_pings == ONION_NODE_MAX_PINGS - 1
1715 && is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)) { 1724 && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].added_time, TIME_TO_STABLE)) {
1716 /* Last chance for a long-lived node - try a random path */ 1725 /* Last chance for a long-lived node - try a random path */
1717 path_to_use = ~0; 1726 path_to_use = ~0;
1718 } 1727 }
1719 1728
1720 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key, 1729 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key,
1721 list_nodes[i].ping_id, path_to_use) == 0) { 1730 list_nodes[i].ping_id, path_to_use) == 0) {
1722 list_nodes[i].last_pinged = unix_time(); 1731 list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time);
1723 ++list_nodes[i].unsuccessful_pings; 1732 ++list_nodes[i].unsuccessful_pings;
1724 onion_c->last_announce = unix_time(); 1733 onion_c->last_announce = mono_time_get(onion_c->mono_time);
1725 } 1734 }
1726 } 1735 }
1727 } 1736 }
@@ -1756,7 +1765,7 @@ static int onion_isconnected(const Onion_Client *onion_c)
1756{ 1765{
1757 unsigned int i, num = 0, announced = 0; 1766 unsigned int i, num = 0, announced = 0;
1758 1767
1759 if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) { 1768 if (mono_time_is_timeout(onion_c->mono_time, onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) {
1760 return 0; 1769 return 0;
1761 } 1770 }
1762 1771
@@ -1765,7 +1774,7 @@ static int onion_isconnected(const Onion_Client *onion_c)
1765 } 1774 }
1766 1775
1767 for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) { 1776 for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
1768 if (!onion_node_timed_out(&onion_c->clients_announce_list[i])) { 1777 if (!onion_node_timed_out(&onion_c->clients_announce_list[i], onion_c->mono_time)) {
1769 ++num; 1778 ++num;
1770 1779
1771 if (onion_c->clients_announce_list[i].is_stored) { 1780 if (onion_c->clients_announce_list[i].is_stored) {
@@ -1812,11 +1821,11 @@ unsigned int onion_connection_status(const Onion_Client *onion_c)
1812 1821
1813void do_onion_client(Onion_Client *onion_c) 1822void do_onion_client(Onion_Client *onion_c)
1814{ 1823{
1815 if (onion_c->last_run == unix_time()) { 1824 if (onion_c->last_run == mono_time_get(onion_c->mono_time)) {
1816 return; 1825 return;
1817 } 1826 }
1818 1827
1819 if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) { 1828 if (mono_time_is_timeout(onion_c->mono_time, onion_c->first_run, ONION_CONNECTION_SECONDS)) {
1820 populate_path_nodes(onion_c); 1829 populate_path_nodes(onion_c);
1821 do_announce(onion_c); 1830 do_announce(onion_c);
1822 } 1831 }
@@ -1835,7 +1844,7 @@ void do_onion_client(Onion_Client *onion_c)
1835 1844
1836 bool udp_connected = dht_non_lan_connected(onion_c->dht); 1845 bool udp_connected = dht_non_lan_connected(onion_c->dht);
1837 1846
1838 if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) { 1847 if (mono_time_is_timeout(onion_c->mono_time, onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) {
1839 set_tcp_onion_status(nc_get_tcp_c(onion_c->c), !udp_connected); 1848 set_tcp_onion_status(nc_get_tcp_c(onion_c->c), !udp_connected);
1840 } 1849 }
1841 1850
@@ -1849,13 +1858,13 @@ void do_onion_client(Onion_Client *onion_c)
1849 } 1858 }
1850 1859
1851 if (onion_c->last_run == 0) { 1860 if (onion_c->last_run == 0) {
1852 onion_c->first_run = unix_time(); 1861 onion_c->first_run = mono_time_get(onion_c->mono_time);
1853 } 1862 }
1854 1863
1855 onion_c->last_run = unix_time(); 1864 onion_c->last_run = mono_time_get(onion_c->mono_time);
1856} 1865}
1857 1866
1858Onion_Client *new_onion_client(Net_Crypto *c) 1867Onion_Client *new_onion_client(Mono_Time *mono_time, Net_Crypto *c)
1859{ 1868{
1860 if (c == nullptr) { 1869 if (c == nullptr) {
1861 return nullptr; 1870 return nullptr;
@@ -1874,6 +1883,7 @@ Onion_Client *new_onion_client(Net_Crypto *c)
1874 return nullptr; 1883 return nullptr;
1875 } 1884 }
1876 1885
1886 onion_c->mono_time = mono_time;
1877 onion_c->dht = nc_get_dht(c); 1887 onion_c->dht = nc_get_dht(c);
1878 onion_c->net = dht_get_net(onion_c->dht); 1888 onion_c->net = dht_get_net(onion_c->dht);
1879 onion_c->c = c; 1889 onion_c->c = c;
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h
index 660ccdd2..c6aaec45 100644
--- a/toxcore/onion_client.h
+++ b/toxcore/onion_client.h
@@ -188,7 +188,7 @@ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_ha
188 188
189void do_onion_client(Onion_Client *onion_c); 189void do_onion_client(Onion_Client *onion_c);
190 190
191Onion_Client *new_onion_client(Net_Crypto *c); 191Onion_Client *new_onion_client(Mono_Time *mono_time, Net_Crypto *c);
192 192
193void kill_onion_client(Onion_Client *onion_c); 193void kill_onion_client(Onion_Client *onion_c);
194 194
diff --git a/toxcore/ping.api.h b/toxcore/ping.api.h
index edc04723..e75c4e14 100644
--- a/toxcore/ping.api.h
+++ b/toxcore/ping.api.h
@@ -35,12 +35,13 @@
35 35
36class iP_Port { struct this; } 36class iP_Port { struct this; }
37class dHT { struct this; } 37class dHT { struct this; }
38class mono_Time { struct this; }
38 39
39class ping { 40class ping {
40 41
41struct this; 42struct this;
42 43
43static this new(dHT::this *dht); 44static this new(const mono_Time::this *mono_time, dHT::this *dht);
44void kill(); 45void kill();
45 46
46/** Add nodes to the to_ping list. 47/** Add nodes to the to_ping list.
diff --git a/toxcore/ping.c b/toxcore/ping.c
index 1bf096bf..7ffe13b4 100644
--- a/toxcore/ping.c
+++ b/toxcore/ping.c
@@ -48,6 +48,7 @@
48 48
49 49
50struct Ping { 50struct Ping {
51 const Mono_Time *mono_time;
51 DHT *dht; 52 DHT *dht;
52 53
53 Ping_Array *ping_array; 54 Ping_Array *ping_array;
@@ -78,7 +79,7 @@ int32_t ping_send_request(Ping *ping, IP_Port ipp, const uint8_t *public_key)
78 uint8_t data[PING_DATA_SIZE]; 79 uint8_t data[PING_DATA_SIZE];
79 id_copy(data, public_key); 80 id_copy(data, public_key);
80 memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port)); 81 memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port));
81 ping_id = ping_array_add(ping->ping_array, data, sizeof(data)); 82 ping_id = ping_array_add(ping->ping_array, ping->mono_time, data, sizeof(data));
82 83
83 if (ping_id == 0) { 84 if (ping_id == 0) {
84 return 1; 85 return 1;
@@ -219,7 +220,7 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac
219 memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); 220 memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
220 uint8_t data[PING_DATA_SIZE]; 221 uint8_t data[PING_DATA_SIZE];
221 222
222 if (ping_array_check(ping->ping_array, data, sizeof(data), ping_id) != sizeof(data)) { 223 if (ping_array_check(ping->ping_array, ping->mono_time, data, sizeof(data), ping_id) != sizeof(data)) {
223 return 1; 224 return 1;
224 } 225 }
225 226
@@ -243,7 +244,8 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac
243 * return 1 if it is. 244 * return 1 if it is.
244 * return 0 if it isn't. 245 * return 0 if it isn't.
245 */ 246 */
246static int in_list(const Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port) 247static int in_list(const Client_data *list, uint16_t length, const Mono_Time *mono_time, const uint8_t *public_key,
248 IP_Port ip_port)
247{ 249{
248 unsigned int i; 250 unsigned int i;
249 251
@@ -257,7 +259,7 @@ static int in_list(const Client_data *list, uint16_t length, const uint8_t *publ
257 ipptp = &list[i].assoc6; 259 ipptp = &list[i].assoc6;
258 } 260 }
259 261
260 if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) { 262 if (!mono_time_is_timeout(mono_time, ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) {
261 return 1; 263 return 1;
262 } 264 }
263 } 265 }
@@ -286,7 +288,7 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port)
286 return -1; 288 return -1;
287 } 289 }
288 290
289 if (in_list(dht_get_close_clientlist(ping->dht), LCLIENT_LIST, public_key, ip_port)) { 291 if (in_list(dht_get_close_clientlist(ping->dht), LCLIENT_LIST, ping->mono_time, public_key, ip_port)) {
290 return -1; 292 return -1;
291 } 293 }
292 294
@@ -324,7 +326,7 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port)
324 */ 326 */
325void ping_iterate(Ping *ping) 327void ping_iterate(Ping *ping)
326{ 328{
327 if (!is_timeout(ping->last_to_ping, TIME_TO_PING)) { 329 if (!mono_time_is_timeout(ping->mono_time, ping->last_to_ping, TIME_TO_PING)) {
328 return; 330 return;
329 } 331 }
330 332
@@ -348,12 +350,12 @@ void ping_iterate(Ping *ping)
348 } 350 }
349 351
350 if (i != 0) { 352 if (i != 0) {
351 ping->last_to_ping = unix_time(); 353 ping->last_to_ping = mono_time_get(ping->mono_time);
352 } 354 }
353} 355}
354 356
355 357
356Ping *ping_new(DHT *dht) 358Ping *ping_new(const Mono_Time *mono_time, DHT *dht)
357{ 359{
358 Ping *ping = (Ping *)calloc(1, sizeof(Ping)); 360 Ping *ping = (Ping *)calloc(1, sizeof(Ping));
359 361
@@ -368,6 +370,7 @@ Ping *ping_new(DHT *dht)
368 return nullptr; 370 return nullptr;
369 } 371 }
370 372
373 ping->mono_time = mono_time;
371 ping->dht = dht; 374 ping->dht = dht;
372 networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht); 375 networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
373 networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); 376 networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);
diff --git a/toxcore/ping.h b/toxcore/ping.h
index 61875a0b..63ecb017 100644
--- a/toxcore/ping.h
+++ b/toxcore/ping.h
@@ -41,12 +41,17 @@ typedef struct IP_Port IP_Port;
41typedef struct DHT DHT; 41typedef struct DHT DHT;
42#endif /* DHT_DEFINED */ 42#endif /* DHT_DEFINED */
43 43
44#ifndef MONO_TIME_DEFINED
45#define MONO_TIME_DEFINED
46typedef struct Mono_Time Mono_Time;
47#endif /* MONO_TIME_DEFINED */
48
44#ifndef PING_DEFINED 49#ifndef PING_DEFINED
45#define PING_DEFINED 50#define PING_DEFINED
46typedef struct Ping Ping; 51typedef struct Ping Ping;
47#endif /* PING_DEFINED */ 52#endif /* PING_DEFINED */
48 53
49Ping *ping_new(DHT *dht); 54Ping *ping_new(const struct Mono_Time *mono_time, DHT *dht);
50 55
51void ping_kill(Ping *ping); 56void ping_kill(Ping *ping);
52 57
diff --git a/toxcore/ping_array.api.h b/toxcore/ping_array.api.h
index 55b80570..61021e24 100644
--- a/toxcore/ping_array.api.h
+++ b/toxcore/ping_array.api.h
@@ -28,6 +28,8 @@
28#include "network.h" 28#include "network.h"
29%} 29%}
30 30
31class mono_Time { struct this; }
32
31class ping_Array { 33class ping_Array {
32 34
33struct this; 35struct this;
@@ -53,7 +55,7 @@ void kill();
53 * return ping_id on success. 55 * return ping_id on success.
54 * return 0 on failure. 56 * return 0 on failure.
55 */ 57 */
56uint64_t add(const uint8_t *data, uint32_t length); 58uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t length);
57 59
58/** 60/**
59 * Check if ping_id is valid and not timed out. 61 * Check if ping_id is valid and not timed out.
@@ -63,7 +65,7 @@ uint64_t add(const uint8_t *data, uint32_t length);
63 * return length of data copied on success. 65 * return length of data copied on success.
64 * return -1 on failure. 66 * return -1 on failure.
65 */ 67 */
66int32_t check(uint8_t[length] data, uint64_t ping_id); 68int32_t check(const mono_Time::this *mono_time, uint8_t[length] data, uint64_t ping_id);
67 69
68} 70}
69 71
diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c
index 142640dd..9130254e 100644
--- a/toxcore/ping_array.c
+++ b/toxcore/ping_array.c
@@ -109,12 +109,12 @@ void ping_array_kill(Ping_Array *array)
109 109
110/* Clear timed out entries. 110/* Clear timed out entries.
111 */ 111 */
112static void ping_array_clear_timedout(Ping_Array *array) 112static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time)
113{ 113{
114 while (array->last_deleted != array->last_added) { 114 while (array->last_deleted != array->last_added) {
115 uint32_t index = array->last_deleted % array->total_size; 115 uint32_t index = array->last_deleted % array->total_size;
116 116
117 if (!is_timeout(array->entries[index].time, array->timeout)) { 117 if (!mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) {
118 break; 118 break;
119 } 119 }
120 120
@@ -128,9 +128,9 @@ static void ping_array_clear_timedout(Ping_Array *array)
128 * return ping_id on success. 128 * return ping_id on success.
129 * return 0 on failure. 129 * return 0 on failure.
130 */ 130 */
131uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length) 131uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uint8_t *data, uint32_t length)
132{ 132{
133 ping_array_clear_timedout(array); 133 ping_array_clear_timedout(array, mono_time);
134 uint32_t index = array->last_added % array->total_size; 134 uint32_t index = array->last_added % array->total_size;
135 135
136 if (array->entries[index].data != nullptr) { 136 if (array->entries[index].data != nullptr) {
@@ -146,7 +146,7 @@ uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length)
146 146
147 memcpy(array->entries[index].data, data, length); 147 memcpy(array->entries[index].data, data, length);
148 array->entries[index].length = length; 148 array->entries[index].length = length;
149 array->entries[index].time = unix_time(); 149 array->entries[index].time = mono_time_get(mono_time);
150 ++array->last_added; 150 ++array->last_added;
151 uint64_t ping_id = random_u64(); 151 uint64_t ping_id = random_u64();
152 ping_id /= array->total_size; 152 ping_id /= array->total_size;
@@ -169,7 +169,7 @@ uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length)
169 * return length of data copied on success. 169 * return length of data copied on success.
170 * return -1 on failure. 170 * return -1 on failure.
171 */ 171 */
172int32_t ping_array_check(Ping_Array *array, uint8_t *data, size_t length, uint64_t ping_id) 172int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t *data, size_t length, uint64_t ping_id)
173{ 173{
174 if (ping_id == 0) { 174 if (ping_id == 0) {
175 return -1; 175 return -1;
@@ -181,7 +181,7 @@ int32_t ping_array_check(Ping_Array *array, uint8_t *data, size_t length, uint64
181 return -1; 181 return -1;
182 } 182 }
183 183
184 if (is_timeout(array->entries[index].time, array->timeout)) { 184 if (mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) {
185 return -1; 185 return -1;
186 } 186 }
187 187
diff --git a/toxcore/ping_array.h b/toxcore/ping_array.h
index b927bbd4..cfa9bfcc 100644
--- a/toxcore/ping_array.h
+++ b/toxcore/ping_array.h
@@ -26,6 +26,11 @@
26 26
27#include "network.h" 27#include "network.h"
28 28
29#ifndef MONO_TIME_DEFINED
30#define MONO_TIME_DEFINED
31typedef struct Mono_Time Mono_Time;
32#endif /* MONO_TIME_DEFINED */
33
29#ifndef PING_ARRAY_DEFINED 34#ifndef PING_ARRAY_DEFINED
30#define PING_ARRAY_DEFINED 35#define PING_ARRAY_DEFINED
31typedef struct Ping_Array Ping_Array; 36typedef struct Ping_Array Ping_Array;
@@ -52,7 +57,8 @@ void ping_array_kill(struct Ping_Array *_array);
52 * return ping_id on success. 57 * return ping_id on success.
53 * return 0 on failure. 58 * return 0 on failure.
54 */ 59 */
55uint64_t ping_array_add(struct Ping_Array *_array, const uint8_t *data, uint32_t length); 60uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *mono_time, const uint8_t *data,
61 uint32_t length);
56 62
57/** 63/**
58 * Check if ping_id is valid and not timed out. 64 * Check if ping_id is valid and not timed out.
@@ -62,6 +68,7 @@ uint64_t ping_array_add(struct Ping_Array *_array, const uint8_t *data, uint32_t
62 * return length of data copied on success. 68 * return length of data copied on success.
63 * return -1 on failure. 69 * return -1 on failure.
64 */ 70 */
65int32_t ping_array_check(struct Ping_Array *_array, uint8_t *data, size_t length, uint64_t ping_id); 71int32_t ping_array_check(struct Ping_Array *_array, const struct Mono_Time *mono_time, uint8_t *data, size_t length,
72 uint64_t ping_id);
66 73
67#endif 74#endif
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 879b5c09..4f596045 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -78,6 +78,8 @@
78 78
79struct Tox { 79struct Tox {
80 Messenger *m; 80 Messenger *m;
81 Mono_Time *mono_time;
82
81 tox_self_connection_status_cb *self_connection_status_callback; 83 tox_self_connection_status_cb *self_connection_status_callback;
82 tox_friend_name_cb *friend_name_callback; 84 tox_friend_name_cb *friend_name_callback;
83 tox_friend_status_message_cb *friend_status_message_callback; 85 tox_friend_status_message_cb *friend_status_message_callback;
@@ -336,8 +338,6 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
336 return nullptr; 338 return nullptr;
337 } 339 }
338 340
339 unix_time_update();
340
341 Messenger_Options m_options = {0}; 341 Messenger_Options m_options = {0};
342 342
343 bool load_savedata_sk = false, load_savedata_tox = false; 343 bool load_savedata_sk = false, load_savedata_tox = false;
@@ -455,13 +455,22 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
455 m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(opts)); 455 m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(opts));
456 } 456 }
457 457
458 tox->mono_time = mono_time_new();
459
460 if (tox->mono_time == nullptr) {
461 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
462 tox_options_free(default_options);
463 free(tox);
464 return nullptr;
465 }
466
458 unsigned int m_error; 467 unsigned int m_error;
459 Messenger *const m = new_messenger(&m_options, &m_error); 468 Messenger *const m = new_messenger(tox->mono_time, &m_options, &m_error);
460 tox->m = m; 469 tox->m = m;
461 470
462 // TODO(iphydf): Clarify this code, check for NULL before new_groupchats, so 471 // TODO(iphydf): Clarify this code, check for NULL before new_groupchats, so
463 // new_groupchats can assume m is non-NULL. 472 // new_groupchats can assume m is non-NULL.
464 if (!new_groupchats(m)) { 473 if (!new_groupchats(tox->mono_time, m)) {
465 kill_messenger(m); 474 kill_messenger(m);
466 475
467 if (m_error == MESSENGER_ERROR_PORT) { 476 if (m_error == MESSENGER_ERROR_PORT) {
@@ -472,6 +481,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
472 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); 481 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
473 } 482 }
474 483
484 mono_time_free(tox->mono_time);
475 tox_options_free(default_options); 485 tox_options_free(default_options);
476 free(tox); 486 free(tox);
477 return nullptr; 487 return nullptr;
@@ -522,6 +532,7 @@ void tox_kill(Tox *tox)
522 Messenger *m = tox->m; 532 Messenger *m = tox->m;
523 kill_groupchats(m->conferences_object); 533 kill_groupchats(m->conferences_object);
524 kill_messenger(m); 534 kill_messenger(m);
535 mono_time_free(tox->mono_time);
525 free(tox); 536 free(tox);
526} 537}
527 538
@@ -656,7 +667,7 @@ uint32_t tox_iteration_interval(const Tox *tox)
656 667
657void tox_iterate(Tox *tox, void *user_data) 668void tox_iterate(Tox *tox, void *user_data)
658{ 669{
659 unix_time_update(); 670 mono_time_update(tox->mono_time);
660 671
661 Messenger *m = tox->m; 672 Messenger *m = tox->m;
662 struct Tox_Userdata tox_data = { tox, user_data }; 673 struct Tox_Userdata tox_data = { tox, user_data };