summaryrefslogtreecommitdiff
path: root/toxcore/friend_connection.c
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-04-29 01:02:47 +0200
committermannol <eniz_vukovic@hotmail.com>2015-04-29 01:02:47 +0200
commitd8c34f4ffafedc256e9a52af5e591c4998c0003d (patch)
tree190b3605de8f24a85caace8a841115e96dc4e539 /toxcore/friend_connection.c
parent9bba7a0434d0967d5dd76b8afc7783ea2edad0cf (diff)
parent3454bc7da78e467f55f6b7fea4e03775d2649a63 (diff)
Merge branch 'master' into new_api
Diffstat (limited to 'toxcore/friend_connection.c')
-rw-r--r--toxcore/friend_connection.c199
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 */
154int 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. */
180static 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
201static 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. */
150static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) 239static 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. */ 273static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key)
185static 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. */
336static 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
258static int handle_packet(void *object, int number, uint8_t *data, uint16_t length) 360static 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. */
767static 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. */
640void do_friend_connections(Friend_Connections *fr_c) 776void 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}