diff options
author | zugz (tox) <mbays+tox@sdf.org> | 2018-11-17 21:33:46 +0100 |
---|---|---|
committer | iphydf <iphydf@users.noreply.github.com> | 2019-01-06 19:37:33 +0000 |
commit | e5561ad2b0db69cc58ce6d858bd6aca1928b0d8f (patch) | |
tree | 1cb55c7639edebb4f2d8c877eb898be81534592b /toxcore | |
parent | e08f631547612a807922adc50f12ed8d2231a955 (diff) |
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
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/group.c | 185 |
1 files changed, 130 insertions, 55 deletions
diff --git a/toxcore/group.c b/toxcore/group.c index b345a01c..dfa821a4 100644 --- a/toxcore/group.c +++ b/toxcore/group.c | |||
@@ -42,6 +42,7 @@ typedef enum Group_Message_Id { | |||
42 | GROUP_MESSAGE_PING_ID = 0, | 42 | GROUP_MESSAGE_PING_ID = 0, |
43 | GROUP_MESSAGE_NEW_PEER_ID = 16, | 43 | GROUP_MESSAGE_NEW_PEER_ID = 16, |
44 | GROUP_MESSAGE_KILL_PEER_ID = 17, | 44 | GROUP_MESSAGE_KILL_PEER_ID = 17, |
45 | GROUP_MESSAGE_FREEZE_PEER_ID = 18, | ||
45 | GROUP_MESSAGE_NAME_ID = 48, | 46 | GROUP_MESSAGE_NAME_ID = 48, |
46 | GROUP_MESSAGE_TITLE_ID = 49, | 47 | GROUP_MESSAGE_TITLE_ID = 49, |
47 | } Group_Message_Id; | 48 | } Group_Message_Id; |
@@ -201,6 +202,17 @@ static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk) | |||
201 | return -1; | 202 | return -1; |
202 | } | 203 | } |
203 | 204 | ||
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 | |||
204 | /* | 216 | /* |
205 | * check if group with the given type and id is in group array. | 217 | * check if group with the given type and id is in group array. |
206 | * | 218 | * |
@@ -457,6 +469,34 @@ static int get_frozen_index(Group_c *g, uint16_t peer_number) | |||
457 | return -1; | 469 | return -1; |
458 | } | 470 | } |
459 | 471 | ||
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 | |||
460 | /* Update last_active timestamp on peer, and thaw the peer if it is frozen. | 500 | /* Update last_active timestamp on peer, and thaw the peer if it is frozen. |
461 | * | 501 | * |
462 | * return peer index if peer is in the conference. | 502 | * 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 | |||
500 | 540 | ||
501 | ++g->numpeers; | 541 | ++g->numpeers; |
502 | 542 | ||
503 | --g->numfrozen; | 543 | if (!delete_frozen(g, frozen_index)) { |
504 | 544 | return -1; | |
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; | ||
520 | } | 545 | } |
521 | 546 | ||
522 | if (g_c->peer_list_changed_callback) { | 547 | 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 | |||
532 | return g->numpeers - 1; | 557 | return g->numpeers - 1; |
533 | } | 558 | } |
534 | 559 | ||
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 | |||
535 | /* Add a peer to the group chat, or update an existing peer. | 583 | /* Add a peer to the group chat, or update an existing peer. |
536 | * | 584 | * |
537 | * fresh indicates whether we should consider this information on the peer to | 585 | * 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 | |||
584 | } | 632 | } |
585 | } | 633 | } |
586 | 634 | ||
635 | delete_any_peer_with_pk(g_c, groupnumber, real_pk, userdata); | ||
636 | |||
587 | Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1)); | 637 | Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1)); |
588 | 638 | ||
589 | if (temp == nullptr) { | 639 | if (temp == nullptr) { |
@@ -1034,7 +1084,7 @@ int add_groupchat(Group_Chats *g_c, uint8_t type) | |||
1034 | return groupnumber; | 1084 | return groupnumber; |
1035 | } | 1085 | } |
1036 | 1086 | ||
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); |
1038 | 1088 | ||
1039 | /* Delete a groupchat from the chats array, informing the group first as | 1089 | /* Delete a groupchat from the chats array, informing the group first as |
1040 | * appropriate. | 1090 | * appropriate. |
@@ -1050,9 +1100,7 @@ int del_groupchat(Group_Chats *g_c, uint32_t groupnumber, bool leave_permanently | |||
1050 | return -1; | 1100 | return -1; |
1051 | } | 1101 | } |
1052 | 1102 | ||
1053 | if (leave_permanently) { | 1103 | group_leave(g_c, groupnumber, leave_permanently); |
1054 | group_leave(g_c, groupnumber); | ||
1055 | } | ||
1056 | 1104 | ||
1057 | for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | 1105 | for (uint32_t i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { |
1058 | if (g->close[i].type == GROUPCHAT_CLOSE_NONE) { | 1106 | 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 | |||
1606 | } | 1654 | } |
1607 | 1655 | ||
1608 | /* send a kill_peer message | 1656 | /* send a kill_peer message |
1609 | * return 0 on success | 1657 | * return true on success |
1610 | * return -1 on failure | ||
1611 | */ | 1658 | */ |
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) |
1613 | { | 1660 | { |
1614 | uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH]; | 1661 | uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH]; |
1615 | 1662 | ||
@@ -1617,10 +1664,27 @@ static int group_kill_peer_send(const Group_Chats *g_c, uint32_t groupnumber, ui | |||
1617 | memcpy(packet, &peer_num, sizeof(uint16_t)); | 1664 | memcpy(packet, &peer_num, sizeof(uint16_t)); |
1618 | 1665 | ||
1619 | if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) { | 1666 | if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) { |
1620 | return 0; | 1667 | return true; |
1621 | } | 1668 | } |
1622 | 1669 | ||
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; | ||
1624 | } | 1688 | } |
1625 | 1689 | ||
1626 | /* send a name message | 1690 | /* send a name message |
@@ -1641,18 +1705,21 @@ static int group_name_send(const Group_Chats *g_c, uint32_t groupnumber, const u | |||
1641 | } | 1705 | } |
1642 | 1706 | ||
1643 | /* send message to announce leaving group | 1707 | /* send message to announce leaving group |
1644 | * return 0 on success | 1708 | * return true on success |
1645 | * return -1 on failure | ||
1646 | */ | 1709 | */ |
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) |
1648 | { | 1711 | { |
1649 | Group_c *g = get_group_c(g_c, groupnumber); | 1712 | Group_c *g = get_group_c(g_c, groupnumber); |
1650 | 1713 | ||
1651 | if (!g) { | 1714 | if (!g) { |
1652 | return -1; | 1715 | return false; |
1653 | } | 1716 | } |
1654 | 1717 | ||
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 | } | ||
1656 | } | 1723 | } |
1657 | 1724 | ||
1658 | 1725 | ||
@@ -1744,11 +1811,11 @@ static bool get_peer_number(const Group_c *g, const uint8_t *real_pk, uint16_t * | |||
1744 | return true; | 1811 | return true; |
1745 | } | 1812 | } |
1746 | 1813 | ||
1747 | for (uint32_t i = 0; i < g->numfrozen; ++i) { | 1814 | const int frozen_index = frozen_in_chat(g, real_pk); |
1748 | if (id_equal(g->frozen[i].real_pk, real_pk)) { | 1815 | |
1749 | *peer_number = g->frozen[i].peer_number; | 1816 | if (frozen_index >= 0) { |
1750 | return true; | 1817 | *peer_number = g->frozen[frozen_index].peer_number; |
1751 | } | 1818 | return true; |
1752 | } | 1819 | } |
1753 | 1820 | ||
1754 | return false; | 1821 | return false; |
@@ -2497,9 +2564,24 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, | |||
2497 | memcpy(&peer_number, data, sizeof(uint16_t)); | 2564 | memcpy(&peer_number, data, sizeof(uint16_t)); |
2498 | peer_number = net_ntohs(peer_number); | 2565 | peer_number = net_ntohs(peer_number); |
2499 | 2566 | ||
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); | ||
2501 | 2579 | ||
2502 | if (index == -1) { | 2580 | if (index == -1) { |
2581 | if (ignore_frozen) { | ||
2582 | return; | ||
2583 | } | ||
2584 | |||
2503 | /* If we don't know the peer this packet came from, then we query the | 2585 | /* If we don't know the peer this packet came from, then we query the |
2504 | * list of peers from the relaying peer. | 2586 | * list of peers from the relaying peer. |
2505 | * (They would not have relayed it if they didn't know the peer.) */ | 2587 | * (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, | |||
2526 | } | 2608 | } |
2527 | } | 2609 | } |
2528 | 2610 | ||
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 | |||
2537 | if (!check_message_info(message_number, message_id, &g->group[index])) { | 2611 | if (!check_message_info(message_number, message_id, &g->group[index])) { |
2538 | return; | 2612 | return; |
2539 | } | 2613 | } |
@@ -2555,7 +2629,8 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, | |||
2555 | } | 2629 | } |
2556 | break; | 2630 | break; |
2557 | 2631 | ||
2558 | case GROUP_MESSAGE_KILL_PEER_ID: { | 2632 | case GROUP_MESSAGE_KILL_PEER_ID: |
2633 | case GROUP_MESSAGE_FREEZE_PEER_ID: { | ||
2559 | if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) { | 2634 | if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) { |
2560 | return; | 2635 | return; |
2561 | } | 2636 | } |
@@ -2565,7 +2640,11 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, | |||
2565 | kill_peer_number = net_ntohs(kill_peer_number); | 2640 | kill_peer_number = net_ntohs(kill_peer_number); |
2566 | 2641 | ||
2567 | if (peer_number == kill_peer_number) { | 2642 | 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 | } | ||
2569 | } else { | 2648 | } else { |
2570 | return; | 2649 | return; |
2571 | // TODO(irungentoo): | 2650 | // TODO(irungentoo): |
@@ -3011,7 +3090,7 @@ static uint8_t *save_conf(const Group_c *g, uint8_t *data) | |||
3011 | host_to_lendian_bytes16(data, g->peer_number); | 3090 | host_to_lendian_bytes16(data, g->peer_number); |
3012 | data += sizeof(uint16_t); | 3091 | data += sizeof(uint16_t); |
3013 | 3092 | ||
3014 | host_to_lendian_bytes32(data, g->numpeers - 1 + g->numfrozen); | 3093 | uint8_t *numsaved_location = data; |
3015 | data += sizeof(uint32_t); | 3094 | data += sizeof(uint32_t); |
3016 | 3095 | ||
3017 | *data = g->title_len; | 3096 | *data = g->title_len; |
@@ -3020,24 +3099,20 @@ static uint8_t *save_conf(const Group_c *g, uint8_t *data) | |||
3020 | memcpy(data, g->title, g->title_len); | 3099 | memcpy(data, g->title, g->title_len); |
3021 | data += g->title_len; | 3100 | data += g->title_len; |
3022 | 3101 | ||
3023 | #ifndef NDEBUG | 3102 | uint32_t numsaved = 0; |
3024 | bool found_self = false; | ||
3025 | #endif | ||
3026 | 3103 | ||
3027 | for (uint32_t j = 0; j < g->numpeers + g->numfrozen; ++j) { | 3104 | for (uint32_t j = 0; j < g->numpeers + g->numfrozen; ++j) { |
3028 | const Group_Peer *peer = (j < g->numpeers) ? &g->group[j] : &g->frozen[j - g->numpeers]; | 3105 | const Group_Peer *peer = (j < g->numpeers) ? &g->group[j] : &g->frozen[j - g->numpeers]; |
3029 | 3106 | ||
3030 | if (id_equal(peer->real_pk, g->real_pk)) { | 3107 | if (id_equal(peer->real_pk, g->real_pk)) { |
3031 | #ifndef NDEBUG | ||
3032 | found_self = true; | ||
3033 | #endif | ||
3034 | continue; | 3108 | continue; |
3035 | } | 3109 | } |
3036 | 3110 | ||
3037 | data = save_peer(peer, data); | 3111 | data = save_peer(peer, data); |
3112 | ++numsaved; | ||
3038 | } | 3113 | } |
3039 | 3114 | ||
3040 | assert(found_self); | 3115 | host_to_lendian_bytes32(numsaved_location, numsaved); |
3041 | 3116 | ||
3042 | return data; | 3117 | return data; |
3043 | } | 3118 | } |