diff --git a/.circleci/config.yml b/.circleci/config.yml index ee37ea56fde..3bd04544bea 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -77,6 +77,7 @@ jobs: llvm-dev ninja-build pkg-config + llvm-dev - checkout - run: git submodule update --init --recursive - run: CC=clang .circleci/cmake-asan diff --git a/.gitignore b/.gitignore index fc3cc5f7332..4a4d74c5a0c 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ testing/data # Vim *.swp +*.nvimlog # Object files *.o diff --git a/CMakeLists.txt b/CMakeLists.txt index e6634322632..06228911293 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -270,6 +270,8 @@ set(toxcore_SOURCES toxcore/mem.h toxcore/mono_time.c toxcore/mono_time.h + toxcore/net_profile.c + toxcore/net_profile.h toxcore/net_crypto.c toxcore/net_crypto.h toxcore/network.c diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index f478f3c53f8..18a3eb6b80a 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -34,11 +34,11 @@ static IP get_loopback(void) return ip; } -static void do_tcp_server_delay(TCP_Server *tcp_s, Mono_Time *mono_time, int delay) +static void do_TCP_server_delay(TCP_Server *tcp_s, Mono_Time *mono_time, int delay) { c_sleep(delay); mono_time_update(mono_time); - do_tcp_server(tcp_s, mono_time); + do_TCP_server(tcp_s, mono_time); c_sleep(delay); } static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643}; @@ -111,12 +111,12 @@ static void test_basic(void) // Sending the handshake ck_assert_msg(net_send(ns, logger, sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1, - &localhost) == TCP_CLIENT_HANDSHAKE_SIZE - 1, + &localhost, 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(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost) == 1, + ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost, nullptr) == 1, "The attempt to send the last byte of handshake failed."); free(handshake); @@ -155,7 +155,7 @@ static void test_basic(void) msg_length = sizeof(r_req) - i; } - ck_assert_msg(net_send(ns, logger, sock, r_req + i, msg_length, &localhost) == msg_length, + ck_assert_msg(net_send(ns, logger, sock, r_req + i, msg_length, &localhost, nullptr) == msg_length, "Failed to send request after completing the handshake."); i += msg_length; @@ -234,12 +234,12 @@ static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem, "Failed to encrypt the outgoing handshake."); ck_assert_msg(net_send(ns, logger, sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1, - &localhost) == TCP_CLIENT_HANDSHAKE_SIZE - 1, + &localhost, 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(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost) == 1, + ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost, nullptr) == 1, "Failed to send last byte of handshake."); do_tcp_server_delay(tcp_s, mono_time, 50); @@ -282,7 +282,7 @@ static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP localhost.ip = get_loopback(); localhost.port = 0; - ck_assert_msg(net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &localhost) == SIZEOF_VLA(packet), + ck_assert_msg(net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &localhost, nullptr) == SIZEOF_VLA(packet), "Failed to send a packet."); return 0; } @@ -523,7 +523,7 @@ static void test_client(void) ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); ip_port_tcp_s.ip = get_loopback(); - TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr); + TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr, nullptr); do_tcp_connection(logger, mono_time, conn, nullptr); c_sleep(50); @@ -558,7 +558,7 @@ static void test_client(void) crypto_new_keypair(rng, f2_public_key, f2_secret_key); ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key, - f2_secret_key, nullptr); + f2_secret_key, nullptr, nullptr); // The client should call this function (defined earlier) during the routing process. routing_response_handler(conn, response_callback, (char *)conn + 2); @@ -654,7 +654,7 @@ static void test_client_invalid(void) ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); ip_port_tcp_s.ip = get_loopback(); TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, - self_public_key, f_public_key, f_secret_key, nullptr); + self_public_key, f_public_key, f_secret_key, nullptr, nullptr); // Run the client's main loop but not the server. mono_time_update(mono_time); diff --git a/other/bootstrap_node_packets.c b/other/bootstrap_node_packets.c index 7ff0e9e7563..8ad636a2b3f 100644 --- a/other/bootstrap_node_packets.c +++ b/other/bootstrap_node_packets.c @@ -28,7 +28,7 @@ static int handle_info_request(void *object, const IP_Port *source, const uint8_ return 1; } - const Networking_Core *nc = (const Networking_Core *)object; + Networking_Core *nc = (Networking_Core *)object; uint8_t data[1 + sizeof(bootstrap_version) + MAX_MOTD_LENGTH]; data[0] = BOOTSTRAP_INFO_PACKET_ID; diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 4701cf437d3..7b333777ab1 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -250,6 +250,7 @@ cc_library( ":logger", ":mem", ":mono_time", + ":net_profile", ":util", "@libsodium", "@psocket", @@ -257,6 +258,13 @@ cc_library( ], ) +cc_library( + name = "net_profile", + srcs = ["net_profile.c"], + hdrs = ["net_profile.h"], + deps = [":ccompat"], +) + cc_test( name = "network_test", size = "small", @@ -500,6 +508,7 @@ cc_library( ":crypto_core", ":list", ":mono_time", + ":net_profile", ":onion", ":util", ], diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index ef44d3b5525..00be6915894 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c @@ -209,7 +209,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) * @retval false on failure to find any valid broadcast target. */ non_null() -static bool send_broadcasts(const Networking_Core *net, const Broadcast_Info *broadcast, uint16_t port, +static bool send_broadcasts(Networking_Core *net, const Broadcast_Info *broadcast, uint16_t port, const uint8_t *data, uint16_t length) { if (broadcast->count == 0) { diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 70df82b39e6..b413fded680 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -53,6 +53,8 @@ libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \ ../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 \ diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index aeb722f660e..0d3b6518026 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -573,7 +573,7 @@ void forwarding_handler(TCP_Client_Connection *con, forwarded_response_cb *forwa TCP_Client_Connection *new_tcp_connection( const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, - const TCP_Proxy_Info *proxy_info) + const TCP_Proxy_Info *proxy_info, Net_Profile *net_profile) { assert(logger != nullptr); assert(mem != nullptr); @@ -625,6 +625,7 @@ TCP_Client_Connection *new_tcp_connection( temp->con.rng = rng; temp->con.sock = sock; temp->con.ip_port = *ip_port; + temp->con.net_profile = net_profile; memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE); encrypt_precompute(temp->public_key, self_secret_key, temp->con.shared_key); @@ -669,6 +670,8 @@ static int handle_tcp_client_routing_response(TCP_Client_Connection *conn, const return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, DIR_RECV); + if (data[1] < NUM_RESERVED_PORTS) { return 0; } @@ -697,6 +700,8 @@ static int handle_tcp_client_connection_notification(TCP_Client_Connection *conn return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, DIR_RECV); + if (data[1] < NUM_RESERVED_PORTS) { return -1; } @@ -724,6 +729,8 @@ static int handle_tcp_client_disconnect_notification(TCP_Client_Connection *conn return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, DIR_RECV); + if (data[1] < NUM_RESERVED_PORTS) { return -1; } @@ -755,6 +762,8 @@ static int handle_tcp_client_ping(const Logger *logger, TCP_Client_Connection *c return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, DIR_RECV); + uint64_t ping_id; memcpy(&ping_id, data + 1, sizeof(uint64_t)); conn->ping_response_id = ping_id; @@ -769,6 +778,8 @@ static int handle_tcp_client_pong(TCP_Client_Connection *conn, const uint8_t *da return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, DIR_RECV); + uint64_t ping_id; memcpy(&ping_id, data + 1, sizeof(uint64_t)); @@ -790,6 +801,8 @@ static int handle_tcp_client_oob_recv(TCP_Client_Connection *conn, const uint8_t return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, DIR_RECV); + if (conn->oob_data_callback != nullptr) { conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE), userdata); @@ -810,6 +823,8 @@ static int handle_tcp_client_packet(const Logger *logger, TCP_Client_Connection return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, DIR_RECV); + switch (data[0]) { case TCP_PACKET_ROUTING_RESPONSE: return handle_tcp_client_routing_response(conn, data, length); diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index eceed047b7a..2ff29bb18f1 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -57,11 +57,11 @@ non_null() void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value); /** Create new TCP connection to ip_port/public_key */ -non_null(1, 2, 3, 4, 5, 6, 7, 8, 9) nullable(10) +non_null(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) nullable(11) TCP_Client_Connection *new_tcp_connection( const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, - const TCP_Proxy_Info *proxy_info); + const TCP_Proxy_Info *proxy_info, Net_Profile *net_profile); /** Run the TCP connection */ non_null(1, 2, 3) nullable(4) diff --git a/toxcore/TCP_common.c b/toxcore/TCP_common.c index 5d0019486c0..ea5d09d6a1a 100644 --- a/toxcore/TCP_common.c +++ b/toxcore/TCP_common.c @@ -31,7 +31,7 @@ int send_pending_data_nonpriority(const Logger *logger, TCP_Connection *con) } const uint16_t left = con->last_packet_length - con->last_packet_sent; - const int len = net_send(con->ns, logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port); + const int len = net_send(con->ns, logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port, con->net_profile); if (len <= 0) { return -1; @@ -62,7 +62,7 @@ int send_pending_data(const Logger *logger, TCP_Connection *con) while (p != nullptr) { const uint16_t left = p->size - p->sent; - const int len = net_send(con->ns, logger, con->sock, p->data + p->sent, left, &con->ip_port); + const int len = net_send(con->ns, logger, con->sock, p->data + p->sent, left, &con->ip_port, con->net_profile); if (len != left) { if (len > 0) { @@ -157,7 +157,7 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con } if (priority) { - len = sendpriority ? net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &con->ip_port) : 0; + len = sendpriority ? net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &con->ip_port, con->net_profile) : 0; if (len <= 0) { len = 0; @@ -172,7 +172,7 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con return add_priority(con, packet, SIZEOF_VLA(packet), len) ? 1 : 0; } - len = net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &con->ip_port); + len = net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &con->ip_port, con->net_profile); if (len <= 0) { return 0; diff --git a/toxcore/TCP_common.h b/toxcore/TCP_common.h index 7891168f727..198208b5f1c 100644 --- a/toxcore/TCP_common.h +++ b/toxcore/TCP_common.h @@ -8,6 +8,7 @@ #include "crypto_core.h" #include "mem.h" +#include "net_profile.h" #include "network.h" typedef struct TCP_Priority_List TCP_Priority_List; @@ -77,6 +78,10 @@ typedef struct TCP_Connection { TCP_Priority_List *priority_queue_start; TCP_Priority_List *priority_queue_end; + + // This is a shared pointer to the parent's respective Net_Profile object + // (either TCP_Server for TCP server packets or TCP_Connections for TCP client packets). + Net_Profile *net_profile; } TCP_Connection; /** diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c index f274376c1cd..ca316ea92e9 100644 --- a/toxcore/TCP_connection.c +++ b/toxcore/TCP_connection.c @@ -50,6 +50,9 @@ struct TCP_Connections { bool onion_status; uint16_t onion_num_conns; + + /* Network profile for all TCP client packets. */ + Net_Profile net_profile; }; @@ -925,7 +928,7 @@ 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(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &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->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, &tcp_c->net_profile); if (tcp_con->connection == nullptr) { kill_tcp_relay_connection(tcp_c, tcp_connections_number); @@ -1014,7 +1017,7 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti tcp_con->connection = new_tcp_connection( tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &tcp_con->ip_port, - tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); + tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, &tcp_c->net_profile); if (tcp_con->connection == nullptr) { kill_tcp_relay_connection(tcp_c, tcp_connections_number); @@ -1310,7 +1313,7 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, const IP_Port *ip_port tcp_con->connection = new_tcp_connection( tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ipp_copy, - relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); + relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, &tcp_c->net_profile); if (tcp_con->connection == nullptr) { return -1; @@ -1722,3 +1725,12 @@ void kill_tcp_connections(TCP_Connections *tcp_c) mem_delete(tcp_c->mem, tcp_c->connections); mem_delete(tcp_c->mem, tcp_c); } + +const Net_Profile *tcp_connection_get_client_net_profile(const TCP_Connections *tcp_c) +{ + if (tcp_c == nullptr) { + return nullptr; + } + + return &tcp_c->net_profile; +} diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h index f01e7054459..f5339cf939f 100644 --- a/toxcore/TCP_connection.h +++ b/toxcore/TCP_connection.h @@ -14,6 +14,7 @@ #include "DHT.h" // for Node_format #include "TCP_client.h" #include "TCP_common.h" +#include "net_profile.h" #define TCP_CONN_NONE 0 #define TCP_CONN_VALID 1 @@ -310,4 +311,9 @@ void do_tcp_connections(const Logger *logger, TCP_Connections *tcp_c, void *user nullable(1) void kill_tcp_connections(TCP_Connections *tcp_c); +/** Returns a pointer to the tcp client net profile associated with `tcp_c`. + * Returns null if `tcp_c` is null. + */ +const Net_Profile *tcp_connection_get_client_net_profile(const TCP_Connections *tcp_c); + #endif diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 905d2bb4341..c06df2d036c 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -85,6 +85,9 @@ struct TCP_Server { uint64_t counter; BS_List accepted_key_list; + + /* Network profile for all TCP server packets. */ + Net_Profile net_profile; }; const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server) @@ -227,6 +230,7 @@ static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_ tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter; tcp_server->accepted_connection_array[index].last_pinged = mono_time_get(mono_time); tcp_server->accepted_connection_array[index].ping_id = 0; + tcp_server->accepted_connection_array[index].con.net_profile = &tcp_server->net_profile; return index; } @@ -348,7 +352,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con IP_Port ipp = {{{0}}}; - if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp)) { + if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp, con->con.net_profile)) { crypto_memzero(shared_key, sizeof(shared_key)); return -1; } @@ -668,6 +672,7 @@ static int handle_tcp_packet(TCP_Server *tcp_server, uint32_t con_id, const uint } TCP_Secure_Connection *const con = &tcp_server->accepted_connection_array[con_id]; + netprof_record_packet(con->con.net_profile, data[0], length, DIR_RECV); switch (data[0]) { case TCP_PACKET_ROUTING_REQUEST: { @@ -1412,3 +1417,12 @@ void kill_tcp_server(TCP_Server *tcp_server) mem_delete(tcp_server->mem, tcp_server->socks_listening); mem_delete(tcp_server->mem, tcp_server); } + +const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server) +{ + if (tcp_server == nullptr) { + return nullptr; + } + + return &tcp_server->net_profile; +} diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 0349f60b9e8..13867ba580d 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -11,6 +11,7 @@ #include "crypto_core.h" #include "forwarding.h" +#include "net_profile.h" #include "onion.h" #define MAX_INCOMING_CONNECTIONS 256 @@ -47,5 +48,10 @@ void do_tcp_server(TCP_Server *tcp_server, const Mono_Time *mono_time); nullable(1) void kill_tcp_server(TCP_Server *tcp_server); +/** Returns a pointer to the net profile associated with `tcp_server`. + * Returns null if `tcp_server` is null. + */ +const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server); + #endif diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 4d2aaac1b01..fcf70ec693c 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -3228,3 +3228,18 @@ void kill_net_crypto(Net_Crypto *c) crypto_memzero(c, sizeof(Net_Crypto)); mem_delete(mem, c); } + +const Net_Profile *nc_get_tcp_client_net_profile(const Net_Crypto *c) +{ + if (c == nullptr) { + return nullptr; + } + + const TCP_Connections *tcp_c = nc_get_tcp_c(c); + + if (tcp_c == nullptr) { + return nullptr; + } + + return tcp_connection_get_client_net_profile(tcp_c); +} diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index ac6a0b59cbd..f0389c3b44b 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -412,4 +412,11 @@ void do_net_crypto(Net_Crypto *c, void *userdata); nullable(1) void kill_net_crypto(Net_Crypto *c); +/** + * Returns a pointer to the net profile object for the TCP client associated with `c`. + * Returns null if `c` is null or the TCP_Connections associated with `c` is null. + */ +const Net_Profile *nc_get_tcp_client_net_profile(const Net_Crypto *c); + + #endif diff --git a/toxcore/net_profile.c b/toxcore/net_profile.c new file mode 100644 index 00000000000..b4b21911a28 --- /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 00000000000..8e50da3be7f --- /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 3e0e6f49c70..65b0f9b4583 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -906,6 +906,8 @@ struct Networking_Core { uint16_t port; /* Our UDP socket. */ Socket sock; + + Net_Profile udp_net_profile; }; Family net_family(const Networking_Core *net) @@ -921,7 +923,7 @@ uint16_t net_port(const Networking_Core *net) /* Basic network functions: */ -int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packet) +int send_packet(Networking_Core *net, const IP_Port *ip_port, Packet packet) { IP_Port ipp_copy = *ip_port; @@ -990,6 +992,11 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe loglogdata(net->log, "O=>", packet.data, packet.length, ip_port, res); assert(res <= INT_MAX); + + if (res == packet.length) { + netprof_record_packet(&net->udp_net_profile, packet.data[0], packet.length, DIR_SENT); + } + return (int)res; } @@ -998,7 +1005,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe * * @deprecated Use send_packet instead. */ -int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t *data, uint16_t length) +int sendpacket(Networking_Core *net, const IP_Port *ip_port, const uint8_t *data, uint16_t length) { const Packet packet = {data, length}; return send_packet(net, ip_port, packet); @@ -1078,7 +1085,7 @@ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handl net->packethandlers[byte].object = object; } -void networking_poll(const Networking_Core *net, void *userdata) +void networking_poll(Networking_Core *net, void *userdata) { if (net_family_is_unspec(net->family)) { /* Socket not initialized */ @@ -1094,6 +1101,8 @@ void networking_poll(const Networking_Core *net, void *userdata) continue; } + netprof_record_packet(&net->udp_net_profile, data[0], length, DIR_RECV); + const Packet_Handler *const handler = &net->packethandlers[data[0]]; if (handler->function == nullptr) { @@ -2086,3 +2095,12 @@ void net_kill_strerror(char *strerror) free(strerror); #endif } + +const Net_Profile *net_get_net_profile(const Networking_Core *net) +{ + if (net == nullptr) { + return nullptr; + } + + return &net->udp_net_profile; +} diff --git a/toxcore/network.h b/toxcore/network.h index 2f518c1d910..72e513a0c39 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -15,6 +15,7 @@ #include "logger.h" #include "mem.h" +#include "net_profile.h" #ifdef __cplusplus extern "C" { @@ -282,8 +283,8 @@ extern const Socket net_invalid_socket; /** * Calls send(sockfd, buf, len, MSG_NOSIGNAL). */ -non_null() -int net_send(const Network *ns, const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port); +non_null(1, 2, 4, 6) nullable(7) +int net_send(const Network *ns, const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port, Net_Profile *net_profile); /** * Calls recv(sockfd, buf, len, MSG_NOSIGNAL). */ @@ -613,6 +614,11 @@ Networking_Core *new_networking_no_udp(const Logger *log, const Memory *mem, con nullable(1) void kill_networking(Networking_Core *net); +/** Returns a pointer to the network net_profile object associated with `net` + * Returns null if `net` is null. + */ +const Net_Profile *net_get_net_profile(const Networking_Core *net); + #ifdef __cplusplus } // extern "C" #endif diff --git a/toxcore/onion.c b/toxcore/onion.c index d7ec8bfd788..00480fddc0f 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -283,7 +283,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac * return -1 on failure. * return 0 on success. */ -int send_onion_response(const Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length, +int send_onion_response(Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length, const uint8_t *ret) { if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) { diff --git a/toxcore/onion.h b/toxcore/onion.h index 7f71c2493d3..d4177cbce40 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -127,7 +127,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac * return 0 on success. */ non_null() -int send_onion_response(const Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length, +int send_onion_response(Networking_Core *net, const IP_Port *dest, const uint8_t *data, uint16_t length, const uint8_t *ret); /** @brief Function to handle/send received decrypted versions of the packet created by create_onion_packet. diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 551e7b1fae9..e06589666f7 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -186,7 +186,7 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_ * return -1 on failure. * return 0 on success. */ -int send_announce_request(const Networking_Core *net, const Random *rng, +int send_announce_request(Networking_Core *net, const Random *rng, const Onion_Path *path, const Node_format *dest, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, @@ -230,7 +230,7 @@ int send_announce_request(const Networking_Core *net, const Random *rng, * return -1 on failure. * return 0 on success. */ -int send_data_request(const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, +int send_data_request(Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length) { diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index 857f4706ace..d65243468e1 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h @@ -94,7 +94,7 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_ * return 0 on success. */ non_null() -int send_announce_request(const Networking_Core *net, const Random *rng, +int send_announce_request(Networking_Core *net, const Random *rng, const Onion_Path *path, const Node_format *dest, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, @@ -117,7 +117,7 @@ int send_announce_request(const Networking_Core *net, const Random *rng, * return 0 on success. */ non_null() -int send_data_request(const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, +int send_data_request(Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); diff --git a/toxcore/tox.c b/toxcore/tox.c index 768d5f9efd4..b439b15ad25 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -24,6 +24,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "tox_private.h" #include "tox_struct.h" diff --git a/toxcore/tox_private.h b/toxcore/tox_private.h index 1503293614f..cf2d301acf8 100644 --- a/toxcore/tox_private.h +++ b/toxcore/tox_private.h @@ -156,6 +156,226 @@ uint16_t tox_dht_get_num_closelist(const Tox *tox); */ uint16_t tox_dht_get_num_closelist_announce_capable(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_NETPROF_DIRECTION_SENT, + + /** + * Inbound packets. + */ + TOX_NETPROF_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