diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 6e46492c..03ca8893 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -28,7 +28,7 @@ START_TEST(test_basic) uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; crypto_box_keypair(self_public_key, self_secret_key); - TCP_Server *tcp_s = new_TCP_server(1, NUM_PORTS, ports, self_public_key, self_secret_key); + TCP_Server *tcp_s = new_TCP_server(1, NUM_PORTS, ports, self_public_key, self_secret_key, NULL); ck_assert_msg(tcp_s != NULL, "Failed to create TCP relay server"); sock_t sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); @@ -202,7 +202,7 @@ START_TEST(test_some) uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; crypto_box_keypair(self_public_key, self_secret_key); - TCP_Server *tcp_s = new_TCP_server(1, NUM_PORTS, ports, self_public_key, self_secret_key); + TCP_Server *tcp_s = new_TCP_server(1, NUM_PORTS, ports, self_public_key, self_secret_key, NULL); ck_assert_msg(tcp_s != NULL, "Failed to create TCP relay server"); struct sec_TCP_con *con1 = new_TCP_con(tcp_s); diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 70e6ede6..727c1336 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -167,6 +167,7 @@ static int add_accepted(TCP_Server *TCP_server, TCP_Secure_Connection *con) memcpy(&TCP_server->accepted_connection_array[index], con, sizeof(TCP_Secure_Connection)); TCP_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED; ++TCP_server->num_accepted_connections; + TCP_server->accepted_connection_array[index].identifier = ++TCP_server->counter; return index; } @@ -580,6 +581,29 @@ static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connect } } +static int handle_onion_recv_1(void *object, IP_Port dest, uint8_t *data, uint16_t length) +{ + TCP_Server *TCP_server = object; + uint32_t index = dest.ip.ip6.uint32[0]; + + if (index >= TCP_server->size_accepted_connections) + return 1; + + TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[index]; + + if (con->identifier != dest.ip.ip6.uint64[1]) + return 1; + + uint8_t packet[1 + length]; + memcpy(packet + 1, data, length); + packet[0] = TCP_PACKET_ONION_RESPONSE; + + if (write_packet_TCP_secure_connection(con, packet, sizeof(packet)) != 1) + return 1; + + return 0; +} + /* return 0 on success * return -1 on failure */ @@ -627,16 +651,23 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d } case TCP_PACKET_ONION_REQUEST: { - //if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE*2) - // return -1; + if (TCP_server->onion) { + if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE * 2) + return -1; + + IP_Port source; + source.ip.family = TCP_ONION_FAMILY; + source.ip.ip6.uint32[0] = con_id; + source.ip.ip6.uint64[1] = con->identifier; + onion_send_1(TCP_server->onion, data + 1 + crypto_box_NONCEBYTES, length - (1 + crypto_box_NONCEBYTES), source, + data + 1); + } - //TODO onion_send_1(Onion *onion, data + 1 + crypto_box_NONCEBYTES, length - (1 + crypto_box_NONCEBYTES), IP_Port source, data + 1); return 0; } case TCP_PACKET_ONION_RESPONSE: { - - break; + return -1; } default: { @@ -741,7 +772,7 @@ static sock_t new_listening_TCP_socket(int family, uint16_t port) } TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t *ports, uint8_t *public_key, - uint8_t *secret_key) + uint8_t *secret_key, Onion *onion) { if (num_sockets == 0 || ports == NULL) return NULL; @@ -751,6 +782,11 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t if (temp == NULL) return NULL; + if (onion) { + temp->onion = onion; + set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp); + } + temp->socks_listening = calloc(num_sockets, sizeof(sock_t)); if (temp->socks_listening == NULL) { @@ -898,6 +934,10 @@ void kill_TCP_server(TCP_Server *TCP_server) kill_sock(TCP_server->socks_listening[i]); } + if (TCP_server->onion) { + set_callback_handle_recv_1(TCP_server->onion, NULL, NULL); + } + free(TCP_server->socks_listening); free(TCP_server); } diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 4814d407..7461fe5d 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -21,6 +21,7 @@ */ #include "net_crypto.h" +#include "onion.h" #define MAX_INCOMMING_CONNECTIONS 32 @@ -46,6 +47,8 @@ #define ARRAY_ENTRY_SIZE 6 +#define TCP_ONION_FAMILY (AF_INET6 + 1) + enum { TCP_STATUS_NO_STATUS, TCP_STATUS_CONNECTED, @@ -70,10 +73,13 @@ typedef struct TCP_Secure_Connection { uint8_t last_packet[2 + MAX_PACKET_SIZE]; uint16_t last_packet_length; uint16_t last_packet_sent; + + uint64_t identifier; } TCP_Secure_Connection; typedef struct { + Onion *onion; sock_t *socks_listening; unsigned int num_listening_socks; @@ -87,12 +93,14 @@ typedef struct { TCP_Secure_Connection *accepted_connection_array; uint32_t size_accepted_connections; uint32_t num_accepted_connections; + + uint64_t counter; } TCP_Server; /* Create new TCP server instance. */ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t *ports, uint8_t *public_key, - uint8_t *secret_key); + uint8_t *secret_key, Onion *onion); /* Run the TCP_server */ diff --git a/toxcore/network.h b/toxcore/network.h index 5845932f..e2c8ae2e 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -161,21 +161,30 @@ typedef int sock_t; #define TOX_PORTRANGE_TO 33545 #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM -typedef union { + +/* TODO: remove padding bytes next time we need to break compatibility with old versions of core. */ + +typedef union __attribute__ ((__packed__)) +{ uint8_t uint8[4]; uint16_t uint16[2]; uint32_t uint32; struct in_addr in_addr; -} IP4; +} +IP4; -typedef union { +typedef union __attribute__ ((__packed__)) +{ uint8_t uint8[16]; uint16_t uint16[8]; uint32_t uint32[4]; + uint64_t uint64[2]; struct in6_addr in6_addr; -} IP6; +} +IP6; -typedef struct { +typedef struct __attribute__ ((__packed__)) +{ uint8_t family; /* Not used for anything right now. */ uint8_t padding[3]; @@ -183,9 +192,11 @@ typedef struct { IP4 ip4; IP6 ip6; }; -} IP; +} +IP; -typedef union { +typedef union __attribute__ ((__packed__)) +{ struct { IP4 ip; uint16_t port; @@ -193,11 +204,13 @@ typedef union { uint16_t padding; }; uint8_t uint8[8]; -} IP4_Port; +} +IP4_Port; -typedef struct IP_Port { +typedef struct __attribute__ ((__packed__)) IP_Port { IP ip; uint16_t port; + uint16_t padding; } IP_Port; #define TOX_ENABLE_IPV6_DEFAULT 1 diff --git a/toxcore/onion.c b/toxcore/onion.c index 6bc6ab07..ccb729f3 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -398,13 +398,20 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t uint32_t data_len = length - (1 + RETURN_1); + if (onion->recv_1_function && send_to.ip.family != AF_INET && send_to.ip.family != AF_INET6) + return onion->recv_1_function(onion->callback_object, send_to, packet + (1 + RETURN_1), data_len); + if ((uint32_t)sendpacket(onion->net, send_to, packet + (1 + RETURN_1), data_len) != data_len) return 1; return 0; } - +void set_callback_handle_recv_1(Onion *onion, int (*function)(void *, IP_Port, uint8_t *, uint16_t), void *object) +{ + onion->recv_1_function = function; + onion->callback_object = object; +} Onion *new_onion(DHT *dht) { diff --git a/toxcore/onion.h b/toxcore/onion.h index 9577f019..4e363724 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -34,6 +34,9 @@ typedef struct { Shared_Keys shared_keys_1; Shared_Keys shared_keys_2; Shared_Keys shared_keys_3; + + int (*recv_1_function)(void *, IP_Port, uint8_t *, uint16_t); + void *callback_object; } Onion; #define ONION_RETURN_1 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) @@ -92,9 +95,18 @@ int send_onion_response(Networking_Core *net, IP_Port dest, uint8_t *data, uint3 * return 1 on failure. * * Used to handle these packets that are received in a non traditional way (by TCP for example). + * + * Source family must be set to something else than AF_INET6 or AF_INET so that the callback gets called + * when the response is received. */ int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uint8_t *nonce); +/* Set the callback to be called when the dest ip_port doesn't have AF_INET6 or AF_INET as the family. + * + * Format: function(void *object, IP_Port dest, uint8_t *data, uint32_t length) + */ +void set_callback_handle_recv_1(Onion *onion, int (*function)(void *, IP_Port, uint8_t *, uint16_t), void *object); + Onion *new_onion(DHT *dht); void kill_onion(Onion *onion);