summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/group.c101
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
666static bool remove_connection(Group_Chats *g_c, Group_c *g, int friendcon_id) 666static 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
688static void remove_from_closest(Group_c *g, int peer_index) 676static 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. */
3091static 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 */
3113static 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 */
3095void send_name_all_groups(Group_Chats *g_c) 3159void 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);