diff options
-rw-r--r-- | auto_tests/TCP_test.c | 1 | ||||
-rw-r--r-- | auto_tests/onion_test.c | 89 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | toxcore/Makefile.inc | 2 | ||||
-rw-r--r-- | toxcore/Messenger.c | 4 | ||||
-rw-r--r-- | toxcore/TCP_client.h | 6 | ||||
-rw-r--r-- | toxcore/TCP_connection.c | 722 | ||||
-rw-r--r-- | toxcore/TCP_connection.h | 88 | ||||
-rw-r--r-- | toxcore/TCP_server.c | 4 | ||||
-rw-r--r-- | toxcore/network.c | 11 | ||||
-rw-r--r-- | toxcore/network.h | 7 | ||||
-rw-r--r-- | toxcore/tox.c | 2 | ||||
-rw-r--r-- | toxcore/tox.h | 4 |
13 files changed, 922 insertions, 20 deletions
diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index e222cf01..a03baf92 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c | |||
@@ -419,6 +419,7 @@ START_TEST(test_client) | |||
419 | uint8_t f2_public_key[crypto_box_PUBLICKEYBYTES]; | 419 | uint8_t f2_public_key[crypto_box_PUBLICKEYBYTES]; |
420 | uint8_t f2_secret_key[crypto_box_SECRETKEYBYTES]; | 420 | uint8_t f2_secret_key[crypto_box_SECRETKEYBYTES]; |
421 | crypto_box_keypair(f2_public_key, f2_secret_key); | 421 | crypto_box_keypair(f2_public_key, f2_secret_key); |
422 | ip_port_tcp_s.port = htons(ports[rand() % NUM_PORTS]); | ||
422 | TCP_Client_Connection *conn2 = new_TCP_connection(ip_port_tcp_s, self_public_key, f2_public_key, f2_secret_key, 0); | 423 | TCP_Client_Connection *conn2 = new_TCP_connection(ip_port_tcp_s, self_public_key, f2_public_key, f2_secret_key, 0); |
423 | routing_response_handler(conn, response_callback, ((void *)conn) + 2); | 424 | routing_response_handler(conn, response_callback, ((void *)conn) + 2); |
424 | routing_status_handler(conn, status_callback, (void *)2); | 425 | routing_status_handler(conn, status_callback, (void *)2); |
diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index f27fefb8..31566471 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c | |||
@@ -275,7 +275,8 @@ Onions *new_onions(uint16_t port) | |||
275 | DHT *dht = new_DHT(new_networking(ip, port)); | 275 | DHT *dht = new_DHT(new_networking(ip, port)); |
276 | on->onion = new_onion(dht); | 276 | on->onion = new_onion(dht); |
277 | on->onion_a = new_onion_announce(dht); | 277 | on->onion_a = new_onion_announce(dht); |
278 | on->onion_c = new_onion_client(new_net_crypto(dht, 0)); | 278 | TCP_Proxy_Info inf = {0}; |
279 | on->onion_c = new_onion_client(new_net_crypto(dht, &inf)); | ||
279 | 280 | ||
280 | if (on->onion && on->onion_a && on->onion_c) | 281 | if (on->onion && on->onion_a && on->onion_c) |
281 | return on; | 282 | return on; |
@@ -294,15 +295,70 @@ void kill_onions(Onions *on) | |||
294 | { | 295 | { |
295 | Networking_Core *net = on->onion->dht->net; | 296 | Networking_Core *net = on->onion->dht->net; |
296 | DHT *dht = on->onion->dht; | 297 | DHT *dht = on->onion->dht; |
298 | Net_Crypto *c = on->onion_c->c; | ||
297 | kill_onion_client(on->onion_c); | 299 | kill_onion_client(on->onion_c); |
298 | kill_onion_announce(on->onion_a); | 300 | kill_onion_announce(on->onion_a); |
299 | kill_onion(on->onion); | 301 | kill_onion(on->onion); |
302 | kill_net_crypto(c); | ||
300 | kill_DHT(dht); | 303 | kill_DHT(dht); |
301 | kill_networking(net); | 304 | kill_networking(net); |
302 | free(on); | 305 | free(on); |
303 | } | 306 | } |
304 | 307 | ||
305 | #define NUM_ONIONS 50 | 308 | #define NUM_ONIONS 50 |
309 | #define NUM_FIRST 7 | ||
310 | #define NUM_LAST 37 | ||
311 | |||
312 | _Bool first_ip, last_ip; | ||
313 | void dht_ip_callback(void *object, int32_t number, IP_Port ip_port) | ||
314 | { | ||
315 | if (NUM_FIRST == number) { | ||
316 | first_ip = 1; | ||
317 | return; | ||
318 | } | ||
319 | |||
320 | if (NUM_LAST == number) { | ||
321 | last_ip = 1; | ||
322 | return; | ||
323 | } | ||
324 | |||
325 | ck_abort_msg("Error."); | ||
326 | } | ||
327 | |||
328 | _Bool first, last; | ||
329 | uint8_t first_dht_pk[crypto_box_PUBLICKEYBYTES]; | ||
330 | uint8_t last_dht_pk[crypto_box_PUBLICKEYBYTES]; | ||
331 | |||
332 | static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key) | ||
333 | { | ||
334 | Onions *on = object; | ||
335 | uint16_t count = 0; | ||
336 | int ret = DHT_addfriend(on->onion->dht, dht_public_key, &dht_ip_callback, object, number, &count); | ||
337 | ck_assert_msg(count == 1, "Count not 1"); | ||
338 | ck_assert_msg(ret == 0, "DHT_addfriend() did not return 0"); | ||
339 | |||
340 | if (NUM_FIRST == number && !first) { | ||
341 | first = 1; | ||
342 | |||
343 | if (memcmp(dht_public_key, last_dht_pk, crypto_box_PUBLICKEYBYTES) != 0) { | ||
344 | ck_abort_msg("Error wrong dht key."); | ||
345 | } | ||
346 | |||
347 | return; | ||
348 | } | ||
349 | |||
350 | if (NUM_LAST == number && !last) { | ||
351 | last = 1; | ||
352 | |||
353 | if (memcmp(dht_public_key, first_dht_pk, crypto_box_PUBLICKEYBYTES) != 0) { | ||
354 | ck_abort_msg("Error wrong dht key."); | ||
355 | } | ||
356 | |||
357 | return; | ||
358 | } | ||
359 | |||
360 | ck_abort_msg("Error."); | ||
361 | } | ||
306 | 362 | ||
307 | START_TEST(test_announce) | 363 | START_TEST(test_announce) |
308 | { | 364 | { |
@@ -340,6 +396,8 @@ START_TEST(test_announce) | |||
340 | c_sleep(50); | 396 | c_sleep(50); |
341 | } | 397 | } |
342 | 398 | ||
399 | printf("connected\n"); | ||
400 | |||
343 | for (i = 0; i < 25 * 2; ++i) { | 401 | for (i = 0; i < 25 * 2; ++i) { |
344 | for (j = 0; j < NUM_ONIONS; ++j) { | 402 | for (j = 0; j < NUM_ONIONS; ++j) { |
345 | do_onions(onions[j]); | 403 | do_onions(onions[j]); |
@@ -348,37 +406,40 @@ START_TEST(test_announce) | |||
348 | c_sleep(50); | 406 | c_sleep(50); |
349 | } | 407 | } |
350 | 408 | ||
351 | onion_addfriend(onions[7]->onion_c, onions[37]->onion_c->c->self_public_key); | 409 | memcpy(first_dht_pk, onions[NUM_FIRST]->onion->dht->self_public_key, crypto_box_PUBLICKEYBYTES); |
352 | int frnum = onion_addfriend(onions[37]->onion_c, onions[7]->onion_c->c->self_public_key); | 410 | memcpy(last_dht_pk, onions[NUM_LAST]->onion->dht->self_public_key, crypto_box_PUBLICKEYBYTES); |
411 | |||
412 | printf("adding friend\n"); | ||
413 | int frnum_f = onion_addfriend(onions[NUM_FIRST]->onion_c, onions[NUM_LAST]->onion_c->c->self_public_key); | ||
414 | int frnum = onion_addfriend(onions[NUM_LAST]->onion_c, onions[NUM_FIRST]->onion_c->c->self_public_key); | ||
415 | |||
416 | onion_dht_pk_callback(onions[NUM_FIRST]->onion_c, frnum_f, &dht_pk_callback, onions[NUM_FIRST], NUM_FIRST); | ||
417 | onion_dht_pk_callback(onions[NUM_LAST]->onion_c, frnum, &dht_pk_callback, onions[NUM_LAST], NUM_LAST); | ||
353 | 418 | ||
354 | int ok = -1; | 419 | int ok = -1; |
355 | 420 | ||
356 | IP_Port ip_port; | 421 | IP_Port ip_port; |
357 | 422 | ||
358 | while (ok == -1) { | 423 | while (!first || !last) { |
359 | for (i = 0; i < NUM_ONIONS; ++i) { | 424 | for (i = 0; i < NUM_ONIONS; ++i) { |
360 | networking_poll(onions[i]->onion->net); | 425 | do_onions(onions[i]); |
361 | do_onion_client(onions[i]->onion_c); | ||
362 | } | 426 | } |
363 | 427 | ||
364 | ok = onion_getfriendip(onions[37]->onion_c, frnum, &ip_port); | ||
365 | |||
366 | c_sleep(50); | 428 | c_sleep(50); |
367 | } | 429 | } |
368 | 430 | ||
369 | printf("id discovered\n"); | 431 | printf("Waiting for ips\n"); |
370 | 432 | ||
371 | while (ok != 1) { | 433 | while (!first_ip || !last_ip) { |
372 | for (i = 0; i < NUM_ONIONS; ++i) { | 434 | for (i = 0; i < NUM_ONIONS; ++i) { |
373 | do_onions(onions[i]); | 435 | do_onions(onions[i]); |
374 | } | 436 | } |
375 | 437 | ||
376 | ok = onion_getfriendip(onions[37]->onion_c, frnum, &ip_port); | ||
377 | |||
378 | c_sleep(50); | 438 | c_sleep(50); |
379 | } | 439 | } |
380 | 440 | ||
381 | ck_assert_msg(ip_port.port == onions[7]->onion->net->port, "Port in returned ip not correct."); | 441 | onion_getfriendip(onions[NUM_LAST]->onion_c, frnum, &ip_port); |
442 | ck_assert_msg(ip_port.port == onions[NUM_FIRST]->onion->net->port, "Port in returned ip not correct."); | ||
382 | 443 | ||
383 | for (i = 0; i < NUM_ONIONS; ++i) { | 444 | for (i = 0; i < NUM_ONIONS; ++i) { |
384 | kill_onions(onions[i]); | 445 | kill_onions(onions[i]); |
@@ -391,7 +452,7 @@ Suite *onion_suite(void) | |||
391 | Suite *s = suite_create("Onion"); | 452 | Suite *s = suite_create("Onion"); |
392 | 453 | ||
393 | DEFTESTCASE_SLOW(basic, 5); | 454 | DEFTESTCASE_SLOW(basic, 5); |
394 | //DEFTESTCASE_SLOW(announce, 50); //TODO: fix test. | 455 | DEFTESTCASE_SLOW(announce, 70); |
395 | return s; | 456 | return s; |
396 | } | 457 | } |
397 | 458 | ||
diff --git a/configure.ac b/configure.ac index e43e8f78..a100f344 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -472,7 +472,7 @@ AC_C_BIGENDIAN | |||
472 | # Checks for library functions. | 472 | # Checks for library functions. |
473 | AC_FUNC_FORK | 473 | AC_FUNC_FORK |
474 | AC_CHECK_FUNCS([gettimeofday memset socket strchr malloc]) | 474 | AC_CHECK_FUNCS([gettimeofday memset socket strchr malloc]) |
475 | if (test "x$WIN32" != "xyes") && (test "x$MACH" != "xyes") && (test "x$DISABLE_RT" != "xyes"); then | 475 | if (test "x$WIN32" != "xyes") && (test "x$MACH" != "xyes") && (test "x${host_os#*openbsd}" == "x$host_os") && (test "x$DISABLE_RT" != "xyes"); then |
476 | AC_CHECK_LIB(rt, clock_gettime, | 476 | AC_CHECK_LIB(rt, clock_gettime, |
477 | [ | 477 | [ |
478 | RT_LIBS="-lrt" | 478 | RT_LIBS="-lrt" |
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 9afe7791..9fb910fc 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc | |||
@@ -46,6 +46,8 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ | |||
46 | ../toxcore/TCP_client.c \ | 46 | ../toxcore/TCP_client.c \ |
47 | ../toxcore/TCP_server.h \ | 47 | ../toxcore/TCP_server.h \ |
48 | ../toxcore/TCP_server.c \ | 48 | ../toxcore/TCP_server.c \ |
49 | ../toxcore/TCP_connection.h \ | ||
50 | ../toxcore/TCP_connection.c \ | ||
49 | ../toxcore/list.c \ | 51 | ../toxcore/list.c \ |
50 | ../toxcore/list.h \ | 52 | ../toxcore/list.h \ |
51 | ../toxcore/misc_tools.h | 53 | ../toxcore/misc_tools.h |
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 23c41120..fefc3b17 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -172,7 +172,7 @@ static int send_online_packet(Messenger *m, int32_t friendnumber) | |||
172 | m->friendlist[friendnumber].friendcon_id), &packet, sizeof(packet), 0) != -1; | 172 | m->friendlist[friendnumber].friendcon_id), &packet, sizeof(packet), 0) != -1; |
173 | } | 173 | } |
174 | 174 | ||
175 | static int send_offine_packet(Messenger *m, int friendcon_id) | 175 | static int send_offline_packet(Messenger *m, int friendcon_id) |
176 | { | 176 | { |
177 | uint8_t packet = PACKET_ID_OFFLINE; | 177 | uint8_t packet = PACKET_ID_OFFLINE; |
178 | return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), &packet, | 178 | return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), &packet, |
@@ -408,7 +408,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber) | |||
408 | kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id); | 408 | kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id); |
409 | 409 | ||
410 | if (friend_con_connected(m->fr_c, m->friendlist[friendnumber].friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { | 410 | if (friend_con_connected(m->fr_c, m->friendlist[friendnumber].friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { |
411 | send_offine_packet(m, m->friendlist[friendnumber].friendcon_id); | 411 | send_offline_packet(m, m->friendlist[friendnumber].friendcon_id); |
412 | } | 412 | } |
413 | 413 | ||
414 | memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); | 414 | memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); |
diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index e37a4ee0..d4d18a4b 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h | |||
@@ -78,8 +78,10 @@ typedef struct { | |||
78 | uint64_t ping_response_id; | 78 | uint64_t ping_response_id; |
79 | uint64_t ping_request_id; | 79 | uint64_t ping_request_id; |
80 | 80 | ||
81 | //TODO: remove | ||
81 | void *net_crypto_pointer; | 82 | void *net_crypto_pointer; |
82 | uint32_t net_crypto_location; | 83 | uint32_t net_crypto_location; |
84 | |||
83 | struct { | 85 | struct { |
84 | uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */ | 86 | uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */ |
85 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; | 87 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; |
@@ -96,6 +98,10 @@ typedef struct { | |||
96 | 98 | ||
97 | int (*onion_callback)(void *object, const uint8_t *data, uint16_t length); | 99 | int (*onion_callback)(void *object, const uint8_t *data, uint16_t length); |
98 | void *onion_callback_object; | 100 | void *onion_callback_object; |
101 | |||
102 | /* Can be used by user. */ | ||
103 | void *custom_object; | ||
104 | uint32_t custom_uint; | ||
99 | } TCP_Client_Connection; | 105 | } TCP_Client_Connection; |
100 | 106 | ||
101 | /* Create new TCP connection to ip_port/public_key | 107 | /* Create new TCP connection to ip_port/public_key |
diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c new file mode 100644 index 00000000..ddcbd1d8 --- /dev/null +++ b/toxcore/TCP_connection.c | |||
@@ -0,0 +1,722 @@ | |||
1 | /* TCP_connection.c | ||
2 | * | ||
3 | * Handles TCP relay connections between two Tox clients. | ||
4 | * | ||
5 | * Copyright (C) 2015 Tox project All Rights Reserved. | ||
6 | * | ||
7 | * This file is part of Tox. | ||
8 | * | ||
9 | * Tox is free software: you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation, either version 3 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * Tox is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifdef HAVE_CONFIG_H | ||
25 | #include "config.h" | ||
26 | #endif | ||
27 | |||
28 | #include "TCP_connection.h" | ||
29 | |||
30 | /* Set the size of the array to num. | ||
31 | * | ||
32 | * return -1 if realloc fails. | ||
33 | * return 0 if it succeeds. | ||
34 | */ | ||
35 | #define realloc_tox_array(array, element_size, num, temp_pointer) (num ? (temp_pointer = realloc(array, num * element_size), temp_pointer ? (array = temp_pointer, 0) : (-1) ) : (free(array), array = NULL, 0)) | ||
36 | |||
37 | |||
38 | /* return 1 if the connections_number is not valid. | ||
39 | * return 0 if the connections_number is valid. | ||
40 | */ | ||
41 | static _Bool connections_number_not_valid(const TCP_Connections *tcp_c, int connections_number) | ||
42 | { | ||
43 | if ((unsigned int)connections_number >= tcp_c->connections_length) | ||
44 | return 1; | ||
45 | |||
46 | if (tcp_c->connections == NULL) | ||
47 | return 1; | ||
48 | |||
49 | if (tcp_c->connections[connections_number].status == TCP_CONN_NONE) | ||
50 | return 1; | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | /* return 1 if the tcp_connections_number is not valid. | ||
56 | * return 0 if the tcp_connections_number is valid. | ||
57 | */ | ||
58 | static _Bool tcp_connections_number_not_valid(const TCP_Connections *tcp_c, int tcp_connections_number) | ||
59 | { | ||
60 | if ((unsigned int)tcp_connections_number >= tcp_c->tcp_connections_length) | ||
61 | return 1; | ||
62 | |||
63 | if (tcp_c->tcp_connections == NULL) | ||
64 | return 1; | ||
65 | |||
66 | if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_NONE) | ||
67 | return 1; | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /* Create a new empty connection. | ||
73 | * | ||
74 | * return -1 on failure. | ||
75 | * return connections_number on success. | ||
76 | */ | ||
77 | static int create_connection(TCP_Connections *tcp_c) | ||
78 | { | ||
79 | uint32_t i; | ||
80 | |||
81 | for (i = 0; i < tcp_c->connections_length; ++i) { | ||
82 | if (tcp_c->connections[i].status == TCP_CONN_NONE) | ||
83 | return i; | ||
84 | } | ||
85 | |||
86 | int id = -1; | ||
87 | |||
88 | TCP_Connection_to *temp_pointer; | ||
89 | |||
90 | if (realloc_tox_array(tcp_c->connections, sizeof(TCP_Connection_to), tcp_c->connections_length + 1, | ||
91 | temp_pointer) == 0) { | ||
92 | id = tcp_c->connections_length; | ||
93 | ++tcp_c->connections_length; | ||
94 | memset(&(tcp_c->connections[id]), 0, sizeof(TCP_Connection_to)); | ||
95 | } | ||
96 | |||
97 | return id; | ||
98 | } | ||
99 | |||
100 | /* Create a new empty tcp connection. | ||
101 | * | ||
102 | * return -1 on failure. | ||
103 | * return tcp_connections_number on success. | ||
104 | */ | ||
105 | static int create_tcp_connection(TCP_Connections *tcp_c) | ||
106 | { | ||
107 | uint32_t i; | ||
108 | |||
109 | for (i = 0; i < tcp_c->tcp_connections_length; ++i) { | ||
110 | if (tcp_c->tcp_connections[i].status == TCP_CONN_NONE) | ||
111 | return i; | ||
112 | } | ||
113 | |||
114 | int id = -1; | ||
115 | |||
116 | TCP_con *temp_pointer; | ||
117 | |||
118 | if (realloc_tox_array(tcp_c->tcp_connections, sizeof(TCP_con), tcp_c->tcp_connections_length + 1, temp_pointer) == 0) { | ||
119 | id = tcp_c->tcp_connections_length; | ||
120 | ++tcp_c->tcp_connections_length; | ||
121 | memset(&(tcp_c->tcp_connections[id]), 0, sizeof(TCP_con)); | ||
122 | } | ||
123 | |||
124 | return id; | ||
125 | } | ||
126 | |||
127 | /* Wipe a connection. | ||
128 | * | ||
129 | * return -1 on failure. | ||
130 | * return 0 on success. | ||
131 | */ | ||
132 | static int wipe_connection(TCP_Connections *tcp_c, int connections_number) | ||
133 | { | ||
134 | if (connections_number_not_valid(tcp_c, connections_number)) | ||
135 | return -1; | ||
136 | |||
137 | uint32_t i; | ||
138 | memset(&(tcp_c->connections[connections_number]), 0 , sizeof(TCP_Connection_to)); | ||
139 | |||
140 | for (i = tcp_c->connections_length; i != 0; --i) { | ||
141 | if (tcp_c->connections[i - 1].status != TCP_CONN_NONE) | ||
142 | break; | ||
143 | } | ||
144 | |||
145 | if (tcp_c->connections_length != i) { | ||
146 | tcp_c->connections_length = i; | ||
147 | TCP_Connection_to *temp_pointer; | ||
148 | realloc_tox_array(tcp_c->connections, sizeof(TCP_Connection_to), tcp_c->connections_length, temp_pointer); | ||
149 | } | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | /* Wipe a connection. | ||
155 | * | ||
156 | * return -1 on failure. | ||
157 | * return 0 on success. | ||
158 | */ | ||
159 | static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_number) | ||
160 | { | ||
161 | if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) | ||
162 | return -1; | ||
163 | |||
164 | uint32_t i; | ||
165 | memset(&(tcp_c->tcp_connections[tcp_connections_number]), 0 , sizeof(TCP_con)); | ||
166 | |||
167 | for (i = tcp_c->tcp_connections_length; i != 0; --i) { | ||
168 | if (tcp_c->tcp_connections[i - 1].status != TCP_CONN_NONE) | ||
169 | break; | ||
170 | } | ||
171 | |||
172 | if (tcp_c->tcp_connections_length != i) { | ||
173 | tcp_c->tcp_connections_length = i; | ||
174 | TCP_con *temp_pointer; | ||
175 | realloc_tox_array(tcp_c->tcp_connections, sizeof(TCP_con), tcp_c->tcp_connections_length, temp_pointer); | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static TCP_Connection_to *get_connection(const TCP_Connections *tcp_c, int connections_number) | ||
182 | { | ||
183 | if (connections_number_not_valid(tcp_c, connections_number)) | ||
184 | return 0; | ||
185 | |||
186 | return &tcp_c->connections[connections_number]; | ||
187 | } | ||
188 | |||
189 | static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connections_number) | ||
190 | { | ||
191 | if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) | ||
192 | return 0; | ||
193 | |||
194 | return &tcp_c->tcp_connections[tcp_connections_number]; | ||
195 | } | ||
196 | |||
197 | /* Send a packet to the TCP connection. | ||
198 | * | ||
199 | * return -1 on failure. | ||
200 | * return 0 on success. | ||
201 | */ | ||
202 | int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, uint8_t *packet, uint16_t length) | ||
203 | { | ||
204 | TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); | ||
205 | |||
206 | if (!con_to) { | ||
207 | return -1; | ||
208 | } | ||
209 | |||
210 | unsigned int i; | ||
211 | int ret = -1; | ||
212 | |||
213 | for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { | ||
214 | uint32_t tcp_con_num = con_to->connections[i].tcp_connection; | ||
215 | |||
216 | //TODO | ||
217 | if (tcp_con_num) { | ||
218 | tcp_con_num -= 1; | ||
219 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_con_num); | ||
220 | |||
221 | if (!tcp_con) { | ||
222 | continue; | ||
223 | } | ||
224 | |||
225 | // ret = send_data(c->tcp_connections[tcp_index], conn->con_number_tcp[tcp_index], packet, length); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id, | ||
233 | const uint8_t *data, uint16_t length), void *object) | ||
234 | { | ||
235 | tcp_c->tcp_data_callback = tcp_data_callback; | ||
236 | tcp_c->tcp_data_callback_object = object; | ||
237 | } | ||
238 | |||
239 | /* Find the TCP connection with public_key. | ||
240 | * | ||
241 | * return connections_number on success. | ||
242 | * return -1 on failure. | ||
243 | */ | ||
244 | static int find_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key) | ||
245 | { | ||
246 | unsigned int i; | ||
247 | |||
248 | for (i = 0; i < tcp_c->connections_length; ++i) { | ||
249 | TCP_Connection_to *con_to = get_connection(tcp_c, i); | ||
250 | |||
251 | if (con_to) { | ||
252 | if (memcmp(con_to->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
253 | return i; | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | |||
258 | return -1; | ||
259 | } | ||
260 | |||
261 | /* Find the TCP connection to a relay with relay_pk. | ||
262 | * | ||
263 | * return connections_number on success. | ||
264 | * return -1 on failure. | ||
265 | */ | ||
266 | static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *relay_pk) | ||
267 | { | ||
268 | unsigned int i; | ||
269 | |||
270 | for (i = 0; i < tcp_c->tcp_connections_length; ++i) { | ||
271 | TCP_con *tcp_con = get_tcp_connection(tcp_c, i); | ||
272 | |||
273 | if (tcp_con) { | ||
274 | if (memcmp(tcp_con->connection->public_key, relay_pk, crypto_box_PUBLICKEYBYTES) == 0) { | ||
275 | return i; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | return -1; | ||
281 | } | ||
282 | |||
283 | /* Create a new TCP connection to public_key. | ||
284 | * | ||
285 | * id is the id in the callbacks for that connection. | ||
286 | * | ||
287 | * return connections_number on success. | ||
288 | * return -1 on failure. | ||
289 | */ | ||
290 | int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id) | ||
291 | { | ||
292 | if (find_tcp_connection_to(tcp_c, public_key) != -1) | ||
293 | return -1; | ||
294 | |||
295 | int connections_number = create_connection(tcp_c); | ||
296 | |||
297 | if (connections_number == -1) | ||
298 | return -1; | ||
299 | |||
300 | TCP_Connection_to *con_to = &tcp_c->connections[connections_number]; | ||
301 | |||
302 | con_to->status = TCP_CONN_VALID; | ||
303 | memcpy(con_to->public_key, public_key, crypto_box_PUBLICKEYBYTES); | ||
304 | con_to->id = id; | ||
305 | |||
306 | return connections_number; | ||
307 | } | ||
308 | |||
309 | /* return 0 on success. | ||
310 | * return -1 on failure. | ||
311 | */ | ||
312 | int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number) | ||
313 | { | ||
314 | TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); | ||
315 | |||
316 | if (!con_to) | ||
317 | return -1; | ||
318 | |||
319 | //TODO | ||
320 | return wipe_connection(tcp_c, connections_number); | ||
321 | } | ||
322 | |||
323 | static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, int tcp_connections_number) | ||
324 | { | ||
325 | unsigned int i; | ||
326 | |||
327 | for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { | ||
328 | if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) { | ||
329 | return 1; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | /* return index on success. | ||
337 | * return -1 on failure. | ||
338 | */ | ||
339 | static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, int tcp_connections_number) | ||
340 | { | ||
341 | unsigned int i; | ||
342 | |||
343 | if (tcp_connection_in_conn(con_to, tcp_connections_number)) | ||
344 | return -1; | ||
345 | |||
346 | for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { | ||
347 | if (con_to->connections[i].tcp_connection == 0) { | ||
348 | con_to->connections[i].tcp_connection = tcp_connections_number + 1; | ||
349 | con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE; | ||
350 | con_to->connections[i].connection_id = 0; | ||
351 | return i; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | return -1; | ||
356 | } | ||
357 | |||
358 | /* return index on success. | ||
359 | * return -1 on failure. | ||
360 | */ | ||
361 | static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, int tcp_connections_number) | ||
362 | { | ||
363 | unsigned int i; | ||
364 | |||
365 | for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { | ||
366 | if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) { | ||
367 | con_to->connections[i].tcp_connection = 0; | ||
368 | con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE; | ||
369 | con_to->connections[i].connection_id = 0; | ||
370 | return i; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | return -1; | ||
375 | } | ||
376 | |||
377 | /* return index on success. | ||
378 | * return -1 on failure. | ||
379 | */ | ||
380 | static int set_tcp_connection_status(TCP_Connection_to *con_to, int tcp_connections_number, unsigned int status, | ||
381 | uint8_t connection_id) | ||
382 | { | ||
383 | unsigned int i; | ||
384 | |||
385 | for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { | ||
386 | if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) { | ||
387 | con_to->connections[i].status = status; | ||
388 | con_to->connections[i].connection_id = connection_id; | ||
389 | return i; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | return -1; | ||
394 | } | ||
395 | |||
396 | /* Kill a TCP relay connection. | ||
397 | * | ||
398 | * return 0 on success. | ||
399 | * return -1 on failure. | ||
400 | */ | ||
401 | static int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number) | ||
402 | { | ||
403 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
404 | |||
405 | if (!tcp_con) | ||
406 | return -1; | ||
407 | |||
408 | unsigned int i; | ||
409 | |||
410 | for (i = 0; i < tcp_c->connections_length; ++i) { | ||
411 | TCP_Connection_to *con_to = get_connection(tcp_c, i); | ||
412 | |||
413 | if (con_to) { | ||
414 | rm_tcp_connection_from_conn(con_to, tcp_connections_number); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | kill_TCP_connection(tcp_con->connection); | ||
419 | |||
420 | return wipe_tcp_connection(tcp_c, tcp_connections_number); | ||
421 | } | ||
422 | |||
423 | /* Send a TCP routing request. | ||
424 | * | ||
425 | * return 0 on success. | ||
426 | * return -1 on failure. | ||
427 | */ | ||
428 | static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connections_number, uint8_t *public_key) | ||
429 | { | ||
430 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
431 | |||
432 | if (!tcp_con) | ||
433 | return -1; | ||
434 | |||
435 | if (send_routing_request(tcp_con->connection, public_key) != 1) | ||
436 | return -1; | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key) | ||
442 | { | ||
443 | TCP_Client_Connection *TCP_client_con = object; | ||
444 | TCP_Connections *tcp_c = TCP_client_con->custom_object; | ||
445 | |||
446 | unsigned int tcp_connections_number = TCP_client_con->custom_uint; | ||
447 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
448 | |||
449 | if (!tcp_con) | ||
450 | return -1; | ||
451 | |||
452 | int connections_number = find_tcp_connection_to(tcp_c, public_key); | ||
453 | |||
454 | if (connections_number == -1) | ||
455 | return -1; | ||
456 | |||
457 | set_tcp_connection_number(tcp_con->connection, connection_id, connections_number); | ||
458 | |||
459 | TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); | ||
460 | |||
461 | if (con_to == NULL) | ||
462 | return -1; | ||
463 | |||
464 | if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) | ||
465 | return -1; | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) | ||
471 | { | ||
472 | TCP_Client_Connection *TCP_client_con = object; | ||
473 | TCP_Connections *tcp_c = TCP_client_con->custom_object; | ||
474 | |||
475 | unsigned int tcp_connections_number = TCP_client_con->custom_uint; | ||
476 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
477 | TCP_Connection_to *con_to = get_connection(tcp_c, number); | ||
478 | |||
479 | if (!con_to || !tcp_con) | ||
480 | return -1; | ||
481 | |||
482 | if (status == 1) { | ||
483 | if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) | ||
484 | return -1; | ||
485 | |||
486 | } else if (status == 2) { | ||
487 | if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1) | ||
488 | return -1; | ||
489 | |||
490 | } | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length) | ||
496 | { | ||
497 | |||
498 | if (length == 0) | ||
499 | return -1; | ||
500 | |||
501 | TCP_Client_Connection *TCP_client_con = object; | ||
502 | TCP_Connections *tcp_c = TCP_client_con->custom_object; | ||
503 | |||
504 | unsigned int tcp_connections_number = TCP_client_con->custom_uint; | ||
505 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
506 | |||
507 | if (!tcp_con) | ||
508 | return -1; | ||
509 | |||
510 | TCP_Connection_to *con_to = get_connection(tcp_c, number); | ||
511 | |||
512 | if (!con_to) | ||
513 | return -1; | ||
514 | |||
515 | if (tcp_c->tcp_data_callback) | ||
516 | tcp_c->tcp_data_callback(tcp_c->tcp_data_callback_object, con_to->id, data, length); | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static int tcp_oob_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length) | ||
522 | { | ||
523 | if (length == 0) | ||
524 | return -1; | ||
525 | |||
526 | TCP_Client_Connection *TCP_client_con = object; | ||
527 | TCP_Connections *tcp_c = TCP_client_con->custom_object; | ||
528 | |||
529 | unsigned int tcp_connections_number = TCP_client_con->custom_uint; | ||
530 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
531 | |||
532 | if (!tcp_con) | ||
533 | return -1; | ||
534 | |||
535 | uint8_t relay_pk[crypto_box_PUBLICKEYBYTES]; | ||
536 | memcpy(relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES); | ||
537 | |||
538 | if (tcp_c->tcp_oob_callback) | ||
539 | tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, relay_pk, data, length); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int tcp_onion_callback(void *object, const uint8_t *data, uint16_t length) | ||
545 | { | ||
546 | TCP_Connections *tcp_c = object; | ||
547 | |||
548 | if (tcp_c->tcp_onion_callback) | ||
549 | tcp_c->tcp_onion_callback(tcp_c->tcp_onion_callback_object, data, length); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | /* Set callbacks for the TCP relay connection. | ||
555 | * | ||
556 | * return 0 on success. | ||
557 | * return -1 on failure. | ||
558 | */ | ||
559 | static int tcp_relay_set_callbacks(TCP_Connections *tcp_c, int tcp_connections_number) | ||
560 | { | ||
561 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
562 | |||
563 | if (!tcp_con) | ||
564 | return -1; | ||
565 | |||
566 | TCP_Client_Connection *con = tcp_con->connection; | ||
567 | |||
568 | con->custom_object = tcp_c; | ||
569 | con->custom_uint = tcp_connections_number; | ||
570 | onion_response_handler(con, &tcp_onion_callback, tcp_c); | ||
571 | routing_response_handler(con, &tcp_response_callback, con); | ||
572 | routing_status_handler(con, &tcp_status_callback, con); | ||
573 | routing_data_handler(con, &tcp_data_callback, con); | ||
574 | oob_data_handler(con, &tcp_oob_callback, con); | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_number) | ||
580 | { | ||
581 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
582 | |||
583 | if (!tcp_con) | ||
584 | return -1; | ||
585 | |||
586 | unsigned int i; | ||
587 | |||
588 | for (i = 0; i < tcp_c->connections_length; ++i) { | ||
589 | TCP_Connection_to *con_to = get_connection(tcp_c, i); | ||
590 | |||
591 | if (con_to) { | ||
592 | if (tcp_connection_in_conn(con_to, tcp_connections_number)) { | ||
593 | send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key); | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | |||
598 | tcp_relay_set_callbacks(tcp_c, tcp_connections_number); | ||
599 | tcp_con->status = TCP_CONN_CONNECTED; | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int add_tcp_relay(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk) | ||
604 | { | ||
605 | int tcp_connections_number = create_tcp_connection(tcp_c); | ||
606 | |||
607 | if (tcp_connections_number == -1) | ||
608 | return -1; | ||
609 | |||
610 | TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number]; | ||
611 | |||
612 | |||
613 | tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->dht->self_public_key, tcp_c->dht->self_secret_key, | ||
614 | &tcp_c->proxy_info); | ||
615 | |||
616 | if (!tcp_con->connection) | ||
617 | return -1; | ||
618 | |||
619 | tcp_con->status = TCP_CONN_VALID; | ||
620 | |||
621 | return tcp_connections_number; | ||
622 | } | ||
623 | |||
624 | /* Add a TCP relay tied to a connection. | ||
625 | * | ||
626 | * return 0 on success. | ||
627 | * return -1 on failure. | ||
628 | */ | ||
629 | int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_Port ip_port, const uint8_t *relay_pk) | ||
630 | { | ||
631 | TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); | ||
632 | |||
633 | if (!con_to) | ||
634 | return -1; | ||
635 | |||
636 | int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk); | ||
637 | |||
638 | if (tcp_connections_number != -1) { | ||
639 | if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) | ||
640 | return -1; | ||
641 | |||
642 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
643 | |||
644 | if (!tcp_con) | ||
645 | return -1; | ||
646 | |||
647 | ++tcp_con->lock_count; | ||
648 | |||
649 | if (tcp_con->status == TCP_CONN_CONNECTED) { | ||
650 | send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key); | ||
651 | } | ||
652 | |||
653 | return 0; | ||
654 | } else { | ||
655 | int tcp_connections_number = add_tcp_relay(tcp_c, ip_port, relay_pk); | ||
656 | |||
657 | if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) { | ||
658 | return -1; | ||
659 | } | ||
660 | |||
661 | TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); | ||
662 | |||
663 | if (!tcp_con) | ||
664 | return -1; | ||
665 | |||
666 | ++tcp_con->lock_count; | ||
667 | return 0; | ||
668 | } | ||
669 | } | ||
670 | |||
671 | |||
672 | TCP_Connections *new_tcp_connections(DHT *dht) | ||
673 | { | ||
674 | if (dht == NULL) | ||
675 | return NULL; | ||
676 | |||
677 | TCP_Connections *temp = calloc(1, sizeof(TCP_Connections)); | ||
678 | |||
679 | if (temp == NULL) | ||
680 | return NULL; | ||
681 | |||
682 | temp->dht = dht; | ||
683 | return temp; | ||
684 | } | ||
685 | |||
686 | static void do_tcp_conns(TCP_Connections *tcp_c) | ||
687 | { | ||
688 | unsigned int i; | ||
689 | |||
690 | for (i = 0; i < tcp_c->tcp_connections_length; ++i) { | ||
691 | TCP_con *tcp_con = get_tcp_connection(tcp_c, i); | ||
692 | |||
693 | if (tcp_con) { | ||
694 | do_TCP_connection(tcp_con->connection); | ||
695 | |||
696 | if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) { | ||
697 | kill_tcp_relay_connection(tcp_c, i); | ||
698 | continue; | ||
699 | } | ||
700 | |||
701 | if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) { | ||
702 | tcp_relay_on_online(tcp_c, i); | ||
703 | } | ||
704 | } | ||
705 | } | ||
706 | } | ||
707 | |||
708 | |||
709 | void do_tcp_connections(TCP_Connections *tcp_c) | ||
710 | { | ||
711 | //TODO kill unused conns | ||
712 | |||
713 | do_tcp_conns(tcp_c); | ||
714 | } | ||
715 | |||
716 | void kill_tcp_connections(TCP_Connections *tcp_c) | ||
717 | { | ||
718 | //TODO | ||
719 | free(tcp_c); | ||
720 | } | ||
721 | |||
722 | |||
diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h new file mode 100644 index 00000000..94213814 --- /dev/null +++ b/toxcore/TCP_connection.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* TCP_connection.h | ||
2 | * | ||
3 | * Handles TCP relay connections between two Tox clients. | ||
4 | * | ||
5 | * Copyright (C) 2015 Tox project All Rights Reserved. | ||
6 | * | ||
7 | * This file is part of Tox. | ||
8 | * | ||
9 | * Tox is free software: you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation, either version 3 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * Tox is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef TCP_CONNECTION_H | ||
25 | #define TCP_CONNECTION_H | ||
26 | |||
27 | #include "TCP_client.h" | ||
28 | |||
29 | #define TCP_CONN_NONE 0 | ||
30 | #define TCP_CONN_VALID 1 | ||
31 | #define TCP_CONN_CONNECTED 2 | ||
32 | |||
33 | #define TCP_CONNECTIONS_STATUS_NONE 0 | ||
34 | #define TCP_CONNECTIONS_STATUS_REGISTERED 1 | ||
35 | #define TCP_CONNECTIONS_STATUS_ONLINE 2 | ||
36 | |||
37 | #define MAX_FRIEND_TCP_CONNECTIONS 4 | ||
38 | |||
39 | |||
40 | typedef struct { | ||
41 | uint8_t status; | ||
42 | uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ | ||
43 | |||
44 | struct { | ||
45 | uint32_t tcp_connection; | ||
46 | unsigned int status; | ||
47 | unsigned int connection_id; | ||
48 | } connections[MAX_FRIEND_TCP_CONNECTIONS]; | ||
49 | |||
50 | int id; /* id used in callbacks. */ | ||
51 | } TCP_Connection_to; | ||
52 | |||
53 | typedef struct { | ||
54 | uint8_t status; | ||
55 | TCP_Client_Connection *connection; | ||
56 | uint32_t lock_count; | ||
57 | } TCP_con; | ||
58 | |||
59 | typedef struct { | ||
60 | DHT *dht; | ||
61 | |||
62 | TCP_Connection_to *connections; | ||
63 | uint32_t connections_length; /* Length of connections array. */ | ||
64 | |||
65 | TCP_con *tcp_connections; | ||
66 | uint32_t tcp_connections_length; /* Length of tcp_connections array. */ | ||
67 | |||
68 | int (*tcp_data_callback)(void *object, int id, const uint8_t *data, uint16_t length); | ||
69 | void *tcp_data_callback_object; | ||
70 | |||
71 | int (*tcp_oob_callback)(void *object, const uint8_t *public_key, const uint8_t *relay_pk, const uint8_t *data, | ||
72 | uint16_t length); | ||
73 | void *tcp_oob_callback_object; | ||
74 | |||
75 | int (*tcp_onion_callback)(void *object, const uint8_t *data, uint16_t length); | ||
76 | void *tcp_onion_callback_object; | ||
77 | |||
78 | TCP_Proxy_Info proxy_info; | ||
79 | } TCP_Connections; | ||
80 | |||
81 | |||
82 | |||
83 | TCP_Connections *new_tcp_connections(DHT *dht); | ||
84 | void do_tcp_connections(TCP_Connections *tcp_c); | ||
85 | void kill_tcp_connections(TCP_Connections *tcp_c); | ||
86 | |||
87 | #endif | ||
88 | |||
diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index d7401de8..f07df2c6 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c | |||
@@ -925,6 +925,10 @@ static sock_t new_listening_TCP_socket(int family, uint16_t port) | |||
925 | ok = set_socket_dualstack(sock); | 925 | ok = set_socket_dualstack(sock); |
926 | } | 926 | } |
927 | 927 | ||
928 | if (ok) { | ||
929 | ok = set_socket_reuseaddr(sock); | ||
930 | } | ||
931 | |||
928 | ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0); | 932 | ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0); |
929 | 933 | ||
930 | if (!ok) { | 934 | if (!ok) { |
diff --git a/toxcore/network.c b/toxcore/network.c index d974ddc2..b3df3fbd 100644 --- a/toxcore/network.c +++ b/toxcore/network.c | |||
@@ -172,6 +172,17 @@ int set_socket_nosigpipe(sock_t sock) | |||
172 | #endif | 172 | #endif |
173 | } | 173 | } |
174 | 174 | ||
175 | /* Enable SO_REUSEADDR on socket. | ||
176 | * | ||
177 | * return 1 on success | ||
178 | * return 0 on failure | ||
179 | */ | ||
180 | int set_socket_reuseaddr(sock_t sock) | ||
181 | { | ||
182 | int set = 1; | ||
183 | return (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)) == 0); | ||
184 | } | ||
185 | |||
175 | /* Set socket to dual (IPv4 + IPv6 socket) | 186 | /* Set socket to dual (IPv4 + IPv6 socket) |
176 | * | 187 | * |
177 | * return 1 on success | 188 | * return 1 on success |
diff --git a/toxcore/network.h b/toxcore/network.h index c67f523d..b06c0f6a 100644 --- a/toxcore/network.h +++ b/toxcore/network.h | |||
@@ -334,6 +334,13 @@ int set_socket_nonblock(sock_t sock); | |||
334 | */ | 334 | */ |
335 | int set_socket_nosigpipe(sock_t sock); | 335 | int set_socket_nosigpipe(sock_t sock); |
336 | 336 | ||
337 | /* Enable SO_REUSEADDR on socket. | ||
338 | * | ||
339 | * return 1 on success | ||
340 | * return 0 on failure | ||
341 | */ | ||
342 | int set_socket_reuseaddr(sock_t sock); | ||
343 | |||
337 | /* Set socket to dual (IPv4 + IPv6 socket) | 344 | /* Set socket to dual (IPv4 + IPv6 socket) |
338 | * | 345 | * |
339 | * return 1 on success | 346 | * return 1 on success |
diff --git a/toxcore/tox.c b/toxcore/tox.c index a9306efc..848f81c7 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -851,7 +851,7 @@ void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void | |||
851 | 851 | ||
852 | bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length) | 852 | bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length) |
853 | { | 853 | { |
854 | if (!hash || !data) { | 854 | if (!hash || (length && !data)) { |
855 | return 0; | 855 | return 0; |
856 | } | 856 | } |
857 | 857 | ||
diff --git a/toxcore/tox.h b/toxcore/tox.h index 034b1d78..8e368851 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h | |||
@@ -1418,8 +1418,8 @@ enum TOX_FILE_KIND { | |||
1418 | * primarily for validating cached avatars. This use is highly recommended to | 1418 | * primarily for validating cached avatars. This use is highly recommended to |
1419 | * avoid unnecessary avatar updates. | 1419 | * avoid unnecessary avatar updates. |
1420 | * | 1420 | * |
1421 | * If length is zero or data is NULL, the hash will contain all zero. If hash is | 1421 | * If hash is NULL or data is NULL while length is not 0 the function returns false, |
1422 | * NULL, the function returns false, otherwise it returns true. | 1422 | * otherwise it returns true. |
1423 | * | 1423 | * |
1424 | * This function is a wrapper to internal message-digest functions. | 1424 | * This function is a wrapper to internal message-digest functions. |
1425 | * | 1425 | * |