diff options
-rw-r--r-- | testing/test_avatars.c | 5 | ||||
-rw-r--r-- | toxcore/Messenger.h | 4 | ||||
-rw-r--r-- | toxcore/friend_connection.c | 2 | ||||
-rw-r--r-- | toxcore/friend_connection.h | 2 | ||||
-rw-r--r-- | toxcore/group.c | 617 | ||||
-rw-r--r-- | toxcore/group.h | 22 | ||||
-rw-r--r-- | toxcore/tox.c | 1 |
7 files changed, 562 insertions, 91 deletions
diff --git a/testing/test_avatars.c b/testing/test_avatars.c index 6afbac1d..71a0330e 100644 --- a/testing/test_avatars.c +++ b/testing/test_avatars.c | |||
@@ -444,6 +444,7 @@ static void set_avatar(Tox *tox, const char *base_dir) | |||
444 | tox_get_address(tox, addr); | 444 | tox_get_address(tox, addr); |
445 | 445 | ||
446 | int i; | 446 | int i; |
447 | |||
447 | for (i = 0; ; i++) { | 448 | for (i = 0; ; i++) { |
448 | if (avatar_formats[i].format == TOX_AVATAR_FORMAT_NONE) { | 449 | if (avatar_formats[i].format == TOX_AVATAR_FORMAT_NONE) { |
449 | tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0); | 450 | tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0); |
@@ -452,12 +453,14 @@ static void set_avatar(Tox *tox, const char *base_dir) | |||
452 | } else { | 453 | } else { |
453 | int ret = make_avatar_file_name(path, sizeof(path), base_dir, | 454 | int ret = make_avatar_file_name(path, sizeof(path), base_dir, |
454 | avatar_formats[i].format, addr); | 455 | avatar_formats[i].format, addr); |
456 | |||
455 | if (ret < 0) { | 457 | if (ret < 0) { |
456 | printf("Failed to generate avatar file name.\n"); | 458 | printf("Failed to generate avatar file name.\n"); |
457 | return; | 459 | return; |
458 | } | 460 | } |
459 | 461 | ||
460 | int len = load_avatar_data(path, buf); | 462 | int len = load_avatar_data(path, buf); |
463 | |||
461 | if (len < 0) { | 464 | if (len < 0) { |
462 | printf("Failed to load avatar data from file: %s\n", path); | 465 | printf("Failed to load avatar data from file: %s\n", path); |
463 | continue; | 466 | continue; |
@@ -471,10 +474,12 @@ static void set_avatar(Tox *tox, const char *base_dir) | |||
471 | 474 | ||
472 | ret = tox_set_avatar(tox, avatar_formats[i].format, buf, len); | 475 | ret = tox_set_avatar(tox, avatar_formats[i].format, buf, len); |
473 | DEBUG("tox_set_avatar returned=%d", ret); | 476 | DEBUG("tox_set_avatar returned=%d", ret); |
477 | |||
474 | if (ret == 0) | 478 | if (ret == 0) |
475 | printf("Setting avatar from %s (%d bytes).\n", path, len); | 479 | printf("Setting avatar from %s (%d bytes).\n", path, len); |
476 | else | 480 | else |
477 | printf("Error setting avatar from %s.\n", path); | 481 | printf("Error setting avatar from %s.\n", path); |
482 | |||
478 | return; | 483 | return; |
479 | } | 484 | } |
480 | } | 485 | } |
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index cc09afe3..42919a0d 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h | |||
@@ -58,7 +58,9 @@ | |||
58 | #define PACKET_ID_FILE_CONTROL 81 | 58 | #define PACKET_ID_FILE_CONTROL 81 |
59 | #define PACKET_ID_FILE_DATA 82 | 59 | #define PACKET_ID_FILE_DATA 82 |
60 | #define PACKET_ID_INVITE_GROUPCHAT 96 | 60 | #define PACKET_ID_INVITE_GROUPCHAT 96 |
61 | #define PACKET_ID_MESSAGE_GROUPCHAT 98 | 61 | #define PACKET_ID_ONLINE_PACKET 97 |
62 | #define PACKET_ID_DIRECT_GROUPCHAT 98 | ||
63 | #define PACKET_ID_MESSAGE_GROUPCHAT 99 | ||
62 | 64 | ||
63 | 65 | ||
64 | /* Max number of tcp relays sent to friends */ | 66 | /* Max number of tcp relays sent to friends */ |
diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c index 1838c62d..7be4251a 100644 --- a/toxcore/friend_connection.c +++ b/toxcore/friend_connection.c | |||
@@ -419,7 +419,7 @@ int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Con | |||
419 | 419 | ||
420 | /* Set temp dht key for connection. | 420 | /* Set temp dht key for connection. |
421 | */ | 421 | */ |
422 | void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, uint8_t *dht_temp_pk) | 422 | void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk) |
423 | { | 423 | { |
424 | dht_pk_callback(fr_c, friendcon_id, dht_temp_pk); | 424 | dht_pk_callback(fr_c, friendcon_id, dht_temp_pk); |
425 | } | 425 | } |
diff --git a/toxcore/friend_connection.h b/toxcore/friend_connection.h index 56401547..64280acb 100644 --- a/toxcore/friend_connection.h +++ b/toxcore/friend_connection.h | |||
@@ -122,7 +122,7 @@ int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Con | |||
122 | 122 | ||
123 | /* Set temp dht key for connection. | 123 | /* Set temp dht key for connection. |
124 | */ | 124 | */ |
125 | void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, uint8_t *dht_temp_pk); | 125 | void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk); |
126 | 126 | ||
127 | /* Set the callbacks for the friend connection. | 127 | /* Set the callbacks for the friend connection. |
128 | * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array. | 128 | * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array. |
diff --git a/toxcore/group.c b/toxcore/group.c index ce590015..d5364420 100644 --- a/toxcore/group.c +++ b/toxcore/group.c | |||
@@ -130,7 +130,7 @@ static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber) | |||
130 | } | 130 | } |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * check if peer with client_id is in peer array. | 133 | * check if peer with real_pk is in peer array. |
134 | * | 134 | * |
135 | * return peer index if peer is in chat. | 135 | * return peer index if peer is in chat. |
136 | * return -1 if peer is not in chat. | 136 | * return -1 if peer is not in chat. |
@@ -138,12 +138,12 @@ static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber) | |||
138 | * TODO: make this more efficient. | 138 | * TODO: make this more efficient. |
139 | */ | 139 | */ |
140 | 140 | ||
141 | static int peer_in_chat(const Group_c *chat, const uint8_t *client_id) | 141 | static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk) |
142 | { | 142 | { |
143 | uint32_t i; | 143 | uint32_t i; |
144 | 144 | ||
145 | for (i = 0; i < chat->numpeers; ++i) | 145 | for (i = 0; i < chat->numpeers; ++i) |
146 | if (id_equal(chat->group[i].client_id, client_id)) | 146 | if (id_equal(chat->group[i].real_pk, real_pk)) |
147 | return i; | 147 | return i; |
148 | 148 | ||
149 | return -1; | 149 | return -1; |
@@ -176,7 +176,7 @@ static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier) | |||
176 | * | 176 | * |
177 | * TODO: make this more efficient. | 177 | * TODO: make this more efficient. |
178 | */ | 178 | */ |
179 | int get_peer_index(Group_c *g, uint16_t peer_number) | 179 | static int get_peer_index(Group_c *g, uint16_t peer_number) |
180 | { | 180 | { |
181 | uint32_t i; | 181 | uint32_t i; |
182 | 182 | ||
@@ -187,59 +187,274 @@ int get_peer_index(Group_c *g, uint16_t peer_number) | |||
187 | return -1; | 187 | return -1; |
188 | } | 188 | } |
189 | 189 | ||
190 | |||
191 | static uint16_t calculate_comp_value(const uint8_t *pk1, const uint8_t *pk2) | ||
192 | { | ||
193 | uint8_t cmp1, cmp2; | ||
194 | |||
195 | for (cmp1 = crypto_box_PUBLICKEYBYTES; cmp1 != 0; --cmp1) { | ||
196 | uint8_t index = crypto_box_PUBLICKEYBYTES - cmp1; | ||
197 | |||
198 | if (pk1[index] == pk2[index]) | ||
199 | continue; | ||
200 | |||
201 | cmp2 = abs((int)pk1[index] - (int)pk2[index]); | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | return (cmp1 << 8) + cmp2; | ||
206 | } | ||
207 | |||
208 | static int friend_in_close(Group_c *g, int friendcon_id); | ||
209 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest); | ||
210 | |||
211 | static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk) | ||
212 | { | ||
213 | Group_c *g = get_group_c(g_c, groupnumber); | ||
214 | |||
215 | if (!g) | ||
216 | return -1; | ||
217 | |||
218 | unsigned int i; | ||
219 | unsigned int index = DESIRED_CLOSE_CONNECTIONS; | ||
220 | |||
221 | for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { | ||
222 | if (g->closest_peers[i].entry == 0) { | ||
223 | index = i; | ||
224 | break; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | if (index == DESIRED_CLOSE_CONNECTIONS) { | ||
229 | uint16_t comp_val = calculate_comp_value(g->real_pk, real_pk); | ||
230 | uint16_t comp_d = 0; | ||
231 | |||
232 | for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { | ||
233 | uint16_t comp = calculate_comp_value(g->real_pk, g->closest_peers[i].real_pk); | ||
234 | |||
235 | if (comp > comp_val && comp > comp_d) { | ||
236 | index = i; | ||
237 | comp_d = comp; | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | |||
242 | if (index == DESIRED_CLOSE_CONNECTIONS) { | ||
243 | return -1; | ||
244 | } | ||
245 | |||
246 | g->closest_peers[index].entry = 1; | ||
247 | memcpy(g->closest_peers[index].real_pk, real_pk, crypto_box_PUBLICKEYBYTES); | ||
248 | memcpy(g->closest_peers[index].temp_pk, temp_pk, crypto_box_PUBLICKEYBYTES); | ||
249 | g->changed = 1; | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk) | ||
255 | { | ||
256 | unsigned int i; | ||
257 | |||
258 | for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { | ||
259 | if (!g->closest_peers[i].entry) | ||
260 | continue; | ||
261 | |||
262 | if (memcmp(g->closest_peers[i].real_pk, real_pk, crypto_box_PUBLICKEYBYTES) == 0) | ||
263 | return 1; | ||
264 | |||
265 | } | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int connect_to_closest(Group_Chats *g_c, int groupnumber) | ||
271 | { | ||
272 | Group_c *g = get_group_c(g_c, groupnumber); | ||
273 | |||
274 | if (!g) | ||
275 | return -1; | ||
276 | |||
277 | if (!g->changed) | ||
278 | return 0; | ||
279 | |||
280 | unsigned int i; | ||
281 | |||
282 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | ||
283 | if (g->close[i].type == GROUPCHAT_CLOSE_NONE) | ||
284 | continue; | ||
285 | |||
286 | if (!g->close[i].closest) | ||
287 | continue; | ||
288 | |||
289 | uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; | ||
290 | uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; | ||
291 | get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number); | ||
292 | |||
293 | if (!pk_in_closest_peers(g, real_pk)) { | ||
294 | g->close[i].type = GROUPCHAT_CLOSE_NONE; | ||
295 | kill_friend_connection(g_c->fr_c, g->close[i].number); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { | ||
300 | if (!g->closest_peers[i].entry) | ||
301 | continue; | ||
302 | |||
303 | int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk); | ||
304 | |||
305 | if (friendcon_id == -1) { | ||
306 | friendcon_id = new_friend_connection(g_c->fr_c, g->closest_peers[i].real_pk); | ||
307 | |||
308 | if (friendcon_id == -1) { | ||
309 | continue; | ||
310 | } | ||
311 | |||
312 | set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk); | ||
313 | } | ||
314 | |||
315 | add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1); | ||
316 | } | ||
317 | |||
318 | g->changed = 0; | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
190 | /* | 323 | /* |
191 | * Add a peer to the group chat. | 324 | * Add a peer to the group chat. |
192 | * | 325 | * |
193 | * return peer_index if success or peer already in chat. | 326 | * return peer_index if success or peer already in chat. |
194 | * return -1 if error. | 327 | * return -1 if error. |
195 | */ | 328 | */ |
196 | static int addpeer(Group_c *chat, const uint8_t *client_id, uint16_t peer_number) | 329 | static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk, |
330 | uint16_t peer_number) | ||
197 | { | 331 | { |
332 | Group_c *g = get_group_c(g_c, groupnumber); | ||
333 | |||
334 | if (!g) | ||
335 | return -1; | ||
336 | |||
198 | //TODO | 337 | //TODO |
199 | //int peer_index = peer_in_chat(chat, client_id); | 338 | int peer_index = peer_in_chat(g, real_pk); |
339 | |||
340 | if (peer_index != -1) { | ||
341 | id_copy(g->group[peer_index].temp_pk, temp_pk); | ||
342 | |||
343 | if (g->group[peer_index].peer_number != peer_number) | ||
344 | return -1; | ||
345 | |||
346 | return peer_index; | ||
347 | } | ||
200 | 348 | ||
201 | //if (peer_index != -1) | 349 | peer_index = get_peer_index(g, peer_number); |
202 | // return peer_index; | 350 | |
351 | if (peer_index != -1) | ||
352 | return -1; | ||
203 | 353 | ||
204 | Group_Peer *temp; | 354 | Group_Peer *temp; |
205 | temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1)); | 355 | temp = realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1)); |
206 | 356 | ||
207 | if (temp == NULL) | 357 | if (temp == NULL) |
208 | return -1; | 358 | return -1; |
209 | 359 | ||
210 | memset(&(temp[chat->numpeers]), 0, sizeof(Group_Peer)); | 360 | memset(&(temp[g->numpeers]), 0, sizeof(Group_Peer)); |
211 | chat->group = temp; | 361 | g->group = temp; |
212 | 362 | ||
213 | id_copy(chat->group[chat->numpeers].client_id, client_id); | 363 | id_copy(g->group[g->numpeers].real_pk, real_pk); |
214 | chat->group[chat->numpeers].peer_number = peer_number; | 364 | id_copy(g->group[g->numpeers].temp_pk, temp_pk); |
365 | g->group[g->numpeers].peer_number = peer_number; | ||
215 | 366 | ||
216 | chat->group[chat->numpeers].last_recv = unix_time(); | 367 | g->group[g->numpeers].last_recv = unix_time(); |
217 | chat->group[chat->numpeers].last_recv_msgping = unix_time(); | 368 | g->group[g->numpeers].last_recv_msgping = unix_time(); |
218 | ++chat->numpeers; | 369 | ++g->numpeers; |
219 | 370 | ||
220 | //if (chat->peer_namelistchange != NULL) | 371 | add_to_closest(g_c, groupnumber, real_pk, temp_pk); |
221 | // (*chat->peer_namelistchange)(chat, chat->numpeers - 1, CHAT_CHANGE_PEER_ADD, chat->group_namelistchange_userdata); | 372 | //if (g->peer_namelistchange != NULL) |
373 | // (*g->peer_namelistchange)(g, g->numpeers - 1, CHAT_CHANGE_PEER_ADD, g->group_namelistchange_userdata); | ||
222 | 374 | ||
223 | return (chat->numpeers - 1); | 375 | return (g->numpeers - 1); |
224 | } | 376 | } |
225 | 377 | ||
226 | static int handle_status(void *object, int number, uint8_t status) | 378 | static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id) |
227 | { | 379 | { |
228 | if (status) { /* Went online */ | 380 | Group_c *g = get_group_c(g_c, groupnumber); |
229 | 381 | ||
230 | } else { /* Went offline */ | 382 | if (!g) |
383 | return -1; | ||
384 | |||
385 | uint32_t i; | ||
386 | |||
387 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | ||
388 | if (g->close[i].type == GROUPCHAT_CLOSE_NONE) | ||
389 | continue; | ||
231 | 390 | ||
391 | if (g->close[i].number == friendcon_id) { | ||
392 | g->close[i].type = GROUPCHAT_CLOSE_NONE; | ||
393 | kill_friend_connection(g_c->fr_c, friendcon_id); | ||
394 | return 0; | ||
395 | } | ||
232 | } | 396 | } |
397 | |||
398 | return -1; | ||
233 | } | 399 | } |
234 | 400 | ||
235 | static int handle_packet(void *object, int number, uint8_t *data, uint16_t length); | 401 | static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier); |
402 | |||
403 | static void set_conns_type_close(Group_Chats *g_c, int groupnumber, int friendcon_id, uint8_t type) | ||
404 | { | ||
405 | Group_c *g = get_group_c(g_c, groupnumber); | ||
406 | |||
407 | if (!g) | ||
408 | return; | ||
409 | |||
410 | uint32_t i; | ||
411 | |||
412 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | ||
413 | if (g->close[i].type == GROUPCHAT_CLOSE_NONE) | ||
414 | continue; | ||
415 | |||
416 | if (g->close[i].number != friendcon_id) | ||
417 | continue; | ||
418 | |||
419 | if (type == GROUPCHAT_CLOSE_ONLINE) { | ||
420 | send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier); | ||
421 | } else { | ||
422 | g->close[i].type = type; | ||
423 | } | ||
424 | } | ||
425 | } | ||
426 | /* Set the type for all close connections with friendcon_id */ | ||
427 | static void set_conns_status_groups(Group_Chats *g_c, int friendcon_id, uint8_t type) | ||
428 | { | ||
429 | uint32_t i; | ||
430 | |||
431 | for (i = 0; i < g_c->num_chats; ++i) { | ||
432 | set_conns_type_close(g_c, i, friendcon_id, type); | ||
433 | } | ||
434 | } | ||
435 | |||
436 | static int handle_status(void *object, int friendcon_id, uint8_t status) | ||
437 | { | ||
438 | Group_Chats *g_c = object; | ||
439 | |||
440 | if (status) { /* Went online */ | ||
441 | set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE); | ||
442 | } else { /* Went offline */ | ||
443 | set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION); | ||
444 | //TODO remove timedout connections? | ||
445 | } | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length); | ||
236 | 451 | ||
237 | /* Add friend to group chat. | 452 | /* Add friend to group chat. |
238 | * | 453 | * |
239 | * return 0 on success | 454 | * return close index on success |
240 | * return -1 on failure. | 455 | * return -1 on failure. |
241 | */ | 456 | */ |
242 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint16_t other_groupnum) | 457 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest) |
243 | { | 458 | { |
244 | Group_c *g = get_group_c(g_c, groupnumber); | 459 | Group_c *g = get_group_c(g_c, groupnumber); |
245 | 460 | ||
@@ -254,9 +469,8 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnu | |||
254 | continue; | 469 | continue; |
255 | } | 470 | } |
256 | 471 | ||
257 | if (g->close[i].type == GROUPCHAT_CLOSE_CONNECTION && g->close[i].number == (uint32_t)friendcon_id) { | 472 | if (g->close[i].number == (uint32_t)friendcon_id) { |
258 | g->close[i].group_number = other_groupnum; /* update groupnum. */ | 473 | return i; /* Already in list. */ |
259 | return 0; /* Already in list. */ | ||
260 | } | 474 | } |
261 | 475 | ||
262 | break; | 476 | break; |
@@ -265,14 +479,15 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnu | |||
265 | if (ind == MAX_GROUP_CONNECTIONS) | 479 | if (ind == MAX_GROUP_CONNECTIONS) |
266 | return -1; | 480 | return -1; |
267 | 481 | ||
482 | friend_connection_lock(g_c->fr_c, friendcon_id); | ||
268 | g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION; | 483 | g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION; |
269 | g->close[ind].number = friendcon_id; | 484 | g->close[ind].number = friendcon_id; |
270 | g->close[ind].group_number = other_groupnum; | 485 | g->close[ind].closest = closest; |
271 | //TODO | 486 | //TODO |
272 | friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &handle_status, &handle_packet, 0, | 487 | friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &handle_status, &handle_packet, 0, |
273 | g_c, friendcon_id); | 488 | g_c, friendcon_id); |
274 | 489 | ||
275 | return 0; | 490 | return ind; |
276 | } | 491 | } |
277 | 492 | ||
278 | /* Creates a new groupchat and puts it in the chats array. | 493 | /* Creates a new groupchat and puts it in the chats array. |
@@ -289,9 +504,11 @@ int add_groupchat(Group_Chats *g_c) | |||
289 | 504 | ||
290 | Group_c *g = &g_c->chats[groupnumber]; | 505 | Group_c *g = &g_c->chats[groupnumber]; |
291 | 506 | ||
292 | g->status = GROUPCHAT_STATUS_VALID; | 507 | g->status = GROUPCHAT_STATUS_CONNECTED; |
293 | new_symmetric_key(g->identifier); | 508 | new_symmetric_key(g->identifier); |
294 | g->peer_number = 0; /* Founder is peer 0. */ | 509 | g->peer_number = 0; /* Founder is peer 0. */ |
510 | memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
511 | addpeer(g_c, groupnumber, g->real_pk, g_c->m->dht->self_public_key, 0); | ||
295 | return groupnumber; | 512 | return groupnumber; |
296 | } | 513 | } |
297 | 514 | ||
@@ -311,20 +528,23 @@ int del_groupchat(Group_Chats *g_c, int groupnumber) | |||
311 | return wipe_group_chat(g_c, groupnumber); | 528 | return wipe_group_chat(g_c, groupnumber); |
312 | } | 529 | } |
313 | 530 | ||
314 | /* Send a group message packet. | 531 | /* Send a group packet to friendcon_id. |
315 | * | 532 | * |
316 | * return 1 on success | 533 | * return 1 on success |
317 | * return 0 on failure | 534 | * return 0 on failure |
318 | */ | 535 | */ |
319 | int send_group_message_packet(const Messenger *m, int friendcon_id, const uint8_t *data, uint16_t length) | 536 | static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, |
537 | uint16_t group_num, const uint8_t *data, uint16_t length) | ||
320 | { | 538 | { |
321 | if (length >= MAX_CRYPTO_DATA_SIZE) | 539 | if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) |
322 | return 0; | 540 | return 0; |
323 | 541 | ||
324 | uint8_t packet[1 + length]; | 542 | group_num = htons(group_num); |
325 | packet[0] = PACKET_ID_MESSAGE_GROUPCHAT; | 543 | uint8_t packet[1 + sizeof(uint16_t) + length]; |
326 | memcpy(packet + 1, data, length); | 544 | packet[0] = packet_id; |
327 | return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), packet, | 545 | memcpy(packet + 1, &group_num, sizeof(uint16_t)); |
546 | memcpy(packet + 1 + sizeof(uint16_t), data, length); | ||
547 | return write_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet, | ||
328 | sizeof(packet), 0) != -1; | 548 | sizeof(packet), 0) != -1; |
329 | } | 549 | } |
330 | 550 | ||
@@ -359,6 +579,8 @@ int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber) | |||
359 | } | 579 | } |
360 | } | 580 | } |
361 | 581 | ||
582 | static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); | ||
583 | |||
362 | /* Join a group (you need to have been invited first.) | 584 | /* Join a group (you need to have been invited first.) |
363 | * | 585 | * |
364 | * returns group number on success | 586 | * returns group number on success |
@@ -369,6 +591,11 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, const uint8_t *data, | |||
369 | if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) | 591 | if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) |
370 | return -1; | 592 | return -1; |
371 | 593 | ||
594 | int friendcon_id = getfriendcon_id(g_c->m, friendnumber); | ||
595 | |||
596 | if (friendcon_id == -1) | ||
597 | return -1; | ||
598 | |||
372 | int groupnumber = create_group_chat(g_c); | 599 | int groupnumber = create_group_chat(g_c); |
373 | 600 | ||
374 | if (groupnumber == -1) | 601 | if (groupnumber == -1) |
@@ -378,6 +605,8 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, const uint8_t *data, | |||
378 | 605 | ||
379 | uint16_t group_num = htons(groupnumber); | 606 | uint16_t group_num = htons(groupnumber); |
380 | g->status = GROUPCHAT_STATUS_VALID; | 607 | g->status = GROUPCHAT_STATUS_VALID; |
608 | memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
609 | |||
381 | uint8_t response[INVITE_RESPONSE_PACKET_SIZE]; | 610 | uint8_t response[INVITE_RESPONSE_PACKET_SIZE]; |
382 | response[0] = INVITE_RESPONSE_ID; | 611 | response[0] = INVITE_RESPONSE_ID; |
383 | memcpy(response + 1, &group_num, sizeof(uint16_t)); | 612 | memcpy(response + 1, &group_num, sizeof(uint16_t)); |
@@ -386,12 +615,19 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, const uint8_t *data, | |||
386 | if (send_group_invite_packet(g_c->m, friendnumber, response, sizeof(response))) { | 615 | if (send_group_invite_packet(g_c->m, friendnumber, response, sizeof(response))) { |
387 | uint16_t other_groupnum; | 616 | uint16_t other_groupnum; |
388 | memcpy(&other_groupnum, data, sizeof(other_groupnum)); | 617 | memcpy(&other_groupnum, data, sizeof(other_groupnum)); |
389 | other_groupnum = htons(other_groupnum); | 618 | other_groupnum = ntohs(other_groupnum); |
390 | memcpy(g->identifier, data + sizeof(uint16_t), GROUP_IDENTIFIER_LENGTH); | 619 | memcpy(g->identifier, data + sizeof(uint16_t), GROUP_IDENTIFIER_LENGTH); |
391 | add_conn_to_groupchat(g_c, getfriendcon_id(g_c->m, friendnumber), groupnumber, other_groupnum); | 620 | int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 0); |
392 | g->peer_number = rand(); /* TODO */ | 621 | |
622 | if (close_index != -1) { | ||
623 | g->close[close_index].group_number = other_groupnum; | ||
624 | g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE; | ||
625 | } | ||
626 | |||
627 | send_peer_query(g_c, friendcon_id, other_groupnum); | ||
393 | return groupnumber; | 628 | return groupnumber; |
394 | } else { | 629 | } else { |
630 | g->status = GROUPCHAT_STATUS_NONE; | ||
395 | return -1; | 631 | return -1; |
396 | } | 632 | } |
397 | } | 633 | } |
@@ -420,6 +656,31 @@ void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, i | |||
420 | g_c->message_callback_userdata = userdata; | 656 | g_c->message_callback_userdata = userdata; |
421 | } | 657 | } |
422 | 658 | ||
659 | static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, | ||
660 | uint16_t len); | ||
661 | #define GROUP_MESSAGE_NEW_PEER_ID 16 | ||
662 | #define GROUP_MESSAGE_NEW_PEER_LENGTH (sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2) | ||
663 | /* send a group message | ||
664 | * return 0 on success | ||
665 | * return -1 on failure | ||
666 | */ | ||
667 | int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num, const uint8_t *real_pk, | ||
668 | uint8_t *temp_pk) | ||
669 | { | ||
670 | uint8_t packet[GROUP_MESSAGE_NEW_PEER_LENGTH]; | ||
671 | |||
672 | peer_num = htons(peer_num); | ||
673 | memcpy(packet, &peer_num, sizeof(uint16_t)); | ||
674 | memcpy(packet + sizeof(uint16_t), real_pk, crypto_box_PUBLICKEYBYTES); | ||
675 | memcpy(packet + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, temp_pk, crypto_box_PUBLICKEYBYTES); | ||
676 | |||
677 | if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet))) { | ||
678 | return 0; | ||
679 | } else { | ||
680 | return -1; | ||
681 | } | ||
682 | } | ||
683 | |||
423 | static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) | 684 | static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) |
424 | { | 685 | { |
425 | Group_Chats *g_c = m->group_chat_object; | 686 | Group_Chats *g_c = m->group_chat_object; |
@@ -442,12 +703,6 @@ static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, cons | |||
442 | g_c->invite_callback(m, friendnumber, invite_data, invite_length, g_c->invite_callback_userdata); | 703 | g_c->invite_callback(m, friendnumber, invite_data, invite_length, g_c->invite_callback_userdata); |
443 | 704 | ||
444 | return; | 705 | return; |
445 | } else { | ||
446 | //TODO | ||
447 | uint16_t other_groupnum; | ||
448 | memcpy(&other_groupnum, data + 1, sizeof(uint16_t)); | ||
449 | other_groupnum = ntohs(other_groupnum); | ||
450 | add_conn_to_groupchat(g_c, getfriendcon_id(m, friendnumber), groupnumber, other_groupnum); | ||
451 | } | 706 | } |
452 | 707 | ||
453 | break; | 708 | break; |
@@ -472,8 +727,20 @@ static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, cons | |||
472 | memcpy(&other_groupnum, data + 1, sizeof(uint16_t)); | 727 | memcpy(&other_groupnum, data + 1, sizeof(uint16_t)); |
473 | other_groupnum = ntohs(other_groupnum); | 728 | other_groupnum = ntohs(other_groupnum); |
474 | 729 | ||
475 | add_conn_to_groupchat(g_c, getfriendcon_id(m, friendnumber), groupnum, other_groupnum); | 730 | int friendcon_id = getfriendcon_id(m, friendnumber); |
731 | uint8_t real_pk[crypto_box_PUBLICKEYBYTES], temp_pk[crypto_box_PUBLICKEYBYTES]; | ||
732 | get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id); | ||
476 | 733 | ||
734 | uint16_t peer_number = rand(); /* TODO: make it not random. */ | ||
735 | addpeer(g_c, groupnum, real_pk, temp_pk, peer_number); | ||
736 | int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, 0); | ||
737 | |||
738 | if (close_index != -1) { | ||
739 | g->close[close_index].group_number = other_groupnum; | ||
740 | g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE; | ||
741 | } | ||
742 | |||
743 | group_new_peer_send(g_c, groupnum, peer_number, real_pk, temp_pk); | ||
477 | break; | 744 | break; |
478 | } | 745 | } |
479 | 746 | ||
@@ -492,7 +759,7 @@ static int friend_in_close(Group_c *g, int friendcon_id) | |||
492 | int i; | 759 | int i; |
493 | 760 | ||
494 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | 761 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { |
495 | if (g->close[i].type != GROUPCHAT_CLOSE_CONNECTION) | 762 | if (g->close[i].type == GROUPCHAT_CLOSE_NONE) |
496 | continue; | 763 | continue; |
497 | 764 | ||
498 | if (g->close[i].number != (uint32_t)friendcon_id) | 765 | if (g->close[i].number != (uint32_t)friendcon_id) |
@@ -504,6 +771,165 @@ static int friend_in_close(Group_c *g, int friendcon_id) | |||
504 | return -1; | 771 | return -1; |
505 | } | 772 | } |
506 | 773 | ||
774 | #define ONLINE_PACKET_DATA_SIZE (sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES) | ||
775 | |||
776 | static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier) | ||
777 | { | ||
778 | uint8_t packet[1 + ONLINE_PACKET_DATA_SIZE]; | ||
779 | group_num = htons(group_num); | ||
780 | packet[0] = PACKET_ID_ONLINE_PACKET; | ||
781 | memcpy(packet + 1, &group_num, sizeof(uint16_t)); | ||
782 | memcpy(packet + 1 + sizeof(uint16_t), identifier, crypto_box_PUBLICKEYBYTES); | ||
783 | return write_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet, | ||
784 | sizeof(packet), 0) != -1; | ||
785 | } | ||
786 | |||
787 | static int handle_packet_online(Group_Chats *g_c, int friendcon_id, uint8_t *data, uint16_t length) | ||
788 | { | ||
789 | if (length != ONLINE_PACKET_DATA_SIZE) | ||
790 | return -1; | ||
791 | |||
792 | int groupnumber = get_group_num(g_c, data + sizeof(uint16_t)); | ||
793 | uint16_t other_groupnum; | ||
794 | memcpy(&other_groupnum, data, sizeof(uint16_t)); | ||
795 | other_groupnum = ntohs(other_groupnum); | ||
796 | |||
797 | Group_c *g = get_group_c(g_c, groupnumber); | ||
798 | |||
799 | if (!g) | ||
800 | return -1; | ||
801 | |||
802 | int index = friend_in_close(g, friendcon_id); | ||
803 | |||
804 | if (index == -1) | ||
805 | return -1; | ||
806 | |||
807 | g->close[index].group_number = other_groupnum; | ||
808 | g->close[index].type = GROUPCHAT_CLOSE_ONLINE; | ||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | #define PEER_QUERY_ID 4 | ||
813 | #define PEER_RESPONSE_ID 8 | ||
814 | |||
815 | /* return 1 on success. | ||
816 | * return 0 on failure | ||
817 | */ | ||
818 | static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num) | ||
819 | { | ||
820 | uint8_t packet[1]; | ||
821 | packet[0] = PEER_QUERY_ID; | ||
822 | return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, packet, sizeof(packet)); | ||
823 | } | ||
824 | |||
825 | /* return number of peers sent on success. | ||
826 | * return 0 on failure. | ||
827 | */ | ||
828 | static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_id, uint16_t group_num) | ||
829 | { | ||
830 | Group_c *g = get_group_c(g_c, groupnumber); | ||
831 | |||
832 | if (!g) | ||
833 | return -1; | ||
834 | |||
835 | uint8_t packet[MAX_CRYPTO_DATA_SIZE - (1 + sizeof(uint16_t))]; | ||
836 | packet[0] = PEER_RESPONSE_ID; | ||
837 | uint8_t *p = packet + 1; | ||
838 | |||
839 | uint16_t sent = 0; | ||
840 | unsigned int i; | ||
841 | |||
842 | for (i = 0; i < g->numpeers; ++i) { | ||
843 | uint16_t peer_num = htons(g->group[i].peer_number); | ||
844 | memcpy(p, &peer_num, sizeof(peer_num)); | ||
845 | p += sizeof(peer_num); | ||
846 | memcpy(p, g->group[i].real_pk, crypto_box_PUBLICKEYBYTES); | ||
847 | p += crypto_box_PUBLICKEYBYTES; | ||
848 | memcpy(p, g->group[i].temp_pk, crypto_box_PUBLICKEYBYTES); | ||
849 | p += crypto_box_PUBLICKEYBYTES; | ||
850 | |||
851 | if ((p - packet) + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2 > sizeof(packet)) { | ||
852 | if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, packet, (p - packet))) { | ||
853 | sent = i; | ||
854 | } else { | ||
855 | return sent; | ||
856 | } | ||
857 | |||
858 | p = packet + 1; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | if (sent != i) { | ||
863 | if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_GROUPCHAT, group_num, packet, (p - packet))) { | ||
864 | sent = i; | ||
865 | } | ||
866 | } | ||
867 | |||
868 | return sent; | ||
869 | } | ||
870 | |||
871 | static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length) | ||
872 | { | ||
873 | if (length == 0) | ||
874 | return -1; | ||
875 | |||
876 | if (length % (sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2) != 0) | ||
877 | return -1; | ||
878 | |||
879 | Group_c *g = get_group_c(g_c, groupnumber); | ||
880 | |||
881 | if (!g) | ||
882 | return -1; | ||
883 | |||
884 | unsigned int i; | ||
885 | const uint8_t *d = data; | ||
886 | |||
887 | while ((length - (d - data)) >= sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2) { | ||
888 | uint16_t peer_num; | ||
889 | memcpy(&peer_num, d, sizeof(peer_num)); | ||
890 | peer_num = ntohs(peer_num); | ||
891 | d += sizeof(uint16_t); | ||
892 | addpeer(g_c, groupnumber, d, d + crypto_box_PUBLICKEYBYTES, peer_num); | ||
893 | |||
894 | if (g->status == GROUPCHAT_STATUS_VALID | ||
895 | && memcmp(d, g_c->m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { | ||
896 | g->peer_number = peer_num; | ||
897 | g->status = GROUPCHAT_STATUS_CONNECTED; | ||
898 | } | ||
899 | |||
900 | d += crypto_box_PUBLICKEYBYTES * 2; | ||
901 | } | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, | ||
907 | int close_index) | ||
908 | { | ||
909 | if (length == 0) | ||
910 | return; | ||
911 | |||
912 | switch (data[0]) { | ||
913 | case PEER_QUERY_ID: { | ||
914 | Group_c *g = get_group_c(g_c, groupnumber); | ||
915 | |||
916 | if (!g) | ||
917 | return; | ||
918 | |||
919 | send_peers(g_c, groupnumber, g->close[close_index].number, g->close[close_index].group_number); | ||
920 | } | ||
921 | |||
922 | break; | ||
923 | |||
924 | case PEER_RESPONSE_ID: { | ||
925 | handle_send_peers(g_c, groupnumber, data + 1, length - 1); | ||
926 | } | ||
927 | |||
928 | break; | ||
929 | |||
930 | } | ||
931 | } | ||
932 | |||
507 | #define MIN_MESSAGE_PACKET_LEN (sizeof(uint16_t) * 2 + sizeof(uint32_t) + 1) | 933 | #define MIN_MESSAGE_PACKET_LEN (sizeof(uint16_t) * 2 + sizeof(uint32_t) + 1) |
508 | 934 | ||
509 | /* Send message to all close except receiver (if receiver isn't -1) | 935 | /* Send message to all close except receiver (if receiver isn't -1) |
@@ -514,7 +940,6 @@ static int friend_in_close(Group_c *g, int friendcon_id) | |||
514 | static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data, | 940 | static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data, |
515 | uint16_t length, int receiver) | 941 | uint16_t length, int receiver) |
516 | { | 942 | { |
517 | |||
518 | Group_c *g = get_group_c(g_c, groupnumber); | 943 | Group_c *g = get_group_c(g_c, groupnumber); |
519 | 944 | ||
520 | if (!g) | 945 | if (!g) |
@@ -523,18 +948,14 @@ static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumb | |||
523 | uint16_t i, sent = 0; | 948 | uint16_t i, sent = 0; |
524 | 949 | ||
525 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | 950 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { |
526 | if (g->close[i].type == GROUPCHAT_CLOSE_NONE) | 951 | if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) |
527 | continue; | 952 | continue; |
528 | 953 | ||
529 | if ((int)i == receiver) | 954 | if ((int)i == receiver) |
530 | continue; | 955 | continue; |
531 | 956 | ||
532 | uint16_t other_groupnum = htons(g->close[i].group_number); | 957 | if (send_packet_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_MESSAGE_GROUPCHAT, g->close[i].group_number, data, |
533 | uint8_t packet[sizeof(uint16_t) + length]; | 958 | length)) |
534 | memcpy(packet, &other_groupnum, sizeof(uint16_t)); | ||
535 | memcpy(packet + sizeof(uint16_t), data, length); | ||
536 | |||
537 | if (send_group_message_packet(g_c->m, g->close[i].number, packet, sizeof(packet))) | ||
538 | ++sent; | 959 | ++sent; |
539 | } | 960 | } |
540 | 961 | ||
@@ -559,6 +980,9 @@ static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, | |||
559 | if (!g) | 980 | if (!g) |
560 | return 0; | 981 | return 0; |
561 | 982 | ||
983 | if (g->status != GROUPCHAT_STATUS_CONNECTED) | ||
984 | return 0; | ||
985 | |||
562 | uint8_t packet[sizeof(uint16_t) + sizeof(uint32_t) + 1 + len]; | 986 | uint8_t packet[sizeof(uint16_t) + sizeof(uint32_t) + 1 + len]; |
563 | uint16_t peer_num = htons(g->peer_number); | 987 | uint16_t peer_num = htons(g->peer_number); |
564 | memcpy(packet, &peer_num, sizeof(peer_num)); | 988 | memcpy(packet, &peer_num, sizeof(peer_num)); |
@@ -595,7 +1019,7 @@ int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *m | |||
595 | static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, | 1019 | static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, |
596 | int close_index) | 1020 | int close_index) |
597 | { | 1021 | { |
598 | if (length < MIN_MESSAGE_PACKET_LEN) | 1022 | if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) |
599 | return; | 1023 | return; |
600 | 1024 | ||
601 | Group_c *g = get_group_c(g_c, groupnumber); | 1025 | Group_c *g = get_group_c(g_c, groupnumber); |
@@ -604,22 +1028,16 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const | |||
604 | return; | 1028 | return; |
605 | 1029 | ||
606 | uint16_t peer_number; | 1030 | uint16_t peer_number; |
607 | memcpy(&peer_number, data + sizeof(uint16_t), sizeof(uint16_t)); | 1031 | memcpy(&peer_number, data, sizeof(uint16_t)); |
608 | peer_number = ntohs(peer_number); | 1032 | peer_number = ntohs(peer_number); |
609 | 1033 | ||
610 | int index = get_peer_index(g, peer_number); | 1034 | int index = get_peer_index(g, peer_number); |
611 | 1035 | ||
612 | //TODO remove | ||
613 | if (index == -1) { | ||
614 | uint8_t empty_key[crypto_box_PUBLICKEYBYTES]; | ||
615 | index = addpeer(g, empty_key, peer_number); | ||
616 | } | ||
617 | |||
618 | if (index == -1) | 1036 | if (index == -1) |
619 | return; | 1037 | return; |
620 | 1038 | ||
621 | uint32_t message_number; | 1039 | uint32_t message_number; |
622 | memcpy(&message_number, data + sizeof(uint16_t) * 2, sizeof(message_number)); | 1040 | memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number)); |
623 | message_number = ntohl(message_number); | 1041 | message_number = ntohl(message_number); |
624 | 1042 | ||
625 | if (g->group[index].last_message_number == 0) { | 1043 | if (g->group[index].last_message_number == 0) { |
@@ -631,11 +1049,23 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const | |||
631 | 1049 | ||
632 | g->group[index].last_message_number = message_number; | 1050 | g->group[index].last_message_number = message_number; |
633 | 1051 | ||
634 | uint8_t message_id = data[sizeof(uint16_t) * 2 + sizeof(message_number)]; | 1052 | uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)]; |
635 | const uint8_t *msg_data = data + sizeof(uint16_t) * 2 + sizeof(message_number) + 1; | 1053 | const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1; |
636 | uint16_t msg_data_len = length - (sizeof(uint16_t) * 2 + sizeof(message_number) + 1); | 1054 | uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1); |
637 | 1055 | ||
638 | switch (message_id) { | 1056 | switch (message_id) { |
1057 | case GROUP_MESSAGE_NEW_PEER_ID: { | ||
1058 | if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) | ||
1059 | return; | ||
1060 | |||
1061 | uint16_t new_peer_number; | ||
1062 | memcpy(&new_peer_number, msg_data, sizeof(uint16_t)); | ||
1063 | new_peer_number = ntohs(new_peer_number); | ||
1064 | addpeer(g_c, groupnumber, msg_data + sizeof(uint16_t), msg_data + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, | ||
1065 | new_peer_number); | ||
1066 | } | ||
1067 | break; | ||
1068 | |||
639 | case PACKET_ID_MESSAGE: { | 1069 | case PACKET_ID_MESSAGE: { |
640 | if (msg_data_len == 0) | 1070 | if (msg_data_len == 0) |
641 | return; | 1071 | return; |
@@ -651,38 +1081,44 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const | |||
651 | return; | 1081 | return; |
652 | } | 1082 | } |
653 | 1083 | ||
654 | send_message_all_close(g_c, groupnumber, data + sizeof(uint16_t), length - sizeof(uint16_t), close_index); | 1084 | send_message_all_close(g_c, groupnumber, data, length, close_index); |
655 | } | 1085 | } |
656 | 1086 | ||
657 | static void handle_message_packet(Group_Chats *g_c, int friendcon_id, const uint8_t *data, uint16_t length) | 1087 | static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length) |
658 | { | 1088 | { |
659 | if (length < MIN_MESSAGE_PACKET_LEN) | 1089 | Group_Chats *g_c = object; |
660 | return; | 1090 | |
1091 | if (length < 1 + sizeof(uint16_t) + 1) | ||
1092 | return -1; | ||
1093 | |||
1094 | if (data[0] == PACKET_ID_ONLINE_PACKET) { | ||
1095 | return handle_packet_online(g_c, friendcon_id, data + 1, length - 1); | ||
1096 | } | ||
1097 | |||
1098 | if (data[0] != PACKET_ID_DIRECT_GROUPCHAT && data[0] != PACKET_ID_MESSAGE_GROUPCHAT) | ||
1099 | return -1; | ||
661 | 1100 | ||
662 | uint16_t groupnumber; | 1101 | uint16_t groupnumber; |
663 | memcpy(&groupnumber, data, sizeof(uint16_t)); | 1102 | memcpy(&groupnumber, data + 1, sizeof(uint16_t)); |
664 | groupnumber = ntohs(groupnumber); | 1103 | groupnumber = ntohs(groupnumber); |
665 | Group_c *g = get_group_c(g_c, groupnumber); | 1104 | Group_c *g = get_group_c(g_c, groupnumber); |
666 | 1105 | ||
667 | if (!g) | 1106 | if (!g) |
668 | return; | 1107 | return -1; |
669 | 1108 | ||
670 | int index = friend_in_close(g, friendcon_id); | 1109 | int index = friend_in_close(g, friendcon_id); |
671 | 1110 | ||
672 | if (index == -1) | 1111 | if (index == -1) |
673 | return; | ||
674 | |||
675 | handle_message_packet_group(g_c, groupnumber, data, length, index); | ||
676 | } | ||
677 | |||
678 | static int handle_packet(void *object, int number, uint8_t *data, uint16_t length) | ||
679 | { | ||
680 | if (length <= 1) | ||
681 | return -1; | 1112 | return -1; |
682 | 1113 | ||
683 | switch (data[0]) { | 1114 | switch (data[0]) { |
1115 | case PACKET_ID_DIRECT_GROUPCHAT: { | ||
1116 | handle_direct_packet(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index); | ||
1117 | break; | ||
1118 | } | ||
1119 | |||
684 | case PACKET_ID_MESSAGE_GROUPCHAT: { | 1120 | case PACKET_ID_MESSAGE_GROUPCHAT: { |
685 | handle_message_packet(object, number, data + 1, length - 1); | 1121 | handle_message_packet_group(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index); |
686 | break; | 1122 | break; |
687 | } | 1123 | } |
688 | 1124 | ||
@@ -707,6 +1143,7 @@ Group_Chats *new_groupchats(Messenger *m) | |||
707 | return NULL; | 1143 | return NULL; |
708 | 1144 | ||
709 | temp->m = m; | 1145 | temp->m = m; |
1146 | temp->fr_c = m->fr_c; | ||
710 | m->group_chat_object = temp; | 1147 | m->group_chat_object = temp; |
711 | m_callback_group_invite(m, &handle_friend_invite_packet); | 1148 | m_callback_group_invite(m, &handle_friend_invite_packet); |
712 | 1149 | ||
@@ -716,6 +1153,18 @@ Group_Chats *new_groupchats(Messenger *m) | |||
716 | /* main groupchats loop. */ | 1153 | /* main groupchats loop. */ |
717 | void do_groupchats(Group_Chats *g_c) | 1154 | void do_groupchats(Group_Chats *g_c) |
718 | { | 1155 | { |
1156 | unsigned int i; | ||
1157 | |||
1158 | for (i = 0; i < g_c->num_chats; ++i) { | ||
1159 | Group_c *g = get_group_c(g_c, i); | ||
1160 | |||
1161 | if (!g) | ||
1162 | continue; | ||
1163 | |||
1164 | if (g->status == GROUPCHAT_STATUS_CONNECTED) | ||
1165 | connect_to_closest(g_c, i); | ||
1166 | } | ||
1167 | |||
719 | //TODO | 1168 | //TODO |
720 | } | 1169 | } |
721 | 1170 | ||
diff --git a/toxcore/group.h b/toxcore/group.h index a5b5723c..94ae28bf 100644 --- a/toxcore/group.h +++ b/toxcore/group.h | |||
@@ -29,11 +29,14 @@ | |||
29 | 29 | ||
30 | enum { | 30 | enum { |
31 | GROUPCHAT_STATUS_NONE, | 31 | GROUPCHAT_STATUS_NONE, |
32 | GROUPCHAT_STATUS_VALID | 32 | GROUPCHAT_STATUS_VALID, |
33 | GROUPCHAT_STATUS_CONNECTED | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | typedef struct { | 36 | typedef struct { |
36 | uint8_t client_id[crypto_box_PUBLICKEYBYTES]; | 37 | uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; |
38 | uint8_t temp_pk[crypto_box_PUBLICKEYBYTES]; | ||
39 | |||
37 | uint64_t pingid; | 40 | uint64_t pingid; |
38 | uint64_t last_pinged; | 41 | uint64_t last_pinged; |
39 | 42 | ||
@@ -50,13 +53,14 @@ typedef struct { | |||
50 | uint16_t peer_number; | 53 | uint16_t peer_number; |
51 | } Group_Peer; | 54 | } Group_Peer; |
52 | 55 | ||
53 | #define DESIRED_CLOSE_CONNECTIONS 3 | 56 | #define DESIRED_CLOSE_CONNECTIONS 4 |
54 | #define MAX_GROUP_CONNECTIONS 16 | 57 | #define MAX_GROUP_CONNECTIONS 16 |
55 | #define GROUP_IDENTIFIER_LENGTH crypto_box_KEYBYTES /* So we can use new_symmetric_key(...) to fill it */ | 58 | #define GROUP_IDENTIFIER_LENGTH crypto_box_KEYBYTES /* So we can use new_symmetric_key(...) to fill it */ |
56 | 59 | ||
57 | enum { | 60 | enum { |
58 | GROUPCHAT_CLOSE_NONE, | 61 | GROUPCHAT_CLOSE_NONE, |
59 | GROUPCHAT_CLOSE_CONNECTION | 62 | GROUPCHAT_CLOSE_CONNECTION, |
63 | GROUPCHAT_CLOSE_ONLINE | ||
60 | }; | 64 | }; |
61 | 65 | ||
62 | typedef struct { | 66 | typedef struct { |
@@ -67,10 +71,19 @@ typedef struct { | |||
67 | 71 | ||
68 | struct { | 72 | struct { |
69 | uint8_t type; /* GROUPCHAT_CLOSE_* */ | 73 | uint8_t type; /* GROUPCHAT_CLOSE_* */ |
74 | uint8_t closest; | ||
70 | uint32_t number; | 75 | uint32_t number; |
71 | uint16_t group_number; | 76 | uint16_t group_number; |
72 | } close[MAX_GROUP_CONNECTIONS]; | 77 | } close[MAX_GROUP_CONNECTIONS]; |
73 | 78 | ||
79 | uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; | ||
80 | struct { | ||
81 | uint8_t entry; | ||
82 | uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; | ||
83 | uint8_t temp_pk[crypto_box_PUBLICKEYBYTES]; | ||
84 | } closest_peers[DESIRED_CLOSE_CONNECTIONS]; | ||
85 | uint8_t changed; | ||
86 | |||
74 | uint8_t identifier[GROUP_IDENTIFIER_LENGTH]; | 87 | uint8_t identifier[GROUP_IDENTIFIER_LENGTH]; |
75 | 88 | ||
76 | uint32_t message_number; | 89 | uint32_t message_number; |
@@ -79,6 +92,7 @@ typedef struct { | |||
79 | 92 | ||
80 | typedef struct { | 93 | typedef struct { |
81 | Messenger *m; | 94 | Messenger *m; |
95 | Friend_Connections *fr_c; | ||
82 | 96 | ||
83 | Group_c *chats; | 97 | Group_c *chats; |
84 | uint32_t num_chats; | 98 | uint32_t num_chats; |
diff --git a/toxcore/tox.c b/toxcore/tox.c index 19e1c0a4..30630cf2 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -991,6 +991,7 @@ void tox_do(Tox *tox) | |||
991 | { | 991 | { |
992 | Messenger *m = tox; | 992 | Messenger *m = tox; |
993 | do_messenger(m); | 993 | do_messenger(m); |
994 | do_groupchats(m->group_chat_object); | ||
994 | } | 995 | } |
995 | 996 | ||
996 | /* SAVING AND LOADING FUNCTIONS: */ | 997 | /* SAVING AND LOADING FUNCTIONS: */ |