diff options
Diffstat (limited to 'toxcore/TCP_connection.c')
-rw-r--r-- | toxcore/TCP_connection.c | 722 |
1 files changed, 722 insertions, 0 deletions
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 | |||