diff options
author | zugz <mbays+tox@sdf.org> | 2018-07-25 08:46:28 +0100 |
---|---|---|
committer | zugz (tox) <mbays+tox@sdf.org> | 2018-08-02 22:03:18 +0100 |
commit | aa63c1330c49ee1c4b675037e2e54516950203a2 (patch) | |
tree | d9064b106cd62e7c7fbc212c4dbaefc0298d977b /toxcore/group.c | |
parent | 3a4987da18b165d5a5297ddaf64f1336958bb3c7 (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.c | 141 |
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 | */ |
1066 | int invite_friend(Group_Chats *g_c, uint32_t friendnumber, uint32_t groupnumber) | 1075 | int 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 | ||
2043 | static 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 | */ | ||
2071 | static 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 | |||
2040 | static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length, | 2095 | static 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) { |