summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authorzugz (tox) <mbays+tox@sdf.org>2019-04-28 00:00:00 +0000
committerRobin Linden <dev@robinlinden.eu>2019-11-17 13:29:10 +0100
commit2677a53ee0b0bb58a52e3cb585aaaba8aa9ceccb (patch)
tree8a1c0b78b6f03c9e5bc1b0b48c3b23d6e2930dee /toxcore
parent79748dd9e591b59396964588cd2ddb400e85c995 (diff)
Fix miscellaneous small problems with groups:
* unset global status callback in kill_groupchats * avoid dangling friend connections * fix num_introducer_connections leak * stop trying to keep connection alive on freeze * avoid relaying lossless messages back to sender where possible * avoid sending gratuitous online packets
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/group.c105
1 files changed, 74 insertions, 31 deletions
diff --git a/toxcore/group.c b/toxcore/group.c
index 12ad2f98..1adaa395 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -383,30 +383,14 @@ static unsigned int pk_in_closest_peers(const Group_c *g, uint8_t *real_pk)
383 return 0; 383 return 0;
384} 384}
385 385
386static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t reason,
387 uint8_t lock);
388
389static void remove_conn_reason(Group_Chats *g_c, uint32_t groupnumber, uint16_t i, uint8_t reason); 386static void remove_conn_reason(Group_Chats *g_c, uint32_t groupnumber, uint16_t i, uint8_t reason);
390 387
391static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type, 388static void purge_closest(Group_Chats *g_c, uint32_t groupnumber)
392 const uint8_t *id);
393
394static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *userdata)
395{ 389{
396 Group_c *g = get_group_c(g_c, groupnumber); 390 Group_c *g = get_group_c(g_c, groupnumber);
397 391
398 if (!g) { 392 if (!g) {
399 return -1; 393 return;
400 }
401
402 if (!g->changed) {
403 return 0;
404 }
405
406 if (g->changed == GROUPCHAT_CLOSEST_REMOVED) {
407 for (uint32_t i = 0; i < g->numpeers; ++i) {
408 add_to_closest(g_c, groupnumber, g->group[i].real_pk, g->group[i].temp_pk);
409 }
410 } 394 }
411 395
412 for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 396 for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
@@ -419,13 +403,27 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user
419 } 403 }
420 404
421 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; 405 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
422 uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE]; 406 get_friendcon_public_keys(real_pk, nullptr, g_c->fr_c, g->close[i].number);
423 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number);
424 407
425 if (!pk_in_closest_peers(g, real_pk)) { 408 if (!pk_in_closest_peers(g, real_pk)) {
426 remove_conn_reason(g_c, groupnumber, i, GROUPCHAT_CLOSE_REASON_CLOSEST); 409 remove_conn_reason(g_c, groupnumber, i, GROUPCHAT_CLOSE_REASON_CLOSEST);
427 } 410 }
428 } 411 }
412}
413
414static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type,
415 const uint8_t *id);
416
417static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t reason,
418 uint8_t lock);
419
420static void add_closest_connections(Group_Chats *g_c, uint32_t groupnumber, void *userdata)
421{
422 Group_c *g = get_group_c(g_c, groupnumber);
423
424 if (!g) {
425 return;
426 }
429 427
430 for (uint32_t i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { 428 for (uint32_t i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
431 if (!g->closest_peers[i].entry) { 429 if (!g->closest_peers[i].entry) {
@@ -434,11 +432,11 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user
434 432
435 int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk); 433 int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk);
436 434
437 uint8_t lock = 1; 435 uint8_t fresh = 0;
438 436
439 if (friendcon_id == -1) { 437 if (friendcon_id == -1) {
440 friendcon_id = new_friend_connection(g_c->fr_c, g->closest_peers[i].real_pk); 438 friendcon_id = new_friend_connection(g_c->fr_c, g->closest_peers[i].real_pk);
441 lock = 0; 439 fresh = 1;
442 440
443 if (friendcon_id == -1) { 441 if (friendcon_id == -1) {
444 continue; 442 continue;
@@ -447,12 +445,44 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user
447 set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk, userdata); 445 set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk, userdata);
448 } 446 }
449 447
450 add_conn_to_groupchat(g_c, friendcon_id, groupnumber, GROUPCHAT_CLOSE_REASON_CLOSEST, lock); 448 const int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnumber, GROUPCHAT_CLOSE_REASON_CLOSEST, !fresh);
449
450 if (close_index == -1) {
451 if (fresh) {
452 kill_friend_connection(g_c->fr_c, friendcon_id);
453 }
454
455 continue;
456 }
451 457
452 if (friend_con_connected(g_c->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { 458 if (friend_con_connected(g_c->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED
459 && g->close[close_index].type == GROUPCHAT_CLOSE_CONNECTION) {
453 send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->type, g->id); 460 send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->type, g->id);
454 } 461 }
455 } 462 }
463}
464
465static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *userdata)
466{
467 Group_c *g = get_group_c(g_c, groupnumber);
468
469 if (!g) {
470 return -1;
471 }
472
473 if (!g->changed) {
474 return 0;
475 }
476
477 if (g->changed == GROUPCHAT_CLOSEST_REMOVED) {
478 for (uint32_t i = 0; i < g->numpeers; ++i) {
479 add_to_closest(g_c, groupnumber, g->group[i].real_pk, g->group[i].temp_pk);
480 }
481 }
482
483 purge_closest(g_c, groupnumber);
484
485 add_closest_connections(g_c, groupnumber, userdata);
456 486
457 g->changed = GROUPCHAT_CLOSEST_NONE; 487 g->changed = GROUPCHAT_CLOSEST_NONE;
458 488
@@ -556,7 +586,7 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee
556 return g->numpeers - 1; 586 return g->numpeers - 1;
557} 587}
558 588
559static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata, bool keep_connection); 589static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata);
560 590
561static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, void *userdata) 591static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, void *userdata)
562{ 592{
@@ -569,7 +599,7 @@ static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, cons
569 const int prev_peer_index = peer_in_chat(g, real_pk); 599 const int prev_peer_index = peer_in_chat(g, real_pk);
570 600
571 if (prev_peer_index >= 0) { 601 if (prev_peer_index >= 0) {
572 delpeer(g_c, groupnumber, prev_peer_index, userdata, false); 602 delpeer(g_c, groupnumber, prev_peer_index, userdata);
573 } 603 }
574 604
575 const int prev_frozen_index = frozen_in_chat(g, real_pk); 605 const int prev_frozen_index = frozen_in_chat(g, real_pk);
@@ -679,6 +709,10 @@ static int remove_close_conn(Group_Chats *g_c, uint32_t groupnumber, int friendc
679 } 709 }
680 710
681 if (g->close[i].number == (unsigned int)friendcon_id) { 711 if (g->close[i].number == (unsigned int)friendcon_id) {
712 if (g->close[i].reasons & GROUPCHAT_CLOSE_REASON_INTRODUCER) {
713 --g->num_introducer_connections;
714 }
715
682 g->close[i].type = GROUPCHAT_CLOSE_NONE; 716 g->close[i].type = GROUPCHAT_CLOSE_NONE;
683 kill_friend_connection(g_c->fr_c, friendcon_id); 717 kill_friend_connection(g_c->fr_c, friendcon_id);
684 return 0; 718 return 0;
@@ -706,7 +740,7 @@ static void remove_from_closest(Group_c *g, int peer_index)
706 * return 0 if success 740 * return 0 if success
707 * return -1 if error. 741 * return -1 if error.
708 */ 742 */
709static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata, bool keep_connection) 743static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata)
710{ 744{
711 Group_c *g = get_group_c(g_c, groupnumber); 745 Group_c *g = get_group_c(g_c, groupnumber);
712 746
@@ -718,7 +752,7 @@ static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void
718 752
719 const int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->group[peer_index].real_pk); 753 const int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->group[peer_index].real_pk);
720 754
721 if (friendcon_id != -1 && !keep_connection) { 755 if (friendcon_id != -1) {
722 remove_close_conn(g_c, groupnumber, friendcon_id); 756 remove_close_conn(g_c, groupnumber, friendcon_id);
723 } 757 }
724 758
@@ -824,7 +858,7 @@ static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, v
824 g->frozen[g->numfrozen] = g->group[peer_index]; 858 g->frozen[g->numfrozen] = g->group[peer_index];
825 g->frozen[g->numfrozen].object = nullptr; 859 g->frozen[g->numfrozen].object = nullptr;
826 860
827 if (delpeer(g_c, groupnumber, peer_index, userdata, true) != 0) { 861 if (delpeer(g_c, groupnumber, peer_index, userdata) != 0) {
828 return -1; 862 return -1;
829 } 863 }
830 864
@@ -2727,7 +2761,7 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
2727 2761
2728 if (peer_number == kill_peer_number) { 2762 if (peer_number == kill_peer_number) {
2729 if (message_id == GROUP_MESSAGE_KILL_PEER_ID) { 2763 if (message_id == GROUP_MESSAGE_KILL_PEER_ID) {
2730 delpeer(g_c, groupnumber, index, userdata, false); 2764 delpeer(g_c, groupnumber, index, userdata);
2731 } else { 2765 } else {
2732 freeze_peer(g_c, groupnumber, index, userdata); 2766 freeze_peer(g_c, groupnumber, index, userdata);
2733 } 2767 }
@@ -2790,7 +2824,15 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
2790 return; 2824 return;
2791 } 2825 }
2792 2826
2793 send_message_all_close(g_c, groupnumber, data, length, -1/* TODO(irungentoo) close_index */); 2827 /* If the packet was received from the peer who sent the message, relay it
2828 * back. When the sender only has one group connection (e.g. because there
2829 * are only two peers in the group), this is the only way for them to
2830 * receive their own message. */
2831 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
2832 get_friendcon_public_keys(real_pk, nullptr, g_c->fr_c, g->close[close_index].number);
2833 bool relay_back = id_equal(g->group[index].real_pk, real_pk);
2834
2835 send_message_all_close(g_c, groupnumber, data, length, relay_back ? -1 : close_index);
2794} 2836}
2795 2837
2796static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata) 2838static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
@@ -3434,6 +3476,7 @@ void kill_groupchats(Group_Chats *g_c)
3434 } 3476 }
3435 3477
3436 m_callback_conference_invite(g_c->m, nullptr); 3478 m_callback_conference_invite(g_c->m, nullptr);
3479 set_global_status_callback(g_c->m->fr_c, nullptr, nullptr);
3437 g_c->m->conferences_object = nullptr; 3480 g_c->m->conferences_object = nullptr;
3438 free(g_c); 3481 free(g_c);
3439} 3482}