Skip to content

Commit e5561ad

Browse files
zugziphydf
authored andcommitted
Improve handling of peers entering and leaving conferences
* send freeze packet on quit * delete existing peers with same real_pk on adding a peer * record actual number of conference peers saved
1 parent e08f631 commit e5561ad

File tree

1 file changed

+130
-55
lines changed

1 file changed

+130
-55
lines changed

toxcore/group.c

Lines changed: 130 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ typedef enum Group_Message_Id {
4242
GROUP_MESSAGE_PING_ID = 0,
4343
GROUP_MESSAGE_NEW_PEER_ID = 16,
4444
GROUP_MESSAGE_KILL_PEER_ID = 17,
45+
GROUP_MESSAGE_FREEZE_PEER_ID = 18,
4546
GROUP_MESSAGE_NAME_ID = 48,
4647
GROUP_MESSAGE_TITLE_ID = 49,
4748
} Group_Message_Id;
@@ -201,6 +202,17 @@ static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk)
201202
return -1;
202203
}
203204

205+
static int frozen_in_chat(const Group_c *chat, const uint8_t *real_pk)
206+
{
207+
for (uint32_t i = 0; i < chat->numfrozen; ++i) {
208+
if (id_equal(chat->frozen[i].real_pk, real_pk)) {
209+
return i;
210+
}
211+
}
212+
213+
return -1;
214+
}
215+
204216
/*
205217
* check if group with the given type and id is in group array.
206218
*
@@ -457,6 +469,34 @@ static int get_frozen_index(Group_c *g, uint16_t peer_number)
457469
return -1;
458470
}
459471

472+
static bool delete_frozen(Group_c *g, uint32_t frozen_index)
473+
{
474+
if (frozen_index >= g->numfrozen) {
475+
return false;
476+
}
477+
478+
--g->numfrozen;
479+
480+
if (g->numfrozen == 0) {
481+
free(g->frozen);
482+
g->frozen = nullptr;
483+
} else {
484+
if (g->numfrozen != frozen_index) {
485+
g->frozen[frozen_index] = g->frozen[g->numfrozen];
486+
}
487+
488+
Group_Peer *frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen));
489+
490+
if (frozen_temp == nullptr) {
491+
return false;
492+
}
493+
494+
g->frozen = frozen_temp;
495+
}
496+
497+
return true;
498+
}
499+
460500
/* Update last_active timestamp on peer, and thaw the peer if it is frozen.
461501
*
462502
* return peer index if peer is in the conference.
@@ -500,23 +540,8 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee
500540

501541
++g->numpeers;
502542

503-
--g->numfrozen;
504-
505-
if (g->numfrozen == 0) {
506-
free(g->frozen);
507-
g->frozen = nullptr;
508-
} else {
509-
if (g->numfrozen != (uint32_t)frozen_index) {
510-
g->frozen[frozen_index] = g->frozen[g->numfrozen];
511-
}
512-
513-
Group_Peer *frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen));
514-
515-
if (frozen_temp == nullptr) {
516-
return -1;
517-
}
518-
519-
g->frozen = frozen_temp;
543+
if (!delete_frozen(g, frozen_index)) {
544+
return -1;
520545
}
521546

522547
if (g_c->peer_list_changed_callback) {
@@ -532,6 +557,29 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee
532557
return g->numpeers - 1;
533558
}
534559

560+
static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata, bool keep_connection);
561+
562+
static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, void *userdata)
563+
{
564+
Group_c *g = get_group_c(g_c, groupnumber);
565+
566+
if (!g) {
567+
return;
568+
}
569+
570+
int prev_peer_index = peer_in_chat(g, real_pk);
571+
572+
if (prev_peer_index >= 0) {
573+
delpeer(g_c, groupnumber, prev_peer_index, userdata, false);
574+
}
575+
576+
int prev_frozen_index = frozen_in_chat(g, real_pk);
577+
578+
if (prev_frozen_index >= 0) {
579+
delete_frozen(g, prev_frozen_index);
580+
}
581+
}
582+
535583
/* Add a peer to the group chat, or update an existing peer.
536584
*
537585
* fresh indicates whether we should consider this information on the peer to
@@ -584,6 +632,8 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p
584632
}
585633
}
586634

635+
delete_any_peer_with_pk(g_c, groupnumber, real_pk, userdata);
636+
587637
Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
588638

589639
if (temp == nullptr) {
@@ -1034,7 +1084,7 @@ int add_groupchat(Group_Chats *g_c, uint8_t type)
10341084
return groupnumber;
10351085
}
10361086

1037-
static int group_leave(const Group_Chats *g_c, uint32_t groupnumber);
1087+
static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool permanent);
10381088

10391089
/* Delete a groupchat from the chats array, informing the group first as
10401090
* appropriate.
@@ -1050,9 +1100,7 @@ int del_groupchat(Group_Chats *g_c, uint32_t groupnumber, bool leave_permanently
10501100
return -1;
10511101
}
10521102

1053-
if (leave_permanently) {
1054-
group_leave(g_c, groupnumber);
1055-
}
1103+
group_leave(g_c, groupnumber, leave_permanently);
10561104

10571105
for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
10581106
if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
@@ -1606,21 +1654,37 @@ static int group_new_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uin
16061654
}
16071655

16081656
/* send a kill_peer message
1609-
* return 0 on success
1610-
* return -1 on failure
1657+
* return true on success
16111658
*/
1612-
static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num)
1659+
static bool group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num)
16131660
{
16141661
uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH];
16151662

16161663
peer_num = net_htons(peer_num);
16171664
memcpy(packet, &peer_num, sizeof(uint16_t));
16181665

16191666
if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) {
1620-
return 0;
1667+
return true;
16211668
}
16221669

1623-
return -1;
1670+
return false;
1671+
}
1672+
1673+
/* send a freeze_peer message
1674+
* return true on success
1675+
*/
1676+
static bool group_freeze_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num)
1677+
{
1678+
uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH];
1679+
1680+
peer_num = net_htons(peer_num);
1681+
memcpy(packet, &peer_num, sizeof(uint16_t));
1682+
1683+
if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_FREEZE_PEER_ID, packet, sizeof(packet)) > 0) {
1684+
return true;
1685+
}
1686+
1687+
return false;
16241688
}
16251689

16261690
/* send a name message
@@ -1641,18 +1705,21 @@ static int group_name_send(const Group_Chats *g_c, uint32_t groupnumber, const u
16411705
}
16421706

16431707
/* send message to announce leaving group
1644-
* return 0 on success
1645-
* return -1 on failure
1708+
* return true on success
16461709
*/
1647-
static int group_leave(const Group_Chats *g_c, uint32_t groupnumber)
1710+
static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool permanent)
16481711
{
16491712
Group_c *g = get_group_c(g_c, groupnumber);
16501713

16511714
if (!g) {
1652-
return -1;
1715+
return false;
16531716
}
16541717

1655-
return group_kill_peer_send(g_c, groupnumber, g->peer_number);
1718+
if (permanent) {
1719+
return group_kill_peer_send(g_c, groupnumber, g->peer_number);
1720+
} else {
1721+
return group_freeze_peer_send(g_c, groupnumber, g->peer_number);
1722+
}
16561723
}
16571724

16581725

@@ -1744,11 +1811,11 @@ static bool get_peer_number(const Group_c *g, const uint8_t *real_pk, uint16_t *
17441811
return true;
17451812
}
17461813

1747-
for (uint32_t i = 0; i < g->numfrozen; ++i) {
1748-
if (id_equal(g->frozen[i].real_pk, real_pk)) {
1749-
*peer_number = g->frozen[i].peer_number;
1750-
return true;
1751-
}
1814+
const int frozen_index = frozen_in_chat(g, real_pk);
1815+
1816+
if (frozen_index >= 0) {
1817+
*peer_number = g->frozen[frozen_index].peer_number;
1818+
return true;
17521819
}
17531820

17541821
return false;
@@ -2497,9 +2564,24 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
24972564
memcpy(&peer_number, data, sizeof(uint16_t));
24982565
peer_number = net_ntohs(peer_number);
24992566

2500-
const int index = note_peer_active(g_c, groupnumber, peer_number, userdata);
2567+
uint32_t message_number;
2568+
memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));
2569+
message_number = net_ntohl(message_number);
2570+
2571+
const uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)];
2572+
const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1;
2573+
const uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1);
2574+
2575+
const bool ignore_frozen = message_id == GROUP_MESSAGE_FREEZE_PEER_ID;
2576+
2577+
const int index = ignore_frozen ? get_peer_index(g, peer_number)
2578+
: note_peer_active(g_c, groupnumber, peer_number, userdata);
25012579

25022580
if (index == -1) {
2581+
if (ignore_frozen) {
2582+
return;
2583+
}
2584+
25032585
/* If we don't know the peer this packet came from, then we query the
25042586
* list of peers from the relaying peer.
25052587
* (They would not have relayed it if they didn't know the peer.) */
@@ -2526,14 +2608,6 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
25262608
}
25272609
}
25282610

2529-
uint32_t message_number;
2530-
memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));
2531-
message_number = net_ntohl(message_number);
2532-
2533-
const uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)];
2534-
const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1;
2535-
const uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1);
2536-
25372611
if (!check_message_info(message_number, message_id, &g->group[index])) {
25382612
return;
25392613
}
@@ -2555,7 +2629,8 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
25552629
}
25562630
break;
25572631

2558-
case GROUP_MESSAGE_KILL_PEER_ID: {
2632+
case GROUP_MESSAGE_KILL_PEER_ID:
2633+
case GROUP_MESSAGE_FREEZE_PEER_ID: {
25592634
if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) {
25602635
return;
25612636
}
@@ -2565,7 +2640,11 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
25652640
kill_peer_number = net_ntohs(kill_peer_number);
25662641

25672642
if (peer_number == kill_peer_number) {
2568-
delpeer(g_c, groupnumber, index, userdata, false);
2643+
if (message_id == GROUP_MESSAGE_KILL_PEER_ID) {
2644+
delpeer(g_c, groupnumber, index, userdata, false);
2645+
} else {
2646+
freeze_peer(g_c, groupnumber, index, userdata);
2647+
}
25692648
} else {
25702649
return;
25712650
// TODO(irungentoo):
@@ -3011,7 +3090,7 @@ static uint8_t *save_conf(const Group_c *g, uint8_t *data)
30113090
host_to_lendian_bytes16(data, g->peer_number);
30123091
data += sizeof(uint16_t);
30133092

3014-
host_to_lendian_bytes32(data, g->numpeers - 1 + g->numfrozen);
3093+
uint8_t *numsaved_location = data;
30153094
data += sizeof(uint32_t);
30163095

30173096
*data = g->title_len;
@@ -3020,24 +3099,20 @@ static uint8_t *save_conf(const Group_c *g, uint8_t *data)
30203099
memcpy(data, g->title, g->title_len);
30213100
data += g->title_len;
30223101

3023-
#ifndef NDEBUG
3024-
bool found_self = false;
3025-
#endif
3102+
uint32_t numsaved = 0;
30263103

30273104
for (uint32_t j = 0; j < g->numpeers + g->numfrozen; ++j) {
30283105
const Group_Peer *peer = (j < g->numpeers) ? &g->group[j] : &g->frozen[j - g->numpeers];
30293106

30303107
if (id_equal(peer->real_pk, g->real_pk)) {
3031-
#ifndef NDEBUG
3032-
found_self = true;
3033-
#endif
30343108
continue;
30353109
}
30363110

30373111
data = save_peer(peer, data);
3112+
++numsaved;
30383113
}
30393114

3040-
assert(found_self);
3115+
host_to_lendian_bytes32(numsaved_location, numsaved);
30413116

30423117
return data;
30433118
}

0 commit comments

Comments
 (0)