From d6d305feeb76735ee4b4e14c6bca737a5482bc19 Mon Sep 17 00:00:00 2001 From: iphydf Date: Wed, 1 Aug 2018 23:02:13 +0000 Subject: [PATCH] Use per-instance `Mono_Time` for Messenger and onion. --- auto_tests/TCP_test.c | 152 ++++++++------- auto_tests/dht_test.c | 71 +++---- auto_tests/messenger_test.c | 5 +- auto_tests/onion_test.c | 76 ++++---- other/DHT_bootstrap.c | 17 +- other/astyle/format-source | 4 +- other/bootstrap_daemon/src/tox-bootstrapd.c | 37 ++-- testing/DHT_test.c | 8 +- testing/Messenger_test.c | 11 +- toxav/groupav.c | 12 +- toxcore/DHT.c | 201 +++++++++++--------- toxcore/DHT.h | 7 +- toxcore/Messenger.c | 24 +-- toxcore/Messenger.h | 3 +- toxcore/TCP_client.c | 20 +- toxcore/TCP_client.h | 6 +- toxcore/TCP_connection.c | 26 +-- toxcore/TCP_connection.h | 2 +- toxcore/TCP_server.c | 55 +++--- toxcore/TCP_server.h | 2 +- toxcore/friend_connection.c | 27 +-- toxcore/friend_connection.h | 3 +- toxcore/group.c | 14 +- toxcore/group.h | 4 +- toxcore/mono_time.c | 23 +-- toxcore/mono_time.h | 37 +++- toxcore/mono_time_test.cc | 28 ++- toxcore/net_crypto.c | 42 ++-- toxcore/net_crypto.h | 2 +- toxcore/onion.c | 18 +- toxcore/onion.h | 6 +- toxcore/onion_announce.c | 29 +-- toxcore/onion_announce.h | 2 +- toxcore/onion_client.c | 146 +++++++------- toxcore/onion_client.h | 2 +- toxcore/ping.api.h | 3 +- toxcore/ping.c | 19 +- toxcore/ping.h | 7 +- toxcore/ping_array.api.h | 6 +- toxcore/ping_array.c | 14 +- toxcore/ping_array.h | 11 +- toxcore/tox.c | 21 +- 42 files changed, 683 insertions(+), 520 deletions(-) diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 52ecad77b..3c5d56b9c 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -36,17 +36,19 @@ static inline IP get_loopback() return ip; } -static void do_TCP_server_delay(TCP_Server *tcp_s, int delay) +static void do_TCP_server_delay(TCP_Server *tcp_s, Mono_Time *mono_time, int delay) { c_sleep(delay); - unix_time_update(); - do_TCP_server(tcp_s); + mono_time_update(mono_time); + do_TCP_server(tcp_s, mono_time); c_sleep(delay); } static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643}; START_TEST(test_basic) { + Mono_Time *mono_time = mono_time_new(); + // Attempt to create a new TCP_Server instance. uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; @@ -99,12 +101,12 @@ START_TEST(test_basic) ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1) == TCP_CLIENT_HANDSHAKE_SIZE - 1, "An attempt to send the initial handshake minus last byte failed."); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1) == 1, "The attempt to send the last byte of handshake failed."); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); // Receiving server response and decrypting it uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; @@ -142,8 +144,8 @@ START_TEST(test_basic) i += msg_length; c_sleep(50); - unix_time_update(); - do_TCP_server(tcp_s); + mono_time_update(mono_time); + do_TCP_server(tcp_s, mono_time); } // Receiving the second response and verifying its validity @@ -167,6 +169,8 @@ START_TEST(test_basic) // Closing connections. kill_sock(sock); kill_TCP_server(tcp_s); + + mono_time_free(mono_time); } END_TEST @@ -178,7 +182,7 @@ struct sec_TCP_con { uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; }; -static struct sec_TCP_con *new_TCP_con(TCP_Server *tcp_s) +static struct sec_TCP_con *new_TCP_con(TCP_Server *tcp_s, Mono_Time *mono_time) { struct sec_TCP_con *sec_c = (struct sec_TCP_con *)malloc(sizeof(struct sec_TCP_con)); 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) ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1) == TCP_CLIENT_HANDSHAKE_SIZE - 1, "Failed to send the first portion of the handshake to the TCP relay server."); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1) == 1, "Failed to send last byte of handshake."); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; 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 START_TEST(test_some) { + Mono_Time *mono_time = mono_time_new(); + uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; crypto_new_keypair(self_public_key, self_secret_key); @@ -273,9 +279,9 @@ START_TEST(test_some) ck_assert_msg(tcp_s != nullptr, "Failed to create TCP relay server"); ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind to all ports."); - struct sec_TCP_con *con1 = new_TCP_con(tcp_s); - struct sec_TCP_con *con2 = new_TCP_con(tcp_s); - struct sec_TCP_con *con3 = new_TCP_con(tcp_s); + struct sec_TCP_con *con1 = new_TCP_con(tcp_s, mono_time); + struct sec_TCP_con *con2 = new_TCP_con(tcp_s, mono_time); + struct sec_TCP_con *con3 = new_TCP_con(tcp_s, mono_time); uint8_t requ_p[1 + CRYPTO_PUBLIC_KEY_SIZE]; requ_p[0] = 0; @@ -286,7 +292,7 @@ START_TEST(test_some) memcpy(requ_p + 1, con1->public_key, CRYPTO_PUBLIC_KEY_SIZE); write_packet_TCP_secure_connection(con3, requ_p, sizeof(requ_p)); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); // Testing response from connection 1 uint8_t data[2048]; @@ -309,7 +315,7 @@ START_TEST(test_some) write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet)); write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet)); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); len = read_packet_sec_TCP(con1, data, 2 + 2 + CRYPTO_MAC_SIZE); ck_assert_msg(len == 2, "wrong len %d", len); @@ -334,7 +340,7 @@ START_TEST(test_some) write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); len = read_packet_sec_TCP(con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); 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) uint8_t ping_packet[1 + sizeof(uint64_t)] = {4, 8, 6, 9, 67}; write_packet_TCP_secure_connection(con1, ping_packet, sizeof(ping_packet)); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); len = read_packet_sec_TCP(con1, data, 2 + sizeof(ping_packet) + CRYPTO_MAC_SIZE); ck_assert_msg(len == sizeof(ping_packet), "wrong len %d", len); @@ -363,6 +369,8 @@ START_TEST(test_some) kill_TCP_con(con1); kill_TCP_con(con2); kill_TCP_con(con3); + + mono_time_free(mono_time); } END_TEST @@ -449,7 +457,8 @@ static int oob_data_callback(void *object, const uint8_t *public_key, const uint START_TEST(test_client) { - unix_time_update(); + Mono_Time *mono_time = mono_time_new(); + uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; crypto_new_keypair(self_public_key, self_secret_key); @@ -465,8 +474,9 @@ START_TEST(test_client) ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]); ip_port_tcp_s.ip = get_loopback(); - TCP_Client_Connection *conn = new_TCP_connection(ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr); - do_TCP_connection(conn, nullptr); + TCP_Client_Connection *conn = new_TCP_connection(mono_time, ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, + nullptr); + do_TCP_connection(mono_time, conn, nullptr); c_sleep(50); // The connection status should be unconfirmed here because we have finished @@ -474,13 +484,13 @@ START_TEST(test_client) ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_UNCONFIRMED, "Wrong connection status. Expected: %d, is: %d.", TCP_CLIENT_UNCONFIRMED, tcp_con_status(conn)); - do_TCP_server_delay(tcp_s, 50); // Now let the server handle requests... + do_TCP_server_delay(tcp_s, mono_time, 50); // Now let the server handle requests... const uint8_t LOOP_SIZE = 3; for (uint8_t i = 0; i < LOOP_SIZE; i++) { - unix_time_update(); - do_TCP_connection(conn, nullptr); // Run the connection loop. + mono_time_update(mono_time); + do_TCP_connection(mono_time, conn, nullptr); // Run the connection loop. // The status of the connection should continue to be TCP_CLIENT_CONFIRMED after multiple subsequent do_TCP_connection() calls. 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) c_sleep(i == LOOP_SIZE - 1 ? 0 : 500); // Sleep for 500ms on all except third loop. } - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); // And still after the server runs again. 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) uint8_t f2_secret_key[CRYPTO_SECRET_KEY_SIZE]; crypto_new_keypair(f2_public_key, f2_secret_key); ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]); - TCP_Client_Connection *conn2 = new_TCP_connection( - ip_port_tcp_s, self_public_key, f2_public_key, f2_secret_key, nullptr); + TCP_Client_Connection *conn2 = new_TCP_connection(mono_time, ip_port_tcp_s, self_public_key, f2_public_key, + f2_secret_key, nullptr); // The client should call this function (defined earlier) during the routing process. routing_response_handler(conn, response_callback, (char *)conn + 2); @@ -514,13 +524,13 @@ START_TEST(test_client) // These integers will increment per successful callback. oob_data_callback_good = response_callback_good = status_callback_good = data_callback_good = 0; - do_TCP_connection(conn, nullptr); - do_TCP_connection(conn2, nullptr); + do_TCP_connection(mono_time, conn, nullptr); + do_TCP_connection(mono_time, conn2, nullptr); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); - do_TCP_connection(conn, nullptr); - do_TCP_connection(conn2, nullptr); + do_TCP_connection(mono_time, conn, nullptr); + do_TCP_connection(mono_time, conn2, nullptr); c_sleep(50); uint8_t data[5] = {1, 2, 3, 4, 5}; @@ -529,10 +539,10 @@ START_TEST(test_client) send_routing_request(conn, f2_public_key); send_routing_request(conn2, f_public_key); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); - do_TCP_connection(conn, nullptr); - do_TCP_connection(conn2, nullptr); + do_TCP_connection(mono_time, conn, nullptr); + do_TCP_connection(mono_time, conn2, nullptr); // All callback methods save data should have run during the above network prodding. ck_assert_msg(oob_data_callback_good == 1, "OOB callback not called"); @@ -543,22 +553,22 @@ START_TEST(test_client) ck_assert_msg(status_callback_connection_id == response_callback_connection_id, "Status and response callback connection IDs are not equal."); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); ck_assert_msg(send_data(conn2, 0, data, 5) == 1, "Failed a send_data() call."); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); - do_TCP_connection(conn, nullptr); - do_TCP_connection(conn2, nullptr); + do_TCP_connection(mono_time, conn, nullptr); + do_TCP_connection(mono_time, conn2, nullptr); ck_assert_msg(data_callback_good == 1, "Data callback was not called."); status_callback_good = 0; send_disconnect_request(conn2, 0); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); - do_TCP_connection(conn, nullptr); - do_TCP_connection(conn2, nullptr); + do_TCP_connection(mono_time, conn, nullptr); + do_TCP_connection(mono_time, conn2, nullptr); ck_assert_msg(status_callback_good == 1, "Status callback not called"); ck_assert_msg(status_callback_status == 1, "Wrong status callback status."); @@ -566,13 +576,16 @@ START_TEST(test_client) kill_TCP_server(tcp_s); kill_TCP_connection(conn); kill_TCP_connection(conn2); + + mono_time_free(mono_time); } END_TEST // Test how the client handles servers that don't respond. START_TEST(test_client_invalid) { - unix_time_update(); + Mono_Time *mono_time = mono_time_new(); + uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; crypto_new_keypair(self_public_key, self_secret_key); @@ -584,11 +597,12 @@ START_TEST(test_client_invalid) ip_port_tcp_s.port = net_htons(ports[random_u32() % NUM_PORTS]); ip_port_tcp_s.ip = get_loopback(); - TCP_Client_Connection *conn = new_TCP_connection(ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr); + TCP_Client_Connection *conn = new_TCP_connection(mono_time, ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, + nullptr); // Run the client's main loop but not the server. - unix_time_update(); - do_TCP_connection(conn, nullptr); + mono_time_update(mono_time); + do_TCP_connection(mono_time, conn, nullptr); c_sleep(50); // After 50ms of no response... @@ -596,18 +610,20 @@ START_TEST(test_client_invalid) TCP_CLIENT_CONNECTING, tcp_con_status(conn)); // After 5s... c_sleep(5000); - unix_time_update(); - do_TCP_connection(conn, nullptr); + mono_time_update(mono_time); + do_TCP_connection(mono_time, conn, nullptr); ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONNECTING, "Wrong status. Expected: %d, is: %d.", TCP_CLIENT_CONNECTING, tcp_con_status(conn)); // 11s... (Should wait for 10 before giving up.) c_sleep(6000); - unix_time_update(); - do_TCP_connection(conn, nullptr); + mono_time_update(mono_time); + do_TCP_connection(mono_time, conn, nullptr); ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %d, is: %d.", TCP_CLIENT_DISCONNECTED, tcp_con_status(conn)); kill_TCP_connection(conn); + + mono_time_free(mono_time); } END_TEST @@ -639,8 +655,9 @@ static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t START_TEST(test_tcp_connection) { + Mono_Time *mono_time = mono_time_new(); + tcp_data_callback_called = 0; - unix_time_update(); uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; crypto_new_keypair(self_public_key, self_secret_key); @@ -650,11 +667,11 @@ START_TEST(test_tcp_connection) TCP_Proxy_Info proxy_info; proxy_info.proxy_type = TCP_PROXY_NONE; crypto_new_keypair(self_public_key, self_secret_key); - TCP_Connections *tc_1 = new_tcp_connections(self_secret_key, &proxy_info); + TCP_Connections *tc_1 = new_tcp_connections(mono_time, self_secret_key, &proxy_info); ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_1), self_public_key) == 0, "Wrong public key"); crypto_new_keypair(self_public_key, self_secret_key); - TCP_Connections *tc_2 = new_tcp_connections(self_secret_key, &proxy_info); + TCP_Connections *tc_2 = new_tcp_connections(mono_time, self_secret_key, &proxy_info); ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_2), self_public_key) == 0, "Wrong public key"); IP_Port ip_port_tcp_s; @@ -676,17 +693,17 @@ START_TEST(test_tcp_connection) ck_assert_msg(new_tcp_connection_to(tc_2, tcp_connections_public_key(tc_1), 123) == -1, "Managed to readd same connection\n"); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); @@ -695,7 +712,7 @@ START_TEST(test_tcp_connection) ck_assert_msg(ret == 0, "could not send packet."); set_packet_tcp_connection_callback(tc_2, &tcp_data_callback, (void *) 120397); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); @@ -704,7 +721,7 @@ START_TEST(test_tcp_connection) ck_assert_msg(tcp_connection_to_online_tcp_relays(tc_1, 0) == 1, "Wrong number of connected relays"); ck_assert_msg(kill_tcp_connection_to(tc_1, 0) == 0, "could not kill connection to\n"); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); @@ -715,6 +732,8 @@ START_TEST(test_tcp_connection) kill_TCP_server(tcp_s); kill_tcp_connections(tc_1); kill_tcp_connections(tc_2); + + mono_time_free(mono_time); } END_TEST @@ -741,10 +760,11 @@ static int tcp_oobdata_callback(void *object, const uint8_t *public_key, unsigne START_TEST(test_tcp_connection2) { + Mono_Time *mono_time = mono_time_new(); + tcp_oobdata_callback_called = 0; tcp_data_callback_called = 0; - unix_time_update(); uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; crypto_new_keypair(self_public_key, self_secret_key); @@ -754,11 +774,11 @@ START_TEST(test_tcp_connection2) TCP_Proxy_Info proxy_info; proxy_info.proxy_type = TCP_PROXY_NONE; crypto_new_keypair(self_public_key, self_secret_key); - TCP_Connections *tc_1 = new_tcp_connections(self_secret_key, &proxy_info); + TCP_Connections *tc_1 = new_tcp_connections(mono_time, self_secret_key, &proxy_info); ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_1), self_public_key) == 0, "Wrong public key"); crypto_new_keypair(self_public_key, self_secret_key); - TCP_Connections *tc_2 = new_tcp_connections(self_secret_key, &proxy_info); + TCP_Connections *tc_2 = new_tcp_connections(mono_time, self_secret_key, &proxy_info); ck_assert_msg(public_key_cmp(tcp_connections_public_key(tc_2), self_public_key) == 0, "Wrong public key"); IP_Port ip_port_tcp_s; @@ -774,17 +794,17 @@ START_TEST(test_tcp_connection2) ck_assert_msg(add_tcp_relay_global(tc_2, ip_port_tcp_s, tcp_server_public_key(tcp_s)) == 0, "Could not add global relay"); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); @@ -794,14 +814,14 @@ START_TEST(test_tcp_connection2) set_oob_packet_tcp_connection_callback(tc_2, &tcp_oobdata_callback, tc_2); set_packet_tcp_connection_callback(tc_1, &tcp_data_callback, (void *) 120397); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); ck_assert_msg(tcp_oobdata_callback_called, "could not recv packet."); - do_TCP_server_delay(tcp_s, 50); + do_TCP_server_delay(tcp_s, mono_time, 50); do_tcp_connections(tc_1, nullptr); do_tcp_connections(tc_2, nullptr); @@ -812,6 +832,8 @@ START_TEST(test_tcp_connection2) kill_TCP_server(tcp_s); kill_tcp_connections(tc_1); kill_tcp_connections(tc_2); + + mono_time_free(mono_time); } END_TEST diff --git a/auto_tests/dht_test.c b/auto_tests/dht_test.c index 2f273727a..009c0bbdd 100644 --- a/auto_tests/dht_test.c +++ b/auto_tests/dht_test.c @@ -32,39 +32,39 @@ static inline IP get_loopback() return ip; } -static void mark_bad(IPPTsPng *ipptp) +static void mark_bad(const Mono_Time *mono_time, IPPTsPng *ipptp) { - ipptp->timestamp = unix_time() - 2 * BAD_NODE_TIMEOUT; + ipptp->timestamp = mono_time_get(mono_time) - 2 * BAD_NODE_TIMEOUT; ipptp->hardening.routes_requests_ok = 0; ipptp->hardening.send_nodes_ok = 0; ipptp->hardening.testing_requests = 0; } -static void mark_possible_bad(IPPTsPng *ipptp) +static void mark_possible_bad(const Mono_Time *mono_time, IPPTsPng *ipptp) { - ipptp->timestamp = unix_time(); + ipptp->timestamp = mono_time_get(mono_time); ipptp->hardening.routes_requests_ok = 0; ipptp->hardening.send_nodes_ok = 0; ipptp->hardening.testing_requests = 0; } -static void mark_good(IPPTsPng *ipptp) +static void mark_good(const Mono_Time *mono_time, IPPTsPng *ipptp) { - ipptp->timestamp = unix_time(); + ipptp->timestamp = mono_time_get(mono_time); ipptp->hardening.routes_requests_ok = (HARDENING_ALL_OK >> 0) & 1; ipptp->hardening.send_nodes_ok = (HARDENING_ALL_OK >> 1) & 1; ipptp->hardening.testing_requests = (HARDENING_ALL_OK >> 2) & 1; } -static void mark_all_good(Client_data *list, uint32_t length, uint8_t ipv6) +static void mark_all_good(const Mono_Time *mono_time, Client_data *list, uint32_t length, uint8_t ipv6) { uint32_t i; for (i = 0; i < length; ++i) { if (ipv6) { - mark_good(&list[i].assoc6); + mark_good(mono_time, &list[i].assoc6); } else { - mark_good(&list[i].assoc4); + mark_good(mono_time, &list[i].assoc4); } } } @@ -183,7 +183,7 @@ static void test_addto_lists_bad(DHT *dht, uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0; random_bytes(public_key, sizeof(public_key)); - mark_all_good(list, length, ipv6); + mark_all_good(dht->mono_time, list, length, ipv6); test1 = random_u32() % (length / 3); test2 = random_u32() % (length / 3) + length / 3; @@ -196,13 +196,13 @@ static void test_addto_lists_bad(DHT *dht, // mark nodes as "bad" if (ipv6) { - mark_bad(&list[test1].assoc6); - mark_bad(&list[test2].assoc6); - mark_bad(&list[test3].assoc6); + mark_bad(dht->mono_time, &list[test1].assoc6); + mark_bad(dht->mono_time, &list[test2].assoc6); + mark_bad(dht->mono_time, &list[test3].assoc6); } else { - mark_bad(&list[test1].assoc4); - mark_bad(&list[test2].assoc4); - mark_bad(&list[test3].assoc4); + mark_bad(dht->mono_time, &list[test1].assoc4); + mark_bad(dht->mono_time, &list[test2].assoc4); + mark_bad(dht->mono_time, &list[test3].assoc4); } ip_port->port += 1; @@ -227,7 +227,7 @@ static void test_addto_lists_possible_bad(DHT *dht, uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0; random_bytes(public_key, sizeof(public_key)); - mark_all_good(list, length, ipv6); + mark_all_good(dht->mono_time, list, length, ipv6); test1 = random_u32() % (length / 3); test2 = random_u32() % (length / 3) + length / 3; @@ -240,13 +240,13 @@ static void test_addto_lists_possible_bad(DHT *dht, // mark nodes as "possibly bad" if (ipv6) { - mark_possible_bad(&list[test1].assoc6); - mark_possible_bad(&list[test2].assoc6); - mark_possible_bad(&list[test3].assoc6); + mark_possible_bad(dht->mono_time, &list[test1].assoc6); + mark_possible_bad(dht->mono_time, &list[test2].assoc6); + mark_possible_bad(dht->mono_time, &list[test3].assoc6); } else { - mark_possible_bad(&list[test1].assoc4); - mark_possible_bad(&list[test2].assoc4); - mark_possible_bad(&list[test3].assoc4); + mark_possible_bad(dht->mono_time, &list[test1].assoc4); + mark_possible_bad(dht->mono_time, &list[test2].assoc4); + mark_possible_bad(dht->mono_time, &list[test3].assoc4); } ip_port->port += 1; @@ -288,7 +288,7 @@ static void test_addto_lists_good(DHT *dht, uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t ipv6 = net_family_is_ipv6(ip_port->ip.family) ? 1 : 0; - mark_all_good(list, length, ipv6); + mark_all_good(dht->mono_time, list, length, ipv6); // check "good" client id replacement do { @@ -319,10 +319,13 @@ static void test_addto_lists(IP ip) uint32_t index = 1; logger_callback_log(log, (logger_cb *)print_debug_log, nullptr, &index); + Mono_Time *mono_time = mono_time_new(); + ck_assert_msg(mono_time != nullptr, "Failed to create Mono_Time"); + Networking_Core *net = new_networking(log, ip, TOX_PORT_DEFAULT); ck_assert_msg(net != nullptr, "Failed to create Networking_Core"); - DHT *dht = new_dht(log, net, true); + DHT *dht = new_dht(log, mono_time, net, true); ck_assert_msg(dht != nullptr, "Failed to create DHT"); IP_Port ip_port; @@ -451,6 +454,7 @@ static void test_list_main(void) { DHT *dhts[NUM_DHT]; Logger *logs[NUM_DHT]; + Mono_Time *mono_times[NUM_DHT]; uint32_t index[NUM_DHT]; uint8_t cmp_list1[NUM_DHT][MAX_FRIEND_CLIENTS][CRYPTO_PUBLIC_KEY_SIZE + 1]; @@ -466,7 +470,9 @@ static void test_list_main(void) index[i] = i + 1; logger_callback_log(logs[i], (logger_cb *)print_debug_log, nullptr, &index[i]); - dhts[i] = new_dht(logs[i], new_networking(logs[i], ip, DHT_DEFAULT_PORT + i), true); + mono_times[i] = mono_time_new(); + + dhts[i] = new_dht(logs[i], mono_times[i], new_networking(logs[i], ip, DHT_DEFAULT_PORT + i), true); ck_assert_msg(dhts[i] != nullptr, "Failed to create dht instances %u", i); ck_assert_msg(net_port(dhts[i]->net) != DHT_DEFAULT_PORT + i, "Bound to wrong port: %d", net_port(dhts[i]->net)); @@ -573,6 +579,7 @@ static void test_list_main(void) Networking_Core *n = dhts[i]->net; kill_dht(dhts[i]); kill_networking(n); + mono_time_free(mono_times[i]); logger_kill(logs[i]); } } @@ -598,10 +605,9 @@ static void test_DHT_test(void) uint32_t to_comp = 8394782; DHT *dhts[NUM_DHT]; Logger *logs[NUM_DHT]; + Mono_Time *mono_times[NUM_DHT]; uint32_t index[NUM_DHT]; - unix_time_update(); - uint32_t i, j; for (i = 0; i < NUM_DHT; ++i) { @@ -612,7 +618,9 @@ static void test_DHT_test(void) index[i] = i + 1; logger_callback_log(logs[i], (logger_cb *)print_debug_log, nullptr, &index[i]); - dhts[i] = new_dht(logs[i], new_networking(logs[i], ip, DHT_DEFAULT_PORT + i), true); + mono_times[i] = mono_time_new(); + + dhts[i] = new_dht(logs[i], mono_times[i], new_networking(logs[i], ip, DHT_DEFAULT_PORT + i), true); ck_assert_msg(dhts[i] != nullptr, "Failed to create dht instances %u", i); ck_assert_msg(net_port(dhts[i]->net) != DHT_DEFAULT_PORT + i, "Bound to wrong port"); } @@ -663,7 +671,7 @@ loop_top: } for (i = 0; i < NUM_DHT; ++i) { - unix_time_update(); + mono_time_update(mono_times[i]); networking_poll(dhts[i]->net, nullptr); do_dht(dhts[i]); } @@ -675,6 +683,7 @@ loop_top: Networking_Core *n = dhts[i]->net; kill_dht(dhts[i]); kill_networking(n); + mono_time_free(mono_times[i]); logger_kill(logs[i]); } } @@ -792,8 +801,6 @@ int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - unix_time_update(); - test_dht_create_packet(); test_dht_node_packing(); diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index b8fbbc1f9..dd644e50d 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c @@ -341,13 +341,15 @@ int main(void) good_id = hex_string_to_bin(good_id_str); bad_id = hex_string_to_bin(bad_id_str); + Mono_Time *mono_time = mono_time_new(); + /* IPv6 status from global define */ Messenger_Options options = {0}; options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; options.port_range[0] = 41234; options.port_range[1] = 44234; options.log_callback = (logger_cb *)print_debug_log; - m = new_messenger(&options, nullptr); + m = new_messenger(mono_time, &options, nullptr); /* setup a default friend and friendnum */ if (m_addfriend_norequest(m, friend_id) < 0) { @@ -375,6 +377,7 @@ int main(void) free(bad_id); kill_messenger(m); + mono_time_free(mono_time); return number_failed; } diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index 0a9a05770..a11fb8078 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -31,7 +31,7 @@ static inline IP get_loopback() } static void do_onion(Onion *onion) { - unix_time_update(); + mono_time_update(onion->mono_time); networking_poll(onion->net, nullptr); do_dht(onion->dht); @@ -152,7 +152,7 @@ static int handle_test_4(void *object, IP_Port source, const uint8_t *packet, ui return 0; } -START_TEST(test_basic) +static void test_basic(void) { uint32_t index[] = { 1, 2, 3 }; Logger *log1 = logger_new(); @@ -160,9 +160,12 @@ START_TEST(test_basic) Logger *log2 = logger_new(); logger_callback_log(log2, (logger_cb *)print_debug_log, nullptr, &index[1]); + Mono_Time *mono_time1 = mono_time_new(); + Mono_Time *mono_time2 = mono_time_new(); + IP ip = get_loopback(); - Onion *onion1 = new_onion(new_dht(log1, new_networking(log1, ip, 36567), true)); - Onion *onion2 = new_onion(new_dht(log2, new_networking(log2, ip, 36568), true)); + Onion *onion1 = new_onion(mono_time1, new_dht(log1, mono_time1, new_networking(log1, ip, 36567), true)); + Onion *onion2 = new_onion(mono_time2, new_dht(log2, mono_time2, new_networking(log2, ip, 36568), true)); ck_assert_msg((onion1 != nullptr) && (onion2 != nullptr), "Onion failed initializing."); networking_registerhandler(onion2->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_test_1, onion2); @@ -202,8 +205,8 @@ START_TEST(test_basic) do_onion(onion2); } - Onion_Announce *onion1_a = new_onion_announce(onion1->dht); - Onion_Announce *onion2_a = new_onion_announce(onion2->dht); + Onion_Announce *onion1_a = new_onion_announce(mono_time1, onion1->dht); + Onion_Announce *onion2_a = new_onion_announce(mono_time2, onion2->dht); networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1); ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing."); uint8_t zeroes[64] = {0}; @@ -229,7 +232,7 @@ START_TEST(test_basic) random_bytes(sb_data, sizeof(sb_data)); memcpy(&s, sb_data, sizeof(uint64_t)); memcpy(onion_announce_entry_public_key(onion2_a, 1), dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE); - onion_announce_entry_set_time(onion2_a, 1, unix_time()); + onion_announce_entry_set_time(onion2_a, 1, mono_time_get(mono_time2)); networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); send_announce_request(onion1->net, &path, nodes[3], dht_get_self_public_key(onion1->dht), @@ -250,7 +253,9 @@ START_TEST(test_basic) Logger *log3 = logger_new(); logger_callback_log(log3, (logger_cb *)print_debug_log, nullptr, &index[2]); - Onion *onion3 = new_onion(new_dht(log3, new_networking(log3, ip, 36569), true)); + Mono_Time *mono_time3 = mono_time_new(); + + Onion *onion3 = new_onion(mono_time3, new_dht(log3, mono_time3, new_networking(log3, ip, 36569), true)); ck_assert_msg((onion3 != nullptr), "Onion failed initializing."); random_nonce(nonce); @@ -278,6 +283,7 @@ START_TEST(test_basic) kill_onion(onion); kill_dht(dht); kill_networking(net); + mono_time_free(mono_time3); logger_kill(log3); } @@ -289,6 +295,7 @@ START_TEST(test_basic) kill_onion(onion); kill_dht(dht); kill_networking(net); + mono_time_free(mono_time2); logger_kill(log2); } @@ -300,13 +307,14 @@ START_TEST(test_basic) kill_onion(onion); kill_dht(dht); kill_networking(net); + mono_time_free(mono_time1); logger_kill(log1); } } -END_TEST typedef struct { Logger *log; + Mono_Time *mono_time; Onion *onion; Onion_Announce *onion_a; Onion_Client *onion_c; @@ -329,56 +337,67 @@ static Onions *new_onions(uint16_t port, uint32_t *index) return nullptr; } - unix_time_update(); - logger_callback_log(on->log, (logger_cb *)print_debug_log, nullptr, index); + on->mono_time = mono_time_new(); + + if (!on->mono_time) { + logger_kill(on->log); + free(on); + return nullptr; + } + Networking_Core *net = new_networking(on->log, ip, port); if (!net) { + mono_time_free(on->mono_time); logger_kill(on->log); free(on); return nullptr; } - DHT *dht = new_dht(on->log, net, true); + DHT *dht = new_dht(on->log, on->mono_time, net, true); if (!dht) { kill_networking(net); + mono_time_free(on->mono_time); logger_kill(on->log); free(on); return nullptr; } - on->onion = new_onion(dht); + on->onion = new_onion(on->mono_time, dht); if (!on->onion) { kill_dht(dht); kill_networking(net); + mono_time_free(on->mono_time); logger_kill(on->log); free(on); return nullptr; } - on->onion_a = new_onion_announce(dht); + on->onion_a = new_onion_announce(on->mono_time, dht); if (!on->onion_a) { kill_onion(on->onion); kill_dht(dht); kill_networking(net); + mono_time_free(on->mono_time); logger_kill(on->log); free(on); return nullptr; } TCP_Proxy_Info inf = {{{{0}}}}; - on->onion_c = new_onion_client(new_net_crypto(on->log, dht, &inf)); + on->onion_c = new_onion_client(on->mono_time, new_net_crypto(on->log, on->mono_time, dht, &inf)); if (!on->onion_c) { kill_onion_announce(on->onion_a); kill_onion(on->onion); kill_dht(dht); kill_networking(net); + mono_time_free(on->mono_time); logger_kill(on->log); free(on); return nullptr; @@ -389,7 +408,7 @@ static Onions *new_onions(uint16_t port, uint32_t *index) static void do_onions(Onions *on) { - unix_time_update(); + mono_time_update(on->mono_time); networking_poll(on->onion->net, nullptr); do_dht(on->onion->dht); @@ -407,6 +426,7 @@ static void kill_onions(Onions *on) kill_net_crypto(c); kill_dht(dht); kill_networking(net); + mono_time_free(on->mono_time); logger_kill(on->log); free(on); } @@ -468,7 +488,7 @@ static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_pub } } -START_TEST(test_announce) +static void test_announce(void) { uint32_t i, j; uint32_t index[NUM_ONIONS]; @@ -553,29 +573,13 @@ START_TEST(test_announce) kill_onions(onions[i]); } } -END_TEST - -static Suite *onion_suite(void) -{ - Suite *s = suite_create("Onion"); - - DEFTESTCASE_SLOW(basic, 5); - DEFTESTCASE_SLOW(announce, 70); - return s; -} int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - Suite *onion = onion_suite(); - SRunner *test_runner = srunner_create(onion); + test_basic(); + test_announce(); - int number_failed = 0; - srunner_run_all(test_runner, CK_NORMAL); - number_failed = srunner_ntests_failed(test_runner); - - srunner_free(test_runner); - - return number_failed; + return 0; } diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index fc1bba47d..6af042ace 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -115,12 +115,11 @@ int main(int argc, char *argv[]) IP ip; ip_init(&ip, ipv6enabled); - unix_time_update(); - Logger *logger = logger_new(); - DHT *dht = new_dht(logger, new_networking(logger, ip, PORT), true); - Onion *onion = new_onion(dht); - Onion_Announce *onion_a = new_onion_announce(dht); + Mono_Time *mono_time = mono_time_new(); + DHT *dht = new_dht(logger, mono_time, new_networking(logger, ip, PORT), true); + Onion *onion = new_onion(mono_time, dht); + Onion_Announce *onion_a = new_onion_announce(mono_time, dht); #ifdef DHT_NODE_EXTRA_PACKETS 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[]) lan_discovery_init(dht); while (1) { - unix_time_update(); + mono_time_update(mono_time); if (is_waiting_for_dht_connection && dht_isconnected(dht)) { printf("Connected to other bootstrap node successfully.\n"); @@ -197,13 +196,13 @@ int main(int argc, char *argv[]) do_dht(dht); - if (is_timeout(last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) { + if (mono_time_is_timeout(mono_time, last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) { lan_discovery_send(net_htons(PORT), dht); - last_LANdiscovery = unix_time(); + last_LANdiscovery = mono_time_get(mono_time); } #ifdef TCP_RELAY_ENABLED - do_TCP_server(tcp_s); + do_TCP_server(tcp_s, mono_time); #endif networking_poll(dht_get_net(dht), nullptr); diff --git a/other/astyle/format-source b/other/astyle/format-source index 5b560622f..5e139d896 100755 --- a/other/astyle/format-source +++ b/other/astyle/format-source @@ -36,11 +36,13 @@ apidsl_curl() { # Check if apidsl generated sources are up to date. $APIDSL toxcore/crypto_core.api.h > toxcore/crypto_core.h & +$APIDSL toxcore/ping.api.h > toxcore/ping.h & +$APIDSL toxcore/ping_array.api.h > toxcore/ping_array.h & $APIDSL toxcore/tox.api.h > toxcore/tox.h & $APIDSL toxav/toxav.api.h > toxav/toxav.h & $APIDSL toxencryptsave/toxencryptsave.api.h > toxencryptsave/toxencryptsave.h & -wait; wait; wait; wait +wait; wait; wait; wait; wait; wait if grep '' */*.h; then 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 d75018d83..807e11009 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[]) IP ip; ip_init(&ip, enable_ipv6); - unix_time_update(); - Logger *logger = logger_new(); Networking_Core *net = new_networking(logger, ip, port); @@ -255,19 +253,31 @@ int main(int argc, char *argv[]) } } - DHT *dht = new_dht(logger, net, true); + Mono_Time *const mono_time = mono_time_new(); - if (dht == nullptr) { - log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n"); + if (mono_time == nullptr) { + log_write(LOG_LEVEL_ERROR, "Couldn't initialize monotonic timer. Exiting.\n"); logger_kill(logger); return 1; } - Onion *onion = new_onion(dht); - Onion_Announce *onion_a = new_onion_announce(dht); + mono_time_update(mono_time); + + DHT *const dht = new_dht(logger, mono_time, net, true); + + if (dht == nullptr) { + log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n"); + mono_time_free(mono_time); + logger_kill(logger); + return 1; + } + + Onion *onion = new_onion(mono_time, dht); + Onion_Announce *onion_a = new_onion_announce(mono_time, dht); if (!(onion && onion_a)) { log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion. Exiting.\n"); + mono_time_free(mono_time); logger_kill(logger); return 1; } @@ -277,6 +287,7 @@ int main(int argc, char *argv[]) log_write(LOG_LEVEL_INFO, "Set MOTD successfully.\n"); } else { log_write(LOG_LEVEL_ERROR, "Couldn't set MOTD: %s. Exiting.\n", motd); + mono_time_free(mono_time); logger_kill(logger); return 1; } @@ -288,6 +299,7 @@ int main(int argc, char *argv[]) log_write(LOG_LEVEL_INFO, "Keys are managed successfully.\n"); } else { log_write(LOG_LEVEL_ERROR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); + mono_time_free(mono_time); logger_kill(logger); return 1; } @@ -299,6 +311,7 @@ int main(int argc, char *argv[]) if (enable_tcp_relay) { if (tcp_relay_port_count == 0) { log_write(LOG_LEVEL_ERROR, "No TCP relay ports read. Exiting.\n"); + mono_time_free(mono_time); logger_kill(logger); return 1; } @@ -312,6 +325,7 @@ int main(int argc, char *argv[]) log_write(LOG_LEVEL_INFO, "Initialized Tox TCP server successfully.\n"); } else { log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox TCP server. Exiting.\n"); + mono_time_free(mono_time); logger_kill(logger); return 1; } @@ -321,6 +335,7 @@ int main(int argc, char *argv[]) log_write(LOG_LEVEL_INFO, "List of bootstrap nodes read successfully.\n"); } else { log_write(LOG_LEVEL_ERROR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); + mono_time_free(mono_time); logger_kill(logger); return 1; } @@ -338,17 +353,17 @@ int main(int argc, char *argv[]) } while (1) { - unix_time_update(); + mono_time_update(mono_time); do_dht(dht); - if (enable_lan_discovery && is_timeout(last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) { + if (enable_lan_discovery && mono_time_is_timeout(mono_time, last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) { lan_discovery_send(net_htons_port, dht); - last_LANdiscovery = unix_time(); + last_LANdiscovery = mono_time_get(mono_time); } if (enable_tcp_relay) { - do_TCP_server(tcp_server); + do_TCP_server(tcp_server, mono_time); } networking_poll(dht_get_net(dht), nullptr); diff --git a/testing/DHT_test.c b/testing/DHT_test.c index 1d01f0a2a..5e5f68349 100644 --- a/testing/DHT_test.c +++ b/testing/DHT_test.c @@ -190,11 +190,11 @@ int main(int argc, char *argv[]) IP ip; ip_init(&ip, ipv6enabled); - DHT *dht = new_dht(nullptr, new_networking(nullptr, ip, PORT), true); + Mono_Time *const mono_time = mono_time_new(); + DHT *dht = new_dht(nullptr, mono_time, new_networking(nullptr, ip, PORT), true); printf("OUR ID: "); - uint32_t i; - for (i = 0; i < 32; i++) { + for (uint32_t i = 0; i < 32; i++) { const uint8_t *const self_public_key = dht_get_self_public_key(dht); if (self_public_key[i] < 16) { @@ -238,7 +238,7 @@ int main(int argc, char *argv[]) #endif while (1) { - unix_time_update(); + mono_time_update(mono_time); do_dht(dht); diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index a5abfda0d..880fc5145 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -107,11 +107,16 @@ int main(int argc, char *argv[]) exit(0); } - unix_time_update(); + Mono_Time *const mono_time = mono_time_new(); + + if (mono_time == nullptr) { + fputs("Failed to allocate monotonic timer datastructure\n", stderr); + exit(0); + } Messenger_Options options = {0}; options.ipv6enabled = ipv6enabled; - m = new_messenger(&options, nullptr); + m = new_messenger(mono_time, &options, nullptr); if (!m) { fputs("Failed to allocate messenger datastructure\n", stderr); @@ -180,7 +185,7 @@ int main(int argc, char *argv[]) perror("Initialization"); while (1) { - unix_time_update(); + mono_time_update(mono_time); uint8_t name[128]; const char *const filename = "Save.bak"; diff --git a/toxav/groupav.c b/toxav/groupav.c index b10a7f8e5..40338fb86 100644 --- a/toxav/groupav.c +++ b/toxav/groupav.c @@ -97,13 +97,13 @@ static void terminate_queue(Group_JitterBuffer *q) /* Return 0 if packet was queued, -1 if it wasn't. */ -static int queue(Group_JitterBuffer *q, Group_Audio_Packet *pk) +static int queue(Group_JitterBuffer *q, const Mono_Time *mono_time, Group_Audio_Packet *pk) { uint16_t sequnum = pk->sequnum; unsigned int num = sequnum % q->size; - if (!is_timeout(q->last_queued_time, GROUP_JBUF_DEAD_SECONDS)) { + if (!mono_time_is_timeout(mono_time, q->last_queued_time, GROUP_JBUF_DEAD_SECONDS)) { if ((uint32_t)(sequnum - q->bottom) > (1 << 15)) { /* Drop old packet. */ return -1; @@ -115,7 +115,7 @@ static int queue(Group_JitterBuffer *q, Group_Audio_Packet *pk) q->bottom = sequnum - q->capacity; q->queue[num] = pk; q->top = sequnum + 1; - q->last_queued_time = unix_time(); + q->last_queued_time = mono_time_get(mono_time); return 0; } @@ -129,7 +129,7 @@ static int queue(Group_JitterBuffer *q, Group_Audio_Packet *pk) q->top = sequnum + 1; } - q->last_queued_time = unix_time(); + q->last_queued_time = mono_time_get(mono_time); return 0; } @@ -178,6 +178,7 @@ typedef struct Group_AV { } Group_AV; typedef struct Group_Peer_AV { + const Mono_Time *mono_time; Group_JitterBuffer *buffer; OpusDecoder *audio_decoder; @@ -264,6 +265,7 @@ static void group_av_peer_new(void *object, uint32_t groupnumber, uint32_t frien return; } + peer_av->mono_time = group_av->g_c->mono_time; peer_av->buffer = create_queue(GROUP_JBUF_SIZE); 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_ pk->length = length - sizeof(uint16_t); memcpy(pk->data, packet + sizeof(uint16_t), pk->length); - if (queue(peer_av->buffer, pk) == -1) { + if (queue(peer_av->buffer, peer_av->mono_time, pk) == -1) { free(pk); return -1; } diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 94928b75c..46db6e763 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -93,6 +93,7 @@ typedef struct Cryptopacket_Handler { struct DHT { const Logger *log; + Mono_Time *mono_time; Networking_Core *net; bool hole_punching_enabled; @@ -243,7 +244,8 @@ static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2) * If shared key is already in shared_keys, copy it to shared_key. * else generate it into shared_key and copy it to shared_keys */ -void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key) +void get_shared_key(const Mono_Time *mono_time, Shared_Keys *shared_keys, uint8_t *shared_key, + const uint8_t *secret_key, const uint8_t *public_key) { uint32_t num = ~0; uint32_t curr = 0; @@ -256,12 +258,12 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t if (id_equal(public_key, key->public_key)) { memcpy(shared_key, key->shared_key, CRYPTO_SHARED_KEY_SIZE); ++key->times_requested; - key->time_last_requested = unix_time(); + key->time_last_requested = mono_time_get(mono_time); return; } if (num != 0) { - if (is_timeout(key->time_last_requested, KEYS_TIMEOUT)) { + if (mono_time_is_timeout(mono_time, key->time_last_requested, KEYS_TIMEOUT)) { num = 0; curr = index; } 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 key->times_requested = 1; memcpy(key->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(key->shared_key, shared_key, CRYPTO_SHARED_KEY_SIZE); - key->time_last_requested = unix_time(); + key->time_last_requested = mono_time_get(mono_time); } } @@ -292,7 +294,7 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t */ void dht_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key) { - get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key); + get_shared_key(dht->mono_time, &dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key); } /* 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 */ void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key) { - get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key); + get_shared_key(dht->mono_time, &dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key); } #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, /* Update ip_port of client if it's needed. */ -static void update_client(const Logger *log, int index, Client_data *client, IP_Port ip_port) +static void update_client(const Logger *log, const Mono_Time *mono_time, int index, Client_data *client, + IP_Port ip_port) { IPPTsPng *assoc; int ip_version; @@ -697,7 +700,7 @@ static void update_client(const Logger *log, int index, Client_data *client, IP_ } assoc->ip_port = ip_port; - assoc->timestamp = unix_time(); + assoc->timestamp = mono_time_get(mono_time); } /* 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_ * * return True(1) or False(0) */ -static int client_or_ip_port_in_list(const Logger *log, Client_data *list, uint16_t length, const uint8_t *public_key, - IP_Port ip_port) +static int client_or_ip_port_in_list(const Logger *log, const Mono_Time *mono_time, Client_data *list, uint16_t length, + const uint8_t *public_key, IP_Port ip_port) { - const uint64_t temp_time = unix_time(); + const uint64_t temp_time = mono_time_get(mono_time); uint32_t index = index_of_client_pk(list, length, public_key); /* if public_key is in list, find it and maybe overwrite ip_port */ if (index != UINT32_MAX) { - update_client(log, index, &list[index], ip_port); + update_client(log, mono_time, index, &list[index], ip_port); return 1; } @@ -793,7 +796,7 @@ static uint8_t hardening_correct(const Hardening *h) /* * helper for get_close_nodes(). argument list is a monster :D */ -static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list, +static void get_close_nodes_inner(const Mono_Time *mono_time, const uint8_t *public_key, Node_format *nodes_list, Family sa_family, const Client_data *client_list, uint32_t client_list_length, uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) { @@ -824,7 +827,7 @@ static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_ } /* node not in a good condition? */ - if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) { + if (mono_time_is_timeout(mono_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) { continue; } @@ -862,14 +865,14 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N Family sa_family, uint8_t is_LAN, uint8_t want_good) { uint32_t num_nodes = 0; - get_close_nodes_inner(public_key, nodes_list, sa_family, + get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family, dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0); /* TODO(irungentoo): uncomment this when hardening is added to close friend clients */ #if 0 for (uint32_t i = 0; i < dht->num_friends; ++i) { - get_close_nodes_inner(dht, public_key, nodes_list, sa_family, + get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &num_nodes, is_LAN, want_good); } @@ -877,7 +880,7 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N #endif for (uint32_t i = 0; i < dht->num_friends; ++i) { - get_close_nodes_inner(public_key, nodes_list, sa_family, + get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &num_nodes, is_LAN, 0); } @@ -893,13 +896,14 @@ int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *node } typedef struct DHT_Cmp_data { + const Mono_Time *mono_time; const uint8_t *base_public_key; Client_data entry; } DHT_Cmp_data; -static bool assoc_timeout(const IPPTsPng *assoc) +static bool assoc_timeout(const Mono_Time *mono_time, const IPPTsPng *assoc) { - return is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT); + return mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT); } static bool incorrect_hardening(const IPPTsPng *assoc) @@ -916,8 +920,8 @@ static int cmp_dht_entry(const void *a, const void *b) const Client_data entry2 = cmp2.entry; const uint8_t *cmp_public_key = cmp1.base_public_key; - bool t1 = assoc_timeout(&entry1.assoc4) && assoc_timeout(&entry1.assoc6); - bool t2 = assoc_timeout(&entry2.assoc4) && assoc_timeout(&entry2.assoc6); + bool t1 = assoc_timeout(cmp1.mono_time, &entry1.assoc4) && assoc_timeout(cmp1.mono_time, &entry1.assoc6); + bool t2 = assoc_timeout(cmp2.mono_time, &entry2.assoc4) && assoc_timeout(cmp2.mono_time, &entry2.assoc6); if (t1 && t2) { return 0; @@ -960,20 +964,23 @@ static int cmp_dht_entry(const void *a, const void *b) * return 0 if node can't be stored. * return 1 if it can. */ -static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key) +static unsigned int store_node_ok(const Client_data *client, const Mono_Time *mono_time, const uint8_t *public_key, + const uint8_t *comp_public_key) { - return (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) - && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) + return (mono_time_is_timeout(mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) + && mono_time_is_timeout(mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) || id_closest(comp_public_key, client->public_key, public_key) == 2; } -static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key) +static void sort_client_list(Client_data *list, const Mono_Time *mono_time, unsigned int length, + const uint8_t *comp_public_key) { // Pass comp_public_key to qsort with each Client_data entry, so the // comparison function can use it as the base of comparison. VLA(DHT_Cmp_data, cmp_list, length); for (uint32_t i = 0; i < length; ++i) { + cmp_list[i].mono_time = mono_time; cmp_list[i].base_public_key = comp_public_key; cmp_list[i].entry = list[i]; } @@ -985,7 +992,7 @@ static void sort_client_list(Client_data *list, unsigned int length, const uint8 } } -static void update_client_with_reset(Client_data *client, const IP_Port *ip_port) +static void update_client_with_reset(const Mono_Time *mono_time, Client_data *client, const IP_Port *ip_port) { IPPTsPng *ipptp_write = nullptr; IPPTsPng *ipptp_clear = nullptr; @@ -999,7 +1006,7 @@ static void update_client_with_reset(Client_data *client, const IP_Port *ip_port } ipptp_write->ip_port = *ip_port; - ipptp_write->timestamp = unix_time(); + ipptp_write->timestamp = mono_time_get(mono_time); ip_reset(&ipptp_write->ret_ip_port.ip); 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 * than public_key. * * returns true when the item was stored, false otherwise */ -static bool replace_all(Client_data *list, +static bool replace_all(const Mono_Time *mono_time, + Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port, @@ -1032,17 +1040,17 @@ static bool replace_all(Client_data *list, return false; } - if (!store_node_ok(&list[1], public_key, comp_public_key) && - !store_node_ok(&list[0], public_key, comp_public_key)) { + if (!store_node_ok(&list[1], mono_time, public_key, comp_public_key) && + !store_node_ok(&list[0], mono_time, public_key, comp_public_key)) { return false; } - sort_client_list(list, length, comp_public_key); + sort_client_list(list, mono_time, length, comp_public_key); Client_data *const client = &list[0]; id_copy(client->public_key, public_key); - update_client_with_reset(client, &ip_port); + update_client_with_reset(mono_time, client, &ip_port); return true; } @@ -1066,8 +1074,8 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bo * index is left as >= LCLIENT_LENGTH */ Client_data *const client = &dht->close_clientlist[(index * LCLIENT_NODES) + i]; - if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || - !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) || + !mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { continue; } @@ -1076,7 +1084,7 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bo } id_copy(client->public_key, public_key); - update_client_with_reset(client, &ip_port); + update_client_with_reset(dht->mono_time, client, &ip_port); return 0; } @@ -1090,8 +1098,8 @@ bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_ return add_to_close(dht, public_key, ip_port, 1) == 0; } -static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, const uint8_t *public_key, - IP_Port ip_port) +static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, const Mono_Time *mono_time, + const uint8_t *public_key, IP_Port ip_port) { const uint32_t index = index_of_client_pk(list, client_list_length, public_key); @@ -1103,7 +1111,7 @@ static bool is_pk_in_client_list(const Client_data *list, unsigned int client_li ? &list[index].assoc4 : &list[index].assoc6; - return !is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT); + return !mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT); } static 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_ index = LCLIENT_LENGTH - 1; } - return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, public_key, ip_port); + return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->mono_time, public_key, + ip_port); } /* 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 bool store_ok = false; - if (store_node_ok(&dht_friend->client_list[1], public_key, dht_friend->public_key)) { + if (store_node_ok(&dht_friend->client_list[1], dht->mono_time, public_key, dht_friend->public_key)) { store_ok = true; } - if (store_node_ok(&dht_friend->client_list[0], public_key, dht_friend->public_key)) { + if (store_node_ok(&dht_friend->client_list[0], dht->mono_time, public_key, dht_friend->public_key)) { store_ok = true; } unsigned int *const friend_num = &dht_friend->num_to_bootstrap; const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key); - const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, public_key, ip_port); + const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->mono_time, public_key, + ip_port); if (store_ok && index == UINT32_MAX && !pk_in_list) { 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) /* NOTE: Current behavior if there are two clients with the same id is * to replace the first ip by the second. */ - const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->close_clientlist, - LCLIENT_LIST, public_key, ip_port); + const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->close_clientlist, LCLIENT_LIST, + public_key, ip_port); /* add_to_close should be called only if !in_list (don't extract to variable) */ 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) DHT_Friend *friend_foundip = nullptr; for (uint32_t i = 0; i < dht->num_friends; ++i) { - const bool in_list = client_or_ip_port_in_list(dht->log, dht->friends_list[i].client_list, + const bool in_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, ip_port); /* replace_all should be called only if !in_list (don't extract to variable) */ - if (in_list || replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, - ip_port, dht->friends_list[i].public_key)) { + if (in_list + || replace_all(dht->mono_time, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, ip_port, + dht->friends_list[i].public_key)) { DHT_Friend *dht_friend = &dht->friends_list[i]; 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) return used; } -static bool update_client_data(Client_data *array, size_t size, IP_Port ip_port, const uint8_t *pk) +static bool update_client_data(const Mono_Time *mono_time, Client_data *array, size_t size, IP_Port ip_port, + const uint8_t *pk) { - const uint64_t temp_time = unix_time(); + const uint64_t temp_time = mono_time_get(mono_time); const uint32_t index = index_of_client_pk(array, size, pk); if (index == UINT32_MAX) { @@ -1278,7 +1290,7 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_ke } if (id_equal(public_key, dht->self_public_key)) { - update_client_data(dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key); + update_client_data(dht->mono_time, dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key); return; } @@ -1286,7 +1298,7 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_ke if (id_equal(public_key, dht->friends_list[i].public_key)) { Client_data *const client_list = dht->friends_list[i].client_list; - if (update_client_data(client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) { + if (update_client_data(dht->mono_time, client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) { return; } } @@ -1314,9 +1326,9 @@ static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const if (sendback_node != nullptr) { memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format)); - ping_id = ping_array_add(dht->dht_harden_ping_array, plain_message, sizeof(plain_message)); + ping_id = ping_array_add(dht->dht_harden_ping_array, dht->mono_time, plain_message, sizeof(plain_message)); } else { - ping_id = ping_array_add(dht->dht_ping_array, plain_message, sizeof(receiver)); + ping_id = ping_array_add(dht->dht_ping_array, dht->mono_time, plain_message, sizeof(receiver)); } if (ping_id == 0) { @@ -1433,9 +1445,9 @@ static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port no { uint8_t data[sizeof(Node_format) * 2]; - if (ping_array_check(dht->dht_ping_array, data, sizeof(data), ping_id) == sizeof(Node_format)) { + if (ping_array_check(dht->dht_ping_array, dht->mono_time, data, sizeof(data), ping_id) == sizeof(Node_format)) { memset(sendback_node, 0, sizeof(Node_format)); - } else if (ping_array_check(dht->dht_harden_ping_array, data, sizeof(data), ping_id) == sizeof(data)) { + } else if (ping_array_check(dht->dht_harden_ping_array, dht->mono_time, data, sizeof(data), ping_id) == sizeof(data)) { memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format)); } else { return false; @@ -1678,7 +1690,7 @@ int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port) for (const IPPTsPng * const *it = assocs; *it; ++it) { const IPPTsPng *const assoc = *it; - if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { *ip_port = assoc->ip_port; return 1; } @@ -1692,7 +1704,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable) { uint8_t not_kill = 0; - const uint64_t temp_time = unix_time(); + const uint64_t temp_time = mono_time_get(dht->mono_time); uint32_t num_nodes = 0; 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 for (uint32_t j = 0; j < sizeof(assocs) / sizeof(assocs[0]); ++j) { IPPTsPng *const assoc = assocs[j]; - if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, KILL_NODE_TIMEOUT)) { sort = 0; ++not_kill; - if (is_timeout(assoc->last_pinged, PING_INTERVAL)) { + if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) { getnodes(dht, assoc->ip_port, client->public_key, public_key, nullptr); assoc->last_pinged = temp_time; } /* If node is good. */ - if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { client_list[num_nodes] = client; assoc_list[num_nodes] = assoc; ++num_nodes; @@ -1736,10 +1748,11 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co } if (sortable && sort_ok) { - sort_client_list(list, list_count, public_key); + sort_client_list(list, dht->mono_time, list_count, public_key); } - if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) { + if ((num_nodes != 0) && (mono_time_is_timeout(dht->mono_time, *lastgetnode, GET_NODE_INTERVAL) + || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) { uint32_t rand_node = random_u32() % num_nodes; if ((num_nodes - 1) != rand_node) { @@ -1801,7 +1814,7 @@ static void do_Close(DHT *dht) * * so: reset all nodes to be BAD_NODE_TIMEOUT, but not * KILL_NODE_TIMEOUT, so we at least keep trying pings */ - const uint64_t badonly = unix_time() - BAD_NODE_TIMEOUT; + const uint64_t badonly = mono_time_get(dht->mono_time) - BAD_NODE_TIMEOUT; for (size_t i = 0; i < LCLIENT_LIST; ++i) { 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 const Client_data *const client = &dht_friend->client_list[i]; /* If ip is not zero and node is good. */ - if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&client->assoc4.ret_ip_port.ip) + && !mono_time_is_timeout(dht->mono_time, client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) { ipv4s[num_ipv4s] = client->assoc4.ret_ip_port; ++num_ipv4s; } - if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&client->assoc6.ret_ip_port.ip) + && !mono_time_is_timeout(dht->mono_time, client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) { ipv6s[num_ipv6s] = client->assoc6.ret_ip_port; ++num_ipv6s; } if (id_equal(client->public_key, dht_friend->public_key)) { - if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) - || !is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT) + || !mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT)) { return 0; /* direct connectivity */ } } @@ -1997,7 +2012,7 @@ int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *pack const IPPTsPng *const assoc = *it; /* If ip is not zero and node is good. */ - if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&assoc->ret_ip_port.ip) && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { const int retval = sendpacket(dht->net, assoc->ip_port, packet, length); if ((unsigned int)retval == length) { @@ -2039,7 +2054,7 @@ static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t * const IPPTsPng *const assoc = *it; /* If ip is not zero and node is good. */ - if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&assoc->ret_ip_port.ip) && !mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { ip_list[n] = assoc->ip_port; ++n; } @@ -2116,7 +2131,7 @@ static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pu if (packet[0] == NAT_PING_REQUEST) { /* 1 is reply */ send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); - dht_friend->nat.recv_nat_ping_timestamp = unix_time(); + dht_friend->nat.recv_nat_ping_timestamp = mono_time_get(dht->mono_time); return 0; } @@ -2243,7 +2258,7 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, static void do_NAT(DHT *dht) { - const uint64_t temp_time = unix_time(); + const uint64_t temp_time = mono_time_get(dht->mono_time); for (uint32_t i = 0; i < dht->num_friends; ++i) { 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) const IPPTsPng *const temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family); if (temp) { - if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(dht->mono_time, temp->timestamp, BAD_NODE_TIMEOUT)) { ++counter; } } @@ -2464,7 +2479,7 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_ return 1; } - if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { + if (mono_time_is_timeout(dht->mono_time, temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { return 1; } @@ -2512,7 +2527,8 @@ static Node_format random_node(DHT *dht, Family sa_family) * * return the number of nodes. */ -static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes, uint16_t max_num) +static uint16_t list_nodes(Client_data *list, size_t length, const Mono_Time *mono_time, Node_format *nodes, + uint16_t max_num) { if (max_num == 0) { return 0; @@ -2523,11 +2539,11 @@ static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes, for (size_t i = length; i != 0; --i) { const IPPTsPng *assoc = nullptr; - if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(mono_time, list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) { assoc = &list[i - 1].assoc4; } - if (!is_timeout(list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(mono_time, list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) { if (assoc == nullptr) { assoc = &list[i - 1].assoc6; } else if (random_u08() % 2) { @@ -2563,8 +2579,8 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) const uint32_t r = random_u32(); for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { - count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, nodes + count, - max_num - count); + count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, dht->mono_time, + nodes + count, max_num - count); if (count >= max_num) { break; @@ -2580,7 +2596,7 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) */ uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) { - return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num); + return list_nodes(dht->close_clientlist, LCLIENT_LIST, dht->mono_time, nodes, max_num); } #if DHT_HARDENING @@ -2599,12 +2615,12 @@ static void do_hardening(DHT *dht) sa_family = net_family_ipv6; } - if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) { + if (mono_time_is_timeout(dht->mono_time, cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) { continue; } if (cur_iptspng->hardening.send_nodes_ok == 0) { - if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { + if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) { Node_format rand_node = random_node(dht, sa_family); if (!ipport_isset(&rand_node.ip_port)) { @@ -2622,11 +2638,11 @@ static void do_hardening(DHT *dht) // TODO(irungentoo): The search id should maybe not be ours? if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) { memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, CRYPTO_PUBLIC_KEY_SIZE); - cur_iptspng->hardening.send_nodes_timestamp = unix_time(); + cur_iptspng->hardening.send_nodes_timestamp = mono_time_get(dht->mono_time); } } } else { - if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) { + if (mono_time_is_timeout(dht->mono_time, cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) { cur_iptspng->hardening.send_nodes_ok = 0; } } @@ -2688,7 +2704,7 @@ static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *pack /*----------------------------------------------------------------------------------*/ -DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled) +DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool holepunching_enabled) { if (net == nullptr) { return nullptr; @@ -2700,12 +2716,13 @@ DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled) return nullptr; } + dht->mono_time = mono_time; dht->log = log; dht->net = net; dht->hole_punching_enabled = holepunching_enabled; - dht->ping = ping_new(dht); + dht->ping = ping_new(mono_time, dht); if (dht->ping == nullptr) { kill_dht(dht); @@ -2738,7 +2755,7 @@ DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled) void do_dht(DHT *dht) { - if (dht->last_run == unix_time()) { + if (dht->last_run == mono_time_get(dht->mono_time)) { return; } @@ -2754,7 +2771,7 @@ void do_dht(DHT *dht) #if DHT_HARDENING do_hardening(dht); #endif - dht->last_run = unix_time(); + dht->last_run = mono_time_get(dht->mono_time); } void kill_dht(DHT *dht) @@ -2961,8 +2978,8 @@ bool dht_isconnected(const DHT *dht) for (uint32_t i = 0; i < LCLIENT_LIST; ++i) { const Client_data *const client = &dht->close_clientlist[i]; - if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || - !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { + if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) || + !mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { return true; } } @@ -2978,11 +2995,13 @@ bool dht_non_lan_connected(const DHT *dht) for (uint32_t i = 0; i < LCLIENT_LIST; ++i) { const Client_data *const client = &dht->close_clientlist[i]; - if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && ip_is_lan(client->assoc4.ip_port.ip) == -1) { + if (!mono_time_is_timeout(dht->mono_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) + && ip_is_lan(client->assoc4.ip_port.ip) == -1) { return true; } - if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) && ip_is_lan(client->assoc6.ip_port.ip) == -1) { + if (!mono_time_is_timeout(dht->mono_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT) + && ip_is_lan(client->assoc6.ip_port.ip) == -1) { return true; } } diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 0852827c8..4219bf472 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -26,6 +26,7 @@ #include "crypto_core.h" #include "logger.h" +#include "mono_time.h" #include "network.h" #include "ping_array.h" @@ -240,8 +241,8 @@ const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num); * If shared key is already in shared_keys, copy it to shared_key. * else generate it into shared_key and copy it to shared_keys */ -void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, - const uint8_t *public_key); +void get_shared_key(const Mono_Time *mono_time, Shared_Keys *shared_keys, uint8_t *shared_key, + const uint8_t *secret_key, const uint8_t *public_key); /* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key * for packets that we receive. @@ -401,7 +402,7 @@ void dht_save(const DHT *dht, uint8_t *data); int dht_load(DHT *dht, const uint8_t *data, uint32_t length); /* Initialize DHT. */ -DHT *new_dht(const Logger *log, Networking_Core *net, bool holepunching_enabled); +DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool holepunching_enabled); void kill_dht(DHT *dht); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index ab341e615..dacd662b0 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) } /* Run this at startup. */ -Messenger *new_messenger(Messenger_Options *options, unsigned int *error) +Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsigned int *error) { if (!options) { return nullptr; @@ -1965,6 +1965,8 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error) return nullptr; } + m->mono_time = mono_time; + m->fr = friendreq_new(); if (!m->fr) { @@ -2010,7 +2012,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error) return nullptr; } - m->dht = new_dht(m->log, m->net, options->hole_punching_enabled); + m->dht = new_dht(m->log, m->mono_time, m->net, options->hole_punching_enabled); if (m->dht == nullptr) { kill_networking(m->net); @@ -2020,7 +2022,7 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error) return nullptr; } - m->net_crypto = new_net_crypto(m->log, m->dht, &options->proxy_info); + m->net_crypto = new_net_crypto(m->log, m->mono_time, m->dht, &options->proxy_info); if (m->net_crypto == nullptr) { kill_networking(m->net); @@ -2031,10 +2033,10 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error) return nullptr; } - m->onion = new_onion(m->dht); - m->onion_a = new_onion_announce(m->dht); - m->onion_c = new_onion_client(m->net_crypto); - m->fr_c = new_friend_connections(m->onion_c, options->local_discovery_enabled); + m->onion = new_onion(m->mono_time, m->dht); + m->onion_a = new_onion_announce(m->mono_time, m->dht); + m->onion_c = new_onion_client(m->mono_time, m->net_crypto); + m->fr_c = new_friend_connections(m->mono_time, m->onion_c, options->local_discovery_enabled); if (!(m->onion && m->onion_a && m->onion_c)) { 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 static void do_friends(Messenger *m, void *userdata) { uint32_t i; - uint64_t temp_time = unix_time(); + uint64_t temp_time = mono_time_get(m->mono_time); for (i = 0; i < m->numfriends; ++i) { if (m->friendlist[i].status == FRIEND_ADDED) { @@ -2609,7 +2611,7 @@ void do_messenger(Messenger *m, void *userdata) } if (m->tcp_server) { - do_TCP_server(m->tcp_server); + do_TCP_server(m->tcp_server, m->mono_time); } do_net_crypto(m->net_crypto, userdata); @@ -2618,8 +2620,8 @@ void do_messenger(Messenger *m, void *userdata) do_friends(m, userdata); connection_status_callback(m, userdata); - if (unix_time() > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { - m->lastdump = unix_time(); + if (mono_time_get(m->mono_time) > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { + m->lastdump = mono_time_get(m->mono_time); uint32_t client, last_pinged; for (client = 0; client < LCLIENT_LIST; ++client) { diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 6fc4df024..0bb230cf4 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -233,6 +233,7 @@ typedef struct Friend { struct Messenger { Logger *log; + Mono_Time *mono_time; Networking_Core *net; Net_Crypto *net_crypto; @@ -738,7 +739,7 @@ typedef enum Messenger_Error { * * if error is not NULL it will be set to one of the values in the enum above. */ -Messenger *new_messenger(Messenger_Options *options, unsigned int *error); +Messenger *new_messenger(Mono_Time *mono_time, Messenger_Options *options, unsigned int *error); /* Run this before closing shop * Free all datastructures. diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index d6a27c95f..a6beac4d4 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 /* Create new TCP connection to ip_port/public_key */ -TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key, - const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info) +TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip_port, const uint8_t *public_key, + const uint8_t *self_public_key, const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info) { if (networking_at_startup() != 0) { return nullptr; @@ -765,7 +765,7 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public break; } - temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT; + temp->kill_at = mono_time_get(mono_time) + TCP_CONNECTION_TIMEOUT; return temp; } @@ -949,13 +949,13 @@ static bool tcp_process_packet(TCP_Client_Connection *conn, void *userdata) return true; } -static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata) +static int do_confirmed_TCP(TCP_Client_Connection *conn, const Mono_Time *mono_time, void *userdata) { client_send_pending_data(conn); tcp_send_ping_response(conn); tcp_send_ping_request(conn); - if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { + if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) { uint64_t ping_id = random_u64(); if (!ping_id) { @@ -965,10 +965,10 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata) conn->ping_request_id = ping_id; conn->ping_id = ping_id; tcp_send_ping_request(conn); - conn->last_pinged = unix_time(); + conn->last_pinged = mono_time_get(mono_time); } - if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { + if (conn->ping_id && mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_TIMEOUT)) { conn->status = TCP_CLIENT_DISCONNECTED; return 0; } @@ -983,7 +983,7 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata) /* Run the TCP connection */ -void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata) +void do_TCP_connection(Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, void *userdata) { if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) { return; @@ -1059,10 +1059,10 @@ void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata) } if (tcp_connection->status == TCP_CLIENT_CONFIRMED) { - do_confirmed_TCP(tcp_connection, userdata); + do_confirmed_TCP(tcp_connection, mono_time, userdata); } - if (tcp_connection->kill_at <= unix_time()) { + if (tcp_connection->kill_at <= mono_time_get(mono_time)) { tcp_connection->status = TCP_CLIENT_DISCONNECTED; } } diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 6d1cbb3bd..38c6e01ef 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); /* Create new TCP connection to ip_port/public_key */ -TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key, - const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info); +TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip_port, const uint8_t *public_key, + const uint8_t *self_public_key, const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info); /* Run the TCP connection */ -void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata); +void do_TCP_connection(Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, void *userdata); /* Kill the TCP connection */ diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c index 6763328da..0c388a392 100644 --- a/toxcore/TCP_connection.c +++ b/toxcore/TCP_connection.c @@ -36,6 +36,7 @@ struct TCP_Connections { + Mono_Time *mono_time; DHT *dht; 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 uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE]; memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE); kill_TCP_connection(tcp_con->connection); - tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, - &tcp_c->proxy_info); + tcp_con->connection = new_TCP_connection(tcp_c->mono_time, ip_port, relay_pk, tcp_c->self_public_key, + tcp_c->self_secret_key, &tcp_c->proxy_info); if (!tcp_con->connection) { 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 return -1; } - tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key, + tcp_con->connection = new_TCP_connection(tcp_c->mono_time, tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); if (!tcp_con->connection) { @@ -1122,7 +1123,7 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe /* If this connection isn't used by any connection, we don't need to wait for them to come online. */ if (sent) { - tcp_con->connected_time = unix_time(); + tcp_con->connected_time = mono_time_get(tcp_c->mono_time); } else { tcp_con->connected_time = 0; } @@ -1155,8 +1156,8 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number]; - tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, - &tcp_c->proxy_info); + tcp_con->connection = new_TCP_connection(tcp_c->mono_time, ip_port, relay_pk, tcp_c->self_public_key, + tcp_c->self_secret_key, &tcp_c->proxy_info); if (!tcp_con->connection) { return -1; @@ -1216,7 +1217,7 @@ int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_numb if (tcp_con->status == TCP_CONN_CONNECTED) { if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) { - tcp_con->connected_time = unix_time(); + tcp_con->connected_time = mono_time_get(tcp_c->mono_time); } } @@ -1391,7 +1392,7 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status) * * Returns NULL on failure. */ -TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info) +TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret_key, TCP_Proxy_Info *proxy_info) { if (secret_key == nullptr) { return nullptr; @@ -1403,6 +1404,8 @@ TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info * return nullptr; } + temp->mono_time = mono_time; + memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE); crypto_derive_public_key(temp->self_public_key, temp->self_secret_key); temp->proxy_info = *proxy_info; @@ -1419,7 +1422,7 @@ static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata) if (tcp_con) { if (tcp_con->status != TCP_CONN_SLEEPING) { - do_TCP_connection(tcp_con->connection, userdata); + do_TCP_connection(tcp_c->mono_time, tcp_con->connection, userdata); /* callbacks can change TCP connection address. */ tcp_con = get_tcp_connection(tcp_c, i); @@ -1443,7 +1446,7 @@ static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata) if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count && tcp_con->lock_count == tcp_con->sleep_count - && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { + && mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { sleep_tcp_relay_connection(tcp_c, i); } } @@ -1471,7 +1474,8 @@ static void kill_nonused_tcp(TCP_Connections *tcp_c) if (tcp_con) { if (tcp_con->status == TCP_CONN_CONNECTED) { - if (!tcp_con->onion && !tcp_con->lock_count && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { + if (!tcp_con->onion && !tcp_con->lock_count + && mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { to_kill[num_kill] = i; ++num_kill; } diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h index 2d99e1228..06b358291 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 * * Returns NULL on failure. */ -TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info); +TCP_Connections *new_tcp_connections(Mono_Time *mono_time, const uint8_t *secret_key, TCP_Proxy_Info *proxy_info); void do_tcp_connections(TCP_Connections *tcp_c, void *userdata); void kill_tcp_connections(TCP_Connections *tcp_c); diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 207a51070..7fe17434d 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); * return index on success * return -1 on failure */ -static int add_accepted(TCP_Server *tcp_server, const TCP_Secure_Connection *con) +static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, const TCP_Secure_Connection *con) { int index = get_TCP_connection_index(tcp_server, con->public_key); @@ -216,7 +216,7 @@ static int add_accepted(TCP_Server *tcp_server, const TCP_Secure_Connection *con tcp_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED; ++tcp_server->num_accepted_connections; tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter; - tcp_server->accepted_connection_array[index].last_pinged = unix_time(); + tcp_server->accepted_connection_array[index].last_pinged = mono_time_get(mono_time); tcp_server->accepted_connection_array[index].ping_id = 0; return index; @@ -954,10 +954,11 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint } -static int confirm_TCP_connection(TCP_Server *tcp_server, TCP_Secure_Connection *con, const uint8_t *data, +static int confirm_TCP_connection(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_Secure_Connection *con, + const uint8_t *data, uint16_t length) { - int index = add_accepted(tcp_server, con); + int index = add_accepted(tcp_server, mono_time, con); if (index == -1) { kill_TCP_secure_connection(con); @@ -1161,7 +1162,7 @@ static int do_incoming(TCP_Server *tcp_server, uint32_t i) return -1; } -static int do_unconfirmed(TCP_Server *tcp_server, uint32_t i) +static int do_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time, uint32_t i) { TCP_Secure_Connection *conn = &tcp_server->unconfirmed_connection_queue[i]; @@ -1182,7 +1183,7 @@ static int do_unconfirmed(TCP_Server *tcp_server, uint32_t i) return -1; } - return confirm_TCP_connection(tcp_server, conn, packet, len); + return confirm_TCP_connection(tcp_server, mono_time, conn, packet, len); } static 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) #ifndef TCP_SERVER_USE_EPOLL static void do_TCP_incoming(TCP_Server *tcp_server) { - uint32_t i; - - for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { + for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { do_incoming(tcp_server, i); } } -static void do_TCP_unconfirmed(TCP_Server *tcp_server) +static void do_TCP_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time) { - uint32_t i; - - for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { - do_unconfirmed(tcp_server, i); + for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { + do_unconfirmed(tcp_server, mono_time, i); } } #endif -static void do_TCP_confirmed(TCP_Server *tcp_server) +static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time) { #ifdef TCP_SERVER_USE_EPOLL - if (tcp_server->last_run_pinged == unix_time()) { + if (tcp_server->last_run_pinged == mono_time_get(mono_time)) { return; } - tcp_server->last_run_pinged = unix_time(); + tcp_server->last_run_pinged = mono_time_get(mono_time); #endif uint32_t i; @@ -1257,7 +1254,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server) continue; } - if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { + if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) { uint8_t ping[1 + sizeof(uint64_t)]; ping[0] = TCP_PACKET_PING; uint64_t ping_id = random_u64(); @@ -1270,17 +1267,17 @@ static void do_TCP_confirmed(TCP_Server *tcp_server) int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); if (ret == 1) { - conn->last_pinged = unix_time(); + conn->last_pinged = mono_time_get(mono_time); conn->ping_id = ping_id; } else { - if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { + if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { kill_accepted(tcp_server, i); continue; } } } - if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { + if (conn->ping_id && mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_TIMEOUT)) { kill_accepted(tcp_server, i); continue; } @@ -1296,7 +1293,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server) } #ifdef TCP_SERVER_USE_EPOLL -static bool tcp_epoll_process(TCP_Server *tcp_server) +static bool tcp_epoll_process(TCP_Server *tcp_server, const Mono_Time *mono_time) { #define MAX_EVENTS 16 struct epoll_event events[MAX_EVENTS]; @@ -1387,7 +1384,7 @@ static bool tcp_epoll_process(TCP_Server *tcp_server) } case TCP_SOCKET_UNCONFIRMED: { - const int index_new = do_unconfirmed(tcp_server, index); + const int index_new = do_unconfirmed(tcp_server, mono_time, index); if (index_new != -1) { events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP; @@ -1413,27 +1410,27 @@ static bool tcp_epoll_process(TCP_Server *tcp_server) return nfds > 0; } -static void do_TCP_epoll(TCP_Server *tcp_server) +static void do_TCP_epoll(TCP_Server *tcp_server, const Mono_Time *mono_time) { - while (tcp_epoll_process(tcp_server)) { + while (tcp_epoll_process(tcp_server, mono_time)) { // Keep processing packets until there are no more FDs ready for reading. continue; } } #endif -void do_TCP_server(TCP_Server *tcp_server) +void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time) { #ifdef TCP_SERVER_USE_EPOLL - do_TCP_epoll(tcp_server); + do_TCP_epoll(tcp_server, mono_time); #else do_TCP_accept_new(tcp_server); do_TCP_incoming(tcp_server); - do_TCP_unconfirmed(tcp_server); + do_TCP_unconfirmed(tcp_server, mono_time); #endif - do_TCP_confirmed(tcp_server); + do_TCP_confirmed(tcp_server, mono_time); } void kill_TCP_server(TCP_Server *tcp_server) diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 632a5e79b..77ffd5395 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 /* Run the TCP_server */ -void do_TCP_server(TCP_Server *tcp_server); +void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time); /* Kill the TCP server */ diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c index 4d2458714..f8b0ccf19 100644 --- a/toxcore/friend_connection.c +++ b/toxcore/friend_connection.c @@ -74,6 +74,7 @@ typedef struct Friend_Conn { struct Friend_Connections { + const Mono_Time *mono_time; Net_Crypto *net_crypto; DHT *dht; Onion_Client *onion_c; @@ -298,7 +299,7 @@ static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id) ++length; if (write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, data, length, 0) != -1) { - friend_con->share_relays_lastsent = unix_time(); + friend_con->share_relays_lastsent = mono_time_get(fr_c->mono_time); return 1; } @@ -339,7 +340,7 @@ static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port) set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1); friend_con->dht_ip_port = ip_port; - friend_con->dht_ip_port_lastrecv = unix_time(); + friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time); if (friend_con->hosting_tcp_relay) { 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 return; } - friend_con->dht_pk_lastrecv = unix_time(); + friend_con->dht_pk_lastrecv = mono_time_get(fr_c->mono_time); if (friend_con->dht_lock) { 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 if (status) { /* Went online. */ status_changed = 1; friend_con->status = FRIENDCONN_STATUS_CONNECTED; - friend_con->ping_lastrecv = unix_time(); + friend_con->ping_lastrecv = mono_time_get(fr_c->mono_time); friend_con->share_relays_lastsent = 0; onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); } else { /* Went offline. */ if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) { status_changed = 1; - friend_con->dht_pk_lastrecv = unix_time(); + friend_con->dht_pk_lastrecv = mono_time_get(fr_c->mono_time); onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); } @@ -463,7 +464,7 @@ static int handle_packet(void *object, int number, const uint8_t *data, uint16_t } if (data[0] == PACKET_ID_ALIVE) { - friend_con->ping_lastrecv = unix_time(); + friend_con->ping_lastrecv = mono_time_get(fr_c->mono_time); return 0; } @@ -558,7 +559,7 @@ static int handle_new_connections(void *object, New_Connection *n_c) set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0); } else { friend_con->dht_ip_port = n_c->source; - friend_con->dht_ip_port_lastrecv = unix_time(); + friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time); } 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) const int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0); if (ret != -1) { - friend_con->ping_lastsent = unix_time(); + friend_con->ping_lastsent = mono_time_get(fr_c->mono_time); return 0; } @@ -850,7 +851,8 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3 } /* Create new friend_connections instance. */ -Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled) +Friend_Connections *new_friend_connections(const Mono_Time *mono_time, Onion_Client *onion_c, + bool local_discovery_enabled) { if (onion_c == nullptr) { return nullptr; @@ -862,6 +864,7 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_dis return nullptr; } + temp->mono_time = mono_time; temp->dht = onion_get_dht(onion_c); temp->net_crypto = onion_get_net_crypto(onion_c); temp->onion_c = onion_c; @@ -881,7 +884,7 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_dis /* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ static void lan_discovery(Friend_Connections *fr_c) { - if (fr_c->last_lan_discovery + LAN_DISCOVERY_INTERVAL < unix_time()) { + if (fr_c->last_lan_discovery + LAN_DISCOVERY_INTERVAL < mono_time_get(fr_c->mono_time)) { const uint16_t first = fr_c->next_lan_port; uint16_t last = first + PORTS_PER_DISCOVERY; last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last; @@ -896,14 +899,14 @@ static void lan_discovery(Friend_Connections *fr_c) // Don't include default port in port range fr_c->next_lan_port = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1; - fr_c->last_lan_discovery = unix_time(); + fr_c->last_lan_discovery = mono_time_get(fr_c->mono_time); } } /* main friend_connections loop. */ void do_friend_connections(Friend_Connections *fr_c, void *userdata) { - const uint64_t temp_time = unix_time(); + const uint64_t temp_time = mono_time_get(fr_c->mono_time); for (uint32_t i = 0; i < fr_c->num_cons; ++i) { Friend_Conn *const friend_con = get_conn(fr_c, i); diff --git a/toxcore/friend_connection.h b/toxcore/friend_connection.h index 024befeec..06d7a1237 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 void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_request_callback, void *object); /* Create new friend_connections instance. */ -Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled); +Friend_Connections *new_friend_connections(const Mono_Time *mono_time, Onion_Client *onion_c, + bool local_discovery_enabled); /* main friend_connections loop. */ void do_friend_connections(Friend_Connections *fr_c, void *userdata); diff --git a/toxcore/group.c b/toxcore/group.c index 20075c8b9..114676054 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 id_copy(g->group[g->numpeers].temp_pk, temp_pk); g->group[g->numpeers].peer_number = peer_number; - g->group[g->numpeers].last_recv = unix_time(); + g->group[g->numpeers].last_recv = mono_time_get(g_c->mono_time); ++g->numpeers; 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, return; } - g->group[index].last_recv = unix_time(); + g->group[index].last_recv = mono_time_get(g_c->mono_time); } break; @@ -2508,9 +2508,9 @@ static int ping_groupchat(Group_Chats *g_c, uint32_t groupnumber) return -1; } - if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) { + if (mono_time_is_timeout(g_c->mono_time, g->last_sent_ping, GROUP_PING_INTERVAL)) { if (group_ping_send(g_c, groupnumber) != -1) { /* Ping */ - g->last_sent_ping = unix_time(); + g->last_sent_ping = mono_time_get(g_c->mono_time); } } @@ -2526,7 +2526,8 @@ static int groupchat_clear_timedout(Group_Chats *g_c, uint32_t groupnumber, void } for (uint32_t i = 0; i < g->numpeers; ++i) { - if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) { + if (g->peer_number != g->group[i].peer_number + && mono_time_is_timeout(g_c->mono_time, g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) { delpeer(g_c, groupnumber, i, userdata); } @@ -2556,7 +2557,7 @@ void send_name_all_groups(Group_Chats *g_c) } /* Create new groupchat instance. */ -Group_Chats *new_groupchats(Messenger *m) +Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m) { if (!m) { return nullptr; @@ -2568,6 +2569,7 @@ Group_Chats *new_groupchats(Messenger *m) return nullptr; } + temp->mono_time = mono_time; temp->m = m; temp->fr_c = m->fr_c; m->conferences_object = temp; diff --git a/toxcore/group.h b/toxcore/group.h index 175999ae7..90e7e9240 100644 --- a/toxcore/group.h +++ b/toxcore/group.h @@ -172,6 +172,8 @@ typedef struct Group_Lossy_Handler { } Group_Lossy_Handler; typedef struct Group_Chats { + const Mono_Time *mono_time; + Messenger *m; Friend_Connections *fr_c; @@ -433,7 +435,7 @@ int callback_groupchat_peer_delete(Group_Chats *g_c, uint32_t groupnumber, peer_ int callback_groupchat_delete(Group_Chats *g_c, uint32_t groupnumber, group_on_delete_cb *function); /* Create new groupchat instance. */ -Group_Chats *new_groupchats(Messenger *m); +Group_Chats *new_groupchats(Mono_Time *mono_time, Messenger *m); /* main groupchats loop. */ void do_groupchats(Group_Chats *g_c, void *userdata); diff --git a/toxcore/mono_time.c b/toxcore/mono_time.c index 0beb72542..3c4154207 100644 --- a/toxcore/mono_time.c +++ b/toxcore/mono_time.c @@ -41,6 +41,8 @@ Mono_Time *mono_time_new(void) monotime->time = 0; monotime->base_time = 0; + mono_time_update(monotime); + return monotime; } @@ -69,27 +71,6 @@ bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_ } -//!TOKSTYLE- -// No global mutable state in Tokstyle. -static Mono_Time global_time; -//!TOKSTYLE+ - -/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of - * unix_time() may fail to increase monotonically with increasing time */ -void unix_time_update(void) -{ - mono_time_update(&global_time); -} -uint64_t unix_time(void) -{ - return mono_time_get(&global_time); -} -int is_timeout(uint64_t timestamp, uint64_t timeout) -{ - return mono_time_is_timeout(&global_time, timestamp, timeout); -} - - //!TOKSTYLE- // No global mutable state in Tokstyle. #ifdef OS_WIN32 diff --git a/toxcore/mono_time.h b/toxcore/mono_time.h index 977595608..1d2dd539d 100644 --- a/toxcore/mono_time.h +++ b/toxcore/mono_time.h @@ -8,7 +8,39 @@ extern "C" { #endif +#ifndef MONO_TIME_DEFINED +#define MONO_TIME_DEFINED +/** + * The timer portion of the toxcore event loop. + * + * We update the time exactly once per tox_iterate call. Programs built on lower + * level APIs such as the DHT bootstrap node must update the time manually in + * each iteration. + * + * Time is kept per Tox instance, not globally, even though "time" as a concept + * is global. This is because by definition `mono_time` represents the time at + * the start of an iteration, and also by definition the time when all network + * events for the current iteration occurred. This affects mainly two situations: + * + * 1. Two timers started in the same iteration: e.g. two timers set to expire in + * 10 seconds will both expire at the same time, i.e. about 10 seconds later. + * If the time were global, `mono_time` would be a random number that is + * either the time at the start of an iteration, or 1 second later (since the + * timer resolution is 1 second). This can happen when one update happens at + * e.g. 10:00:00.995 and a few milliseconds later a concurrently running + * instance updates the time at 10:00:01.005, making one timer expire a + * second after the other. + * 2. One timer based on an event: if we want to encode a behaviour of a timer + * expiring e.g. 10 seconds after a network event occurred, we simply start a + * timer in the event handler. If a concurrent instance updates the time + * underneath us, it may instead expire 9 seconds after the event. + * + * Both these situations cause incorrect behaviour randomly. In practice, + * toxcore is somewhat robust against strange timer behaviour, but the + * implementation should at least theoretically match the specification. + */ typedef struct Mono_Time Mono_Time; +#endif /* MONO_TIME_DEFINED */ Mono_Time *mono_time_new(void); void mono_time_free(Mono_Time *monotime); @@ -17,11 +49,6 @@ void mono_time_update(Mono_Time *monotime); uint64_t mono_time_get(const Mono_Time *monotime); bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_t timeout); -// TODO(#405): Use per-tox monotime, delete these functions. -void unix_time_update(void); -uint64_t unix_time(void); -int is_timeout(uint64_t timestamp, uint64_t timeout); - /* return current monotonic time in milliseconds (ms). */ uint64_t current_time_monotonic(void); diff --git a/toxcore/mono_time_test.cc b/toxcore/mono_time_test.cc index 5ad913224..3e241b17c 100644 --- a/toxcore/mono_time_test.cc +++ b/toxcore/mono_time_test.cc @@ -5,26 +5,34 @@ namespace { TEST(Util, UnixTimeIncreasesOverTime) { - unix_time_update(); - uint64_t const start = unix_time(); + Mono_Time *mono_time = mono_time_new(); - while (start == unix_time()) { - unix_time_update(); + mono_time_update(mono_time); + uint64_t const start = mono_time_get(mono_time); + + while (start == mono_time_get(mono_time)) { + mono_time_update(mono_time); } - uint64_t const end = unix_time(); + uint64_t const end = mono_time_get(mono_time); EXPECT_GT(end, start); + + mono_time_free(mono_time); } TEST(Util, IsTimeout) { - uint64_t const start = unix_time(); - EXPECT_FALSE(is_timeout(start, 1)); + Mono_Time *mono_time = mono_time_new(); - while (start == unix_time()) { - unix_time_update(); + uint64_t const start = mono_time_get(mono_time); + EXPECT_FALSE(mono_time_is_timeout(mono_time, start, 1)); + + while (start == mono_time_get(mono_time)) { + mono_time_update(mono_time); } - EXPECT_TRUE(is_timeout(start, 1)); + EXPECT_TRUE(mono_time_is_timeout(mono_time, start, 1)); + + mono_time_free(mono_time); } } // namespace diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index bd214b916..a577b6c75 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -134,6 +134,7 @@ typedef struct Crypto_Connection { struct Net_Crypto { const Logger *log; + Mono_Time *mono_time; DHT *dht; TCP_Connections *tcp_c; @@ -248,10 +249,11 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, uint8_t * * return -1 on failure. * return 0 on success. */ -static int create_cookie(const Logger *log, uint8_t *cookie, const uint8_t *bytes, const uint8_t *encryption_key) +static int create_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes, + const uint8_t *encryption_key) { uint8_t contents[COOKIE_CONTENTS_LENGTH]; - const uint64_t temp_time = unix_time(); + const uint64_t temp_time = mono_time_get(mono_time); memcpy(contents, &temp_time, sizeof(temp_time)); memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH); random_nonce(cookie); @@ -269,7 +271,8 @@ static int create_cookie(const Logger *log, uint8_t *cookie, const uint8_t *byte * return -1 on failure. * return 0 on success. */ -static int open_cookie(const Logger *log, uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key) +static int open_cookie(const Logger *log, const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie, + const uint8_t *encryption_key) { uint8_t contents[COOKIE_CONTENTS_LENGTH]; 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, uint64_t cookie_time; memcpy(&cookie_time, contents, sizeof(cookie_time)); - const uint64_t temp_time = unix_time(); + const uint64_t temp_time = mono_time_get(mono_time); if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) { return -1; @@ -307,7 +310,7 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE); uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; - if (create_cookie(c->log, plain, cookie_plain, c->secret_symmetric_key) != 0) { + if (create_cookie(c->log, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) { return -1; } @@ -475,8 +478,8 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); - if (create_cookie(c->log, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, cookie_plain, - c->secret_symmetric_key) != 0) { + if (create_cookie(c->log, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, + cookie_plain, c->secret_symmetric_key) != 0) { return -1; } @@ -521,7 +524,7 @@ static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t uint8_t cookie_plain[COOKIE_DATA_LENGTH]; - if (open_cookie(c->log, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { + if (open_cookie(c->log, c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { return -1; } @@ -620,7 +623,7 @@ static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id) return empty; } - uint64_t current_time = unix_time(); + const uint64_t current_time = mono_time_get(c->mono_time); bool v6 = 0, v4 = 0; 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 } // TODO(irungentoo): a better way of sending packets directly to confirm the others ip. - uint64_t current_time = unix_time(); + const uint64_t current_time = mono_time_get(c->mono_time); if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) > current_time && length < 96) || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { if ((uint32_t)sendpacket(dht_get_net(c->dht), ip_port, data, length) == length) { direct_send_attempt = 1; - conn->direct_send_attempt_time = unix_time(); + conn->direct_send_attempt_time = mono_time_get(c->mono_time); } } } @@ -1841,9 +1844,9 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, } if (net_family_is_ipv4(source.ip.family)) { - conn->direct_lastrecv_timev4 = unix_time(); + conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time); } else { - conn->direct_lastrecv_timev6 = unix_time(); + conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time); } return 0; @@ -2069,7 +2072,7 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, return -1; } - const uint64_t direct_lastrecv_time = connected ? unix_time() : 0; + const uint64_t direct_lastrecv_time = connected ? mono_time_get(c->mono_time) : 0; if (net_family_is_ipv4(ip_port.ip.family)) { 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 pthread_mutex_lock(&conn->mutex); if (net_family_is_ipv4(source.ip.family)) { - conn->direct_lastrecv_timev4 = unix_time(); + conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time); } else { - conn->direct_lastrecv_timev6 = unix_time(); + conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time); } pthread_mutex_unlock(&conn->mutex); @@ -2877,7 +2880,7 @@ Crypto_Conn_State crypto_connection_status(const Net_Crypto *c, int crypt_connec if (direct_connected) { *direct_connected = 0; - uint64_t current_time = unix_time(); + const uint64_t current_time = mono_time_get(c->mono_time); if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) { *direct_connected = 1; @@ -2923,7 +2926,7 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk) /* Run this to (re)initialize net_crypto. * Sets all the global connection variables to their default values. */ -Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info) +Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TCP_Proxy_Info *proxy_info) { if (dht == nullptr) { return nullptr; @@ -2936,8 +2939,9 @@ Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_in } temp->log = log; + temp->mono_time = mono_time; - temp->tcp_c = new_tcp_connections(dht_get_self_secret_key(dht), proxy_info); + temp->tcp_c = new_tcp_connections(mono_time, dht_get_self_secret_key(dht), proxy_info); if (temp->tcp_c == nullptr) { free(temp); diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index e40b7bfd9..4a1d7f2c1 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); /* Create new instance of Net_Crypto. * Sets all the global connection variables to their default values. */ -Net_Crypto *new_net_crypto(const Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info); +Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TCP_Proxy_Info *proxy_info); /* return the optimal interval in ms for running do_net_crypto. */ diff --git a/toxcore/onion.c b/toxcore/onion.c index 5ba716fd6..eceeb9f8b 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -46,9 +46,9 @@ #define KEY_REFRESH_INTERVAL (2 * 60 * 60) static void change_symmetric_key(Onion *onion) { - if (is_timeout(onion->timestamp, KEY_REFRESH_INTERVAL)) { + if (mono_time_is_timeout(onion->mono_time, onion->timestamp, KEY_REFRESH_INTERVAL)) { new_symmetric_key(onion->secret_symmetric_key); - onion->timestamp = unix_time(); + onion->timestamp = mono_time_get(onion->mono_time); } } @@ -343,7 +343,8 @@ static int handle_send_initial(void *object, IP_Port source, const uint8_t *pack uint8_t plain[ONION_MAX_PACKET_SIZE]; uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; - get_shared_key(&onion->shared_keys_1, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); + get_shared_key(onion->mono_time, &onion->shared_keys_1, shared_key, dht_get_self_secret_key(onion->dht), + packet + 1 + CRYPTO_NONCE_SIZE); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain); @@ -412,7 +413,8 @@ static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, ui uint8_t plain[ONION_MAX_PACKET_SIZE]; uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; - get_shared_key(&onion->shared_keys_2, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); + get_shared_key(onion->mono_time, &onion->shared_keys_2, shared_key, dht_get_self_secret_key(onion->dht), + packet + 1 + CRYPTO_NONCE_SIZE); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain); @@ -468,7 +470,8 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui uint8_t plain[ONION_MAX_PACKET_SIZE]; uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; - get_shared_key(&onion->shared_keys_3, shared_key, dht_get_self_secret_key(onion->dht), packet + 1 + CRYPTO_NONCE_SIZE); + get_shared_key(onion->mono_time, &onion->shared_keys_3, shared_key, dht_get_self_secret_key(onion->dht), + packet + 1 + CRYPTO_NONCE_SIZE); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain); @@ -662,7 +665,7 @@ void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *o onion->callback_object = object; } -Onion *new_onion(DHT *dht) +Onion *new_onion(Mono_Time *mono_time, DHT *dht) { if (dht == nullptr) { return nullptr; @@ -676,8 +679,9 @@ Onion *new_onion(DHT *dht) onion->dht = dht; onion->net = dht_get_net(dht); + onion->mono_time = mono_time; new_symmetric_key(onion->secret_symmetric_key); - onion->timestamp = unix_time(); + onion->timestamp = mono_time_get(onion->mono_time); networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion); networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion); diff --git a/toxcore/onion.h b/toxcore/onion.h index 0e025a1ce..ea177c70a 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -25,11 +25,13 @@ #define ONION_H #include "DHT.h" +#include "mono_time.h" typedef int onion_recv_1_cb(void *object, IP_Port dest, const uint8_t *data, uint16_t length); typedef struct Onion { - DHT *dht; + Mono_Time *mono_time; + DHT *dht; Networking_Core *net; uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE]; uint64_t timestamp; @@ -158,7 +160,7 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port */ void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *object); -Onion *new_onion(DHT *dht); +Onion *new_onion(Mono_Time *mono_time, DHT *dht); void kill_onion(Onion *onion); diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index d368facee..f7f066819 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -50,6 +50,7 @@ typedef struct Onion_Announce_Entry { } Onion_Announce_Entry; struct Onion_Announce { + Mono_Time *mono_time; DHT *dht; Networking_Core *net; 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) unsigned int i; for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) { - if (!is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT) + if (!mono_time_is_timeout(onion_a->mono_time, onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT) && public_key_cmp(onion_a->entries[i].public_key, public_key) == 0) { return i; } @@ -266,6 +267,7 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key) } typedef struct Cmp_data { + const Mono_Time *mono_time; const uint8_t *base_public_key; Onion_Announce_Entry entry; } Cmp_data; @@ -279,8 +281,8 @@ static int cmp_entry(const void *a, const void *b) Onion_Announce_Entry entry2 = cmp2.entry; const uint8_t *cmp_public_key = cmp1.base_public_key; - int t1 = is_timeout(entry1.time, ONION_ANNOUNCE_TIMEOUT); - int t2 = is_timeout(entry2.time, ONION_ANNOUNCE_TIMEOUT); + int t1 = mono_time_is_timeout(cmp1.mono_time, entry1.time, ONION_ANNOUNCE_TIMEOUT); + int t2 = mono_time_is_timeout(cmp1.mono_time, entry2.time, ONION_ANNOUNCE_TIMEOUT); if (t1 && t2) { return 0; @@ -307,13 +309,15 @@ static int cmp_entry(const void *a, const void *b) return 0; } -static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const uint8_t *comp_public_key) +static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const Mono_Time *mono_time, + const uint8_t *comp_public_key) { // Pass comp_public_key to qsort with each Client_data entry, so the // comparison function can use it as the base of comparison. VLA(Cmp_data, cmp_list, length); for (uint32_t i = 0; i < length; ++i) { + cmp_list[i].mono_time = mono_time; cmp_list[i].base_public_key = comp_public_key; cmp_list[i].entry = list[i]; } @@ -338,7 +342,7 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui if (pos == -1) { for (unsigned i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) { - if (is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) { + if (mono_time_is_timeout(onion_a->mono_time, onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) { pos = i; } } @@ -358,9 +362,10 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const ui onion_a->entries[pos].ret_ip_port = ret_ip_port; memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3); memcpy(onion_a->entries[pos].data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE); - onion_a->entries[pos].time = unix_time(); + onion_a->entries[pos].time = mono_time_get(onion_a->mono_time); - sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, dht_get_self_public_key(onion_a->dht)); + sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, onion_a->mono_time, + dht_get_self_public_key(onion_a->dht)); return in_entries(onion_a, public_key); } @@ -374,7 +379,8 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t * const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE; uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; - get_shared_key(&onion_a->shared_keys_recv, shared_key, dht_get_self_secret_key(onion_a->dht), packet_public_key); + get_shared_key(onion_a->mono_time, &onion_a->shared_keys_recv, shared_key, dht_get_self_secret_key(onion_a->dht), + packet_public_key); uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; @@ -387,10 +393,10 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t * } uint8_t ping_id1[ONION_PING_ID_SIZE]; - generate_ping_id(onion_a, unix_time(), packet_public_key, source, ping_id1); + generate_ping_id(onion_a, mono_time_get(onion_a->mono_time), packet_public_key, source, ping_id1); uint8_t ping_id2[ONION_PING_ID_SIZE]; - generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet_public_key, source, ping_id2); + generate_ping_id(onion_a, mono_time_get(onion_a->mono_time) + PING_ID_TIMEOUT, packet_public_key, source, ping_id2); int index; @@ -493,7 +499,7 @@ static int handle_data_request(void *object, IP_Port source, const uint8_t *pack return 0; } -Onion_Announce *new_onion_announce(DHT *dht) +Onion_Announce *new_onion_announce(Mono_Time *mono_time, DHT *dht) { if (dht == nullptr) { return nullptr; @@ -505,6 +511,7 @@ Onion_Announce *new_onion_announce(DHT *dht) return nullptr; } + onion_a->mono_time = mono_time; onion_a->dht = dht; onion_a->net = dht_get_net(dht); new_symmetric_key(onion_a->secret_bytes); diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index 84e76a38a..628dc0025 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 const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); -Onion_Announce *new_onion_announce(DHT *dht); +Onion_Announce *new_onion_announce(Mono_Time *mono_time, DHT *dht); void kill_onion_announce(Onion_Announce *onion_a); diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 819bd23fa..d3b5cefcb 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -113,6 +113,8 @@ typedef struct Onion_Data_Handler { } Onion_Data_Handler; struct Onion_Client { + Mono_Time *mono_time; + DHT *dht; Net_Crypto *c; Networking_Core *net; @@ -316,16 +318,16 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format * return -1 if nodes are suitable for creating a new path. * return path number of already existing similar path if one already exists. */ -static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format *nodes) +static int is_path_used(const Mono_Time *mono_time, const Onion_Client_Paths *onion_paths, const Node_format *nodes) { unsigned int i; for (i = 0; i < NUMBER_ONION_PATHS; ++i) { - if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) { + if (mono_time_is_timeout(mono_time, onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) { continue; } - if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) { + if (mono_time_is_timeout(mono_time, onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) { continue; } @@ -339,7 +341,7 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format } /* is path timed out */ -static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum) +static bool path_timed_out(const Mono_Time *mono_time, Onion_Client_Paths *onion_paths, uint32_t pathnum) { pathnum = pathnum % NUMBER_ONION_PATHS; @@ -347,16 +349,16 @@ static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum) uint64_t timeout = is_new ? ONION_PATH_FIRST_TIMEOUT : ONION_PATH_TIMEOUT; return ((onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES - && is_timeout(onion_paths->last_path_used[pathnum], timeout)) - || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)); + && mono_time_is_timeout(mono_time, onion_paths->last_path_used[pathnum], timeout)) + || mono_time_is_timeout(mono_time, onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)); } /* should node be considered to have timed out */ -static bool onion_node_timed_out(const Onion_Node *node) +static bool onion_node_timed_out(const Onion_Node *node, const Mono_Time *mono_time) { return (node->timestamp == 0 || (node->unsuccessful_pings >= ONION_NODE_MAX_PINGS - && is_timeout(node->last_pinged, ONION_NODE_TIMEOUT))); + && mono_time_is_timeout(mono_time, node->last_pinged, ONION_NODE_TIMEOUT))); } /* 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 pathnum = pathnum % NUMBER_ONION_PATHS; } - if (path_timed_out(onion_paths, pathnum)) { + if (path_timed_out(onion_c->mono_time, onion_paths, pathnum)) { Node_format nodes[ONION_PATH_LENGTH]; if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) { return -1; } - int n = is_path_used(onion_paths, nodes); + int n = is_path_used(onion_c->mono_time, onion_paths, nodes); if (n == -1) { if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) { return -1; } - onion_paths->path_creation_time[pathnum] = unix_time(); + onion_paths->path_creation_time[pathnum] = mono_time_get(onion_c->mono_time); onion_paths->last_path_success[pathnum] = onion_paths->path_creation_time[pathnum]; onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2; @@ -406,7 +408,7 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa } if (onion_paths->last_path_used_times[pathnum] < ONION_PATH_MAX_NO_RESPONSE_USES) { - onion_paths->last_path_used[pathnum] = unix_time(); + onion_paths->last_path_used[pathnum] = mono_time_get(onion_c->mono_time); } ++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 } /* Does path with path_num exist. */ -static bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num) +static bool path_exists(const Mono_Time *mono_time, Onion_Client_Paths *onion_paths, uint32_t path_num) { - if (path_timed_out(onion_paths, path_num)) { + if (path_timed_out(mono_time, onion_paths, path_num)) { return 0; } @@ -442,7 +444,7 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t } if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) { - onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time(); + onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = mono_time_get(onion_c->mono_time); onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0; 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 memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, &ip_port, sizeof(IP_Port)); memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t)); - *sendback = ping_array_add(onion_c->announce_ping_array, data, sizeof(data)); + *sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data)); if (*sendback == 0) { return -1; @@ -547,7 +549,7 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u memcpy(&sback, sendback, sizeof(uint64_t)); uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)]; - if (ping_array_check(onion_c->announce_ping_array, data, sizeof(data), sback) != sizeof(data)) { + if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) { return ~0; } @@ -611,6 +613,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_ } typedef struct Onion_Client_Cmp_data { + const Mono_Time *mono_time; const uint8_t *base_public_key; Onion_Node entry; } Onion_Client_Cmp_data; @@ -624,8 +627,8 @@ static int onion_client_cmp_entry(const void *a, const void *b) Onion_Node entry2 = cmp2.entry; const uint8_t *cmp_public_key = cmp1.base_public_key; - int t1 = onion_node_timed_out(&entry1); - int t2 = onion_node_timed_out(&entry2); + int t1 = onion_node_timed_out(&entry1, cmp1.mono_time); + int t2 = onion_node_timed_out(&entry2, cmp2.mono_time); if (t1 && t2) { return 0; @@ -652,13 +655,15 @@ static int onion_client_cmp_entry(const void *a, const void *b) return 0; } -static void sort_onion_node_list(Onion_Node *list, unsigned int length, const uint8_t *comp_public_key) +static void sort_onion_node_list(Onion_Node *list, unsigned int length, const Mono_Time *mono_time, + const uint8_t *comp_public_key) { // Pass comp_public_key to qsort with each Client_data entry, so the // comparison function can use it as the base of comparison. VLA(Onion_Client_Cmp_data, cmp_list, length); for (uint32_t i = 0; i < length; ++i) { + cmp_list[i].mono_time = mono_time; cmp_list[i].base_public_key = comp_public_key; cmp_list[i].entry = list[i]; } @@ -695,7 +700,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t } if (is_stored == 1) { - onion_c->friends_list[num - 1].last_reported_announced = unix_time(); + onion_c->friends_list[num - 1].last_reported_announced = mono_time_get(onion_c->mono_time); } 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 list_length = MAX_ONION_CLIENTS; } - sort_onion_node_list(list_nodes, list_length, reference_id); + sort_onion_node_list(list_nodes, list_length, onion_c->mono_time, reference_id); int index = -1, stored = 0; unsigned int i; - if (onion_node_timed_out(&list_nodes[0]) + if (onion_node_timed_out(&list_nodes[0], onion_c->mono_time) || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) { index = 0; } @@ -738,24 +743,25 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t } list_nodes[index].is_stored = is_stored; - list_nodes[index].timestamp = unix_time(); + list_nodes[index].timestamp = mono_time_get(onion_c->mono_time); list_nodes[index].unsuccessful_pings = 0; if (!stored) { list_nodes[index].last_pinged = 0; - list_nodes[index].added_time = unix_time(); + list_nodes[index].added_time = mono_time_get(onion_c->mono_time); } list_nodes[index].path_used = path_used; return 0; } -static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *public_key) +static int good_to_ping(Mono_Time *mono_time, Last_Pinged *last_pinged, uint8_t *last_pinged_index, + const uint8_t *public_key) { unsigned int i; for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) { - if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME)) { + if (!mono_time_is_timeout(mono_time, last_pinged[i].timestamp, MIN_NODE_PING_TIME)) { if (public_key_cmp(last_pinged[i].public_key, public_key) == 0) { return 0; } @@ -763,7 +769,7 @@ static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, co } memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); - last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time(); + last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = mono_time_get(mono_time); ++*last_pinged_index; return 1; } @@ -811,9 +817,9 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for } } - if (onion_node_timed_out(&list_nodes[0]) + if (onion_node_timed_out(&list_nodes[0], onion_c->mono_time) || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2 - || onion_node_timed_out(&list_nodes[1]) + || onion_node_timed_out(&list_nodes[1], onion_c->mono_time) || id_closest(reference_id, list_nodes[1].public_key, nodes[i].public_key) == 2) { /* check if node is already in list. */ 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 } } - if (j == list_length && good_to_ping(last_pinged, last_pinged_index, nodes[i].public_key)) { + if (j == list_length && good_to_ping(onion_c->mono_time, last_pinged, last_pinged_index, nodes[i].public_key)) { client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, nullptr, ~0); } } @@ -894,7 +900,7 @@ static int handle_announce_response(void *object, IP_Port source, const uint8_t } // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline? - onion_c->last_packet_recv = unix_time(); + onion_c->last_packet_recv = mono_time_get(onion_c->mono_time); return 0; } @@ -975,7 +981,7 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con } onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t)); - onion_c->friends_list[friend_num].last_seen = unix_time(); + onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time); uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH; @@ -1054,7 +1060,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list; for (i = 0; i < MAX_ONION_CLIENTS; ++i) { - if (onion_node_timed_out(&list_nodes[i])) { + if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) { continue; } @@ -1196,7 +1202,7 @@ static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8 uint8_t data[DHTPK_DATA_MAX_LENGTH]; data[0] = ONION_DATA_DHTPK; - uint64_t no_replay = unix_time(); + uint64_t no_replay = mono_time_get(onion_c->mono_time); host_to_net((uint8_t *)&no_replay, sizeof(no_replay)); memcpy(data + 1, &no_replay, sizeof(no_replay)); 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 onion_c->friends_list[friend_num].know_dht_public_key = 0; } - onion_c->friends_list[friend_num].last_seen = unix_time(); + onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time); onion_c->friends_list[friend_num].know_dht_public_key = 1; memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, CRYPTO_PUBLIC_KEY_SIZE); @@ -1485,7 +1491,7 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on } if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1) { - onion_c->friends_list[friend_num].last_seen = unix_time(); + onion_c->friends_list[friend_num].last_seen = mono_time_get(onion_c->mono_time); } 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) interval = ANNOUNCE_FRIEND_BEGINNING; } else { if (onion_c->friends_list[friendnum].last_reported_announced == 0) { - onion_c->friends_list[friendnum].last_reported_announced = unix_time(); + onion_c->friends_list[friendnum].last_reported_announced = mono_time_get(onion_c->mono_time); } - uint64_t backoff_interval = (unix_time() - onion_c->friends_list[friendnum].last_reported_announced) + uint64_t backoff_interval = (mono_time_get(onion_c->mono_time) - + onion_c->friends_list[friendnum].last_reported_announced) / ONION_FRIEND_BACKOFF_FACTOR; if (backoff_interval > ONION_FRIEND_MAX_PING_INTERVAL) { @@ -1572,15 +1579,15 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) bool ping_random = true; for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) { - if (!(is_timeout(list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS) - && is_timeout(list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) { + if (!(mono_time_is_timeout(onion_c->mono_time, list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS) + && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) { ping_random = false; break; } } for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) { - if (onion_node_timed_out(&list_nodes[i])) { + if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) { continue; } @@ -1588,7 +1595,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) if (list_nodes[i].last_pinged == 0) { - list_nodes[i].last_pinged = unix_time(); + list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time); continue; } @@ -1596,11 +1603,11 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) continue; } - if (is_timeout(list_nodes[i].last_pinged, interval) + if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, interval) || (ping_random && random_u32() % (MAX_ONION_CLIENTS - i) == 0)) { if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].public_key, nullptr, ~0) == 0) { - list_nodes[i].last_pinged = unix_time(); + list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time); ++list_nodes[i].unsuccessful_pings; ping_random = false; } @@ -1634,15 +1641,17 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) } /* send packets to friend telling them our DHT public key. */ - if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_onion_sent, ONION_DHTPK_SEND_INTERVAL)) { + if (mono_time_is_timeout(onion_c->mono_time, onion_c->friends_list[friendnum].last_dht_pk_onion_sent, + ONION_DHTPK_SEND_INTERVAL)) { if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) { - onion_c->friends_list[friendnum].last_dht_pk_onion_sent = unix_time(); + onion_c->friends_list[friendnum].last_dht_pk_onion_sent = mono_time_get(onion_c->mono_time); } } - if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_dht_sent, DHT_DHTPK_SEND_INTERVAL)) { + if (mono_time_is_timeout(onion_c->mono_time, onion_c->friends_list[friendnum].last_dht_pk_dht_sent, + DHT_DHTPK_SEND_INTERVAL)) { if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) { - onion_c->friends_list[friendnum].last_dht_pk_dht_sent = unix_time(); + onion_c->friends_list[friendnum].last_dht_pk_dht_sent = mono_time_get(onion_c->mono_time); } } } @@ -1668,7 +1677,7 @@ static void do_announce(Onion_Client *onion_c) Onion_Node *list_nodes = onion_c->clients_announce_list; for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) { - if (onion_node_timed_out(&list_nodes[i])) { + if (onion_node_timed_out(&list_nodes[i], onion_c->mono_time)) { continue; } @@ -1687,7 +1696,7 @@ static void do_announce(Onion_Client *onion_c) unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; - if (list_nodes[i].is_stored && path_exists(&onion_c->onion_paths_self, list_nodes[i].path_used)) { + if (list_nodes[i].is_stored && path_exists(onion_c->mono_time, &onion_c->onion_paths_self, list_nodes[i].path_used)) { interval = ANNOUNCE_INTERVAL_ANNOUNCED; uint32_t pathnum = list_nodes[i].path_used % NUMBER_ONION_PATHS; @@ -1696,32 +1705,32 @@ static void do_announce(Onion_Client *onion_c) * aggressively, if it has survived for at least TIME_TO_STABLE * and the latest packets sent to it are not timing out. */ - if (is_timeout(list_nodes[i].added_time, TIME_TO_STABLE) + if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].added_time, TIME_TO_STABLE) && !(list_nodes[i].unsuccessful_pings > 0 - && is_timeout(list_nodes[i].last_pinged, ONION_NODE_TIMEOUT)) - && is_timeout(onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE) + && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, ONION_NODE_TIMEOUT)) + && mono_time_is_timeout(onion_c->mono_time, onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE) && !(onion_c->onion_paths_self.last_path_used_times[pathnum] > 0 - && is_timeout(onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) { + && mono_time_is_timeout(onion_c->mono_time, onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) { interval = ANNOUNCE_INTERVAL_STABLE; } } - if (is_timeout(list_nodes[i].last_pinged, interval) - || (is_timeout(onion_c->last_announce, ONION_NODE_PING_INTERVAL) + if (mono_time_is_timeout(onion_c->mono_time, list_nodes[i].last_pinged, interval) + || (mono_time_is_timeout(onion_c->mono_time, onion_c->last_announce, ONION_NODE_PING_INTERVAL) && random_u32() % (MAX_ONION_CLIENTS_ANNOUNCE - i) == 0)) { uint32_t path_to_use = list_nodes[i].path_used; if (list_nodes[i].unsuccessful_pings == ONION_NODE_MAX_PINGS - 1 - && is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)) { + && mono_time_is_timeout(onion_c->mono_time, list_nodes[i].added_time, TIME_TO_STABLE)) { /* Last chance for a long-lived node - try a random path */ path_to_use = ~0; } if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key, list_nodes[i].ping_id, path_to_use) == 0) { - list_nodes[i].last_pinged = unix_time(); + list_nodes[i].last_pinged = mono_time_get(onion_c->mono_time); ++list_nodes[i].unsuccessful_pings; - onion_c->last_announce = unix_time(); + onion_c->last_announce = mono_time_get(onion_c->mono_time); } } } @@ -1756,7 +1765,7 @@ static int onion_isconnected(const Onion_Client *onion_c) { unsigned int i, num = 0, announced = 0; - if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) { + if (mono_time_is_timeout(onion_c->mono_time, onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) { return 0; } @@ -1765,7 +1774,7 @@ static int onion_isconnected(const Onion_Client *onion_c) } for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) { - if (!onion_node_timed_out(&onion_c->clients_announce_list[i])) { + if (!onion_node_timed_out(&onion_c->clients_announce_list[i], onion_c->mono_time)) { ++num; if (onion_c->clients_announce_list[i].is_stored) { @@ -1812,11 +1821,11 @@ unsigned int onion_connection_status(const Onion_Client *onion_c) void do_onion_client(Onion_Client *onion_c) { - if (onion_c->last_run == unix_time()) { + if (onion_c->last_run == mono_time_get(onion_c->mono_time)) { return; } - if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) { + if (mono_time_is_timeout(onion_c->mono_time, onion_c->first_run, ONION_CONNECTION_SECONDS)) { populate_path_nodes(onion_c); do_announce(onion_c); } @@ -1835,7 +1844,7 @@ void do_onion_client(Onion_Client *onion_c) bool udp_connected = dht_non_lan_connected(onion_c->dht); - if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) { + if (mono_time_is_timeout(onion_c->mono_time, onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) { set_tcp_onion_status(nc_get_tcp_c(onion_c->c), !udp_connected); } @@ -1849,13 +1858,13 @@ void do_onion_client(Onion_Client *onion_c) } if (onion_c->last_run == 0) { - onion_c->first_run = unix_time(); + onion_c->first_run = mono_time_get(onion_c->mono_time); } - onion_c->last_run = unix_time(); + onion_c->last_run = mono_time_get(onion_c->mono_time); } -Onion_Client *new_onion_client(Net_Crypto *c) +Onion_Client *new_onion_client(Mono_Time *mono_time, Net_Crypto *c) { if (c == nullptr) { return nullptr; @@ -1874,6 +1883,7 @@ Onion_Client *new_onion_client(Net_Crypto *c) return nullptr; } + onion_c->mono_time = mono_time; onion_c->dht = nc_get_dht(c); onion_c->net = dht_get_net(onion_c->dht); onion_c->c = c; diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 660ccdd28..c6aaec459 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 void do_onion_client(Onion_Client *onion_c); -Onion_Client *new_onion_client(Net_Crypto *c); +Onion_Client *new_onion_client(Mono_Time *mono_time, Net_Crypto *c); void kill_onion_client(Onion_Client *onion_c); diff --git a/toxcore/ping.api.h b/toxcore/ping.api.h index edc04723a..e75c4e142 100644 --- a/toxcore/ping.api.h +++ b/toxcore/ping.api.h @@ -35,12 +35,13 @@ class iP_Port { struct this; } class dHT { struct this; } +class mono_Time { struct this; } class ping { struct this; -static this new(dHT::this *dht); +static this new(const mono_Time::this *mono_time, dHT::this *dht); void kill(); /** Add nodes to the to_ping list. diff --git a/toxcore/ping.c b/toxcore/ping.c index 1bf096bfc..7ffe13b46 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -48,6 +48,7 @@ struct Ping { + const Mono_Time *mono_time; DHT *dht; Ping_Array *ping_array; @@ -78,7 +79,7 @@ int32_t ping_send_request(Ping *ping, IP_Port ipp, const uint8_t *public_key) uint8_t data[PING_DATA_SIZE]; id_copy(data, public_key); memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port)); - ping_id = ping_array_add(ping->ping_array, data, sizeof(data)); + ping_id = ping_array_add(ping->ping_array, ping->mono_time, data, sizeof(data)); if (ping_id == 0) { return 1; @@ -219,7 +220,7 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); uint8_t data[PING_DATA_SIZE]; - if (ping_array_check(ping->ping_array, data, sizeof(data), ping_id) != sizeof(data)) { + if (ping_array_check(ping->ping_array, ping->mono_time, data, sizeof(data), ping_id) != sizeof(data)) { return 1; } @@ -243,7 +244,8 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac * return 1 if it is. * return 0 if it isn't. */ -static int in_list(const Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port) +static int in_list(const Client_data *list, uint16_t length, const Mono_Time *mono_time, const uint8_t *public_key, + IP_Port ip_port) { unsigned int i; @@ -257,7 +259,7 @@ static int in_list(const Client_data *list, uint16_t length, const uint8_t *publ ipptp = &list[i].assoc6; } - if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) { + if (!mono_time_is_timeout(mono_time, ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) { return 1; } } @@ -286,7 +288,7 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port) return -1; } - if (in_list(dht_get_close_clientlist(ping->dht), LCLIENT_LIST, public_key, ip_port)) { + if (in_list(dht_get_close_clientlist(ping->dht), LCLIENT_LIST, ping->mono_time, public_key, ip_port)) { return -1; } @@ -324,7 +326,7 @@ int32_t ping_add(Ping *ping, const uint8_t *public_key, IP_Port ip_port) */ void ping_iterate(Ping *ping) { - if (!is_timeout(ping->last_to_ping, TIME_TO_PING)) { + if (!mono_time_is_timeout(ping->mono_time, ping->last_to_ping, TIME_TO_PING)) { return; } @@ -348,12 +350,12 @@ void ping_iterate(Ping *ping) } if (i != 0) { - ping->last_to_ping = unix_time(); + ping->last_to_ping = mono_time_get(ping->mono_time); } } -Ping *ping_new(DHT *dht) +Ping *ping_new(const Mono_Time *mono_time, DHT *dht) { Ping *ping = (Ping *)calloc(1, sizeof(Ping)); @@ -368,6 +370,7 @@ Ping *ping_new(DHT *dht) return nullptr; } + ping->mono_time = mono_time; ping->dht = dht; networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht); 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 61875a0bd..63ecb017d 100644 --- a/toxcore/ping.h +++ b/toxcore/ping.h @@ -41,12 +41,17 @@ typedef struct IP_Port IP_Port; typedef struct DHT DHT; #endif /* DHT_DEFINED */ +#ifndef MONO_TIME_DEFINED +#define MONO_TIME_DEFINED +typedef struct Mono_Time Mono_Time; +#endif /* MONO_TIME_DEFINED */ + #ifndef PING_DEFINED #define PING_DEFINED typedef struct Ping Ping; #endif /* PING_DEFINED */ -Ping *ping_new(DHT *dht); +Ping *ping_new(const struct Mono_Time *mono_time, DHT *dht); void ping_kill(Ping *ping); diff --git a/toxcore/ping_array.api.h b/toxcore/ping_array.api.h index 55b805705..61021e241 100644 --- a/toxcore/ping_array.api.h +++ b/toxcore/ping_array.api.h @@ -28,6 +28,8 @@ #include "network.h" %} +class mono_Time { struct this; } + class ping_Array { struct this; @@ -53,7 +55,7 @@ void kill(); * return ping_id on success. * return 0 on failure. */ -uint64_t add(const uint8_t *data, uint32_t length); +uint64_t add(const mono_Time::this *mono_time, const uint8_t *data, uint32_t length); /** * Check if ping_id is valid and not timed out. @@ -63,7 +65,7 @@ uint64_t add(const uint8_t *data, uint32_t length); * return length of data copied on success. * return -1 on failure. */ -int32_t check(uint8_t[length] data, uint64_t ping_id); +int32_t check(const mono_Time::this *mono_time, uint8_t[length] data, uint64_t ping_id); } diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c index 142640dd2..9130254e9 100644 --- a/toxcore/ping_array.c +++ b/toxcore/ping_array.c @@ -109,12 +109,12 @@ void ping_array_kill(Ping_Array *array) /* Clear timed out entries. */ -static void ping_array_clear_timedout(Ping_Array *array) +static void ping_array_clear_timedout(Ping_Array *array, const Mono_Time *mono_time) { while (array->last_deleted != array->last_added) { uint32_t index = array->last_deleted % array->total_size; - if (!is_timeout(array->entries[index].time, array->timeout)) { + if (!mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) { break; } @@ -128,9 +128,9 @@ static void ping_array_clear_timedout(Ping_Array *array) * return ping_id on success. * return 0 on failure. */ -uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length) +uint64_t ping_array_add(Ping_Array *array, const Mono_Time *mono_time, const uint8_t *data, uint32_t length) { - ping_array_clear_timedout(array); + ping_array_clear_timedout(array, mono_time); uint32_t index = array->last_added % array->total_size; 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) memcpy(array->entries[index].data, data, length); array->entries[index].length = length; - array->entries[index].time = unix_time(); + array->entries[index].time = mono_time_get(mono_time); ++array->last_added; uint64_t ping_id = random_u64(); ping_id /= array->total_size; @@ -169,7 +169,7 @@ uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length) * return length of data copied on success. * return -1 on failure. */ -int32_t ping_array_check(Ping_Array *array, uint8_t *data, size_t length, uint64_t ping_id) +int32_t ping_array_check(Ping_Array *array, const Mono_Time *mono_time, uint8_t *data, size_t length, uint64_t ping_id) { if (ping_id == 0) { return -1; @@ -181,7 +181,7 @@ int32_t ping_array_check(Ping_Array *array, uint8_t *data, size_t length, uint64 return -1; } - if (is_timeout(array->entries[index].time, array->timeout)) { + if (mono_time_is_timeout(mono_time, array->entries[index].time, array->timeout)) { return -1; } diff --git a/toxcore/ping_array.h b/toxcore/ping_array.h index b927bbd42..cfa9bfcc9 100644 --- a/toxcore/ping_array.h +++ b/toxcore/ping_array.h @@ -26,6 +26,11 @@ #include "network.h" +#ifndef MONO_TIME_DEFINED +#define MONO_TIME_DEFINED +typedef struct Mono_Time Mono_Time; +#endif /* MONO_TIME_DEFINED */ + #ifndef PING_ARRAY_DEFINED #define PING_ARRAY_DEFINED typedef struct Ping_Array Ping_Array; @@ -52,7 +57,8 @@ void ping_array_kill(struct Ping_Array *_array); * return ping_id on success. * return 0 on failure. */ -uint64_t ping_array_add(struct Ping_Array *_array, const uint8_t *data, uint32_t length); +uint64_t ping_array_add(struct Ping_Array *_array, const struct Mono_Time *mono_time, const uint8_t *data, + uint32_t length); /** * 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 * return length of data copied on success. * return -1 on failure. */ -int32_t ping_array_check(struct Ping_Array *_array, uint8_t *data, size_t length, uint64_t ping_id); +int32_t ping_array_check(struct Ping_Array *_array, const struct Mono_Time *mono_time, uint8_t *data, size_t length, + uint64_t ping_id); #endif diff --git a/toxcore/tox.c b/toxcore/tox.c index 879b5c093..4f5960451 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -78,6 +78,8 @@ struct Tox { Messenger *m; + Mono_Time *mono_time; + tox_self_connection_status_cb *self_connection_status_callback; tox_friend_name_cb *friend_name_callback; 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) return nullptr; } - unix_time_update(); - Messenger_Options m_options = {0}; 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) m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(opts)); } + tox->mono_time = mono_time_new(); + + if (tox->mono_time == nullptr) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); + tox_options_free(default_options); + free(tox); + return nullptr; + } + unsigned int m_error; - Messenger *const m = new_messenger(&m_options, &m_error); + Messenger *const m = new_messenger(tox->mono_time, &m_options, &m_error); tox->m = m; // TODO(iphydf): Clarify this code, check for NULL before new_groupchats, so // new_groupchats can assume m is non-NULL. - if (!new_groupchats(m)) { + if (!new_groupchats(tox->mono_time, m)) { kill_messenger(m); if (m_error == MESSENGER_ERROR_PORT) { @@ -472,6 +481,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC); } + mono_time_free(tox->mono_time); tox_options_free(default_options); free(tox); return nullptr; @@ -522,6 +532,7 @@ void tox_kill(Tox *tox) Messenger *m = tox->m; kill_groupchats(m->conferences_object); kill_messenger(m); + mono_time_free(tox->mono_time); free(tox); } @@ -656,7 +667,7 @@ uint32_t tox_iteration_interval(const Tox *tox) void tox_iterate(Tox *tox, void *user_data) { - unix_time_update(); + mono_time_update(tox->mono_time); Messenger *m = tox->m; struct Tox_Userdata tox_data = { tox, user_data };