diff options
author | zugz (tox) <mbays+tox@sdf.org> | 2020-03-01 00:00:00 +0000 |
---|---|---|
committer | zugz (tox) <mbays+tox@sdf.org> | 2020-03-18 00:00:00 +0000 |
commit | db07bda7f7b1ab7f5f219a9ed3d7f732b7da66b0 (patch) | |
tree | e5b4e5b43320c4073b619c006c1b32040cd06b8d /toxcore | |
parent | 84e6a8d05704d9f4db79898984af861d759c478a (diff) |
Add "member" invite response
This allows invitations to work in the case that the invitee is already
in the group, which can happen if the group becomes split. Such an
invitation is automatically accepted, leading to the peers becoming
connected in the group and sharing peer lists.
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/group.c | 128 |
1 files changed, 91 insertions, 37 deletions
diff --git a/toxcore/group.c b/toxcore/group.c index 50f6f2fe..b4248fd8 100644 --- a/toxcore/group.c +++ b/toxcore/group.c | |||
@@ -39,11 +39,13 @@ typedef enum Group_Message_Id { | |||
39 | 39 | ||
40 | typedef enum Invite_Id { | 40 | typedef enum Invite_Id { |
41 | INVITE_ID = 0, | 41 | INVITE_ID = 0, |
42 | INVITE_RESPONSE_ID = 1, | 42 | INVITE_ACCEPT_ID = 1, |
43 | INVITE_MEMBER_ID = 2, | ||
43 | } Invite_Id; | 44 | } Invite_Id; |
44 | 45 | ||
45 | #define INVITE_PACKET_SIZE (1 + sizeof(uint16_t) + 1 + GROUP_ID_LENGTH) | 46 | #define INVITE_PACKET_SIZE (1 + sizeof(uint16_t) + 1 + GROUP_ID_LENGTH) |
46 | #define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + 1 + GROUP_ID_LENGTH) | 47 | #define INVITE_ACCEPT_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + 1 + GROUP_ID_LENGTH) |
48 | #define INVITE_MEMBER_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + 1 + GROUP_ID_LENGTH + sizeof(uint16_t)) | ||
47 | 49 | ||
48 | #define ONLINE_PACKET_DATA_SIZE (sizeof(uint16_t) + 1 + GROUP_ID_LENGTH) | 50 | #define ONLINE_PACKET_DATA_SIZE (sizeof(uint16_t) + 1 + GROUP_ID_LENGTH) |
49 | 51 | ||
@@ -1512,6 +1514,9 @@ static bool try_send_rejoin(Group_Chats *g_c, Group_c *g, const uint8_t *real_pk | |||
1512 | 1514 | ||
1513 | static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); | 1515 | static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); |
1514 | 1516 | ||
1517 | static bool send_invite_response(Group_Chats *g_c, int groupnumber, uint32_t friendnumber, const uint8_t *data, | ||
1518 | uint16_t length); | ||
1519 | |||
1515 | /* Join a group (we need to have been invited first.) | 1520 | /* Join a group (we need to have been invited first.) |
1516 | * | 1521 | * |
1517 | * expected_type is the groupchat type we expect the chat we are joining to | 1522 | * expected_type is the groupchat type we expect the chat we are joining to |
@@ -1553,35 +1558,65 @@ int join_groupchat(Group_Chats *g_c, uint32_t friendnumber, uint8_t expected_typ | |||
1553 | 1558 | ||
1554 | Group_c *g = &g_c->chats[groupnumber]; | 1559 | Group_c *g = &g_c->chats[groupnumber]; |
1555 | 1560 | ||
1556 | const uint16_t group_num = net_htons(groupnumber); | ||
1557 | g->status = GROUPCHAT_STATUS_VALID; | 1561 | g->status = GROUPCHAT_STATUS_VALID; |
1558 | memcpy(g->real_pk, nc_get_self_public_key(g_c->m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE); | 1562 | memcpy(g->real_pk, nc_get_self_public_key(g_c->m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE); |
1559 | 1563 | ||
1560 | uint8_t response[INVITE_RESPONSE_PACKET_SIZE]; | 1564 | if (!send_invite_response(g_c, groupnumber, friendnumber, data, length)) { |
1561 | response[0] = INVITE_RESPONSE_ID; | 1565 | g->status = GROUPCHAT_STATUS_NONE; |
1562 | memcpy(response + 1, &group_num, sizeof(uint16_t)); | 1566 | return -6; |
1563 | memcpy(response + 1 + sizeof(uint16_t), data, sizeof(uint16_t) + 1 + GROUP_ID_LENGTH); | 1567 | } |
1568 | |||
1569 | return groupnumber; | ||
1570 | } | ||
1571 | |||
1572 | static bool send_invite_response(Group_Chats *g_c, int groupnumber, uint32_t friendnumber, const uint8_t *data, | ||
1573 | uint16_t length) | ||
1574 | { | ||
1575 | Group_c *g = get_group_c(g_c, groupnumber); | ||
1576 | |||
1577 | const bool member = (g->status == GROUPCHAT_STATUS_CONNECTED); | ||
1578 | |||
1579 | VLA(uint8_t, response, member ? INVITE_MEMBER_PACKET_SIZE : INVITE_ACCEPT_PACKET_SIZE); | ||
1580 | response[0] = member ? INVITE_MEMBER_ID : INVITE_ACCEPT_ID; | ||
1581 | net_pack_u16(response + 1, groupnumber); | ||
1582 | memcpy(response + 1 + sizeof(uint16_t), data, length); | ||
1583 | |||
1584 | if (member) { | ||
1585 | net_pack_u16(response + 1 + sizeof(uint16_t) + length, g->peer_number); | ||
1586 | } | ||
1587 | |||
1588 | if (!send_conference_invite_packet(g_c->m, friendnumber, response, SIZEOF_VLA(response))) { | ||
1589 | return false; | ||
1590 | } | ||
1564 | 1591 | ||
1565 | if (send_conference_invite_packet(g_c->m, friendnumber, response, sizeof(response))) { | 1592 | if (!member) { |
1566 | uint16_t other_groupnum; | ||
1567 | memcpy(&other_groupnum, data, sizeof(other_groupnum)); | ||
1568 | other_groupnum = net_ntohs(other_groupnum); | ||
1569 | g->type = data[sizeof(uint16_t)]; | 1593 | g->type = data[sizeof(uint16_t)]; |
1570 | memcpy(g->id, data + sizeof(uint16_t) + 1, GROUP_ID_LENGTH); | 1594 | memcpy(g->id, data + sizeof(uint16_t) + 1, GROUP_ID_LENGTH); |
1571 | const int connection_index = add_conn_to_groupchat(g_c, friendcon_id, g, | 1595 | } |
1572 | GROUPCHAT_CONNECTION_REASON_INTRODUCER, 1); | ||
1573 | 1596 | ||
1574 | if (connection_index != -1) { | 1597 | uint16_t other_groupnum; |
1575 | g->connections[connection_index].group_number = other_groupnum; | 1598 | net_unpack_u16(data, &other_groupnum); |
1576 | g->connections[connection_index].type = GROUPCHAT_CONNECTION_ONLINE; | ||
1577 | } | ||
1578 | 1599 | ||
1579 | send_peer_query(g_c, friendcon_id, other_groupnum); | 1600 | const int friendcon_id = getfriendcon_id(g_c->m, friendnumber); |
1580 | return groupnumber; | 1601 | |
1602 | if (friendcon_id == -1) { | ||
1603 | return false; | ||
1604 | } | ||
1605 | |||
1606 | const int connection_index = add_conn_to_groupchat(g_c, friendcon_id, g, GROUPCHAT_CONNECTION_REASON_INTRODUCER, 1); | ||
1607 | |||
1608 | if (member) { | ||
1609 | add_conn_to_groupchat(g_c, friendcon_id, g, GROUPCHAT_CONNECTION_REASON_INTRODUCING, 0); | ||
1581 | } | 1610 | } |
1582 | 1611 | ||
1583 | g->status = GROUPCHAT_STATUS_NONE; | 1612 | if (connection_index != -1) { |
1584 | return -6; | 1613 | g->connections[connection_index].group_number = other_groupnum; |
1614 | g->connections[connection_index].type = GROUPCHAT_CONNECTION_ONLINE; | ||
1615 | } | ||
1616 | |||
1617 | send_peer_query(g_c, friendcon_id, other_groupnum); | ||
1618 | |||
1619 | return true; | ||
1585 | } | 1620 | } |
1586 | 1621 | ||
1587 | /* Set handlers for custom lossy packets. */ | 1622 | /* Set handlers for custom lossy packets. */ |
@@ -1911,19 +1946,28 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con | |||
1911 | } | 1946 | } |
1912 | 1947 | ||
1913 | return; | 1948 | return; |
1949 | } else { | ||
1950 | Group_c *g = get_group_c(g_c, groupnumber); | ||
1951 | |||
1952 | if (g && g->status == GROUPCHAT_STATUS_CONNECTED) { | ||
1953 | send_invite_response(g_c, groupnumber, friendnumber, invite_data, invite_length); | ||
1954 | } | ||
1914 | } | 1955 | } |
1915 | 1956 | ||
1916 | break; | 1957 | break; |
1917 | } | 1958 | } |
1918 | 1959 | ||
1919 | case INVITE_RESPONSE_ID: { | 1960 | case INVITE_ACCEPT_ID: |
1920 | if (length != INVITE_RESPONSE_PACKET_SIZE) { | 1961 | case INVITE_MEMBER_ID: { |
1962 | const bool member = (data[0] == INVITE_MEMBER_ID); | ||
1963 | |||
1964 | if (length != (member ? INVITE_MEMBER_PACKET_SIZE : INVITE_ACCEPT_PACKET_SIZE)) { | ||
1921 | return; | 1965 | return; |
1922 | } | 1966 | } |
1923 | 1967 | ||
1924 | uint16_t other_groupnum, groupnum; | 1968 | uint16_t other_groupnum, groupnum; |
1925 | memcpy(&groupnum, data + 1 + sizeof(uint16_t), sizeof(uint16_t)); | 1969 | net_unpack_u16(data + 1, &other_groupnum); |
1926 | groupnum = net_ntohs(groupnum); | 1970 | net_unpack_u16(data + 1 + sizeof(uint16_t), &groupnum); |
1927 | 1971 | ||
1928 | Group_c *g = get_group_c(g_c, groupnum); | 1972 | Group_c *g = get_group_c(g_c, groupnum); |
1929 | 1973 | ||
@@ -1939,24 +1983,28 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con | |||
1939 | return; | 1983 | return; |
1940 | } | 1984 | } |
1941 | 1985 | ||
1942 | /* TODO(irungentoo): what if two people enter the group at the same time and | 1986 | uint16_t peer_number; |
1943 | are given the same peer_number by different nodes? */ | ||
1944 | uint16_t peer_number = random_u16(); | ||
1945 | 1987 | ||
1946 | unsigned int tries = 0; | 1988 | if (member) { |
1947 | 1989 | net_unpack_u16(data + 1 + sizeof(uint16_t) * 2 + 1 + GROUP_ID_LENGTH, &peer_number); | |
1948 | while (get_peer_index(g, peer_number) != -1 || get_frozen_index(g, peer_number) != -1) { | 1990 | } else { |
1991 | /* TODO(irungentoo): what if two people enter the group at the | ||
1992 | * same time and are given the same peer_number by different | ||
1993 | * nodes? */ | ||
1949 | peer_number = random_u16(); | 1994 | peer_number = random_u16(); |
1950 | ++tries; | ||
1951 | 1995 | ||
1952 | if (tries > 32) { | 1996 | unsigned int tries = 0; |
1953 | return; | 1997 | |
1998 | while (get_peer_index(g, peer_number) != -1 || get_frozen_index(g, peer_number) != -1) { | ||
1999 | peer_number = random_u16(); | ||
2000 | ++tries; | ||
2001 | |||
2002 | if (tries > 32) { | ||
2003 | return; | ||
2004 | } | ||
1954 | } | 2005 | } |
1955 | } | 2006 | } |
1956 | 2007 | ||
1957 | memcpy(&other_groupnum, data + 1, sizeof(uint16_t)); | ||
1958 | other_groupnum = net_ntohs(other_groupnum); | ||
1959 | |||
1960 | const int friendcon_id = getfriendcon_id(m, friendnumber); | 2008 | const int friendcon_id = getfriendcon_id(m, friendnumber); |
1961 | 2009 | ||
1962 | if (friendcon_id == -1) { | 2010 | if (friendcon_id == -1) { |
@@ -1971,12 +2019,18 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con | |||
1971 | const int connection_index = add_conn_to_groupchat(g_c, friendcon_id, g, | 2019 | const int connection_index = add_conn_to_groupchat(g_c, friendcon_id, g, |
1972 | GROUPCHAT_CONNECTION_REASON_INTRODUCING, 1); | 2020 | GROUPCHAT_CONNECTION_REASON_INTRODUCING, 1); |
1973 | 2021 | ||
2022 | if (member) { | ||
2023 | add_conn_to_groupchat(g_c, friendcon_id, g, GROUPCHAT_CONNECTION_REASON_INTRODUCER, 0); | ||
2024 | send_peer_query(g_c, friendcon_id, other_groupnum); | ||
2025 | } | ||
2026 | |||
1974 | if (connection_index != -1) { | 2027 | if (connection_index != -1) { |
1975 | g->connections[connection_index].group_number = other_groupnum; | 2028 | g->connections[connection_index].group_number = other_groupnum; |
1976 | g->connections[connection_index].type = GROUPCHAT_CONNECTION_ONLINE; | 2029 | g->connections[connection_index].type = GROUPCHAT_CONNECTION_ONLINE; |
1977 | } | 2030 | } |
1978 | 2031 | ||
1979 | group_new_peer_send(g_c, groupnum, peer_number, real_pk, temp_pk); | 2032 | group_new_peer_send(g_c, groupnum, peer_number, real_pk, temp_pk); |
2033 | |||
1980 | break; | 2034 | break; |
1981 | } | 2035 | } |
1982 | 2036 | ||