mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
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
This commit is contained in:
parent
e08f631547
commit
e5561ad2b0
185
toxcore/group.c
185
toxcore/group.c
|
@ -42,6 +42,7 @@ typedef enum Group_Message_Id {
|
|||
GROUP_MESSAGE_PING_ID = 0,
|
||||
GROUP_MESSAGE_NEW_PEER_ID = 16,
|
||||
GROUP_MESSAGE_KILL_PEER_ID = 17,
|
||||
GROUP_MESSAGE_FREEZE_PEER_ID = 18,
|
||||
GROUP_MESSAGE_NAME_ID = 48,
|
||||
GROUP_MESSAGE_TITLE_ID = 49,
|
||||
} Group_Message_Id;
|
||||
|
@ -201,6 +202,17 @@ static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int frozen_in_chat(const Group_c *chat, const uint8_t *real_pk)
|
||||
{
|
||||
for (uint32_t i = 0; i < chat->numfrozen; ++i) {
|
||||
if (id_equal(chat->frozen[i].real_pk, real_pk)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if group with the given type and id is in group array.
|
||||
*
|
||||
|
@ -457,6 +469,34 @@ static int get_frozen_index(Group_c *g, uint16_t peer_number)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static bool delete_frozen(Group_c *g, uint32_t frozen_index)
|
||||
{
|
||||
if (frozen_index >= g->numfrozen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
--g->numfrozen;
|
||||
|
||||
if (g->numfrozen == 0) {
|
||||
free(g->frozen);
|
||||
g->frozen = nullptr;
|
||||
} else {
|
||||
if (g->numfrozen != frozen_index) {
|
||||
g->frozen[frozen_index] = g->frozen[g->numfrozen];
|
||||
}
|
||||
|
||||
Group_Peer *frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen));
|
||||
|
||||
if (frozen_temp == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g->frozen = frozen_temp;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Update last_active timestamp on peer, and thaw the peer if it is frozen.
|
||||
*
|
||||
* 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
|
|||
|
||||
++g->numpeers;
|
||||
|
||||
--g->numfrozen;
|
||||
|
||||
if (g->numfrozen == 0) {
|
||||
free(g->frozen);
|
||||
g->frozen = nullptr;
|
||||
} else {
|
||||
if (g->numfrozen != (uint32_t)frozen_index) {
|
||||
g->frozen[frozen_index] = g->frozen[g->numfrozen];
|
||||
}
|
||||
|
||||
Group_Peer *frozen_temp = (Group_Peer *)realloc(g->frozen, sizeof(Group_Peer) * (g->numfrozen));
|
||||
|
||||
if (frozen_temp == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
g->frozen = frozen_temp;
|
||||
if (!delete_frozen(g, frozen_index)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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
|
|||
return g->numpeers - 1;
|
||||
}
|
||||
|
||||
static int delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void *userdata, bool keep_connection);
|
||||
|
||||
static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_pk, void *userdata)
|
||||
{
|
||||
Group_c *g = get_group_c(g_c, groupnumber);
|
||||
|
||||
if (!g) {
|
||||
return;
|
||||
}
|
||||
|
||||
int prev_peer_index = peer_in_chat(g, real_pk);
|
||||
|
||||
if (prev_peer_index >= 0) {
|
||||
delpeer(g_c, groupnumber, prev_peer_index, userdata, false);
|
||||
}
|
||||
|
||||
int prev_frozen_index = frozen_in_chat(g, real_pk);
|
||||
|
||||
if (prev_frozen_index >= 0) {
|
||||
delete_frozen(g, prev_frozen_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a peer to the group chat, or update an existing peer.
|
||||
*
|
||||
* 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
|
|||
}
|
||||
}
|
||||
|
||||
delete_any_peer_with_pk(g_c, groupnumber, real_pk, userdata);
|
||||
|
||||
Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
|
||||
|
||||
if (temp == nullptr) {
|
||||
|
@ -1034,7 +1084,7 @@ int add_groupchat(Group_Chats *g_c, uint8_t type)
|
|||
return groupnumber;
|
||||
}
|
||||
|
||||
static int group_leave(const Group_Chats *g_c, uint32_t groupnumber);
|
||||
static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool permanent);
|
||||
|
||||
/* Delete a groupchat from the chats array, informing the group first as
|
||||
* appropriate.
|
||||
|
@ -1050,9 +1100,7 @@ int del_groupchat(Group_Chats *g_c, uint32_t groupnumber, bool leave_permanently
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (leave_permanently) {
|
||||
group_leave(g_c, groupnumber);
|
||||
}
|
||||
group_leave(g_c, groupnumber, leave_permanently);
|
||||
|
||||
for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
|
||||
if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
|
||||
|
@ -1606,10 +1654,9 @@ static int group_new_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uin
|
|||
}
|
||||
|
||||
/* send a kill_peer message
|
||||
* return 0 on success
|
||||
* return -1 on failure
|
||||
* return true on success
|
||||
*/
|
||||
static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num)
|
||||
static bool group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num)
|
||||
{
|
||||
uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH];
|
||||
|
||||
|
@ -1617,10 +1664,27 @@ static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, ui
|
|||
memcpy(packet, &peer_num, sizeof(uint16_t));
|
||||
|
||||
if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) {
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* send a freeze_peer message
|
||||
* return true on success
|
||||
*/
|
||||
static bool group_freeze_peer_send(const Group_Chats *g_c, uint32_t groupnumber, uint16_t peer_num)
|
||||
{
|
||||
uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH];
|
||||
|
||||
peer_num = net_htons(peer_num);
|
||||
memcpy(packet, &peer_num, sizeof(uint16_t));
|
||||
|
||||
if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_FREEZE_PEER_ID, packet, sizeof(packet)) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* send a name message
|
||||
|
@ -1641,18 +1705,21 @@ static int group_name_send(const Group_Chats *g_c, uint32_t groupnumber, const u
|
|||
}
|
||||
|
||||
/* send message to announce leaving group
|
||||
* return 0 on success
|
||||
* return -1 on failure
|
||||
* return true on success
|
||||
*/
|
||||
static int group_leave(const Group_Chats *g_c, uint32_t groupnumber)
|
||||
static bool group_leave(const Group_Chats *g_c, uint32_t groupnumber, bool permanent)
|
||||
{
|
||||
Group_c *g = get_group_c(g_c, groupnumber);
|
||||
|
||||
if (!g) {
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return group_kill_peer_send(g_c, groupnumber, g->peer_number);
|
||||
if (permanent) {
|
||||
return group_kill_peer_send(g_c, groupnumber, g->peer_number);
|
||||
} else {
|
||||
return group_freeze_peer_send(g_c, groupnumber, g->peer_number);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1744,11 +1811,11 @@ static bool get_peer_number(const Group_c *g, const uint8_t *real_pk, uint16_t *
|
|||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < g->numfrozen; ++i) {
|
||||
if (id_equal(g->frozen[i].real_pk, real_pk)) {
|
||||
*peer_number = g->frozen[i].peer_number;
|
||||
return true;
|
||||
}
|
||||
const int frozen_index = frozen_in_chat(g, real_pk);
|
||||
|
||||
if (frozen_index >= 0) {
|
||||
*peer_number = g->frozen[frozen_index].peer_number;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -2497,9 +2564,24 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
|
|||
memcpy(&peer_number, data, sizeof(uint16_t));
|
||||
peer_number = net_ntohs(peer_number);
|
||||
|
||||
const int index = note_peer_active(g_c, groupnumber, peer_number, userdata);
|
||||
uint32_t message_number;
|
||||
memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));
|
||||
message_number = net_ntohl(message_number);
|
||||
|
||||
const uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)];
|
||||
const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1;
|
||||
const uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1);
|
||||
|
||||
const bool ignore_frozen = message_id == GROUP_MESSAGE_FREEZE_PEER_ID;
|
||||
|
||||
const int index = ignore_frozen ? get_peer_index(g, peer_number)
|
||||
: note_peer_active(g_c, groupnumber, peer_number, userdata);
|
||||
|
||||
if (index == -1) {
|
||||
if (ignore_frozen) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we don't know the peer this packet came from, then we query the
|
||||
* list of peers from the relaying peer.
|
||||
* (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,
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t message_number;
|
||||
memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));
|
||||
message_number = net_ntohl(message_number);
|
||||
|
||||
const uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)];
|
||||
const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1;
|
||||
const uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1);
|
||||
|
||||
if (!check_message_info(message_number, message_id, &g->group[index])) {
|
||||
return;
|
||||
}
|
||||
|
@ -2555,7 +2629,8 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
|
|||
}
|
||||
break;
|
||||
|
||||
case GROUP_MESSAGE_KILL_PEER_ID: {
|
||||
case GROUP_MESSAGE_KILL_PEER_ID:
|
||||
case GROUP_MESSAGE_FREEZE_PEER_ID: {
|
||||
if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) {
|
||||
return;
|
||||
}
|
||||
|
@ -2565,7 +2640,11 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
|
|||
kill_peer_number = net_ntohs(kill_peer_number);
|
||||
|
||||
if (peer_number == kill_peer_number) {
|
||||
delpeer(g_c, groupnumber, index, userdata, false);
|
||||
if (message_id == GROUP_MESSAGE_KILL_PEER_ID) {
|
||||
delpeer(g_c, groupnumber, index, userdata, false);
|
||||
} else {
|
||||
freeze_peer(g_c, groupnumber, index, userdata);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
// TODO(irungentoo):
|
||||
|
@ -3011,7 +3090,7 @@ static uint8_t *save_conf(const Group_c *g, uint8_t *data)
|
|||
host_to_lendian_bytes16(data, g->peer_number);
|
||||
data += sizeof(uint16_t);
|
||||
|
||||
host_to_lendian_bytes32(data, g->numpeers - 1 + g->numfrozen);
|
||||
uint8_t *numsaved_location = data;
|
||||
data += sizeof(uint32_t);
|
||||
|
||||
*data = g->title_len;
|
||||
|
@ -3020,24 +3099,20 @@ static uint8_t *save_conf(const Group_c *g, uint8_t *data)
|
|||
memcpy(data, g->title, g->title_len);
|
||||
data += g->title_len;
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool found_self = false;
|
||||
#endif
|
||||
uint32_t numsaved = 0;
|
||||
|
||||
for (uint32_t j = 0; j < g->numpeers + g->numfrozen; ++j) {
|
||||
const Group_Peer *peer = (j < g->numpeers) ? &g->group[j] : &g->frozen[j - g->numpeers];
|
||||
|
||||
if (id_equal(peer->real_pk, g->real_pk)) {
|
||||
#ifndef NDEBUG
|
||||
found_self = true;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
data = save_peer(peer, data);
|
||||
++numsaved;
|
||||
}
|
||||
|
||||
assert(found_self);
|
||||
host_to_lendian_bytes32(numsaved_location, numsaved);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user