summaryrefslogtreecommitdiff
path: root/toxcore/group.c
diff options
context:
space:
mode:
authorzugz (tox) <mbays+tox@sdf.org>2019-02-17 00:00:00 +0000
committerzugz (tox) <mbays+tox@sdf.org>2019-05-19 18:51:28 +0200
commit306dd1f21f25d65ffd1c289d28e4450695c83745 (patch)
tree89d91af3ef10a29ae8a8a9ead0d5d7ea15619389 /toxcore/group.c
parentd26b11d0c263bd796762374154edc7386dd601d4 (diff)
add configurable limit on number of stored frozen peers
Diffstat (limited to 'toxcore/group.c')
-rw-r--r--toxcore/group.c100
1 files changed, 93 insertions, 7 deletions
diff --git a/toxcore/group.c b/toxcore/group.c
index 20ee5459..f6f8c704 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -118,6 +118,8 @@ static bool realloc_conferences(Group_Chats *g_c, uint16_t num)
118static void setup_conference(Group_c *g) 118static void setup_conference(Group_c *g)
119{ 119{
120 memset(g, 0, sizeof(Group_c)); 120 memset(g, 0, sizeof(Group_c));
121
122 g->maxfrozen = MAX_FROZEN_DEFAULT;
121} 123}
122 124
123/* Create a new empty groupchat connection. 125/* Create a new empty groupchat connection.
@@ -644,8 +646,8 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p
644 id_copy(g->group[g->numpeers].temp_pk, temp_pk); 646 id_copy(g->group[g->numpeers].temp_pk, temp_pk);
645 g->group[g->numpeers].temp_pk_updated = true; 647 g->group[g->numpeers].temp_pk_updated = true;
646 g->group[g->numpeers].peer_number = peer_number; 648 g->group[g->numpeers].peer_number = peer_number;
647
648 g->group[g->numpeers].last_active = mono_time_get(g_c->mono_time); 649 g->group[g->numpeers].last_active = mono_time_get(g_c->mono_time);
650 g->group[g->numpeers].is_friend = (getfriend_id(g_c->m, real_pk) != -1);
649 ++g->numpeers; 651 ++g->numpeers;
650 652
651 add_to_closest(g_c, groupnumber, real_pk, temp_pk); 653 add_to_closest(g_c, groupnumber, real_pk, temp_pk);
@@ -752,6 +754,56 @@ static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void
752 return 0; 754 return 0;
753} 755}
754 756
757static int cmp_u64(uint64_t a, uint64_t b)
758{
759 return (a > b) - (a < b);
760}
761
762/* Order peers with friends first and with more recently active earlier */
763static int cmp_frozen(const void *a, const void *b)
764{
765 const Group_Peer *pa = (const Group_Peer *) a;
766 const Group_Peer *pb = (const Group_Peer *) b;
767
768 if (pa->is_friend ^ pb->is_friend) {
769 return pa->is_friend ? -1 : 1;
770 }
771
772 return cmp_u64(pb->last_active, pa->last_active);
773}
774
775/* Delete frozen peers as necessary to ensure at most g->maxfrozen remain.
776 *
777 * return true if any frozen peers are removed.
778 */
779static bool delete_old_frozen(Group_c *g)
780{
781 if (g->numfrozen <= g->maxfrozen) {
782 return false;
783 }
784
785 if (g->maxfrozen == 0) {
786 free(g->frozen);
787 g->frozen = nullptr;
788 g->numfrozen = 0;
789 return true;
790 }
791
792 qsort(g->frozen, g->numfrozen, sizeof(Group_Peer), cmp_frozen);
793
794 Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * g->maxfrozen);
795
796 if (temp == nullptr) {
797 return false;
798 }
799
800 g->frozen = temp;
801
802 g->numfrozen = g->maxfrozen;
803
804 return true;
805}
806
755static bool try_send_rejoin(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk); 807static bool try_send_rejoin(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk);
756 808
757static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata) 809static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata)
@@ -762,8 +814,6 @@ static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, v
762 return -1; 814 return -1;
763 } 815 }
764 816
765 try_send_rejoin(g_c, groupnumber, g->group[peer_index].real_pk);
766
767 Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen + 1)); 817 Group_Peer *temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen + 1));
768 818
769 if (temp == nullptr) { 819 if (temp == nullptr) {
@@ -773,9 +823,18 @@ static int freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, v
773 g->frozen = temp; 823 g->frozen = temp;
774 g->frozen[g->numfrozen] = g->group[peer_index]; 824 g->frozen[g->numfrozen] = g->group[peer_index];
775 g->frozen[g->numfrozen].object = nullptr; 825 g->frozen[g->numfrozen].object = nullptr;
826
827 if (delpeer(g_c, groupnumber, peer_index, userdata, true) != 0) {
828 return -1;
829 }
830
831 try_send_rejoin(g_c, groupnumber, g->frozen[g->numfrozen].real_pk);
832
776 ++g->numfrozen; 833 ++g->numfrozen;
777 834
778 return delpeer(g_c, groupnumber, peer_index, userdata, true); 835 delete_old_frozen(g);
836
837 return 0;
779} 838}
780 839
781 840
@@ -1236,6 +1295,24 @@ int group_frozen_last_active(const Group_Chats *g_c, uint32_t groupnumber, int p
1236 return 0; 1295 return 0;
1237} 1296}
1238 1297
1298/* Set maximum number of frozen peers.
1299 *
1300 * return 0 on success.
1301 * return -1 if groupnumber is invalid.
1302 */
1303int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t maxfrozen)
1304{
1305 Group_c *g = get_group_c(g_c, groupnumber);
1306
1307 if (!g) {
1308 return -1;
1309 }
1310
1311 g->maxfrozen = maxfrozen;
1312 delete_old_frozen(g);
1313 return 0;
1314}
1315
1239/* List all the (frozen, if frozen is true) peers in the group chat. 1316/* List all the (frozen, if frozen is true) peers in the group chat.
1240 * 1317 *
1241 * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array. 1318 * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array.
@@ -3208,10 +3285,12 @@ static State_Load_Status load_conferences(Group_Chats *g_c, const uint8_t *data,
3208 lendian_bytes_to_host32(&g->numfrozen, data); 3285 lendian_bytes_to_host32(&g->numfrozen, data);
3209 data += sizeof(uint32_t); 3286 data += sizeof(uint32_t);
3210 3287
3211 g->frozen = (Group_Peer *)malloc(sizeof(Group_Peer) * g->numfrozen); 3288 if (g->numfrozen > 0) {
3289 g->frozen = (Group_Peer *)malloc(sizeof(Group_Peer) * g->numfrozen);
3212 3290
3213 if (g->frozen == nullptr) { 3291 if (g->frozen == nullptr) {
3214 return STATE_LOAD_STATUS_ERROR; 3292 return STATE_LOAD_STATUS_ERROR;
3293 }
3215 } 3294 }
3216 3295
3217 g->title_len = *data; 3296 g->title_len = *data;
@@ -3252,6 +3331,13 @@ static State_Load_Status load_conferences(Group_Chats *g_c, const uint8_t *data,
3252 3331
3253 memcpy(peer->nick, data, peer->nick_len); 3332 memcpy(peer->nick, data, peer->nick_len);
3254 data += peer->nick_len; 3333 data += peer->nick_len;
3334
3335 // NOTE: this relies on friends being loaded before conferences.
3336 peer->is_friend = (getfriend_id(g_c->m, peer->real_pk) != -1);
3337 }
3338
3339 if (g->numfrozen > g->maxfrozen) {
3340 g->maxfrozen = g->numfrozen;
3255 } 3341 }
3256 3342
3257 g->status = GROUPCHAT_STATUS_CONNECTED; 3343 g->status = GROUPCHAT_STATUS_CONNECTED;