summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzugz (tox) <mbays+tox@sdf.org>2020-03-01 00:00:00 +0000
committerzugz (tox) <mbays+tox@sdf.org>2020-03-18 00:00:00 +0000
commitdb07bda7f7b1ab7f5f219a9ed3d7f732b7da66b0 (patch)
treee5b4e5b43320c4073b619c006c1b32040cd06b8d
parent84e6a8d05704d9f4db79898984af861d759c478a (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.
-rw-r--r--CMakeLists.txt1
-rw-r--r--auto_tests/Makefile.inc5
-rw-r--r--auto_tests/conference_double_invite_test.c4
-rw-r--r--auto_tests/conference_invite_merge_test.c244
-rw-r--r--toxcore/group.c128
5 files changed, 344 insertions, 38 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 81a41e7f..355fd103 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -397,6 +397,7 @@ auto_test(TCP)
397auto_test(bootstrap) 397auto_test(bootstrap)
398auto_test(conference) 398auto_test(conference)
399auto_test(conference_double_invite) 399auto_test(conference_double_invite)
400auto_test(conference_invite_merge)
400auto_test(conference_peer_nick) 401auto_test(conference_peer_nick)
401auto_test(conference_simple) 402auto_test(conference_simple)
402auto_test(conference_two) 403auto_test(conference_two)
diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc
index fcaeff5b..983c83d3 100644
--- a/auto_tests/Makefile.inc
+++ b/auto_tests/Makefile.inc
@@ -3,6 +3,7 @@ if BUILD_TESTS
3TESTS = \ 3TESTS = \
4 bootstrap_test \ 4 bootstrap_test \
5 conference_double_invite_test \ 5 conference_double_invite_test \
6 conference_invite_merge_test \
6 conference_peer_nick_test \ 7 conference_peer_nick_test \
7 conference_simple_test \ 8 conference_simple_test \
8 conference_test \ 9 conference_test \
@@ -73,6 +74,10 @@ conference_double_invite_test_SOURCES = ../auto_tests/conference_double_invite_t
73conference_double_invite_test_CFLAGS = $(AUTOTEST_CFLAGS) 74conference_double_invite_test_CFLAGS = $(AUTOTEST_CFLAGS)
74conference_double_invite_test_LDADD = $(AUTOTEST_LDADD) 75conference_double_invite_test_LDADD = $(AUTOTEST_LDADD)
75 76
77conference_invite_merge_test_SOURCES = ../auto_tests/conference_invite_merge_test.c
78conference_invite_merge_test_CFLAGS = $(AUTOTEST_CFLAGS)
79conference_invite_merge_test_LDADD = $(AUTOTEST_LDADD)
80
76conference_peer_nick_test_SOURCES = ../auto_tests/conference_peer_nick_test.c 81conference_peer_nick_test_SOURCES = ../auto_tests/conference_peer_nick_test.c
77conference_peer_nick_test_CFLAGS = $(AUTOTEST_CFLAGS) 82conference_peer_nick_test_CFLAGS = $(AUTOTEST_CFLAGS)
78conference_peer_nick_test_LDADD = $(AUTOTEST_LDADD) 83conference_peer_nick_test_LDADD = $(AUTOTEST_LDADD)
diff --git a/auto_tests/conference_double_invite_test.c b/auto_tests/conference_double_invite_test.c
index 17124f1c..c9e64e5b 100644
--- a/auto_tests/conference_double_invite_test.c
+++ b/auto_tests/conference_double_invite_test.c
@@ -28,6 +28,8 @@ static void handle_conference_invite(
28 state->index, friend_number, type, (unsigned)length); 28 state->index, friend_number, type, (unsigned)length);
29 fprintf(stderr, "tox%u joining conference\n", state->index); 29 fprintf(stderr, "tox%u joining conference\n", state->index);
30 30
31 ck_assert_msg(!state->joined, "invitation callback generated for already joined conference");
32
31 if (friend_number != -1) { 33 if (friend_number != -1) {
32 Tox_Err_Conference_Join err; 34 Tox_Err_Conference_Join err;
33 state->conference = tox_conference_join(tox, friend_number, cookie, length, &err); 35 state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
@@ -71,7 +73,7 @@ static void conference_double_invite_test(Tox **toxes, State *state)
71 73
72 fprintf(stderr, "Invitations accepted\n"); 74 fprintf(stderr, "Invitations accepted\n");
73 75
74 // Invite one more time, resulting in friend -1 inviting tox1 (toxes[1]). 76 fprintf(stderr, "Sending second invitation; should be ignored\n");
75 tox_conference_invite(toxes[0], 0, state[0].conference, nullptr); 77 tox_conference_invite(toxes[0], 0, state[0].conference, nullptr);
76 78
77 iterate_all_wait(2, toxes, state, ITERATION_INTERVAL); 79 iterate_all_wait(2, toxes, state, ITERATION_INTERVAL);
diff --git a/auto_tests/conference_invite_merge_test.c b/auto_tests/conference_invite_merge_test.c
new file mode 100644
index 00000000..e7ec499c
--- /dev/null
+++ b/auto_tests/conference_invite_merge_test.c
@@ -0,0 +1,244 @@
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdbool.h>
6#include <stdint.h>
7#include <stdlib.h>
8
9typedef struct State {
10 uint32_t index;
11 uint64_t clock;
12
13 size_t save_size;
14 uint8_t *save_state;
15 bool alive;
16
17 bool connected;
18 uint32_t conference;
19} State;
20
21#define NUM_INVITE_MERGE_TOX 5
22
23#include "run_auto_test.h"
24
25static void handle_conference_invite(
26 Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
27 const uint8_t *cookie, size_t length, void *user_data)
28{
29 State *state = (State *)user_data;
30
31 if (friend_number != -1) {
32 Tox_Err_Conference_Join err;
33 state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
34 ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
35 "attempting to join the conference returned with an error: %d", err);
36 fprintf(stderr, "#%u accepted invite to conference %u\n", state->index, state->conference);
37 }
38}
39
40static void handle_conference_connected(
41 Tox *tox, uint32_t conference_number, void *user_data)
42{
43 State *state = (State *)user_data;
44 fprintf(stderr, "#%u connected to conference %u\n", state->index, state->conference);
45 state->connected = true;
46}
47
48static void iterate_alive(Tox **toxes, State *state)
49{
50 for (uint32_t i = 0; i < NUM_INVITE_MERGE_TOX; i++) {
51 if (!state[i].alive) {
52 continue;
53 }
54
55 tox_iterate(toxes[i], &state[i]);
56 state[i].clock += ITERATION_INTERVAL;
57 }
58
59 c_sleep(20);
60}
61
62static void save(Tox **toxes, State *state, uint32_t n)
63{
64 fprintf(stderr, "Saving #%u\n", state[n].index);
65
66 if (state[n].save_state != nullptr) {
67 free(state[n].save_state);
68 }
69
70 state[n].save_size = tox_get_savedata_size(toxes[n]);
71 state[n].save_state = (uint8_t *)malloc(state[n].save_size);
72 ck_assert_msg(state[n].save_state != nullptr, "malloc failed");
73 tox_get_savedata(toxes[n], state[n].save_state);
74}
75
76static void kill(Tox **toxes, State *state, uint32_t n)
77{
78 fprintf(stderr, "Killing #%u\n", state[n].index);
79 state[n].alive = false;
80 tox_kill(toxes[n]);
81}
82
83static void reload(Tox **toxes, State *state, uint32_t n)
84{
85 if (state[n].alive) {
86 state[n].alive = false;
87 tox_kill(toxes[n]);
88 }
89
90 fprintf(stderr, "Reloading #%u\n", state[n].index);
91 ck_assert(state[n].save_state != nullptr);
92
93 struct Tox_Options *const options = tox_options_new(nullptr);
94 tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
95 tox_options_set_savedata_data(options, state[n].save_state, state[n].save_size);
96 toxes[n] = tox_new_log(options, nullptr, &state[n].index);
97 tox_options_free(options);
98
99 set_mono_time_callback(toxes[n], &state[n]);
100 state[n].alive = true;
101}
102
103static void wait_connected(Tox **toxes, State *state, uint32_t n, uint32_t friendnumber)
104{
105 do {
106 iterate_alive(toxes, state);
107 } while (tox_friend_get_connection_status(toxes[n], friendnumber, nullptr) == TOX_CONNECTION_NONE);
108}
109
110static void do_invite(Tox **toxes, State *state, uint32_t inviter, uint32_t invitee, uint32_t friendnum)
111{
112 fprintf(stderr, "#%u inviting #%u\n", state[inviter].index, state[invitee].index);
113
114 Tox_Err_Conference_Invite err;
115 tox_conference_invite(toxes[inviter], friendnum, state[inviter].conference, &err);
116 ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK,
117 "#%u attempting to invite #%u (friendnumber %u) returned with an error: %d", state[inviter].index, state[invitee].index,
118 friendnum, err);
119
120 do {
121 iterate_alive(toxes, state);
122 } while (!state[invitee].connected);
123}
124
125static bool group_complete(Tox **toxes, State *state)
126{
127 int c = -1, size = 0;
128
129 for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) {
130 if (!state[i].alive) {
131 continue;
132 }
133
134 const int ct = tox_conference_peer_count(toxes[i], state[i].conference, nullptr);
135
136 if (c == -1) {
137 c = ct;
138 } else if (c != ct) {
139 return false;
140 }
141
142 ++size;
143 }
144
145 return (c == size);
146}
147
148static void wait_group_complete(Tox **toxes, State *state)
149{
150 do {
151 iterate_alive(toxes, state);
152 } while (!group_complete(toxes, state));
153}
154
155static void conference_invite_merge_test(Tox **toxes, State *state)
156{
157 // Test that an explicit invite between peers in different connected
158 // components will cause a split group to merge
159
160 for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) {
161 tox_callback_conference_invite(toxes[i], handle_conference_invite);
162 tox_callback_conference_connected(toxes[i], &handle_conference_connected);
163 state[i].alive = true;
164 state[i].save_state = nullptr;
165 }
166
167 {
168 // Create new conference, tox 2 is the founder.
169 Tox_Err_Conference_New err;
170 state[2].conference = tox_conference_new(toxes[2], &err);
171 state[2].connected = true;
172 ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK,
173 "attempting to create a new conference returned with an error: %d", err);
174 fprintf(stderr, "Created conference: index=%u\n", state[2].conference);
175 }
176
177 save(toxes, state, 2);
178
179 do_invite(toxes, state, 2, 1, 0);
180 do_invite(toxes, state, 1, 0, 0);
181
182 save(toxes, state, 1);
183 kill(toxes, state, 1);
184
185 do {
186 iterate_alive(toxes, state);
187 } while (tox_conference_peer_count(toxes[2], state[2].conference, nullptr) != 1);
188
189 do_invite(toxes, state, 2, 3, 1);
190 do_invite(toxes, state, 3, 4, 1);
191
192 kill(toxes, state, 2);
193
194 reload(toxes, state, 1);
195
196 uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
197 tox_self_get_public_key(toxes[1], public_key);
198 tox_friend_add_norequest(toxes[3], public_key, nullptr);
199 tox_self_get_public_key(toxes[3], public_key);
200 tox_friend_add_norequest(toxes[1], public_key, nullptr);
201 wait_connected(toxes, state, 1, 2);
202
203 do_invite(toxes, state, 1, 3, 2);
204
205 fprintf(stderr, "Waiting for group to merge\n");
206
207 wait_group_complete(toxes, state);
208
209 fprintf(stderr, "Group merged\n");
210
211 reload(toxes, state, 2);
212 wait_connected(toxes, state, 2, 0);
213 do_invite(toxes, state, 2, 1, 0);
214
215 fprintf(stderr, "Waiting for #2 to rejoin\n");
216
217 wait_group_complete(toxes, state);
218
219 kill(toxes, state, 2);
220 wait_group_complete(toxes, state);
221 reload(toxes, state, 2);
222 wait_connected(toxes, state, 2, 0);
223 wait_connected(toxes, state, 1, 1);
224
225 do_invite(toxes, state, 1, 2, 1);
226
227 fprintf(stderr, "Waiting for #2 to rejoin\n");
228
229 wait_group_complete(toxes, state);
230
231 for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) {
232 if (state[i].save_state != nullptr) {
233 free(state[i].save_state);
234 }
235 }
236}
237
238int main(void)
239{
240 setvbuf(stdout, nullptr, _IONBF, 0);
241
242 run_auto_test(NUM_INVITE_MERGE_TOX, conference_invite_merge_test, true);
243 return 0;
244}
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
40typedef enum Invite_Id { 40typedef 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
1513static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); 1515static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
1514 1516
1517static 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
1572static 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