diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 0fbffac2..29a9f518 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -340,6 +340,27 @@ static int data_callback(void *object, uint32_t number, uint8_t connection_id, u return 1; } +static int oob_data_callback_good; +static uint8_t oob_pubkey[crypto_box_PUBLICKEYBYTES]; +static int oob_data_callback(void *object, uint8_t *public_key, uint8_t *data, uint16_t length) +{ + if (object != (void *)4) + return 1; + + if (length != 5) + return 1; + + if (memcmp(public_key, oob_pubkey, crypto_box_PUBLICKEYBYTES) != 0) + return 1; + + if (data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4 && data[4] == 5) { + oob_data_callback_good++; + return 0; + } + + return 1; +} + START_TEST(test_client) { unix_time_update(); @@ -389,7 +410,8 @@ START_TEST(test_client) routing_response_handler(conn, response_callback, ((void *)conn) + 2); routing_status_handler(conn, status_callback, (void *)2); routing_data_handler(conn, data_callback, (void *)3); - response_callback_good = status_callback_good = data_callback_good = 0; + oob_data_handler(conn, oob_data_callback, (void *)4); + oob_data_callback_good = response_callback_good = status_callback_good = data_callback_good = 0; c_sleep(50); do_TCP_connection(conn); do_TCP_connection(conn2); @@ -399,6 +421,9 @@ START_TEST(test_client) do_TCP_connection(conn); do_TCP_connection(conn2); c_sleep(50); + uint8_t data[5] = {1, 2, 3, 4, 5}; + memcpy(oob_pubkey, f2_public_key, crypto_box_PUBLICKEYBYTES); + send_oob_packet(conn2, f_public_key, data, 5); send_routing_request(conn, f2_public_key); send_routing_request(conn2, f_public_key); c_sleep(50); @@ -406,6 +431,7 @@ START_TEST(test_client) c_sleep(50); do_TCP_connection(conn); do_TCP_connection(conn2); + ck_assert_msg(oob_data_callback_good == 1, "oob callback not called"); ck_assert_msg(response_callback_good == 1, "response callback not called"); ck_assert_msg(memcmp(response_callback_public_key, f2_public_key, crypto_box_PUBLICKEYBYTES) == 0, "wrong public key"); ck_assert_msg(status_callback_good == 1, "status callback not called"); @@ -413,7 +439,6 @@ START_TEST(test_client) ck_assert_msg(status_callback_connection_id == response_callback_connection_id, "connection ids not equal"); c_sleep(50); do_TCP_server(tcp_s); - uint8_t data[5] = {1, 2, 3, 4, 5}; ck_assert_msg(send_data(conn2, 0, data, 5) == 1, "send data failed"); c_sleep(50); do_TCP_server(tcp_s); diff --git a/docs/TCP_Network.txt b/docs/TCP_Network.txt index 9841329c..4bc2d433 100644 --- a/docs/TCP_Network.txt +++ b/docs/TCP_Network.txt @@ -104,6 +104,10 @@ special ids and packets: [uint8_t id (4)][uint64_t ping_id (0 is invalid)] 5 - ping response (pong) [uint8_t id (5)][uint64_t ping_id (0 is invalid)] +6 - OOB send +[uint8_t id (6)][destination public key (32 bytes)][data] +7 - OOB recv +[uint8_t id (7)][senders public key (32 bytes)][data] 8 - onion packet (same format as initial onion packet (See: Prevent tracking.txt) but packet id is 8 instead of 128) 9 - onion packet response (same format as onion packet with id 142 but id is 9 @@ -140,6 +144,11 @@ If the server receives a ping packet he must respond with a ping response. The server will send a ping packet to clients every 30 seconds, they have 30 seconds to respond, if they don't the connection is deleted. +OOB send packets will be sent to the peer connected to the TCP server with the +destination public key as a OOB recv packet. The client sending this packet has +no way of knowing if the packet reached its destination. + + Client: Implementation details coming soon. diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 891c864f..4652b4a6 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -214,6 +214,23 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_ return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); } +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure. + */ +int send_oob_packet(TCP_Client_Connection *con, uint8_t *public_key, uint8_t *data, uint16_t length) +{ + if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) + return -1; + + uint8_t packet[1 + crypto_box_PUBLICKEYBYTES + length]; + packet[0] = TCP_PACKET_OOB_SEND; + memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + + /* Set the number that will be used as an argument in the callbacks related to con_id. * * When not set by this function, the number is ~0. @@ -240,6 +257,12 @@ void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void con->data_callback_object = object; } +void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, uint8_t *public_key, + uint8_t *data, uint16_t length), void *object) +{ + con->oob_data_callback = oob_data_callback; + con->oob_data_callback_object = object; +} /* return 1 on success. * return 0 if could not send packet. @@ -448,6 +471,17 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ } } + case TCP_PACKET_OOB_RECV: { + if (length <= 1 + crypto_box_PUBLICKEYBYTES) + return -1; + + if (conn->oob_data_callback) + conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, + length - (1 + crypto_box_PUBLICKEYBYTES)); + + return 0; + } + case TCP_PACKET_ONION_RESPONSE: { conn->onion_callback(conn->onion_callback_object, data + 1, length - 1); return 0; diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 64678790..277378b9 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -67,6 +67,8 @@ typedef struct { void *status_callback_object; int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length); void *data_callback_object; + int (*oob_data_callback)(void *object, uint8_t *public_key, uint8_t *data, uint16_t length); + void *oob_data_callback_object; int (*onion_callback)(void *object, uint8_t *data, uint16_t length); void *onion_callback_object; @@ -120,4 +122,13 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_ void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length), void *object); +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure. + */ +int send_oob_packet(TCP_Client_Connection *con, uint8_t *public_key, uint8_t *data, uint16_t length); +void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, uint8_t *public_key, + uint8_t *data, uint16_t length), void *object); + + #endif diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 79a420d3..914317b7 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -508,6 +508,31 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, uint8 return 0; } +/* return 0 on success. + * return -1 on failure (connection must be killed). + */ +static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, uint8_t *public_key, uint8_t *data, + uint16_t length) +{ + if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) + return -1; + + TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id]; + + int other_index = get_TCP_connection_index(TCP_server, public_key); + + if (other_index != -1) { + uint8_t resp_packet[1 + crypto_box_PUBLICKEYBYTES + length]; + resp_packet[0] = TCP_PACKET_OOB_RECV; + memcpy(resp_packet + 1, con->public_key, crypto_box_PUBLICKEYBYTES); + memcpy(resp_packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); + write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet, + sizeof(resp_packet)); + } + + return 0; +} + static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) { if (con_number >= NUM_CLIENT_CONNECTIONS) @@ -624,6 +649,14 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d } } + case TCP_PACKET_OOB_SEND: { + if (length <= 1 + crypto_box_PUBLICKEYBYTES) + return -1; + + return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, + length - (1 + crypto_box_PUBLICKEYBYTES)); + } + case TCP_PACKET_ONION_REQUEST: { if (TCP_server->onion) { if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE * 2) diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 2a6b8276..136231d0 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -39,6 +39,7 @@ #define TCP_HANDSHAKE_PLAIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES) #define TCP_SERVER_HANDSHAKE_SIZE (crypto_box_NONCEBYTES + TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) #define TCP_CLIENT_HANDSHAKE_SIZE (crypto_box_PUBLICKEYBYTES + TCP_SERVER_HANDSHAKE_SIZE) +#define TCP_MAX_OOB_DATA_LENGTH 1024 #define NUM_RESERVED_PORTS 16 #define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS) @@ -49,6 +50,8 @@ #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 diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 73726a59..73cb1f75 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -52,7 +52,6 @@ static int is_path_used(Onion_Client_Paths *onion_paths, Node_format *nodes) } if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[0].ip_port)) { - printf("bad\n"); return i; } }