diff options
author | mannol <eniz_vukovic@hotmail.com> | 2015-04-29 01:02:47 +0200 |
---|---|---|
committer | mannol <eniz_vukovic@hotmail.com> | 2015-04-29 01:02:47 +0200 |
commit | d8c34f4ffafedc256e9a52af5e591c4998c0003d (patch) | |
tree | 190b3605de8f24a85caace8a841115e96dc4e539 /toxcore/friend_connection.c | |
parent | 9bba7a0434d0967d5dd76b8afc7783ea2edad0cf (diff) | |
parent | 3454bc7da78e467f55f6b7fea4e03775d2649a63 (diff) |
Merge branch 'master' into new_api
Diffstat (limited to 'toxcore/friend_connection.c')
-rw-r--r-- | toxcore/friend_connection.c | 199 |
1 files changed, 171 insertions, 28 deletions
diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c index 074021da..c13ca949 100644 --- a/toxcore/friend_connection.c +++ b/toxcore/friend_connection.c | |||
@@ -146,6 +146,95 @@ int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk) | |||
146 | return -1; | 146 | return -1; |
147 | } | 147 | } |
148 | 148 | ||
149 | /* Add a TCP relay associated to the friend. | ||
150 | * | ||
151 | * return -1 on failure. | ||
152 | * return 0 on success. | ||
153 | */ | ||
154 | int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key) | ||
155 | { | ||
156 | Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); | ||
157 | |||
158 | if (!friend_con) | ||
159 | return -1; | ||
160 | |||
161 | unsigned int i; | ||
162 | |||
163 | uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS; | ||
164 | |||
165 | for (i = 0; i < FRIEND_MAX_STORED_TCP_RELAYS; ++i) { | ||
166 | if (friend_con->tcp_relays[i].ip_port.ip.family != 0 | ||
167 | && memcmp(friend_con->tcp_relays[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
168 | memset(&friend_con->tcp_relays[i], 0, sizeof(Node_format)); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | friend_con->tcp_relays[index].ip_port = ip_port; | ||
173 | memcpy(friend_con->tcp_relays[index].public_key, public_key, crypto_box_PUBLICKEYBYTES); | ||
174 | ++friend_con->tcp_relay_counter; | ||
175 | |||
176 | return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key); | ||
177 | } | ||
178 | |||
179 | /* Connect to number saved relays for friend. */ | ||
180 | static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_id, unsigned int number) | ||
181 | { | ||
182 | Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); | ||
183 | |||
184 | if (!friend_con) | ||
185 | return; | ||
186 | |||
187 | unsigned int i; | ||
188 | |||
189 | for (i = 0; (i < FRIEND_MAX_STORED_TCP_RELAYS) && (number != 0); ++i) { | ||
190 | uint16_t index = (friend_con->tcp_relay_counter - (i + 1)) % FRIEND_MAX_STORED_TCP_RELAYS; | ||
191 | |||
192 | if (friend_con->tcp_relays[index].ip_port.ip.family) { | ||
193 | if (add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->tcp_relays[index].ip_port, | ||
194 | friend_con->tcp_relays[index].public_key) == 0) { | ||
195 | --number; | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id) | ||
202 | { | ||
203 | Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); | ||
204 | |||
205 | if (!friend_con) | ||
206 | return 0; | ||
207 | |||
208 | Node_format nodes[MAX_SHARED_RELAYS]; | ||
209 | uint8_t data[1024]; | ||
210 | int n, length; | ||
211 | |||
212 | n = copy_connected_tcp_relays(fr_c->net_crypto, nodes, MAX_SHARED_RELAYS); | ||
213 | |||
214 | unsigned int i; | ||
215 | |||
216 | for (i = 0; i < n; ++i) { | ||
217 | /* Associated the relays being sent with this connection. | ||
218 | On receiving the peer will do the same which will establish the connection. */ | ||
219 | friend_add_tcp_relay(fr_c, friendcon_id, nodes[i].ip_port, nodes[i].public_key); | ||
220 | } | ||
221 | |||
222 | length = pack_nodes(data + 1, sizeof(data) - 1, nodes, n); | ||
223 | |||
224 | if (length <= 0) | ||
225 | return 0; | ||
226 | |||
227 | data[0] = PACKET_ID_SHARE_RELAYS; | ||
228 | ++length; | ||
229 | |||
230 | if (write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, data, length, 0) != -1) { | ||
231 | friend_con->share_relays_lastsent = unix_time(); | ||
232 | return 1; | ||
233 | } | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
149 | /* callback for recv TCP relay nodes. */ | 238 | /* callback for recv TCP relay nodes. */ |
150 | static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) | 239 | static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) |
151 | { | 240 | { |
@@ -156,7 +245,7 @@ static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_por | |||
156 | return -1; | 245 | return -1; |
157 | 246 | ||
158 | if (friend_con->crypt_connection_id != -1) { | 247 | if (friend_con->crypt_connection_id != -1) { |
159 | return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key); | 248 | return friend_add_tcp_relay(fr_c, number, ip_port, public_key); |
160 | } else { | 249 | } else { |
161 | return add_tcp_relay(fr_c->net_crypto, ip_port, public_key); | 250 | return add_tcp_relay(fr_c->net_crypto, ip_port, public_key); |
162 | } | 251 | } |
@@ -181,19 +270,14 @@ static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port) | |||
181 | friend_con->dht_ip_port_lastrecv = unix_time(); | 270 | friend_con->dht_ip_port_lastrecv = unix_time(); |
182 | } | 271 | } |
183 | 272 | ||
184 | /* Callback for dht public key changes. */ | 273 | static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key) |
185 | static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key) | ||
186 | { | 274 | { |
187 | Friend_Connections *fr_c = object; | 275 | Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); |
188 | Friend_Conn *friend_con = get_conn(fr_c, number); | ||
189 | 276 | ||
190 | if (!friend_con) | 277 | if (!friend_con) |
191 | return; | 278 | return; |
192 | 279 | ||
193 | friend_con->dht_ping_lastrecv = unix_time(); | 280 | friend_con->dht_pk_lastrecv = unix_time(); |
194 | |||
195 | if (memcmp(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
196 | return; | ||
197 | 281 | ||
198 | if (friend_con->dht_lock) { | 282 | if (friend_con->dht_lock) { |
199 | if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) { | 283 | if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) { |
@@ -204,15 +288,7 @@ static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_pub | |||
204 | friend_con->dht_lock = 0; | 288 | friend_con->dht_lock = 0; |
205 | } | 289 | } |
206 | 290 | ||
207 | DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, object, number, &friend_con->dht_lock); | 291 | DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, fr_c, friendcon_id, &friend_con->dht_lock); |
208 | |||
209 | if (friend_con->crypt_connection_id == -1) { | ||
210 | friend_new_connection(fr_c, number); | ||
211 | } | ||
212 | |||
213 | set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, dht_public_key); | ||
214 | onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key); | ||
215 | |||
216 | memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES); | 292 | memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES); |
217 | } | 293 | } |
218 | 294 | ||
@@ -230,11 +306,12 @@ static int handle_status(void *object, int number, uint8_t status) | |||
230 | call_cb = 1; | 306 | call_cb = 1; |
231 | friend_con->status = FRIENDCONN_STATUS_CONNECTED; | 307 | friend_con->status = FRIENDCONN_STATUS_CONNECTED; |
232 | friend_con->ping_lastrecv = unix_time(); | 308 | friend_con->ping_lastrecv = unix_time(); |
309 | friend_con->share_relays_lastsent = 0; | ||
233 | onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); | 310 | onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); |
234 | } else { /* Went offline. */ | 311 | } else { /* Went offline. */ |
235 | if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) { | 312 | if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) { |
236 | call_cb = 1; | 313 | call_cb = 1; |
237 | friend_con->dht_ping_lastrecv = unix_time(); | 314 | friend_con->dht_pk_lastrecv = unix_time(); |
238 | onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); | 315 | onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status); |
239 | } | 316 | } |
240 | 317 | ||
@@ -255,6 +332,31 @@ static int handle_status(void *object, int number, uint8_t status) | |||
255 | return 0; | 332 | return 0; |
256 | } | 333 | } |
257 | 334 | ||
335 | /* Callback for dht public key changes. */ | ||
336 | static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key) | ||
337 | { | ||
338 | Friend_Connections *fr_c = object; | ||
339 | Friend_Conn *friend_con = get_conn(fr_c, number); | ||
340 | |||
341 | if (!friend_con) | ||
342 | return; | ||
343 | |||
344 | if (memcmp(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) | ||
345 | return; | ||
346 | |||
347 | change_dht_pk(fr_c, number, dht_public_key); | ||
348 | |||
349 | /* if pk changed, create a new connection.*/ | ||
350 | if (friend_con->crypt_connection_id != -1) { | ||
351 | crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id); | ||
352 | friend_con->crypt_connection_id = -1; | ||
353 | handle_status(object, number, 0); /* Going offline. */ | ||
354 | } | ||
355 | |||
356 | friend_new_connection(fr_c, number); | ||
357 | onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key); | ||
358 | } | ||
359 | |||
258 | static int handle_packet(void *object, int number, uint8_t *data, uint16_t length) | 360 | static int handle_packet(void *object, int number, uint8_t *data, uint16_t length) |
259 | { | 361 | { |
260 | if (length == 0) | 362 | if (length == 0) |
@@ -263,18 +365,30 @@ static int handle_packet(void *object, int number, uint8_t *data, uint16_t lengt | |||
263 | Friend_Connections *fr_c = object; | 365 | Friend_Connections *fr_c = object; |
264 | Friend_Conn *friend_con = get_conn(fr_c, number); | 366 | Friend_Conn *friend_con = get_conn(fr_c, number); |
265 | 367 | ||
368 | if (!friend_con) | ||
369 | return -1; | ||
370 | |||
266 | if (data[0] == PACKET_ID_FRIEND_REQUESTS) { | 371 | if (data[0] == PACKET_ID_FRIEND_REQUESTS) { |
267 | if (fr_c->fr_request_callback) | 372 | if (fr_c->fr_request_callback) |
268 | fr_c->fr_request_callback(fr_c->fr_request_object, friend_con->real_public_key, data, length); | 373 | fr_c->fr_request_callback(fr_c->fr_request_object, friend_con->real_public_key, data, length); |
269 | 374 | ||
270 | return 0; | 375 | return 0; |
271 | } | 376 | } else if (data[0] == PACKET_ID_ALIVE) { |
377 | friend_con->ping_lastrecv = unix_time(); | ||
378 | return 0; | ||
379 | } else if (data[0] == PACKET_ID_SHARE_RELAYS) { | ||
380 | Node_format nodes[MAX_SHARED_RELAYS]; | ||
381 | int n; | ||
272 | 382 | ||
273 | if (!friend_con) | 383 | if ((n = unpack_nodes(nodes, MAX_SHARED_RELAYS, NULL, data + 1, length - 1, 1)) == -1) |
274 | return -1; | 384 | return -1; |
385 | |||
386 | int j; | ||
387 | |||
388 | for (j = 0; j < n; j++) { | ||
389 | friend_add_tcp_relay(fr_c, number, nodes[j].ip_port, nodes[j].public_key); | ||
390 | } | ||
275 | 391 | ||
276 | if (data[0] == PACKET_ID_ALIVE) { | ||
277 | friend_con->ping_lastrecv = unix_time(); | ||
278 | return 0; | 392 | return 0; |
279 | } | 393 | } |
280 | 394 | ||
@@ -333,6 +447,11 @@ static int handle_new_connections(void *object, New_Connection *n_c) | |||
333 | return -1; | 447 | return -1; |
334 | 448 | ||
335 | int id = accept_crypto_connection(fr_c->net_crypto, n_c); | 449 | int id = accept_crypto_connection(fr_c->net_crypto, n_c); |
450 | |||
451 | if (id == -1) { | ||
452 | return -1; | ||
453 | } | ||
454 | |||
336 | connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id); | 455 | connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id); |
337 | connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id); | 456 | connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id); |
338 | connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id); | 457 | connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id); |
@@ -345,7 +464,9 @@ static int handle_new_connections(void *object, New_Connection *n_c) | |||
345 | friend_con->dht_ip_port_lastrecv = unix_time(); | 464 | friend_con->dht_ip_port_lastrecv = unix_time(); |
346 | } | 465 | } |
347 | 466 | ||
348 | dht_pk_callback(fr_c, friendcon_id, n_c->dht_public_key); | 467 | if (memcmp(friend_con->dht_temp_pk, n_c->dht_public_key, crypto_box_PUBLICKEYBYTES) != 0) { |
468 | change_dht_pk(fr_c, friendcon_id, n_c->dht_public_key); | ||
469 | } | ||
349 | 470 | ||
350 | nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id); | 471 | nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id); |
351 | return 0; | 472 | return 0; |
@@ -365,7 +486,12 @@ static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id) | |||
365 | return -1; | 486 | return -1; |
366 | } | 487 | } |
367 | 488 | ||
368 | int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key); | 489 | /* If dht_temp_pk does not contains a pk. */ |
490 | if (!friend_con->dht_lock) { | ||
491 | return -1; | ||
492 | } | ||
493 | |||
494 | int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key, friend_con->dht_temp_pk); | ||
369 | 495 | ||
370 | if (id == -1) | 496 | if (id == -1) |
371 | return -1; | 497 | return -1; |
@@ -632,10 +758,20 @@ Friend_Connections *new_friend_connections(Onion_Client *onion_c) | |||
632 | temp->onion_c = onion_c; | 758 | temp->onion_c = onion_c; |
633 | 759 | ||
634 | new_connection_handler(temp->net_crypto, &handle_new_connections, temp); | 760 | new_connection_handler(temp->net_crypto, &handle_new_connections, temp); |
761 | LANdiscovery_init(temp->dht); | ||
635 | 762 | ||
636 | return temp; | 763 | return temp; |
637 | } | 764 | } |
638 | 765 | ||
766 | /* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ | ||
767 | static void LANdiscovery(Friend_Connections *fr_c) | ||
768 | { | ||
769 | if (fr_c->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) { | ||
770 | send_LANdiscovery(htons(TOX_PORT_DEFAULT), fr_c->dht); | ||
771 | fr_c->last_LANdiscovery = unix_time(); | ||
772 | } | ||
773 | } | ||
774 | |||
639 | /* main friend_connections loop. */ | 775 | /* main friend_connections loop. */ |
640 | void do_friend_connections(Friend_Connections *fr_c) | 776 | void do_friend_connections(Friend_Connections *fr_c) |
641 | { | 777 | { |
@@ -647,7 +783,7 @@ void do_friend_connections(Friend_Connections *fr_c) | |||
647 | 783 | ||
648 | if (friend_con) { | 784 | if (friend_con) { |
649 | if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) { | 785 | if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) { |
650 | if (friend_con->dht_ping_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { | 786 | if (friend_con->dht_pk_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) { |
651 | if (friend_con->dht_lock) { | 787 | if (friend_con->dht_lock) { |
652 | DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock); | 788 | DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock); |
653 | friend_con->dht_lock = 0; | 789 | friend_con->dht_lock = 0; |
@@ -660,8 +796,8 @@ void do_friend_connections(Friend_Connections *fr_c) | |||
660 | 796 | ||
661 | if (friend_con->dht_lock) { | 797 | if (friend_con->dht_lock) { |
662 | if (friend_new_connection(fr_c, i) == 0) { | 798 | if (friend_new_connection(fr_c, i) == 0) { |
663 | set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_temp_pk); | ||
664 | set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port); | 799 | set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port); |
800 | connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */ | ||
665 | } | 801 | } |
666 | } | 802 | } |
667 | 803 | ||
@@ -670,6 +806,10 @@ void do_friend_connections(Friend_Connections *fr_c) | |||
670 | send_ping(fr_c, i); | 806 | send_ping(fr_c, i); |
671 | } | 807 | } |
672 | 808 | ||
809 | if (friend_con->share_relays_lastsent + SHARE_RELAYS_INTERVAL < temp_time) { | ||
810 | send_relays(fr_c, i); | ||
811 | } | ||
812 | |||
673 | if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { | 813 | if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { |
674 | /* If we stopped receiving ping packets, kill it. */ | 814 | /* If we stopped receiving ping packets, kill it. */ |
675 | crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id); | 815 | crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id); |
@@ -679,6 +819,8 @@ void do_friend_connections(Friend_Connections *fr_c) | |||
679 | } | 819 | } |
680 | } | 820 | } |
681 | } | 821 | } |
822 | |||
823 | LANdiscovery(fr_c); | ||
682 | } | 824 | } |
683 | 825 | ||
684 | /* Free everything related with friend_connections. */ | 826 | /* Free everything related with friend_connections. */ |
@@ -693,5 +835,6 @@ void kill_friend_connections(Friend_Connections *fr_c) | |||
693 | kill_friend_connection(fr_c, i); | 835 | kill_friend_connection(fr_c, i); |
694 | } | 836 | } |
695 | 837 | ||
838 | LANdiscovery_kill(fr_c->dht); | ||
696 | free(fr_c); | 839 | free(fr_c); |
697 | } | 840 | } |