From 3a28a8c5fb0e916629cd04c45658ba5201fe029b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 8 May 2015 22:03:24 -0400 Subject: [PATCH] Added basic TCP server hosting to tox.h api. TODO: tell friends we are hosting a relay and prioritize using relays hosted by friends over bootstrap ones. --- auto_tests/tox_test.c | 95 +++++++++++++++++++++++++++++++++++++++++++ other/apidsl/tox.in.h | 5 +++ toxcore/Messenger.c | 29 +++++++++++++ toxcore/Messenger.h | 3 ++ toxcore/tox.c | 13 ++++-- toxcore/tox.h | 6 +++ 6 files changed, 148 insertions(+), 3 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 0dab2e69..2e2d4538 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -809,6 +809,100 @@ loop_top: } END_TEST +#define TCP_RELAY_PORT 33445 + +START_TEST(test_many_clients_tcp) +{ + long long unsigned int cur_time = time(NULL); + Tox *toxes[NUM_TOXES]; + uint32_t i, j; + uint32_t to_comp = 974536; + + for (i = 0; i < NUM_TOXES; ++i) { + struct Tox_Options opts; + tox_options_default(&opts); + + if (i == 0) { + opts.tcp_port = TCP_RELAY_PORT; + } else { + opts.udp_enabled = 0; + } + + toxes[i] = tox_new(&opts, 0, 0, 0); + ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i); + tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp); + uint8_t dpk[TOX_PUBLIC_KEY_SIZE]; + tox_self_get_dht_id(toxes[0], dpk); + tox_add_tcp_relay(toxes[i], "::1", TCP_RELAY_PORT, dpk, 0); + tox_bootstrap(toxes[i], "::1", 33445, dpk, 0); + } + + { + TOX_ERR_GET_PORT error; + ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n"); + ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error"); + ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT, + "First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT); + ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error"); + } + + struct { + uint16_t tox1; + uint16_t tox2; + } pairs[NUM_FRIENDS]; + + uint8_t address[TOX_ADDRESS_SIZE]; + + for (i = 0; i < NUM_FRIENDS; ++i) { +loop_top: + pairs[i].tox1 = rand() % NUM_TOXES; + pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES; + + for (j = 0; j < i; ++j) { + if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) + goto loop_top; + } + + tox_self_get_address(toxes[pairs[i].tox1], address); + + TOX_ERR_FRIEND_ADD test; + uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7, &test); + + if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) { + goto loop_top; + } + + ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test); + } + + while (1) { + uint16_t counter = 0; + + for (i = 0; i < NUM_TOXES; ++i) { + for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j) + if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP) + ++counter; + } + + if (counter == NUM_FRIENDS * 2) { + break; + } + + for (i = 0; i < NUM_TOXES; ++i) { + tox_iterate(toxes[i]); + } + + c_sleep(50); + } + + for (i = 0; i < NUM_TOXES; ++i) { + tox_kill(toxes[i]); + } + + printf("test_many_clients_tcp succeeded, took %llu seconds\n", time(NULL) - cur_time); +} +END_TEST + #define NUM_GROUP_TOX 32 void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) @@ -996,6 +1090,7 @@ Suite *tox_suite(void) DEFTESTCASE(one); DEFTESTCASE_SLOW(few_clients, 50); DEFTESTCASE_SLOW(many_clients, 150); + DEFTESTCASE_SLOW(many_clients_tcp, 150); DEFTESTCASE_SLOW(many_group, 100); return s; } diff --git a/other/apidsl/tox.in.h b/other/apidsl/tox.in.h index 84a4a03e..dd47df23 100644 --- a/other/apidsl/tox.in.h +++ b/other/apidsl/tox.in.h @@ -411,6 +411,11 @@ static class options { * The end port of the inclusive port range to attempt to use. */ uint16_t end_port; + + /** + * The port to use for the TCP server. If 0, the tcp server is disabled. + */ + uint16_t tcp_port; } diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 5b7a7f61..359708ee 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1807,6 +1807,27 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error) return NULL; } + if (options->tcp_server_port) { + m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, m->dht->self_public_key, + m->dht->self_secret_key, m->onion); + + if (m->tcp_server == NULL) { + kill_friend_connections(m->fr_c); + kill_onion(m->onion); + kill_onion_announce(m->onion_a); + kill_onion_client(m->onion_c); + kill_DHT(m->dht); + kill_net_crypto(m->net_crypto); + kill_networking(m->net); + free(m); + + if (error) + *error = MESSENGER_ERROR_TCP_SERVER; + + return NULL; + } + } + m->options = *options; friendreq_init(&(m->fr), m->fr_c); set_nospam(&(m->fr), random_int()); @@ -1826,6 +1847,10 @@ void kill_messenger(Messenger *m) uint32_t i; + if (m->tcp_server) { + kill_TCP_server(m->tcp_server); + } + kill_friend_connections(m->fr_c); kill_onion(m->onion); kill_onion_announce(m->onion_a); @@ -2270,6 +2295,10 @@ void do_messenger(Messenger *m) do_DHT(m->dht); } + if (m->tcp_server) { + do_TCP_server(m->tcp_server); + } + do_net_crypto(m->net_crypto); do_onion_client(m->onion_c); do_friend_connections(m->fr_c); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 8ab6b6ed..26704dd1 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -70,6 +70,7 @@ typedef struct { uint8_t udp_disabled; TCP_Proxy_Info proxy_info; uint16_t port_range[2]; + uint16_t tcp_server_port; } Messenger_Options; @@ -219,6 +220,7 @@ struct Messenger { Friend_Connections *fr_c; + TCP_Server *tcp_server; Friend_Requests fr; uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; @@ -727,6 +729,7 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const enum { MESSENGER_ERROR_NONE, MESSENGER_ERROR_PORT, + MESSENGER_ERROR_TCP_SERVER, MESSENGER_ERROR_OTHER }; diff --git a/toxcore/tox.c b/toxcore/tox.c index 848f81c7..92318cf9 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -152,6 +152,7 @@ Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t leng m_options.udp_disabled = !options->udp_enabled; m_options.port_range[0] = options->start_port; m_options.port_range[1] = options->end_port; + m_options.tcp_server_port = options->tcp_port; switch (options->proxy_type) { case TOX_PROXY_TYPE_HTTP: @@ -1205,9 +1206,15 @@ uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error) uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error) { - /* TCP server not yet implemented in clients. */ - SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND); - return 0; + const Messenger *m = tox; + + if (m->tcp_server) { + SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK); + return m->options.tcp_server_port; + } else { + SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND); + return 0; + } } #include "tox_old_code.h" diff --git a/toxcore/tox.h b/toxcore/tox.h index abd2f051..4afdf7c3 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -426,6 +426,12 @@ struct Tox_Options { */ uint16_t end_port; + + /** + * The port to use for the TCP server. If 0, the tcp server is disabled. + */ + uint16_t tcp_port; + };