diff options
author | zugz (tox) <mbays+tox@sdf.org> | 2020-03-14 00:00:00 +0000 |
---|---|---|
committer | zugz (tox) <mbays+tox@sdf.org> | 2020-03-18 00:00:00 +0000 |
commit | 94c2a5182bafef9fb8943c02d389723bdbc72752 (patch) | |
tree | 0be6142e9c1bf5c105200ed80564becbf939b9b2 /toxcore | |
parent | db07bda7f7b1ab7f5f219a9ed3d7f732b7da66b0 (diff) |
clear out old conference connections
This may fix problems with very large conferences. Sadly, it seems
infeasible to test large conferences on one machine, so this is entirely
theoretical.
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/group.c | 101 |
1 files changed, 83 insertions, 18 deletions
diff --git a/toxcore/group.c b/toxcore/group.c index b4248fd8..3e04f181 100644 --- a/toxcore/group.c +++ b/toxcore/group.c | |||
@@ -663,28 +663,16 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p | |||
663 | return new_index; | 663 | return new_index; |
664 | } | 664 | } |
665 | 665 | ||
666 | static bool remove_connection(Group_Chats *g_c, Group_c *g, int friendcon_id) | 666 | static void remove_connection(Group_Chats *g_c, Group_c *g, uint16_t i) |
667 | { | 667 | { |
668 | for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | 668 | if (g->connections[i].reasons & GROUPCHAT_CONNECTION_REASON_INTRODUCER) { |
669 | if (g->connections[i].type == GROUPCHAT_CONNECTION_NONE) { | 669 | --g->num_introducer_connections; |
670 | continue; | ||
671 | } | ||
672 | |||
673 | if (g->connections[i].number == (unsigned int)friendcon_id) { | ||
674 | if (g->connections[i].reasons & GROUPCHAT_CONNECTION_REASON_INTRODUCER) { | ||
675 | --g->num_introducer_connections; | ||
676 | } | ||
677 | |||
678 | g->connections[i].type = GROUPCHAT_CONNECTION_NONE; | ||
679 | kill_friend_connection(g_c->fr_c, friendcon_id); | ||
680 | return true; | ||
681 | } | ||
682 | } | 670 | } |
683 | 671 | ||
684 | return false; | 672 | kill_friend_connection(g_c->fr_c, g->connections[i].number); |
673 | g->connections[i].type = GROUPCHAT_CONNECTION_NONE; | ||
685 | } | 674 | } |
686 | 675 | ||
687 | |||
688 | static void remove_from_closest(Group_c *g, int peer_index) | 676 | static void remove_from_closest(Group_c *g, int peer_index) |
689 | { | 677 | { |
690 | for (uint32_t i = 0; i < DESIRED_CLOSEST; ++i) { | 678 | for (uint32_t i = 0; i < DESIRED_CLOSEST; ++i) { |
@@ -715,7 +703,16 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void | |||
715 | const int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->group[peer_index].real_pk); | 703 | const int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->group[peer_index].real_pk); |
716 | 704 | ||
717 | if (friendcon_id != -1) { | 705 | if (friendcon_id != -1) { |
718 | remove_connection(g_c, g, friendcon_id); | 706 | for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { |
707 | if (g->connections[i].type == GROUPCHAT_CONNECTION_NONE) { | ||
708 | continue; | ||
709 | } | ||
710 | |||
711 | if (g->connections[i].number == (unsigned int)friendcon_id) { | ||
712 | remove_connection(g_c, g, i); | ||
713 | break; | ||
714 | } | ||
715 | } | ||
719 | } | 716 | } |
720 | 717 | ||
721 | --g->numpeers; | 718 | --g->numpeers; |
@@ -3090,6 +3087,73 @@ static bool groupchat_freeze_timedout(Group_Chats *g_c, uint32_t groupnumber, vo | |||
3090 | return true; | 3087 | return true; |
3091 | } | 3088 | } |
3092 | 3089 | ||
3090 | /* Push non-empty slots to start. */ | ||
3091 | static void squash_connections(Group_c *g) | ||
3092 | { | ||
3093 | uint16_t i = 0; | ||
3094 | |||
3095 | for (uint16_t j = 0; j < MAX_GROUP_CONNECTIONS; ++j) { | ||
3096 | if (g->connections[j].type != GROUPCHAT_CONNECTION_NONE) { | ||
3097 | g->connections[i] = g->connections[j]; | ||
3098 | ++i; | ||
3099 | } | ||
3100 | } | ||
3101 | |||
3102 | for (; i < MAX_GROUP_CONNECTIONS; ++i) { | ||
3103 | g->connections[i].type = GROUPCHAT_CONNECTION_NONE; | ||
3104 | } | ||
3105 | } | ||
3106 | |||
3107 | #define MIN_EMPTY_CONNECTIONS (1 + MAX_GROUP_CONNECTIONS / 10) | ||
3108 | |||
3109 | /* Remove old connections as necessary to ensure we have space for new | ||
3110 | * connections. This invalidates connections array indices (which is | ||
3111 | * why we do this periodically rather than on adding a connection). | ||
3112 | */ | ||
3113 | static void clean_connections(Group_Chats *g_c, Group_c *g) | ||
3114 | { | ||
3115 | uint16_t to_clear = MIN_EMPTY_CONNECTIONS; | ||
3116 | |||
3117 | for (uint16_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | ||
3118 | if (g->connections[i].type == GROUPCHAT_CONNECTION_NONE) { | ||
3119 | --to_clear; | ||
3120 | |||
3121 | if (to_clear == 0) { | ||
3122 | break; | ||
3123 | } | ||
3124 | } | ||
3125 | } | ||
3126 | |||
3127 | for (; to_clear > 0; --to_clear) { | ||
3128 | // Remove a connection. Prefer non-closest connections, and given | ||
3129 | // that prefer non-online connections, and given that prefer earlier | ||
3130 | // slots. | ||
3131 | uint16_t i = 0; | ||
3132 | |||
3133 | while (i < MAX_GROUP_CONNECTIONS | ||
3134 | && (g->connections[i].type != GROUPCHAT_CONNECTION_CONNECTING | ||
3135 | || (g->connections[i].reasons & GROUPCHAT_CONNECTION_REASON_CLOSEST))) { | ||
3136 | ++i; | ||
3137 | } | ||
3138 | |||
3139 | if (i == MAX_GROUP_CONNECTIONS) { | ||
3140 | i = 0; | ||
3141 | |||
3142 | while (i < MAX_GROUP_CONNECTIONS - to_clear | ||
3143 | && (g->connections[i].type != GROUPCHAT_CONNECTION_ONLINE | ||
3144 | || (g->connections[i].reasons & GROUPCHAT_CONNECTION_REASON_CLOSEST))) { | ||
3145 | ++i; | ||
3146 | } | ||
3147 | } | ||
3148 | |||
3149 | if (g->connections[i].type != GROUPCHAT_CONNECTION_NONE) { | ||
3150 | remove_connection(g_c, g, i); | ||
3151 | } | ||
3152 | } | ||
3153 | |||
3154 | squash_connections(g); | ||
3155 | } | ||
3156 | |||
3093 | /* Send current name (set in messenger) to all online groups. | 3157 | /* Send current name (set in messenger) to all online groups. |
3094 | */ | 3158 | */ |
3095 | void send_name_all_groups(Group_Chats *g_c) | 3159 | void send_name_all_groups(Group_Chats *g_c) |
@@ -3408,6 +3472,7 @@ void do_groupchats(Group_Chats *g_c, void *userdata) | |||
3408 | connect_to_closest(g_c, i, userdata); | 3472 | connect_to_closest(g_c, i, userdata); |
3409 | ping_groupchat(g_c, i); | 3473 | ping_groupchat(g_c, i); |
3410 | groupchat_freeze_timedout(g_c, i, userdata); | 3474 | groupchat_freeze_timedout(g_c, i, userdata); |
3475 | clean_connections(g_c, g); | ||
3411 | 3476 | ||
3412 | if (g->need_send_name) { | 3477 | if (g->need_send_name) { |
3413 | group_name_send(g_c, i, g_c->m->name, g_c->m->name_length); | 3478 | group_name_send(g_c, i, g_c->m->name, g_c->m->name_length); |