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 | |
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.
-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); |