diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 04dd3c22..2fbc3083 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -68,6 +68,24 @@ void print_typingchange(Tox *m, int friendnumber, uint8_t typing, void *userdata typing_changes = 2; } +uint32_t custom_packet; + +int handle_custom_packet(void *object, const uint8_t *data, uint32_t len) +{ + uint8_t number = *((uint32_t *)object); + + if (len != TOX_MAX_CUSTOM_PACKET_SIZE) + return -1; + + uint8_t f_data[len]; + memset(f_data, number, len); + if (memcmp(f_data, data, len) == 0) { + ++custom_packet; + } else { + printf("Custom packet fail. %u\n",number ); + } +} + uint8_t filenum; uint32_t file_accepted; uint64_t file_size; @@ -110,7 +128,7 @@ void write_file(Tox *m, int friendnumber, uint8_t filenumber, const uint8_t *dat if (*((uint32_t *)userdata) != 974536) return; - uint8_t *f_data = malloc(length); + uint8_t f_data[length]; memset(f_data, num, length); ++num; @@ -234,6 +252,53 @@ START_TEST(test_few_clients) ck_assert_msg(tox_get_is_typing(tox2, 0) == 0, "Typing fail"); + uint32_t packet_number = 160; + int ret = tox_lossless_packet_registerhandler(tox3, 0, packet_number, handle_custom_packet, &packet_number); + ck_assert_msg(ret == 0, "tox_lossless_packet_registerhandler fail %i", ret); + uint8_t data_c[TOX_MAX_CUSTOM_PACKET_SIZE + 1]; + memset(data_c, ((uint8_t)packet_number), sizeof(data_c)); + ret = tox_send_lossless_packet(tox2, 0, data_c, sizeof(data_c)); + ck_assert_msg(ret == -1, "tox_send_lossless_packet bigger fail %i", ret); + ret = tox_send_lossless_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE); + ck_assert_msg(ret == 0, "tox_send_lossless_packet fail %i", ret); + + while (1) { + custom_packet = 0; + tox_do(tox1); + tox_do(tox2); + tox_do(tox3); + + if (custom_packet == 1) + break; + else + ck_assert_msg(custom_packet == 0, "Lossless packet fail"); + + c_sleep(50); + } + + packet_number = 200; + ret = tox_lossy_packet_registerhandler(tox3, 0, packet_number, handle_custom_packet, &packet_number); + ck_assert_msg(ret == 0, "tox_lossy_packet_registerhandler fail %i", ret); + memset(data_c, ((uint8_t)packet_number), sizeof(data_c)); + ret = tox_send_lossy_packet(tox2, 0, data_c, sizeof(data_c)); + ck_assert_msg(ret == -1, "tox_send_lossy_packet bigger fail %i", ret); + ret = tox_send_lossy_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE); + ck_assert_msg(ret == 0, "tox_send_lossy_packet fail %i", ret); + + while (1) { + custom_packet = 0; + tox_do(tox1); + tox_do(tox2); + tox_do(tox3); + + if (custom_packet == 1) + break; + else + ck_assert_msg(custom_packet == 0, "lossy packet fail"); + + c_sleep(50); + } + filenum = file_accepted = file_size = file_sent = sendf_ok = size_recv = 0; long long unsigned int f_time = time(NULL); tox_callback_file_data(tox3, write_file, &to_compare); @@ -244,7 +309,7 @@ START_TEST(test_few_clients) int fnum = tox_new_file_sender(tox2, 0, totalf_size, (uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe")); ck_assert_msg(fnum != -1, "tox_new_file_sender fail"); int fpiece_size = tox_file_data_size(tox2, 0); - uint8_t *f_data = malloc(fpiece_size); + uint8_t f_data[fpiece_size]; uint8_t num = 0; memset(f_data, num, fpiece_size); @@ -292,7 +357,7 @@ START_TEST(test_few_clients) END_TEST #define NUM_TOXES 66 -#define NUM_FRIENDS 20 +#define NUM_FRIENDS 50 START_TEST(test_many_clients) { diff --git a/docs/Prevent_Tracking.txt b/docs/Prevent_Tracking.txt index d170103f..86402110 100644 --- a/docs/Prevent_Tracking.txt +++ b/docs/Prevent_Tracking.txt @@ -117,8 +117,9 @@ Data sent to us: announce response packet: [uint8_t packet id (132)][data to send back in response(fixed size)][nonce] encrypted with the DHT private key of Node D, the public key in the request and the nonce:[[uint8_t is_stored] -[(32 bytes) ping_id if is_stored is 0, public key that must be used to send data packets if is_stored is not 0][Node_Format * (maximum of 8)]] +[(32 bytes) ping_id if is_stored is 0 or 2, public key that must be used to send data packets if is_stored is 1][Node_Format * (maximum of 8)]] (if the is_stored is not 0, it means the information to reach the client id we are searching for is stored on this node) +is_stored is 2 as a response to a peer trying to announce himself to tell the peer that he is currently annouced successfully. data to route response packet: [uint8_t packet id (134)][nonce][temporary just generated public key] diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index a84132b6..ff894246 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -63,7 +63,7 @@ Cookie sitting outside the encrypted part][Other Cookie (used by the other to respond to the handshake packet)]] The handshake packet is encrypted using the real private key of the sender, the -real private key of the receiver and the nonce. +real public key of the receiver and the nonce. Alice wants to connect to bob. diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index fffaf4cb..7ea89ea6 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1773,13 +1773,26 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const if (friend_not_valid(m, friendnumber)) return -1; + if (length == 0) + return -1; + + if (data[0] < PACKET_ID_LOSSLESS_RANGE_START) + return -1; + + if (data[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) + return -1; + if (m->friendlist[friendnumber].status != FRIEND_ONLINE) return -1; if (m->friendlist[friendnumber].crypt_connection_id == -1) return -1; - return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, data, length, 1) != -1; + if (write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, data, length, 1) == -1) { + return -1; + } else { + return 0; + } } /* Function to filter out some friend requests*/ diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index baccc95b..b25b6b11 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -333,10 +333,14 @@ static int handle_announce_request(void *object, IP_Port source, const uint8_t * pl[0] = 0; memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE); } else { - if (memcmp(onion_a->entries[index].public_key, packet_public_key, crypto_box_PUBLICKEYBYTES) == 0 - && memcmp(onion_a->entries[index].data_public_key, data_public_key, crypto_box_PUBLICKEYBYTES) != 0) { - pl[0] = 0; - memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE); + if (memcmp(onion_a->entries[index].public_key, packet_public_key, crypto_box_PUBLICKEYBYTES) == 0) { + if (memcmp(onion_a->entries[index].data_public_key, data_public_key, crypto_box_PUBLICKEYBYTES) != 0) { + pl[0] = 0; + memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE); + } else { + pl[0] = 2; + memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE); + } } else { pl[0] = 1; memcpy(pl + 1, onion_a->entries[index].data_public_key, crypto_box_PUBLICKEYBYTES); diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index f2ba3715..36ffe767 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h @@ -25,7 +25,7 @@ #include "onion.h" -#define ONION_ANNOUNCE_MAX_ENTRIES 48 +#define ONION_ANNOUNCE_MAX_ENTRIES 64 #define ONION_ANNOUNCE_TIMEOUT 300 #define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 167a26f9..ab7958c6 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -398,11 +398,14 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t list_nodes = onion_c->clients_announce_list; reference_id = onion_c->c->self_public_key; - if (is_stored && memcmp(pingid_or_key, onion_c->temp_public_key, crypto_box_PUBLICKEYBYTES) != 0) { + if (is_stored == 1 && memcmp(pingid_or_key, onion_c->temp_public_key, crypto_box_PUBLICKEYBYTES) != 0) { is_stored = 0; } } else { + if (is_stored >= 2) + return -1; + list_nodes = onion_c->friends_list[num - 1].clients_list; reference_id = onion_c->friends_list[num - 1].real_client_id; } @@ -435,7 +438,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t //TODO: remove this and find a better source of nodes to use for paths. onion_add_path_node(onion_c, ip_port, public_key); - if (is_stored) { + if (is_stored == 1) { memcpy(list_nodes[index].data_public_key, pingid_or_key, crypto_box_PUBLICKEYBYTES); } else { memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE); diff --git a/toxcore/tox.c b/toxcore/tox.c index c3199fef..12145a09 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -469,6 +469,77 @@ void tox_get_keys(Tox *tox, uint8_t *public_key, uint8_t *secret_key) memcpy(secret_key, m->net_crypto->self_secret_key, crypto_box_SECRETKEYBYTES); } +/* Set handlers for custom lossy packets. + * Set the function to be called when friend sends us a lossy packet starting with byte. + * byte must be in the 200-254 range. + * + * NOTE: lossy packets behave like UDP packets meaning they might never reach the other side + * or might arrive more than once (if someone is messing with the connection) or might arrive + * in the wrong order. + * + * Unless latency is an issue, it is recommended that you use lossless packets instead. + * + * return -1 on failure. + * return 0 on success. + */ +int tox_lossy_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, + int (*packet_handler_callback)(void *object, const uint8_t *data, uint32_t len), void *object) +{ + Messenger *m = tox; + + if (byte < (PACKET_ID_LOSSY_RANGE_START + 8)) /* First 8 reserved for A/V*/ + return -1; + + return custom_lossy_packet_registerhandler(m, friendnumber, byte, packet_handler_callback, object); +} + +/* Function to send custom lossy packets. + * First byte of data must be in the range: 200-254. + * + * return -1 on failure. + * return 0 on success. + */ +int tox_send_lossy_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length) +{ + const Messenger *m = tox; + + if (length == 0) + return -1; + + if (data[0] < (PACKET_ID_LOSSY_RANGE_START + 8)) /* First 8 reserved for A/V*/ + return -1; + + return send_custom_lossy_packet(m, friendnumber, data, length); +} + +/* Set handlers for custom lossless packets. + * Set the function to be called when friend sends us a lossless packet starting with byte. + * byte must be in the 160-191 range. + * + * return -1 on failure. + * return 0 on success. + */ +int tox_lossless_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, + int (*packet_handler_callback)(void *object, const uint8_t *data, uint32_t len), void *object) +{ + Messenger *m = tox; + + return custom_lossless_packet_registerhandler(m, friendnumber, byte, packet_handler_callback, object); +} + +/* Function to send custom lossless packets. + * First byte of data must be in the range: 160-191. + * + * return -1 on failure. + * return 0 on success. + */ +int tox_send_lossless_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length) +{ + const Messenger *m = tox; + + return send_custom_lossless_packet(m, friendnumber, data, length); +} + /**********GROUP CHAT FUNCTIONS: WARNING Group chats will be rewritten so this might change ************/ /* Set the callback for group invites. diff --git a/toxcore/tox.h b/toxcore/tox.h index e900cc7f..c457fea5 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -354,6 +354,53 @@ void tox_set_nospam(Tox *tox, uint32_t nospam); if the pointer is NULL, no data will be copied to it.*/ void tox_get_keys(Tox *tox, uint8_t *public_key, uint8_t *secret_key); +/* Maximum size of custom packets. */ +#define TOX_MAX_CUSTOM_PACKET_SIZE 1373 + +/* Set handlers for custom lossy packets. + * Set the function to be called when friend sends us a lossy packet starting with byte. + * byte must be in the 200-254 range. + * + * NOTE: lossy packets behave like UDP packets meaning they might never reach the other side + * or might arrive more than once (if someone is messing with the connection) or might arrive + * in the wrong order. + * + * Unless latency is an issue, it is recommended that you use lossless packets instead. + * + * return -1 on failure. + * return 0 on success. + */ +int tox_lossy_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, + int (*packet_handler_callback)(void *object, const uint8_t *data, uint32_t len), void *object); + +/* Function to send custom lossy packets. + * First byte of data must be in the range: 200-254. + * + * return -1 on failure. + * return 0 on success. + */ +int tox_send_lossy_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length); + +/* Set handlers for custom lossless packets. + * Set the function to be called when friend sends us a lossless packet starting with byte. + * byte must be in the 160-191 range. + * + * Lossless packets behave kind of like TCP (reliability, arrive in order.) but with packets instead of a stream. + * + * return -1 on failure. + * return 0 on success. + */ +int tox_lossless_packet_registerhandler(Tox *tox, int32_t friendnumber, uint8_t byte, + int (*packet_handler_callback)(void *object, const uint8_t *data, uint32_t len), void *object); + +/* Function to send custom lossless packets. + * First byte of data must be in the range: 160-191. + * + * return -1 on failure. + * return 0 on success. + */ +int tox_send_lossless_packet(const Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length); + /**********GROUP CHAT FUNCTIONS: WARNING Group chats will be rewritten so this might change ************/ /* Set the callback for group invites.