diff --git a/.circleci/config.yml b/.circleci/config.yml index 0d6bdc4412..36a7b383ac 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,6 +36,7 @@ jobs: libvpx-dev ninja-build pkg-config + llvm-dev - checkout - run: CC=clang .circleci/cmake-asan @@ -84,7 +85,7 @@ jobs: steps: - run: *apt_install - - run: apt-get install -y --no-install-recommends cppcheck g++ llvm-dev + - run: apt-get install -y --no-install-recommends cppcheck g++ - checkout - run: other/analysis/check_logger_levels - run: other/analysis/run-check-recursion diff --git a/CMakeLists.txt b/CMakeLists.txt index edfd3b2add..40c300f2a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,6 +178,8 @@ set(toxcore_SOURCES ${toxcore_SOURCES} toxcore/logger.h toxcore/mono_time.c toxcore/mono_time.h + toxcore/net_profile.c + toxcore/net_profile.h toxcore/network.c toxcore/network.h toxcore/state.c diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 8e7bdcd3bb..64c7c1581c 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -95,12 +95,12 @@ START_TEST(test_basic) "encrypt_data() call failed."); // Sending the handshake - ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1) == TCP_CLIENT_HANDSHAKE_SIZE - 1, + ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1, nullptr) == TCP_CLIENT_HANDSHAKE_SIZE - 1, "An attempt to send the initial handshake minus last byte failed."); do_TCP_server_delay(tcp_s, mono_time, 50); - ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1) == 1, + ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, nullptr) == 1, "The attempt to send the last byte of handshake failed."); do_TCP_server_delay(tcp_s, mono_time, 50); @@ -137,7 +137,7 @@ START_TEST(test_basic) msg_length = sizeof(r_req) - i; } - ck_assert_msg(net_send(sock, r_req + i, msg_length) == msg_length, + ck_assert_msg(net_send(sock, r_req + i, msg_length, nullptr) == msg_length, "Failed to send request after completing the handshake."); i += msg_length; @@ -212,12 +212,12 @@ static struct sec_TCP_con *new_TCP_con(TCP_Server *tcp_s, Mono_Time *mono_time) ck_assert_msg(ret == TCP_CLIENT_HANDSHAKE_SIZE - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), "Failed to encrypt the outgoing handshake."); - ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1) == TCP_CLIENT_HANDSHAKE_SIZE - 1, + ck_assert_msg(net_send(sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1, nullptr) == 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, mono_time, 50); - ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1) == 1, + ck_assert_msg(net_send(sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, nullptr) == 1, "Failed to send last byte of handshake."); do_TCP_server_delay(tcp_s, mono_time, 50); @@ -255,7 +255,8 @@ static int write_packet_TCP_secure_connection(struct sec_TCP_con *con, uint8_t * increment_nonce(con->sent_nonce); - ck_assert_msg(net_send(con->sock, packet, SIZEOF_VLA(packet)) == SIZEOF_VLA(packet), "Failed to send a packet."); + ck_assert_msg(net_send(con->sock, packet, SIZEOF_VLA(packet), nullptr) == SIZEOF_VLA(packet), + "Failed to send a packet."); return 0; } @@ -480,7 +481,7 @@ START_TEST(test_client) 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(logger, mono_time, conn, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, nullptr); c_sleep(50); // The connection status should be unconfirmed here because we have finished @@ -494,7 +495,7 @@ START_TEST(test_client) for (uint8_t i = 0; i < LOOP_SIZE; i++) { mono_time_update(mono_time); - do_TCP_connection(logger, mono_time, conn, nullptr); // Run the connection loop. + do_TCP_connection(logger, mono_time, conn, nullptr, 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", @@ -528,25 +529,25 @@ 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(logger, mono_time, conn, nullptr); - do_TCP_connection(logger, mono_time, conn2, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, nullptr); + do_TCP_connection(logger, mono_time, conn2, nullptr, nullptr); do_TCP_server_delay(tcp_s, mono_time, 50); - do_TCP_connection(logger, mono_time, conn, nullptr); - do_TCP_connection(logger, mono_time, conn2, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, nullptr); + do_TCP_connection(logger, mono_time, conn2, nullptr, nullptr); c_sleep(50); uint8_t data[5] = {1, 2, 3, 4, 5}; memcpy(oob_pubkey, f2_public_key, CRYPTO_PUBLIC_KEY_SIZE); - send_oob_packet(conn2, f_public_key, data, 5); - send_routing_request(conn, f2_public_key); - send_routing_request(conn2, f_public_key); + send_oob_packet(conn2, nullptr, f_public_key, data, 5); + send_routing_request(conn, f2_public_key, nullptr); + send_routing_request(conn2, f_public_key, nullptr); do_TCP_server_delay(tcp_s, mono_time, 50); - do_TCP_connection(logger, mono_time, conn, nullptr); - do_TCP_connection(logger, mono_time, conn2, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, nullptr); + do_TCP_connection(logger, mono_time, conn2, nullptr, 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"); @@ -559,20 +560,20 @@ START_TEST(test_client) do_TCP_server_delay(tcp_s, mono_time, 50); - ck_assert_msg(send_data(conn2, 0, data, 5) == 1, "Failed a send_data() call."); + ck_assert_msg(send_data(conn2, 0, nullptr, data, 5) == 1, "Failed a send_data() call."); do_TCP_server_delay(tcp_s, mono_time, 50); - do_TCP_connection(logger, mono_time, conn, nullptr); - do_TCP_connection(logger, mono_time, conn2, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, nullptr); + do_TCP_connection(logger, mono_time, conn2, nullptr, nullptr); ck_assert_msg(data_callback_good == 1, "Data callback was not called."); status_callback_good = 0; - send_disconnect_request(conn2, 0); + send_disconnect_request(conn2, 0, nullptr); do_TCP_server_delay(tcp_s, mono_time, 50); - do_TCP_connection(logger, mono_time, conn, nullptr); - do_TCP_connection(logger, mono_time, conn2, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, nullptr); + do_TCP_connection(logger, mono_time, conn2, nullptr, nullptr); ck_assert_msg(status_callback_good == 1, "Status callback not called"); ck_assert_msg(status_callback_status == 1, "Wrong status callback status."); @@ -608,7 +609,7 @@ START_TEST(test_client_invalid) // Run the client's main loop but not the server. mono_time_update(mono_time); - do_TCP_connection(logger, mono_time, conn, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, nullptr); c_sleep(50); // After 50ms of no response... @@ -617,13 +618,13 @@ START_TEST(test_client_invalid) // After 5s... c_sleep(5000); mono_time_update(mono_time); - do_TCP_connection(logger, mono_time, conn, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, 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); mono_time_update(mono_time); - do_TCP_connection(logger, mono_time, conn, nullptr); + do_TCP_connection(logger, mono_time, conn, nullptr, nullptr); ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %d, is: %d.", TCP_CLIENT_DISCONNECTED, tcp_con_status(conn)); diff --git a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 index 8628c8d970..44ef4425d9 100644 --- a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 +++ b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 @@ -1 +1 @@ -7f4c96481e30156e3c2e7e448e70faaaa12911694390374ae09bd53d5d7b4f9c /usr/local/bin/tox-bootstrapd +01ce8b7ff2444dfa3013881fac9cb351e40efc5e38cc06ce84094cfcde176ae7 /usr/local/bin/tox-bootstrapd diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 2169cf63d9..04bdc38044 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -129,12 +129,20 @@ cc_library( ":crypto_core", ":logger", ":mono_time", + ":net_profile", "@libsodium", "@psocket", "@pthread", ], ) +cc_library( + name = "net_profile", + srcs = ["net_profile.c"], + hdrs = ["net_profile.h"], + deps = [":ccompat"], +) + cc_test( name = "network_test", size = "small", @@ -282,6 +290,7 @@ cc_library( ":crypto_core", ":list", ":mono_time", + ":net_profile", ":network", ":onion", ], @@ -427,6 +436,7 @@ cc_library( ":group", ":logger", ":mono_time", + ":net_profile", ":network", "//c-toxcore/toxencryptsave:defines", ], diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index bcf6781ae0..b39e80cb8a 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -19,6 +19,8 @@ libtoxcore_la_SOURCES = ../toxcore/ccompat.h \ ../toxcore/ping_array.c \ ../toxcore/net_crypto.h \ ../toxcore/net_crypto.c \ + ../toxcore/net_profile.c \ + ../toxcore/net_profile.h \ ../toxcore/friend_requests.h \ ../toxcore/friend_requests.c \ ../toxcore/LAN_discovery.h \ @@ -44,6 +46,8 @@ libtoxcore_la_SOURCES = ../toxcore/ccompat.h \ ../toxcore/logger.h \ ../toxcore/logger.c \ ../toxcore/onion_announce.h \ + ../toxcore/net_profile.c \ + ../toxcore/net_profile.h \ ../toxcore/onion_announce.c \ ../toxcore/onion_client.h \ ../toxcore/onion_client.c \ diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 6fe2337b63..342274cdfc 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -312,14 +312,14 @@ static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data /** return 0 if pending data was sent completely * return -1 if it wasn't */ -static int client_send_pending_data_nonpriority(TCP_Client_Connection *con) +static int client_send_pending_data_nonpriority(TCP_Client_Connection *con, Net_Profile *tcp_client_prof) { if (con->last_packet_length == 0) { return 0; } const uint16_t left = con->last_packet_length - con->last_packet_sent; - const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left); + const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left, tcp_client_prof); if (len <= 0) { return -1; @@ -338,10 +338,10 @@ static int client_send_pending_data_nonpriority(TCP_Client_Connection *con) /** return 0 if pending data was sent completely * return -1 if it wasn't */ -static int client_send_pending_data(TCP_Client_Connection *con) +static int client_send_pending_data(TCP_Client_Connection *con, Net_Profile *tcp_client_prof) { /* finish sending current non-priority packet */ - if (client_send_pending_data_nonpriority(con) == -1) { + if (client_send_pending_data_nonpriority(con, tcp_client_prof) == -1) { return -1; } @@ -349,7 +349,7 @@ static int client_send_pending_data(TCP_Client_Connection *con) while (p) { const uint16_t left = p->size - p->sent; - const int len = net_send(con->sock, p->data + p->sent, left); + const int len = net_send(con->sock, p->data + p->sent, left, tcp_client_prof); if (len != left) { if (len > 0) { @@ -405,8 +405,8 @@ static bool client_add_priority(TCP_Client_Connection *con, const uint8_t *packe * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length, - bool priority) +static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, Net_Profile *tcp_client_prof, + const uint8_t *data, uint16_t length, bool priority) { if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { return -1; @@ -414,7 +414,7 @@ static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, bool sendpriority = 1; - if (client_send_pending_data(con) == -1) { + if (client_send_pending_data(con, tcp_client_prof) == -1) { if (priority) { sendpriority = 0; } else { @@ -433,7 +433,7 @@ static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, } if (priority) { - len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0; + len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet), tcp_client_prof) : 0; if (len <= 0) { len = 0; @@ -448,7 +448,7 @@ static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, return client_add_priority(con, packet, SIZEOF_VLA(packet), len); } - len = net_send(con->sock, packet, SIZEOF_VLA(packet)); + len = net_send(con->sock, packet, SIZEOF_VLA(packet), tcp_client_prof); if (len <= 0) { return 0; @@ -470,12 +470,12 @@ static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) +int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key, Net_Profile *tcp_client_prof) { uint8_t packet[1 + CRYPTO_PUBLIC_KEY_SIZE]; packet[0] = TCP_PACKET_ROUTING_REQUEST; memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE); - return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); + return write_packet_TCP_client_secure_connection(con, tcp_client_prof, packet, sizeof(packet), 1); } void routing_response_handler(TCP_Client_Connection *con, tcp_routing_response_cb *response_callback, void *object) @@ -490,14 +490,15 @@ void routing_status_handler(TCP_Client_Connection *con, tcp_routing_status_cb *s con->status_callback_object = object; } -static int tcp_send_ping_response(TCP_Client_Connection *con); -static int tcp_send_ping_request(TCP_Client_Connection *con); +static int tcp_send_ping_response(TCP_Client_Connection *con, Net_Profile *tcp_client_prof); +static int tcp_send_ping_request(TCP_Client_Connection *con, Net_Profile *tcp_client_prof); /** return 1 on success. * return 0 if could not send packet. * return -1 on failure. */ -int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length) +int send_data(TCP_Client_Connection *con, uint8_t con_id, Net_Profile *tcp_client_prof, const uint8_t *data, + uint16_t length) { if (con_id >= NUM_CLIENT_CONNECTIONS) { return -1; @@ -507,21 +508,22 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, u return -1; } - if (tcp_send_ping_response(con) == 0 || tcp_send_ping_request(con) == 0) { + if (tcp_send_ping_response(con, tcp_client_prof) == 0 || tcp_send_ping_request(con, tcp_client_prof) == 0) { return 0; } VLA(uint8_t, packet, 1 + length); packet[0] = con_id + NUM_RESERVED_PORTS; memcpy(packet + 1, data, length); - return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); + return write_packet_TCP_client_secure_connection(con, tcp_client_prof, packet, SIZEOF_VLA(packet), 0); } /** return 1 on success. * return 0 if could not send packet. * return -1 on failure. */ -int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length) +int send_oob_packet(TCP_Client_Connection *con, Net_Profile *tcp_client_prof, const uint8_t *public_key, + const uint8_t *data, uint16_t length) { if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) { return -1; @@ -531,7 +533,7 @@ int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const packet[0] = TCP_PACKET_OOB_SEND; memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length); - return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); + return write_packet_TCP_client_secure_connection(con, tcp_client_prof, packet, SIZEOF_VLA(packet), 0); } @@ -572,19 +574,19 @@ void oob_data_handler(TCP_Client_Connection *con, tcp_oob_data_cb *oob_data_call * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int client_send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) +static int client_send_disconnect_notification(TCP_Client_Connection *con, uint8_t id, Net_Profile *tcp_client_prof) { uint8_t packet[1 + 1]; packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; packet[1] = id; - return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); + return write_packet_TCP_client_secure_connection(con, tcp_client_prof, packet, sizeof(packet), 1); } /** return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int tcp_send_ping_request(TCP_Client_Connection *con) +static int tcp_send_ping_request(TCP_Client_Connection *con, Net_Profile *tcp_client_prof) { if (!con->ping_request_id) { return 1; @@ -593,7 +595,7 @@ static int tcp_send_ping_request(TCP_Client_Connection *con) uint8_t packet[1 + sizeof(uint64_t)]; packet[0] = TCP_PACKET_PING; memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t)); - const int ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); + const int ret = write_packet_TCP_client_secure_connection(con, tcp_client_prof, packet, sizeof(packet), 1); if (ret == 1) { con->ping_request_id = 0; @@ -606,7 +608,7 @@ static int tcp_send_ping_request(TCP_Client_Connection *con) * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int tcp_send_ping_response(TCP_Client_Connection *con) +static int tcp_send_ping_response(TCP_Client_Connection *con, Net_Profile *tcp_client_prof) { if (!con->ping_response_id) { return 1; @@ -615,7 +617,7 @@ static int tcp_send_ping_response(TCP_Client_Connection *con) uint8_t packet[1 + sizeof(uint64_t)]; packet[0] = TCP_PACKET_PONG; memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t)); - const int ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); + const int ret = write_packet_TCP_client_secure_connection(con, tcp_client_prof, packet, sizeof(packet), 1); if (ret == 1) { con->ping_response_id = 0; @@ -628,7 +630,7 @@ static int tcp_send_ping_response(TCP_Client_Connection *con) * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id) +int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id, Net_Profile *tcp_client_prof) { if (con_id >= NUM_CLIENT_CONNECTIONS) { return -1; @@ -636,19 +638,19 @@ int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id) con->connections[con_id].status = 0; con->connections[con_id].number = 0; - return client_send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS); + return client_send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS, tcp_client_prof); } /** return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length) +int send_onion_request(TCP_Client_Connection *con, Net_Profile *tcp_client_prof, const uint8_t *data, uint16_t length) { VLA(uint8_t, packet, 1 + length); packet[0] = TCP_PACKET_ONION_REQUEST; memcpy(packet + 1, data, length); - return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); + return write_packet_TCP_client_secure_connection(con, tcp_client_prof, packet, SIZEOF_VLA(packet), 0); } void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *onion_callback, void *object) @@ -746,12 +748,15 @@ TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip /** return 0 on success * return -1 on failure */ -static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length, void *userdata) +static int handle_TCP_client_packet(TCP_Client_Connection *conn, Net_Profile *tcp_client_prof, const uint8_t *data, + uint16_t length, void *userdata) { if (length <= 1) { return -1; } + netprof_record_packet(tcp_client_prof, data[0], length, DIR_RECV); + switch (data[0]) { case TCP_PACKET_ROUTING_RESPONSE: { if (length != 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE) { @@ -841,7 +846,7 @@ static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t * uint64_t ping_id; memcpy(&ping_id, data + 1, sizeof(uint64_t)); conn->ping_response_id = ping_id; - tcp_send_ping_response(conn); + tcp_send_ping_response(conn, tcp_client_prof); return 0; } @@ -899,7 +904,8 @@ static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t * return 0; } -static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn, void *userdata) +static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn, Net_Profile *tcp_client_prof, + void *userdata) { uint8_t packet[MAX_PACKET_SIZE]; const int len = read_packet_TCP_secure_connection(logger, conn->sock, &conn->next_packet_length, conn->shared_key, @@ -914,7 +920,7 @@ static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn return false; } - if (handle_TCP_client_packet(conn, packet, len, userdata) == -1) { + if (handle_TCP_client_packet(conn, tcp_client_prof, packet, len, userdata) == -1) { conn->status = TCP_CLIENT_DISCONNECTED; return false; } @@ -923,11 +929,11 @@ static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn } static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, const Mono_Time *mono_time, - void *userdata) + Net_Profile *tcp_client_prof, void *userdata) { - client_send_pending_data(conn); - tcp_send_ping_response(conn); - tcp_send_ping_request(conn); + client_send_pending_data(conn, tcp_client_prof); + tcp_send_ping_response(conn, tcp_client_prof); + tcp_send_ping_request(conn, tcp_client_prof); if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) { uint64_t ping_id = random_u64(); @@ -938,7 +944,7 @@ static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, c conn->ping_request_id = ping_id; conn->ping_id = ping_id; - tcp_send_ping_request(conn); + tcp_send_ping_request(conn, tcp_client_prof); conn->last_pinged = mono_time_get(mono_time); } @@ -947,7 +953,7 @@ static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, c return 0; } - while (tcp_process_packet(logger, conn, userdata)) { + while (tcp_process_packet(logger, conn, tcp_client_prof, userdata)) { // Keep reading until error or out of data. continue; } @@ -958,14 +964,14 @@ static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, c /** Run the TCP connection */ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, - void *userdata) + Net_Profile *tcp_client_prof, void *userdata) { if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) { return; } if (tcp_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) { - if (client_send_pending_data(tcp_connection) == 0) { + if (client_send_pending_data(tcp_connection, tcp_client_prof) == 0) { int ret = proxy_http_read_connection_response(logger, tcp_connection); if (ret == -1) { @@ -981,7 +987,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co } if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) { - if (client_send_pending_data(tcp_connection) == 0) { + if (client_send_pending_data(tcp_connection, tcp_client_prof) == 0) { int ret = socks5_read_handshake_response(logger, tcp_connection); if (ret == -1) { @@ -997,7 +1003,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co } if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) { - if (client_send_pending_data(tcp_connection) == 0) { + if (client_send_pending_data(tcp_connection, tcp_client_prof) == 0) { int ret = proxy_socks5_read_connection_response(logger, tcp_connection); if (ret == -1) { @@ -1013,7 +1019,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co } if (tcp_connection->status == TCP_CLIENT_CONNECTING) { - if (client_send_pending_data(tcp_connection) == 0) { + if (client_send_pending_data(tcp_connection, tcp_client_prof) == 0) { tcp_connection->status = TCP_CLIENT_UNCONFIRMED; } } @@ -1034,7 +1040,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co } if (tcp_connection->status == TCP_CLIENT_CONFIRMED) { - do_confirmed_TCP(logger, tcp_connection, mono_time, userdata); + do_confirmed_TCP(logger, tcp_connection, mono_time, tcp_client_prof, userdata); } if (tcp_connection->kill_at <= mono_time_get(mono_time)) { diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index fed8b63738..a8e46f8774 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -11,6 +11,7 @@ #include "TCP_server.h" #include "crypto_core.h" +#include "net_profile.h" #define TCP_CONNECTION_TIMEOUT 10 @@ -55,7 +56,7 @@ TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip /** Run the TCP connection */ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Connection *tcp_connection, - void *userdata); + Net_Profile *tcp_client_prof, void *userdata); /** Kill the TCP connection */ @@ -67,7 +68,7 @@ typedef int tcp_onion_response_cb(void *object, const uint8_t *data, uint16_t le * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length); +int send_onion_request(TCP_Client_Connection *con, Net_Profile *tcp_client_prof, const uint8_t *data, uint16_t length); void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *onion_callback, void *object); typedef int tcp_routing_response_cb(void *object, uint8_t connection_id, const uint8_t *public_key); @@ -77,7 +78,8 @@ typedef int tcp_routing_status_cb(void *object, uint32_t number, uint8_t connect * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key); +int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key, Net_Profile *tcp_client_prof); + void routing_response_handler(TCP_Client_Connection *con, tcp_routing_response_cb *response_callback, void *object); void routing_status_handler(TCP_Client_Connection *con, tcp_routing_status_cb *status_callback, void *object); @@ -85,7 +87,7 @@ void routing_status_handler(TCP_Client_Connection *con, tcp_routing_status_cb *s * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id); +int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id, Net_Profile *tcp_client_prof); /** Set the number that will be used as an argument in the callbacks related to con_id. * @@ -103,7 +105,8 @@ typedef int tcp_routing_data_cb(void *object, uint32_t number, uint8_t connectio * return 0 if could not send packet. * return -1 on failure. */ -int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length); +int send_data(TCP_Client_Connection *con, uint8_t con_id, Net_Profile *tcp_client_prof, const uint8_t *data, + uint16_t length); void routing_data_handler(TCP_Client_Connection *con, tcp_routing_data_cb *data_callback, void *object); typedef int tcp_oob_data_cb(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length, @@ -113,8 +116,8 @@ typedef int tcp_oob_data_cb(void *object, const uint8_t *public_key, const uint8 * return 0 if could not send packet. * return -1 on failure. */ -int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length); +int send_oob_packet(TCP_Client_Connection *con, Net_Profile *tcp_client_prof, const uint8_t *public_key, + const uint8_t *data, uint16_t length); void oob_data_handler(TCP_Client_Connection *con, tcp_oob_data_cb *oob_data_callback, void *object); - #endif diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c index 57f1161baa..20535f6bc4 100644 --- a/toxcore/TCP_connection.c +++ b/toxcore/TCP_connection.c @@ -42,6 +42,8 @@ struct TCP_Connections { bool onion_status; uint16_t onion_num_conns; + + Net_Profile net_profile; }; @@ -50,6 +52,10 @@ const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c) return tcp_c->self_public_key; } +const Net_Profile *tcp_connections_get_net_profile(const TCP_Connections *tcp_c) +{ + return &tcp_c->net_profile; +} uint32_t tcp_connections_count(const TCP_Connections *tcp_c) { @@ -316,7 +322,7 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c continue; } - ret = send_data(tcp_con->connection, connection_id, packet, length); + ret = send_data(tcp_con->connection, connection_id, &tcp_c->net_profile, packet, length); if (ret == 0) { limit_reached = 1; @@ -348,7 +354,7 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c continue; } - if (send_oob_packet(tcp_con->connection, con_to->public_key, packet, length) == 1) { + if (send_oob_packet(tcp_con->connection, &tcp_c->net_profile, con_to->public_key, packet, length) == 1) { ret += 1; } } @@ -400,7 +406,8 @@ int tcp_send_onion_request(TCP_Connections *tcp_c, uint32_t tcp_connections_numb } if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_CONNECTED) { - int ret = send_onion_request(tcp_c->tcp_connections[tcp_connections_number].connection, data, length); + int ret = send_onion_request(tcp_c->tcp_connections[tcp_connections_number].connection, &tcp_c->net_profile, data, + length); if (ret == 1) { return 0; @@ -428,7 +435,7 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num return -1; } - int ret = send_oob_packet(tcp_con->connection, public_key, packet, length); + int ret = send_oob_packet(tcp_con->connection, &tcp_c->net_profile, public_key, packet, length); if (ret == 1) { return 0; @@ -577,7 +584,7 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number) } if (tcp_con->status == TCP_CONN_CONNECTED) { - send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id); + send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id, &tcp_c->net_profile); } if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) { @@ -915,7 +922,7 @@ static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connec return -1; } - if (send_routing_request(tcp_con->connection, public_key) != 1) { + if (send_routing_request(tcp_con->connection, public_key, &tcp_c->net_profile) != 1) { return -1; } @@ -1418,7 +1425,7 @@ static void do_tcp_conns(const Logger *logger, TCP_Connections *tcp_c, void *use } if (tcp_con->status != TCP_CONN_SLEEPING) { - do_TCP_connection(logger, tcp_c->mono_time, tcp_con->connection, userdata); + do_TCP_connection(logger, tcp_c->mono_time, tcp_con->connection, &tcp_c->net_profile, userdata); /* callbacks can change TCP connection address. */ tcp_con = get_tcp_connection(tcp_c, i); diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h index d27b3e941d..f068c1d30d 100644 --- a/toxcore/TCP_connection.h +++ b/toxcore/TCP_connection.h @@ -10,7 +10,9 @@ #define C_TOXCORE_TOXCORE_TCP_CONNECTION_H #include + #include "TCP_client.h" +#include "net_profile.h" #define TCP_CONN_NONE 0 #define TCP_CONN_VALID 1 @@ -70,6 +72,9 @@ typedef struct TCP_Connections TCP_Connections; const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c); +/** Returns a pointer to the network profile object associated with `tcp_c`. */ +const Net_Profile *tcp_connections_get_net_profile(const TCP_Connections *tcp_c); + uint32_t tcp_connections_count(const TCP_Connections *tcp_c); /** Returns the number of connected TCP relays */ diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 9b56e6ea38..df1d4cf2e4 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -85,6 +85,8 @@ struct TCP_Server { uint64_t counter; BS_List accepted_key_list; + + Net_Profile net_profile; }; const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server) @@ -367,14 +369,14 @@ int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_ /** return 0 if pending data was sent completely * return -1 if it wasn't */ -static int send_pending_data_nonpriority(TCP_Secure_Connection *con) +static int send_pending_data_nonpriority(TCP_Secure_Connection *con, Net_Profile *tcp_server_prof) { if (con->last_packet_length == 0) { return 0; } const uint16_t left = con->last_packet_length - con->last_packet_sent; - const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left); + const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left, tcp_server_prof); if (len <= 0) { return -1; @@ -393,10 +395,10 @@ static int send_pending_data_nonpriority(TCP_Secure_Connection *con) /** return 0 if pending data was sent completely * return -1 if it wasn't */ -static int send_pending_data(TCP_Secure_Connection *con) +static int send_pending_data(TCP_Secure_Connection *con, Net_Profile *tcp_server_net_profile) { /* finish sending current non-priority packet */ - if (send_pending_data_nonpriority(con) == -1) { + if (send_pending_data_nonpriority(con, tcp_server_net_profile) == -1) { return -1; } @@ -404,7 +406,7 @@ static int send_pending_data(TCP_Secure_Connection *con) while (p) { const uint16_t left = p->size - p->sent; - const int len = net_send(con->sock, p->data + p->sent, left); + const int len = net_send(con->sock, p->data + p->sent, left, tcp_server_net_profile); if (len != left) { if (len > 0) { @@ -461,7 +463,7 @@ static bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint * return -1 on failure (connection must be killed). */ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, - bool priority) + bool priority, Net_Profile *tcp_server_prof) { if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { return -1; @@ -469,7 +471,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const bool sendpriority = 1; - if (send_pending_data(con) == -1) { + if (send_pending_data(con, tcp_server_prof) == -1) { if (priority) { sendpriority = 0; } else { @@ -488,7 +490,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const } if (priority) { - len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0; + len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet), tcp_server_prof) : 0; if (len <= 0) { len = 0; @@ -503,7 +505,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const return add_priority(con, packet, SIZEOF_VLA(packet), len); } - len = net_send(con->sock, packet, SIZEOF_VLA(packet)); + len = net_send(con->sock, packet, SIZEOF_VLA(packet), tcp_server_prof); if (len <= 0) { return 0; @@ -560,7 +562,7 @@ static int kill_accepted(TCP_Server *tcp_server, int index) * return -1 if the connection must be killed. */ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, - const uint8_t *self_secret_key) + const uint8_t *self_secret_key, Net_Profile *tcp_server_prof) { if (length != TCP_CLIENT_HANDSHAKE_SIZE) { return -1; @@ -600,7 +602,7 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, return -1; } - if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE)) { + if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE, tcp_server_prof)) { crypto_memzero(shared_key, sizeof(shared_key)); return -1; } @@ -617,13 +619,14 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, * return 0 if we didn't get it yet. * return -1 if the connection must be killed. */ -static int read_connection_handshake(const Logger *logger, TCP_Secure_Connection *con, const uint8_t *self_secret_key) +static int read_connection_handshake(const Logger *logger, TCP_Secure_Connection *con, const uint8_t *self_secret_key, + Net_Profile *tcp_server_prof) { uint8_t data[TCP_CLIENT_HANDSHAKE_SIZE]; const int len = read_TCP_packet(logger, con->sock, data, TCP_CLIENT_HANDSHAKE_SIZE); if (len != -1) { - return handle_TCP_handshake(con, data, len, self_secret_key); + return handle_TCP_handshake(con, data, len, self_secret_key, tcp_server_prof); } return 0; @@ -633,34 +636,35 @@ static int read_connection_handshake(const Logger *logger, TCP_Secure_Connection * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const uint8_t *public_key) +static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const uint8_t *public_key, + Net_Profile *tcp_server_prof) { uint8_t data[1 + 1 + CRYPTO_PUBLIC_KEY_SIZE]; data[0] = TCP_PACKET_ROUTING_RESPONSE; data[1] = rpid; memcpy(data + 2, public_key, CRYPTO_PUBLIC_KEY_SIZE); - return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); + return write_packet_TCP_secure_connection(con, data, sizeof(data), 1, tcp_server_prof); } /** return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) +static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id, Net_Profile *tcp_server_prof) { uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)}; - return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); + return write_packet_TCP_secure_connection(con, data, sizeof(data), 1, tcp_server_prof); } /** return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id) +static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id, Net_Profile *tcp_server_prof) { uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)}; - return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); + return write_packet_TCP_secure_connection(con, data, sizeof(data), 1, tcp_server_prof); } /** return 0 on success. @@ -670,10 +674,11 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const { uint32_t index = -1; TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[con_id]; + Net_Profile *tcp_server_prof = &tcp_server->net_profile; /* If person tries to cennect to himself we deny the request*/ if (public_key_cmp(con->public_key, public_key) == 0) { - if (send_routing_response(con, 0, public_key) == -1) { + if (send_routing_response(con, 0, public_key, tcp_server_prof) == -1) { return -1; } @@ -683,7 +688,7 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const for (uint32_t i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { if (con->connections[i].status != 0) { if (public_key_cmp(public_key, con->connections[i].public_key) == 0) { - if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) { + if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key, tcp_server_prof) == -1) { return -1; } @@ -695,14 +700,14 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const } if (index == (uint32_t) -1) { - if (send_routing_response(con, 0, public_key) == -1) { + if (send_routing_response(con, 0, public_key, tcp_server_prof) == -1) { return -1; } return 0; } - int ret = send_routing_response(con, index + NUM_RESERVED_PORTS, public_key); + int ret = send_routing_response(con, index + NUM_RESERVED_PORTS, public_key, tcp_server_prof); if (ret == 0) { return 0; @@ -736,8 +741,8 @@ static int handle_TCP_routing_req(TCP_Server *tcp_server, uint32_t con_id, const other_conn->connections[other_id].index = con_id; other_conn->connections[other_id].other_id = index; // TODO(irungentoo): return values? - send_connect_notification(con, index); - send_connect_notification(other_conn, other_id); + send_connect_notification(con, index, &tcp_server->net_profile); + send_connect_notification(other_conn, other_id, &tcp_server->net_profile); } } @@ -764,7 +769,7 @@ static int handle_TCP_oob_send(TCP_Server *tcp_server, uint32_t con_id, const ui memcpy(resp_packet + 1, con->public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(resp_packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length); write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[other_index], resp_packet, - SIZEOF_VLA(resp_packet), 0); + SIZEOF_VLA(resp_packet), 0, &tcp_server->net_profile); } return 0; @@ -794,7 +799,7 @@ static int rm_connection_index(TCP_Server *tcp_server, TCP_Secure_Connection *co tcp_server->accepted_connection_array[index].connections[other_id].index = 0; tcp_server->accepted_connection_array[index].connections[other_id].status = 1; // TODO(irungentoo): return values? - send_disconnect_notification(&tcp_server->accepted_connection_array[index], other_id); + send_disconnect_notification(&tcp_server->accepted_connection_array[index], other_id, &tcp_server->net_profile); } con->connections[con_number].index = 0; @@ -825,7 +830,7 @@ static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, memcpy(packet + 1, data, length); packet[0] = TCP_PACKET_ONION_RESPONSE; - if (write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0) != 1) { + if (write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0, &tcp_server->net_profile) != 1) { return 1; } @@ -843,6 +848,8 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint TCP_Secure_Connection *con = &tcp_server->accepted_connection_array[con_id]; + netprof_record_packet(&tcp_server->net_profile, data[0], length, DIR_RECV); + switch (data[0]) { case TCP_PACKET_ROUTING_REQUEST: { if (length != 1 + CRYPTO_PUBLIC_KEY_SIZE) { @@ -876,7 +883,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint uint8_t response[1 + sizeof(uint64_t)]; response[0] = TCP_PACKET_PONG; memcpy(response + 1, data + 1, sizeof(uint64_t)); - write_packet_TCP_secure_connection(con, response, sizeof(response), 1); + write_packet_TCP_secure_connection(con, response, sizeof(response), 1, &tcp_server->net_profile); return 0; } @@ -955,7 +962,8 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint VLA(uint8_t, new_data, length); memcpy(new_data, data, length); new_data[0] = other_c_id; - int ret = write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[index], new_data, length, 0); + int ret = write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[index], + new_data, length, 0, &tcp_server->net_profile); if (ret == -1) { return -1; @@ -1152,7 +1160,7 @@ static int do_incoming(TCP_Server *tcp_server, uint32_t i) } int ret = read_connection_handshake(tcp_server->logger, &tcp_server->incoming_connection_queue[i], - tcp_server->secret_key); + tcp_server->secret_key, &tcp_server->net_profile); if (ret == -1) { kill_TCP_secure_connection(&tcp_server->incoming_connection_queue[i]); @@ -1275,7 +1283,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time) } memcpy(ping + 1, &ping_id, sizeof(uint64_t)); - int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); + int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1, &tcp_server->net_profile); if (ret == 1) { conn->last_pinged = mono_time_get(mono_time); @@ -1293,7 +1301,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time) continue; } - send_pending_data(conn); + send_pending_data(conn, &tcp_server->net_profile); #ifndef TCP_SERVER_USE_EPOLL @@ -1472,3 +1480,12 @@ void kill_TCP_server(TCP_Server *tcp_server) free(tcp_server->socks_listening); free(tcp_server); } + +const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server) +{ + if (tcp_server) { + return &tcp_server->net_profile; + } + + return nullptr; +} diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index b9e4a671aa..edf6adb23c 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -11,6 +11,7 @@ #include "crypto_core.h" #include "list.h" +#include "net_profile.h" #include "onion.h" #define MAX_INCOMING_CONNECTIONS 256 @@ -67,6 +68,11 @@ typedef struct TCP_Server TCP_Server; const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server); size_t tcp_server_listen_count(const TCP_Server *tcp_server); +/** Returns a pointer to the network net_profile object associated with `tcp_server`. + * Returns a null pointer if `tcp_server` is null. + */ +const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server); + /** Create new TCP server instance. */ TCP_Server *new_TCP_server(const Logger *logger, uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 16a4a17527..256e918531 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -165,6 +165,17 @@ TCP_Connections *nc_get_tcp_c(const Net_Crypto *c) return c->tcp_c; } +const Net_Profile *nc_get_tcp_client_net_profile(const Net_Crypto *c) +{ + const TCP_Connections *tcp_c = nc_get_tcp_c(c); + + if (tcp_c == nullptr) { + return nullptr; + } + + return tcp_connections_get_net_profile(tcp_c); +} + DHT *nc_get_dht(const Net_Crypto *c) { return c->dht; diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 452066a702..214413d4fc 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -131,6 +131,12 @@ typedef int connection_lossy_data_cb(void *object, int id, const uint8_t *data, typedef void dht_pk_cb(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata); typedef int new_connection_cb(void *object, New_Connection *n_c); +/** + * Returns a pointer to the net profile object for the TCP client associated with `c`. + * Returns a null pointer if `c` is null. + */ +const Net_Profile *nc_get_tcp_client_net_profile(const Net_Crypto *c); + /* Set function to be called when someone requests a new connection to us. * * The set function should return -1 on failure and 0 on success. diff --git a/toxcore/net_profile.c b/toxcore/net_profile.c new file mode 100644 index 0000000000..8f20cd7f1a --- /dev/null +++ b/toxcore/net_profile.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +/* + * Functions for the network profile. + */ + +#include "net_profile.h" +#include "ccompat.h" + +#define NETPROF_TCP_DATA_PACKET_ID 0x10 + +/** Returns the number of sent or received packets for all ID's between `start_id` and `end_id`. */ +static uint64_t netprof_get_packet_count_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id, + Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + const uint64_t *arr = dir == DIR_SENT ? profile->packets_sent : profile->packets_recv; + uint64_t count = 0; + + for (uint8_t i = start_id; i <= end_id; ++i) { + count += arr[i]; + } + + return count; +} + +/** Returns the number of sent or received bytes for all ID's between `start_id` and `end_id`. */ +static uint64_t netprof_get_bytes_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id, + Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + const uint64_t *arr = dir == DIR_SENT ? profile->bytes_sent : profile->bytes_recv; + uint64_t bytes = 0; + + for (uint8_t i = start_id; i <= end_id; ++i) { + bytes += arr[i]; + } + + return bytes; +} + +void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir) +{ + if (profile == nullptr) { + return; + } + + if (dir == DIR_SENT) { + ++profile->total_packets_sent; + ++profile->packets_sent[id]; + + profile->total_bytes_sent += length; + profile->bytes_sent[id] += length; + } else { + ++profile->total_packets_recv; + ++profile->packets_recv[id]; + + profile->total_bytes_recv += length; + profile->bytes_recv[id] += length; + } +} + +uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + // Special case - TCP data packets can have any ID between 0x10 and 0xff + if (id == NETPROF_TCP_DATA_PACKET_ID) { + return netprof_get_packet_count_id_range(profile, id, 0xff, dir); + } + + return dir == DIR_SENT ? profile->packets_sent[id] : profile->packets_recv[id]; +} + +uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + return dir == DIR_SENT ? profile->total_packets_sent : profile->total_packets_recv; +} + +uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + // Special case - TCP data packets can have any ID between 0x10 and 0xff + if (id == NETPROF_TCP_DATA_PACKET_ID) { + return netprof_get_bytes_id_range(profile, id, 0xff, dir); + } + + return dir == DIR_SENT ? profile->bytes_sent[id] : profile->bytes_recv[id]; +} + +uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + return dir == DIR_SENT ? profile->total_bytes_sent : profile->total_bytes_recv; +} diff --git a/toxcore/net_profile.h b/toxcore/net_profile.h new file mode 100644 index 0000000000..8e50da3be7 --- /dev/null +++ b/toxcore/net_profile.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022 The TokTok team. + */ + +/* + * Functions for the network profile. + */ +#ifndef C_TOXCORE_TOXCORE_NET_PROFILE_H +#define C_TOXCORE_TOXCORE_NET_PROFILE_H + +#include +#include + +/* The max number of packet ID's (should always be >= 256) */ +#define NET_PROF_MAX_PACKET_IDS 256 + +typedef struct Net_Profile { + uint64_t packets_recv[NET_PROF_MAX_PACKET_IDS]; + uint64_t packets_sent[NET_PROF_MAX_PACKET_IDS]; + + uint64_t total_packets_recv; + uint64_t total_packets_sent; + + uint64_t bytes_recv[NET_PROF_MAX_PACKET_IDS]; + uint64_t bytes_sent[NET_PROF_MAX_PACKET_IDS]; + + uint64_t total_bytes_recv; + uint64_t total_bytes_sent; +} Net_Profile; + +/** Specifies whether the query is for sent or received packets. */ +typedef enum Packet_Direction { + DIR_SENT, + DIR_RECV, +} Packet_Direction; + +/** + * Records a sent or received packet of type `id` and size `length` to the given profile. + */ +void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir); + +/** + * Returns the number of sent or received packets of type `id` for the given profile. + */ +uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir); + +/** + * Returns the total number of sent or received packets for the given profile. + */ +uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir); + +/** + * Returns the number of bytes sent or received of packet type `id` for the given profile. + */ +uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir); + +/** + * Returns the total number of bytes sent or received for the given profile. + */ +uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir); + +#endif // C_TOXCORE_TOXCORE_NET_PROFILE_H diff --git a/toxcore/network.c b/toxcore/network.c index 81a9ad333f..535f229a21 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -523,6 +523,8 @@ struct Networking_Core { uint16_t port; /* Our UDP socket. */ Socket sock; + + Net_Profile udp_net_profile; }; Family net_family(const Networking_Core *net) @@ -610,6 +612,10 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1 loglogdata(net->log, "O=>", data, length, ip_port, res); + if (res == length) { + netprof_record_packet(&net->udp_net_profile, data[0], length, DIR_SENT); + } + return res; } @@ -710,6 +716,8 @@ void networking_poll(Networking_Core *net, void *userdata) continue; } + netprof_record_packet(&net->udp_net_profile, data[0], length, DIR_RECV); + packet_handler_cb *const cb = net->packethandlers[data[0]].function; void *const object = net->packethandlers[data[0]].object; @@ -1560,13 +1568,21 @@ Socket net_socket(Family domain, int type, int protocol) #endif } -int net_send(Socket sock, const void *buf, size_t len) +int net_send(Socket sock, const void *buf, size_t len, Net_Profile *net_profile) { + int ret; #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return fuzz_send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL); + ret = fuzz_send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL); #else - return send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL); + ret = send(sock.socket, (const char *)buf, len, MSG_NOSIGNAL); #endif + + if (buf && ret == len) { + const uint8_t *data = (const uint8_t *)buf; + netprof_record_packet(net_profile, data[0], len, DIR_SENT); + } + + return ret; } int net_recv(Socket sock, void *buf, size_t len) @@ -1728,3 +1744,12 @@ void net_kill_strerror(const char *strerror) LocalFree((char *)strerror); #endif } + +const Net_Profile *net_get_net_profile(const Networking_Core *net) +{ + if (net) { + return &net->udp_net_profile; + } + + return nullptr; +} diff --git a/toxcore/network.h b/toxcore/network.h index efc1988f6d..3a1fd6eacb 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -10,6 +10,7 @@ #define C_TOXCORE_TOXCORE_NETWORK_H #include "logger.h" +#include "net_profile.h" #include // bool #include // size_t @@ -61,7 +62,7 @@ extern const Socket net_invalid_socket; /** * Calls send(sockfd, buf, len, MSG_NOSIGNAL). */ -int net_send(Socket sock, const void *buf, size_t len); +int net_send(Socket sock, const void *buf, size_t len, Net_Profile *net_profile); /** * Calls recv(sockfd, buf, len, MSG_NOSIGNAL). */ @@ -458,6 +459,11 @@ Networking_Core *new_networking_no_udp(const Logger *log); /** Function to cleanup networking stuff (doesn't do much right now). */ void kill_networking(Networking_Core *net); +/** Returns a pointer to the network net_profile object associated with `net`. + * Returns a null pointer if `net` is null. + */ +const Net_Profile *net_get_net_profile(const Networking_Core *net); + #ifdef __cplusplus } // extern "C" #endif diff --git a/toxcore/tox.c b/toxcore/tox.c index 7299f3b141..b7d6af1504 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -21,6 +21,7 @@ #include "group.h" #include "logger.h" #include "mono_time.h" +#include "net_profile.h" #include "../toxencryptsave/defines.h" @@ -2521,3 +2522,197 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error) unlock(tox); return 0; } + +uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Packet_Id id, Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + lock(tox); + + const Net_Profile *tcp_c_profile = nc_get_tcp_client_net_profile(tox->m->net_crypto); + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + Packet_Direction dir = (Packet_Direction) direction; + + uint64_t count = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + count = netprof_get_packet_count_id(tcp_c_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + count = netprof_get_packet_count_id(tcp_s_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_count = netprof_get_packet_count_id(tcp_c_profile, id, dir); + const uint64_t tcp_s_count = netprof_get_packet_count_id(tcp_s_profile, id, dir); + count = tcp_c_count + tcp_s_count; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + count = netprof_get_packet_count_id(udp_profile, id, dir); + break; + } + + default: { /* can't happen */ + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + unlock(tox); + + return count; +} + +uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + lock(tox); + + const Net_Profile *tcp_c_profile = nc_get_tcp_client_net_profile(tox->m->net_crypto); + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + Packet_Direction dir = (Packet_Direction) direction; + + uint64_t count = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + count = netprof_get_packet_count_total(tcp_c_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + count = netprof_get_packet_count_total(tcp_s_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_count = netprof_get_packet_count_total(tcp_c_profile, dir); + const uint64_t tcp_s_count = netprof_get_packet_count_total(tcp_s_profile, dir); + count = tcp_c_count + tcp_s_count; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + count = netprof_get_packet_count_total(udp_profile, dir); + break; + } + + default: { /* can't happen */ + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + unlock(tox); + + return count; +} + +uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Packet_Id id, Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + lock(tox); + + const Net_Profile *tcp_c_profile = nc_get_tcp_client_net_profile(tox->m->net_crypto); + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + Packet_Direction dir = (Packet_Direction) direction; + + uint64_t bytes = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + bytes = netprof_get_bytes_id(tcp_c_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + bytes = netprof_get_bytes_id(tcp_s_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_bytes = netprof_get_bytes_id(tcp_c_profile, id, dir); + const uint64_t tcp_s_bytes = netprof_get_bytes_id(tcp_s_profile, id, dir); + bytes = tcp_c_bytes + tcp_s_bytes; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + bytes = netprof_get_bytes_id(udp_profile, id, dir); + break; + } + + default: { /* can't happen */ + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + unlock(tox); + + return bytes; +} + +uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + lock(tox); + + const Net_Profile *tcp_c_profile = nc_get_tcp_client_net_profile(tox->m->net_crypto); + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + Packet_Direction dir = (Packet_Direction) direction; + + uint64_t bytes = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + bytes = netprof_get_bytes_total(tcp_c_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + bytes = netprof_get_bytes_total(tcp_s_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_bytes = netprof_get_bytes_total(tcp_c_profile, dir); + const uint64_t tcp_s_bytes = netprof_get_bytes_total(tcp_s_profile, dir); + bytes = tcp_c_bytes + tcp_s_bytes; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + bytes = netprof_get_bytes_total(udp_profile, dir); + break; + } + + default: { /* can't happen */ + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + return bytes; +} diff --git a/toxcore/tox_private.h b/toxcore/tox_private.h index 593282f7c8..40027b11d2 100644 --- a/toxcore/tox_private.h +++ b/toxcore/tox_private.h @@ -37,8 +37,234 @@ void tox_callback_friend_lossless_packet_per_pktid(Tox *tox, tox_friend_lossless void tox_set_av_object(Tox *tox, void *object); void *tox_get_av_object(const Tox *tox); + +/******************************************************************************* + * + * :: Network profiler + * + ******************************************************************************/ + + + +/** + * Represents all of the network packet identifiers that Toxcore uses. + * + * Note: Some packet ID's have different purposes depending on the + * packet type. These ID's are given numeral names. + */ +typedef enum Tox_Netprof_Packet_Id { + /** + * Ping request packet (UDP). + * Routing request (TCP). + */ + TOX_NETPROF_PACKET_ID_ZERO = 0x00, + + /** + * Ping response packet (UDP). + * Routing response (TCP). + */ + TOX_NETPROF_PACKET_ID_ONE = 0x01, + + /** + * Get nodes request packet (UDP). + * Connection notification (TCP). + */ + TOX_NETPROF_PACKET_ID_TWO = 0x02, + + /** + * TCP disconnect notification. + */ + TOX_NETPROF_PACKET_ID_TCP_DISCONNECT = 0x03, + + /** + * Send nodes response packet (UDP). + * Ping packet (TCP). + */ + TOX_NETPROF_PACKET_ID_FOUR = 0x04, + + /** + * TCP pong packet. + */ + TOX_NETPROF_PACKET_ID_TCP_PONG = 0x05, + + /** + * TCP out-of-band send packet. + */ + TOX_NETPROF_PACKET_ID_TCP_OOB_SEND = 0x06, + + /** + * TCP out-of-band receive packet. + */ + TOX_NETPROF_PACKET_ID_TCP_OOB_RECV = 0x07, + + /** + * TCP onion request packet. + */ + TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST = 0x08, + + /** + * TCP onion response packet. + */ + TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE = 0x09, + + /** + * TCP data packet. + */ + TOX_NETPROF_PACKET_ID_TCP_DATA = 0x10, + + /** + * Cookie request packet. + */ + TOX_NETPROF_PACKET_ID_COOKIE_REQUEST = 0x18, + + /** + * Cookie response packet. + */ + TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE = 0x19, + + /** + * Crypto handshake packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO_HS = 0x1a, + + /** + * Crypto data packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO_DATA = 0x1b, + + /** + * Encrypted data packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO = 0x20, + + /** + * LAN discovery packet. + */ + TOX_NETPROF_PACKET_ID_LAN_DISCOVERY = 0x21, + + /** + * Onion send packets. + */ + TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL = 0x80, + TOX_NETPROF_PACKET_ID_ONION_SEND_1 = 0x81, + TOX_NETPROF_PACKET_ID_ONION_SEND_2 = 0x82, + + /** + * DHT announce request packet. + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST = 0x83, + + /** + * DHT announce response packet. + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE = 0x84, + + /** + * Onion data request packet. + */ + TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST = 0x85, + + /** + * Onion data response packet. + */ + TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE = 0x86, + + /** + * Onion receive packets. + */ + TOX_NETPROF_PACKET_ID_ONION_RECV_3 = 0x8c, + TOX_NETPROF_PACKET_ID_ONION_RECV_2 = 0x8d, + TOX_NETPROF_PACKET_ID_ONION_RECV_1 = 0x8e, + + /** + * Bootstrap info packet. + */ + TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO = 0xf0, +} Tox_Netprof_Packet_Id; + +/** + * Specifies the packet type for a given query. + */ +typedef enum Tox_Netprof_Packet_Type { + /** + * TCP client packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP_CLIENT, + + /** + * TCP server packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP_SERVER, + + /** + * Combined TCP server and TCP client packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP, + + /** + * UDP packets. + */ + TOX_NETPROF_PACKET_TYPE_UDP, +} Tox_Netprof_Packet_Type; + +/** + * Specifies the packet direction for a given query. + */ +typedef enum Tox_Netprof_Direction { + /** + * Outbound packets. + */ + TOX_NET_PROFILE_DIRECTION_SENT, + + /** + * Inbound packets. + */ + TOX_NET_PROFILE_DIRECTION_RECV, +} Tox_Netprof_Direction; + +/** + * Return the number of packets sent or received for a specific packet ID. + * + * @param type The types of packets being queried. + * @param id The packet ID being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Packet_Id id, Tox_Netprof_Direction direction); + +/** + * Return the total number of packets sent or received. + * + * @param type The types of packets being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction); +/** + * Return the number of bytes sent or received for a specific packet ID. + * + * @param type The types of packets being queried. + * @param id The packet ID being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Packet_Id id, Tox_Netprof_Direction direction); +/** + * Return the total number of bytes sent or received. + * + * @param type The types of packets being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction); + + #ifdef __cplusplus } #endif +typedef Tox_Netprof_Packet_Id TOX_NETPROF_PACKET_ID; +typedef Tox_Netprof_Direction TOX_NETPROF_DIRECTION; +typedef Tox_Netprof_Packet_Type TOX_NETPROF_PACKET_TYPE; + #endif // C_TOXCORE_TOXCORE_TOX_PRIVATE_H