summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-09-26 13:25:52 -0400
committerirungentoo <irungentoo@gmail.com>2014-09-26 13:25:52 -0400
commit8b35d194c040270280bf658e514ef61ee2759dfb (patch)
tree46cad4ec443445b04c668b863239baed7ea2ee82
parentd5d84818fecc62425281aaf0cbe71d0f264fdc18 (diff)
Group chats are starting to work.
-rw-r--r--testing/nTox.c4
-rw-r--r--toxcore/group.c304
-rw-r--r--toxcore/group.h25
-rw-r--r--toxcore/tox.c48
-rw-r--r--toxcore/tox.h16
5 files changed, 348 insertions, 49 deletions
diff --git a/testing/nTox.c b/testing/nTox.c
index edda43b1..b33b1fd3 100644
--- a/testing/nTox.c
+++ b/testing/nTox.c
@@ -1001,11 +1001,11 @@ void print_help(char *prog_name)
1001 puts(" -f keyfile [Optional] Specify a keyfile to read from and write to."); 1001 puts(" -f keyfile [Optional] Specify a keyfile to read from and write to.");
1002} 1002}
1003 1003
1004void print_invite(Tox *m, int friendnumber, const uint8_t *group_public_key, void *userdata) 1004void print_invite(Tox *m, int friendnumber, const uint8_t *data, uint16_t length, void *userdata)
1005{ 1005{
1006 char msg[256]; 1006 char msg[256];
1007 sprintf(msg, "[i] received group chat invite from: %u, auto accepting and joining. group number: %u", friendnumber, 1007 sprintf(msg, "[i] received group chat invite from: %u, auto accepting and joining. group number: %u", friendnumber,
1008 tox_join_groupchat(m, friendnumber, group_public_key)); 1008 tox_join_groupchat(m, friendnumber, data, length));
1009 new_lines(msg); 1009 new_lines(msg);
1010} 1010}
1011 1011
diff --git a/toxcore/group.c b/toxcore/group.c
index d3652e17..602c9124 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -220,7 +220,7 @@ static int wipe_group_chat(Group_Chats *g_c, int groupnumber)
220 return 0; 220 return 0;
221} 221}
222 222
223static Group_c *get_group_c(Group_Chats *g_c, int groupnumber) 223static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber)
224{ 224{
225 if (groupnumber_not_valid(g_c, groupnumber)) 225 if (groupnumber_not_valid(g_c, groupnumber))
226 return 0; 226 return 0;
@@ -231,7 +231,7 @@ static Group_c *get_group_c(Group_Chats *g_c, int groupnumber)
231/* 231/*
232 * check if peer with client_id is in peer array. 232 * check if peer with client_id is in peer array.
233 * 233 *
234 * return peer number if peer is in chat. 234 * return peer index if peer is in chat.
235 * return -1 if peer is not in chat. 235 * return -1 if peer is not in chat.
236 * 236 *
237 * TODO: make this more efficient. 237 * TODO: make this more efficient.
@@ -268,17 +268,37 @@ static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier)
268} 268}
269 269
270/* 270/*
271 * check if peer with peer_number is in peer array.
272 *
273 * return peer number if peer is in chat.
274 * return -1 if peer is not in chat.
275 *
276 * TODO: make this more efficient.
277 */
278int get_peer_index(Group_c *g, uint16_t peer_number)
279{
280 uint32_t i;
281
282 for (i = 0; i < g->numpeers; ++i)
283 if (g->group[i].peer_number == peer_number)
284 return i;
285
286 return -1;
287}
288
289/*
271 * Add a peer to the group chat. 290 * Add a peer to the group chat.
272 * 291 *
273 * return peernum if success or peer already in chat. 292 * return peer_index if success or peer already in chat.
274 * return -1 if error. 293 * return -1 if error.
275 */ 294 */
276static int addpeer(Group_c *chat, const uint8_t *client_id) 295static int addpeer(Group_c *chat, const uint8_t *client_id, uint16_t peer_number)
277{ 296{
278 int peernum = peer_in_chat(chat, client_id); 297 //TODO
298 //int peer_index = peer_in_chat(chat, client_id);
279 299
280 if (peernum != -1) 300 //if (peer_index != -1)
281 return peernum; 301 // return peer_index;
282 302
283 Group_Peer *temp; 303 Group_Peer *temp;
284 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1)); 304 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1));
@@ -290,6 +310,8 @@ static int addpeer(Group_c *chat, const uint8_t *client_id)
290 chat->group = temp; 310 chat->group = temp;
291 311
292 id_copy(chat->group[chat->numpeers].client_id, client_id); 312 id_copy(chat->group[chat->numpeers].client_id, client_id);
313 chat->group[chat->numpeers].peer_number = peer_number;
314
293 chat->group[chat->numpeers].last_recv = unix_time(); 315 chat->group[chat->numpeers].last_recv = unix_time();
294 chat->group[chat->numpeers].last_recv_msgping = unix_time(); 316 chat->group[chat->numpeers].last_recv_msgping = unix_time();
295 ++chat->numpeers; 317 ++chat->numpeers;
@@ -300,6 +322,39 @@ static int addpeer(Group_c *chat, const uint8_t *client_id)
300 return (chat->numpeers - 1); 322 return (chat->numpeers - 1);
301} 323}
302 324
325/* Add friend to group chat.
326 *
327 * return 0 on success
328 * return -1 on failure.
329 */
330static int add_friend_to_groupchat(Group_Chats *g_c, int32_t friendnumber, int groupnumber, uint16_t other_groupnum)
331{
332 if (!m_friend_exists(g_c->m, friendnumber))
333 return -1;
334
335 Group_c *g = get_group_c(g_c, groupnumber);
336
337 if (!g)
338 return -1;
339
340 uint16_t i;
341
342 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
343 if (g->close[i].type != GROUPCHAT_CLOSE_NONE)
344 continue;
345
346 break;
347 }
348
349 if (i == MAX_GROUP_CONNECTIONS)
350 return -1;
351
352 g->close[i].type = GROUPCHAT_CLOSE_FRIEND;
353 g->close[i].number = friendnumber;
354 g->close[i].group_number = other_groupnum;
355
356 return 0;
357}
303 358
304/* Creates a new groupchat and puts it in the chats array. 359/* Creates a new groupchat and puts it in the chats array.
305 * 360 *
@@ -310,13 +365,14 @@ int add_groupchat(Group_Chats *g_c)
310{ 365{
311 int groupnumber = create_group_chat(g_c); 366 int groupnumber = create_group_chat(g_c);
312 367
313 Group_c *g = get_group_c(g_c, groupnumber); 368 if (groupnumber == -1)
314
315 if (!g)
316 return -1; 369 return -1;
317 370
371 Group_c *g = &g_c->chats[groupnumber];
372
318 g->status = GROUPCHAT_STATUS_VALID; 373 g->status = GROUPCHAT_STATUS_VALID;
319 new_symmetric_key(g->identifier); 374 new_symmetric_key(g->identifier);
375 g->peer_number = 0; /* Founder is peer 0. */
320 return groupnumber; 376 return groupnumber;
321} 377}
322 378
@@ -356,18 +412,18 @@ int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber)
356 * returns group number on success 412 * returns group number on success
357 * returns -1 on failure. 413 * returns -1 on failure.
358 */ 414 */
359int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t *data, uint16_t length) 415int join_groupchat(Group_Chats *g_c, int32_t friendnumber, const uint8_t *data, uint16_t length)
360{ 416{
361 if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) 417 if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH)
362 return -1; 418 return -1;
363 419
364 int groupnumber = create_group_chat(g_c); 420 int groupnumber = create_group_chat(g_c);
365 421
366 Group_c *g = get_group_c(g_c, groupnumber); 422 if (groupnumber == -1)
367
368 if (!g)
369 return -1; 423 return -1;
370 424
425 Group_c *g = &g_c->chats[groupnumber];
426
371 uint16_t group_num = htons(groupnumber); 427 uint16_t group_num = htons(groupnumber);
372 g->status = GROUPCHAT_STATUS_VALID; 428 g->status = GROUPCHAT_STATUS_VALID;
373 uint8_t response[INVITE_RESPONSE_PACKET_SIZE]; 429 uint8_t response[INVITE_RESPONSE_PACKET_SIZE];
@@ -379,7 +435,9 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t *data, uint16
379 uint16_t other_groupnum; 435 uint16_t other_groupnum;
380 memcpy(&other_groupnum, data, sizeof(other_groupnum)); 436 memcpy(&other_groupnum, data, sizeof(other_groupnum));
381 other_groupnum = htons(other_groupnum); 437 other_groupnum = htons(other_groupnum);
382 //TODO add_friend_to_groupchat(g_c, friendnumber, groupnumber, other_groupnum); 438 memcpy(g->identifier, data + sizeof(uint16_t), GROUP_IDENTIFIER_LENGTH);
439 add_friend_to_groupchat(g_c, friendnumber, groupnumber, other_groupnum);
440 g->peer_number = rand(); /* TODO */
383 return groupnumber; 441 return groupnumber;
384 } else { 442 } else {
385 return -1; 443 return -1;
@@ -428,10 +486,16 @@ static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, cons
428 int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t)); 486 int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t));
429 487
430 if (groupnumber == -1) { 488 if (groupnumber == -1) {
431 g_c->invite_callback(m, friendnumber, invite_data, invite_length, g_c->invite_callback_userdata); 489 if (g_c->invite_callback)
490 g_c->invite_callback(m, friendnumber, invite_data, invite_length, g_c->invite_callback_userdata);
491
432 return; 492 return;
433 } else { 493 } else {
434 //TODO 494 //TODO
495 uint16_t other_groupnum;
496 memcpy(&other_groupnum, data + 1, sizeof(uint16_t));
497 other_groupnum = ntohs(other_groupnum);
498 add_friend_to_groupchat(g_c, friendnumber, groupnumber, other_groupnum);
435 } 499 }
436 500
437 break; 501 break;
@@ -441,13 +505,22 @@ static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, cons
441 if (length != INVITE_RESPONSE_PACKET_SIZE) 505 if (length != INVITE_RESPONSE_PACKET_SIZE)
442 return; 506 return;
443 507
444 int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t)); 508 uint16_t other_groupnum, groupnum;
509 memcpy(&groupnum, data + 1 + sizeof(uint16_t), sizeof(uint16_t));
510 groupnum = ntohs(groupnum);
445 511
446 if (groupnumber == -1) { 512 Group_c *g = get_group_c(g_c, groupnum);
513
514 if (!g)
515 return;
516
517 if (memcmp(data + 1 + sizeof(uint16_t) * 2, g->identifier, GROUP_IDENTIFIER_LENGTH) != 0)
447 return; 518 return;
448 } else { 519
449 //TODO add_friend_to_groupchat(g_c, friendnumber, groupnumber, other_groupnum); 520 memcpy(&other_groupnum, data + 1, sizeof(uint16_t));
450 } 521 other_groupnum = ntohs(other_groupnum);
522
523 add_friend_to_groupchat(g_c, friendnumber, groupnum, other_groupnum);
451 524
452 break; 525 break;
453 } 526 }
@@ -457,9 +530,197 @@ static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, cons
457 } 530 }
458} 531}
459 532
533/* Find index of friend in the close list;
534 *
535 * returns index on success
536 * returns -1 on failure.
537 */
538static int friend_in_close(Group_c *g, int32_t friendnumber)
539{
540 int i;
541
542 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
543 if (g->close[i].type != GROUPCHAT_CLOSE_FRIEND)
544 continue;
545
546 if (g->close[i].number != (uint32_t)friendnumber)
547 continue;
548
549 break;
550 }
551
552 if (i == MAX_GROUP_CONNECTIONS)
553 return -1;
554
555 return i;
556}
557
558#define MIN_MESSAGE_PACKET_LEN (sizeof(uint16_t) * 2 + sizeof(uint32_t) + 1)
559
560/* Send message to all close except receiver (if receiver isn't -1)
561 * NOTE: this function appends the group chat number to the data passed to it.
562 *
563 * return number of messages sent.
564 */
565static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data,
566 uint16_t length, int receiver)
567{
568
569 Group_c *g = get_group_c(g_c, groupnumber);
570
571 if (!g)
572 return 0;
573
574 uint16_t i, sent = 0;
575
576 for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
577 if (g->close[i].type == GROUPCHAT_CLOSE_NONE)
578 continue;
579
580 if ((int)i == receiver)
581 continue;
582
583 uint16_t other_groupnum = htons(g->close[i].group_number);
584 uint8_t packet[sizeof(uint16_t) + length];
585 memcpy(packet, &other_groupnum, sizeof(uint16_t));
586 memcpy(packet + sizeof(uint16_t), data, length);
587
588 if (send_group_message_packet(g_c->m, g->close[i].number, packet, sizeof(packet)))
589 ++sent;
590 }
591
592 return sent;
593}
594
595/* Send data of len with message_id to groupnumber.
596 *
597 * return number of peers it was sent to on success.
598 * return 0 on failure.
599 */
600static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
601 uint16_t len)
602{
603 Group_c *g = get_group_c(g_c, groupnumber);
604
605 if (!g)
606 return 0;
607
608 uint8_t packet[sizeof(uint16_t) + sizeof(uint32_t) + 1 + len];
609 uint16_t peer_num = htons(g->peer_number);
610 memcpy(packet, &peer_num, sizeof(peer_num));
611
612 ++g->message_number;
613
614 if (!g->message_number)
615 ++g->message_number;
616
617 uint32_t message_num = htonl(g->message_number);
618 memcpy(packet + sizeof(uint16_t), &message_num, sizeof(message_num));
619
620 packet[sizeof(uint16_t) + sizeof(uint32_t)] = message_id;
621
622 if (len)
623 memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len);
624
625 return send_message_all_close(g_c, groupnumber, packet, sizeof(packet), -1);
626}
627
628/* send a group message
629 * return 0 on success
630 * return -1 on failure
631 */
632int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length)
633{
634 if (send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length)) {
635 return 0;
636 } else {
637 return -1;
638 }
639}
640
641static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
642 int close_index)
643{
644 if (length < MIN_MESSAGE_PACKET_LEN)
645 return;
646
647 Group_c *g = get_group_c(g_c, groupnumber);
648
649 if (!g)
650 return;
651
652 uint16_t peer_number;
653 memcpy(&peer_number, data + sizeof(uint16_t), sizeof(uint16_t));
654 peer_number = ntohs(peer_number);
655
656 int index = get_peer_index(g, peer_number);
657
658 //TODO remove
659 if (index == -1) {
660 uint8_t empty_key[crypto_box_PUBLICKEYBYTES];
661 index = addpeer(g, empty_key, peer_number);
662 }
663
664 if (index == -1)
665 return;
666
667 uint32_t message_number;
668 memcpy(&message_number, data + sizeof(uint16_t) * 2, sizeof(message_number));
669 message_number = ntohl(message_number);
670
671 if (g->group[index].last_message_number == 0) {
672 g->group[index].last_message_number = message_number;
673 } else if (message_number - g->group[index].last_message_number > 64 ||
674 message_number == g->group[index].last_message_number) {
675 return;
676 }
677
678 g->group[index].last_message_number = message_number;
679
680 uint8_t message_id = data[sizeof(uint16_t) * 2 + sizeof(message_number)];
681 const uint8_t *msg_data = data + sizeof(uint16_t) * 2 + sizeof(message_number) + 1;
682 uint16_t msg_data_len = length - (sizeof(uint16_t) * 2 + sizeof(message_number) + 1);
683
684 switch (message_id) {
685 case PACKET_ID_MESSAGE: {
686 if (msg_data_len == 0)
687 return;
688
689 //TODO
690 if (g_c->message_callback)
691 g_c->message_callback(g_c->m, groupnumber, index, msg_data, msg_data_len, g_c->message_callback_userdata);
692
693 break;
694 }
695
696 default:
697 return;
698 }
699
700 send_message_all_close(g_c, groupnumber, data + sizeof(uint16_t), length - sizeof(uint16_t), close_index);
701}
702
460static void handle_friend_message_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) 703static void handle_friend_message_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
461{ 704{
705 Group_Chats *g_c = m->group_chat_object;
706
707 if (length < MIN_MESSAGE_PACKET_LEN)
708 return;
709
710 uint16_t groupnumber;
711 memcpy(&groupnumber, data, sizeof(uint16_t));
712 groupnumber = ntohs(groupnumber);
713 Group_c *g = get_group_c(g_c, groupnumber);
714
715 if (!g)
716 return;
717
718 int index = friend_in_close(g, friendnumber);
719
720 if (index == -1)
721 return;
462 722
723 handle_message_packet_group(g_c, groupnumber, data, length, index);
463} 724}
464 725
465/* Create new groupchat instance. */ 726/* Create new groupchat instance. */
@@ -476,6 +737,7 @@ Group_Chats *new_groupchats(Messenger *m)
476 temp->m = m; 737 temp->m = m;
477 m->group_chat_object = temp; 738 m->group_chat_object = temp;
478 m_callback_group_invite(m, &handle_friend_invite_packet); 739 m_callback_group_invite(m, &handle_friend_invite_packet);
740 m_callback_group_message(m, &handle_friend_message_packet);
479 741
480 return temp; 742 return temp;
481} 743}
diff --git a/toxcore/group.h b/toxcore/group.h
index 544fbdb7..51152843 100644
--- a/toxcore/group.h
+++ b/toxcore/group.h
@@ -41,7 +41,6 @@ typedef struct {
41 uint8_t client_id[crypto_box_PUBLICKEYBYTES]; 41 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
42 uint64_t pingid; 42 uint64_t pingid;
43 uint64_t last_pinged; 43 uint64_t last_pinged;
44 IP_Port ping_via;
45 44
46 uint64_t last_recv; 45 uint64_t last_recv;
47 uint64_t last_recv_msgping; 46 uint64_t last_recv_msgping;
@@ -52,12 +51,20 @@ typedef struct {
52 51
53 uint8_t deleted; 52 uint8_t deleted;
54 uint64_t deleted_time; 53 uint64_t deleted_time;
55} Group_Peer;
56 54
55 uint16_t peer_number;
56} Group_Peer;
57 57
58#define MAX_GROUP_CONNECTIONS 4 58#define DESIRED_CLOSE_CONNECTIONS 3
59#define MAX_GROUP_CONNECTIONS 16
59#define GROUP_IDENTIFIER_LENGTH crypto_box_KEYBYTES /* So we can use new_symmetric_key(...) to fill it */ 60#define GROUP_IDENTIFIER_LENGTH crypto_box_KEYBYTES /* So we can use new_symmetric_key(...) to fill it */
60 61
62enum {
63 GROUPCHAT_CLOSE_NONE,
64 GROUPCHAT_CLOSE_FRIEND,
65 GROUPCHAT_CLOSE_GROUPCON
66};
67
61typedef struct { 68typedef struct {
62 uint8_t status; 69 uint8_t status;
63 70
@@ -65,11 +72,15 @@ typedef struct {
65 uint32_t numpeers; 72 uint32_t numpeers;
66 73
67 struct { 74 struct {
68 uint8_t type; 75 uint8_t type; /* GROUPCHAT_CLOSE_* */
69 uint32_t number; 76 uint32_t number;
77 uint16_t group_number;
70 } close[MAX_GROUP_CONNECTIONS]; 78 } close[MAX_GROUP_CONNECTIONS];
71 79
72 uint8_t identifier[GROUP_IDENTIFIER_LENGTH]; 80 uint8_t identifier[GROUP_IDENTIFIER_LENGTH];
81
82 uint32_t message_number;
83 uint16_t peer_number;
73} Group_c; 84} Group_c;
74 85
75typedef struct { 86typedef struct {
@@ -155,19 +166,19 @@ int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber);
155 * returns group number on success 166 * returns group number on success
156 * returns -1 on failure. 167 * returns -1 on failure.
157 */ 168 */
158int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t *data, uint16_t length); 169int join_groupchat(Group_Chats *g_c, int32_t friendnumber, const uint8_t *data, uint16_t length);
159 170
160/* send a group message 171/* send a group message
161 * return 0 on success 172 * return 0 on success
162 * return -1 on failure 173 * return -1 on failure
163 */ 174 */
164int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint32_t length); 175int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length);
165 176
166/* send a group action 177/* send a group action
167 * return 0 on success 178 * return 0 on success
168 * return -1 on failure 179 * return -1 on failure
169 */ 180 */
170int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint32_t length); 181int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length);
171 182
172/* Return the number of peers in the group chat on success. 183/* Return the number of peers in the group chat on success.
173 * return -1 on failure 184 * return -1 on failure
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 39a63fd9..789ef3c9 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27 27
28#include "Messenger.h" 28#include "Messenger.h"
29#include "group.h"
29#include "logger.h" 30#include "logger.h"
30 31
31#define __TOX_DEFINED__ 32#define __TOX_DEFINED__
@@ -544,13 +545,15 @@ int tox_send_lossless_packet(const Tox *tox, int32_t friendnumber, const uint8_t
544 545
545/* Set the callback for group invites. 546/* Set the callback for group invites.
546 * 547 *
547 * Function(Tox *tox, int32_t friendnumber, uint8_t *group_public_key, void *userdata) 548 * Function(Tox *tox, int32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
549 *
550 * data of length is what needs to be passed to join_groupchat().
548 */ 551 */
549void tox_callback_group_invite(Tox *tox, void (*function)(Messenger *tox, int32_t, const uint8_t *, void *), 552void tox_callback_group_invite(Tox *tox, void (*function)(Messenger *tox, int32_t, const uint8_t *, uint16_t, void *),
550 void *userdata) 553 void *userdata)
551{ 554{
552 Messenger *m = tox; 555 Messenger *m = tox;
553 //m_callback_group_invite(m, function, userdata); 556 g_callback_group_invite(m->group_chat_object, function, userdata);
554} 557}
555 558
556/* Set the callback for group messages. 559/* Set the callback for group messages.
@@ -561,7 +564,7 @@ void tox_callback_group_message(Tox *tox, void (*function)(Messenger *tox, int,
561 void *userdata) 564 void *userdata)
562{ 565{
563 Messenger *m = tox; 566 Messenger *m = tox;
564 //m_callback_group_message(m, function, userdata); 567 g_callback_group_message(m->group_chat_object, function, userdata);
565} 568}
566 569
567/* Set the callback for group actions. 570/* Set the callback for group actions.
@@ -594,8 +597,9 @@ void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int
594int tox_add_groupchat(Tox *tox) 597int tox_add_groupchat(Tox *tox)
595{ 598{
596 Messenger *m = tox; 599 Messenger *m = tox;
597 //return add_groupchat(m); 600 return add_groupchat(m->group_chat_object);
598} 601}
602
599/* Delete a groupchat from the chats array. 603/* Delete a groupchat from the chats array.
600 * 604 *
601 * return 0 on success. 605 * return 0 on success.
@@ -605,6 +609,7 @@ int tox_del_groupchat(Tox *tox, int groupnumber)
605{ 609{
606 Messenger *m = tox; 610 Messenger *m = tox;
607 //return del_groupchat(m, groupnumber); 611 //return del_groupchat(m, groupnumber);
612 return -1;
608} 613}
609 614
610/* Copy the name of peernumber who is in groupnumber to name. 615/* Copy the name of peernumber who is in groupnumber to name.
@@ -617,7 +622,9 @@ int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t
617{ 622{
618 const Messenger *m = tox; 623 const Messenger *m = tox;
619 //return m_group_peername(m, groupnumber, peernumber, name); 624 //return m_group_peername(m, groupnumber, peernumber, name);
625 return -1;
620} 626}
627
621/* invite friendnumber to groupnumber 628/* invite friendnumber to groupnumber
622 * return 0 on success 629 * return 0 on success
623 * return -1 on failure 630 * return -1 on failure
@@ -625,37 +632,40 @@ int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t
625int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber) 632int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber)
626{ 633{
627 Messenger *m = tox; 634 Messenger *m = tox;
628 //return invite_friend(m, friendnumber, groupnumber); 635 return invite_friend(m->group_chat_object, friendnumber, groupnumber);
629} 636}
630/* Join a group (you need to have been invited first.) 637
638/* Join a group (you need to have been invited first.) using data of length obtained
639 * in the group invite callback.
631 * 640 *
632 * returns group number on success 641 * returns group number on success
633 * returns -1 on failure. 642 * returns -1 on failure.
634 */ 643 */
635int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *friend_group_public_key) 644int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length)
636{ 645{
637 Messenger *m = tox; 646 Messenger *m = tox;
638 //return join_groupchat(m, friendnumber, friend_group_public_key); 647 return join_groupchat(m->group_chat_object, friendnumber, data, length);
639} 648}
640 649
641/* send a group message 650/* send a group message
642 * return 0 on success 651 * return 0 on success
643 * return -1 on failure 652 * return -1 on failure
644 */ 653 */
645int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint32_t length) 654int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint16_t length)
646{ 655{
647 Messenger *m = tox; 656 Messenger *m = tox;
648 //return group_message_send(m, groupnumber, message, length); 657 return group_message_send(m->group_chat_object, groupnumber, message, length);
649} 658}
650 659
651/* send a group action 660/* send a group action
652 * return 0 on success 661 * return 0 on success
653 * return -1 on failure 662 * return -1 on failure
654 */ 663 */
655int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint32_t length) 664int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint16_t length)
656{ 665{
657 Messenger *m = tox; 666 Messenger *m = tox;
658 //return group_action_send(m, groupnumber, action, length); 667 //return group_action_send(m, groupnumber, action, length);
668 return -1;
659} 669}
660 670
661/* Return the number of peers in the group chat on success. 671/* Return the number of peers in the group chat on success.
@@ -665,6 +675,7 @@ int tox_group_number_peers(const Tox *tox, int groupnumber)
665{ 675{
666 const Messenger *m = tox; 676 const Messenger *m = tox;
667 //return group_number_peers(m, groupnumber); 677 //return group_number_peers(m, groupnumber);
678 return -1;
668} 679}
669 680
670/* List all the peers in the group chat. 681/* List all the peers in the group chat.
@@ -682,6 +693,7 @@ int tox_group_get_names(const Tox *tox, int groupnumber, uint8_t names[][TOX_MAX
682{ 693{
683 const Messenger *m = tox; 694 const Messenger *m = tox;
684 //return group_names(m, groupnumber, names, lengths, length); 695 //return group_names(m, groupnumber, names, lengths, length);
696 return -1;
685} 697}
686 698
687/* Return the number of chats in the instance m. 699/* Return the number of chats in the instance m.
@@ -691,6 +703,7 @@ uint32_t tox_count_chatlist(const Tox *tox)
691{ 703{
692 const Messenger *m = tox; 704 const Messenger *m = tox;
693 //return count_chatlist(m); 705 //return count_chatlist(m);
706 return 0;
694} 707}
695 708
696/* Copy a list of valid chat IDs into the array out_list. 709/* Copy a list of valid chat IDs into the array out_list.
@@ -702,6 +715,7 @@ uint32_t tox_get_chatlist(const Tox *tox, int *out_list, uint32_t list_size)
702{ 715{
703 const Messenger *m = tox; 716 const Messenger *m = tox;
704 //return copy_chatlist(m, out_list, list_size); 717 //return copy_chatlist(m, out_list, list_size);
718 return 0;
705} 719}
706 720
707 721
@@ -947,7 +961,14 @@ Tox *tox_new(Tox_Options *options)
947 } 961 }
948 } 962 }
949 963
950 return new_messenger(&m_options); 964 Messenger *m = new_messenger(&m_options);
965
966 if (!new_groupchats(m)) {
967 kill_messenger(m);
968 return NULL;
969 }
970
971 return m;
951} 972}
952 973
953/* Run this before closing shop. 974/* Run this before closing shop.
@@ -956,6 +977,7 @@ Tox *tox_new(Tox_Options *options)
956void tox_kill(Tox *tox) 977void tox_kill(Tox *tox)
957{ 978{
958 Messenger *m = tox; 979 Messenger *m = tox;
980 kill_groupchats(m->group_chat_object);
959 kill_messenger(m); 981 kill_messenger(m);
960} 982}
961 983
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 61cfdf70..a271bc60 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -419,9 +419,12 @@ int tox_send_lossless_packet(const Tox *tox, int32_t friendnumber, const uint8_t
419 419
420/* Set the callback for group invites. 420/* Set the callback for group invites.
421 * 421 *
422 * Function(Tox *tox, int friendnumber, uint8_t *group_public_key, void *userdata) 422 * Function(Tox *tox, int32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
423 *
424 * data of length is what needs to be passed to join_groupchat().
423 */ 425 */
424void tox_callback_group_invite(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, void *), void *userdata); 426void tox_callback_group_invite(Tox *tox, void (*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *),
427 void *userdata);
425 428
426/* Set the callback for group messages. 429/* Set the callback for group messages.
427 * 430 *
@@ -479,24 +482,25 @@ int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t
479 */ 482 */
480int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber); 483int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber);
481 484
482/* Join a group (you need to have been invited first.) 485/* Join a group (you need to have been invited first.) using data of length obtained
486 * in the group invite callback.
483 * 487 *
484 * returns group number on success 488 * returns group number on success
485 * returns -1 on failure. 489 * returns -1 on failure.
486 */ 490 */
487int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *friend_group_public_key); 491int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length);
488 492
489/* send a group message 493/* send a group message
490 * return 0 on success 494 * return 0 on success
491 * return -1 on failure 495 * return -1 on failure
492 */ 496 */
493int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint32_t length); 497int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint16_t length);
494 498
495/* send a group action 499/* send a group action
496 * return 0 on success 500 * return 0 on success
497 * return -1 on failure 501 * return -1 on failure
498 */ 502 */
499int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint32_t length); 503int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint16_t length);
500 504
501/* Return the number of peers in the group chat on success. 505/* Return the number of peers in the group chat on success.
502 * return -1 on failure 506 * return -1 on failure