summaryrefslogtreecommitdiff
path: root/toxcore/group.c
diff options
context:
space:
mode:
authorzugz <mbays+tox@sdf.org>2018-07-25 08:46:28 +0100
committerzugz (tox) <mbays+tox@sdf.org>2018-08-02 22:03:18 +0100
commitaa63c1330c49ee1c4b675037e2e54516950203a2 (patch)
treed9064b106cd62e7c7fbc212c4dbaefc0298d977b /toxcore/group.c
parent3a4987da18b165d5a5297ddaf64f1336958bb3c7 (diff)
Fix problems with initial connections and name-setting in conferences
* test names in conference_test * raise error on attempt to invite friend to group before we are connected * revise handling of temporary invited connections We are now careful not to prematurely delete a connection to a peer established during the invitation process; namely, before we have sufficient other connections and have confirmed that we have an alternative route to the peer. * process out-of-order messages from a peer * don't reset names when handling a Peer Response
Diffstat (limited to 'toxcore/group.c')
-rw-r--r--toxcore/group.c141
1 files changed, 107 insertions, 34 deletions
diff --git a/toxcore/group.c b/toxcore/group.c
index 826ea239..317b885f 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -405,8 +405,12 @@ static int connect_to_closest(Group_Chats *g_c, uint32_t groupnumber, void *user
405 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number); 405 get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number);
406 406
407 if (!pk_in_closest_peers(g, real_pk)) { 407 if (!pk_in_closest_peers(g, real_pk)) {
408 g->close[i].type = GROUPCHAT_CLOSE_NONE; 408 g->close[i].closest = false;
409 kill_friend_connection(g_c->fr_c, g->close[i].number); 409
410 if (!g->close[i].introducer && !g->close[i].introduced) {
411 g->close[i].type = GROUPCHAT_CLOSE_NONE;
412 kill_friend_connection(g_c->fr_c, g->close[i].number);
413 }
410 } 414 }
411 } 415 }
412 416
@@ -618,6 +622,8 @@ static int setnick(Group_Chats *g_c, uint32_t groupnumber, int peer_index, const
618 return -1; 622 return -1;
619 } 623 }
620 624
625 g->group[peer_index].nick_updated = true;
626
621 /* same name as already stored? */ 627 /* same name as already stored? */
622 if (g->group[peer_index].nick_len == nick_len) { 628 if (g->group[peer_index].nick_len == nick_len) {
623 if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len)) { 629 if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len)) {
@@ -740,7 +746,7 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t gr
740 } 746 }
741 747
742 if (g->close[i].number == (uint32_t)friendcon_id) { 748 if (g->close[i].number == (uint32_t)friendcon_id) {
743 g->close[i].closest = closest; 749 g->close[i].closest |= closest;
744 return i; /* Already in list. */ 750 return i; /* Already in list. */
745 } 751 }
746 } 752 }
@@ -756,6 +762,8 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, uint32_t gr
756 g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION; 762 g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION;
757 g->close[ind].number = friendcon_id; 763 g->close[ind].number = friendcon_id;
758 g->close[ind].closest = closest; 764 g->close[ind].closest = closest;
765 g->close[ind].introducer = false;
766 g->close[ind].introduced = false;
759 // TODO(irungentoo): 767 // TODO(irungentoo):
760 friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &g_handle_status, &g_handle_packet, 768 friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &g_handle_status, &g_handle_packet,
761 &handle_lossy, g_c, friendcon_id); 769 &handle_lossy, g_c, friendcon_id);
@@ -1062,6 +1070,7 @@ static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendco
1062 * return 0 on success. 1070 * return 0 on success.
1063 * return -1 if groupnumber is invalid. 1071 * return -1 if groupnumber is invalid.
1064 * return -2 if invite packet failed to send. 1072 * return -2 if invite packet failed to send.
1073 * return -3 if we are not connected to the group chat.
1065 */ 1074 */
1066int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber) 1075int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber)
1067{ 1076{
@@ -1071,6 +1080,10 @@ int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber)
1071 return -1; 1080 return -1;
1072 } 1081 }
1073 1082
1083 if (g->status != GROUPCHAT_STATUS_CONNECTED) {
1084 return -3;
1085 }
1086
1074 uint8_t invite[INVITE_PACKET_SIZE]; 1087 uint8_t invite[INVITE_PACKET_SIZE];
1075 invite[0] = INVITE_ID; 1088 invite[0] = INVITE_ID;
1076 uint16_t groupchat_num = net_htons((uint16_t)groupnumber); 1089 uint16_t groupchat_num = net_htons((uint16_t)groupnumber);
@@ -1081,7 +1094,6 @@ int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber)
1081 return 0; 1094 return 0;
1082 } 1095 }
1083 1096
1084 wipe_group_chat(g_c, groupnumber);
1085 return -2; 1097 return -2;
1086} 1098}
1087 1099
@@ -1148,6 +1160,7 @@ int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_typ
1148 g->close[close_index].group_number = other_groupnum; 1160 g->close[close_index].group_number = other_groupnum;
1149 g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE; 1161 g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE;
1150 g->number_joined = friendcon_id; 1162 g->number_joined = friendcon_id;
1163 g->close[close_index].introducer = true;
1151 } 1164 }
1152 1165
1153 send_peer_query(g_c, friendcon_id, other_groupnum); 1166 send_peer_query(g_c, friendcon_id, other_groupnum);
@@ -1503,6 +1516,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
1503 if (close_index != -1) { 1516 if (close_index != -1) {
1504 g->close[close_index].group_number = other_groupnum; 1517 g->close[close_index].group_number = other_groupnum;
1505 g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE; 1518 g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE;
1519 g->close[close_index].introduced = true;
1506 } 1520 }
1507 1521
1508 group_new_peer_send(g_c, groupnum, peer_number, real_pk, temp_pk); 1522 group_new_peer_send(g_c, groupnum, peer_number, real_pk, temp_pk);
@@ -1606,21 +1620,6 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_
1606 g->close[index].type = GROUPCHAT_CLOSE_ONLINE; 1620 g->close[index].type = GROUPCHAT_CLOSE_ONLINE;
1607 send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier); 1621 send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
1608 1622
1609 if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) {
1610 int fr_close_index = friend_in_close(g, g->number_joined);
1611
1612 if (fr_close_index == -1) {
1613 return -1;
1614 }
1615
1616 if (!g->close[fr_close_index].closest) {
1617 g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE;
1618 send_peer_kill(g_c, g->close[fr_close_index].number, g->close[fr_close_index].group_number);
1619 kill_friend_connection(g_c->fr_c, g->close[fr_close_index].number);
1620 g->number_joined = -1;
1621 }
1622 }
1623
1624 return 0; 1623 return 0;
1625} 1624}
1626 1625
@@ -1729,11 +1728,6 @@ static int handle_send_peers(Group_Chats *g_c, uint32_t groupnumber, const uint8
1729 memcpy(&peer_num, d, sizeof(peer_num)); 1728 memcpy(&peer_num, d, sizeof(peer_num));
1730 peer_num = net_ntohs(peer_num); 1729 peer_num = net_ntohs(peer_num);
1731 d += sizeof(uint16_t); 1730 d += sizeof(uint16_t);
1732 int peer_index = addpeer(g_c, groupnumber, d, d + CRYPTO_PUBLIC_KEY_SIZE, peer_num, userdata, true);
1733
1734 if (peer_index == -1) {
1735 return -1;
1736 }
1737 1731
1738 if (g->status == GROUPCHAT_STATUS_VALID 1732 if (g->status == GROUPCHAT_STATUS_VALID
1739 && public_key_cmp(d, nc_get_self_public_key(g_c->m->net_crypto)) == 0) { 1733 && public_key_cmp(d, nc_get_self_public_key(g_c->m->net_crypto)) == 0) {
@@ -1742,6 +1736,12 @@ static int handle_send_peers(Group_Chats *g_c, uint32_t groupnumber, const uint8
1742 group_name_send(g_c, groupnumber, g_c->m->name, g_c->m->name_length); 1736 group_name_send(g_c, groupnumber, g_c->m->name, g_c->m->name_length);
1743 } 1737 }
1744 1738
1739 int peer_index = addpeer(g_c, groupnumber, d, d + CRYPTO_PUBLIC_KEY_SIZE, peer_num, userdata, true);
1740
1741 if (peer_index == -1) {
1742 return -1;
1743 }
1744
1745 d += CRYPTO_PUBLIC_KEY_SIZE * 2; 1745 d += CRYPTO_PUBLIC_KEY_SIZE * 2;
1746 uint8_t name_length = *d; 1746 uint8_t name_length = *d;
1747 d += 1; 1747 d += 1;
@@ -1750,7 +1750,10 @@ static int handle_send_peers(Group_Chats *g_c, uint32_t groupnumber, const uint8
1750 return -1; 1750 return -1;
1751 } 1751 }
1752 1752
1753 setnick(g_c, groupnumber, peer_index, d, name_length, userdata, true); 1753 if (!g->group[peer_index].nick_updated) {
1754 setnick(g_c, groupnumber, peer_index, d, name_length, userdata, true);
1755 }
1756
1754 d += name_length; 1757 d += name_length;
1755 } 1758 }
1756 1759
@@ -2037,6 +2040,58 @@ int send_group_lossy_packet(const Group_Chats *g_c, uint32_t groupnumber, const
2037 return 0; 2040 return 0;
2038} 2041}
2039 2042
2043static Message_Info *find_message_slot_or_reject(uint32_t message_number, uint8_t message_id, Group_Peer *peer)
2044{
2045 const bool ignore_older = (message_id == GROUP_MESSAGE_NAME_ID || message_id == GROUP_MESSAGE_TITLE_ID);
2046
2047 Message_Info *i;
2048
2049 for (i = peer->last_message_infos; i < peer->last_message_infos + peer->num_last_message_infos; ++i) {
2050 if (message_number > i->message_number) {
2051 break;
2052 }
2053
2054 if (message_number == i->message_number) {
2055 return nullptr;
2056 }
2057
2058 if (ignore_older && message_id == i->message_id) {
2059 return nullptr;
2060 }
2061 }
2062
2063 return i;
2064}
2065
2066/* Stores message info in peer->last_message_infos.
2067 *
2068 * return true if message should be processed;
2069 * return false otherwise.
2070 */
2071static bool check_message_info(uint32_t message_number, uint8_t message_id, Group_Peer *peer)
2072{
2073 Message_Info *const i = find_message_slot_or_reject(message_number, message_id, peer);
2074
2075 if (i == nullptr) {
2076 return false;
2077 }
2078
2079 if (i == peer->last_message_infos + MAX_LAST_MESSAGE_INFOS) {
2080 return false;
2081 }
2082
2083 if (peer->num_last_message_infos < MAX_LAST_MESSAGE_INFOS) {
2084 ++peer->num_last_message_infos;
2085 }
2086
2087 memmove(i + 1, i, ((peer->last_message_infos + peer->num_last_message_infos - 1) - i) * sizeof(Message_Info));
2088
2089 i->message_number = message_number;
2090 i->message_id = message_id;
2091
2092 return true;
2093}
2094
2040static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length, 2095static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length,
2041 int close_index, void *userdata) 2096 int close_index, void *userdata)
2042{ 2097{
@@ -2063,23 +2118,41 @@ static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber,
2063 return; 2118 return;
2064 } 2119 }
2065 2120
2121 if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) {
2122 const int fr_close_index = friend_in_close(g, g->number_joined);
2123
2124 if (fr_close_index >= 0 && fr_close_index != close_index && !g->close[fr_close_index].closest) {
2125 uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
2126 get_friendcon_public_keys(real_pk, nullptr, g_c->fr_c, g->close[fr_close_index].number);
2127
2128 if (id_equal(g->group[index].real_pk, real_pk)) {
2129 /* Received message from peer relayed via another peer, so
2130 * the introduction was successful */
2131 g->number_joined = -1;
2132 g->close[fr_close_index].introducer = false;
2133
2134 if (!g->close[fr_close_index].closest && !g->close[fr_close_index].introduced) {
2135 g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE;
2136 send_peer_kill(g_c, g->close[fr_close_index].number, g->close[fr_close_index].group_number);
2137 kill_friend_connection(g_c->fr_c, g->close[fr_close_index].number);
2138 }
2139 }
2140 }
2141 }
2142
2066 uint32_t message_number; 2143 uint32_t message_number;
2067 memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number)); 2144 memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));
2068 message_number = net_ntohl(message_number); 2145 message_number = net_ntohl(message_number);
2069 2146
2070 if (g->group[index].last_message_number == 0) {
2071 g->group[index].last_message_number = message_number;
2072 } else if (message_number - g->group[index].last_message_number > 64 ||
2073 message_number == g->group[index].last_message_number) {
2074 return;
2075 }
2076
2077 g->group[index].last_message_number = message_number;
2078
2079 uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)]; 2147 uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)];
2080 const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1; 2148 const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1;
2081 uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1); 2149 uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1);
2082 2150
2151 // FIXME(zugz) update discussion of message numbers in the spec
2152 if (!check_message_info(message_number, message_id, &g->group[index])) {
2153 return;
2154 }
2155
2083 switch (message_id) { 2156 switch (message_id) {
2084 case GROUP_MESSAGE_PING_ID: { 2157 case GROUP_MESSAGE_PING_ID: {
2085 if (msg_data_len != 0) { 2158 if (msg_data_len != 0) {