diff --git a/CMakeLists.txt b/CMakeLists.txt index 17ccfd54a8a..9d4816d64c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,6 +198,8 @@ set(toxcore_SOURCES ${toxcore_SOURCES} set(toxcore_SOURCES ${toxcore_SOURCES} toxcore/TCP_client.c toxcore/TCP_client.h + toxcore/TCP_common.c + toxcore/TCP_common.h toxcore/TCP_connection.c toxcore/TCP_connection.h toxcore/TCP_server.c diff --git a/auto_tests/BUILD.bazel b/auto_tests/BUILD.bazel index 0fa6cd9bd7b..dabea2d6b6a 100644 --- a/auto_tests/BUILD.bazel +++ b/auto_tests/BUILD.bazel @@ -39,7 +39,10 @@ flaky_tests = { "//c-toxcore/toxcore", "//c-toxcore/toxcore:DHT_srcs", "//c-toxcore/toxcore:Messenger", + "//c-toxcore/toxcore:TCP_client", + "//c-toxcore/toxcore:TCP_common", "//c-toxcore/toxcore:TCP_connection", + "//c-toxcore/toxcore:TCP_server", "//c-toxcore/toxcore:ccompat", "//c-toxcore/toxcore:crypto_core", "//c-toxcore/toxcore:friend_connection", diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 8e7bdcd3bb7..fa9528d5fda 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -3,6 +3,7 @@ #include "../testing/misc_tools.h" #include "../toxcore/TCP_client.h" +#include "../toxcore/TCP_common.h" #include "../toxcore/TCP_server.h" #include "../toxcore/crypto_core.h" #include "../toxcore/mono_time.h" @@ -241,7 +242,7 @@ static void kill_TCP_con(struct sec_TCP_con *con) free(con); } -static int write_packet_TCP_secure_connection(struct sec_TCP_con *con, uint8_t *data, uint16_t length) +static int write_packet_TCP_test_connection(struct sec_TCP_con *con, uint8_t *data, uint16_t length) { VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); @@ -290,9 +291,9 @@ START_TEST(test_some) // Sending wrong public keys to test server response. memcpy(requ_p + 1, con3->public_key, CRYPTO_PUBLIC_KEY_SIZE); - write_packet_TCP_secure_connection(con1, requ_p, sizeof(requ_p)); + write_packet_TCP_test_connection(con1, requ_p, sizeof(requ_p)); memcpy(requ_p + 1, con1->public_key, CRYPTO_PUBLIC_KEY_SIZE); - write_packet_TCP_secure_connection(con3, requ_p, sizeof(requ_p)); + write_packet_TCP_test_connection(con3, requ_p, sizeof(requ_p)); do_TCP_server_delay(tcp_s, mono_time, 50); @@ -313,9 +314,9 @@ START_TEST(test_some) uint8_t test_packet[512] = {16, 17, 16, 86, 99, 127, 255, 189, 78}; // What is this packet???? - write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet)); - write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet)); - write_packet_TCP_secure_connection(con3, test_packet, sizeof(test_packet)); + write_packet_TCP_test_connection(con3, test_packet, sizeof(test_packet)); + write_packet_TCP_test_connection(con3, test_packet, sizeof(test_packet)); + write_packet_TCP_test_connection(con3, test_packet, sizeof(test_packet)); do_TCP_server_delay(tcp_s, mono_time, 50); @@ -339,9 +340,9 @@ START_TEST(test_some) ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1], data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]); - write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); - write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); - write_packet_TCP_secure_connection(con1, test_packet, sizeof(test_packet)); + write_packet_TCP_test_connection(con1, test_packet, sizeof(test_packet)); + write_packet_TCP_test_connection(con1, test_packet, sizeof(test_packet)); + write_packet_TCP_test_connection(con1, test_packet, sizeof(test_packet)); do_TCP_server_delay(tcp_s, mono_time, 50); len = read_packet_sec_TCP(con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); @@ -357,7 +358,7 @@ START_TEST(test_some) data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]); uint8_t ping_packet[1 + sizeof(uint64_t)] = {TCP_PACKET_PING, 8, 6, 9, 67}; - write_packet_TCP_secure_connection(con1, ping_packet, sizeof(ping_packet)); + write_packet_TCP_test_connection(con1, ping_packet, sizeof(ping_packet)); do_TCP_server_delay(tcp_s, mono_time, 50); diff --git a/other/BUILD.bazel b/other/BUILD.bazel index ebfde2380ef..85b0ebadbf8 100644 --- a/other/BUILD.bazel +++ b/other/BUILD.bazel @@ -18,7 +18,7 @@ cc_binary( "//c-toxcore/testing:misc_tools", "//c-toxcore/toxcore", "//c-toxcore/toxcore:DHT", - "//c-toxcore/toxcore:TCP_connection", + "//c-toxcore/toxcore:TCP_server", "//c-toxcore/toxcore:friend_requests", "//c-toxcore/toxcore:logger", "//c-toxcore/toxcore:mono_time", diff --git a/other/bootstrap_daemon/BUILD.bazel b/other/bootstrap_daemon/BUILD.bazel index 86363ff1e33..06725d8793e 100644 --- a/other/bootstrap_daemon/BUILD.bazel +++ b/other/bootstrap_daemon/BUILD.bazel @@ -12,7 +12,7 @@ cc_binary( "//c-toxcore/other:bootstrap_node_packets", "//c-toxcore/toxcore", "//c-toxcore/toxcore:DHT", - "//c-toxcore/toxcore:TCP_connection", + "//c-toxcore/toxcore:TCP_server", "//c-toxcore/toxcore:ccompat", "//c-toxcore/toxcore:logger", "//c-toxcore/toxcore:mono_time", diff --git a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 index 0e7b640b015..441b85c2655 100644 --- a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 +++ b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 @@ -1 +1 @@ -058c26e86ce3fcdd5d32850f46434e618bec6b122288fbdbc7cf9a9d23ee1d9c /usr/local/bin/tox-bootstrapd +bf2c94623c4d09e19703ed536caf5dd0de7fc7b06620616631cea273dbae5183 /usr/local/bin/tox-bootstrapd diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index d7b3f7ba090..d5b77acfc02 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -253,15 +253,19 @@ cc_library( ) cc_library( - name = "TCP_connection", + name = "TCP_common", + srcs = ["TCP_common.c"], + hdrs = ["TCP_common.h"], + visibility = ["//c-toxcore/auto_tests:__pkg__"], + deps = [":network"], +) + +cc_library( + name = "TCP_server", srcs = [ - "TCP_client.c", - "TCP_connection.c", "TCP_server.c", ], hdrs = [ - "TCP_client.h", - "TCP_connection.h", "TCP_server.h", ], copts = select({ @@ -274,6 +278,36 @@ cc_library( "//c-toxcore/other/bootstrap_daemon:__pkg__", ], deps = [ + ":TCP_common", + ":crypto_core", + ":list", + ":mono_time", + ":network", + ":onion", + ], +) + +cc_library( + name = "TCP_client", + srcs = ["TCP_client.c"], + hdrs = ["TCP_client.h"], + visibility = ["//c-toxcore/auto_tests:__pkg__"], + deps = [ + ":TCP_common", + ":mono_time", + ":network", + ], +) + +cc_library( + name = "TCP_connection", + srcs = ["TCP_connection.c"], + hdrs = ["TCP_connection.h"], + visibility = ["//c-toxcore/auto_tests:__pkg__"], + deps = [ + ":DHT", + ":TCP_client", + ":TCP_common", ":crypto_core", ":list", ":mono_time", @@ -301,6 +335,7 @@ cc_library( deps = [ ":DHT", ":TCP_connection", + ":list", ":mono_time", ":network", ], @@ -386,6 +421,7 @@ cc_library( "//c-toxcore/toxav:__pkg__", ], deps = [ + ":TCP_server", ":friend_requests", ":logger", ":mono_time", diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 30aa177f7e5..4aedb5228b1 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -48,6 +48,8 @@ libtoxcore_la_SOURCES = ../toxcore/ccompat.h \ ../toxcore/onion_client.c \ ../toxcore/TCP_client.h \ ../toxcore/TCP_client.c \ + ../toxcore/TCP_common.h \ + ../toxcore/TCP_common.c \ ../toxcore/TCP_server.h \ ../toxcore/TCP_server.c \ ../toxcore/TCP_connection.h \ diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index bbe1633a2fc..cbb2d46de1d 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -10,6 +10,7 @@ #ifndef C_TOXCORE_TOXCORE_MESSENGER_H #define C_TOXCORE_TOXCORE_MESSENGER_H +#include "TCP_server.h" #include "friend_connection.h" #include "friend_requests.h" #include "logger.h" diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 04584f9d6e1..14b9c0cea84 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -12,6 +12,7 @@ #include #include +#include "TCP_common.h" #include "mono_time.h" #include "util.h" @@ -23,26 +24,17 @@ typedef struct TCP_Client_Conn { } TCP_Client_Conn; struct TCP_Client_Connection { + TCP_Connection con; TCP_Client_Status status; - Socket sock; uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */ IP_Port ip_port; /* The ip and port of the server */ TCP_Proxy_Info proxy_info; uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */ - uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */ - uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; uint16_t next_packet_length; uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE]; - uint8_t last_packet[2 + MAX_PACKET_SIZE]; - uint16_t last_packet_length; - uint16_t last_packet_sent; - - TCP_Priority_List *priority_queue_start; - TCP_Priority_List *priority_queue_end; - uint64_t kill_at; uint64_t last_pinged; @@ -131,15 +123,15 @@ static int proxy_http_generate_connection_request(TCP_Client_Connection *tcp_con } const uint16_t port = net_ntohs(tcp_conn->ip_port.port); - const int written = snprintf((char *)tcp_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two, - ip, port, three); + const int written = snprintf((char *)tcp_conn->con.last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, + two, ip, port, three); if (written < 0 || MAX_PACKET_SIZE < written) { return 0; } - tcp_conn->last_packet_length = written; - tcp_conn->last_packet_sent = 0; + tcp_conn->con.last_packet_length = written; + tcp_conn->con.last_packet_sent = 0; return 1; } @@ -153,7 +145,7 @@ static int proxy_http_read_connection_response(const Logger *logger, TCP_Client_ char success[] = "200"; uint8_t data[16]; // draining works the best if the length is a power of 2 - int ret = read_TCP_packet(logger, tcp_conn->sock, data, sizeof(data) - 1); + int ret = read_TCP_packet(logger, tcp_conn->con.sock, data, sizeof(data) - 1); if (ret == -1) { return 0; @@ -163,11 +155,11 @@ static int proxy_http_read_connection_response(const Logger *logger, TCP_Client_ if (strstr((const char *)data, success)) { // drain all data - unsigned int data_left = net_socket_data_recv_buffer(tcp_conn->sock); + unsigned int data_left = net_socket_data_recv_buffer(tcp_conn->con.sock); if (data_left) { VLA(uint8_t, temp_data, data_left); - read_TCP_packet(logger, tcp_conn->sock, temp_data, data_left); + read_TCP_packet(logger, tcp_conn->con.sock, temp_data, data_left); } return 1; @@ -178,12 +170,12 @@ static int proxy_http_read_connection_response(const Logger *logger, TCP_Client_ static void proxy_socks5_generate_handshake(TCP_Client_Connection *tcp_conn) { - tcp_conn->last_packet[0] = 5; /* SOCKSv5 */ - tcp_conn->last_packet[1] = 1; /* number of authentication methods supported */ - tcp_conn->last_packet[2] = 0; /* No authentication */ + tcp_conn->con.last_packet[0] = 5; /* SOCKSv5 */ + tcp_conn->con.last_packet[1] = 1; /* number of authentication methods supported */ + tcp_conn->con.last_packet[2] = 0; /* No authentication */ - tcp_conn->last_packet_length = 3; - tcp_conn->last_packet_sent = 0; + tcp_conn->con.last_packet_length = 3; + tcp_conn->con.last_packet_sent = 0; } /** return 1 on success. @@ -193,7 +185,7 @@ static void proxy_socks5_generate_handshake(TCP_Client_Connection *tcp_conn) static int socks5_read_handshake_response(const Logger *logger, TCP_Client_Connection *tcp_conn) { uint8_t data[2]; - int ret = read_TCP_packet(logger, tcp_conn->sock, data, sizeof(data)); + int ret = read_TCP_packet(logger, tcp_conn->con.sock, data, sizeof(data)); if (ret == -1) { return 0; @@ -208,28 +200,28 @@ static int socks5_read_handshake_response(const Logger *logger, TCP_Client_Conne static void proxy_socks5_generate_connection_request(TCP_Client_Connection *tcp_conn) { - tcp_conn->last_packet[0] = 5; /* SOCKSv5 */ - tcp_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */ - tcp_conn->last_packet[2] = 0; /* reserved, must be 0 */ + tcp_conn->con.last_packet[0] = 5; /* SOCKSv5 */ + tcp_conn->con.last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */ + tcp_conn->con.last_packet[2] = 0; /* reserved, must be 0 */ uint16_t length = 3; if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) { - tcp_conn->last_packet[3] = 1; /* IPv4 address */ + tcp_conn->con.last_packet[3] = 1; /* IPv4 address */ ++length; - memcpy(tcp_conn->last_packet + length, tcp_conn->ip_port.ip.ip.v4.uint8, sizeof(IP4)); + memcpy(tcp_conn->con.last_packet + length, tcp_conn->ip_port.ip.ip.v4.uint8, sizeof(IP4)); length += sizeof(IP4); } else { - tcp_conn->last_packet[3] = 4; /* IPv6 address */ + tcp_conn->con.last_packet[3] = 4; /* IPv6 address */ ++length; - memcpy(tcp_conn->last_packet + length, tcp_conn->ip_port.ip.ip.v6.uint8, sizeof(IP6)); + memcpy(tcp_conn->con.last_packet + length, tcp_conn->ip_port.ip.ip.v6.uint8, sizeof(IP6)); length += sizeof(IP6); } - memcpy(tcp_conn->last_packet + length, &tcp_conn->ip_port.port, sizeof(uint16_t)); + memcpy(tcp_conn->con.last_packet + length, &tcp_conn->ip_port.port, sizeof(uint16_t)); length += sizeof(uint16_t); - tcp_conn->last_packet_length = length; - tcp_conn->last_packet_sent = 0; + tcp_conn->con.last_packet_length = length; + tcp_conn->con.last_packet_sent = 0; } /** return 1 on success. @@ -240,7 +232,7 @@ static int proxy_socks5_read_connection_response(const Logger *logger, TCP_Clien { if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) { uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)]; - int ret = read_TCP_packet(logger, tcp_conn->sock, data, sizeof(data)); + int ret = read_TCP_packet(logger, tcp_conn->con.sock, data, sizeof(data)); if (ret == -1) { return 0; @@ -251,7 +243,7 @@ static int proxy_socks5_read_connection_response(const Logger *logger, TCP_Clien } } else { uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)]; - int ret = read_TCP_packet(logger, tcp_conn->sock, data, sizeof(data)); + int ret = read_TCP_packet(logger, tcp_conn->con.sock, data, sizeof(data)); if (ret == -1) { return 0; @@ -272,19 +264,19 @@ static int generate_handshake(TCP_Client_Connection *tcp_conn) { uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE]; crypto_new_keypair(plain, tcp_conn->temp_secret_key); - random_nonce(tcp_conn->sent_nonce); - memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->sent_nonce, CRYPTO_NONCE_SIZE); - memcpy(tcp_conn->last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE); - random_nonce(tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE); - int len = encrypt_data_symmetric(tcp_conn->shared_key, tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain, - sizeof(plain), tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); + random_nonce(tcp_conn->con.sent_nonce); + memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->con.sent_nonce, CRYPTO_NONCE_SIZE); + memcpy(tcp_conn->con.last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE); + random_nonce(tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE); + int len = encrypt_data_symmetric(tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain, + sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); if (len != sizeof(plain) + CRYPTO_MAC_SIZE) { return -1; } - tcp_conn->last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE; - tcp_conn->last_packet_sent = 0; + tcp_conn->con.last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE; + tcp_conn->con.last_packet_sent = 0; return 0; } @@ -296,7 +288,7 @@ static int generate_handshake(TCP_Client_Connection *tcp_conn) static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data) { uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE]; - int len = decrypt_data_symmetric(tcp_conn->shared_key, data, data + CRYPTO_NONCE_SIZE, + int len = decrypt_data_symmetric(tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE, TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain); if (len != sizeof(plain)) { @@ -304,168 +296,11 @@ static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data } memcpy(tcp_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE); - encrypt_precompute(plain, tcp_conn->temp_secret_key, tcp_conn->shared_key); + encrypt_precompute(plain, tcp_conn->temp_secret_key, tcp_conn->con.shared_key); crypto_memzero(tcp_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE); return 0; } -/** return 0 if pending data was sent completely - * return -1 if it wasn't - */ -static int client_send_pending_data_nonpriority(TCP_Client_Connection *con) -{ - if (con->last_packet_length == 0) { - return 0; - } - - const uint16_t left = con->last_packet_length - con->last_packet_sent; - const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left); - - if (len <= 0) { - return -1; - } - - if (len == left) { - con->last_packet_length = 0; - con->last_packet_sent = 0; - return 0; - } - - con->last_packet_sent += len; - return -1; -} - -/** return 0 if pending data was sent completely - * return -1 if it wasn't - */ -static int client_send_pending_data(TCP_Client_Connection *con) -{ - /* finish sending current non-priority packet */ - if (client_send_pending_data_nonpriority(con) == -1) { - return -1; - } - - TCP_Priority_List *p = con->priority_queue_start; - - while (p) { - const uint16_t left = p->size - p->sent; - const int len = net_send(con->sock, p->data + p->sent, left); - - if (len != left) { - if (len > 0) { - p->sent += len; - } - - break; - } - - TCP_Priority_List *pp = p; - p = p->next; - free(pp); - } - - con->priority_queue_start = p; - - if (!p) { - con->priority_queue_end = nullptr; - return 0; - } - - return -1; -} - -/** return 0 on failure (only if calloc fails) - * return 1 on success - */ -static bool client_add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) -{ - TCP_Priority_List *p = con->priority_queue_end; - TCP_Priority_List *new_list = (TCP_Priority_List *)calloc(1, sizeof(TCP_Priority_List) + size); - - if (!new_list) { - return 0; - } - - new_list->next = nullptr; - new_list->size = size; - new_list->sent = sent; - memcpy(new_list->data, packet, size); - - if (p) { - p->next = new_list; - } else { - con->priority_queue_start = new_list; - } - - con->priority_queue_end = new_list; - return 1; -} - -/** return 1 on success. - * return 0 if could not send packet. - * return -1 on failure (connection must be killed). - */ -static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length, - bool priority) -{ - if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { - return -1; - } - - bool sendpriority = 1; - - if (client_send_pending_data(con) == -1) { - if (priority) { - sendpriority = 0; - } else { - return 0; - } - } - - VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); - - uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); - memcpy(packet, &c_length, sizeof(uint16_t)); - int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); - - if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { - return -1; - } - - if (priority) { - len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0; - - if (len <= 0) { - len = 0; - } - - increment_nonce(con->sent_nonce); - - if ((unsigned int)len == SIZEOF_VLA(packet)) { - return 1; - } - - return client_add_priority(con, packet, SIZEOF_VLA(packet), len); - } - - len = net_send(con->sock, packet, SIZEOF_VLA(packet)); - - if (len <= 0) { - return 0; - } - - increment_nonce(con->sent_nonce); - - if ((unsigned int)len == SIZEOF_VLA(packet)) { - return 1; - } - - memcpy(con->last_packet, packet, SIZEOF_VLA(packet)); - con->last_packet_length = SIZEOF_VLA(packet); - con->last_packet_sent = len; - return 1; -} - /** return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). @@ -475,7 +310,7 @@ int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) uint8_t packet[1 + CRYPTO_PUBLIC_KEY_SIZE]; packet[0] = TCP_PACKET_ROUTING_REQUEST; memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE); - return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); + return write_packet_TCP_secure_connection(&con->con, packet, sizeof(packet), 1); } void routing_response_handler(TCP_Client_Connection *con, tcp_routing_response_cb *response_callback, void *object) @@ -514,7 +349,7 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, u VLA(uint8_t, packet, 1 + length); packet[0] = con_id + NUM_RESERVED_PORTS; memcpy(packet + 1, data, length); - return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); + return write_packet_TCP_secure_connection(&con->con, packet, SIZEOF_VLA(packet), 0); } /** return 1 on success. @@ -531,7 +366,7 @@ int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const packet[0] = TCP_PACKET_OOB_SEND; memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length); - return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); + return write_packet_TCP_secure_connection(&con->con, packet, SIZEOF_VLA(packet), 0); } @@ -577,7 +412,7 @@ static int client_send_disconnect_notification(TCP_Client_Connection *con, uint8 uint8_t packet[1 + 1]; packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; packet[1] = id; - return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); + return write_packet_TCP_secure_connection(&con->con, packet, sizeof(packet), 1); } /** return 1 on success. @@ -593,7 +428,7 @@ static int tcp_send_ping_request(TCP_Client_Connection *con) uint8_t packet[1 + sizeof(uint64_t)]; packet[0] = TCP_PACKET_PING; memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t)); - const int ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); + const int ret = write_packet_TCP_secure_connection(&con->con, packet, sizeof(packet), 1); if (ret == 1) { con->ping_request_id = 0; @@ -615,7 +450,7 @@ static int tcp_send_ping_response(TCP_Client_Connection *con) uint8_t packet[1 + sizeof(uint64_t)]; packet[0] = TCP_PACKET_PONG; memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t)); - const int ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); + const int ret = write_packet_TCP_secure_connection(&con->con, packet, sizeof(packet), 1); if (ret == 1) { con->ping_response_id = 0; @@ -648,7 +483,7 @@ int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t VLA(uint8_t, packet, 1 + length); packet[0] = TCP_PACKET_ONION_REQUEST; memcpy(packet + 1, data, length); - return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); + return write_packet_TCP_secure_connection(&con->con, packet, SIZEOF_VLA(packet), 0); } void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *onion_callback, void *object) @@ -705,10 +540,10 @@ TCP_Client_Connection *new_TCP_connection(const Mono_Time *mono_time, IP_Port ip return nullptr; } - temp->sock = sock; + temp->con.sock = sock; memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE); - encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key); + encrypt_precompute(temp->public_key, self_secret_key, temp->con.shared_key); temp->ip_port = ip_port; temp->proxy_info = *proxy_info; @@ -902,8 +737,8 @@ static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t * static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn, void *userdata) { uint8_t packet[MAX_PACKET_SIZE]; - const int len = read_packet_TCP_secure_connection(logger, conn->sock, &conn->next_packet_length, conn->shared_key, - conn->recv_nonce, packet, sizeof(packet)); + const int len = read_packet_TCP_secure_connection(logger, conn->con.sock, &conn->next_packet_length, + conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet)); if (len == 0) { return false; @@ -925,7 +760,7 @@ static bool tcp_process_packet(const Logger *logger, TCP_Client_Connection *conn static int do_confirmed_TCP(const Logger *logger, TCP_Client_Connection *conn, const Mono_Time *mono_time, void *userdata) { - client_send_pending_data(conn); + send_pending_data(&conn->con); tcp_send_ping_response(conn); tcp_send_ping_request(conn); @@ -965,7 +800,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co } if (tcp_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) { - if (client_send_pending_data(tcp_connection) == 0) { + if (send_pending_data(&tcp_connection->con) == 0) { int ret = proxy_http_read_connection_response(logger, tcp_connection); if (ret == -1) { @@ -981,7 +816,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co } if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) { - if (client_send_pending_data(tcp_connection) == 0) { + if (send_pending_data(&tcp_connection->con) == 0) { int ret = socks5_read_handshake_response(logger, tcp_connection); if (ret == -1) { @@ -997,7 +832,7 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co } if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) { - if (client_send_pending_data(tcp_connection) == 0) { + if (send_pending_data(&tcp_connection->con) == 0) { int ret = proxy_socks5_read_connection_response(logger, tcp_connection); if (ret == -1) { @@ -1013,14 +848,14 @@ void do_TCP_connection(const Logger *logger, Mono_Time *mono_time, TCP_Client_Co } if (tcp_connection->status == TCP_CLIENT_CONNECTING) { - if (client_send_pending_data(tcp_connection) == 0) { + if (send_pending_data(&tcp_connection->con) == 0) { tcp_connection->status = TCP_CLIENT_UNCONFIRMED; } } if (tcp_connection->status == TCP_CLIENT_UNCONFIRMED) { uint8_t data[TCP_SERVER_HANDSHAKE_SIZE]; - int len = read_TCP_packet(logger, tcp_connection->sock, data, sizeof(data)); + int len = read_TCP_packet(logger, tcp_connection->con.sock, data, sizeof(data)); if (sizeof(data) == len) { if (handle_handshake(tcp_connection, data) == 0) { @@ -1050,8 +885,8 @@ void kill_TCP_connection(TCP_Client_Connection *tcp_connection) return; } - wipe_priority_list(tcp_connection->priority_queue_start); - kill_sock(tcp_connection->sock); + wipe_priority_list(tcp_connection->con.priority_queue_start); + kill_sock(tcp_connection->con.sock); crypto_memzero(tcp_connection, sizeof(TCP_Client_Connection)); free(tcp_connection); } diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index fed8b637380..e73d572a235 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -9,8 +9,8 @@ #ifndef C_TOXCORE_TOXCORE_TCP_CLIENT_H #define C_TOXCORE_TOXCORE_TCP_CLIENT_H -#include "TCP_server.h" -#include "crypto_core.h" +#include "mono_time.h" +#include "network.h" #define TCP_CONNECTION_TIMEOUT 10 diff --git a/toxcore/TCP_common.c b/toxcore/TCP_common.c new file mode 100644 index 00000000000..037974e018e --- /dev/null +++ b/toxcore/TCP_common.c @@ -0,0 +1,274 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2018 The TokTok team. + * Copyright © 2014 Tox project. + */ + +#include "TCP_common.h" + +#include +#include + +void wipe_priority_list(TCP_Priority_List *p) +{ + while (p) { + TCP_Priority_List *pp = p; + p = p->next; + free(pp); + } +} + +/** return 0 if pending data was sent completely + * return -1 if it wasn't + */ +int send_pending_data_nonpriority(TCP_Connection *con) +{ + if (con->last_packet_length == 0) { + return 0; + } + + const uint16_t left = con->last_packet_length - con->last_packet_sent; + const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left); + + if (len <= 0) { + return -1; + } + + if (len == left) { + con->last_packet_length = 0; + con->last_packet_sent = 0; + return 0; + } + + con->last_packet_sent += len; + return -1; +} + +/** return 0 if pending data was sent completely + * return -1 if it wasn't + */ +int send_pending_data(TCP_Connection *con) +{ + /* finish sending current non-priority packet */ + if (send_pending_data_nonpriority(con) == -1) { + return -1; + } + + TCP_Priority_List *p = con->priority_queue_start; + + while (p) { + const uint16_t left = p->size - p->sent; + const int len = net_send(con->sock, p->data + p->sent, left); + + if (len != left) { + if (len > 0) { + p->sent += len; + } + + break; + } + + TCP_Priority_List *pp = p; + p = p->next; + free(pp); + } + + con->priority_queue_start = p; + + if (!p) { + con->priority_queue_end = nullptr; + return 0; + } + + return -1; +} + +/** return 0 on failure (only if calloc fails) + * return 1 on success + */ +bool add_priority(TCP_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) +{ + TCP_Priority_List *p = con->priority_queue_end; + TCP_Priority_List *new_list = (TCP_Priority_List *)calloc(1, sizeof(TCP_Priority_List) + size); + + if (!new_list) { + return 0; + } + + new_list->next = nullptr; + new_list->size = size; + new_list->sent = sent; + memcpy(new_list->data, packet, size); + + if (p) { + p->next = new_list; + } else { + con->priority_queue_start = new_list; + } + + con->priority_queue_end = new_list; + return 1; +} + +/** return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +int write_packet_TCP_secure_connection(TCP_Connection *con, const uint8_t *data, uint16_t length, bool priority) +{ + if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { + return -1; + } + + bool sendpriority = 1; + + if (send_pending_data(con) == -1) { + if (priority) { + sendpriority = 0; + } else { + return 0; + } + } + + VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); + + uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); + memcpy(packet, &c_length, sizeof(uint16_t)); + int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + + if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { + return -1; + } + + if (priority) { + len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0; + + if (len <= 0) { + len = 0; + } + + increment_nonce(con->sent_nonce); + + if ((unsigned int)len == SIZEOF_VLA(packet)) { + return 1; + } + + return add_priority(con, packet, SIZEOF_VLA(packet), len); + } + + len = net_send(con->sock, packet, SIZEOF_VLA(packet)); + + if (len <= 0) { + return 0; + } + + increment_nonce(con->sent_nonce); + + if ((unsigned int)len == SIZEOF_VLA(packet)) { + return 1; + } + + memcpy(con->last_packet, packet, SIZEOF_VLA(packet)); + con->last_packet_length = SIZEOF_VLA(packet); + con->last_packet_sent = len; + return 1; +} + +/** Read length bytes from socket. + * + * return length on success + * return -1 on failure/no data in buffer. + */ +int read_TCP_packet(const Logger *logger, Socket sock, uint8_t *data, uint16_t length) +{ + unsigned int count = net_socket_data_recv_buffer(sock); + + if (count >= length) { + const int len = net_recv(sock, data, length); + + if (len != length) { + LOGGER_ERROR(logger, "FAIL recv packet"); + return -1; + } + + return len; + } + + return -1; +} + +/** Read the next two bytes in TCP stream then convert them to + * length (host byte order). + * + * return length on success + * return 0 if nothing has been read from socket. + * return -1 on failure. + */ +static uint16_t read_TCP_length(const Logger *logger, Socket sock) +{ + const unsigned int count = net_socket_data_recv_buffer(sock); + + if (count >= sizeof(uint16_t)) { + uint16_t length; + const int len = net_recv(sock, &length, sizeof(uint16_t)); + + if (len != sizeof(uint16_t)) { + LOGGER_ERROR(logger, "FAIL recv packet"); + return 0; + } + + length = net_ntohs(length); + + if (length > MAX_PACKET_SIZE) { + return -1; + } + + return length; + } + + return 0; +} + +/** return length of received packet on success. + * return 0 if could not read any packet. + * return -1 on failure (connection must be killed). + */ +int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_t *next_packet_length, + const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) +{ + if (*next_packet_length == 0) { + uint16_t len = read_TCP_length(logger, sock); + + if (len == (uint16_t) -1) { + return -1; + } + + if (len == 0) { + return 0; + } + + *next_packet_length = len; + } + + if (max_len + CRYPTO_MAC_SIZE < *next_packet_length) { + return -1; + } + + VLA(uint8_t, data_encrypted, *next_packet_length); + int len_packet = read_TCP_packet(logger, sock, data_encrypted, *next_packet_length); + + if (len_packet != *next_packet_length) { + return 0; + } + + *next_packet_length = 0; + + int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); + + if (len + CRYPTO_MAC_SIZE != len_packet) { + return -1; + } + + increment_nonce(recv_nonce); + + return len; +} diff --git a/toxcore/TCP_common.h b/toxcore/TCP_common.h new file mode 100644 index 00000000000..f6273df4a29 --- /dev/null +++ b/toxcore/TCP_common.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2018 The TokTok team. + * Copyright © 2014 Tox project. + */ + +#ifndef C_TOXCORE_TOXCORE_TCP_COMMON_H +#define C_TOXCORE_TOXCORE_TCP_COMMON_H + +#include "crypto_core.h" +#include "network.h" + +typedef struct TCP_Priority_List TCP_Priority_List; +struct TCP_Priority_List { + TCP_Priority_List *next; + uint16_t size; + uint16_t sent; + uint8_t data[]; +}; + +void wipe_priority_list(TCP_Priority_List *p); + +#define NUM_RESERVED_PORTS 16 +#define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS) + +#define TCP_PACKET_ROUTING_REQUEST 0 +#define TCP_PACKET_ROUTING_RESPONSE 1 +#define TCP_PACKET_CONNECTION_NOTIFICATION 2 +#define TCP_PACKET_DISCONNECT_NOTIFICATION 3 +#define TCP_PACKET_PING 4 +#define TCP_PACKET_PONG 5 +#define TCP_PACKET_OOB_SEND 6 +#define TCP_PACKET_OOB_RECV 7 +#define TCP_PACKET_ONION_REQUEST 8 +#define TCP_PACKET_ONION_RESPONSE 9 + +#define TCP_HANDSHAKE_PLAIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE) +#define TCP_SERVER_HANDSHAKE_SIZE (CRYPTO_NONCE_SIZE + TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) +#define TCP_CLIENT_HANDSHAKE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + TCP_SERVER_HANDSHAKE_SIZE) +#define TCP_MAX_OOB_DATA_LENGTH 1024 + +/* frequency to ping connected nodes and timeout in seconds */ +#define TCP_PING_FREQUENCY 30 +#define TCP_PING_TIMEOUT 10 + +#define MAX_PACKET_SIZE 2048 + +typedef struct TCP_Connection { + Socket sock; + uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */ + uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; + uint8_t last_packet[2 + MAX_PACKET_SIZE]; + uint16_t last_packet_length; + uint16_t last_packet_sent; + + TCP_Priority_List *priority_queue_start; + TCP_Priority_List *priority_queue_end; +} TCP_Connection; + +/** return 0 if pending data was sent completely + * return -1 if it wasn't + */ +int send_pending_data_nonpriority(TCP_Connection *con); + +/** return 0 if pending data was sent completely + * return -1 if it wasn't + */ +int send_pending_data(TCP_Connection *con); + +/** return 0 on failure (only if calloc fails) + * return 1 on success + */ +bool add_priority(TCP_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent); + +/** return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +int write_packet_TCP_secure_connection(TCP_Connection *con, const uint8_t *data, uint16_t length, bool priority); + +/** Read length bytes from socket. + * + * return length on success + * return -1 on failure/no data in buffer. + */ +int read_TCP_packet(const Logger *logger, Socket sock, uint8_t *data, uint16_t length); + +/** return length of received packet on success. + * return 0 if could not read any packet. + * return -1 on failure (connection must be killed). + */ +int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_t *next_packet_length, + const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len); + +#endif diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h index d27b3e941db..b31260eaf48 100644 --- a/toxcore/TCP_connection.h +++ b/toxcore/TCP_connection.h @@ -9,8 +9,11 @@ #ifndef C_TOXCORE_TOXCORE_TCP_CONNECTION_H #define C_TOXCORE_TOXCORE_TCP_CONNECTION_H -#include +#include "DHT.h" // for Node_format #include "TCP_client.h" +#include "TCP_common.h" + +#include #define TCP_CONN_NONE 0 #define TCP_CONN_VALID 1 diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 9b56e6ea387..a0bdd384501 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -19,6 +19,8 @@ #include #endif +#include "TCP_common.h" +#include "list.h" #include "mono_time.h" #include "util.h" @@ -38,20 +40,13 @@ typedef struct TCP_Secure_Conn { } TCP_Secure_Conn; typedef struct TCP_Secure_Connection { - Socket sock; + TCP_Connection con; + uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */ - uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */ - uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; uint16_t next_packet_length; TCP_Secure_Conn connections[NUM_CLIENT_CONNECTIONS]; - uint8_t last_packet[2 + MAX_PACKET_SIZE]; uint8_t status; - uint16_t last_packet_length; - uint16_t last_packet_sent; - - TCP_Priority_List *priority_queue_start; - TCP_Priority_List *priority_queue_end; uint64_t identifier; @@ -135,19 +130,10 @@ static int alloc_new_connections(TCP_Server *tcp_server, uint32_t num) return 0; } -void wipe_priority_list(TCP_Priority_List *p) -{ - while (p) { - TCP_Priority_List *pp = p; - p = p->next; - free(pp); - } -} - static void wipe_secure_connection(TCP_Secure_Connection *con) { if (con->status) { - wipe_priority_list(con->priority_queue_start); + wipe_priority_list(con->con.priority_queue_start); crypto_memzero(con, sizeof(TCP_Secure_Connection)); } } @@ -264,268 +250,11 @@ static int del_accepted(TCP_Server *tcp_server, int index) return 0; } -/** Read the next two bytes in TCP stream then convert them to - * length (host byte order). - * - * return length on success - * return 0 if nothing has been read from socket. - * return -1 on failure. - */ -uint16_t read_TCP_length(const Logger *logger, Socket sock) -{ - const unsigned int count = net_socket_data_recv_buffer(sock); - - if (count >= sizeof(uint16_t)) { - uint16_t length; - const int len = net_recv(sock, &length, sizeof(uint16_t)); - - if (len != sizeof(uint16_t)) { - LOGGER_ERROR(logger, "FAIL recv packet"); - return 0; - } - - length = net_ntohs(length); - - if (length > MAX_PACKET_SIZE) { - return -1; - } - - return length; - } - - return 0; -} - -/** Read length bytes from socket. - * - * return length on success - * return -1 on failure/no data in buffer. - */ -int read_TCP_packet(const Logger *logger, Socket sock, uint8_t *data, uint16_t length) -{ - unsigned int count = net_socket_data_recv_buffer(sock); - - if (count >= length) { - const int len = net_recv(sock, data, length); - - if (len != length) { - LOGGER_ERROR(logger, "FAIL recv packet"); - return -1; - } - - return len; - } - - return -1; -} - -/** return length of received packet on success. - * return 0 if could not read any packet. - * return -1 on failure (connection must be killed). - */ -int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_t *next_packet_length, - const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) -{ - if (*next_packet_length == 0) { - uint16_t len = read_TCP_length(logger, sock); - - if (len == (uint16_t) -1) { - return -1; - } - - if (len == 0) { - return 0; - } - - *next_packet_length = len; - } - - if (max_len + CRYPTO_MAC_SIZE < *next_packet_length) { - return -1; - } - - VLA(uint8_t, data_encrypted, *next_packet_length); - int len_packet = read_TCP_packet(logger, sock, data_encrypted, *next_packet_length); - - if (len_packet != *next_packet_length) { - return 0; - } - - *next_packet_length = 0; - - int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); - - if (len + CRYPTO_MAC_SIZE != len_packet) { - return -1; - } - - increment_nonce(recv_nonce); - - return len; -} - -/** return 0 if pending data was sent completely - * return -1 if it wasn't - */ -static int send_pending_data_nonpriority(TCP_Secure_Connection *con) -{ - if (con->last_packet_length == 0) { - return 0; - } - - const uint16_t left = con->last_packet_length - con->last_packet_sent; - const int len = net_send(con->sock, con->last_packet + con->last_packet_sent, left); - - if (len <= 0) { - return -1; - } - - if (len == left) { - con->last_packet_length = 0; - con->last_packet_sent = 0; - return 0; - } - - con->last_packet_sent += len; - return -1; -} - -/** return 0 if pending data was sent completely - * return -1 if it wasn't - */ -static int send_pending_data(TCP_Secure_Connection *con) -{ - /* finish sending current non-priority packet */ - if (send_pending_data_nonpriority(con) == -1) { - return -1; - } - - TCP_Priority_List *p = con->priority_queue_start; - - while (p) { - const uint16_t left = p->size - p->sent; - const int len = net_send(con->sock, p->data + p->sent, left); - - if (len != left) { - if (len > 0) { - p->sent += len; - } - - break; - } - - TCP_Priority_List *pp = p; - p = p->next; - free(pp); - } - - con->priority_queue_start = p; - - if (!p) { - con->priority_queue_end = nullptr; - return 0; - } - - return -1; -} - -/** return 0 on failure (only if calloc fails) - * return 1 on success - */ -static bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) -{ - TCP_Priority_List *p = con->priority_queue_end; - TCP_Priority_List *new_list = (TCP_Priority_List *)calloc(1, sizeof(TCP_Priority_List) + size); - - if (!new_list) { - return 0; - } - - new_list->next = nullptr; - new_list->size = size; - new_list->sent = sent; - memcpy(new_list->data, packet, size); - - if (p) { - p->next = new_list; - } else { - con->priority_queue_start = new_list; - } - - con->priority_queue_end = new_list; - return 1; -} - -/** return 1 on success. - * return 0 if could not send packet. - * return -1 on failure (connection must be killed). - */ -static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, - bool priority) -{ - if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) { - return -1; - } - - bool sendpriority = 1; - - if (send_pending_data(con) == -1) { - if (priority) { - sendpriority = 0; - } else { - return 0; - } - } - - VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); - - const uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); - memcpy(packet, &c_length, sizeof(uint16_t)); - int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); - - if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { - return -1; - } - - if (priority) { - len = sendpriority ? net_send(con->sock, packet, SIZEOF_VLA(packet)) : 0; - - if (len <= 0) { - len = 0; - } - - increment_nonce(con->sent_nonce); - - if ((unsigned int)len == SIZEOF_VLA(packet)) { - return 1; - } - - return add_priority(con, packet, SIZEOF_VLA(packet), len); - } - - len = net_send(con->sock, packet, SIZEOF_VLA(packet)); - - if (len <= 0) { - return 0; - } - - increment_nonce(con->sent_nonce); - - if ((unsigned int)len == SIZEOF_VLA(packet)) { - return 1; - } - - memcpy(con->last_packet, packet, SIZEOF_VLA(packet)); - con->last_packet_length = SIZEOF_VLA(packet); - con->last_packet_sent = len; - return 1; -} - /** Kill a TCP_Secure_Connection */ static void kill_TCP_secure_connection(TCP_Secure_Connection *con) { - kill_sock(con->sock); + kill_sock(con->con.sock); wipe_secure_connection(con); } @@ -546,7 +275,7 @@ static int kill_accepted(TCP_Server *tcp_server, int index) rm_connection_index(tcp_server, &tcp_server->accepted_connection_array[index], i); } - Socket sock = tcp_server->accepted_connection_array[index].sock; + Socket sock = tcp_server->accepted_connection_array[index].con.sock; if (del_accepted(tcp_server, index) != 0) { return -1; @@ -585,8 +314,8 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE]; uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE]; crypto_new_keypair(resp_plain, temp_secret_key); - random_nonce(con->sent_nonce); - memcpy(resp_plain + CRYPTO_PUBLIC_KEY_SIZE, con->sent_nonce, CRYPTO_NONCE_SIZE); + random_nonce(con->con.sent_nonce); + memcpy(resp_plain + CRYPTO_PUBLIC_KEY_SIZE, con->con.sent_nonce, CRYPTO_NONCE_SIZE); memcpy(con->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE); uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; @@ -600,12 +329,12 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, return -1; } - if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE)) { + if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE)) { crypto_memzero(shared_key, sizeof(shared_key)); return -1; } - encrypt_precompute(plain, temp_secret_key, con->shared_key); + encrypt_precompute(plain, temp_secret_key, con->con.shared_key); con->status = TCP_STATUS_UNCONFIRMED; crypto_memzero(shared_key, sizeof(shared_key)); @@ -620,7 +349,7 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, static int read_connection_handshake(const Logger *logger, TCP_Secure_Connection *con, const uint8_t *self_secret_key) { uint8_t data[TCP_CLIENT_HANDSHAKE_SIZE]; - const int len = read_TCP_packet(logger, con->sock, data, TCP_CLIENT_HANDSHAKE_SIZE); + const int len = read_TCP_packet(logger, con->con.sock, data, TCP_CLIENT_HANDSHAKE_SIZE); if (len != -1) { return handle_TCP_handshake(con, data, len, self_secret_key); @@ -640,7 +369,7 @@ static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const data[1] = rpid; memcpy(data + 2, public_key, CRYPTO_PUBLIC_KEY_SIZE); - return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); + return write_packet_TCP_secure_connection(&con->con, data, sizeof(data), 1); } /** return 1 on success. @@ -650,7 +379,7 @@ static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) { uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)}; - return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); + return write_packet_TCP_secure_connection(&con->con, data, sizeof(data), 1); } /** return 1 on success. @@ -660,7 +389,7 @@ static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id) { uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)}; - return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); + return write_packet_TCP_secure_connection(&con->con, data, sizeof(data), 1); } /** return 0 on success. @@ -763,7 +492,7 @@ static int handle_TCP_oob_send(TCP_Server *tcp_server, uint32_t con_id, const ui resp_packet[0] = TCP_PACKET_OOB_RECV; memcpy(resp_packet + 1, con->public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(resp_packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length); - write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[other_index], resp_packet, + write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[other_index].con, resp_packet, SIZEOF_VLA(resp_packet), 0); } @@ -825,7 +554,7 @@ static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, memcpy(packet + 1, data, length); packet[0] = TCP_PACKET_ONION_RESPONSE; - if (write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0) != 1) { + if (write_packet_TCP_secure_connection(&con->con, packet, SIZEOF_VLA(packet), 0) != 1) { return 1; } @@ -876,7 +605,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint uint8_t response[1 + sizeof(uint64_t)]; response[0] = TCP_PACKET_PONG; memcpy(response + 1, data + 1, sizeof(uint64_t)); - write_packet_TCP_secure_connection(con, response, sizeof(response), 1); + write_packet_TCP_secure_connection(&con->con, response, sizeof(response), 1); return 0; } @@ -955,7 +684,7 @@ static int handle_TCP_packet(TCP_Server *tcp_server, uint32_t con_id, const uint VLA(uint8_t, new_data, length); memcpy(new_data, data, length); new_data[0] = other_c_id; - int ret = write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[index], new_data, length, 0); + int ret = write_packet_TCP_secure_connection(&tcp_server->accepted_connection_array[index].con, new_data, length, 0); if (ret == -1) { return -1; @@ -1018,7 +747,7 @@ static int accept_connection(TCP_Server *tcp_server, Socket sock) } conn->status = TCP_STATUS_CONNECTED; - conn->sock = sock; + conn->con.sock = sock; conn->next_packet_length = 0; ++tcp_server->incoming_connection_queue_index; @@ -1183,8 +912,8 @@ static int do_unconfirmed(TCP_Server *tcp_server, const Mono_Time *mono_time, ui } uint8_t packet[MAX_PACKET_SIZE]; - int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->sock, &conn->next_packet_length, conn->shared_key, - conn->recv_nonce, packet, sizeof(packet)); + int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->con.sock, &conn->next_packet_length, + conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet)); if (len == 0) { return -1; @@ -1203,8 +932,8 @@ static bool tcp_process_secure_packet(TCP_Server *tcp_server, uint32_t i) TCP_Secure_Connection *const conn = &tcp_server->accepted_connection_array[i]; uint8_t packet[MAX_PACKET_SIZE]; - int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->sock, &conn->next_packet_length, conn->shared_key, - conn->recv_nonce, packet, sizeof(packet)); + int len = read_packet_TCP_secure_connection(tcp_server->logger, conn->con.sock, &conn->next_packet_length, + conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet)); if (len == 0) { return false; @@ -1275,7 +1004,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time) } memcpy(ping + 1, &ping_id, sizeof(uint64_t)); - int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); + int ret = write_packet_TCP_secure_connection(&conn->con, ping, sizeof(ping), 1); if (ret == 1) { conn->last_pinged = mono_time_get(mono_time); @@ -1293,7 +1022,7 @@ static void do_TCP_confirmed(TCP_Server *tcp_server, const Mono_Time *mono_time) continue; } - send_pending_data(conn); + send_pending_data(&conn->con); #ifndef TCP_SERVER_USE_EPOLL diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index b9e4a671aac..300b2887eef 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -10,40 +10,14 @@ #define C_TOXCORE_TOXCORE_TCP_SERVER_H #include "crypto_core.h" -#include "list.h" #include "onion.h" #define MAX_INCOMING_CONNECTIONS 256 #define TCP_MAX_BACKLOG MAX_INCOMING_CONNECTIONS -#define MAX_PACKET_SIZE 2048 - -#define TCP_HANDSHAKE_PLAIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE) -#define TCP_SERVER_HANDSHAKE_SIZE (CRYPTO_NONCE_SIZE + TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) -#define TCP_CLIENT_HANDSHAKE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + TCP_SERVER_HANDSHAKE_SIZE) -#define TCP_MAX_OOB_DATA_LENGTH 1024 - -#define NUM_RESERVED_PORTS 16 -#define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS) - -#define TCP_PACKET_ROUTING_REQUEST 0 -#define TCP_PACKET_ROUTING_RESPONSE 1 -#define TCP_PACKET_CONNECTION_NOTIFICATION 2 -#define TCP_PACKET_DISCONNECT_NOTIFICATION 3 -#define TCP_PACKET_PING 4 -#define TCP_PACKET_PONG 5 -#define TCP_PACKET_OOB_SEND 6 -#define TCP_PACKET_OOB_RECV 7 -#define TCP_PACKET_ONION_REQUEST 8 -#define TCP_PACKET_ONION_RESPONSE 9 - #define ARRAY_ENTRY_SIZE 6 -/* frequency to ping connected nodes and timeout in seconds */ -#define TCP_PING_FREQUENCY 30 -#define TCP_PING_TIMEOUT 10 - typedef enum TCP_Status { TCP_STATUS_NO_STATUS, TCP_STATUS_CONNECTED, @@ -51,17 +25,6 @@ typedef enum TCP_Status { TCP_STATUS_CONFIRMED, } TCP_Status; -typedef struct TCP_Priority_List TCP_Priority_List; - -struct TCP_Priority_List { - TCP_Priority_List *next; - uint16_t size; - uint16_t sent; - uint8_t data[]; -}; - -void wipe_priority_list(TCP_Priority_List *p); - typedef struct TCP_Server TCP_Server; const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server); @@ -80,28 +43,5 @@ void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time); */ void kill_TCP_server(TCP_Server *tcp_server); -/** Read the next two bytes in TCP stream then convert them to - * length (host byte order). - * - * return length on success - * return 0 if nothing has been read from socket. - * return -1 on failure. - */ -uint16_t read_TCP_length(const Logger *logger, Socket sock); - -/** Read length bytes from socket. - * - * return length on success - * return -1 on failure/no data in buffer. - */ -int read_TCP_packet(const Logger *logger, Socket sock, uint8_t *data, uint16_t length); - -/** return length of received packet on success. - * return 0 if could not read any packet. - * return -1 on failure (connection must be killed). - */ -int read_packet_TCP_secure_connection(const Logger *logger, Socket sock, uint16_t *next_packet_length, - const uint8_t *shared_key, uint8_t *recv_nonce, uint8_t *data, uint16_t max_len); - #endif diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 16a4a17527b..e43f07c2072 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -14,6 +14,7 @@ #include #include +#include "list.h" #include "mono_time.h" #include "util.h"