summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/tox_test.c192
-rw-r--r--other/apidsl/tox.in.h5
-rw-r--r--testing/irc_syncbot.c20
-rw-r--r--toxcore/LAN_discovery.c37
-rw-r--r--toxcore/LAN_discovery.h3
-rw-r--r--toxcore/Messenger.c38
-rw-r--r--toxcore/Messenger.h3
-rw-r--r--toxcore/friend_connection.c15
-rw-r--r--toxcore/friend_connection.h2
-rw-r--r--toxcore/onion_announce.h2
-rw-r--r--toxcore/onion_client.c2
-rw-r--r--toxcore/tox.c132
-rw-r--r--toxcore/tox.h6
13 files changed, 394 insertions, 63 deletions
diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c
index 0dab2e69..142a178f 100644
--- a/auto_tests/tox_test.c
+++ b/auto_tests/tox_test.c
@@ -809,6 +809,196 @@ loop_top:
809} 809}
810END_TEST 810END_TEST
811 811
812#define TCP_RELAY_PORT 33448
813
814START_TEST(test_many_clients_tcp)
815{
816 long long unsigned int cur_time = time(NULL);
817 Tox *toxes[NUM_TOXES];
818 uint32_t i, j;
819 uint32_t to_comp = 974536;
820
821 for (i = 0; i < NUM_TOXES; ++i) {
822 struct Tox_Options opts;
823 tox_options_default(&opts);
824
825 if (i == 0) {
826 opts.tcp_port = TCP_RELAY_PORT;
827 } else {
828 opts.udp_enabled = 0;
829 }
830
831 toxes[i] = tox_new(&opts, 0, 0, 0);
832 ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
833 tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
834 uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
835 tox_self_get_dht_id(toxes[0], dpk);
836 ck_assert_msg(tox_add_tcp_relay(toxes[i], "::1", TCP_RELAY_PORT, dpk, 0), "add relay error");
837 ck_assert_msg(tox_bootstrap(toxes[i], "::1", 33445, dpk, 0), "Bootstrap error");
838 }
839
840 {
841 TOX_ERR_GET_PORT error;
842 ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
843 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
844 ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT,
845 "First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT);
846 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
847 }
848
849 struct {
850 uint16_t tox1;
851 uint16_t tox2;
852 } pairs[NUM_FRIENDS];
853
854 uint8_t address[TOX_ADDRESS_SIZE];
855
856 for (i = 0; i < NUM_FRIENDS; ++i) {
857loop_top:
858 pairs[i].tox1 = rand() % NUM_TOXES;
859 pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES;
860
861 for (j = 0; j < i; ++j) {
862 if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2)
863 goto loop_top;
864 }
865
866 tox_self_get_address(toxes[pairs[i].tox1], address);
867
868 TOX_ERR_FRIEND_ADD test;
869 uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7, &test);
870
871 if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
872 goto loop_top;
873 }
874
875 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
876 }
877
878 while (1) {
879 uint16_t counter = 0;
880
881 for (i = 0; i < NUM_TOXES; ++i) {
882 for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j)
883 if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP)
884 ++counter;
885 }
886
887 if (counter == NUM_FRIENDS * 2) {
888 break;
889 }
890
891 for (i = 0; i < NUM_TOXES; ++i) {
892 tox_iterate(toxes[i]);
893 }
894
895 c_sleep(50);
896 }
897
898 for (i = 0; i < NUM_TOXES; ++i) {
899 tox_kill(toxes[i]);
900 }
901
902 printf("test_many_clients_tcp succeeded, took %llu seconds\n", time(NULL) - cur_time);
903}
904END_TEST
905
906#define NUM_TCP_RELAYS 3
907
908START_TEST(test_many_clients_tcp_b)
909{
910 long long unsigned int cur_time = time(NULL);
911 Tox *toxes[NUM_TOXES];
912 uint32_t i, j;
913 uint32_t to_comp = 974536;
914
915 for (i = 0; i < NUM_TOXES; ++i) {
916 struct Tox_Options opts;
917 tox_options_default(&opts);
918
919 if (i < NUM_TCP_RELAYS) {
920 opts.tcp_port = TCP_RELAY_PORT + i;
921 } else {
922 opts.udp_enabled = 0;
923 }
924
925 toxes[i] = tox_new(&opts, 0, 0, 0);
926 ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
927 tox_callback_friend_request(toxes[i], accept_friend_request, &to_comp);
928 uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
929 tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk);
930 ck_assert_msg(tox_add_tcp_relay(toxes[i], "::1", TCP_RELAY_PORT + (i % NUM_TCP_RELAYS), dpk, 0), "add relay error");
931 tox_self_get_dht_id(toxes[0], dpk);
932 ck_assert_msg(tox_bootstrap(toxes[i], "::1", 33445, dpk, 0), "Bootstrap error");
933 }
934
935 {
936 TOX_ERR_GET_PORT error;
937 ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
938 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
939 ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT,
940 "First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT);
941 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
942 }
943
944 struct {
945 uint16_t tox1;
946 uint16_t tox2;
947 } pairs[NUM_FRIENDS];
948
949 uint8_t address[TOX_ADDRESS_SIZE];
950
951 for (i = 0; i < NUM_FRIENDS; ++i) {
952loop_top:
953 pairs[i].tox1 = rand() % NUM_TOXES;
954 pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES;
955
956 for (j = 0; j < i; ++j) {
957 if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2)
958 goto loop_top;
959 }
960
961 tox_self_get_address(toxes[pairs[i].tox1], address);
962
963 TOX_ERR_FRIEND_ADD test;
964 uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7, &test);
965
966 if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
967 goto loop_top;
968 }
969
970 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
971 }
972
973 while (1) {
974 uint16_t counter = 0;
975
976 for (i = 0; i < NUM_TOXES; ++i) {
977 for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j)
978 if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP)
979 ++counter;
980 }
981
982 if (counter == NUM_FRIENDS * 2) {
983 break;
984 }
985
986 for (i = 0; i < NUM_TOXES; ++i) {
987 tox_iterate(toxes[i]);
988 }
989
990 c_sleep(50);
991 }
992
993 for (i = 0; i < NUM_TOXES; ++i) {
994 tox_kill(toxes[i]);
995 }
996
997 printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(NULL) - cur_time);
998}
999END_TEST
1000
1001
812#define NUM_GROUP_TOX 32 1002#define NUM_GROUP_TOX 32
813 1003
814void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) 1004void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
@@ -996,6 +1186,8 @@ Suite *tox_suite(void)
996 DEFTESTCASE(one); 1186 DEFTESTCASE(one);
997 DEFTESTCASE_SLOW(few_clients, 50); 1187 DEFTESTCASE_SLOW(few_clients, 50);
998 DEFTESTCASE_SLOW(many_clients, 150); 1188 DEFTESTCASE_SLOW(many_clients, 150);
1189 DEFTESTCASE_SLOW(many_clients_tcp, 20);
1190 DEFTESTCASE_SLOW(many_clients_tcp_b, 20);
999 DEFTESTCASE_SLOW(many_group, 100); 1191 DEFTESTCASE_SLOW(many_group, 100);
1000 return s; 1192 return s;
1001} 1193}
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 {
411 * The end port of the inclusive port range to attempt to use. 411 * The end port of the inclusive port range to attempt to use.
412 */ 412 */
413 uint16_t end_port; 413 uint16_t end_port;
414
415 /**
416 * The port to use for the TCP server. If 0, the tcp server is disabled.
417 */
418 uint16_t tcp_port;
414 } 419 }
415 420
416 421
diff --git a/testing/irc_syncbot.c b/testing/irc_syncbot.c
index b879e4eb..2d326c4b 100644
--- a/testing/irc_syncbot.c
+++ b/testing/irc_syncbot.c
@@ -163,9 +163,15 @@ void send_irc_group(Tox *tox, uint8_t *msg, uint16_t len)
163 uint8_t req[len]; 163 uint8_t req[len];
164 unsigned int i; 164 unsigned int i;
165 165
166 unsigned int spaces = 0;
167
166 for (i = 0; i < (len - 1); ++i) { 168 for (i = 0; i < (len - 1); ++i) {
167 if (msg[i + 1] == ':') { 169 if (msg[i + 1] == ' ') {
168 break; 170 ++spaces;
171 } else {
172 if (spaces >= 3 && msg[i + 1] == ':') {
173 break;
174 }
169 } 175 }
170 176
171 req[i] = msg[i + 1]; 177 req[i] = msg[i + 1];
@@ -227,11 +233,6 @@ Tox *init_tox(int argc, char *argv[])
227 tox_callback_group_message(tox, &copy_groupmessage, 0); 233 tox_callback_group_message(tox, &copy_groupmessage, 0);
228 tox_callback_group_action(tox, &copy_groupmessage, 0); 234 tox_callback_group_action(tox, &copy_groupmessage, 0);
229 235
230 uint16_t port = atoi(argv[argvoffset + 2]);
231 unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
232 tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
233 free(binary_string);
234
235 char temp_id[128]; 236 char temp_id[128];
236 printf("\nEnter the address of irc_syncbots master (38 bytes HEX format):\n"); 237 printf("\nEnter the address of irc_syncbots master (38 bytes HEX format):\n");
237 238
@@ -239,6 +240,11 @@ Tox *init_tox(int argc, char *argv[])
239 exit (1); 240 exit (1);
240 } 241 }
241 242
243 uint16_t port = atoi(argv[argvoffset + 2]);
244 unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
245 tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
246 free(binary_string);
247
242 uint8_t *bin_id = hex_string_to_bin(temp_id); 248 uint8_t *bin_id = hex_string_to_bin(temp_id);
243 uint32_t num = tox_friend_add(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo") - 1, 0); 249 uint32_t num = tox_friend_add(tox, bin_id, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo") - 1, 0);
244 free(bin_id); 250 free(bin_id);
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index dbce762e..5ab5b0e1 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -227,18 +227,43 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
227 return ip; 227 return ip;
228} 228}
229 229
230/* Is IP a local ip or not. */
231_Bool Local_ip(IP ip)
232{
233 if (ip.family == AF_INET) {
234 IP4 ip4 = ip.ip4;
235
236 /* Loopback. */
237 if (ip4.uint8[0] == 127)
238 return 1;
239 } else {
240 /* embedded IPv4-in-IPv6 */
241 if (IPV6_IPV4_IN_V6(ip.ip6)) {
242 IP ip4;
243 ip4.family = AF_INET;
244 ip4.ip4.uint32 = ip.ip6.uint32[3];
245 return Local_ip(ip4);
246 }
247
248 /* localhost in IPv6 (::1) */
249 if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1))
250 return 1;
251 }
252
253 return 0;
254}
255
230/* return 0 if ip is a LAN ip. 256/* return 0 if ip is a LAN ip.
231 * return -1 if it is not. 257 * return -1 if it is not.
232 */ 258 */
233int LAN_ip(IP ip) 259int LAN_ip(IP ip)
234{ 260{
261 if (Local_ip(ip))
262 return 0;
263
235 if (ip.family == AF_INET) { 264 if (ip.family == AF_INET) {
236 IP4 ip4 = ip.ip4; 265 IP4 ip4 = ip.ip4;
237 266
238 /* Loopback. */
239 if (ip4.uint8[0] == 127)
240 return 0;
241
242 /* 10.0.0.0 to 10.255.255.255 range. */ 267 /* 10.0.0.0 to 10.255.255.255 range. */
243 if (ip4.uint8[0] == 10) 268 if (ip4.uint8[0] == 10)
244 return 0; 269 return 0;
@@ -276,10 +301,6 @@ int LAN_ip(IP ip)
276 ip4.ip4.uint32 = ip.ip6.uint32[3]; 301 ip4.ip4.uint32 = ip.ip6.uint32[3];
277 return LAN_ip(ip4); 302 return LAN_ip(ip4);
278 } 303 }
279
280 /* localhost in IPv6 (::1) */
281 if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1))
282 return 0;
283 } 304 }
284 305
285 return -1; 306 return -1;
diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h
index 5243bd93..358bea2f 100644
--- a/toxcore/LAN_discovery.h
+++ b/toxcore/LAN_discovery.h
@@ -40,6 +40,9 @@ void LANdiscovery_init(DHT *dht);
40/* Clear packet handlers. */ 40/* Clear packet handlers. */
41void LANdiscovery_kill(DHT *dht); 41void LANdiscovery_kill(DHT *dht);
42 42
43/* Is IP a local ip or not. */
44_Bool Local_ip(IP ip);
45
43/* checks if a given IP isn't routable 46/* checks if a given IP isn't routable
44 * 47 *
45 * return 0 if ip is a LAN ip. 48 * return 0 if ip is a LAN ip.
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 5b7a7f61..6294aa9c 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1807,6 +1807,27 @@ Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
1807 return NULL; 1807 return NULL;
1808 } 1808 }
1809 1809
1810 if (options->tcp_server_port) {
1811 m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, m->dht->self_public_key,
1812 m->dht->self_secret_key, m->onion);
1813
1814 if (m->tcp_server == NULL) {
1815 kill_friend_connections(m->fr_c);
1816 kill_onion(m->onion);
1817 kill_onion_announce(m->onion_a);
1818 kill_onion_client(m->onion_c);
1819 kill_DHT(m->dht);
1820 kill_net_crypto(m->net_crypto);
1821 kill_networking(m->net);
1822 free(m);
1823
1824 if (error)
1825 *error = MESSENGER_ERROR_TCP_SERVER;
1826
1827 return NULL;
1828 }
1829 }
1830
1810 m->options = *options; 1831 m->options = *options;
1811 friendreq_init(&(m->fr), m->fr_c); 1832 friendreq_init(&(m->fr), m->fr_c);
1812 set_nospam(&(m->fr), random_int()); 1833 set_nospam(&(m->fr), random_int());
@@ -1826,6 +1847,10 @@ void kill_messenger(Messenger *m)
1826 1847
1827 uint32_t i; 1848 uint32_t i;
1828 1849
1850 if (m->tcp_server) {
1851 kill_TCP_server(m->tcp_server);
1852 }
1853
1829 kill_friend_connections(m->fr_c); 1854 kill_friend_connections(m->fr_c);
1830 kill_onion(m->onion); 1855 kill_onion(m->onion);
1831 kill_onion_announce(m->onion_a); 1856 kill_onion_announce(m->onion_a);
@@ -2261,6 +2286,15 @@ void do_messenger(Messenger *m)
2261 for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) { 2286 for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) {
2262 add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key); 2287 add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key);
2263 } 2288 }
2289
2290 if (m->tcp_server) {
2291 /* Add self tcp server. */
2292 IP_Port local_ip_port;
2293 local_ip_port.port = m->options.tcp_server_port;
2294 local_ip_port.ip.family = AF_INET;
2295 local_ip_port.ip.ip4.uint32 = INADDR_LOOPBACK;
2296 add_tcp_relay(m->net_crypto, local_ip_port, m->tcp_server->public_key);
2297 }
2264 } 2298 }
2265 2299
2266 unix_time_update(); 2300 unix_time_update();
@@ -2270,6 +2304,10 @@ void do_messenger(Messenger *m)
2270 do_DHT(m->dht); 2304 do_DHT(m->dht);
2271 } 2305 }
2272 2306
2307 if (m->tcp_server) {
2308 do_TCP_server(m->tcp_server);
2309 }
2310
2273 do_net_crypto(m->net_crypto); 2311 do_net_crypto(m->net_crypto);
2274 do_onion_client(m->onion_c); 2312 do_onion_client(m->onion_c);
2275 do_friend_connections(m->fr_c); 2313 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 {
70 uint8_t udp_disabled; 70 uint8_t udp_disabled;
71 TCP_Proxy_Info proxy_info; 71 TCP_Proxy_Info proxy_info;
72 uint16_t port_range[2]; 72 uint16_t port_range[2];
73 uint16_t tcp_server_port;
73} Messenger_Options; 74} Messenger_Options;
74 75
75 76
@@ -219,6 +220,7 @@ struct Messenger {
219 220
220 Friend_Connections *fr_c; 221 Friend_Connections *fr_c;
221 222
223 TCP_Server *tcp_server;
222 Friend_Requests fr; 224 Friend_Requests fr;
223 uint8_t name[MAX_NAME_LENGTH]; 225 uint8_t name[MAX_NAME_LENGTH];
224 uint16_t name_length; 226 uint16_t name_length;
@@ -727,6 +729,7 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const
727enum { 729enum {
728 MESSENGER_ERROR_NONE, 730 MESSENGER_ERROR_NONE,
729 MESSENGER_ERROR_PORT, 731 MESSENGER_ERROR_PORT,
732 MESSENGER_ERROR_TCP_SERVER,
730 MESSENGER_ERROR_OTHER 733 MESSENGER_ERROR_OTHER
731}; 734};
732 735
diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c
index de34e570..1656def0 100644
--- a/toxcore/friend_connection.c
+++ b/toxcore/friend_connection.c
@@ -158,6 +158,15 @@ int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_
158 if (!friend_con) 158 if (!friend_con)
159 return -1; 159 return -1;
160 160
161 /* Local ip and same pk means that they are hosting a TCP relay. */
162 if (Local_ip(ip_port.ip) && memcmp(friend_con->dht_temp_pk, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
163 if (friend_con->dht_ip_port.ip.family != 0) {
164 ip_port.ip = friend_con->dht_ip_port.ip;
165 } else {
166 friend_con->hosting_tcp_relay = 0;
167 }
168 }
169
161 unsigned int i; 170 unsigned int i;
162 171
163 uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS; 172 uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS;
@@ -268,6 +277,11 @@ static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
268 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1); 277 set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1);
269 friend_con->dht_ip_port = ip_port; 278 friend_con->dht_ip_port = ip_port;
270 friend_con->dht_ip_port_lastrecv = unix_time(); 279 friend_con->dht_ip_port_lastrecv = unix_time();
280
281 if (friend_con->hosting_tcp_relay) {
282 friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk);
283 friend_con->hosting_tcp_relay = 0;
284 }
271} 285}
272 286
273static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key) 287static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key)
@@ -317,6 +331,7 @@ static int handle_status(void *object, int number, uint8_t status)
317 331
318 friend_con->status = FRIENDCONN_STATUS_CONNECTING; 332 friend_con->status = FRIENDCONN_STATUS_CONNECTING;
319 friend_con->crypt_connection_id = -1; 333 friend_con->crypt_connection_id = -1;
334 friend_con->hosting_tcp_relay = 0;
320 } 335 }
321 336
322 if (call_cb) { 337 if (call_cb) {
diff --git a/toxcore/friend_connection.h b/toxcore/friend_connection.h
index baca4b76..32e947ac 100644
--- a/toxcore/friend_connection.h
+++ b/toxcore/friend_connection.h
@@ -96,6 +96,8 @@ typedef struct {
96 96
97 Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS]; 97 Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS];
98 uint16_t tcp_relay_counter; 98 uint16_t tcp_relay_counter;
99
100 _Bool hosting_tcp_relay;
99} Friend_Conn; 101} Friend_Conn;
100 102
101 103
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h
index 36ffe767..0e041e50 100644
--- a/toxcore/onion_announce.h
+++ b/toxcore/onion_announce.h
@@ -25,7 +25,7 @@
25 25
26#include "onion.h" 26#include "onion.h"
27 27
28#define ONION_ANNOUNCE_MAX_ENTRIES 64 28#define ONION_ANNOUNCE_MAX_ENTRIES 96
29#define ONION_ANNOUNCE_TIMEOUT 300 29#define ONION_ANNOUNCE_TIMEOUT 300
30#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES 30#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES
31 31
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index 5db426d3..6575f632 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -1204,7 +1204,7 @@ static void populate_path_nodes_tcp(Onion_Client *onion_c)
1204 unsigned int i; 1204 unsigned int i;
1205 1205
1206 for (i = 0; i < num_nodes; ++i) { 1206 for (i = 0; i < num_nodes; ++i) {
1207 onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key); 1207 onion_add_bs_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
1208 } 1208 }
1209} 1209}
1210 1210
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 848f81c7..de615768 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
152 m_options.udp_disabled = !options->udp_enabled; 152 m_options.udp_disabled = !options->udp_enabled;
153 m_options.port_range[0] = options->start_port; 153 m_options.port_range[0] = options->start_port;
154 m_options.port_range[1] = options->end_port; 154 m_options.port_range[1] = options->end_port;
155 m_options.tcp_server_port = options->tcp_port;
155 156
156 switch (options->proxy_type) { 157 switch (options->proxy_type) {
157 case TOX_PROXY_TYPE_HTTP: 158 case TOX_PROXY_TYPE_HTTP:
@@ -238,31 +239,6 @@ void tox_get_savedata(const Tox *tox, uint8_t *data)
238 } 239 }
239} 240}
240 241
241static int address_to_ip(Messenger *m, const char *address, IP_Port *ip_port, IP_Port *ip_port_v4)
242{
243 if (!addr_parse_ip(address, &ip_port->ip)) {
244 if (m->options.udp_disabled) { /* Disable DNS when udp is disabled. */
245 return -1;
246 }
247
248 IP *ip_extra = NULL;
249 ip_init(&ip_port->ip, m->options.ipv6enabled);
250
251 if (m->options.ipv6enabled && ip_port_v4) {
252 /* setup for getting BOTH: an IPv6 AND an IPv4 address */
253 ip_port->ip.family = AF_UNSPEC;
254 ip_reset(&ip_port_v4->ip);
255 ip_extra = &ip_port_v4->ip;
256 }
257
258 if (!addr_resolve(address, &ip_port->ip, ip_extra)) {
259 return -1;
260 }
261 }
262
263 return 0;
264}
265
266bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error) 242bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error)
267{ 243{
268 if (!address || !public_key) { 244 if (!address || !public_key) {
@@ -270,23 +246,53 @@ bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *
270 return 0; 246 return 0;
271 } 247 }
272 248
273 Messenger *m = tox; 249 if (port == 0) {
274 bool ret = tox_add_tcp_relay(tox, address, port, public_key, error); 250 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
251 return 0;
252 }
275 253
276 if (!ret) { 254 struct addrinfo *root, *info;
255
256 if (getaddrinfo(address, NULL, NULL, &root) != 0) {
257 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
277 return 0; 258 return 0;
278 } 259 }
279 260
280 if (m->options.udp_disabled) { 261 info = root;
281 return ret; 262
282 } else { /* DHT only works on UDP. */ 263 unsigned int count = 0;
283 if (DHT_bootstrap_from_address(m->dht, address, m->options.ipv6enabled, htons(port), public_key) == 0) { 264
284 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST); 265 do {
285 return 0; 266 IP_Port ip_port;
267 ip_port.port = htons(port);
268 ip_port.ip.family = info->ai_family;
269
270 if (info->ai_socktype && info->ai_socktype != SOCK_DGRAM) {
271 continue;
272 }
273
274 if (info->ai_family == AF_INET) {
275 ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
276 } else if (info->ai_family == AF_INET6) {
277 ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
278 } else {
279 continue;
286 } 280 }
287 281
282 Messenger *m = tox;
283 onion_add_bs_path_node(m->onion_c, ip_port, public_key);
284 DHT_bootstrap(m->dht, ip_port, public_key);
285 ++count;
286 } while ((info = info->ai_next));
287
288 freeaddrinfo(root);
289
290 if (count) {
288 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK); 291 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
289 return 1; 292 return 1;
293 } else {
294 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
295 return 0;
290 } 296 }
291} 297}
292 298
@@ -298,25 +304,53 @@ bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8
298 return 0; 304 return 0;
299 } 305 }
300 306
301 Messenger *m = tox;
302 IP_Port ip_port, ip_port_v4;
303
304 if (port == 0) { 307 if (port == 0) {
305 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT); 308 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
306 return 0; 309 return 0;
307 } 310 }
308 311
309 if (address_to_ip(m, address, &ip_port, &ip_port_v4) == -1) { 312 struct addrinfo *root, *info;
313
314 if (getaddrinfo(address, NULL, NULL, &root) != 0) {
310 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST); 315 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
311 return 0; 316 return 0;
312 } 317 }
313 318
314 ip_port.port = htons(port); 319 info = root;
315 add_tcp_relay(m->net_crypto, ip_port, public_key);
316 onion_add_bs_path_node(m->onion_c, ip_port, public_key); //TODO: move this
317 320
318 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK); 321 unsigned int count = 0;
319 return 1; 322
323 do {
324 IP_Port ip_port;
325 ip_port.port = htons(port);
326 ip_port.ip.family = info->ai_family;
327
328 if (info->ai_socktype && info->ai_socktype != SOCK_STREAM) {
329 continue;
330 }
331
332 if (info->ai_family == AF_INET) {
333 ip_port.ip.ip4.in_addr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
334 } else if (info->ai_family == AF_INET6) {
335 ip_port.ip.ip6.in6_addr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
336 } else {
337 continue;
338 }
339
340 Messenger *m = tox;
341 add_tcp_relay(m->net_crypto, ip_port, public_key);
342 ++count;
343 } while ((info = info->ai_next));
344
345 freeaddrinfo(root);
346
347 if (count) {
348 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
349 return 1;
350 } else {
351 SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
352 return 0;
353 }
320} 354}
321 355
322TOX_CONNECTION tox_self_get_connection_status(const Tox *tox) 356TOX_CONNECTION tox_self_get_connection_status(const Tox *tox)
@@ -1205,9 +1239,15 @@ uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
1205 1239
1206uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error) 1240uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
1207{ 1241{
1208 /* TCP server not yet implemented in clients. */ 1242 const Messenger *m = tox;
1209 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND); 1243
1210 return 0; 1244 if (m->tcp_server) {
1245 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
1246 return m->options.tcp_server_port;
1247 } else {
1248 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
1249 return 0;
1250 }
1211} 1251}
1212 1252
1213#include "tox_old_code.h" 1253#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 {
426 */ 426 */
427 uint16_t end_port; 427 uint16_t end_port;
428 428
429
430 /**
431 * The port to use for the TCP server. If 0, the tcp server is disabled.
432 */
433 uint16_t tcp_port;
434
429}; 435};
430 436
431 437