summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authorJfreegman <jfreegman@gmail.com>2016-09-17 17:32:25 -0400
committerJfreegman <jfreegman@gmail.com>2016-09-17 19:11:28 -0400
commit8e43ca834cc0a5b2f904ce2589154c2f17bd12ce (patch)
treee88701e5dfe6a623c7fe7f60ba2ddb304ffadc07 /toxcore
parentc0397a0a4614671679d409c428b47549a01fdf7f (diff)
Complete old groupchat conversion to new API
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/Makefile.inc1
-rw-r--r--toxcore/group.c176
-rw-r--r--toxcore/group.h67
-rw-r--r--toxcore/tox.c334
-rw-r--r--toxcore/tox.h419
-rw-r--r--toxcore/tox_group.c289
6 files changed, 801 insertions, 485 deletions
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc
index cf1dfa2c..ff413a88 100644
--- a/toxcore/Makefile.inc
+++ b/toxcore/Makefile.inc
@@ -27,7 +27,6 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \
27 ../toxcore/ping.c \ 27 ../toxcore/ping.c \
28 ../toxcore/tox.h \ 28 ../toxcore/tox.h \
29 ../toxcore/tox.c \ 29 ../toxcore/tox.c \
30 ../toxcore/tox_group.c \
31 ../toxcore/util.h \ 30 ../toxcore/util.h \
32 ../toxcore/util.c \ 31 ../toxcore/util.c \
33 ../toxcore/group.h \ 32 ../toxcore/group.h \
diff --git a/toxcore/group.c b/toxcore/group.c
index 55531ad3..b03dd6ed 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -452,9 +452,9 @@ static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, co
452 452
453 add_to_closest(g_c, groupnumber, real_pk, temp_pk); 453 add_to_closest(g_c, groupnumber, real_pk, temp_pk);
454 454
455 if (g_c->peer_namelistchange) { 455 if (g_c->group_namelistchange) {
456 g_c->peer_namelistchange(g_c->m, groupnumber, g->numpeers - 1, CHAT_CHANGE_PEER_ADD, 456 g_c->group_namelistchange(g_c->m, groupnumber, g->numpeers - 1, CHAT_CHANGE_PEER_ADD,
457 g_c->group_namelistchange_userdata); 457 g_c->group_namelistchange_userdata);
458 } 458 }
459 459
460 if (g->peer_on_join) { 460 if (g->peer_on_join) {
@@ -542,8 +542,8 @@ static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index)
542 g->group = temp; 542 g->group = temp;
543 } 543 }
544 544
545 if (g_c->peer_namelistchange) { 545 if (g_c->group_namelistchange) {
546 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, g_c->group_namelistchange_userdata);
547 } 547 }
548 548
549 if (g->peer_on_leave) { 549 if (g->peer_on_leave) {
@@ -578,8 +578,8 @@ static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint
578 578
579 g->group[peer_index].nick_len = nick_len; 579 g->group[peer_index].nick_len = nick_len;
580 580
581 if (g_c->peer_namelistchange) { 581 if (g_c->group_namelistchange) {
582 g_c->peer_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_NAME, g_c->group_namelistchange_userdata); 582 g_c->group_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_NAME, g_c->group_namelistchange_userdata);
583 } 583 }
584 584
585 return 0; 585 return 0;
@@ -748,7 +748,7 @@ static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_
748/* Delete a groupchat from the chats array. 748/* Delete a groupchat from the chats array.
749 * 749 *
750 * return 0 on success. 750 * return 0 on success.
751 * return -1 if failure. 751 * return -1 if groupnumber is invalid.
752 */ 752 */
753int del_groupchat(Group_Chats *g_c, int groupnumber) 753int del_groupchat(Group_Chats *g_c, int groupnumber)
754{ 754{
@@ -789,8 +789,9 @@ int del_groupchat(Group_Chats *g_c, int groupnumber)
789/* Copy the public key of peernumber who is in groupnumber to pk. 789/* Copy the public key of peernumber who is in groupnumber to pk.
790 * pk must be crypto_box_PUBLICKEYBYTES long. 790 * pk must be crypto_box_PUBLICKEYBYTES long.
791 * 791 *
792 * returns 0 on success 792 * return 0 on success
793 * returns -1 on failure 793 * return -1 if groupnumber is invalid.
794 * return -2 if peernumber is invalid.
794 */ 795 */
795int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk) 796int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk)
796{ 797{
@@ -801,13 +802,19 @@ int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, u
801 } 802 }
802 803
803 if ((uint32_t)peernumber >= g->numpeers) { 804 if ((uint32_t)peernumber >= g->numpeers) {
804 return -1; 805 return -2;
805 } 806 }
806 807
807 memcpy(pk, g->group[peernumber].real_pk, crypto_box_PUBLICKEYBYTES); 808 memcpy(pk, g->group[peernumber].real_pk, crypto_box_PUBLICKEYBYTES);
808 return 0; 809 return 0;
809} 810}
810 811
812/*
813 * Return the size of peernumber's name.
814 *
815 * return -1 if groupnumber is invalid.
816 * return -2 if peernumber is invalid.
817 */
811int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber) 818int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber)
812{ 819{
813 Group_c *g = get_group_c(g_c, groupnumber); 820 Group_c *g = get_group_c(g_c, groupnumber);
@@ -817,7 +824,7 @@ int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber)
817 } 824 }
818 825
819 if ((uint32_t)peernumber >= g->numpeers) { 826 if ((uint32_t)peernumber >= g->numpeers) {
820 return -1; 827 return -2;
821 } 828 }
822 829
823 if (g->group[peernumber].nick_len == 0) { 830 if (g->group[peernumber].nick_len == 0) {
@@ -831,7 +838,8 @@ int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber)
831 * name must be at least MAX_NAME_LENGTH long. 838 * name must be at least MAX_NAME_LENGTH long.
832 * 839 *
833 * return length of name if success 840 * return length of name if success
834 * return -1 if failure 841 * return -1 if groupnumber is invalid.
842 * return -2 if peernumber is invalid.
835 */ 843 */
836int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name) 844int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name)
837{ 845{
@@ -842,7 +850,7 @@ int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint
842 } 850 }
843 851
844 if ((uint32_t)peernumber >= g->numpeers) { 852 if ((uint32_t)peernumber >= g->numpeers) {
845 return -1; 853 return -2;
846 } 854 }
847 855
848 if (g->group[peernumber].nick_len == 0) { 856 if (g->group[peernumber].nick_len == 0) {
@@ -883,7 +891,7 @@ int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAM
883} 891}
884 892
885/* Return the number of peers in the group chat on success. 893/* Return the number of peers in the group chat on success.
886 * return -1 on failure 894 * return -1 if groupnumber is invalid.
887 */ 895 */
888int group_number_peers(const Group_Chats *g_c, int groupnumber) 896int group_number_peers(const Group_Chats *g_c, int groupnumber)
889{ 897{
@@ -897,22 +905,25 @@ int group_number_peers(const Group_Chats *g_c, int groupnumber)
897} 905}
898 906
899/* return 1 if the peernumber corresponds to ours. 907/* return 1 if the peernumber corresponds to ours.
900 * return 0 on failure. 908 * return 0 if the peernumber is not ours.
909 * return -1 if groupnumber is invalid.
910 * return -2 if peernumber is invalid.
911 * return -3 if we are not connected to the group chat.
901 */ 912 */
902unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber) 913int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber)
903{ 914{
904 Group_c *g = get_group_c(g_c, groupnumber); 915 Group_c *g = get_group_c(g_c, groupnumber);
905 916
906 if (!g) { 917 if (!g) {
907 return 0; 918 return -1;
908 } 919 }
909 920
910 if (g->status != GROUPCHAT_STATUS_CONNECTED) { 921 if ((uint32_t)peernumber >= g->numpeers) {
911 return 0; 922 return -2;
912 } 923 }
913 924
914 if ((uint32_t)peernumber >= g->numpeers) { 925 if (g->status != GROUPCHAT_STATUS_CONNECTED) {
915 return 0; 926 return -3;
916 } 927 }
917 928
918 return g->peer_number == g->group[peernumber].peer_number; 929 return g->peer_number == g->group[peernumber].peer_number;
@@ -982,9 +993,11 @@ static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendco
982#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH) 993#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH)
983#define INVITE_RESPONSE_ID 1 994#define INVITE_RESPONSE_ID 1
984 995
985/* invite friendnumber to groupnumber 996/* invite friendnumber to groupnumber.
986 * return 0 on success 997 *
987 * return -1 on failure 998 * return 0 on success.
999 * return -1 if groupnumber is invalid.
1000 * return -2 if invite packet failed to send.
988 */ 1001 */
989int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber) 1002int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber)
990{ 1003{
@@ -1005,7 +1018,7 @@ int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber)
1005 } 1018 }
1006 1019
1007 wipe_group_chat(g_c, groupnumber); 1020 wipe_group_chat(g_c, groupnumber);
1008 return -1; 1021 return -2;
1009} 1022}
1010 1023
1011static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num); 1024static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
@@ -1014,8 +1027,13 @@ static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t
1014 * 1027 *
1015 * expected_type is the groupchat type we expect the chat we are joining is. 1028 * expected_type is the groupchat type we expect the chat we are joining is.
1016 * 1029 *
1017 * returns group number on success 1030 * return group number on success.
1018 * returns -1 on failure. 1031 * return -1 if data length is invalid.
1032 * return -2 if group is not the expected type.
1033 * return -3 if friendnumber is invalid.
1034 * return -4 if client is already in this group.
1035 * return -5 if group instance failed to initialize.
1036 * return -6 if join packet fails to send.
1019 */ 1037 */
1020int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length) 1038int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length)
1021{ 1039{
@@ -1024,23 +1042,23 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type
1024 } 1042 }
1025 1043
1026 if (data[sizeof(uint16_t)] != expected_type) { 1044 if (data[sizeof(uint16_t)] != expected_type) {
1027 return -1; 1045 return -2;
1028 } 1046 }
1029 1047
1030 int friendcon_id = getfriendcon_id(g_c->m, friendnumber); 1048 int friendcon_id = getfriendcon_id(g_c->m, friendnumber);
1031 1049
1032 if (friendcon_id == -1) { 1050 if (friendcon_id == -1) {
1033 return -1; 1051 return -3;
1034 } 1052 }
1035 1053
1036 if (get_group_num(g_c, data + sizeof(uint16_t)) != -1) { 1054 if (get_group_num(g_c, data + sizeof(uint16_t)) != -1) {
1037 return -1; 1055 return -4;
1038 } 1056 }
1039 1057
1040 int groupnumber = create_group_chat(g_c); 1058 int groupnumber = create_group_chat(g_c);
1041 1059
1042 if (groupnumber == -1) { 1060 if (groupnumber == -1) {
1043 return -1; 1061 return -5;
1044 } 1062 }
1045 1063
1046 Group_c *g = &g_c->chats[groupnumber]; 1064 Group_c *g = &g_c->chats[groupnumber];
@@ -1073,7 +1091,7 @@ int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type
1073 } 1091 }
1074 1092
1075 g->status = GROUPCHAT_STATUS_NONE; 1093 g->status = GROUPCHAT_STATUS_NONE;
1076 return -1; 1094 return -6;
1077} 1095}
1078 1096
1079/* Set the callback for group invites. 1097/* Set the callback for group invites.
@@ -1094,8 +1112,7 @@ void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, ui
1094 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 1112 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
1095 */ 1113 */
1096void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *, 1114void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
1097 size_t, 1115 size_t, void *), void *userdata)
1098 void *), void *userdata)
1099{ 1116{
1100 g_c->message_callback = function; 1117 g_c->message_callback = function;
1101 g_c->message_callback_userdata = userdata; 1118 g_c->message_callback_userdata = userdata;
@@ -1121,7 +1138,7 @@ void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*fu
1121void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *), 1138void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *),
1122 void *userdata) 1139 void *userdata)
1123{ 1140{
1124 g_c->peer_namelistchange = function; 1141 g_c->group_namelistchange = function;
1125 g_c->group_namelistchange_userdata = userdata; 1142 g_c->group_namelistchange_userdata = userdata;
1126} 1143}
1127 1144
@@ -1131,8 +1148,7 @@ void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenge
1131 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group) 1148 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
1132 */ 1149 */
1133void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *, 1150void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
1134 size_t, 1151 size_t, void *), void *userdata)
1135 void *), void *userdata)
1136{ 1152{
1137 g_c->title_callback = function; 1153 g_c->title_callback = function;
1138 g_c->title_callback_userdata = userdata; 1154 g_c->title_callback_userdata = userdata;
@@ -1195,13 +1211,13 @@ int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function
1195 return 0; 1211 return 0;
1196} 1212}
1197 1213
1198static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, 1214static int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
1199 uint16_t len); 1215 uint16_t len);
1200 1216
1201#define GROUP_MESSAGE_PING_ID 0 1217#define GROUP_MESSAGE_PING_ID 0
1202static int group_ping_send(const Group_Chats *g_c, int groupnumber) 1218static int group_ping_send(const Group_Chats *g_c, int groupnumber)
1203{ 1219{
1204 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, 0, 0)) { 1220 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, 0, 0) > 0) {
1205 return 0; 1221 return 0;
1206 } 1222 }
1207 1223
@@ -1224,7 +1240,7 @@ static int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t
1224 memcpy(packet + sizeof(uint16_t), real_pk, crypto_box_PUBLICKEYBYTES); 1240 memcpy(packet + sizeof(uint16_t), real_pk, crypto_box_PUBLICKEYBYTES);
1225 memcpy(packet + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, temp_pk, crypto_box_PUBLICKEYBYTES); 1241 memcpy(packet + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES, temp_pk, crypto_box_PUBLICKEYBYTES);
1226 1242
1227 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet))) { 1243 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet)) > 0) {
1228 return 0; 1244 return 0;
1229 } 1245 }
1230 1246
@@ -1245,7 +1261,7 @@ static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_
1245 peer_num = htons(peer_num); 1261 peer_num = htons(peer_num);
1246 memcpy(packet, &peer_num, sizeof(uint16_t)); 1262 memcpy(packet, &peer_num, sizeof(uint16_t));
1247 1263
1248 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet))) { 1264 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) {
1249 return 0; 1265 return 0;
1250 } 1266 }
1251 1267
@@ -1264,7 +1280,7 @@ static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_
1264 return -1; 1280 return -1;
1265 } 1281 }
1266 1282
1267 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NAME_ID, nick, nick_len)) { 1283 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NAME_ID, nick, nick_len) > 0) {
1268 return 0; 1284 return 0;
1269 } 1285 }
1270 1286
@@ -1275,20 +1291,22 @@ static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_
1275 1291
1276/* set the group's title, limited to MAX_NAME_LENGTH 1292/* set the group's title, limited to MAX_NAME_LENGTH
1277 * return 0 on success 1293 * return 0 on success
1278 * return -1 on failure 1294 * return -1 if groupnumber is invalid.
1295 * return -2 if title is too long or empty.
1296 * return -3 if packet fails to send.
1279 */ 1297 */
1280int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len) 1298int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len)
1281{ 1299{
1282 if (title_len > MAX_NAME_LENGTH || title_len == 0) {
1283 return -1;
1284 }
1285
1286 Group_c *g = get_group_c(g_c, groupnumber); 1300 Group_c *g = get_group_c(g_c, groupnumber);
1287 1301
1288 if (!g) { 1302 if (!g) {
1289 return -1; 1303 return -1;
1290 } 1304 }
1291 1305
1306 if (title_len > MAX_NAME_LENGTH || title_len == 0) {
1307 return -2;
1308 }
1309
1292 /* same as already set? */ 1310 /* same as already set? */
1293 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) { 1311 if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
1294 return 0; 1312 return 0;
@@ -1301,13 +1319,17 @@ int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *tit
1301 return 0; 1319 return 0;
1302 } 1320 }
1303 1321
1304 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len)) { 1322 if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len) > 0) {
1305 return 0; 1323 return 0;
1306 } 1324 }
1307 1325
1308 return -1; 1326 return -3;
1309} 1327}
1310 1328
1329/* return the group's title size.
1330 * return -1 of groupnumber is invalid.
1331 * return -2 if title is too long or empty.
1332 */
1311int group_title_get_size(const Group_Chats *g_c, int groupnumber) 1333int group_title_get_size(const Group_Chats *g_c, int groupnumber)
1312{ 1334{
1313 Group_c *g = get_group_c(g_c, groupnumber); 1335 Group_c *g = get_group_c(g_c, groupnumber);
@@ -1317,17 +1339,18 @@ int group_title_get_size(const Group_Chats *g_c, int groupnumber)
1317 } 1339 }
1318 1340
1319 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) { 1341 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
1320 return -1; 1342 return -2;
1321 } 1343 }
1322 1344
1323 return g->title_len; 1345 return g->title_len;
1324} 1346}
1325 1347
1326/* Get group title from groupnumber and put it in title. 1348/* Get group title from groupnumber and put it in title.
1327 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes. 1349 * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
1328 * 1350 *
1329 * return length of copied title if success. 1351 * return length of copied title if success.
1330 * return -1 if failure. 1352 * return -1 if groupnumber is invalid.
1353 * return -2 if title is too long or empty.
1331 */ 1354 */
1332int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title) 1355int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title)
1333{ 1356{
@@ -1338,7 +1361,7 @@ int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title)
1338 } 1361 }
1339 1362
1340 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) { 1363 if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
1341 return -1; 1364 return -2;
1342 } 1365 }
1343 1366
1344 memcpy(title, g->title, g->title_len); 1367 memcpy(title, g->title, g->title_len);
@@ -1851,23 +1874,26 @@ static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber
1851/* Send data of len with message_id to groupnumber. 1874/* Send data of len with message_id to groupnumber.
1852 * 1875 *
1853 * return number of peers it was sent to on success. 1876 * return number of peers it was sent to on success.
1854 * return 0 on failure. 1877 * return -1 if groupnumber is invalid.
1878 * return -2 if message is too long.
1879 * return -3 if we are not connected to the group.
1880 * reutrn -4 if message failed to send.
1855 */ 1881 */
1856static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, 1882static int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
1857 uint16_t len) 1883 uint16_t len)
1858{ 1884{
1859 if (len > MAX_GROUP_MESSAGE_DATA_LEN) {
1860 return 0;
1861 }
1862
1863 Group_c *g = get_group_c(g_c, groupnumber); 1885 Group_c *g = get_group_c(g_c, groupnumber);
1864 1886
1865 if (!g) { 1887 if (!g) {
1866 return 0; 1888 return -1;
1889 }
1890
1891 if (len > MAX_GROUP_MESSAGE_DATA_LEN) {
1892 return -2;
1867 } 1893 }
1868 1894
1869 if (g->status != GROUPCHAT_STATUS_CONNECTED) { 1895 if (g->status != GROUPCHAT_STATUS_CONNECTED) {
1870 return 0; 1896 return -3;
1871 } 1897 }
1872 1898
1873 uint8_t packet[sizeof(uint16_t) + sizeof(uint32_t) + 1 + len]; 1899 uint8_t packet[sizeof(uint16_t) + sizeof(uint32_t) + 1 + len];
@@ -1889,33 +1915,39 @@ static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber,
1889 memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len); 1915 memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len);
1890 } 1916 }
1891 1917
1892 return send_message_all_close(g_c, groupnumber, packet, sizeof(packet), -1); 1918 unsigned int ret = send_message_all_close(g_c, groupnumber, packet, sizeof(packet), -1);
1919
1920 return (ret == 0) ? -4 : ret;
1893} 1921}
1894 1922
1895/* send a group message 1923/* send a group message
1896 * return 0 on success 1924 * return 0 on success
1897 * return -1 on failure 1925 * see: send_message_group() for error codes.
1898 */ 1926 */
1899int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length) 1927int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length)
1900{ 1928{
1901 if (send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length)) { 1929 int ret = send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length);
1930
1931 if (ret > 0) {
1902 return 0; 1932 return 0;
1903 } 1933 }
1904 1934
1905 return -1; 1935 return ret;
1906} 1936}
1907 1937
1908/* send a group action 1938/* send a group action
1909 * return 0 on success 1939 * return 0 on success
1910 * return -1 on failure 1940 * see: send_message_group() for error codes.
1911 */ 1941 */
1912int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length) 1942int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length)
1913{ 1943{
1914 if (send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length)) { 1944 int ret = send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length);
1945
1946 if (ret > 0) {
1915 return 0; 1947 return 0;
1916 } 1948 }
1917 1949
1918 return -1; 1950 return ret;
1919} 1951}
1920 1952
1921/* High level function to send custom lossy packets. 1953/* High level function to send custom lossy packets.
diff --git a/toxcore/group.h b/toxcore/group.h
index 6d278dde..fc7629f3 100644
--- a/toxcore/group.h
+++ b/toxcore/group.h
@@ -120,7 +120,7 @@ typedef struct {
120 void *invite_callback_userdata; 120 void *invite_callback_userdata;
121 void (*message_callback)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *, size_t, void *); 121 void (*message_callback)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *, size_t, void *);
122 void *message_callback_userdata; 122 void *message_callback_userdata;
123 void (*peer_namelistchange)(Messenger *m, int, int, uint8_t, void *); 123 void (*group_namelistchange)(Messenger *m, int, int, uint8_t, void *);
124 void *group_namelistchange_userdata; 124 void *group_namelistchange_userdata;
125 void (*title_callback)(Messenger *m, uint32_t, uint32_t, const uint8_t *, size_t, void *); 125 void (*title_callback)(Messenger *m, uint32_t, uint32_t, const uint8_t *, size_t, void *);
126 void *title_callback_userdata; 126 void *title_callback_userdata;
@@ -144,8 +144,7 @@ void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, ui
144 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 144 * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
145 */ 145 */
146void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *, 146void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
147 size_t, 147 size_t, void *), void *userdata);
148 void *), void *userdata);
149 148
150 149
151/* Set callback function for title changes. 150/* Set callback function for title changes.
@@ -154,8 +153,7 @@ void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, u
154 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group) 153 * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
155 */ 154 */
156void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *, 155void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
157 size_t, 156 size_t, void *), void *userdata);
158 void *), void *userdata);
159 157
160/* Set callback function for peer name list changes. 158/* Set callback function for peer name list changes.
161 * 159 *
@@ -182,31 +180,41 @@ int add_groupchat(Group_Chats *g_c, uint8_t type);
182/* Delete a groupchat from the chats array. 180/* Delete a groupchat from the chats array.
183 * 181 *
184 * return 0 on success. 182 * return 0 on success.
185 * return -1 if failure. 183 * return -1 if groupnumber is invalid.
186 */ 184 */
187int del_groupchat(Group_Chats *g_c, int groupnumber); 185int del_groupchat(Group_Chats *g_c, int groupnumber);
188 186
189/* Copy the public key of peernumber who is in groupnumber to pk. 187/* Copy the public key of peernumber who is in groupnumber to pk.
190 * pk must be crypto_box_PUBLICKEYBYTES long. 188 * pk must be crypto_box_PUBLICKEYBYTES long.
191 * 189 *
192 * returns 0 on success 190 * return 0 on success
193 * returns -1 on failure 191 * return -1 if groupnumber is invalid.
192 * return -2 if peernumber is invalid.
194 */ 193 */
195int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk); 194int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk);
196 195
196/*
197 * Return the size of peernumber's name.
198 *
199 * return -1 if groupnumber is invalid.
200 * return -2 if peernumber is invalid.
201 */
197int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber); 202int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber);
198 203
199/* Copy the name of peernumber who is in groupnumber to name. 204/* Copy the name of peernumber who is in groupnumber to name.
200 * name must be at least MAX_NAME_LENGTH long. 205 * name must be at least MAX_NAME_LENGTH long.
201 * 206 *
202 * return length of name if success 207 * return length of name if success
203 * return -1 if failure 208 * return -1 if groupnumber is invalid.
209 * return -2 if peernumber is invalid.
204 */ 210 */
205int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name); 211int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name);
206 212
207/* invite friendnumber to groupnumber 213/* invite friendnumber to groupnumber
208 * return 0 on success 214 *
209 * return -1 on failure 215 * return 0 on success.
216 * return -1 if groupnumber is invalid.
217 * return -2 if invite packet failed to send.
210 */ 218 */
211int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber); 219int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber);
212 220
@@ -214,49 +222,64 @@ int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber);
214 * 222 *
215 * expected_type is the groupchat type we expect the chat we are joining is. 223 * expected_type is the groupchat type we expect the chat we are joining is.
216 * 224 *
217 * returns group number on success 225 * return group number on success.
218 * returns -1 on failure. 226 * return -1 if data length is invalid.
227 * return -2 if group is not the expected type.
228 * return -3 if friendnumber is invalid.
229 * return -4 if client is already in this group.
230 * return -5 if group instance failed to initialize.
231 * return -6 if join packet fails to send.
219 */ 232 */
220int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length); 233int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length);
221 234
222/* send a group message 235/* send a group message
223 * return 0 on success 236 * return 0 on success
224 * return -1 on failure 237 * see: send_message_group() for error codes.
225 */ 238 */
226int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length); 239int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length);
227 240
228/* send a group action 241/* send a group action
229 * return 0 on success 242 * return 0 on success
230 * return -1 on failure 243 * see: send_message_group() for error codes.
231 */ 244 */
232int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length); 245int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length);
233 246
234/* set the group's title, limited to MAX_NAME_LENGTH 247/* set the group's title, limited to MAX_NAME_LENGTH
235 * return 0 on success 248 * return 0 on success
236 * return -1 on failure 249 * return -1 if groupnumber is invalid.
250 * return -2 if title is too long or empty.
251 * return -3 if packet fails to send.
237 */ 252 */
238int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len); 253int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len);
239 254
240 255
256/* return the group's title size.
257 * return -1 of groupnumber is invalid.
258 * return -2 if title is too long or empty.
259 */
241int group_title_get_size(const Group_Chats *g_c, int groupnumber); 260int group_title_get_size(const Group_Chats *g_c, int groupnumber);
242 261
243/* Get group title from groupnumber and put it in title. 262/* Get group title from groupnumber and put it in title.
244 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes. 263 * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
245 * 264 *
246 * return length of copied title if success. 265 * return length of copied title if success.
247 * return -1 if failure. 266 * return -1 if groupnumber is invalid.
267 * return -2 if title is too long or empty.
248 */ 268 */
249int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title); 269int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title);
250 270
251/* Return the number of peers in the group chat on success. 271/* Return the number of peers in the group chat on success.
252 * return -1 on failure 272 * return -1 if groupnumber is invalid.
253 */ 273 */
254int group_number_peers(const Group_Chats *g_c, int groupnumber); 274int group_number_peers(const Group_Chats *g_c, int groupnumber);
255 275
256/* return 1 if the peernumber corresponds to ours. 276/* return 1 if the peernumber corresponds to ours.
257 * return 0 on failure. 277 * return 0 if the peernumber is not ours.
278 * return -1 if groupnumber is invalid.
279 * return -2 if peernumber is invalid.
280 * return -3 if we are not connected to the group chat.
258 */ 281 */
259unsigned int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber); 282int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber);
260 283
261/* List all the peers in the group chat. 284/* List all the peers in the group chat.
262 * 285 *
diff --git a/toxcore/tox.c b/toxcore/tox.c
index b9bab973..fa53f35e 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -1216,6 +1216,340 @@ void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback)
1216 callback_file_data(m, callback); 1216 callback_file_data(m, callback);
1217} 1217}
1218 1218
1219void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback, void *user_data)
1220{
1221 Messenger *m = tox;
1222 g_callback_group_invite(m->group_chat_object, (void (*)(Messenger * m, uint32_t, int, const uint8_t *, size_t,
1223 void *))callback, user_data);
1224}
1225
1226void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback, void *user_data)
1227{
1228 Messenger *m = tox;
1229 g_callback_group_message(m->group_chat_object, (void (*)(Messenger * m, uint32_t, uint32_t, int, const uint8_t *,
1230 size_t, void *))callback, user_data);
1231}
1232
1233void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback, void *user_data)
1234{
1235 Messenger *m = tox;
1236 g_callback_group_title(m->group_chat_object, callback, user_data);
1237}
1238
1239void tox_callback_conference_namelist_change(Tox *tox, tox_conference_namelist_change_cb *callback, void *user_data)
1240{
1241 Messenger *m = tox;
1242 g_callback_group_namelistchange(m->group_chat_object, (void (*)(struct Messenger *, int, int, uint8_t,
1243 void *))callback, user_data);
1244}
1245
1246uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error)
1247{
1248 Messenger *m = tox;
1249 int ret = add_groupchat(m->group_chat_object, GROUPCHAT_TYPE_TEXT);
1250
1251 if (ret == -1) {
1252 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_INIT);
1253 return UINT32_MAX;
1254 }
1255
1256 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_OK);
1257 return ret;
1258}
1259
1260bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error)
1261{
1262 Messenger *m = tox;
1263 int ret = del_groupchat(m->group_chat_object, conference_number);
1264
1265 if (ret == -1) {
1266 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND);
1267 return false;
1268 }
1269
1270 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_OK);
1271 return true;
1272}
1273
1274uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_PEER_QUERY *error)
1275{
1276 const Messenger *m = tox;
1277 int ret = group_number_peers(m->group_chat_object, conference_number);
1278
1279 if (ret == -1) {
1280 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1281 return UINT32_MAX;
1282 }
1283
1284 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1285 return ret;
1286}
1287
1288size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1289 TOX_ERR_CONFERENCE_PEER_QUERY *error)
1290{
1291 const Messenger *m = tox;
1292 int ret = group_peername_size(m->group_chat_object, conference_number, peer_number);
1293
1294 switch (ret) {
1295 case -1:
1296 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1297 return -1;
1298
1299 case -2:
1300 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
1301 return -1;
1302 }
1303
1304 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1305 return ret;
1306}
1307
1308bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
1309 TOX_ERR_CONFERENCE_PEER_QUERY *error)
1310{
1311 const Messenger *m = tox;
1312 int ret = group_peername(m->group_chat_object, conference_number, peer_number, name);
1313
1314 switch (ret) {
1315 case -1:
1316 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1317 return false;
1318
1319 case -2:
1320 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
1321 return false;
1322 }
1323
1324 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1325 return true;
1326}
1327
1328bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1329 uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error)
1330{
1331 const Messenger *m = tox;
1332 int ret = group_peer_pubkey(m->group_chat_object, conference_number, peer_number, public_key);
1333
1334 switch (ret) {
1335 case -1:
1336 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1337 return false;
1338
1339 case -2:
1340 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
1341 return false;
1342 }
1343
1344 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1345 return true;
1346}
1347
1348bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1349 TOX_ERR_CONFERENCE_PEER_QUERY *error)
1350{
1351 const Messenger *m = tox;
1352 int ret = group_peernumber_is_ours(m->group_chat_object, conference_number, peer_number);
1353
1354 switch (ret) {
1355 case -1:
1356 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
1357 return false;
1358
1359 case -2:
1360 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
1361 return false;
1362
1363 case -3:
1364 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION);
1365 return false;
1366 }
1367
1368 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
1369 return ret;
1370}
1371
1372bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
1373 TOX_ERR_CONFERENCE_INVITE *error)
1374{
1375 Messenger *m = tox;
1376 int ret = invite_friend(m->group_chat_object, friend_number, conference_number);
1377
1378 switch (ret) {
1379 case -1:
1380 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND);
1381 return false;
1382
1383 case -2:
1384 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_FAIL_SEND);
1385 return false;
1386 }
1387
1388 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_OK);
1389 return true;
1390}
1391
1392uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
1393 TOX_ERR_CONFERENCE_JOIN *error)
1394{
1395 Messenger *m = tox;
1396 int ret = join_groupchat(m->group_chat_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length);
1397
1398 switch (ret) {
1399 case -1:
1400 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH);
1401 return UINT32_MAX;
1402
1403 case -2:
1404 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE);
1405 return UINT32_MAX;
1406
1407 case -3:
1408 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND);
1409 return UINT32_MAX;
1410
1411 case -4:
1412 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_DUPLICATE);
1413 return UINT32_MAX;
1414
1415 case -5:
1416 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INIT_FAIL);
1417 return UINT32_MAX;
1418
1419 case -6:
1420 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FAIL_SEND);
1421 return UINT32_MAX;
1422 }
1423
1424 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_OK);
1425 return ret;
1426}
1427
1428bool tox_conference_send_message(Tox *tox, uint32_t conference_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
1429 size_t length, TOX_ERR_CONFERENCE_SEND_MESSAGE *error)
1430{
1431 Messenger *m = tox;
1432 int ret = 0;
1433
1434 if (type == TOX_MESSAGE_TYPE_NORMAL) {
1435 ret = group_message_send(m->group_chat_object, conference_number, message, length);
1436 } else {
1437 ret = group_action_send(m->group_chat_object, conference_number, message, length);
1438 }
1439
1440 switch (ret) {
1441 case -1:
1442 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND);
1443 return false;
1444
1445 case -2:
1446 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG);
1447 return false;
1448
1449 case -3:
1450 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION);
1451 return false;
1452
1453 case -4:
1454 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND);
1455 return false;
1456 }
1457
1458 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_OK);
1459 return true;
1460}
1461
1462size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_TITLE *error)
1463{
1464 const Messenger *m = tox;
1465 int ret = group_title_get_size(m->group_chat_object, conference_number);
1466
1467 switch (ret) {
1468 case -1:
1469 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
1470 return -1;
1471
1472 case -2:
1473 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
1474 return -1;
1475 }
1476
1477 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
1478 return ret;
1479}
1480
1481bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
1482 TOX_ERR_CONFERENCE_TITLE *error)
1483{
1484 const Messenger *m = tox;
1485 int ret = group_title_get(m->group_chat_object, conference_number, title);
1486
1487 switch (ret) {
1488 case -1:
1489 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
1490 return false;
1491
1492 case -2:
1493 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
1494 return false;
1495 }
1496
1497 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
1498 return true;
1499}
1500
1501bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
1502 TOX_ERR_CONFERENCE_TITLE *error)
1503{
1504 Messenger *m = tox;
1505 int ret = group_title_send(m->group_chat_object, conference_number, title, length);
1506
1507 switch (ret) {
1508 case -1:
1509 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
1510 return false;
1511
1512 case -2:
1513 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
1514 return false;
1515
1516 case -3:
1517 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_FAIL_SEND);
1518 return false;
1519 }
1520
1521 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
1522 return true;
1523}
1524
1525size_t tox_conference_get_chatlist_size(const Tox *tox)
1526{
1527 const Messenger *m = tox;
1528 return count_chatlist(m->group_chat_object);
1529}
1530
1531void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist)
1532{
1533 const Messenger *m = tox;
1534 size_t list_size = tox_conference_get_chatlist_size(tox);
1535 copy_chatlist(m->group_chat_object, chatlist, list_size);
1536}
1537
1538TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_number,
1539 TOX_ERR_CONFERENCE_GET_TYPE *error)
1540{
1541 const Messenger *m = tox;
1542 int ret = group_get_type(m->group_chat_object, conference_number);
1543
1544 if (ret == -1) {
1545 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND);
1546 return -1;
1547 }
1548
1549 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_OK);
1550 return ret;
1551}
1552
1219static void set_custom_packet_error(int ret, TOX_ERR_FRIEND_CUSTOM_PACKET *error) 1553static void set_custom_packet_error(int ret, TOX_ERR_FRIEND_CUSTOM_PACKET *error)
1220{ 1554{
1221 switch (ret) { 1555 switch (ret) {
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 7b04bb14..268ae779 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -344,7 +344,7 @@ typedef enum TOX_USER_STATUS {
344 344
345 345
346/** 346/**
347 * Represents message types for tox_friend_send_message and group chat 347 * Represents message types for tox_friend_send_message and conference
348 * messages. 348 * messages.
349 */ 349 */
350typedef enum TOX_MESSAGE_TYPE { 350typedef enum TOX_MESSAGE_TYPE {
@@ -2268,27 +2268,12 @@ void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback);
2268 2268
2269/******************************************************************************* 2269/*******************************************************************************
2270 * 2270 *
2271 * :: Group chat management 2271 * :: Conference management
2272 * 2272 *
2273 ******************************************************************************/ 2273 ******************************************************************************/
2274 2274
2275 2275
2276 2276
2277typedef enum TOX_ERR_CONFERENCE {
2278
2279 /**
2280 * The function returned successfully.
2281 */
2282 TOX_ERR_CONFERENCE_OK,
2283
2284 /**
2285 * Some error occurred.
2286 */
2287 TOX_ERR_CONFERENCE_FAILURE,
2288
2289} TOX_ERR_CONFERENCE;
2290
2291
2292/** 2277/**
2293 * Conference types for the conference_invite event. 2278 * Conference types for the conference_invite event.
2294 */ 2279 */
@@ -2329,188 +2314,420 @@ typedef void tox_conference_invite_cb(Tox *tox, uint32_t friend_number, TOX_CONF
2329void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback, void *user_data); 2314void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback, void *user_data);
2330 2315
2331/** 2316/**
2332 * TODO 2317 * @param conference_number The conference number of the conference the message is intended for.
2318 * @param peer_number The ID of the peer who sent the message.
2319 * @param type The type of message (normal, action, ...).
2320 * @param message The message data.
2321 * @param length The length of the message.
2333 */ 2322 */
2334typedef void tox_conference_message_cb(Tox *tox, uint32_t group_number, uint32_t peer_number, TOX_MESSAGE_TYPE type, 2323typedef void tox_conference_message_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number,
2335 const uint8_t *message, size_t length, void *user_data); 2324 TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *user_data);
2336 2325
2337 2326
2338/** 2327/**
2339 * Set the callback for the `conference_message` event. Pass NULL to unset. 2328 * Set the callback for the `conference_message` event. Pass NULL to unset.
2340 * 2329 *
2341 * Set the callback for group messages. 2330 * This event is triggered when the client receives a conference message.
2342 */ 2331 */
2343void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback, void *user_data); 2332void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback, void *user_data);
2344 2333
2345/** 2334/**
2346 * TODO 2335 * @param conference_number The conference number of the conference the title change is intended for.
2336 * @param peer_number The ID of the peer who changed the title.
2337 * @param title The title data.
2338 * @param length The title length.
2347 */ 2339 */
2348typedef void tox_conference_title_cb(Tox *tox, uint32_t group_number, uint32_t peer_number, const uint8_t *title, 2340typedef void tox_conference_title_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number, const uint8_t *title,
2349 size_t length, void *user_data); 2341 size_t length, void *user_data);
2350 2342
2351 2343
2352/** 2344/**
2353 * Set the callback for the `conference_title` event. Pass NULL to unset. 2345 * Set the callback for the `conference_title` event. Pass NULL to unset.
2354 * 2346 *
2355 * Set callback function for title changes. 2347 * This event is triggered when a peer changes the conference title.
2356 * 2348 *
2357 * if peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the group) 2349 * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference).
2358 */ 2350 */
2359void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback, void *user_data); 2351void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback, void *user_data);
2360 2352
2361typedef enum TOX_CONFERENCE_CHANGE { 2353/**
2354 * Peer list state change types.
2355 */
2356typedef enum TOX_CONFERENCE_STATE_CHANGE {
2362 2357
2363 /** 2358 /**
2364 * TODO: Generate doc 2359 * A peer has joined the conference.
2365 */ 2360 */
2366 TOX_CONFERENCE_CHANGE_PEER_ADD, 2361 TOX_CONFERENCE_STATE_CHANGE_PEER_JOIN,
2367 2362
2368 /** 2363 /**
2369 * TODO: Generate doc 2364 * A peer has exited the conference.
2370 */ 2365 */
2371 TOX_CONFERENCE_CHANGE_PEER_DEL, 2366 TOX_CONFERENCE_STATE_CHANGE_PEER_EXIT,
2372 2367
2373 /** 2368 /**
2374 * TODO: Generate doc 2369 * A peer has changed their name.
2375 */ 2370 */
2376 TOX_CONFERENCE_CHANGE_PEER_NAME, 2371 TOX_CONFERENCE_STATE_CHANGE_PEER_NAME_CHANGE,
2377 2372
2378} TOX_CONFERENCE_CHANGE; 2373} TOX_CONFERENCE_STATE_CHANGE;
2379 2374
2380 2375
2381/** 2376/**
2382 * TODO 2377 * @param conference_number The conference number of the conference the title change is intended for.
2378 * @param peer_number The ID of the peer who changed the title.
2379 * @param change The type of change (one of TOX_CONFERENCE_STATE_CHANGE).
2383 */ 2380 */
2384typedef void tox_conference_namelist_change_cb(Tox *tox, uint32_t group_number, uint32_t peer_number, 2381typedef void tox_conference_namelist_change_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number,
2385 TOX_CONFERENCE_CHANGE change, void *user_data); 2382 TOX_CONFERENCE_STATE_CHANGE change, void *user_data);
2386 2383
2387 2384
2388/** 2385/**
2389 * Set the callback for the `conference_namelist_change` event. Pass NULL to unset. 2386 * Set the callback for the `conference_namelist_change` event. Pass NULL to unset.
2390 * 2387 *
2391 * Set callback function for peer name list changes. 2388 * This event is triggered when the peer list changes (name change, peer join, peer exit).
2392 *
2393 * It gets called every time the name list changes(new peer/name, deleted peer)
2394 */ 2389 */
2395void tox_callback_conference_namelist_change(Tox *tox, tox_conference_namelist_change_cb *callback, void *user_data); 2390void tox_callback_conference_namelist_change(Tox *tox, tox_conference_namelist_change_cb *callback, void *user_data);
2396 2391
2392typedef enum TOX_ERR_CONFERENCE_NEW {
2393
2394 /**
2395 * The function returned successfully.
2396 */
2397 TOX_ERR_CONFERENCE_NEW_OK,
2398
2399 /**
2400 * The conference instance failed to initialize.
2401 */
2402 TOX_ERR_CONFERENCE_NEW_INIT,
2403
2404} TOX_ERR_CONFERENCE_NEW;
2405
2406
2397/** 2407/**
2398 * Creates a new groupchat. 2408 * Creates a new conference.
2409 *
2410 * This function creates a new text conference.
2399 * 2411 *
2400 * @return the group number. 2412 * @return conference number on success, or UINT32_MAX on failure.
2401 */ 2413 */
2402uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE *error); 2414uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error);
2415
2416typedef enum TOX_ERR_CONFERENCE_DELETE {
2417
2418 /**
2419 * The function returned successfully.
2420 */
2421 TOX_ERR_CONFERENCE_DELETE_OK,
2422
2423 /**
2424 * The conference number passed did not designate a valid conference.
2425 */
2426 TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND,
2427
2428} TOX_ERR_CONFERENCE_DELETE;
2429
2403 2430
2404/** 2431/**
2405 * Delete a groupchat. 2432 * This function deletes a conference.
2433 *
2434 * @param conference_number The conference number of the conference to be deleted.
2406 * 2435 *
2407 * @return true on success. 2436 * @return true on success.
2408 */ 2437 */
2409bool tox_conference_delete(Tox *tox, uint32_t group_number, TOX_ERR_CONFERENCE *error); 2438bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error);
2410 2439
2411/** 2440/**
2412 * Return the number of peers in the group chat. 2441 * Error codes for peer info queries.
2413 */ 2442 */
2414uint32_t tox_conference_peer_count(const Tox *tox, uint32_t group_number, TOX_ERR_CONFERENCE *error); 2443typedef enum TOX_ERR_CONFERENCE_PEER_QUERY {
2444
2445 /**
2446 * The function returned successfully.
2447 */
2448 TOX_ERR_CONFERENCE_PEER_QUERY_OK,
2449
2450 /**
2451 * The conference number passed did not designate a valid conference.
2452 */
2453 TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND,
2454
2455 /**
2456 * The peer number passed did not designate a valid peer.
2457 */
2458 TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND,
2459
2460 /**
2461 * The client is not connected to the conference.
2462 */
2463 TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION,
2464
2465} TOX_ERR_CONFERENCE_PEER_QUERY;
2415 2466
2416size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t group_number, uint32_t peer_number,
2417 TOX_ERR_CONFERENCE *error);
2418 2467
2419/** 2468/**
2420 * Copy the name of peer_number who is in group_number to name. 2469 * Return the number of peers in the conference. Return value is unspecified on failure.
2470 */
2471uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_PEER_QUERY *error);
2472
2473/**
2474 * Return the length of the peer's name. Return value is unspecified on failure.
2475 */
2476size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
2477 TOX_ERR_CONFERENCE_PEER_QUERY *error);
2478
2479/**
2480 * Copy the name of peer_number who is in conference_number to name.
2421 * name must be at least TOX_MAX_NAME_LENGTH long. 2481 * name must be at least TOX_MAX_NAME_LENGTH long.
2422 * 2482 *
2423 * return length of name if success 2483 * @return true on success.
2424 * return -1 if failure
2425 */ 2484 */
2426bool tox_conference_peer_get_name(const Tox *tox, uint32_t group_number, uint32_t peer_number, uint8_t *name, 2485bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
2427 TOX_ERR_CONFERENCE *error); 2486 TOX_ERR_CONFERENCE_PEER_QUERY *error);
2428 2487
2429/** 2488/**
2430 * Copy the public key of peer_number who is in group_number to public_key. 2489 * Copy the public key of peer_number who is in conference_number to public_key.
2431 * public_key must be TOX_PUBLIC_KEY_SIZE long. 2490 * public_key must be TOX_PUBLIC_KEY_SIZE long.
2432 * 2491 *
2433 * returns 0 on success 2492 * @return true on success.
2434 * returns -1 on failure
2435 */ 2493 */
2436bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t group_number, uint32_t peer_number, 2494bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
2437 uint8_t *public_key, TOX_ERR_CONFERENCE *error); 2495 uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error);
2438 2496
2439/** 2497/**
2440 * Check if the current peer_number corresponds to ours. 2498 * Return true if passed peer_number corresponds to our own.
2441 *
2442 * return 1 if the peer_number corresponds to ours.
2443 * return 0 on failure.
2444 */ 2499 */
2445bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t group_number, uint32_t peer_number); 2500bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
2501 TOX_ERR_CONFERENCE_PEER_QUERY *error);
2502
2503typedef enum TOX_ERR_CONFERENCE_INVITE {
2504
2505 /**
2506 * The function returned successfully.
2507 */
2508 TOX_ERR_CONFERENCE_INVITE_OK,
2509
2510 /**
2511 * The conference number passed did not designate a valid conference.
2512 */
2513 TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND,
2514
2515 /**
2516 * The invite packet failed to send.
2517 */
2518 TOX_ERR_CONFERENCE_INVITE_FAIL_SEND,
2519
2520} TOX_ERR_CONFERENCE_INVITE;
2521
2446 2522
2447/** 2523/**
2448 * invite friend_number to group_number 2524 * Invites a friend to a conference.
2449 * return 0 on success 2525 *
2450 * return -1 on failure 2526 * @param friend_number The friend number of the friend we want to invite.
2527 * @param conference_number The conference number of the conference we want to invite the friend to.
2528 *
2529 * @return true on success.
2451 */ 2530 */
2452bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t group_number, TOX_ERR_CONFERENCE *error); 2531bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
2532 TOX_ERR_CONFERENCE_INVITE *error);
2533
2534typedef enum TOX_ERR_CONFERENCE_JOIN {
2535
2536 /**
2537 * The function returned successfully.
2538 */
2539 TOX_ERR_CONFERENCE_JOIN_OK,
2540
2541 /**
2542 * The cookie passed has an invalid length.
2543 */
2544 TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH,
2545
2546 /**
2547 * The conference is not the expected type. This indicates an invalid cookie.
2548 */
2549 TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE,
2550
2551 /**
2552 * The friend number passed does not designate a valid friend.
2553 */
2554 TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND,
2555
2556 /**
2557 * Client is already in this conference.
2558 */
2559 TOX_ERR_CONFERENCE_JOIN_DUPLICATE,
2560
2561 /**
2562 * Conference instance failed to initialize.
2563 */
2564 TOX_ERR_CONFERENCE_JOIN_INIT_FAIL,
2565
2566 /**
2567 * The join packet failed to send.
2568 */
2569 TOX_ERR_CONFERENCE_JOIN_FAIL_SEND,
2570
2571} TOX_ERR_CONFERENCE_JOIN;
2572
2453 2573
2454/** 2574/**
2455 * Join a group (you need to have been invited first.) using cookie of length obtained 2575 * Joins a conference that the client has been invited to.
2456 * in the group invite callback.
2457 * 2576 *
2458 * returns group number on success 2577 * @param friend_number The friend number of the friend who sent the invite.
2459 * returns -1 on failure. 2578 * @param cookie Received via the `conference_invite` event.
2579 * @param length The size of cookie.
2580 *
2581 * @return conference number on success, UINT32_MAX on failure.
2460 */ 2582 */
2461uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length, 2583uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
2462 TOX_ERR_CONFERENCE *error); 2584 TOX_ERR_CONFERENCE_JOIN *error);
2585
2586typedef enum TOX_ERR_CONFERENCE_SEND_MESSAGE {
2587
2588 /**
2589 * The function returned successfully.
2590 */
2591 TOX_ERR_CONFERENCE_SEND_MESSAGE_OK,
2592
2593 /**
2594 * The conference number passed did not designate a valid conference.
2595 */
2596 TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND,
2597
2598 /**
2599 * The message is too long.
2600 */
2601 TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG,
2602
2603 /**
2604 * The client is not connected to the conference.
2605 */
2606 TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION,
2607
2608 /**
2609 * The message packet failed to send.
2610 */
2611 TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND,
2612
2613} TOX_ERR_CONFERENCE_SEND_MESSAGE;
2614
2463 2615
2464/** 2616/**
2465 * send a group message 2617 * Send a text chat message to the conference.
2466 * return 0 on success 2618 *
2467 * return -1 on failure 2619 * This function creates a conference message packet and pushes it into the send
2620 * queue.
2621 *
2622 * The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages
2623 * must be split by the client and sent as separate messages. Other clients can
2624 * then reassemble the fragments.
2625 *
2626 * @param conference_number The conference number of the conference the message is intended for.
2627 * @param type Message type (normal, action, ...).
2628 * @param message A non-NULL pointer to the first element of a byte array
2629 * containing the message text.
2630 * @param length Length of the message to be sent.
2631 *
2632 * @return true on success.
2468 */ 2633 */
2469bool tox_conference_send_message(Tox *tox, uint32_t group_number, TOX_MESSAGE_TYPE type, const uint8_t *message, 2634bool tox_conference_send_message(Tox *tox, uint32_t conference_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
2470 size_t length, TOX_ERR_CONFERENCE *error); 2635 size_t length, TOX_ERR_CONFERENCE_SEND_MESSAGE *error);
2636
2637typedef enum TOX_ERR_CONFERENCE_TITLE {
2638
2639 /**
2640 * The function returned successfully.
2641 */
2642 TOX_ERR_CONFERENCE_TITLE_OK,
2643
2644 /**
2645 * The conference number passed did not designate a valid conference.
2646 */
2647 TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND,
2471 2648
2472size_t tox_conference_get_title_size(const Tox *tox, uint32_t group_number, TOX_ERR_CONFERENCE *error); 2649 /**
2650 * The title is too long or empty.
2651 */
2652 TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH,
2653
2654 /**
2655 * The title packet failed to send.
2656 */
2657 TOX_ERR_CONFERENCE_TITLE_FAIL_SEND,
2658
2659} TOX_ERR_CONFERENCE_TITLE;
2660
2661
2662/**
2663 * Return the length of the conference title. Return value is unspecified on failure.
2664 *
2665 * The return value is equal to the `length` argument received by the last
2666 * `conference_title` callback.
2667 */
2668size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_TITLE *error);
2473 2669
2474/** 2670/**
2475 * Get group title from group_number and put it in title. 2671 * Write the title designated by the given conference number to a byte array.
2476 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes. 2672 *
2673 * Call tox_conference_get_title_size to determine the allocation size for the `title` parameter.
2477 * 2674 *
2478 * return length of copied title if success. 2675 * The data written to `title` is equal to the data received by the last
2479 * return -1 if failure. 2676 * `conference_title` callback.
2677 *
2678 * @param title A valid memory region large enough to store the title.
2679 * If this parameter is NULL, this function has no effect.
2680 *
2681 * @return true on success.
2480 */ 2682 */
2481bool tox_conference_get_title(const Tox *tox, uint32_t group_number, uint8_t *title, TOX_ERR_CONFERENCE *error); 2683bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
2684 TOX_ERR_CONFERENCE_TITLE *error);
2482 2685
2483/** 2686/**
2484 * set the group's title, limited to MAX_NAME_LENGTH 2687 * Set the conference title and broadcast it to the rest of the conference.
2485 * return 0 on success 2688 *
2486 * return -1 on failure 2689 * Title length cannot be longer than TOX_MAX_NAME_LENGTH.
2690 *
2691 * @return true on success.
2487 */ 2692 */
2488bool tox_conference_set_title(Tox *tox, uint32_t group_number, const uint8_t *title, size_t length, 2693bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
2489 TOX_ERR_CONFERENCE *error); 2694 TOX_ERR_CONFERENCE_TITLE *error);
2490 2695
2491/** 2696/**
2492 * Return the number of chats in the instance m. 2697 * Return the number of conferences in the Tox instance.
2493 * You should use this to determine how much memory to allocate 2698 * This should be used to determine how much memory to allocate for `tox_conference_get_chatlist`.
2494 * for copy_chatlist.
2495 */ 2699 */
2496size_t tox_conference_get_chatlist_size(const Tox *tox); 2700size_t tox_conference_get_chatlist_size(const Tox *tox);
2497 2701
2498/** 2702/**
2499 * Copy a list of valid chat IDs into the array out_list. 2703 * Copy a list of valid conference IDs into the array chatlist. Determine how much space
2500 * If out_list is NULL, returns 0. 2704 * to allocate for the array with the `tox_conference_get_chatlist_size` function.
2501 * Otherwise, returns the number of elements copied. 2705 *
2502 * If the array was too small, the contents 2706 * @return The number of elements copied to the array, or 0 if chatlist is set to NULL.
2503 * of out_list will be truncated to list_size.
2504 */ 2707 */
2505void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist); 2708void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist);
2506 2709
2507/** 2710/**
2508 * return the type of groupchat (TOX_CONFERENCE_TYPE) that group_number is. 2711 * Returns the type of conference (TOX_CONFERENCE_TYPE) that conference_number is. Return value is
2509 * 2712 * unspecified on failure.
2510 * return -1 on failure.
2511 * return type on success.
2512 */ 2713 */
2513TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t group_number, TOX_ERR_CONFERENCE *error); 2714typedef enum TOX_ERR_CONFERENCE_GET_TYPE {
2715
2716 /**
2717 * The function returned successfully.
2718 */
2719 TOX_ERR_CONFERENCE_GET_TYPE_OK,
2720
2721 /**
2722 * The conference number passed did not designate a valid conference.
2723 */
2724 TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND,
2725
2726} TOX_ERR_CONFERENCE_GET_TYPE;
2727
2728
2729TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_number,
2730 TOX_ERR_CONFERENCE_GET_TYPE *error);
2514 2731
2515 2732
2516/******************************************************************************* 2733/*******************************************************************************
diff --git a/toxcore/tox_group.c b/toxcore/tox_group.c
deleted file mode 100644
index 445ce9de..00000000
--- a/toxcore/tox_group.c
+++ /dev/null
@@ -1,289 +0,0 @@
1/* tox.c
2 *
3 * The Tox public API.
4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Tox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#define TOX_DEFINED
29typedef struct Messenger Tox;
30#include "tox_group.h"
31
32#include "Messenger.h"
33#include "group.h"
34
35#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
36
37/**********GROUP CHAT FUNCTIONS: WARNING Group chats will be rewritten so this might change ************/
38
39/* Set the callback for group invites.
40 *
41 * Function(Tox *tox, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata)
42 *
43 * data of length is what needs to be passed to join_groupchat().
44 */
45void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback, void *user_data)
46{
47 Messenger *m = tox;
48 g_callback_group_invite(
49 m->group_chat_object,
50 (void (*)(Messenger * m, uint32_t, int, const uint8_t *, size_t, void *))callback,
51 user_data);
52}
53
54/* Set the callback for group messages.
55 *
56 * Function(Tox *tox, int groupnumber, int peernumber, uint8_t * message, uint16_t length, void *userdata)
57 */
58void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback, void *user_data)
59{
60 Messenger *m = tox;
61 g_callback_group_message(
62 m->group_chat_object,
63 (void (*)(Messenger * m, uint32_t, uint32_t, int, const uint8_t *, size_t, void *))callback,
64 user_data);
65}
66
67/* Set callback function for title changes.
68 *
69 * Function(Tox *tox, int groupnumber, int peernumber, uint8_t * title, uint8_t length, void *userdata)
70 * if peernumber == -1, then author is unknown (e.g. initial joining the group)
71 */
72void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback, void *user_data)
73{
74 Messenger *m = tox;
75 g_callback_group_title(m->group_chat_object, callback, user_data);
76}
77
78/* Set callback function for peer name list changes.
79 *
80 * It gets called every time the name list changes(new peer/name, deleted peer)
81 * Function(Tox *tox, int groupnumber, void *userdata)
82 */
83void tox_callback_conference_namelist_change(Tox *tox, tox_conference_namelist_change_cb *callback, void *user_data)
84{
85 Messenger *m = tox;
86 g_callback_group_namelistchange(
87 m->group_chat_object,
88 (void (*)(struct Messenger *, int, int, uint8_t, void *))callback,
89 user_data);
90}
91
92/* Creates a new groupchat and puts it in the chats array.
93 *
94 * return group number on success.
95 * return -1 on failure.
96 */
97uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE *error)
98{
99 Messenger *m = tox;
100 int res = add_groupchat(m->group_chat_object, GROUPCHAT_TYPE_TEXT);
101
102 if (res == -1) {
103 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_FAILURE);
104 return 0;
105 }
106
107 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_OK);
108 return res;
109}
110
111/* Delete a groupchat from the chats array.
112 *
113 * return 0 on success.
114 * return -1 if failure.
115 */
116bool tox_conference_delete(Tox *tox, uint32_t group_number, TOX_ERR_CONFERENCE *error)
117{
118 Messenger *m = tox;
119 int res = del_groupchat(m->group_chat_object, group_number);
120
121 if (res == -1) {
122 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_FAILURE);
123 return false;
124 }
125
126 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_OK);
127 return true;
128}
129
130size_t tox_conference_peer_get_name_size(
131 const Tox *tox, uint32_t group_number, uint32_t peer_number, TOX_ERR_CONFERENCE *error)
132{
133 const Messenger *m = tox;
134 int res = group_peername_size(m->group_chat_object, group_number, peer_number);
135
136 if (res == -1) {
137 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_FAILURE);
138 return 0;
139 }
140
141 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_OK);
142 return res;
143}
144
145/* Copy the name of peernumber who is in groupnumber to name.
146 * name must be at least MAX_NICK_BYTES long.
147 *
148 * return length of name if success
149 * return -1 if failure
150 */
151bool tox_conference_peer_get_name(const Tox *tox, uint32_t group_number, uint32_t peer_number, uint8_t *name,
152 TOX_ERR_CONFERENCE *error)
153{
154 const Messenger *m = tox;
155 return group_peername(m->group_chat_object, group_number, peer_number, name);
156}
157
158/* Copy the public key of peernumber who is in groupnumber to public_key.
159 * public_key must be crypto_box_PUBLICKEYBYTES long.
160 *
161 * returns 0 on success
162 * returns -1 on failure
163 */
164bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t group_number, uint32_t peer_number,
165 uint8_t *public_key, TOX_ERR_CONFERENCE *error)
166{
167 const Messenger *m = tox;
168 return group_peer_pubkey(m->group_chat_object, group_number, peer_number, public_key);
169}
170
171/* invite friendnumber to groupnumber
172 * return 0 on success
173 * return -1 on failure
174 */
175bool tox_conference_invite(Tox *tox, uint32_t friendnumber, uint32_t group_number, TOX_ERR_CONFERENCE *error)
176{
177 Messenger *m = tox;
178 return invite_friend(m->group_chat_object, friendnumber, group_number);
179}
180
181/* Join a group (you need to have been invited first.) using data of length obtained
182 * in the group invite callback.
183 *
184 * returns group number on success
185 * returns -1 on failure.
186 */
187uint32_t tox_conference_join(Tox *tox, uint32_t friendnumber, const uint8_t *data, size_t length,
188 TOX_ERR_CONFERENCE *error)
189{
190 Messenger *m = tox;
191 return join_groupchat(m->group_chat_object, friendnumber, GROUPCHAT_TYPE_TEXT, data, length);
192}
193
194/* send a group message
195 * return 0 on success
196 * return -1 on failure
197 */
198bool tox_conference_send_message(Tox *tox, uint32_t groupnumber, TOX_MESSAGE_TYPE type, const uint8_t *message,
199 size_t length, TOX_ERR_CONFERENCE *error)
200{
201 Messenger *m = tox;
202
203 if (type == TOX_MESSAGE_TYPE_NORMAL) {
204 return group_message_send(m->group_chat_object, groupnumber, message, length);
205 } else {
206 return group_action_send(m->group_chat_object, groupnumber, message, length);
207 }
208}
209
210/* set the group's title, limited to MAX_NAME_LENGTH
211 * return 0 on success
212 * return -1 on failure
213 */
214bool tox_conference_set_title(Tox *tox, uint32_t groupnumber, const uint8_t *title, size_t length,
215 TOX_ERR_CONFERENCE *error)
216{
217 Messenger *m = tox;
218 return group_title_send(m->group_chat_object, groupnumber, title, length);
219}
220
221size_t tox_conference_get_title_size(const Tox *tox, uint32_t groupnumber, TOX_ERR_CONFERENCE *error)
222{
223 const Messenger *m = tox;
224 return group_title_get_size(m->group_chat_object, groupnumber);
225}
226
227/* Get group title from groupnumber and put it in title.
228 * title needs to be a valid memory location with a max_length size of at least MAX_NAME_LENGTH (128) bytes.
229 *
230 * return length of copied title if success.
231 * return -1 if failure.
232 */
233bool tox_conference_get_title(const Tox *tox, uint32_t groupnumber, uint8_t *title, TOX_ERR_CONFERENCE *error)
234{
235 const Messenger *m = tox;
236 return group_title_get(m->group_chat_object, groupnumber, title);
237}
238
239/* Check if the current peernumber corresponds to ours.
240 *
241 * return 1 if the peernumber corresponds to ours.
242 * return 0 on failure.
243 */
244bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t groupnumber, uint32_t peernumber)
245{
246 const Messenger *m = tox;
247 return group_peernumber_is_ours(m->group_chat_object, groupnumber, peernumber);
248}
249
250/* Return the number of peers in the group chat on success.
251 * return -1 on failure
252 */
253uint32_t tox_conference_peer_count(const Tox *tox, uint32_t groupnumber, TOX_ERR_CONFERENCE *error)
254{
255 const Messenger *m = tox;
256 return group_number_peers(m->group_chat_object, groupnumber);
257}
258
259/* Return the number of chats in the instance m.
260 * You should use this to determine how much memory to allocate
261 * for copy_chatlist. */
262size_t tox_conference_get_chatlist_size(const Tox *tox)
263{
264 const Messenger *m = tox;
265 return count_chatlist(m->group_chat_object);
266}
267
268/* Copy a list of valid chat IDs into the array out_list.
269 * If out_list is NULL, returns 0.
270 * Otherwise, returns the number of elements copied.
271 * If the array was too small, the contents
272 * of out_list will be truncated to list_size. */
273void tox_conference_get_chatlist(const Tox *tox, uint32_t *out_list)
274{
275 const Messenger *m = tox;
276 size_t list_size = tox_conference_get_chatlist_size(tox);
277 copy_chatlist(m->group_chat_object, out_list, list_size);
278}
279
280/* return the type of groupchat (TOX_GROUPCHAT_TYPE_) that groupnumber is.
281 *
282 * return -1 on failure.
283 * return type on success.
284 */
285TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t groupnumber, TOX_ERR_CONFERENCE *error)
286{
287 const Messenger *m = tox;
288 return group_get_type(m->group_chat_object, groupnumber);
289}