summaryrefslogtreecommitdiff
path: root/toxcore/group.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/group.c')
-rw-r--r--toxcore/group.c902
1 files changed, 562 insertions, 340 deletions
diff --git a/toxcore/group.c b/toxcore/group.c
index 9313a24b..d56301cf 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27 27
28#include "group.h" 28#include "group.h"
29
29#include "util.h" 30#include "util.h"
30 31
31/* return 1 if the groupnumber is not valid. 32/* return 1 if the groupnumber is not valid.
@@ -33,14 +34,17 @@
33 */ 34 */
34static uint8_t groupnumber_not_valid(const Group_Chats *g_c, int groupnumber) 35static uint8_t groupnumber_not_valid(const Group_Chats *g_c, int groupnumber)
35{ 36{
36 if ((unsigned int)groupnumber >= g_c->num_chats) 37 if ((unsigned int)groupnumber >= g_c->num_chats) {
37 return 1; 38 return 1;
39 }
38 40
39 if (g_c->chats == NULL) 41 if (g_c->chats == NULL) {
40 return 1; 42 return 1;
43 }
41 44
42 if (g_c->chats[groupnumber].status == GROUPCHAT_STATUS_NONE) 45 if (g_c->chats[groupnumber].status == GROUPCHAT_STATUS_NONE) {
43 return 1; 46 return 1;
47 }
44 48
45 return 0; 49 return 0;
46} 50}
@@ -59,10 +63,11 @@ static int realloc_groupchats(Group_Chats *g_c, uint32_t num)
59 return 0; 63 return 0;
60 } 64 }
61 65
62 Group_c *newgroup_chats = realloc(g_c->chats, num * sizeof(Group_c)); 66 Group_c *newgroup_chats = (Group_c *)realloc(g_c->chats, num * sizeof(Group_c));
63 67
64 if (newgroup_chats == NULL) 68 if (newgroup_chats == NULL) {
65 return -1; 69 return -1;
70 }
66 71
67 g_c->chats = newgroup_chats; 72 g_c->chats = newgroup_chats;
68 return 0; 73 return 0;
@@ -79,8 +84,9 @@ static int create_group_chat(Group_Chats *g_c)
79 uint32_t i; 84 uint32_t i;
80 85
81 for (i = 0; i < g_c->num_chats; ++i) { 86 for (i = 0; i < g_c->num_chats; ++i) {
82 if (g_c->chats[i].status == GROUPCHAT_STATUS_NONE) 87 if (g_c->chats[i].status == GROUPCHAT_STATUS_NONE) {
83 return i; 88 return i;
89 }
84 } 90 }
85 91
86 int id = -1; 92 int id = -1;
@@ -102,15 +108,17 @@ static int create_group_chat(Group_Chats *g_c)
102 */ 108 */
103static int wipe_group_chat(Group_Chats *g_c, int groupnumber) 109static int wipe_group_chat(Group_Chats *g_c, int groupnumber)
104{ 110{
105 if (groupnumber_not_valid(g_c, groupnumber)) 111 if (groupnumber_not_valid(g_c, groupnumber)) {
106 return -1; 112 return -1;
113 }
107 114
108 uint32_t i; 115 uint32_t i;
109 sodium_memzero(&(g_c->chats[groupnumber]), sizeof(Group_c)); 116 sodium_memzero(&(g_c->chats[groupnumber]), sizeof(Group_c));
110 117
111 for (i = g_c->num_chats; i != 0; --i) { 118 for (i = g_c->num_chats; i != 0; --i) {
112 if (g_c->chats[i - 1].status != GROUPCHAT_STATUS_NONE) 119 if (g_c->chats[i - 1].status != GROUPCHAT_STATUS_NONE) {
113 break; 120 break;
121 }
114 } 122 }
115 123
116 if (g_c->num_chats != i) { 124 if (g_c->num_chats != i) {
@@ -123,8 +131,9 @@ static int wipe_group_chat(Group_Chats *g_c, int groupnumber)
123 131
124static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber) 132static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber)
125{ 133{
126 if (groupnumber_not_valid(g_c, groupnumber)) 134 if (groupnumber_not_valid(g_c, groupnumber)) {
127 return 0; 135 return 0;
136 }
128 137
129 return &g_c->chats[groupnumber]; 138 return &g_c->chats[groupnumber];
130} 139}
@@ -135,16 +144,18 @@ static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber)
135 * return peer index if peer is in chat. 144 * return peer index if peer is in chat.
136 * return -1 if peer is not in chat. 145 * return -1 if peer is not in chat.
137 * 146 *
138 * TODO: make this more efficient. 147 * TODO(irungentoo): make this more efficient.
139 */ 148 */
140 149
141static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk) 150static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk)
142{ 151{
143 uint32_t i; 152 uint32_t i;
144 153
145 for (i = 0; i < chat->numpeers; ++i) 154 for (i = 0; i < chat->numpeers; ++i) {
146 if (id_equal(chat->group[i].real_pk, real_pk)) 155 if (id_equal(chat->group[i].real_pk, real_pk)) {
147 return i; 156 return i;
157 }
158 }
148 159
149 return -1; 160 return -1;
150} 161}
@@ -155,15 +166,17 @@ static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk)
155 * return group number if peer is in list. 166 * return group number if peer is in list.
156 * return -1 if group is not in list. 167 * return -1 if group is not in list.
157 * 168 *
158 * TODO: make this more efficient and maybe use constant time comparisons? 169 * TODO(irungentoo): make this more efficient and maybe use constant time comparisons?
159 */ 170 */
160static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier) 171static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier)
161{ 172{
162 uint32_t i; 173 uint32_t i;
163 174
164 for (i = 0; i < g_c->num_chats; ++i) 175 for (i = 0; i < g_c->num_chats; ++i) {
165 if (sodium_memcmp(g_c->chats[i].identifier, identifier, GROUP_IDENTIFIER_LENGTH) == 0) 176 if (sodium_memcmp(g_c->chats[i].identifier, identifier, GROUP_IDENTIFIER_LENGTH) == 0) {
166 return i; 177 return i;
178 }
179 }
167 180
168 return -1; 181 return -1;
169} 182}
@@ -174,15 +187,17 @@ static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier)
174 * return peer number if peer is in chat. 187 * return peer number if peer is in chat.
175 * return -1 if peer is not in chat. 188 * return -1 if peer is not in chat.
176 * 189 *
177 * TODO: make this more efficient. 190 * TODO(irungentoo): make this more efficient.
178 */ 191 */
179static int get_peer_index(Group_c *g, uint16_t peer_number) 192static int get_peer_index(Group_c *g, uint16_t peer_number)
180{ 193{
181 uint32_t i; 194 uint32_t i;
182 195
183 for (i = 0; i < g->numpeers; ++i) 196 for (i = 0; i < g->numpeers; ++i) {
184 if (g->group[i].peer_number == peer_number) 197 if (g->group[i].peer_number == peer_number) {
185 return i; 198 return i;
199 }
200 }
186 201
187 return -1; 202 return -1;
188} 203}
@@ -215,11 +230,13 @@ static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real
215{ 230{
216 Group_c *g = get_group_c(g_c, groupnumber); 231 Group_c *g = get_group_c(g_c, groupnumber);
217 232
218 if (!g) 233 if (!g) {
219 return -1; 234 return -1;
235 }
220 236
221 if (public_key_cmp(g->real_pk, real_pk) == 0) 237 if (public_key_cmp(g->real_pk, real_pk) == 0) {
222 return -1; 238 return -1;
239 }
223 240
224 unsigned int i; 241 unsigned int i;
225 unsigned int index = DESIRED_CLOSE_CONNECTIONS; 242 unsigned int index = DESIRED_CLOSE_CONNECTIONS;
@@ -285,8 +302,9 @@ static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real
285 add_to_closest(g_c, groupnumber, old_real_pk, old_temp_pk); 302 add_to_closest(g_c, groupnumber, old_real_pk, old_temp_pk);
286 } 303 }
287 304
288 if (!g->changed) 305 if (!g->changed) {
289 g->changed = GROUPCHAT_CLOSEST_ADDED; 306 g->changed = GROUPCHAT_CLOSEST_ADDED;
307 }
290 308
291 return 0; 309 return 0;
292} 310}
@@ -296,12 +314,13 @@ static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk)
296 unsigned int i; 314 unsigned int i;
297 315
298 for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { 316 for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
299 if (!g->closest_peers[i].entry) 317 if (!g->closest_peers[i].entry) {
300 continue; 318 continue;
319 }
301 320
302 if (public_key_cmp(g->closest_peers[i].real_pk, real_pk) == 0) 321 if (public_key_cmp(g->closest_peers[i].real_pk, real_pk) == 0) {
303 return 1; 322 return 1;
304 323 }
305 } 324 }
306 325
307 return 0; 326 return 0;
@@ -309,15 +328,17 @@ static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk)
309 328
310static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier); 329static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier);
311 330
312static int connect_to_closest(Group_Chats *g_c, int groupnumber) 331static int connect_to_closest(Group_Chats *g_c, int groupnumber, void *userdata)
313{ 332{
314 Group_c *g = get_group_c(g_c, groupnumber); 333 Group_c *g = get_group_c(g_c, groupnumber);
315 334
316 if (!g) 335 if (!g) {
317 return -1; 336 return -1;
337 }
318 338
319 if (!g->changed) 339 if (!g->changed) {
320 return 0; 340 return 0;
341 }
321 342
322 unsigned int i; 343 unsigned int i;
323 344
@@ -328,11 +349,13 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber)
328 } 349 }
329 350
330 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 351 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
331 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 352 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
332 continue; 353 continue;
354 }
333 355
334 if (!g->close[i].closest) 356 if (!g->close[i].closest) {
335 continue; 357 continue;
358 }
336 359
337 uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; 360 uint8_t real_pk[crypto_box_PUBLICKEYBYTES];
338 uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; 361 uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES];
@@ -345,8 +368,9 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber)
345 } 368 }
346 369
347 for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { 370 for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
348 if (!g->closest_peers[i].entry) 371 if (!g->closest_peers[i].entry) {
349 continue; 372 continue;
373 }
350 374
351 int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk); 375 int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk);
352 376
@@ -360,7 +384,7 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber)
360 continue; 384 continue;
361 } 385 }
362 386
363 set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk); 387 set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk, userdata);
364 } 388 }
365 389
366 add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1, lock); 390 add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1, lock);
@@ -375,42 +399,48 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber)
375 return 0; 399 return 0;
376} 400}
377 401
378/* 402/* Add a peer to the group chat.
379 * Add a peer to the group chat. 403 *
404 * do_gc_callback indicates whether we want to trigger callbacks set by the client
405 * via the public API. This should be set to false if this function is called
406 * from outside of the tox_iterate() loop.
380 * 407 *
381 * return peer_index if success or peer already in chat. 408 * return peer_index if success or peer already in chat.
382 * return -1 if error. 409 * return -1 if error.
383 */ 410 */
384static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk, 411static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk,
385 uint16_t peer_number) 412 uint16_t peer_number, void *userdata, bool do_gc_callback)
386{ 413{
387 Group_c *g = get_group_c(g_c, groupnumber); 414 Group_c *g = get_group_c(g_c, groupnumber);
388 415
389 if (!g) 416 if (!g) {
390 return -1; 417 return -1;
418 }
391 419
392 //TODO 420 // TODO(irungentoo):
393 int peer_index = peer_in_chat(g, real_pk); 421 int peer_index = peer_in_chat(g, real_pk);
394 422
395 if (peer_index != -1) { 423 if (peer_index != -1) {
396 id_copy(g->group[peer_index].temp_pk, temp_pk); 424 id_copy(g->group[peer_index].temp_pk, temp_pk);
397 425
398 if (g->group[peer_index].peer_number != peer_number) 426 if (g->group[peer_index].peer_number != peer_number) {
399 return -1; 427 return -1;
428 }
400 429
401 return peer_index; 430 return peer_index;
402 } 431 }
403 432
404 peer_index = get_peer_index(g, peer_number); 433 peer_index = get_peer_index(g, peer_number);
405 434
406 if (peer_index != -1) 435 if (peer_index != -1) {
407 return -1; 436 return -1;
437 }
408 438
409 Group_Peer *temp; 439 Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
410 temp = realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
411 440
412 if (temp == NULL) 441 if (temp == NULL) {
413 return -1; 442 return -1;
443 }
414 444
415 memset(&(temp[g->numpeers]), 0, sizeof(Group_Peer)); 445 memset(&(temp[g->numpeers]), 0, sizeof(Group_Peer));
416 g->group = temp; 446 g->group = temp;
@@ -424,12 +454,13 @@ static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, co
424 454
425 add_to_closest(g_c, groupnumber, real_pk, temp_pk); 455 add_to_closest(g_c, groupnumber, real_pk, temp_pk);
426 456
427 if (g_c->peer_namelistchange) 457 if (do_gc_callback && g_c->group_namelistchange) {
428 g_c->peer_namelistchange(g_c->m, groupnumber, g->numpeers - 1, CHAT_CHANGE_PEER_ADD, 458 g_c->group_namelistchange(g_c->m, groupnumber, g->numpeers - 1, CHAT_CHANGE_PEER_ADD, userdata);
429 g_c->group_namelistchange_userdata); 459 }
430 460
431 if (g->peer_on_join) 461 if (g->peer_on_join) {
432 g->peer_on_join(g->object, groupnumber, g->numpeers - 1); 462 g->peer_on_join(g->object, groupnumber, g->numpeers - 1);
463 }
433 464
434 return (g->numpeers - 1); 465 return (g->numpeers - 1);
435} 466}
@@ -438,14 +469,16 @@ static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id
438{ 469{
439 Group_c *g = get_group_c(g_c, groupnumber); 470 Group_c *g = get_group_c(g_c, groupnumber);
440 471
441 if (!g) 472 if (!g) {
442 return -1; 473 return -1;
474 }
443 475
444 uint32_t i; 476 uint32_t i;
445 477
446 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 478 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
447 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 479 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
448 continue; 480 continue;
481 }
449 482
450 if (g->close[i].number == (unsigned int)friendcon_id) { 483 if (g->close[i].number == (unsigned int)friendcon_id) {
451 g->close[i].type = GROUPCHAT_CLOSE_NONE; 484 g->close[i].type = GROUPCHAT_CLOSE_NONE;
@@ -464,12 +497,13 @@ static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id
464 * return 0 if success 497 * return 0 if success
465 * return -1 if error. 498 * return -1 if error.
466 */ 499 */
467static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index) 500static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index, void *userdata)
468{ 501{
469 Group_c *g = get_group_c(g_c, groupnumber); 502 Group_c *g = get_group_c(g_c, groupnumber);
470 503
471 if (!g) 504 if (!g) {
472 return -1; 505 return -1;
506 }
473 507
474 uint32_t i; 508 uint32_t i;
475 509
@@ -487,7 +521,6 @@ static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index)
487 remove_close_conn(g_c, groupnumber, friendcon_id); 521 remove_close_conn(g_c, groupnumber, friendcon_id);
488 } 522 }
489 523
490 Group_Peer *temp;
491 --g->numpeers; 524 --g->numpeers;
492 525
493 void *peer_object = g->group[peer_index].object; 526 void *peer_object = g->group[peer_index].object;
@@ -496,71 +529,96 @@ static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index)
496 free(g->group); 529 free(g->group);
497 g->group = NULL; 530 g->group = NULL;
498 } else { 531 } else {
499 if (g->numpeers != (uint32_t)peer_index) 532 if (g->numpeers != (uint32_t)peer_index) {
500 memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer)); 533 memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer));
534 }
501 535
502 temp = realloc(g->group, sizeof(Group_Peer) * (g->numpeers)); 536 Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers));
503 537
504 if (temp == NULL) 538 if (temp == NULL) {
505 return -1; 539 return -1;
540 }
506 541
507 g->group = temp; 542 g->group = temp;
508 } 543 }
509 544
510 if (g_c->peer_namelistchange) 545 if (g_c->group_namelistchange) {
511 g_c->peer_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_DEL, g_c->group_namelistchange_userdata); 546 g_c->group_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_DEL, userdata);
547 }
512 548
513 if (g->peer_on_leave) 549 if (g->peer_on_leave) {
514 g->peer_on_leave(g->object, groupnumber, peer_index, peer_object); 550 g->peer_on_leave(g->object, groupnumber, peer_index, peer_object);
551 }
515 552
516 return 0; 553 return 0;
517} 554}
518 555
519static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *nick, uint16_t nick_len) 556/* Set the nick for a peer.
557 *
558 * do_gc_callback indicates whether we want to trigger callbacks set by the client
559 * via the public API. This should be set to false if this function is called
560 * from outside of the tox_iterate() loop.
561 *
562 * return 0 on success.
563 * return -1 if error.
564 */
565static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *nick, uint16_t nick_len,
566 void *userdata, bool do_gc_callback)
520{ 567{
521 if (nick_len > MAX_NAME_LENGTH) 568 if (nick_len > MAX_NAME_LENGTH) {
522 return -1; 569 return -1;
570 }
523 571
524 Group_c *g = get_group_c(g_c, groupnumber); 572 Group_c *g = get_group_c(g_c, groupnumber);
525 573
526 if (!g) 574 if (!g) {
527 return -1; 575 return -1;
576 }
528 577
529 /* same name as already stored? */ 578 /* same name as already stored? */
530 if (g->group[peer_index].nick_len == nick_len) 579 if (g->group[peer_index].nick_len == nick_len) {
531 if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len)) 580 if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len)) {
532 return 0; 581 return 0;
582 }
583 }
533 584
534 if (nick_len) 585 if (nick_len) {
535 memcpy(g->group[peer_index].nick, nick, nick_len); 586 memcpy(g->group[peer_index].nick, nick, nick_len);
587 }
536 588
537 g->group[peer_index].nick_len = nick_len; 589 g->group[peer_index].nick_len = nick_len;
538 590
539 if (g_c->peer_namelistchange) 591 if (do_gc_callback && g_c->group_namelistchange) {
540 g_c->peer_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_NAME, g_c->group_namelistchange_userdata); 592 g_c->group_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_NAME, userdata);
593 }
541 594
542 return 0; 595 return 0;
543} 596}
544 597
545static int settitle(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *title, uint8_t title_len) 598static int settitle(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *title, uint8_t title_len,
599 void *userdata)
546{ 600{
547 if (title_len > MAX_NAME_LENGTH || title_len == 0) 601 if (title_len > MAX_NAME_LENGTH || title_len == 0) {
548 return -1; 602 return -1;
603 }
549 604
550 Group_c *g = get_group_c(g_c, groupnumber); 605 Group_c *g = get_group_c(g_c, groupnumber);
551 606
552 if (!g) 607 if (!g) {
553 return -1; 608 return -1;
609 }
554 610
555 /* same as already set? */ 611 /* same as already set? */
556 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) 612 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
557 return 0; 613 return 0;
614 }
558 615
559 memcpy(g->title, title, title_len); 616 memcpy(g->title, title, title_len);
560 g->title_len = title_len; 617 g->title_len = title_len;
561 618
562 if (g_c->title_callback) 619 if (g_c->title_callback) {
563 g_c->title_callback(g_c->m, groupnumber, peer_index, title, title_len, g_c->title_callback_userdata); 620 g_c->title_callback(g_c->m, groupnumber, peer_index, title, title_len, userdata);
621 }
564 622
565 return 0; 623 return 0;
566} 624}
@@ -569,17 +627,20 @@ static void set_conns_type_close(Group_Chats *g_c, int groupnumber, int friendco
569{ 627{
570 Group_c *g = get_group_c(g_c, groupnumber); 628 Group_c *g = get_group_c(g_c, groupnumber);
571 629
572 if (!g) 630 if (!g) {
573 return; 631 return;
632 }
574 633
575 uint32_t i; 634 uint32_t i;
576 635
577 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 636 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
578 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 637 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
579 continue; 638 continue;
639 }
580 640
581 if (g->close[i].number != (unsigned int)friendcon_id) 641 if (g->close[i].number != (unsigned int)friendcon_id) {
582 continue; 642 continue;
643 }
583 644
584 if (type == GROUPCHAT_CLOSE_ONLINE) { 645 if (type == GROUPCHAT_CLOSE_ONLINE) {
585 send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier); 646 send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
@@ -598,22 +659,22 @@ static void set_conns_status_groups(Group_Chats *g_c, int friendcon_id, uint8_t
598 } 659 }
599} 660}
600 661
601static int handle_status(void *object, int friendcon_id, uint8_t status) 662static int handle_status(void *object, int friendcon_id, uint8_t status, void *userdata)
602{ 663{
603 Group_Chats *g_c = object; 664 Group_Chats *g_c = (Group_Chats *)object;
604 665
605 if (status) { /* Went online */ 666 if (status) { /* Went online */
606 set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE); 667 set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE);
607 } else { /* Went offline */ 668 } else { /* Went offline */
608 set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION); 669 set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION);
609 //TODO remove timedout connections? 670 // TODO(irungentoo): remove timedout connections?
610 } 671 }
611 672
612 return 0; 673 return 0;
613} 674}
614 675
615static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length); 676static int handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
616static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length); 677static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
617 678
618/* Add friend to group chat. 679/* Add friend to group chat.
619 * 680 *
@@ -624,8 +685,9 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnu
624{ 685{
625 Group_c *g = get_group_c(g_c, groupnumber); 686 Group_c *g = get_group_c(g_c, groupnumber);
626 687
627 if (!g) 688 if (!g) {
628 return -1; 689 return -1;
690 }
629 691
630 uint16_t i, ind = MAX_GROUP_CONNECTIONS; 692 uint16_t i, ind = MAX_GROUP_CONNECTIONS;
631 693
@@ -641,16 +703,18 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnu
641 } 703 }
642 } 704 }
643 705
644 if (ind == MAX_GROUP_CONNECTIONS) 706 if (ind == MAX_GROUP_CONNECTIONS) {
645 return -1; 707 return -1;
708 }
646 709
647 if (lock) 710 if (lock) {
648 friend_connection_lock(g_c->fr_c, friendcon_id); 711 friend_connection_lock(g_c->fr_c, friendcon_id);
712 }
649 713
650 g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION; 714 g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION;
651 g->close[ind].number = friendcon_id; 715 g->close[ind].number = friendcon_id;
652 g->close[ind].closest = closest; 716 g->close[ind].closest = closest;
653 //TODO 717 // TODO(irungentoo):
654 friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &handle_status, &handle_packet, 718 friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &handle_status, &handle_packet,
655 &handle_lossy, g_c, friendcon_id); 719 &handle_lossy, g_c, friendcon_id);
656 720
@@ -668,8 +732,9 @@ int add_groupchat(Group_Chats *g_c, uint8_t type)
668{ 732{
669 int groupnumber = create_group_chat(g_c); 733 int groupnumber = create_group_chat(g_c);
670 734
671 if (groupnumber == -1) 735 if (groupnumber == -1) {
672 return -1; 736 return -1;
737 }
673 738
674 Group_c *g = &g_c->chats[groupnumber]; 739 Group_c *g = &g_c->chats[groupnumber];
675 740
@@ -679,13 +744,13 @@ int add_groupchat(Group_Chats *g_c, uint8_t type)
679 g->identifier[0] = type; 744 g->identifier[0] = type;
680 g->peer_number = 0; /* Founder is peer 0. */ 745 g->peer_number = 0; /* Founder is peer 0. */
681 memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); 746 memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES);
682 int peer_index = addpeer(g_c, groupnumber, g->real_pk, g_c->m->dht->self_public_key, 0); 747 int peer_index = addpeer(g_c, groupnumber, g->real_pk, g_c->m->dht->self_public_key, 0, NULL, false);
683 748
684 if (peer_index == -1) { 749 if (peer_index == -1) {
685 return -1; 750 return -1;
686 } 751 }
687 752
688 setnick(g_c, groupnumber, peer_index, g_c->m->name, g_c->m->name_length); 753 setnick(g_c, groupnumber, peer_index, g_c->m->name, g_c->m->name_length, NULL, false);
689 754
690 return groupnumber; 755 return groupnumber;
691} 756}
@@ -694,36 +759,40 @@ static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_
694/* Delete a groupchat from the chats array. 759/* Delete a groupchat from the chats array.
695 * 760 *
696 * return 0 on success. 761 * return 0 on success.
697 * return -1 if failure. 762 * return -1 if groupnumber is invalid.
698 */ 763 */
699int del_groupchat(Group_Chats *g_c, int groupnumber) 764int del_groupchat(Group_Chats *g_c, int groupnumber)
700{ 765{
701 Group_c *g = get_group_c(g_c, groupnumber); 766 Group_c *g = get_group_c(g_c, groupnumber);
702 767
703 if (!g) 768 if (!g) {
704 return -1; 769 return -1;
770 }
705 771
706 group_kill_peer_send(g_c, groupnumber, g->peer_number); 772 group_kill_peer_send(g_c, groupnumber, g->peer_number);
707 773
708 unsigned int i; 774 unsigned int i;
709 775
710 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 776 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
711 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 777 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
712 continue; 778 continue;
779 }
713 780
714 g->close[i].type = GROUPCHAT_CLOSE_NONE; 781 g->close[i].type = GROUPCHAT_CLOSE_NONE;
715 kill_friend_connection(g_c->fr_c, g->close[i].number); 782 kill_friend_connection(g_c->fr_c, g->close[i].number);
716 } 783 }
717 784
718 for (i = 0; i < g->numpeers; ++i) { 785 for (i = 0; i < g->numpeers; ++i) {
719 if (g->peer_on_leave) 786 if (g->peer_on_leave) {
720 g->peer_on_leave(g->object, groupnumber, i, g->group[i].object); 787 g->peer_on_leave(g->object, groupnumber, i, g->group[i].object);
788 }
721 } 789 }
722 790
723 free(g->group); 791 free(g->group);
724 792
725 if (g->group_on_delete) 793 if (g->group_on_delete) {
726 g->group_on_delete(g->object, groupnumber); 794 g->group_on_delete(g->object, groupnumber);
795 }
727 796
728 return wipe_group_chat(g_c, groupnumber); 797 return wipe_group_chat(g_c, groupnumber);
729} 798}
@@ -731,38 +800,69 @@ int del_groupchat(Group_Chats *g_c, int groupnumber)
731/* Copy the public key of peernumber who is in groupnumber to pk. 800/* Copy the public key of peernumber who is in groupnumber to pk.
732 * pk must be crypto_box_PUBLICKEYBYTES long. 801 * pk must be crypto_box_PUBLICKEYBYTES long.
733 * 802 *
734 * returns 0 on success 803 * return 0 on success
735 * returns -1 on failure 804 * return -1 if groupnumber is invalid.
805 * return -2 if peernumber is invalid.
736 */ 806 */
737int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk) 807int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk)
738{ 808{
739 Group_c *g = get_group_c(g_c, groupnumber); 809 Group_c *g = get_group_c(g_c, groupnumber);
740 810
741 if (!g) 811 if (!g) {
742 return -1; 812 return -1;
813 }
743 814
744 if ((uint32_t)peernumber >= g->numpeers) 815 if ((uint32_t)peernumber >= g->numpeers) {
745 return -1; 816 return -2;
817 }
746 818
747 memcpy(pk, g->group[peernumber].real_pk, crypto_box_PUBLICKEYBYTES); 819 memcpy(pk, g->group[peernumber].real_pk, crypto_box_PUBLICKEYBYTES);
748 return 0; 820 return 0;
749} 821}
750 822
823/*
824 * Return the size of peernumber's name.
825 *
826 * return -1 if groupnumber is invalid.
827 * return -2 if peernumber is invalid.
828 */
829int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber)
830{
831 Group_c *g = get_group_c(g_c, groupnumber);
832
833 if (!g) {
834 return -1;
835 }
836
837 if ((uint32_t)peernumber >= g->numpeers) {
838 return -2;
839 }
840
841 if (g->group[peernumber].nick_len == 0) {
842 return 8;
843 }
844
845 return g->group[peernumber].nick_len;
846}
847
751/* Copy the name of peernumber who is in groupnumber to name. 848/* Copy the name of peernumber who is in groupnumber to name.
752 * name must be at least MAX_NAME_LENGTH long. 849 * name must be at least MAX_NAME_LENGTH long.
753 * 850 *
754 * return length of name if success 851 * return length of name if success
755 * return -1 if failure 852 * return -1 if groupnumber is invalid.
853 * return -2 if peernumber is invalid.
756 */ 854 */
757int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name) 855int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name)
758{ 856{
759 Group_c *g = get_group_c(g_c, groupnumber); 857 Group_c *g = get_group_c(g_c, groupnumber);
760 858
761 if (!g) 859 if (!g) {
762 return -1; 860 return -1;
861 }
763 862
764 if ((uint32_t)peernumber >= g->numpeers) 863 if ((uint32_t)peernumber >= g->numpeers) {
765 return -1; 864 return -2;
865 }
766 866
767 if (g->group[peernumber].nick_len == 0) { 867 if (g->group[peernumber].nick_len == 0) {
768 memcpy(name, "Tox User", 8); 868 memcpy(name, "Tox User", 8);
@@ -788,8 +888,9 @@ int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAM
788{ 888{
789 Group_c *g = get_group_c(g_c, groupnumber); 889 Group_c *g = get_group_c(g_c, groupnumber);
790 890
791 if (!g) 891 if (!g) {
792 return -1; 892 return -1;
893 }
793 894
794 unsigned int i; 895 unsigned int i;
795 896
@@ -801,33 +902,40 @@ int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAM
801} 902}
802 903
803/* Return the number of peers in the group chat on success. 904/* Return the number of peers in the group chat on success.
804 * return -1 on failure 905 * return -1 if groupnumber is invalid.
805 */ 906 */
806int group_number_peers(const Group_Chats *g_c, int groupnumber) 907int group_number_peers(const Group_Chats *g_c, int groupnumber)
807{ 908{
808 Group_c *g = get_group_c(g_c, groupnumber); 909 Group_c *g = get_group_c(g_c, groupnumber);
809 910
810 if (!g) 911 if (!g) {
811 return -1; 912 return -1;
913 }
812 914
813 return g->numpeers; 915 return g->numpeers;
814} 916}
815 917
816/* return 1 if the peernumber corresponds to ours. 918/* return 1 if the peernumber corresponds to ours.
817 * return 0 on failure. 919 * return 0 if the peernumber is not ours.
920 * return -1 if groupnumber is invalid.
921 * return -2 if peernumber is invalid.
922 * return -3 if we are not connected to the group chat.
818 */ 923 */
819unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber) 924int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber)
820{ 925{
821 Group_c *g = get_group_c(g_c, groupnumber); 926 Group_c *g = get_group_c(g_c, groupnumber);
822 927
823 if (!g) 928 if (!g) {
824 return 0; 929 return -1;
930 }
825 931
826 if (g->status != GROUPCHAT_STATUS_CONNECTED) 932 if ((uint32_t)peernumber >= g->numpeers) {
827 return 0; 933 return -2;
934 }
828 935
829 if ((uint32_t)peernumber >= g->numpeers) 936 if (g->status != GROUPCHAT_STATUS_CONNECTED) {
830 return 0; 937 return -3;
938 }
831 939
832 return g->peer_number == g->group[peernumber].peer_number; 940 return g->peer_number == g->group[peernumber].peer_number;
833} 941}
@@ -841,8 +949,9 @@ int group_get_type(const Group_Chats *g_c, int groupnumber)
841{ 949{
842 Group_c *g = get_group_c(g_c, groupnumber); 950 Group_c *g = get_group_c(g_c, groupnumber);
843 951
844 if (!g) 952 if (!g) {
845 return -1; 953 return -1;
954 }
846 955
847 return g->identifier[0]; 956 return g->identifier[0];
848} 957}
@@ -855,8 +964,9 @@ int group_get_type(const Group_Chats *g_c, int groupnumber)
855static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, 964static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,
856 uint16_t group_num, const uint8_t *data, uint16_t length) 965 uint16_t group_num, const uint8_t *data, uint16_t length)
857{ 966{
858 if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) 967 if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) {
859 return 0; 968 return 0;
969 }
860 970
861 group_num = htons(group_num); 971 group_num = htons(group_num);
862 uint8_t packet[1 + sizeof(uint16_t) + length]; 972 uint8_t packet[1 + sizeof(uint16_t) + length];
@@ -875,8 +985,9 @@ static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendc
875static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id, 985static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,
876 uint16_t group_num, const uint8_t *data, uint16_t length) 986 uint16_t group_num, const uint8_t *data, uint16_t length)
877{ 987{
878 if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) 988 if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) {
879 return 0; 989 return 0;
990 }
880 991
881 group_num = htons(group_num); 992 group_num = htons(group_num);
882 uint8_t packet[1 + sizeof(uint16_t) + length]; 993 uint8_t packet[1 + sizeof(uint16_t) + length];
@@ -893,16 +1004,19 @@ static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendco
893#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH) 1004#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH)
894#define INVITE_RESPONSE_ID 1 1005#define INVITE_RESPONSE_ID 1
895 1006
896/* invite friendnumber to groupnumber 1007/* invite friendnumber to groupnumber.
897 * return 0 on success 1008 *
898 * return -1 on failure 1009 * return 0 on success.
1010 * return -1 if groupnumber is invalid.
1011 * return -2 if invite packet failed to send.
899 */ 1012 */
900int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber) 1013int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber)
901{ 1014{
902 Group_c *g = get_group_c(g_c, groupnumber); 1015 Group_c *g = get_group_c(g_c, groupnumber);
903 1016
904 if (!g) 1017 if (!g) {
905 return -1; 1018 return -1;
1019 }
906 1020
907 uint8_t invite[INVITE_PACKET_SIZE]; 1021 uint8_t invite[INVITE_PACKET_SIZE];
908 invite[0] = INVITE_ID; 1022 invite[0] = INVITE_ID;
@@ -912,10 +1026,10 @@ int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber)
912 1026
913 if (send_group_invite_packet(g_c->m, friendnumber, invite, sizeof(invite))) { 1027 if (send_group_invite_packet(g_c->m, friendnumber, invite, sizeof(invite))) {
914 return 0; 1028 return 0;
915 } else {
916 wipe_group_chat(g_c, groupnumber);
917 return -1;
918 } 1029 }
1030
1031 wipe_group_chat(g_c, groupnumber);
1032 return -2;
919} 1033}
920 1034
921static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); 1035static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
@@ -924,29 +1038,39 @@ static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t
924 * 1038 *
925 * expected_type is the groupchat type we expect the chat we are joining is. 1039 * expected_type is the groupchat type we expect the chat we are joining is.
926 * 1040 *
927 * returns group number on success 1041 * return group number on success.
928 * returns -1 on failure. 1042 * return -1 if data length is invalid.
1043 * return -2 if group is not the expected type.
1044 * return -3 if friendnumber is invalid.
1045 * return -4 if client is already in this group.
1046 * return -5 if group instance failed to initialize.
1047 * return -6 if join packet fails to send.
929 */ 1048 */
930int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length) 1049int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length)
931{ 1050{
932 if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) 1051 if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) {
933 return -1; 1052 return -1;
1053 }
934 1054
935 if (data[sizeof(uint16_t)] != expected_type) 1055 if (data[sizeof(uint16_t)] != expected_type) {
936 return -1; 1056 return -2;
1057 }
937 1058
938 int friendcon_id = getfriendcon_id(g_c->m, friendnumber); 1059 int friendcon_id = getfriendcon_id(g_c->m, friendnumber);
939 1060
940 if (friendcon_id == -1) 1061 if (friendcon_id == -1) {
941 return -1; 1062 return -3;
1063 }
942 1064
943 if (get_group_num(g_c, data + sizeof(uint16_t)) != -1) 1065 if (get_group_num(g_c, data + sizeof(uint16_t)) != -1) {
944 return -1; 1066 return -4;
1067 }
945 1068
946 int groupnumber = create_group_chat(g_c); 1069 int groupnumber = create_group_chat(g_c);
947 1070
948 if (groupnumber == -1) 1071 if (groupnumber == -1) {
949 return -1; 1072 return -5;
1073 }
950 1074
951 Group_c *g = &g_c->chats[groupnumber]; 1075 Group_c *g = &g_c->chats[groupnumber];
952 1076
@@ -975,10 +1099,22 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type
975 1099
976 send_peer_query(g_c, friendcon_id, other_groupnum); 1100 send_peer_query(g_c, friendcon_id, other_groupnum);
977 return groupnumber; 1101 return groupnumber;
978 } else {
979 g->status = GROUPCHAT_STATUS_NONE;
980 return -1;
981 } 1102 }
1103
1104 g->status = GROUPCHAT_STATUS_NONE;
1105 return -6;
1106}
1107
1108/* Set handlers for custom lossy packets.
1109 *
1110 * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
1111 *
1112 * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length)
1113 */
1114void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *,
1115 const uint8_t *, uint16_t))
1116{
1117 g_c->lossy_packethandlers[byte].function = function;
982} 1118}
983 1119
984/* Set the callback for group invites. 1120/* Set the callback for group invites.
@@ -987,45 +1123,20 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type
987 * 1123 *
988 * data of length is what needs to be passed to join_groupchat(). 1124 * data of length is what needs to be passed to join_groupchat().
989 */ 1125 */
990void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, int32_t, uint8_t, const uint8_t *, 1126void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, int, const uint8_t *,
991 uint16_t, void *), void *userdata) 1127 size_t, void *))
992{ 1128{
993 g_c->invite_callback = function; 1129 g_c->invite_callback = function;
994 g_c->invite_callback_userdata = userdata;
995} 1130}
996 1131
997/* Set the callback for group messages. 1132/* Set the callback for group messages.
998 * 1133 *
999 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 1134 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
1000 */ 1135 */
1001void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, 1136void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
1002 void *), void *userdata) 1137 size_t, void *))
1003{ 1138{
1004 g_c->message_callback = function; 1139 g_c->message_callback = function;
1005 g_c->message_callback_userdata = userdata;
1006}
1007
1008/* Set the callback for group actions.
1009 *
1010 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
1011 */
1012void g_callback_group_action(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t,
1013 void *), void *userdata)
1014{
1015 g_c->action_callback = function;
1016 g_c->action_callback_userdata = userdata;
1017}
1018
1019/* Set handlers for custom lossy packets.
1020 *
1021 * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
1022 *
1023 * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length)
1024 */
1025void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *,
1026 const uint8_t *, uint16_t))
1027{
1028 g_c->lossy_packethandlers[byte].function = function;
1029} 1140}
1030 1141
1031/* Set callback function for peer name list changes. 1142/* Set callback function for peer name list changes.
@@ -1033,11 +1144,9 @@ void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*fu
1033 * It gets called every time the name list changes(new peer/name, deleted peer) 1144 * It gets called every time the name list changes(new peer/name, deleted peer)
1034 * Function(Group_Chats *g_c, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata) 1145 * Function(Group_Chats *g_c, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata)
1035 */ 1146 */
1036void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *), 1147void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *))
1037 void *userdata)
1038{ 1148{
1039 g_c->peer_namelistchange = function; 1149 g_c->group_namelistchange = function;
1040 g_c->group_namelistchange_userdata = userdata;
1041} 1150}
1042 1151
1043/* Set callback function for title changes. 1152/* Set callback function for title changes.
@@ -1045,11 +1154,10 @@ void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenge
1045 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata) 1154 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata)
1046 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group) 1155 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
1047 */ 1156 */
1048void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, int, int, const uint8_t *, uint8_t, 1157void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
1049 void *), void *userdata) 1158 size_t, void *))
1050{ 1159{
1051 g_c->title_callback = function; 1160 g_c->title_callback = function;
1052 g_c->title_callback_userdata = userdata;
1053} 1161}
1054 1162
1055/* Set a function to be called when a new peer joins a group chat. 1163/* Set a function to be called when a new peer joins a group chat.
@@ -1063,8 +1171,9 @@ int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*
1063{ 1171{
1064 Group_c *g = get_group_c(g_c, groupnumber); 1172 Group_c *g = get_group_c(g_c, groupnumber);
1065 1173
1066 if (!g) 1174 if (!g) {
1067 return -1; 1175 return -1;
1176 }
1068 1177
1069 g->peer_on_join = function; 1178 g->peer_on_join = function;
1070 return 0; 1179 return 0;
@@ -1081,8 +1190,9 @@ int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*fun
1081{ 1190{
1082 Group_c *g = get_group_c(g_c, groupnumber); 1191 Group_c *g = get_group_c(g_c, groupnumber);
1083 1192
1084 if (!g) 1193 if (!g) {
1085 return -1; 1194 return -1;
1195 }
1086 1196
1087 g->peer_on_leave = function; 1197 g->peer_on_leave = function;
1088 return 0; 1198 return 0;
@@ -1099,24 +1209,25 @@ int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function
1099{ 1209{
1100 Group_c *g = get_group_c(g_c, groupnumber); 1210 Group_c *g = get_group_c(g_c, groupnumber);
1101 1211
1102 if (!g) 1212 if (!g) {
1103 return -1; 1213 return -1;
1214 }
1104 1215
1105 g->group_on_delete = function; 1216 g->group_on_delete = function;
1106 return 0; 1217 return 0;
1107} 1218}
1108 1219
1109static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, 1220static int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
1110 uint16_t len); 1221 uint16_t len);
1111 1222
1112#define GROUP_MESSAGE_PING_ID 0 1223#define GROUP_MESSAGE_PING_ID 0
1113int group_ping_send(const Group_Chats *g_c, int groupnumber) 1224static int group_ping_send(const Group_Chats *g_c, int groupnumber)
1114{ 1225{
1115 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, 0, 0)) { 1226 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, 0, 0) > 0) {
1116 return 0; 1227 return 0;
1117 } else {
1118 return -1;
1119 } 1228 }
1229
1230 return -1;
1120} 1231}
1121 1232
1122#define GROUP_MESSAGE_NEW_PEER_ID 16 1233#define GROUP_MESSAGE_NEW_PEER_ID 16
@@ -1125,8 +1236,8 @@ int group_ping_send(const Group_Chats *g_c, int groupnumber)
1125 * return 0 on success 1236 * return 0 on success
1126 * return -1 on failure 1237 * return -1 on failure
1127 */ 1238 */
1128int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num, const uint8_t *real_pk, 1239static int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num, const uint8_t *real_pk,
1129 uint8_t *temp_pk) 1240 uint8_t *temp_pk)
1130{ 1241{
1131 uint8_t packet[GROUP_MESSAGE_NEW_PEER_LENGTH]; 1242 uint8_t packet[GROUP_MESSAGE_NEW_PEER_LENGTH];
1132 1243
@@ -1135,11 +1246,11 @@ int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_n
1135 memcpy(packet + sizeof(uint16_t), real_pk, crypto_box_PUBLICKEYBYTES); 1246 memcpy(packet + sizeof(uint16_t), real_pk, crypto_box_PUBLICKEYBYTES);
1136 memcpy(packet + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, temp_pk, crypto_box_PUBLICKEYBYTES); 1247 memcpy(packet + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, temp_pk, crypto_box_PUBLICKEYBYTES);
1137 1248
1138 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet))) { 1249 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet)) > 0) {
1139 return 0; 1250 return 0;
1140 } else {
1141 return -1;
1142 } 1251 }
1252
1253 return -1;
1143} 1254}
1144 1255
1145#define GROUP_MESSAGE_KILL_PEER_ID 17 1256#define GROUP_MESSAGE_KILL_PEER_ID 17
@@ -1156,11 +1267,11 @@ static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_
1156 peer_num = htons(peer_num); 1267 peer_num = htons(peer_num);
1157 memcpy(packet, &peer_num, sizeof(uint16_t)); 1268 memcpy(packet, &peer_num, sizeof(uint16_t));
1158 1269
1159 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet))) { 1270 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) {
1160 return 0; 1271 return 0;
1161 } else {
1162 return -1;
1163 } 1272 }
1273
1274 return -1;
1164} 1275}
1165 1276
1166#define GROUP_MESSAGE_NAME_ID 48 1277#define GROUP_MESSAGE_NAME_ID 48
@@ -1171,92 +1282,122 @@ static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_
1171 */ 1282 */
1172static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_t *nick, uint16_t nick_len) 1283static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_t *nick, uint16_t nick_len)
1173{ 1284{
1174 if (nick_len > MAX_NAME_LENGTH) 1285 if (nick_len > MAX_NAME_LENGTH) {
1175 return -1; 1286 return -1;
1287 }
1176 1288
1177 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NAME_ID, nick, nick_len)) { 1289 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NAME_ID, nick, nick_len) > 0) {
1178 return 0; 1290 return 0;
1179 } else {
1180 return -1;
1181 } 1291 }
1292
1293 return -1;
1182} 1294}
1183 1295
1184#define GROUP_MESSAGE_TITLE_ID 49 1296#define GROUP_MESSAGE_TITLE_ID 49
1185 1297
1186/* set the group's title, limited to MAX_NAME_LENGTH 1298/* set the group's title, limited to MAX_NAME_LENGTH
1187 * return 0 on success 1299 * return 0 on success
1188 * return -1 on failure 1300 * return -1 if groupnumber is invalid.
1301 * return -2 if title is too long or empty.
1302 * return -3 if packet fails to send.
1189 */ 1303 */
1190int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len) 1304int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len)
1191{ 1305{
1192 if (title_len > MAX_NAME_LENGTH || title_len == 0)
1193 return -1;
1194
1195 Group_c *g = get_group_c(g_c, groupnumber); 1306 Group_c *g = get_group_c(g_c, groupnumber);
1196 1307
1197 if (!g) 1308 if (!g) {
1198 return -1; 1309 return -1;
1310 }
1311
1312 if (title_len > MAX_NAME_LENGTH || title_len == 0) {
1313 return -2;
1314 }
1199 1315
1200 /* same as already set? */ 1316 /* same as already set? */
1201 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) 1317 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
1202 return 0; 1318 return 0;
1319 }
1203 1320
1204 memcpy(g->title, title, title_len); 1321 memcpy(g->title, title, title_len);
1205 g->title_len = title_len; 1322 g->title_len = title_len;
1206 1323
1207 if (g->numpeers == 1) 1324 if (g->numpeers == 1) {
1208 return 0; 1325 return 0;
1326 }
1209 1327
1210 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len)) 1328 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len) > 0) {
1211 return 0; 1329 return 0;
1212 else 1330 }
1331
1332 return -3;
1333}
1334
1335/* return the group's title size.
1336 * return -1 of groupnumber is invalid.
1337 * return -2 if title is too long or empty.
1338 */
1339int group_title_get_size(const Group_Chats *g_c, int groupnumber)
1340{
1341 Group_c *g = get_group_c(g_c, groupnumber);
1342
1343 if (!g) {
1213 return -1; 1344 return -1;
1345 }
1346
1347 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
1348 return -2;
1349 }
1350
1351 return g->title_len;
1214} 1352}
1215 1353
1216/* Get group title from groupnumber and put it in title. 1354/* Get group title from groupnumber and put it in title.
1217 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes. 1355 * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
1218 * 1356 *
1219 * return length of copied title if success. 1357 * return length of copied title if success.
1220 * return -1 if failure. 1358 * return -1 if groupnumber is invalid.
1359 * return -2 if title is too long or empty.
1221 */ 1360 */
1222int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title, uint32_t max_length) 1361int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title)
1223{ 1362{
1224 Group_c *g = get_group_c(g_c, groupnumber); 1363 Group_c *g = get_group_c(g_c, groupnumber);
1225 1364
1226 if (!g) 1365 if (!g) {
1227 return -1;
1228
1229 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH)
1230 return -1; 1366 return -1;
1367 }
1231 1368
1232 if (max_length > g->title_len) 1369 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
1233 max_length = g->title_len; 1370 return -2;
1371 }
1234 1372
1235 memcpy(title, g->title, max_length); 1373 memcpy(title, g->title, g->title_len);
1236 return max_length; 1374 return g->title_len;
1237} 1375}
1238 1376
1239static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length) 1377static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length,
1378 void *userdata)
1240{ 1379{
1241 Group_Chats *g_c = m->group_chat_object; 1380 Group_Chats *g_c = (Group_Chats *)m->group_chat_object;
1242 1381
1243 if (length <= 1) 1382 if (length <= 1) {
1244 return; 1383 return;
1384 }
1245 1385
1246 const uint8_t *invite_data = data + 1; 1386 const uint8_t *invite_data = data + 1;
1247 uint16_t invite_length = length - 1; 1387 uint16_t invite_length = length - 1;
1248 1388
1249 switch (data[0]) { 1389 switch (data[0]) {
1250 case INVITE_ID: { 1390 case INVITE_ID: {
1251 if (length != INVITE_PACKET_SIZE) 1391 if (length != INVITE_PACKET_SIZE) {
1252 return; 1392 return;
1393 }
1253 1394
1254 int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t)); 1395 int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t));
1255 1396
1256 if (groupnumber == -1) { 1397 if (groupnumber == -1) {
1257 if (g_c->invite_callback) 1398 if (g_c->invite_callback) {
1258 g_c->invite_callback(m, friendnumber, *(invite_data + sizeof(uint16_t)), invite_data, invite_length, 1399 g_c->invite_callback(m, friendnumber, *(invite_data + sizeof(uint16_t)), invite_data, invite_length, userdata);
1259 g_c->invite_callback_userdata); 1400 }
1260 1401
1261 return; 1402 return;
1262 } 1403 }
@@ -1265,8 +1406,9 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
1265 } 1406 }
1266 1407
1267 case INVITE_RESPONSE_ID: { 1408 case INVITE_RESPONSE_ID: {
1268 if (length != INVITE_RESPONSE_PACKET_SIZE) 1409 if (length != INVITE_RESPONSE_PACKET_SIZE) {
1269 return; 1410 return;
1411 }
1270 1412
1271 uint16_t other_groupnum, groupnum; 1413 uint16_t other_groupnum, groupnum;
1272 memcpy(&groupnum, data + 1 + sizeof(uint16_t), sizeof(uint16_t)); 1414 memcpy(&groupnum, data + 1 + sizeof(uint16_t), sizeof(uint16_t));
@@ -1274,14 +1416,17 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
1274 1416
1275 Group_c *g = get_group_c(g_c, groupnum); 1417 Group_c *g = get_group_c(g_c, groupnum);
1276 1418
1277 if (!g) 1419 if (!g) {
1278 return; 1420 return;
1421 }
1279 1422
1280 if (sodium_memcmp(data + 1 + sizeof(uint16_t) * 2, g->identifier, GROUP_IDENTIFIER_LENGTH) != 0) 1423 if (sodium_memcmp(data + 1 + sizeof(uint16_t) * 2, g->identifier, GROUP_IDENTIFIER_LENGTH) != 0) {
1281 return; 1424 return;
1425 }
1282 1426
1283 uint16_t peer_number = rand(); /* TODO: what if two people enter the group at the same time and 1427 /* TODO(irungentoo): what if two people enter the group at the same time and
1284 are given the same peer_number by different nodes? */ 1428 are given the same peer_number by different nodes? */
1429 uint16_t peer_number = rand();
1285 1430
1286 unsigned int tries = 0; 1431 unsigned int tries = 0;
1287 1432
@@ -1289,8 +1434,9 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
1289 peer_number = rand(); 1434 peer_number = rand();
1290 ++tries; 1435 ++tries;
1291 1436
1292 if (tries > 32) 1437 if (tries > 32) {
1293 return; 1438 return;
1439 }
1294 } 1440 }
1295 1441
1296 memcpy(&other_groupnum, data + 1, sizeof(uint16_t)); 1442 memcpy(&other_groupnum, data + 1, sizeof(uint16_t));
@@ -1300,7 +1446,7 @@ static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, con
1300 uint8_t real_pk[crypto_box_PUBLICKEYBYTES], temp_pk[crypto_box_PUBLICKEYBYTES]; 1446 uint8_t real_pk[crypto_box_PUBLICKEYBYTES], temp_pk[crypto_box_PUBLICKEYBYTES];
1301 get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id); 1447 get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id);
1302 1448
1303 addpeer(g_c, groupnum, real_pk, temp_pk, peer_number); 1449 addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, userdata, true);
1304 int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, 0, 1); 1450 int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, 0, 1);
1305 1451
1306 if (close_index != -1) { 1452 if (close_index != -1) {
@@ -1327,11 +1473,13 @@ static int friend_in_close(Group_c *g, int friendcon_id)
1327 unsigned int i; 1473 unsigned int i;
1328 1474
1329 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 1475 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
1330 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 1476 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
1331 continue; 1477 continue;
1478 }
1332 1479
1333 if (g->close[i].number != (uint32_t)friendcon_id) 1480 if (g->close[i].number != (uint32_t)friendcon_id) {
1334 continue; 1481 continue;
1482 }
1335 1483
1336 return i; 1484 return i;
1337 } 1485 }
@@ -1369,10 +1517,11 @@ static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16
1369 1517
1370static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num); 1518static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
1371 1519
1372static int handle_packet_online(Group_Chats *g_c, int friendcon_id, uint8_t *data, uint16_t length) 1520static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_t *data, uint16_t length)
1373{ 1521{
1374 if (length != ONLINE_PACKET_DATA_SIZE) 1522 if (length != ONLINE_PACKET_DATA_SIZE) {
1375 return -1; 1523 return -1;
1524 }
1376 1525
1377 int groupnumber = get_group_num(g_c, data + sizeof(uint16_t)); 1526 int groupnumber = get_group_num(g_c, data + sizeof(uint16_t));
1378 uint16_t other_groupnum; 1527 uint16_t other_groupnum;
@@ -1381,13 +1530,15 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, uint8_t *dat
1381 1530
1382 Group_c *g = get_group_c(g_c, groupnumber); 1531 Group_c *g = get_group_c(g_c, groupnumber);
1383 1532
1384 if (!g) 1533 if (!g) {
1385 return -1; 1534 return -1;
1535 }
1386 1536
1387 int index = friend_in_close(g, friendcon_id); 1537 int index = friend_in_close(g, friendcon_id);
1388 1538
1389 if (index == -1) 1539 if (index == -1) {
1390 return -1; 1540 return -1;
1541 }
1391 1542
1392 if (g->close[index].type == GROUPCHAT_CLOSE_ONLINE) { 1543 if (g->close[index].type == GROUPCHAT_CLOSE_ONLINE) {
1393 return -1; 1544 return -1;
@@ -1404,8 +1555,9 @@ static int handle_packet_online(Group_Chats *g_c, int friendcon_id, uint8_t *dat
1404 if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) { 1555 if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) {
1405 int fr_close_index = friend_in_close(g, g->number_joined); 1556 int fr_close_index = friend_in_close(g, g->number_joined);
1406 1557
1407 if (fr_close_index == -1) 1558 if (fr_close_index == -1) {
1408 return -1; 1559 return -1;
1560 }
1409 1561
1410 if (!g->close[fr_close_index].closest) { 1562 if (!g->close[fr_close_index].closest) {
1411 g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE; 1563 g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE;
@@ -1452,8 +1604,9 @@ static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_
1452{ 1604{
1453 Group_c *g = get_group_c(g_c, groupnumber); 1605 Group_c *g = get_group_c(g_c, groupnumber);
1454 1606
1455 if (!g) 1607 if (!g) {
1456 return -1; 1608 return -1;
1609 }
1457 1610
1458 uint8_t packet[MAX_CRYPTO_DATA_SIZE - (1 + sizeof(uint16_t))]; 1611 uint8_t packet[MAX_CRYPTO_DATA_SIZE - (1 + sizeof(uint16_t))];
1459 packet[0] = PEER_RESPONSE_ID; 1612 packet[0] = PEER_RESPONSE_ID;
@@ -1502,15 +1655,17 @@ static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_
1502 return sent; 1655 return sent;
1503} 1656}
1504 1657
1505static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length) 1658static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, void *userdata)
1506{ 1659{
1507 if (length == 0) 1660 if (length == 0) {
1508 return -1; 1661 return -1;
1662 }
1509 1663
1510 Group_c *g = get_group_c(g_c, groupnumber); 1664 Group_c *g = get_group_c(g_c, groupnumber);
1511 1665
1512 if (!g) 1666 if (!g) {
1513 return -1; 1667 return -1;
1668 }
1514 1669
1515 const uint8_t *d = data; 1670 const uint8_t *d = data;
1516 1671
@@ -1519,10 +1674,11 @@ static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *d
1519 memcpy(&peer_num, d, sizeof(peer_num)); 1674 memcpy(&peer_num, d, sizeof(peer_num));
1520 peer_num = ntohs(peer_num); 1675 peer_num = ntohs(peer_num);
1521 d += sizeof(uint16_t); 1676 d += sizeof(uint16_t);
1522 int peer_index = addpeer(g_c, groupnumber, d, d + crypto_box_PUBLICKEYBYTES, peer_num); 1677 int peer_index = addpeer(g_c, groupnumber, d, d + crypto_box_PUBLICKEYBYTES, peer_num, userdata, true);
1523 1678
1524 if (peer_index == -1) 1679 if (peer_index == -1) {
1525 return -1; 1680 return -1;
1681 }
1526 1682
1527 if (g->status == GROUPCHAT_STATUS_VALID 1683 if (g->status == GROUPCHAT_STATUS_VALID
1528 && public_key_cmp(d, g_c->m->net_crypto->self_public_key) == 0) { 1684 && public_key_cmp(d, g_c->m->net_crypto->self_public_key) == 0) {
@@ -1535,10 +1691,11 @@ static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *d
1535 uint8_t name_length = *d; 1691 uint8_t name_length = *d;
1536 d += 1; 1692 d += 1;
1537 1693
1538 if (name_length > (length - (d - data)) || name_length > MAX_NAME_LENGTH) 1694 if (name_length > (length - (d - data)) || name_length > MAX_NAME_LENGTH) {
1539 return -1; 1695 return -1;
1696 }
1540 1697
1541 setnick(g_c, groupnumber, peer_index, d, name_length); 1698 setnick(g_c, groupnumber, peer_index, d, name_length, userdata, true);
1542 d += name_length; 1699 d += name_length;
1543 } 1700 }
1544 1701
@@ -1546,17 +1703,19 @@ static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *d
1546} 1703}
1547 1704
1548static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, 1705static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
1549 int close_index) 1706 int close_index, void *userdata)
1550{ 1707{
1551 if (length == 0) 1708 if (length == 0) {
1552 return; 1709 return;
1710 }
1553 1711
1554 switch (data[0]) { 1712 switch (data[0]) {
1555 case PEER_KILL_ID: { 1713 case PEER_KILL_ID: {
1556 Group_c *g = get_group_c(g_c, groupnumber); 1714 Group_c *g = get_group_c(g_c, groupnumber);
1557 1715
1558 if (!g) 1716 if (!g) {
1559 return; 1717 return;
1718 }
1560 1719
1561 if (!g->close[close_index].closest) { 1720 if (!g->close[close_index].closest) {
1562 g->close[close_index].type = GROUPCHAT_CLOSE_NONE; 1721 g->close[close_index].type = GROUPCHAT_CLOSE_NONE;
@@ -1569,8 +1728,9 @@ static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_
1569 case PEER_QUERY_ID: { 1728 case PEER_QUERY_ID: {
1570 Group_c *g = get_group_c(g_c, groupnumber); 1729 Group_c *g = get_group_c(g_c, groupnumber);
1571 1730
1572 if (!g) 1731 if (!g) {
1573 return; 1732 return;
1733 }
1574 1734
1575 send_peers(g_c, groupnumber, g->close[close_index].number, g->close[close_index].group_number); 1735 send_peers(g_c, groupnumber, g->close[close_index].number, g->close[close_index].group_number);
1576 } 1736 }
@@ -1578,13 +1738,13 @@ static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_
1578 break; 1738 break;
1579 1739
1580 case PEER_RESPONSE_ID: { 1740 case PEER_RESPONSE_ID: {
1581 handle_send_peers(g_c, groupnumber, data + 1, length - 1); 1741 handle_send_peers(g_c, groupnumber, data + 1, length - 1, userdata);
1582 } 1742 }
1583 1743
1584 break; 1744 break;
1585 1745
1586 case PEER_TITLE_ID: { 1746 case PEER_TITLE_ID: {
1587 settitle(g_c, groupnumber, -1, data + 1, length - 1); 1747 settitle(g_c, groupnumber, -1, data + 1, length - 1, userdata);
1588 } 1748 }
1589 1749
1590 break; 1750 break;
@@ -1603,21 +1763,25 @@ static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumb
1603{ 1763{
1604 Group_c *g = get_group_c(g_c, groupnumber); 1764 Group_c *g = get_group_c(g_c, groupnumber);
1605 1765
1606 if (!g) 1766 if (!g) {
1607 return 0; 1767 return 0;
1768 }
1608 1769
1609 uint16_t i, sent = 0; 1770 uint16_t i, sent = 0;
1610 1771
1611 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 1772 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
1612 if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) 1773 if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) {
1613 continue; 1774 continue;
1775 }
1614 1776
1615 if ((int)i == receiver) 1777 if ((int)i == receiver) {
1616 continue; 1778 continue;
1779 }
1617 1780
1618 if (send_packet_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_MESSAGE_GROUPCHAT, g->close[i].group_number, data, 1781 if (send_packet_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_MESSAGE_GROUPCHAT, g->close[i].group_number, data,
1619 length)) 1782 length)) {
1620 ++sent; 1783 ++sent;
1784 }
1621 } 1785 }
1622 1786
1623 return sent; 1787 return sent;
@@ -1633,17 +1797,20 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1633{ 1797{
1634 Group_c *g = get_group_c(g_c, groupnumber); 1798 Group_c *g = get_group_c(g_c, groupnumber);
1635 1799
1636 if (!g) 1800 if (!g) {
1637 return 0; 1801 return 0;
1802 }
1638 1803
1639 unsigned int i, sent = 0, num_connected_closest = 0, connected_closest[DESIRED_CLOSE_CONNECTIONS]; 1804 unsigned int i, sent = 0, num_connected_closest = 0, connected_closest[DESIRED_CLOSE_CONNECTIONS];
1640 1805
1641 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { 1806 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
1642 if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) 1807 if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) {
1643 continue; 1808 continue;
1809 }
1644 1810
1645 if ((int)i == receiver) 1811 if ((int)i == receiver) {
1646 continue; 1812 continue;
1813 }
1647 1814
1648 if (g->close[i].closest) { 1815 if (g->close[i].closest) {
1649 connected_closest[num_connected_closest] = i; 1816 connected_closest[num_connected_closest] = i;
@@ -1652,8 +1819,9 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1652 } 1819 }
1653 1820
1654 if (send_lossy_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_LOSSY_GROUPCHAT, g->close[i].group_number, data, 1821 if (send_lossy_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_LOSSY_GROUPCHAT, g->close[i].group_number, data,
1655 length)) 1822 length)) {
1656 ++sent; 1823 ++sent;
1824 }
1657 } 1825 }
1658 1826
1659 if (!num_connected_closest) { 1827 if (!num_connected_closest) {
@@ -1712,21 +1880,27 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1712/* Send data of len with message_id to groupnumber. 1880/* Send data of len with message_id to groupnumber.
1713 * 1881 *
1714 * return number of peers it was sent to on success. 1882 * return number of peers it was sent to on success.
1715 * return 0 on failure. 1883 * return -1 if groupnumber is invalid.
1884 * return -2 if message is too long.
1885 * return -3 if we are not connected to the group.
1886 * reutrn -4 if message failed to send.
1716 */ 1887 */
1717static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, 1888static int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
1718 uint16_t len) 1889 uint16_t len)
1719{ 1890{
1720 if (len > MAX_GROUP_MESSAGE_DATA_LEN)
1721 return 0;
1722
1723 Group_c *g = get_group_c(g_c, groupnumber); 1891 Group_c *g = get_group_c(g_c, groupnumber);
1724 1892
1725 if (!g) 1893 if (!g) {
1726 return 0; 1894 return -1;
1895 }
1727 1896
1728 if (g->status != GROUPCHAT_STATUS_CONNECTED) 1897 if (len > MAX_GROUP_MESSAGE_DATA_LEN) {
1729 return 0; 1898 return -2;
1899 }
1900
1901 if (g->status != GROUPCHAT_STATUS_CONNECTED) {
1902 return -3;
1903 }
1730 1904
1731 uint8_t packet[sizeof(uint16_t) + sizeof(uint32_t) + 1 + len]; 1905 uint8_t packet[sizeof(uint16_t) + sizeof(uint32_t) + 1 + len];
1732 uint16_t peer_num = htons(g->peer_number); 1906 uint16_t peer_num = htons(g->peer_number);
@@ -1734,44 +1908,52 @@ static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber,
1734 1908
1735 ++g->message_number; 1909 ++g->message_number;
1736 1910
1737 if (!g->message_number) 1911 if (!g->message_number) {
1738 ++g->message_number; 1912 ++g->message_number;
1913 }
1739 1914
1740 uint32_t message_num = htonl(g->message_number); 1915 uint32_t message_num = htonl(g->message_number);
1741 memcpy(packet + sizeof(uint16_t), &message_num, sizeof(message_num)); 1916 memcpy(packet + sizeof(uint16_t), &message_num, sizeof(message_num));
1742 1917
1743 packet[sizeof(uint16_t) + sizeof(uint32_t)] = message_id; 1918 packet[sizeof(uint16_t) + sizeof(uint32_t)] = message_id;
1744 1919
1745 if (len) 1920 if (len) {
1746 memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len); 1921 memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len);
1922 }
1923
1924 unsigned int ret = send_message_all_close(g_c, groupnumber, packet, sizeof(packet), -1);
1747 1925
1748 return send_message_all_close(g_c, groupnumber, packet, sizeof(packet), -1); 1926 return (ret == 0) ? -4 : ret;
1749} 1927}
1750 1928
1751/* send a group message 1929/* send a group message
1752 * return 0 on success 1930 * return 0 on success
1753 * return -1 on failure 1931 * see: send_message_group() for error codes.
1754 */ 1932 */
1755int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length) 1933int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length)
1756{ 1934{
1757 if (send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length)) { 1935 int ret = send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length);
1936
1937 if (ret > 0) {
1758 return 0; 1938 return 0;
1759 } else {
1760 return -1;
1761 } 1939 }
1940
1941 return ret;
1762} 1942}
1763 1943
1764/* send a group action 1944/* send a group action
1765 * return 0 on success 1945 * return 0 on success
1766 * return -1 on failure 1946 * see: send_message_group() for error codes.
1767 */ 1947 */
1768int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length) 1948int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length)
1769{ 1949{
1770 if (send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length)) { 1950 int ret = send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length);
1951
1952 if (ret > 0) {
1771 return 0; 1953 return 0;
1772 } else {
1773 return -1;
1774 } 1954 }
1955
1956 return ret;
1775} 1957}
1776 1958
1777/* High level function to send custom lossy packets. 1959/* High level function to send custom lossy packets.
@@ -1781,11 +1963,12 @@ int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *ac
1781 */ 1963 */
1782int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length) 1964int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length)
1783{ 1965{
1784 //TODO: length check here? 1966 // TODO(irungentoo): length check here?
1785 Group_c *g = get_group_c(g_c, groupnumber); 1967 Group_c *g = get_group_c(g_c, groupnumber);
1786 1968
1787 if (!g) 1969 if (!g) {
1788 return -1; 1970 return -1;
1971 }
1789 1972
1790 uint8_t packet[sizeof(uint16_t) * 2 + length]; 1973 uint8_t packet[sizeof(uint16_t) * 2 + length];
1791 uint16_t peer_number = htons(g->peer_number); 1974 uint16_t peer_number = htons(g->peer_number);
@@ -1803,15 +1986,17 @@ int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8
1803} 1986}
1804 1987
1805static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, 1988static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
1806 int close_index) 1989 int close_index, void *userdata)
1807{ 1990{
1808 if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) 1991 if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) {
1809 return; 1992 return;
1993 }
1810 1994
1811 Group_c *g = get_group_c(g_c, groupnumber); 1995 Group_c *g = get_group_c(g_c, groupnumber);
1812 1996
1813 if (!g) 1997 if (!g) {
1814 return; 1998 return;
1999 }
1815 2000
1816 uint16_t peer_number; 2001 uint16_t peer_number;
1817 memcpy(&peer_number, data, sizeof(uint16_t)); 2002 memcpy(&peer_number, data, sizeof(uint16_t));
@@ -1845,80 +2030,89 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const
1845 2030
1846 switch (message_id) { 2031 switch (message_id) {
1847 case GROUP_MESSAGE_PING_ID: { 2032 case GROUP_MESSAGE_PING_ID: {
1848 if (msg_data_len != 0) 2033 if (msg_data_len != 0) {
1849 return; 2034 return;
2035 }
1850 2036
1851 g->group[index].last_recv = unix_time(); 2037 g->group[index].last_recv = unix_time();
1852 } 2038 }
1853 break; 2039 break;
1854 2040
1855 case GROUP_MESSAGE_NEW_PEER_ID: { 2041 case GROUP_MESSAGE_NEW_PEER_ID: {
1856 if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) 2042 if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) {
1857 return; 2043 return;
2044 }
1858 2045
1859 uint16_t new_peer_number; 2046 uint16_t new_peer_number;
1860 memcpy(&new_peer_number, msg_data, sizeof(uint16_t)); 2047 memcpy(&new_peer_number, msg_data, sizeof(uint16_t));
1861 new_peer_number = ntohs(new_peer_number); 2048 new_peer_number = ntohs(new_peer_number);
1862 addpeer(g_c, groupnumber, msg_data + sizeof(uint16_t), msg_data + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, 2049 addpeer(g_c, groupnumber, msg_data + sizeof(uint16_t), msg_data + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES,
1863 new_peer_number); 2050 new_peer_number, userdata, true);
1864 } 2051 }
1865 break; 2052 break;
1866 2053
1867 case GROUP_MESSAGE_KILL_PEER_ID: { 2054 case GROUP_MESSAGE_KILL_PEER_ID: {
1868 if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) 2055 if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) {
1869 return; 2056 return;
2057 }
1870 2058
1871 uint16_t kill_peer_number; 2059 uint16_t kill_peer_number;
1872 memcpy(&kill_peer_number, msg_data, sizeof(uint16_t)); 2060 memcpy(&kill_peer_number, msg_data, sizeof(uint16_t));
1873 kill_peer_number = ntohs(kill_peer_number); 2061 kill_peer_number = ntohs(kill_peer_number);
1874 2062
1875 if (peer_number == kill_peer_number) { 2063 if (peer_number == kill_peer_number) {
1876 delpeer(g_c, groupnumber, index); 2064 delpeer(g_c, groupnumber, index, userdata);
1877 } else { 2065 } else {
1878 return; 2066 return;
1879 //TODO 2067 // TODO(irungentoo):
1880 } 2068 }
1881 } 2069 }
1882 break; 2070 break;
1883 2071
1884 case GROUP_MESSAGE_NAME_ID: { 2072 case GROUP_MESSAGE_NAME_ID: {
1885 if (setnick(g_c, groupnumber, index, msg_data, msg_data_len) == -1) 2073 if (setnick(g_c, groupnumber, index, msg_data, msg_data_len, userdata, true) == -1) {
1886 return; 2074 return;
2075 }
1887 } 2076 }
1888 break; 2077 break;
1889 2078
1890 case GROUP_MESSAGE_TITLE_ID: { 2079 case GROUP_MESSAGE_TITLE_ID: {
1891 if (settitle(g_c, groupnumber, index, msg_data, msg_data_len) == -1) 2080 if (settitle(g_c, groupnumber, index, msg_data, msg_data_len, userdata) == -1) {
1892 return; 2081 return;
2082 }
1893 } 2083 }
1894 break; 2084 break;
1895 2085
1896 case PACKET_ID_MESSAGE: { 2086 case PACKET_ID_MESSAGE: {
1897 if (msg_data_len == 0) 2087 if (msg_data_len == 0) {
1898 return; 2088 return;
2089 }
1899 2090
1900 uint8_t newmsg[msg_data_len + 1]; 2091 uint8_t newmsg[msg_data_len + 1];
1901 memcpy(newmsg, msg_data, msg_data_len); 2092 memcpy(newmsg, msg_data, msg_data_len);
1902 newmsg[msg_data_len] = 0; 2093 newmsg[msg_data_len] = 0;
1903 2094
1904 //TODO 2095 // TODO(irungentoo):
1905 if (g_c->message_callback) 2096 if (g_c->message_callback) {
1906 g_c->message_callback(g_c->m, groupnumber, index, newmsg, msg_data_len, g_c->message_callback_userdata); 2097 g_c->message_callback(g_c->m, groupnumber, index, 0, newmsg, msg_data_len, userdata);
2098 }
1907 2099
1908 break; 2100 break;
1909 } 2101 }
1910 2102
1911 case PACKET_ID_ACTION: { 2103 case PACKET_ID_ACTION: {
1912 if (msg_data_len == 0) 2104 if (msg_data_len == 0) {
1913 return; 2105 return;
2106 }
1914 2107
1915 uint8_t newmsg[msg_data_len + 1]; 2108 uint8_t newmsg[msg_data_len + 1];
1916 memcpy(newmsg, msg_data, msg_data_len); 2109 memcpy(newmsg, msg_data, msg_data_len);
1917 newmsg[msg_data_len] = 0; 2110 newmsg[msg_data_len] = 0;
1918 2111
1919 //TODO 2112 // TODO(irungentoo):
1920 if (g_c->action_callback) 2113 if (g_c->message_callback) {
1921 g_c->action_callback(g_c->m, groupnumber, index, newmsg, msg_data_len, g_c->action_callback_userdata); 2114 g_c->message_callback(g_c->m, groupnumber, index, 1, newmsg, msg_data_len, userdata);
2115 }
1922 2116
1923 break; 2117 break;
1924 } 2118 }
@@ -1927,44 +2121,49 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const
1927 return; 2121 return;
1928 } 2122 }
1929 2123
1930 send_message_all_close(g_c, groupnumber, data, length, -1/*TODO close_index*/); 2124 send_message_all_close(g_c, groupnumber, data, length, -1/* TODO(irungentoo) close_index */);
1931} 2125}
1932 2126
1933static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length) 2127static int handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
1934{ 2128{
1935 Group_Chats *g_c = object; 2129 Group_Chats *g_c = (Group_Chats *)object;
1936 2130
1937 if (length < 1 + sizeof(uint16_t) + 1) 2131 if (length < 1 + sizeof(uint16_t) + 1) {
1938 return -1; 2132 return -1;
2133 }
1939 2134
1940 if (data[0] == PACKET_ID_ONLINE_PACKET) { 2135 if (data[0] == PACKET_ID_ONLINE_PACKET) {
1941 return handle_packet_online(g_c, friendcon_id, data + 1, length - 1); 2136 return handle_packet_online(g_c, friendcon_id, data + 1, length - 1);
1942 } 2137 }
1943 2138
1944 if (data[0] != PACKET_ID_DIRECT_GROUPCHAT && data[0] != PACKET_ID_MESSAGE_GROUPCHAT) 2139 if (data[0] != PACKET_ID_DIRECT_GROUPCHAT && data[0] != PACKET_ID_MESSAGE_GROUPCHAT) {
1945 return -1; 2140 return -1;
2141 }
1946 2142
1947 uint16_t groupnumber; 2143 uint16_t groupnumber;
1948 memcpy(&groupnumber, data + 1, sizeof(uint16_t)); 2144 memcpy(&groupnumber, data + 1, sizeof(uint16_t));
1949 groupnumber = ntohs(groupnumber); 2145 groupnumber = ntohs(groupnumber);
1950 Group_c *g = get_group_c(g_c, groupnumber); 2146 Group_c *g = get_group_c(g_c, groupnumber);
1951 2147
1952 if (!g) 2148 if (!g) {
1953 return -1; 2149 return -1;
2150 }
1954 2151
1955 int index = friend_in_close(g, friendcon_id); 2152 int index = friend_in_close(g, friendcon_id);
1956 2153
1957 if (index == -1) 2154 if (index == -1) {
1958 return -1; 2155 return -1;
2156 }
1959 2157
1960 switch (data[0]) { 2158 switch (data[0]) {
1961 case PACKET_ID_DIRECT_GROUPCHAT: { 2159 case PACKET_ID_DIRECT_GROUPCHAT: {
1962 handle_direct_packet(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index); 2160 handle_direct_packet(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index, userdata);
1963 break; 2161 break;
1964 } 2162 }
1965 2163
1966 case PACKET_ID_MESSAGE_GROUPCHAT: { 2164 case PACKET_ID_MESSAGE_GROUPCHAT: {
1967 handle_message_packet_group(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index); 2165 handle_message_packet_group(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index,
2166 userdata);
1968 break; 2167 break;
1969 } 2168 }
1970 2169
@@ -1982,12 +2181,13 @@ static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t
1982 * return 0 if packet was not received. 2181 * return 0 if packet was not received.
1983 * return 1 if packet was received. 2182 * return 1 if packet was received.
1984 * 2183 *
1985 * TODO: test this 2184 * TODO(irungentoo): test this
1986 */ 2185 */
1987static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16_t message_number) 2186static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16_t message_number)
1988{ 2187{
1989 if (peer_index == -1) 2188 if (peer_index == -1) {
1990 return -1; 2189 return -1;
2190 }
1991 2191
1992 if (g->group[peer_index].bottom_lossy_number == g->group[peer_index].top_lossy_number) { 2192 if (g->group[peer_index].bottom_lossy_number == g->group[peer_index].top_lossy_number) {
1993 g->group[peer_index].top_lossy_number = message_number; 2193 g->group[peer_index].top_lossy_number = message_number;
@@ -2005,8 +2205,9 @@ static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16
2005 return 0; 2205 return 0;
2006 } 2206 }
2007 2207
2008 if ((uint16_t)(message_number - g->group[peer_index].bottom_lossy_number) > (1 << 15)) 2208 if ((uint16_t)(message_number - g->group[peer_index].bottom_lossy_number) > (1 << 15)) {
2009 return -1; 2209 return -1;
2210 }
2010 2211
2011 uint16_t top_distance = message_number - g->group[peer_index].top_lossy_number; 2212 uint16_t top_distance = message_number - g->group[peer_index].top_lossy_number;
2012 2213
@@ -2035,15 +2236,17 @@ static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16
2035 return -1; 2236 return -1;
2036} 2237}
2037 2238
2038static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length) 2239static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
2039{ 2240{
2040 Group_Chats *g_c = object; 2241 Group_Chats *g_c = (Group_Chats *)object;
2041 2242
2042 if (length < 1 + sizeof(uint16_t) * 3 + 1) 2243 if (length < 1 + sizeof(uint16_t) * 3 + 1) {
2043 return -1; 2244 return -1;
2245 }
2044 2246
2045 if (data[0] != PACKET_ID_LOSSY_GROUPCHAT) 2247 if (data[0] != PACKET_ID_LOSSY_GROUPCHAT) {
2046 return -1; 2248 return -1;
2249 }
2047 2250
2048 uint16_t groupnumber, peer_number, message_number; 2251 uint16_t groupnumber, peer_number, message_number;
2049 memcpy(&groupnumber, data + 1, sizeof(uint16_t)); 2252 memcpy(&groupnumber, data + 1, sizeof(uint16_t));
@@ -2055,24 +2258,29 @@ static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uin
2055 2258
2056 Group_c *g = get_group_c(g_c, groupnumber); 2259 Group_c *g = get_group_c(g_c, groupnumber);
2057 2260
2058 if (!g) 2261 if (!g) {
2059 return -1; 2262 return -1;
2263 }
2060 2264
2061 int index = friend_in_close(g, friendcon_id); 2265 int index = friend_in_close(g, friendcon_id);
2062 2266
2063 if (index == -1) 2267 if (index == -1) {
2064 return -1; 2268 return -1;
2269 }
2065 2270
2066 if (peer_number == g->peer_number) 2271 if (peer_number == g->peer_number) {
2067 return -1; 2272 return -1;
2273 }
2068 2274
2069 int peer_index = get_peer_index(g, peer_number); 2275 int peer_index = get_peer_index(g, peer_number);
2070 2276
2071 if (peer_index == -1) 2277 if (peer_index == -1) {
2072 return -1; 2278 return -1;
2279 }
2073 2280
2074 if (lossy_packet_not_received(g, peer_index, message_number)) 2281 if (lossy_packet_not_received(g, peer_index, message_number)) {
2075 return -1; 2282 return -1;
2283 }
2076 2284
2077 const uint8_t *lossy_data = data + 1 + sizeof(uint16_t) * 3; 2285 const uint8_t *lossy_data = data + 1 + sizeof(uint16_t) * 3;
2078 uint16_t lossy_length = length - (1 + sizeof(uint16_t) * 3); 2286 uint16_t lossy_length = length - (1 + sizeof(uint16_t) * 3);
@@ -2102,8 +2310,9 @@ int group_set_object(const Group_Chats *g_c, int groupnumber, void *object)
2102{ 2310{
2103 Group_c *g = get_group_c(g_c, groupnumber); 2311 Group_c *g = get_group_c(g_c, groupnumber);
2104 2312
2105 if (!g) 2313 if (!g) {
2106 return -1; 2314 return -1;
2315 }
2107 2316
2108 g->object = object; 2317 g->object = object;
2109 return 0; 2318 return 0;
@@ -2118,11 +2327,13 @@ int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumbe
2118{ 2327{
2119 Group_c *g = get_group_c(g_c, groupnumber); 2328 Group_c *g = get_group_c(g_c, groupnumber);
2120 2329
2121 if (!g) 2330 if (!g) {
2122 return -1; 2331 return -1;
2332 }
2123 2333
2124 if ((uint32_t)peernumber >= g->numpeers) 2334 if ((uint32_t)peernumber >= g->numpeers) {
2125 return -1; 2335 return -1;
2336 }
2126 2337
2127 g->group[peernumber].object = object; 2338 g->group[peernumber].object = object;
2128 return 0; 2339 return 0;
@@ -2137,8 +2348,9 @@ void *group_get_object(const Group_Chats *g_c, int groupnumber)
2137{ 2348{
2138 Group_c *g = get_group_c(g_c, groupnumber); 2349 Group_c *g = get_group_c(g_c, groupnumber);
2139 2350
2140 if (!g) 2351 if (!g) {
2141 return NULL; 2352 return NULL;
2353 }
2142 2354
2143 return g->object; 2355 return g->object;
2144} 2356}
@@ -2152,11 +2364,13 @@ void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernum
2152{ 2364{
2153 Group_c *g = get_group_c(g_c, groupnumber); 2365 Group_c *g = get_group_c(g_c, groupnumber);
2154 2366
2155 if (!g) 2367 if (!g) {
2156 return NULL; 2368 return NULL;
2369 }
2157 2370
2158 if ((uint32_t)peernumber >= g->numpeers) 2371 if ((uint32_t)peernumber >= g->numpeers) {
2159 return NULL; 2372 return NULL;
2373 }
2160 2374
2161 return g->group[peernumber].object; 2375 return g->group[peernumber].object;
2162} 2376}
@@ -2168,33 +2382,37 @@ static int ping_groupchat(Group_Chats *g_c, int groupnumber)
2168{ 2382{
2169 Group_c *g = get_group_c(g_c, groupnumber); 2383 Group_c *g = get_group_c(g_c, groupnumber);
2170 2384
2171 if (!g) 2385 if (!g) {
2172 return -1; 2386 return -1;
2387 }
2173 2388
2174 if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) { 2389 if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) {
2175 if (group_ping_send(g_c, groupnumber) != -1) /* Ping */ 2390 if (group_ping_send(g_c, groupnumber) != -1) { /* Ping */
2176 g->last_sent_ping = unix_time(); 2391 g->last_sent_ping = unix_time();
2392 }
2177 } 2393 }
2178 2394
2179 return 0; 2395 return 0;
2180} 2396}
2181 2397
2182static int groupchat_clear_timedout(Group_Chats *g_c, int groupnumber) 2398static int groupchat_clear_timedout(Group_Chats *g_c, int groupnumber, void *userdata)
2183{ 2399{
2184 Group_c *g = get_group_c(g_c, groupnumber); 2400 Group_c *g = get_group_c(g_c, groupnumber);
2185 2401
2186 if (!g) 2402 if (!g) {
2187 return -1; 2403 return -1;
2404 }
2188 2405
2189 uint32_t i; 2406 uint32_t i;
2190 2407
2191 for (i = 0; i < g->numpeers; ++i) { 2408 for (i = 0; i < g->numpeers; ++i) {
2192 if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) { 2409 if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) {
2193 delpeer(g_c, groupnumber, i); 2410 delpeer(g_c, groupnumber, i, userdata);
2194 } 2411 }
2195 2412
2196 if (g->group == NULL || i >= g->numpeers) 2413 if (g->group == NULL || i >= g->numpeers) {
2197 break; 2414 break;
2415 }
2198 } 2416 }
2199 2417
2200 return 0; 2418 return 0;
@@ -2209,8 +2427,9 @@ void send_name_all_groups(Group_Chats *g_c)
2209 for (i = 0; i < g_c->num_chats; ++i) { 2427 for (i = 0; i < g_c->num_chats; ++i) {
2210 Group_c *g = get_group_c(g_c, i); 2428 Group_c *g = get_group_c(g_c, i);
2211 2429
2212 if (!g) 2430 if (!g) {
2213 continue; 2431 continue;
2432 }
2214 2433
2215 if (g->status == GROUPCHAT_STATUS_CONNECTED) { 2434 if (g->status == GROUPCHAT_STATUS_CONNECTED) {
2216 group_name_send(g_c, i, g_c->m->name, g_c->m->name_length); 2435 group_name_send(g_c, i, g_c->m->name, g_c->m->name_length);
@@ -2221,13 +2440,15 @@ void send_name_all_groups(Group_Chats *g_c)
2221/* Create new groupchat instance. */ 2440/* Create new groupchat instance. */
2222Group_Chats *new_groupchats(Messenger *m) 2441Group_Chats *new_groupchats(Messenger *m)
2223{ 2442{
2224 if (!m) 2443 if (!m) {
2225 return NULL; 2444 return NULL;
2445 }
2226 2446
2227 Group_Chats *temp = calloc(1, sizeof(Group_Chats)); 2447 Group_Chats *temp = (Group_Chats *)calloc(1, sizeof(Group_Chats));
2228 2448
2229 if (temp == NULL) 2449 if (temp == NULL) {
2230 return NULL; 2450 return NULL;
2451 }
2231 2452
2232 temp->m = m; 2453 temp->m = m;
2233 temp->fr_c = m->fr_c; 2454 temp->fr_c = m->fr_c;
@@ -2238,24 +2459,25 @@ Group_Chats *new_groupchats(Messenger *m)
2238} 2459}
2239 2460
2240/* main groupchats loop. */ 2461/* main groupchats loop. */
2241void do_groupchats(Group_Chats *g_c) 2462void do_groupchats(Group_Chats *g_c, void *userdata)
2242{ 2463{
2243 unsigned int i; 2464 unsigned int i;
2244 2465
2245 for (i = 0; i < g_c->num_chats; ++i) { 2466 for (i = 0; i < g_c->num_chats; ++i) {
2246 Group_c *g = get_group_c(g_c, i); 2467 Group_c *g = get_group_c(g_c, i);
2247 2468
2248 if (!g) 2469 if (!g) {
2249 continue; 2470 continue;
2471 }
2250 2472
2251 if (g->status == GROUPCHAT_STATUS_CONNECTED) { 2473 if (g->status == GROUPCHAT_STATUS_CONNECTED) {
2252 connect_to_closest(g_c, i); 2474 connect_to_closest(g_c, i, userdata);
2253 ping_groupchat(g_c, i); 2475 ping_groupchat(g_c, i);
2254 groupchat_clear_timedout(g_c, i); 2476 groupchat_clear_timedout(g_c, i, userdata);
2255 } 2477 }
2256 } 2478 }
2257 2479
2258 //TODO 2480 // TODO(irungentoo):
2259} 2481}
2260 2482
2261/* Free everything related with group chats. */ 2483/* Free everything related with group chats. */
@@ -2295,7 +2517,7 @@ uint32_t count_chatlist(Group_Chats *g_c)
2295 * Otherwise, returns the number of elements copied. 2517 * Otherwise, returns the number of elements copied.
2296 * If the array was too small, the contents 2518 * If the array was too small, the contents
2297 * of out_list will be truncated to list_size. */ 2519 * of out_list will be truncated to list_size. */
2298uint32_t copy_chatlist(Group_Chats *g_c, int32_t *out_list, uint32_t list_size) 2520uint32_t copy_chatlist(Group_Chats *g_c, uint32_t *out_list, uint32_t list_size)
2299{ 2521{
2300 if (!out_list) { 2522 if (!out_list) {
2301 return 0; 2523 return 0;