diff options
author | zugz (tox) <mbays+tox@sdf.org> | 2019-04-28 00:00:00 +0000 |
---|---|---|
committer | Robin Linden <dev@robinlinden.eu> | 2019-11-17 13:29:10 +0100 |
commit | 2677a53ee0b0bb58a52e3cb585aaaba8aa9ceccb (patch) | |
tree | 8a1c0b78b6f03c9e5bc1b0b48c3b23d6e2930dee /toxcore | |
parent | 79748dd9e591b59396964588cd2ddb400e85c995 (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.c | 105 |
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 | ||
386 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t reason, | ||
387 | uint8_t lock); | ||
388 | |||
389 | static void remove_conn_reason(Group_Chats *g_c, uint32_t groupnumber, uint16_t i, uint8_t reason); | 386 | static void remove_conn_reason(Group_Chats *g_c, uint32_t groupnumber, uint16_t i, uint8_t reason); |
390 | 387 | ||
391 | static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type, | 388 | static void purge_closest(Group_Chats *g_c, uint32_t groupnumber) |
392 | const uint8_t *id); | ||
393 | |||
394 | static 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 | |||
414 | static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t type, | ||
415 | const uint8_t *id); | ||
416 | |||
417 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t groupnumber, uint8_t reason, | ||
418 | uint8_t lock); | ||
419 | |||
420 | static 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 | |||
465 | static 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 | ||
559 | static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata, bool keep_connection); | 589 | static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata); |
560 | 590 | ||
561 | static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, void *userdata) | 591 | static 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 | */ |
709 | static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata, bool keep_connection) | 743 | static 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 | ||
2796 | static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata) | 2838 | static 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 | } |