diff --git a/auto_tests/CMakeLists.txt b/auto_tests/CMakeLists.txt index 774e3e331a6..d3216cd5d79 100644 --- a/auto_tests/CMakeLists.txt +++ b/auto_tests/CMakeLists.txt @@ -50,6 +50,7 @@ auto_test(invalid_udp_proxy) auto_test(lan_discovery) auto_test(lossless_packet) auto_test(lossy_packet) +auto_test(netprof) auto_test(network) auto_test(onion) auto_test(overflow_recvq) diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 18a3eb6b80a..1457e64e803 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}; diff --git a/auto_tests/netprof_test.c b/auto_tests/netprof_test.c index 6e646d40a5a..07cfc6c328c 100644 --- a/auto_tests/netprof_test.c +++ b/auto_tests/netprof_test.c @@ -52,8 +52,11 @@ static void test_netprof(AutoTox *autotoxes) ck_assert(UDP_count_recv1 > 0 && UDP_count_sent1 > 0); ck_assert(UDP_bytes_recv1 > 0 && UDP_bytes_sent1 > 0); - ck_assert(TCP_count_sent1 == 0 && TCP_count_recv1 == 0); - ck_assert(TCP_bytes_sent1 == 0 && TCP_bytes_recv1 == 0); + + (void)TCP_count_sent1; + (void)TCP_bytes_sent1; + (void)TCP_bytes_recv1; + (void)TCP_count_recv1; unsigned long long total_sent_count = 0; unsigned long long total_recv_count = 0; @@ -107,7 +110,7 @@ int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - Run_Auto_Options autotox_opts = default_run_auto_options; + Run_Auto_Options autotox_opts = default_run_auto_options(); autotox_opts.graph = GRAPH_COMPLETE; run_auto_test(nullptr, NUM_TOXES, test_netprof, 0, &autotox_opts); diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index 6975c3ec300..9fe5532c505 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -204,7 +204,7 @@ static int handle_test_4(void *object, const IP_Port *source, const uint8_t *pac * Use Onion_Path path to send data of length to dest. * Maximum length of data is ONION_MAX_DATA_SIZE. */ -static void send_onion_packet(const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length) +static void send_onion_packet(Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length) { uint8_t packet[ONION_MAX_PACKET_SIZE]; const int len = create_onion_packet(rng, packet, sizeof(packet), path, dest, data, length); diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 7b333777ab1..4714222195e 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -806,6 +806,7 @@ cc_library( ":logger", ":mem", ":mono_time", + ":net_profile", ":network", "//c-toxcore/toxencryptsave:defines", ], diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index 00be6915894..0042c493a6e 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c @@ -339,7 +339,7 @@ bool ip_is_lan(const IP *ip) } -bool lan_discovery_send(const Networking_Core *net, const Broadcast_Info *broadcast, const uint8_t *dht_pk, +bool lan_discovery_send(Networking_Core *net, const Broadcast_Info *broadcast, const uint8_t *dht_pk, uint16_t port) { if (broadcast == nullptr) { diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h index 5d9c83335b6..e91bc552a5e 100644 --- a/toxcore/LAN_discovery.h +++ b/toxcore/LAN_discovery.h @@ -24,7 +24,7 @@ typedef struct Broadcast_Info Broadcast_Info; * @return true on success, false on failure. */ non_null() -bool lan_discovery_send(const Networking_Core *net, const Broadcast_Info *broadcast, const uint8_t *dht_pk, +bool lan_discovery_send(Networking_Core *net, const Broadcast_Info *broadcast, const uint8_t *dht_pk, uint16_t port); /** diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 0d3b6518026..ced5a6f3389 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -670,8 +670,6 @@ 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; } @@ -700,8 +698,6 @@ 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; } @@ -729,8 +725,6 @@ 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; } @@ -762,8 +756,6 @@ 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; @@ -778,8 +770,6 @@ 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)); diff --git a/toxcore/TCP_common.c b/toxcore/TCP_common.c index ea5d09d6a1a..38c8654f116 100644 --- a/toxcore/TCP_common.c +++ b/toxcore/TCP_common.c @@ -31,7 +31,8 @@ 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, con->net_profile); + 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; @@ -157,7 +158,8 @@ 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, con->net_profile) : 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; diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h index f5339cf939f..f9201a11959 100644 --- a/toxcore/TCP_connection.h +++ b/toxcore/TCP_connection.h @@ -311,9 +311,11 @@ 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. +/** @brief a pointer to the tcp client net profile associated with tcp_c. + * + * @retval null if tcp_c is null. */ +non_null() const Net_Profile *tcp_connection_get_client_net_profile(const TCP_Connections *tcp_c); #endif diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 13867ba580d..ea48b3ce0fe 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -34,23 +34,25 @@ const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server); non_null() size_t tcp_server_listen_count(const TCP_Server *tcp_server); -/** Create new TCP server instance. */ +/** @brief Create new TCP server instance. */ non_null(1, 2, 3, 4, 7, 8) nullable(9, 10) TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns, bool ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key, Onion *onion, Forwarding *forwarding); -/** Run the TCP_server */ +/** @brief Run the TCP_server */ non_null() void do_tcp_server(TCP_Server *tcp_server, const Mono_Time *mono_time); -/** Kill the TCP server */ +/** @brief Kill the TCP server */ nullable(1) void kill_tcp_server(TCP_Server *tcp_server); -/** Returns a pointer to the net profile associated with `tcp_server`. +/** @brief Returns a pointer to the net profile associated with `tcp_server`. + * * Returns null if `tcp_server` is null. */ +nullable(1) const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server); diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index f0389c3b44b..8ce44520415 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -416,6 +416,7 @@ 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. */ +non_null() const Net_Profile *nc_get_tcp_client_net_profile(const Net_Crypto *c); diff --git a/toxcore/net_profile.c b/toxcore/net_profile.c index 8e88cc707f8..ee3e231563c 100644 --- a/toxcore/net_profile.c +++ b/toxcore/net_profile.c @@ -2,16 +2,20 @@ * Copyright © 2022 The TokTok team. */ -/* +/** * Functions for the network profile. */ #include "net_profile.h" + +#include + #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`. */ +nullable(1) static uint64_t netprof_get_packet_count_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id, Packet_Direction dir) { @@ -30,6 +34,7 @@ static uint64_t netprof_get_packet_count_id_range(const Net_Profile *profile, ui } /** Returns the number of sent or received bytes for all ID's between `start_id` and `end_id`. */ +nullable(1) static uint64_t netprof_get_bytes_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id, Packet_Direction dir) { diff --git a/toxcore/net_profile.h b/toxcore/net_profile.h index 8e50da3be7f..4e2cf2effa9 100644 --- a/toxcore/net_profile.h +++ b/toxcore/net_profile.h @@ -2,14 +2,16 @@ * 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 -#include + +#include "attributes.h" /* The max number of packet ID's (should always be >= 256) */ #define NET_PROF_MAX_PACKET_IDS 256 @@ -37,26 +39,31 @@ typedef enum Packet_Direction { /** * Records a sent or received packet of type `id` and size `length` to the given profile. */ +nullable(1) 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. */ +nullable(1) 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. */ +nullable(1) 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. */ +nullable(1) 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. */ +nullable(1) 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 65b0f9b4583..fdb11fcb1b8 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -802,9 +802,15 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu } int net_send(const Network *ns, const Logger *log, - Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port) + Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port, Net_Profile *net_profile) { const int res = ns->funcs->send(ns->obj, sock.sock, buf, len); + + if (buf != nullptr && res == len) { + const uint8_t *data = buf; + netprof_record_packet(net_profile, data[0], len, DIR_SENT); + } + loglogdata(log, "T=>", buf, len, ip_port, res); return res; } diff --git a/toxcore/network.h b/toxcore/network.h index 72e513a0c39..e0e7a013071 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -284,7 +284,8 @@ extern const Socket net_invalid_socket; * Calls send(sockfd, buf, len, MSG_NOSIGNAL). */ 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); +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). */ @@ -511,7 +512,7 @@ typedef struct Packet { * Function to send a network packet to a given IP/port. */ non_null() -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); /** * Function to send packet(data) of length length to ip_port. @@ -519,7 +520,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe * @deprecated Use send_packet instead. */ non_null() -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); /** Function to call when packet beginning with byte is received. */ non_null(1) nullable(3, 4) @@ -527,7 +528,7 @@ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handl /** Call this several times a second. */ non_null(1) nullable(2) -void networking_poll(const Networking_Core *net, void *userdata); +void networking_poll(Networking_Core *net, void *userdata); /** @brief Connect a socket to the address specified by the ip_port. * @@ -614,9 +615,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` +/** @brief Returns a pointer to the network net_profile object associated with `net`. + * * Returns null if `net` is null. */ +non_null() const Net_Profile *net_get_net_profile(const Networking_Core *net); #ifdef __cplusplus diff --git a/toxcore/tox.c b/toxcore/tox.c index b439b15ad25..5bbd1af2ef7 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -2840,6 +2840,202 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error) 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); + + tox_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); + + const 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; + } + } + + tox_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); + + tox_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); + + const 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; + } + } + + tox_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); + + tox_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); + + const 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; + } + } + + tox_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); + + tox_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); + + const 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; + } + } + + tox_unlock(tox); + + return bytes; +} + /* GROUPCHAT FUNCTIONS */ #ifndef VANILLA_NACL diff --git a/toxcore/tox_private.h b/toxcore/tox_private.h index cf2d301acf8..051d54ed99f 100644 --- a/toxcore/tox_private.h +++ b/toxcore/tox_private.h @@ -293,6 +293,17 @@ typedef enum Tox_Netprof_Packet_Id { TOX_NETPROF_PACKET_ID_ONION_RECV_2 = 0x8d, TOX_NETPROF_PACKET_ID_ONION_RECV_1 = 0x8e, + TOX_NETPROF_PACKET_FORWARD_REQUEST = 0x90, + TOX_NETPROF_FORWARDING = 0x91, + TOX_NETPROF_FORWARD_REPLY = 0x92, + + TOX_NETPROF_DATA_SEARCH_REQUEST = 0x93, + TOX_NETPROF_DATA_SEARCH_RESPONSE = 0x94, + TOX_NETPROF_DATA_RETRIEVE_REQUEST = 0x95, + TOX_NETPROF_DATA_RETRIEVE_RESPONSE = 0x96, + TOX_NETPROF_STORE_ANNOUNCE_REQUEST = 0x97, + TOX_NETPROF_STORE_ANNOUNCE_RESPONSE = 0x98, + /** * Bootstrap info packet. */