diff options
author | George Hazan <ghazan@miranda.im> | 2022-07-24 16:44:24 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2022-07-24 16:44:24 +0300 |
commit | e55d071e5485a937efd427d159b76c208cccdcce (patch) | |
tree | 48d09dc5cf1df2581fd6471b5ccf1560015fa3a4 /protocols/Tox/libtox/src/toxcore/net_crypto.c | |
parent | f36629f67153bc500c828cf51de31988122a1024 (diff) |
fixes #3118 (Update toxcore to 0.2.18)
Diffstat (limited to 'protocols/Tox/libtox/src/toxcore/net_crypto.c')
-rw-r--r-- | protocols/Tox/libtox/src/toxcore/net_crypto.c | 784 |
1 files changed, 459 insertions, 325 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.c b/protocols/Tox/libtox/src/toxcore/net_crypto.c index 77ba2294ce..c34a45734c 100644 --- a/protocols/Tox/libtox/src/toxcore/net_crypto.c +++ b/protocols/Tox/libtox/src/toxcore/net_crypto.c @@ -14,6 +14,7 @@ #include <stdlib.h> #include <string.h> +#include "ccompat.h" #include "list.h" #include "mono_time.h" #include "util.h" @@ -112,7 +113,7 @@ typedef struct Crypto_Connection { /* TCP_connection connection_number */ unsigned int connection_number_tcp; - uint8_t maximum_speed_reached; + bool maximum_speed_reached; /* Must be a pointer, because the struct is moved in memory */ pthread_mutex_t *mutex; @@ -122,9 +123,13 @@ typedef struct Crypto_Connection { uint32_t dht_pk_callback_number; } Crypto_Connection; +static const Crypto_Connection empty_crypto_connection = {{0}}; + struct Net_Crypto { const Logger *log; + const Random *rng; Mono_Time *mono_time; + const Network *ns; DHT *dht; TCP_Connections *tcp_c; @@ -173,6 +178,7 @@ DHT *nc_get_dht(const Net_Crypto *c) return c->dht; } +non_null() static bool crypt_connection_id_is_valid(const Net_Crypto *c, int crypt_connection_id) { if ((uint32_t)crypt_connection_id >= c->crypto_connections_length) { @@ -185,11 +191,7 @@ static bool crypt_connection_id_is_valid(const Net_Crypto *c, int crypt_connecti const Crypto_Conn_State status = c->crypto_connections[crypt_connection_id].status; - if (status == CRYPTO_CONN_NO_CONNECTION || status == CRYPTO_CONN_FREE) { - return false; - } - - return true; + return status != CRYPTO_CONN_NO_CONNECTION && status != CRYPTO_CONN_FREE; } /** cookie timeout in seconds */ @@ -202,14 +204,16 @@ static bool crypt_connection_id_is_valid(const Net_Crypto *c, int crypt_connecti #define COOKIE_REQUEST_LENGTH (uint16_t)(1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) #define COOKIE_RESPONSE_LENGTH (uint16_t)(1 + CRYPTO_NONCE_SIZE + COOKIE_LENGTH + sizeof(uint64_t) + CRYPTO_MAC_SIZE) -/** Create a cookie request packet and put it in packet. +/** @brief Create a cookie request packet and put it in packet. + * * dht_public_key is the dht public key of the other * * packet must be of size COOKIE_REQUEST_LENGTH or bigger. * - * return -1 on failure. - * return COOKIE_REQUEST_LENGTH on success. + * @retval -1 on failure. + * @retval COOKIE_REQUEST_LENGTH on success. */ +non_null() static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uint8_t *dht_public_key, uint64_t number, uint8_t *shared_key) { @@ -222,34 +226,35 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uin dht_get_shared_key_sent(c->dht, shared_key, dht_public_key); uint8_t nonce[CRYPTO_NONCE_SIZE]; - random_nonce(nonce); + random_nonce(c->rng, nonce); packet[0] = NET_PACKET_COOKIE_REQUEST; memcpy(packet + 1, dht_get_self_public_key(c->dht), CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE); - int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain), + const int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain), packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); if (len != COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) { return -1; } - return (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + len); + return 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + len; } -/** Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key +/** @brief Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ -static int create_cookie(const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes, +non_null() +static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes, const uint8_t *encryption_key) { uint8_t contents[COOKIE_CONTENTS_LENGTH]; const uint64_t temp_time = mono_time_get(mono_time); memcpy(contents, &temp_time, sizeof(temp_time)); memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH); - random_nonce(cookie); - int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE); + random_nonce(rng, cookie); + const int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE); if (len != COOKIE_LENGTH - CRYPTO_NONCE_SIZE) { return -1; @@ -258,11 +263,12 @@ static int create_cookie(const Mono_Time *mono_time, uint8_t *cookie, const uint return 0; } -/** Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_DATA_LENGTH using encryption_key +/** @brief Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_DATA_LENGTH using encryption_key * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int open_cookie(const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key) { @@ -287,13 +293,14 @@ static int open_cookie(const Mono_Time *mono_time, uint8_t *bytes, const uint8_t } -/** Create a cookie response packet and put it in packet. - * request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes. - * packet must be of size COOKIE_RESPONSE_LENGTH or bigger. +/** @brief Create a cookie response packet and put it in packet. + * @param request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes. + * @param packet must be of size COOKIE_RESPONSE_LENGTH or bigger. * - * return -1 on failure. - * return COOKIE_RESPONSE_LENGTH on success. + * @retval -1 on failure. + * @retval COOKIE_RESPONSE_LENGTH on success. */ +non_null() static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const uint8_t *request_plain, const uint8_t *shared_key, const uint8_t *dht_public_key) { @@ -302,14 +309,14 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE); uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; - if (create_cookie(c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) { + if (create_cookie(c->rng, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) { return -1; } memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t)); packet[0] = NET_PACKET_COOKIE_RESPONSE; - random_nonce(packet + 1); - int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE); + random_nonce(c->rng, packet + 1); + const int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE); if (len != COOKIE_RESPONSE_LENGTH - (1 + CRYPTO_NONCE_SIZE)) { return -1; @@ -318,13 +325,14 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui return COOKIE_RESPONSE_LENGTH; } -/** Handle the cookie request packet of length length. +/** @brief Handle the cookie request packet of length length. * Put what was in the request in request_plain (must be of size COOKIE_REQUEST_PLAIN_LENGTH) * Put the key used to decrypt the request into shared_key (of size CRYPTO_SHARED_KEY_SIZE) for use in the response. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key, uint8_t *dht_public_key, const uint8_t *packet, uint16_t length) { @@ -334,7 +342,7 @@ static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, ui memcpy(dht_public_key, packet + 1, CRYPTO_PUBLIC_KEY_SIZE); dht_get_shared_key_sent(c->dht, shared_key, dht_public_key); - int len = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, + const int len = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE, request_plain); @@ -345,8 +353,8 @@ static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, ui return 0; } -/** Handle the cookie request packet (for raw UDP) - */ +/** Handle the cookie request packet (for raw UDP) */ +non_null(1, 2, 3) nullable(5) static int udp_handle_cookie_request(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) { @@ -372,8 +380,8 @@ static int udp_handle_cookie_request(void *object, const IP_Port *source, const return 0; } -/** Handle the cookie request packet (for TCP) - */ +/** Handle the cookie request packet (for TCP) */ +non_null() static int tcp_handle_cookie_request(const Net_Crypto *c, int connections_number, const uint8_t *packet, uint16_t length) { @@ -391,12 +399,12 @@ static int tcp_handle_cookie_request(const Net_Crypto *c, int connections_number return -1; } - int ret = send_packet_tcp_connection(c->tcp_c, connections_number, data, sizeof(data)); + const int ret = send_packet_tcp_connection(c->tcp_c, connections_number, data, sizeof(data)); return ret; } -/** Handle the cookie request packet (for TCP oob packets) - */ +/** Handle the cookie request packet (for TCP oob packets) */ +non_null() static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *dht_public_key, const uint8_t *packet, uint16_t length) { @@ -408,7 +416,7 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c return -1; } - if (public_key_cmp(dht_public_key, dht_public_key_temp) != 0) { + if (!pk_equal(dht_public_key, dht_public_key_temp)) { return -1; } @@ -418,18 +426,19 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c return -1; } - int ret = tcp_send_oob_packet(c->tcp_c, tcp_connections_number, dht_public_key, data, sizeof(data)); + const int ret = tcp_send_oob_packet(c->tcp_c, tcp_connections_number, dht_public_key, data, sizeof(data)); return ret; } -/** Handle a cookie response packet of length encrypted with shared_key. +/** @brief Handle a cookie response packet of length encrypted with shared_key. * put the cookie in the response in cookie * - * cookie must be of length COOKIE_LENGTH. + * @param cookie must be of length COOKIE_LENGTH. * - * return -1 on failure. - * return COOKIE_LENGTH on success. + * @retval -1 on failure. + * @retval COOKIE_LENGTH on success. */ +non_null() static int handle_cookie_response(uint8_t *cookie, uint64_t *number, const uint8_t *packet, uint16_t length, const uint8_t *shared_key) @@ -453,13 +462,14 @@ static int handle_cookie_response(uint8_t *cookie, uint64_t *number, #define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE) -/** Create a handshake packet and put it in packet. - * cookie must be COOKIE_LENGTH bytes. - * packet must be of size HANDSHAKE_PACKET_LENGTH or bigger. +/** @brief Create a handshake packet and put it in packet. + * @param cookie must be COOKIE_LENGTH bytes. + * @param packet must be of size HANDSHAKE_PACKET_LENGTH or bigger. * - * return -1 on failure. - * return HANDSHAKE_PACKET_LENGTH on success. + * @retval -1 on failure. + * @retval HANDSHAKE_PACKET_LENGTH on success. */ +non_null() static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const uint8_t *cookie, const uint8_t *nonce, const uint8_t *session_pk, const uint8_t *peer_real_pk, const uint8_t *peer_dht_pubkey) { @@ -471,13 +481,13 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); - if (create_cookie(c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, + if (create_cookie(c->rng, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, cookie_plain, c->secret_symmetric_key) != 0) { return -1; } - random_nonce(packet + 1 + COOKIE_LENGTH); - int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), + random_nonce(c->rng, packet + 1 + COOKIE_LENGTH); + const int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE); if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE)) { @@ -490,7 +500,7 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u return HANDSHAKE_PACKET_LENGTH; } -/** Handle a crypto handshake packet of length. +/** @brief Handle a crypto handshake packet of length. * put the nonce contained in the packet in nonce, * the session public key in session_pk * the real public key of the peer in peer_real_pk @@ -505,40 +515,41 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u * peer_real_pk must be at least CRYPTO_PUBLIC_KEY_SIZE * cookie must be at least COOKIE_LENGTH * - * return -1 on failure. - * return 0 on success. + * @retval false on failure. + * @retval true on success. */ -static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk, - uint8_t *dht_public_key, uint8_t *cookie, const uint8_t *packet, uint16_t length, const uint8_t *expected_real_pk) +non_null(1, 2, 3, 4, 5, 6, 7) nullable(9) +static bool handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk, + uint8_t *dht_public_key, uint8_t *cookie, const uint8_t *packet, uint16_t length, const uint8_t *expected_real_pk) { if (length != HANDSHAKE_PACKET_LENGTH) { - return -1; + return false; } uint8_t cookie_plain[COOKIE_DATA_LENGTH]; if (open_cookie(c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { - return -1; + return false; } - if (expected_real_pk && public_key_cmp(cookie_plain, expected_real_pk) != 0) { - return -1; + if (expected_real_pk != nullptr && !pk_equal(cookie_plain, expected_real_pk)) { + return false; } uint8_t cookie_hash[CRYPTO_SHA512_SIZE]; crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH); uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH]; - int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, + const int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE, HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE), plain); if (len != sizeof(plain)) { - return -1; + return false; } - if (crypto_sha512_cmp(cookie_hash, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE) != 0) { - return -1; + if (!crypto_sha512_eq(cookie_hash, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE)) { + return false; } memcpy(nonce, plain, CRYPTO_NONCE_SIZE); @@ -546,10 +557,11 @@ static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t memcpy(cookie, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, COOKIE_LENGTH); memcpy(peer_real_pk, cookie_plain, CRYPTO_PUBLIC_KEY_SIZE); memcpy(dht_public_key, cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE); - return 0; + return true; } +non_null() static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_connection_id) { if (!crypt_connection_id_is_valid(c, crypt_connection_id)) { @@ -560,11 +572,12 @@ static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_c } -/** Associate an ip_port to a connection. +/** @brief Associate an ip_port to a connection. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip_port) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -598,14 +611,15 @@ static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, const return -1; } -/** Return the IP_Port that should be used to send packets to the other peer. +/** @brief Return the IP_Port that should be used to send packets to the other peer. * - * return IP_Port with family 0 on failure. - * return IP_Port on success. + * @retval IP_Port with family 0 on failure. + * @return IP_Port on success. */ +non_null() static IP_Port return_ip_port_connection(const Net_Crypto *c, int crypt_connection_id) { - const IP_Port empty = {0}; + const IP_Port empty = {{{0}}}; const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -614,15 +628,15 @@ static IP_Port return_ip_port_connection(const Net_Crypto *c, int crypt_connecti } const uint64_t current_time = mono_time_get(c->mono_time); - bool v6 = 0; - bool v4 = 0; + bool v6 = false; + bool v4 = false; if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) { - v4 = 1; + v4 = true; } if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) { - v6 = 1; + v6 = true; } /* Prefer IP_Ports which haven't timed out to those which have. @@ -655,11 +669,12 @@ static IP_Port return_ip_port_connection(const Net_Crypto *c, int crypt_connecti return empty; } -/** Sends a packet to the peer using the fastest route. +/** @brief Sends a packet to the peer using the fastest route. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) { // TODO(irungentoo): TCP, etc... @@ -669,14 +684,14 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t return -1; } - int direct_send_attempt = 0; + bool direct_send_attempt = false; pthread_mutex_lock(conn->mutex); IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id); // TODO(irungentoo): on bad networks, direct connections might not last indefinitely. if (!net_family_is_unspec(ip_port.ip.family)) { - bool direct_connected = 0; + bool direct_connected = false; // FIXME(sudden6): handle return value crypto_connection_status(c, crypt_connection_id, &direct_connected, nullptr); @@ -688,6 +703,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t } pthread_mutex_unlock(conn->mutex); + LOGGER_WARNING(c->log, "sending packet of length %d failed", length); return -1; } @@ -697,7 +713,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) < current_time && length < 96) || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { if ((uint32_t)sendpacket(dht_get_net(c->dht), &ip_port, data, length) == length) { - direct_send_attempt = 1; + direct_send_attempt = true; conn->direct_send_attempt_time = mono_time_get(c->mono_time); } } @@ -705,7 +721,7 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t pthread_mutex_unlock(conn->mutex); pthread_mutex_lock(&c->tcp_mutex); - int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length); + const int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length); pthread_mutex_unlock(&c->tcp_mutex); pthread_mutex_lock(conn->mutex); @@ -716,38 +732,40 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t pthread_mutex_unlock(conn->mutex); - if (ret == 0 || direct_send_attempt) { + if (direct_send_attempt) { return 0; } - return -1; + return ret; } /*** START: Array Related functions */ -/** Return number of packets in array +/** @brief Return number of packets in array * Note that holes are counted too. */ +non_null() static uint32_t num_packets_array(const Packets_Array *array) { return array->buffer_end - array->buffer_start; } -/** Add data with packet number to array. +/** @brief Add data with packet number to array. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packet_Data *data) { if (number - array->buffer_start >= CRYPTO_PACKET_BUFFER_SIZE) { return -1; } - uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; + const uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; - if (array->buffer[num]) { + if (array->buffer[num] != nullptr) { return -1; } @@ -767,12 +785,13 @@ static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packe return 0; } -/** Get pointer of data with packet number. +/** @brief Get pointer of data with packet number. * - * return -1 on failure. - * return 0 if data at number is empty. - * return 1 if data pointer was put in data. + * @retval -1 on failure. + * @retval 0 if data at number is empty. + * @retval 1 if data pointer was put in data. */ +non_null() static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint32_t number) { const uint32_t num_spots = num_packets_array(array); @@ -781,9 +800,9 @@ static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint return -1; } - uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; + const uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; - if (!array->buffer[num]) { + if (array->buffer[num] == nullptr) { return 0; } @@ -791,37 +810,41 @@ static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint return 1; } -/** Add data to end of array. +/** @brief Add data to end of array. * - * return -1 on failure. - * return packet number on success. + * @retval -1 on failure. + * @return packet number on success. */ -static int64_t add_data_end_of_buffer(Packets_Array *array, const Packet_Data *data) +non_null() +static int64_t add_data_end_of_buffer(const Logger *logger, Packets_Array *array, const Packet_Data *data) { const uint32_t num_spots = num_packets_array(array); if (num_spots >= CRYPTO_PACKET_BUFFER_SIZE) { + LOGGER_WARNING(logger, "crypto packet buffer size exceeded; rejecting packet of length %d", data->length); return -1; } Packet_Data *new_d = (Packet_Data *)calloc(1, sizeof(Packet_Data)); if (new_d == nullptr) { + LOGGER_ERROR(logger, "packet data allocation failed"); return -1; } *new_d = *data; - uint32_t id = array->buffer_end; + const uint32_t id = array->buffer_end; array->buffer[id % CRYPTO_PACKET_BUFFER_SIZE] = new_d; ++array->buffer_end; return id; } -/** Read data from beginning of array. +/** @brief Read data from beginning of array. * - * return -1 on failure. - * return packet number on success. + * @retval -1 on failure. + * @return packet number on success. */ +non_null() static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data) { if (array->buffer_end == array->buffer_start) { @@ -830,23 +853,24 @@ static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data) const uint32_t num = array->buffer_start % CRYPTO_PACKET_BUFFER_SIZE; - if (!array->buffer[num]) { + if (array->buffer[num] == nullptr) { return -1; } *data = *array->buffer[num]; - uint32_t id = array->buffer_start; + const uint32_t id = array->buffer_start; ++array->buffer_start; free(array->buffer[num]); array->buffer[num] = nullptr; return id; } -/** Delete all packets in array before number (but not number) +/** @brief Delete all packets in array before number (but not number) * - * return -1 on failure. - * return 0 on success + * @retval -1 on failure. + * @retval 0 on success */ +non_null() static int clear_buffer_until(Packets_Array *array, uint32_t number) { const uint32_t num_spots = num_packets_array(array); @@ -858,9 +882,9 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number) uint32_t i; for (i = array->buffer_start; i != number; ++i) { - uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; + const uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; - if (array->buffer[num]) { + if (array->buffer[num] != nullptr) { free(array->buffer[num]); array->buffer[num] = nullptr; } @@ -870,14 +894,15 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number) return 0; } +non_null() static int clear_buffer(Packets_Array *array) { uint32_t i; for (i = array->buffer_start; i != array->buffer_end; ++i) { - uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; + const uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; - if (array->buffer[num]) { + if (array->buffer[num] != nullptr) { free(array->buffer[num]); array->buffer[num] = nullptr; } @@ -887,11 +912,12 @@ static int clear_buffer(Packets_Array *array) return 0; } -/** Set array buffer end to number. +/** @brief Set array buffer end to number. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int set_buffer_end(Packets_Array *array, uint32_t number) { if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE) { @@ -906,12 +932,14 @@ static int set_buffer_end(Packets_Array *array, uint32_t number) return 0; } -/** Create a packet request packet from recv_array and send_buffer_end into - * data of length. +/** + * @brief Create a packet request packet from recv_array and send_buffer_end into + * data of length. * - * return -1 on failure. - * return length of packet on success. + * @retval -1 on failure. + * @return length of packet on success. */ +non_null() static int generate_request_packet(uint8_t *data, uint16_t length, const Packets_Array *recv_array) { if (length == 0) { @@ -933,9 +961,9 @@ static int generate_request_packet(uint8_t *data, uint16_t length, const Packets uint32_t n = 1; for (uint32_t i = recv_array->buffer_start; i != recv_array->buffer_end; ++i) { - uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; + const uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; - if (!recv_array->buffer[num]) { + if (recv_array->buffer[num] == nullptr) { data[cur_len] = n; n = 0; ++cur_len; @@ -959,12 +987,13 @@ static int generate_request_packet(uint8_t *data, uint16_t length, const Packets return cur_len; } -/** Handle a request data packet. +/** @brief Handle a request data packet. * Remove all the packets the other received from the array. * - * return -1 on failure. - * return number of requested packets on success. + * @retval -1 on failure. + * @return number of requested packets on success. */ +non_null() static int handle_request_packet(Mono_Time *mono_time, Packets_Array *send_array, const uint8_t *data, uint16_t length, uint64_t *latest_send_time, uint64_t rtt_time) @@ -988,18 +1017,18 @@ static int handle_request_packet(Mono_Time *mono_time, Packets_Array *send_array uint32_t requested = 0; const uint64_t temp_time = current_time_monotonic(mono_time); - uint64_t l_sent_time = -1; + uint64_t l_sent_time = 0; for (uint32_t i = send_array->buffer_start; i != send_array->buffer_end; ++i) { if (length == 0) { break; } - uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; + const uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; if (n == data[0]) { - if (send_array->buffer[num]) { - uint64_t sent_time = send_array->buffer[num]->sent_time; + if (send_array->buffer[num] != nullptr) { + const uint64_t sent_time = send_array->buffer[num]->sent_time; if ((sent_time + rtt_time) < temp_time) { send_array->buffer[num]->sent_time = 0; @@ -1011,7 +1040,7 @@ static int handle_request_packet(Mono_Time *mono_time, Packets_Array *send_array n = 0; ++requested; } else { - if (send_array->buffer[num]) { + if (send_array->buffer[num] != nullptr) { l_sent_time = max_u64(l_sent_time, send_array->buffer[num]->sent_time); free(send_array->buffer[num]); @@ -1042,32 +1071,37 @@ static int handle_request_packet(Mono_Time *mono_time, Packets_Array *send_array #define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE)) -/** Creates and sends a data packet to the peer using the fastest route. +/** @brief Creates and sends a data packet to the peer using the fastest route. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) { const uint16_t max_length = MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE); if (length == 0 || length > max_length) { + LOGGER_ERROR(c->log, "zero-length or too large data packet: %d (max: %d)", length, max_length); return -1; } Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); if (conn == nullptr) { + LOGGER_ERROR(c->log, "connection id %d not found", crypt_connection_id); return -1; } pthread_mutex_lock(conn->mutex); - VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); + const uint16_t packet_size = 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE; + VLA(uint8_t, packet, packet_size); packet[0] = NET_PACKET_CRYPTO_DATA; memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t)); const int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); - if (len + 1 + sizeof(uint16_t) != SIZEOF_VLA(packet)) { + if (len + 1 + sizeof(uint16_t) != packet_size) { + LOGGER_ERROR(c->log, "encryption failed: %d", len); pthread_mutex_unlock(conn->mutex); return -1; } @@ -1078,21 +1112,23 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_ return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet)); } -/** Creates and sends a data packet with buffer_start and num to the peer using the fastest route. +/** @brief Creates and sends a data packet with buffer_start and num to the peer using the fastest route. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num, const uint8_t *data, uint16_t length) { if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) { + LOGGER_ERROR(c->log, "zero-length or too large data packet: %d (max: %d)", length, MAX_CRYPTO_PACKET_SIZE); return -1; } num = net_htonl(num); buffer_start = net_htonl(buffer_start); - uint16_t padding_length = (MAX_CRYPTO_DATA_SIZE - length) % CRYPTO_MAX_PADDING; + const uint16_t padding_length = (MAX_CRYPTO_DATA_SIZE - length) % CRYPTO_MAX_PADDING; VLA(uint8_t, packet, sizeof(uint32_t) + sizeof(uint32_t) + padding_length + length); memcpy(packet, &buffer_start, sizeof(uint32_t)); memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t)); @@ -1102,6 +1138,7 @@ static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint3 return send_data_packet(c, crypt_connection_id, packet, SIZEOF_VLA(packet)); } +non_null() static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1126,19 +1163,23 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id) dt->sent_time = current_time_monotonic(c->mono_time); } - conn->maximum_speed_reached = 0; + conn->maximum_speed_reached = false; } return 0; } -/** return -1 if data could not be put in packet queue. - * return positive packet number if data was put into the queue. +/** + * @retval -1 if data could not be put in packet queue. + * @return positive packet number if data was put into the queue. */ +non_null() static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, - uint8_t congestion_control) + bool congestion_control) { if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) { + LOGGER_ERROR(c->log, "rejecting too large (or empty) packet of size %d on crypt connection %d", length, + crypt_connection_id); return -1; } @@ -1153,6 +1194,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons reset_max_speed_reached(c, crypt_connection_id); if (conn->maximum_speed_reached && congestion_control) { + LOGGER_INFO(c->log, "congestion control: maximum speed reached on crypt connection %d", crypt_connection_id); return -1; } @@ -1161,7 +1203,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons dt.length = length; memcpy(dt.data, data, length); pthread_mutex_lock(conn->mutex); - int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt); + const int64_t packet_num = add_data_end_of_buffer(c->log, &conn->send_array, &dt); pthread_mutex_unlock(conn->mutex); if (packet_num == -1) { @@ -1179,16 +1221,18 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons dt1->sent_time = current_time_monotonic(c->mono_time); } } else { - conn->maximum_speed_reached = 1; - LOGGER_DEBUG(c->log, "send_data_packet failed"); + conn->maximum_speed_reached = true; + LOGGER_DEBUG(c->log, "send_data_packet failed (packet_num = %ld)", (long)packet_num); } return packet_num; } -/** Get the lowest 2 bytes from the nonce and convert - * them to host byte format before returning them. +/** + * @brief Get the lowest 2 bytes from the nonce and convert + * them to host byte format before returning them. */ +non_null() static uint16_t get_nonce_uint16(const uint8_t *nonce) { uint16_t num; @@ -1198,13 +1242,14 @@ static uint16_t get_nonce_uint16(const uint8_t *nonce) #define DATA_NUM_THRESHOLD 21845 -/** Handle a data packet. +/** @brief Handle a data packet. * Decrypt packet of length and put it into data. * data must be at least MAX_DATA_DATA_PACKET_SIZE big. * - * return -1 on failure. - * return length of data on success. + * @retval -1 on failure. + * @return length of data on success. */ +non_null() static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint8_t *data, const uint8_t *packet, uint16_t length) { @@ -1222,12 +1267,12 @@ static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint uint8_t nonce[CRYPTO_NONCE_SIZE]; memcpy(nonce, conn->recv_nonce, CRYPTO_NONCE_SIZE); - uint16_t num_cur_nonce = get_nonce_uint16(nonce); + const uint16_t num_cur_nonce = get_nonce_uint16(nonce); uint16_t num; net_unpack_u16(packet + 1, &num); - uint16_t diff = num - num_cur_nonce; + const uint16_t diff = num - num_cur_nonce; increment_nonce_number(nonce, diff); - int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), + const int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), data); if ((unsigned int)len != length - crypto_packet_overhead) { @@ -1241,11 +1286,12 @@ static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint return len; } -/** Send a request packet. +/** @brief Send a request packet. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int send_request_packet(Net_Crypto *c, int crypt_connection_id) { const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1255,7 +1301,7 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id) } uint8_t data[MAX_CRYPTO_DATA_SIZE]; - int len = generate_request_packet(data, sizeof(data), &conn->recv_array); + const int len = generate_request_packet(data, sizeof(data), &conn->recv_array); if (len == -1) { return -1; @@ -1265,11 +1311,12 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id) len); } -/** Send up to max num previously requested data packets. +/** @brief Send up to max num previously requested data packets. * - * return -1 on failure. - * return number of packets sent on success. + * @retval -1 on failure. + * @return number of packets sent on success. */ +non_null() static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num) { if (max_num == 0) { @@ -1299,7 +1346,7 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32 continue; } - if (dt->sent_time) { + if (dt->sent_time != 0) { continue; } @@ -1318,11 +1365,12 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32 } -/** Add a new temp packet to send repeatedly. +/** @brief Add a new temp packet to send repeatedly. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length) { if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) { @@ -1341,7 +1389,7 @@ static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const u return -1; } - if (conn->temp_packet) { + if (conn->temp_packet != nullptr) { free(conn->temp_packet); } @@ -1353,11 +1401,12 @@ static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const u return 0; } -/** Clear the temp packet. +/** @brief Clear the temp packet. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1366,7 +1415,7 @@ static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id) return -1; } - if (conn->temp_packet) { + if (conn->temp_packet != nullptr) { free(conn->temp_packet); } @@ -1378,11 +1427,12 @@ static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id) } -/** Send the temp packet. +/** @brief Send the temp packet. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1391,7 +1441,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) return -1; } - if (!conn->temp_packet) { + if (conn->temp_packet == nullptr) { return -1; } @@ -1404,12 +1454,13 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) return 0; } -/** Create a handshake packet and set it as a temp packet. - * cookie must be COOKIE_LENGTH. +/** @brief Create a handshake packet and set it as a temp packet. + * @param cookie must be COOKIE_LENGTH. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const uint8_t *cookie, const uint8_t *dht_public_key) { @@ -1434,11 +1485,12 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const u return 0; } -/** Send a kill packet. +/** @brief Send a kill packet. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int send_kill_packet(Net_Crypto *c, int crypt_connection_id) { const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1452,6 +1504,7 @@ static int send_kill_packet(Net_Crypto *c, int crypt_connection_id) &kill_packet, sizeof(kill_packet)); } +non_null(1) nullable(3) static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userdata) { const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1460,15 +1513,15 @@ static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userda return; } - if (conn->connection_status_callback) { - conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0, - userdata); + if (conn->connection_status_callback != nullptr) { + conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, + false, userdata); } - while (1) { /* TODO(irungentoo): is this really the best way to do this? */ + while (true) { /* TODO(irungentoo): is this really the best way to do this? */ pthread_mutex_lock(&c->connections_mutex); - if (!c->connection_use_counter) { + if (c->connection_use_counter == 0) { break; } @@ -1479,11 +1532,12 @@ static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userda pthread_mutex_unlock(&c->connections_mutex); } -/** Handle a received data packet. +/** @brief Handle a received data packet. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null(1, 3) nullable(6) static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, bool udp, void *userdata) { @@ -1498,7 +1552,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const } uint8_t data[MAX_DATA_DATA_PACKET_SIZE]; - int len = handle_data_packet(c, crypt_connection_id, data, packet, length); + const int len = handle_data_packet(c, crypt_connection_id, data, packet, length); if (len <= (int)(sizeof(uint32_t) * 2)) { return -1; @@ -1546,9 +1600,9 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const clear_temp_packet(c, crypt_connection_id); conn->status = CRYPTO_CONN_ESTABLISHED; - if (conn->connection_status_callback) { - conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1, - userdata); + if (conn->connection_status_callback != nullptr) { + conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, + true, userdata); } } @@ -1561,7 +1615,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const rtt_time = DEFAULT_TCP_PING_CONNECTION; } - int requested = handle_request_packet(c->mono_time, &conn->send_array, + const int requested = handle_request_packet(c->mono_time, &conn->send_array, real_data, real_length, &rtt_calc_time, rtt_time); @@ -1579,7 +1633,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const return -1; } - while (1) { + while (true) { pthread_mutex_lock(conn->mutex); const int ret = read_data_beg_buffer(&conn->recv_array, &dt); pthread_mutex_unlock(conn->mutex); @@ -1588,7 +1642,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const break; } - if (conn->connection_data_callback) { + if (conn->connection_data_callback != nullptr) { conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data, dt.length, userdata); } @@ -1607,7 +1661,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const set_buffer_end(&conn->recv_array, num); - if (conn->connection_lossy_data_callback) { + if (conn->connection_lossy_data_callback != nullptr) { conn->connection_lossy_data_callback(conn->connection_lossy_data_callback_object, conn->connection_lossy_data_callback_id, real_data, real_length, userdata); } @@ -1626,6 +1680,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const return 0; } +non_null() static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1657,6 +1712,7 @@ static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id, return 0; } +non_null(1, 3) nullable(5) static int handle_packet_crypto_hs(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, void *userdata) { @@ -1676,12 +1732,12 @@ static int handle_packet_crypto_hs(Net_Crypto *c, int crypt_connection_id, const uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t cookie[COOKIE_LENGTH]; - if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie, - packet, length, conn->public_key) != 0) { + if (!handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie, + packet, length, conn->public_key)) { return -1; } - if (public_key_cmp(dht_public_key, conn->dht_public_key) == 0) { + if (pk_equal(dht_public_key, conn->dht_public_key)) { encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { @@ -1692,7 +1748,7 @@ static int handle_packet_crypto_hs(Net_Crypto *c, int crypt_connection_id, const conn->status = CRYPTO_CONN_NOT_CONFIRMED; } else { - if (conn->dht_pk_callback) { + if (conn->dht_pk_callback != nullptr) { conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, dht_public_key, userdata); } } @@ -1700,6 +1756,7 @@ static int handle_packet_crypto_hs(Net_Crypto *c, int crypt_connection_id, const return 0; } +non_null(1, 3) nullable(6) static int handle_packet_crypto_data(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, bool udp, void *userdata) { @@ -1716,11 +1773,12 @@ static int handle_packet_crypto_data(Net_Crypto *c, int crypt_connection_id, con return handle_data_packet_core(c, crypt_connection_id, packet, length, udp, userdata); } -/** Handle a packet that was received for the connection. +/** @brief Handle a packet that was received for the connection. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null(1, 3) nullable(6) static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, bool udp, void *userdata) { @@ -1743,11 +1801,12 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, cons } } -/** Set the size of the friend list to numfriends. +/** @brief Set the size of the friend list to numfriends. * - * return -1 if realloc fails. - * return 0 if it succeeds. + * @retval -1 if realloc fails. + * @retval 0 if it succeeds. */ +non_null() static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) { if (num == 0) { @@ -1768,17 +1827,18 @@ static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) } -/** Create a new empty crypto connection. +/** @brief Create a new empty crypto connection. * - * return -1 on failure. - * return connection id on success. + * @retval -1 on failure. + * @return connection id on success. */ +non_null() static int create_crypto_connection(Net_Crypto *c) { - while (1) { /* TODO(irungentoo): is this really the best way to do this? */ + while (true) { /* TODO(irungentoo): is this really the best way to do this? */ pthread_mutex_lock(&c->connections_mutex); - if (!c->connection_use_counter) { + if (c->connection_use_counter == 0) { break; } @@ -1798,7 +1858,7 @@ static int create_crypto_connection(Net_Crypto *c) if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == 0) { id = c->crypto_connections_length; ++c->crypto_connections_length; - memset(&c->crypto_connections[id], 0, sizeof(Crypto_Connection)); + c->crypto_connections[id] = empty_crypto_connection; } } @@ -1829,11 +1889,12 @@ static int create_crypto_connection(Net_Crypto *c) return id; } -/** Wipe a crypto connection. +/** @brief Wipe a crypto connection. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null() static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) { if ((uint32_t)crypt_connection_id >= c->crypto_connections_length) { @@ -1871,11 +1932,12 @@ static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) return 0; } -/** Get crypto connection id from public key of peer. +/** @brief Get crypto connection id from public key of peer. * - * return -1 if there are no connections like we are looking for. - * return id if it found it. + * @retval -1 if there are no connections like we are looking for. + * @return id if it found it. */ +non_null() static int getcryptconnection_id(const Net_Crypto *c, const uint8_t *public_key) { for (uint32_t i = 0; i < c->crypto_connections_length; ++i) { @@ -1883,7 +1945,7 @@ static int getcryptconnection_id(const Net_Crypto *c, const uint8_t *public_key) continue; } - if (public_key_cmp(public_key, c->crypto_connections[i].public_key) == 0) { + if (pk_equal(public_key, c->crypto_connections[i].public_key)) { return i; } } @@ -1891,13 +1953,14 @@ static int getcryptconnection_id(const Net_Crypto *c, const uint8_t *public_key) return -1; } -/** Add a source to the crypto connection. +/** @brief Add a source to the crypto connection. * This is to be used only when we have received a packet from that source. * - * return -1 on failure. - * return positive number on success. - * 0 if source was a direct UDP connection. + * @retval -1 on failure. + * @retval 0 if source was a direct UDP connection. + * @return positive number on success. */ +non_null() static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, const IP_Port *source) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1920,8 +1983,10 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, return 0; } - if (net_family_is_tcp_family(source->ip.family)) { - if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source->ip.ip.v6.uint32[0]) == 0) { + unsigned int tcp_connections_number; + + if (ip_port_to_tcp_connections_number(source, &tcp_connections_number)) { + if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, tcp_connections_number) == 0) { return 1; } } @@ -1930,7 +1995,7 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, } -/** Set function to be called when someone requests a new connection to us. +/** @brief 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. * @@ -1942,12 +2007,13 @@ void new_connection_handler(Net_Crypto *c, new_connection_cb *new_connection_cal c->new_connection_callback_object = object; } -/** Handle a handshake packet by someone who wants to initiate a new connection with us. - * This calls the callback set by new_connection_handler() if the handshake is ok. +/** @brief Handle a handshake packet by someone who wants to initiate a new connection with us. + * This calls the callback set by `new_connection_handler()` if the handshake is ok. * - * return -1 on failure. - * return 0 on success. + * @retval -1 on failure. + * @retval 0 on success. */ +non_null(1, 2, 3) nullable(5) static int handle_new_connection_handshake(Net_Crypto *c, const IP_Port *source, const uint8_t *data, uint16_t length, void *userdata) { @@ -1961,8 +2027,8 @@ static int handle_new_connection_handshake(Net_Crypto *c, const IP_Port *source, n_c.source = *source; n_c.cookie_length = COOKIE_LENGTH; - if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key, - n_c.cookie, data, length, nullptr) != 0) { + if (!handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key, + n_c.cookie, data, length, nullptr)) { free(n_c.cookie); return -1; } @@ -1976,7 +2042,7 @@ static int handle_new_connection_handshake(Net_Crypto *c, const IP_Port *source, return -1; } - if (public_key_cmp(n_c.dht_public_key, conn->dht_public_key) != 0) { + if (!pk_equal(n_c.dht_public_key, conn->dht_public_key)) { connection_kill(c, crypt_connection_id, userdata); } else { if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING && conn->status != CRYPTO_CONN_HANDSHAKE_SENT) { @@ -2001,12 +2067,12 @@ static int handle_new_connection_handshake(Net_Crypto *c, const IP_Port *source, } } - int ret = c->new_connection_callback(c->new_connection_callback_object, &n_c); + const int ret = c->new_connection_callback(c->new_connection_callback_object, &n_c); free(n_c.cookie); return ret; } -/** Accept a crypto connection. +/** @brief Accept a crypto connection. * * return -1 on failure. * return connection id on success. @@ -2044,8 +2110,8 @@ int accept_crypto_connection(Net_Crypto *c, const New_Connection *n_c) memcpy(conn->public_key, n_c->public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(conn->recv_nonce, n_c->recv_nonce, CRYPTO_NONCE_SIZE); memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, CRYPTO_PUBLIC_KEY_SIZE); - random_nonce(conn->sent_nonce); - crypto_new_keypair(conn->sessionpublic_key, conn->sessionsecret_key); + random_nonce(c->rng, conn->sent_nonce); + crypto_new_keypair(c->rng, conn->sessionpublic_key, conn->sessionsecret_key); encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); conn->status = CRYPTO_CONN_NOT_CONFIRMED; @@ -2066,7 +2132,7 @@ int accept_crypto_connection(Net_Crypto *c, const New_Connection *n_c) return crypt_connection_id; } -/** Create a crypto connection. +/** @brief Create a crypto connection. * If one to that real public key already exists, return it. * * return -1 on failure. @@ -2099,8 +2165,8 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u conn->connection_number_tcp = connection_number_tcp; memcpy(conn->public_key, real_public_key, CRYPTO_PUBLIC_KEY_SIZE); - random_nonce(conn->sent_nonce); - crypto_new_keypair(conn->sessionpublic_key, conn->sessionsecret_key); + random_nonce(c->rng, conn->sent_nonce); + crypto_new_keypair(c->rng, conn->sessionpublic_key, conn->sessionsecret_key); conn->status = CRYPTO_CONN_COOKIE_REQUESTING; conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE; @@ -2108,7 +2174,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u conn->rtt_time = DEFAULT_PING_CONNECTION; memcpy(conn->dht_public_key, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE); - conn->cookie_request_number = random_u64(); + conn->cookie_request_number = random_u64(c->rng); uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number, @@ -2124,7 +2190,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u return crypt_connection_id; } -/** Set the direct ip of the crypto connection. +/** @brief Set the direct ip of the crypto connection. * * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure. * @@ -2155,6 +2221,7 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip } +non_null(1, 3) nullable(5) static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_t *data, uint16_t length, void *userdata) { @@ -2177,7 +2244,7 @@ static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_ // This unlocks the mutex that at this point is locked by do_tcp before // calling do_tcp_connections. pthread_mutex_unlock(&c->tcp_mutex); - int ret = handle_packet_connection(c, crypt_connection_id, data, length, 0, userdata); + const int ret = handle_packet_connection(c, crypt_connection_id, data, length, false, userdata); pthread_mutex_lock(&c->tcp_mutex); if (ret != 0) { @@ -2188,6 +2255,7 @@ static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_ return 0; } +non_null(1, 2, 4) nullable(6) static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length, void *userdata) { @@ -2202,10 +2270,7 @@ static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned in } if (data[0] == NET_PACKET_CRYPTO_HS) { - IP_Port source; - source.port = 0; - source.ip.family = net_family_tcp_family; - source.ip.ip.v6.uint32[0] = tcp_connections_number; + IP_Port source = tcp_connections_number_to_ip_port(tcp_connections_number); if (handle_new_connection_handshake(c, &source, data, length, userdata) != 0) { return -1; @@ -2217,7 +2282,7 @@ static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned in return -1; } -/** Add a tcp relay, associating it to a crypt_connection_id. +/** @brief Add a tcp relay, associating it to a crypt_connection_id. * * return 0 if it was added. * return -1 if it wasn't. @@ -2231,12 +2296,12 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip } pthread_mutex_lock(&c->tcp_mutex); - int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key); + const int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key); pthread_mutex_unlock(&c->tcp_mutex); return ret; } -/** Add a tcp relay to the array. +/** @brief Add a tcp relay to the array. * * return 0 if it was added. * return -1 if it wasn't. @@ -2244,12 +2309,12 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_key) { pthread_mutex_lock(&c->tcp_mutex); - int ret = add_tcp_relay_global(c->tcp_c, ip_port, public_key); + const int ret = add_tcp_relay_global(c->tcp_c, ip_port, public_key); pthread_mutex_unlock(&c->tcp_mutex); return ret; } -/** Return a random TCP connection number for use in send_tcp_onion_request. +/** @brief Return a random TCP connection number for use in send_tcp_onion_request. * * TODO(irungentoo): This number is just the index of an array that the elements can * change without warning. @@ -2260,13 +2325,27 @@ int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_k int get_random_tcp_con_number(Net_Crypto *c) { pthread_mutex_lock(&c->tcp_mutex); - int ret = get_random_tcp_onion_conn_number(c->tcp_c); + const int ret = get_random_tcp_onion_conn_number(c->tcp_c); pthread_mutex_unlock(&c->tcp_mutex); return ret; } -/** Send an onion packet via the TCP relay corresponding to tcp_connections_number. +/** @brief Put IP_Port of a random onion TCP connection in ip_port. + * + * return true on success. + * return false on failure. + */ +bool get_random_tcp_conn_ip_port(Net_Crypto *c, IP_Port *ip_port) +{ + pthread_mutex_lock(&c->tcp_mutex); + const bool ret = tcp_get_random_conn_ip_port(c->tcp_c, ip_port); + pthread_mutex_unlock(&c->tcp_mutex); + + return ret; +} + +/** @brief Send an onion packet via the TCP relay corresponding to tcp_connections_number. * * return 0 on success. * return -1 on failure. @@ -2274,13 +2353,34 @@ int get_random_tcp_con_number(Net_Crypto *c) int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length) { pthread_mutex_lock(&c->tcp_mutex); - int ret = tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length); + const int ret = tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length); + pthread_mutex_unlock(&c->tcp_mutex); + + return ret; +} + +/** + * Send a forward request to the TCP relay with IP_Port tcp_forwarder, + * requesting to forward data via a chain of dht nodes starting with dht_node. + * A chain_length of 0 means that dht_node is the final destination of data. + * + * return 0 on success. + * return -1 on failure. + */ +int send_tcp_forward_request(const Logger *logger, Net_Crypto *c, const IP_Port *tcp_forwarder, const IP_Port *dht_node, + const uint8_t *chain_keys, uint16_t chain_length, + const uint8_t *data, uint16_t data_length) +{ + pthread_mutex_lock(&c->tcp_mutex); + const int ret = tcp_send_forward_request(logger, c->tcp_c, tcp_forwarder, dht_node, + chain_keys, chain_length, data, data_length); pthread_mutex_unlock(&c->tcp_mutex); return ret; } -/** Copy a maximum of num TCP relays we are connected to to tcp_relays. +/** @brief Copy a maximum of num random TCP relays we are connected to to tcp_relays. + * * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. * * return number of relays copied to tcp_relays on success. @@ -2293,12 +2393,26 @@ unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, u } pthread_mutex_lock(&c->tcp_mutex); - unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num); + const unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num); pthread_mutex_unlock(&c->tcp_mutex); return ret; } +uint32_t copy_connected_tcp_relays_index(Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx) +{ + if (num == 0) { + return 0; + } + + pthread_mutex_lock(&c->tcp_mutex); + const uint32_t ret = tcp_copy_connected_relays_index(c->tcp_c, tcp_relays, num, idx); + pthread_mutex_unlock(&c->tcp_mutex); + + return ret; +} + +non_null() static void do_tcp(Net_Crypto *c, void *userdata) { pthread_mutex_lock(&c->tcp_mutex); @@ -2328,7 +2442,7 @@ static void do_tcp(Net_Crypto *c, void *userdata) } } -/** Set function to be called when connection with crypt_connection_id goes connects/disconnects. +/** @brief Set function to be called when connection with crypt_connection_id goes connects/disconnects. * * The set function should return -1 on failure and 0 on success. * Note that if this function is set, the connection will clear itself on disconnect. @@ -2353,7 +2467,7 @@ int connection_status_handler(const Net_Crypto *c, int crypt_connection_id, return 0; } -/** Set function to be called when connection with crypt_connection_id receives a lossless data packet of length. +/** @brief Set function to be called when connection with crypt_connection_id receives a lossless data packet of length. * * The set function should return -1 on failure and 0 on success. * Object and id will be passed to this function untouched. @@ -2376,7 +2490,7 @@ int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, return 0; } -/** Set function to be called when connection with crypt_connection_id receives a lossy data packet of length. +/** @brief Set function to be called when connection with crypt_connection_id receives a lossy data packet of length. * * The set function should return -1 on failure and 0 on success. * Object and id will be passed to this function untouched. @@ -2401,7 +2515,7 @@ int connection_lossy_data_handler(const Net_Crypto *c, int crypt_connection_id, } -/** Set the function for this friend that will be callbacked with object and number if +/** @brief Set the function for this friend that will be callbacked with object and number if * the friend sends us a different dht public key than we have associated to him. * * If this function is called, the connection should be recreated with the new public key. @@ -2425,11 +2539,12 @@ int nc_dht_pk_callback(const Net_Crypto *c, int crypt_connection_id, dht_pk_cb * return 0; } -/** Get the crypto connection id from the ip_port. +/** @brief Get the crypto connection id from the ip_port. * * return -1 on failure. * return connection id on success. */ +non_null() static int crypto_id_ip_port(const Net_Crypto *c, const IP_Port *ip_port) { return bs_list_find(&c->ip_port_list, (const uint8_t *)ip_port); @@ -2437,7 +2552,7 @@ static int crypto_id_ip_port(const Net_Crypto *c, const IP_Port *ip_port) #define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE) -/** Handle raw UDP packets coming directly from the socket. +/** @brief Handle raw UDP packets coming directly from the socket. * * Handles: * Cookie response packets. @@ -2445,6 +2560,7 @@ static int crypto_id_ip_port(const Net_Crypto *c, const IP_Port *ip_port) * Crypto data packets. * */ +non_null(1, 2, 3) nullable(5) static int udp_handle_packet(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) { @@ -2468,7 +2584,7 @@ static int udp_handle_packet(void *object, const IP_Port *source, const uint8_t return 0; } - if (handle_packet_connection(c, crypt_connection_id, packet, length, 1, userdata) != 0) { + if (handle_packet_connection(c, crypt_connection_id, packet, length, true, userdata) != 0) { return 1; } @@ -2490,24 +2606,27 @@ static int udp_handle_packet(void *object, const IP_Port *source, const uint8_t return 0; } -/** The dT for the average packet receiving rate calculations. - * Also used as the */ +/** @brief The dT for the average packet receiving rate calculations. + * Also used as the + */ #define PACKET_COUNTER_AVERAGE_INTERVAL 50 -/** Ratio of recv queue size / recv packet rate (in seconds) times +/** @brief Ratio of recv queue size / recv packet rate (in seconds) times * the number of ms between request packets to send at that ratio */ #define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0) -/** Timeout for increasing speed after congestion event (in ms). */ +/** @brief Timeout for increasing speed after congestion event (in ms). */ #define CONGESTION_EVENT_TIMEOUT 1000 -/** If the send queue is SEND_QUEUE_RATIO times larger than the +/** + * If the send queue is SEND_QUEUE_RATIO times larger than the * calculated link speed the packet send speed will be reduced * by a value depending on this number. */ #define SEND_QUEUE_RATIO 2.0 +non_null() static void send_crypto_packets(Net_Crypto *c) { const uint64_t temp_time = current_time_monotonic(c->mono_time); @@ -2537,7 +2656,7 @@ static void send_crypto_packets(Net_Crypto *c) double request_packet_interval = REQUEST_PACKETS_COMPARE_CONSTANT / ((num_packets_array( &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0)); - double request_packet_interval2 = ((CRYPTO_PACKET_MIN_RATE / conn->packet_recv_rate) * + const double request_packet_interval2 = ((CRYPTO_PACKET_MIN_RATE / conn->packet_recv_rate) * (double)CRYPTO_SEND_PACKET_INTERVAL) + (double)PACKET_COUNTER_AVERAGE_INTERVAL; if (request_packet_interval2 < request_packet_interval) { @@ -2564,37 +2683,37 @@ static void send_crypto_packets(Net_Crypto *c) } if ((PACKET_COUNTER_AVERAGE_INTERVAL + conn->packet_counter_set) < temp_time) { - const double dt = temp_time - conn->packet_counter_set; + const double dt = (double)(temp_time - conn->packet_counter_set); conn->packet_recv_rate = (double)conn->packet_counter / (dt / 1000.0); conn->packet_counter = 0; conn->packet_counter_set = temp_time; - uint32_t packets_sent = conn->packets_sent; + const uint32_t packets_sent = conn->packets_sent; conn->packets_sent = 0; - uint32_t packets_resent = conn->packets_resent; + const uint32_t packets_resent = conn->packets_resent; conn->packets_resent = 0; /* conjestion control * calculate a new value of conn->packet_send_rate based on some data */ - unsigned int pos = conn->last_sendqueue_counter % CONGESTION_QUEUE_ARRAY_SIZE; + const unsigned int pos = conn->last_sendqueue_counter % CONGESTION_QUEUE_ARRAY_SIZE; conn->last_sendqueue_size[pos] = num_packets_array(&conn->send_array); long signed int sum = 0; sum = (long signed int)conn->last_sendqueue_size[pos] - (long signed int)conn->last_sendqueue_size[(pos + 1) % CONGESTION_QUEUE_ARRAY_SIZE]; - unsigned int n_p_pos = conn->last_sendqueue_counter % CONGESTION_LAST_SENT_ARRAY_SIZE; + const unsigned int n_p_pos = conn->last_sendqueue_counter % CONGESTION_LAST_SENT_ARRAY_SIZE; conn->last_num_packets_sent[n_p_pos] = packets_sent; conn->last_num_packets_resent[n_p_pos] = packets_resent; conn->last_sendqueue_counter = (conn->last_sendqueue_counter + 1) % (CONGESTION_QUEUE_ARRAY_SIZE * CONGESTION_LAST_SENT_ARRAY_SIZE); - bool direct_connected = 0; + bool direct_connected = false; /* return value can be ignored since the `if` above ensures the connection is established */ crypto_connection_status(c, i, &direct_connected, nullptr); @@ -2605,14 +2724,14 @@ static void send_crypto_packets(Net_Crypto *c) // TODO(irungentoo): use real delay unsigned int delay = (unsigned int)(((double)conn->rtt_time / PACKET_COUNTER_AVERAGE_INTERVAL) + 0.5); - unsigned int packets_set_rem_array = CONGESTION_LAST_SENT_ARRAY_SIZE - CONGESTION_QUEUE_ARRAY_SIZE; + const unsigned int packets_set_rem_array = CONGESTION_LAST_SENT_ARRAY_SIZE - CONGESTION_QUEUE_ARRAY_SIZE; if (delay > packets_set_rem_array) { delay = packets_set_rem_array; } for (unsigned j = 0; j < CONGESTION_QUEUE_ARRAY_SIZE; ++j) { - unsigned int ind = (j + (packets_set_rem_array - delay) + n_p_pos) % CONGESTION_LAST_SENT_ARRAY_SIZE; + const unsigned int ind = (j + (packets_set_rem_array - delay) + n_p_pos) % CONGESTION_LAST_SENT_ARRAY_SIZE; total_sent += conn->last_num_packets_sent[ind]; total_resent += conn->last_num_packets_resent[ind]; } @@ -2626,18 +2745,18 @@ static void send_crypto_packets(Net_Crypto *c) } /* if queue is too big only allow resending packets. */ - uint32_t npackets = num_packets_array(&conn->send_array); + const uint32_t npackets = num_packets_array(&conn->send_array); double min_speed = 1000.0 * (((double)total_sent) / ((double)CONGESTION_QUEUE_ARRAY_SIZE * PACKET_COUNTER_AVERAGE_INTERVAL)); - double min_speed_request = 1000.0 * (((double)(total_sent + total_resent)) / ( + const double min_speed_request = 1000.0 * (((double)(total_sent + total_resent)) / ( (double)CONGESTION_QUEUE_ARRAY_SIZE * PACKET_COUNTER_AVERAGE_INTERVAL)); if (min_speed < CRYPTO_PACKET_MIN_RATE) { min_speed = CRYPTO_PACKET_MIN_RATE; } - double send_array_ratio = (double)npackets / min_speed; + const double send_array_ratio = (double)npackets / min_speed; // TODO(irungentoo): Improve formula? if (send_array_ratio > SEND_QUEUE_RATIO && CRYPTO_MIN_QUEUE_LENGTH < npackets) { @@ -2670,8 +2789,8 @@ static void send_crypto_packets(Net_Crypto *c) double n_packets = conn->packet_send_rate * (((double)(temp_time - conn->last_packets_left_set)) / 1000.0); n_packets += conn->last_packets_left_rem; - uint32_t num_packets = n_packets; - double rem = n_packets - (double)num_packets; + const uint32_t num_packets = n_packets; + const double rem = n_packets - (double)num_packets; if (conn->packets_left > num_packets * 4 + CRYPTO_MIN_QUEUE_LENGTH) { conn->packets_left = num_packets * 4 + CRYPTO_MIN_QUEUE_LENGTH; @@ -2702,7 +2821,7 @@ static void send_crypto_packets(Net_Crypto *c) } } - int ret = send_requested_packets(c, i, conn->packets_left_requested); + const int ret = send_requested_packets(c, i, conn->packets_left_requested); if (ret != -1) { conn->packets_left_requested -= ret; @@ -2730,7 +2849,7 @@ static void send_crypto_packets(Net_Crypto *c) } if (total_send_rate > CRYPTO_PACKET_MIN_RATE) { - sleep_time = (1000.0 / total_send_rate); + sleep_time = 1000.0 / total_send_rate; if (c->current_sleep_time > sleep_time) { c->current_sleep_time = sleep_time + 1; @@ -2744,16 +2863,18 @@ static void send_crypto_packets(Net_Crypto *c) } } -/** Return 1 if max speed was reached for this connection (no more data can be physically through the pipe). - * Return 0 if it wasn't reached. +/** + * @retval 1 if max speed was reached for this connection (no more data can be physically through the pipe). + * @retval 0 if it wasn't reached. */ bool max_speed_reached(Net_Crypto *c, int crypt_connection_id) { return reset_max_speed_reached(c, crypt_connection_id) != 0; } -/** returns the number of packet slots left in the sendbuffer. - * return 0 if failure. +/** + * @return the number of packet slots left in the sendbuffer. + * @retval 0 if failure. */ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id) { @@ -2763,7 +2884,7 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti return 0; } - uint32_t max_packets = CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array); + const uint32_t max_packets = CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array); if (conn->packets_left < max_packets) { return conn->packets_left; @@ -2772,7 +2893,7 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti return max_packets; } -/** Sends a lossless cryptopacket. +/** @brief Sends a lossless cryptopacket. * * return -1 if data could not be put in packet queue. * return positive packet number if data was put into the queue. @@ -2782,31 +2903,38 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti * congestion_control: should congestion control apply to this packet? */ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, - uint8_t congestion_control) + bool congestion_control) { if (length == 0) { + // We need at least a packet id. + LOGGER_ERROR(c->log, "rejecting empty packet for crypto connection %d", crypt_connection_id); return -1; } if (data[0] < PACKET_ID_RANGE_LOSSLESS_START || data[0] > PACKET_ID_RANGE_LOSSLESS_END) { + LOGGER_ERROR(c->log, "rejecting lossless packet with out-of-range id %d", data[0]); return -1; } Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); if (conn == nullptr) { + LOGGER_WARNING(c->log, "invalid crypt connection id %d", crypt_connection_id); return -1; } if (conn->status != CRYPTO_CONN_ESTABLISHED) { + LOGGER_WARNING(c->log, "attempted to send packet to non-established connection %d", crypt_connection_id); return -1; } if (congestion_control && conn->packets_left == 0) { + LOGGER_ERROR(c->log, "congestion control: rejecting packet of length %d on crypt connection %d", length, + crypt_connection_id); return -1; } - int64_t ret = send_lossless_packet(c, crypt_connection_id, data, length, congestion_control); + const int64_t ret = send_lossless_packet(c, crypt_connection_id, data, length, congestion_control); if (ret == -1) { return -1; @@ -2821,7 +2949,7 @@ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t return ret; } -/** Check if packet_number was received by the other side. +/** @brief Check if packet_number was received by the other side. * * packet_number must be a valid packet number of a packet sent on this connection. * @@ -2843,8 +2971,8 @@ int cryptpacket_received(const Net_Crypto *c, int crypt_connection_id, uint32_t return -1; } - uint32_t num = num_packets_array(&conn->send_array); - uint32_t num1 = packet_number - conn->send_array.buffer_start; + const uint32_t num = num_packets_array(&conn->send_array); + const uint32_t num1 = packet_number - conn->send_array.buffer_start; if (num >= num1) { return -1; @@ -2853,7 +2981,7 @@ int cryptpacket_received(const Net_Crypto *c, int crypt_connection_id, uint32_t return 0; } -/** Sends a lossy cryptopacket. +/** @brief Sends a lossy cryptopacket. * * return -1 on failure. * return 0 on success. @@ -2878,10 +3006,10 @@ int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t int ret = -1; - if (conn) { + if (conn != nullptr) { pthread_mutex_lock(conn->mutex); - uint32_t buffer_start = conn->recv_array.buffer_start; - uint32_t buffer_end = conn->send_array.buffer_end; + const uint32_t buffer_start = conn->recv_array.buffer_start; + const uint32_t buffer_end = conn->send_array.buffer_end; pthread_mutex_unlock(conn->mutex); ret = send_data_packet_helper(c, crypt_connection_id, buffer_start, buffer_end, data, length); } @@ -2893,7 +3021,7 @@ int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t return ret; } -/** Kill a crypto connection. +/** @brief Kill a crypto connection. * * return -1 on failure. * return 0 on success. @@ -2904,7 +3032,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id) int ret = -1; - if (conn) { + if (conn != nullptr) { if (conn->status == CRYPTO_CONN_ESTABLISHED) { send_kill_packet(c, crypt_connection_id); } @@ -2925,7 +3053,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id) } bool crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected, - unsigned int *online_tcp_relays) + uint32_t *online_tcp_relays) { const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -2933,19 +3061,19 @@ bool crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool return false; } - if (direct_connected) { - *direct_connected = 0; + if (direct_connected != nullptr) { + *direct_connected = false; const uint64_t current_time = mono_time_get(c->mono_time); if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) { - *direct_connected = 1; + *direct_connected = true; } else if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) { - *direct_connected = 1; + *direct_connected = true; } } - if (online_tcp_relays) { + if (online_tcp_relays != nullptr) { *online_tcp_relays = tcp_connection_to_online_tcp_relays(c->tcp_c, conn->connection_number_tcp); } @@ -2954,11 +3082,11 @@ bool crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool void new_keys(Net_Crypto *c) { - crypto_new_keypair(c->self_public_key, c->self_secret_key); + crypto_new_keypair(c->rng, c->self_public_key, c->self_secret_key); } -/** Save the public and private keys to the keys array. - * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE. +/** @brief Save the public and private keys to the keys array. + * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE. * * TODO(irungentoo): Save only secret key. */ @@ -2968,7 +3096,7 @@ void save_keys(const Net_Crypto *c, uint8_t *keys) memcpy(keys + CRYPTO_PUBLIC_KEY_SIZE, c->self_secret_key, CRYPTO_SECRET_KEY_SIZE); } -/** Load the secret key. +/** @brief Load the secret key. * Length must be CRYPTO_SECRET_KEY_SIZE. */ void load_secret_key(Net_Crypto *c, const uint8_t *sk) @@ -2977,10 +3105,10 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk) crypto_derive_public_key(c->self_public_key, c->self_secret_key); } -/** Create new instance of Net_Crypto. - * Sets all the global connection variables to their default values. +/** @brief Create new instance of Net_Crypto. + * Sets all the global connection variables to their default values. */ -Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info) +Net_Crypto *new_net_crypto(const Logger *log, const Random *rng, const Network *ns, Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info) { if (dht == nullptr) { return nullptr; @@ -2993,9 +3121,11 @@ Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, co } temp->log = log; + temp->rng = rng; temp->mono_time = mono_time; + temp->ns = ns; - temp->tcp_c = new_tcp_connections(log, mono_time, dht_get_self_secret_key(dht), proxy_info); + temp->tcp_c = new_tcp_connections(log, rng, ns, mono_time, dht_get_self_secret_key(dht), proxy_info); if (temp->tcp_c == nullptr) { free(temp); @@ -3015,7 +3145,7 @@ Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, co temp->dht = dht; new_keys(temp); - new_symmetric_key(temp->secret_symmetric_key); + new_symmetric_key(rng, temp->secret_symmetric_key); temp->current_sleep_time = CRYPTO_SEND_PACKET_INTERVAL; @@ -3029,6 +3159,7 @@ Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, co return temp; } +non_null(1) nullable(2) static void kill_timedout(Net_Crypto *c, void *userdata) { for (uint32_t i = 0; i < c->crypto_connections_length; ++i) { @@ -3051,15 +3182,14 @@ static void kill_timedout(Net_Crypto *c, void *userdata) if (conn->status == CRYPTO_CONN_ESTABLISHED) { // TODO(irungentoo): add a timeout here? - do_timeout_here(); + /* do_timeout_here(); */ } #endif } } -/** return the optimal interval in ms for running do_net_crypto. - */ +/** return the optimal interval in ms for running do_net_crypto. */ uint32_t crypto_run_interval(const Net_Crypto *c) { return c->current_sleep_time; @@ -3075,6 +3205,10 @@ void do_net_crypto(Net_Crypto *c, void *userdata) void kill_net_crypto(Net_Crypto *c) { + if (c == nullptr) { + return; + } + for (uint32_t i = 0; i < c->crypto_connections_length; ++i) { crypto_kill(c, i); } |