summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-09-25 16:48:18 -0400
committerirungentoo <irungentoo@gmail.com>2014-09-25 16:48:18 -0400
commitd67624bf99d03ecb754a5f406a971ad41de1cd04 (patch)
tree9913ee9d24468b9dbd1c0026abfe269d88eb7415
parentaca2d618435388fb3029c9db6d9ea1c5ba427cbe (diff)
Removed groupchats from core.
-rw-r--r--toxcore/Makefile.inc2
-rw-r--r--toxcore/Messenger.c538
-rw-r--r--toxcore/Messenger.h130
-rw-r--r--toxcore/group_chats.c837
-rw-r--r--toxcore/group_chats.h199
-rw-r--r--toxcore/network.h1
-rw-r--r--toxcore/tox.c30
7 files changed, 57 insertions, 1680 deletions
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc
index ded80681..8af793c8 100644
--- a/toxcore/Makefile.inc
+++ b/toxcore/Makefile.inc
@@ -27,8 +27,6 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \
27 ../toxcore/tox.c \ 27 ../toxcore/tox.c \
28 ../toxcore/util.h \ 28 ../toxcore/util.h \
29 ../toxcore/util.c \ 29 ../toxcore/util.c \
30 ../toxcore/group_chats.h \
31 ../toxcore/group_chats.c \
32 ../toxcore/group.h \ 30 ../toxcore/group.h \
33 ../toxcore/group.c \ 31 ../toxcore/group.c \
34 ../toxcore/assoc.h \ 32 ../toxcore/assoc.h \
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 99b95f67..edb34364 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -492,10 +492,6 @@ int setname(Messenger *m, const uint8_t *name, uint16_t length)
492 for (i = 0; i < m->numfriends; ++i) 492 for (i = 0; i < m->numfriends; ++i)
493 m->friendlist[i].name_sent = 0; 493 m->friendlist[i].name_sent = 0;
494 494
495 for (i = 0; i < m->numchats; i++)
496 if (m->chats[i] != NULL)
497 set_nick(m->chats[i], name, length); /* TODO: remove this (group nicks should not be tied to the global one) */
498
499 return 0; 495 return 0;
500} 496}
501 497
@@ -1015,459 +1011,47 @@ static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_
1015 1011
1016/**********GROUP CHATS************/ 1012/**********GROUP CHATS************/
1017 1013
1018/* return 1 if the groupnumber is not valid.
1019 * return 0 if the groupnumber is valid.
1020 */
1021static uint8_t groupnumber_not_valid(const Messenger *m, int groupnumber)
1022{
1023 if ((unsigned int)groupnumber >= m->numchats)
1024 return 1;
1025
1026 if (m->chats == NULL)
1027 return 1;
1028
1029 if (m->chats[groupnumber] == NULL)
1030 return 1;
1031
1032 return 0;
1033}
1034
1035
1036/* returns valid ip port of connected friend on success
1037 * returns zeroed out IP_Port on failure
1038 */
1039static IP_Port get_friend_ipport(const Messenger *m, int32_t friendnumber)
1040{
1041 IP_Port zero;
1042 memset(&zero, 0, sizeof(zero));
1043
1044 if (friend_not_valid(m, friendnumber))
1045 return zero;
1046
1047 int crypt_id = m->friendlist[friendnumber].crypt_connection_id;
1048
1049 uint8_t direct_connected;
1050
1051 if (crypto_connection_status(m->net_crypto, crypt_id, &direct_connected) != CRYPTO_CONN_ESTABLISHED)
1052 return zero;
1053
1054 if (direct_connected == 0)
1055 return zero;
1056
1057 return m->net_crypto->crypto_connections[crypt_id].ip_port;
1058}
1059
1060/* returns the group number of the chat with public key group_public_key.
1061 * returns -1 on failure.
1062 */
1063static int group_num(const Messenger *m, const uint8_t *group_public_key)
1064{
1065 uint32_t i;
1066
1067 for (i = 0; i < m->numchats; ++i) {
1068 if (m->chats[i] != NULL)
1069 if (id_equal(m->chats[i]->self_public_key, group_public_key))
1070 return i;
1071 }
1072
1073 return -1;
1074}
1075 1014
1076/* Set the callback for group invites. 1015/* Set the callback for group invites.
1077 * 1016 *
1078 * Function(Messenger *m, int32_t friendnumber, uint8_t *group_public_key, void *userdata) 1017 * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number)
1079 */ 1018 */
1080void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, void *), 1019void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number)
1081 void *userdata)
1082{ 1020{
1083 m->group_invite = function; 1021 m->group_invite = function;
1084 m->group_invite_userdata = userdata; 1022 m->group_invite_number = number;
1085} 1023}
1086 1024
1087/* Set the callback for group messages. 1025/* Set the callback for group messages.
1088 * 1026 *
1089 * Function(Tox *tox, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 1027 * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number)
1090 */ 1028 */
1091void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *), 1029void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number)
1092 void *userdata)
1093{ 1030{
1094 m->group_message = function; 1031 m->group_message = function;
1095 m->group_message_userdata = userdata; 1032 m->group_message_number = number;
1096} 1033}
1097 1034
1098/* Set the callback for group actions. 1035/* Send a group invite packet.
1099 * 1036 *
1100 * Function(Tox *tox, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 1037 * return 1 on success
1101 */ 1038 * return 0 on failure
1102void m_callback_group_action(Messenger *m, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *),
1103 void *userdata)
1104{
1105 m->group_action = function;
1106 m->group_action_userdata = userdata;
1107}
1108
1109/* Set callback function for peer name list changes.
1110 *
1111 * It gets called every time the name list changes(new peer/name, deleted peer)
1112 * Function(Tox *tox, int groupnumber, void *userdata)
1113 */
1114void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *),
1115 void *userdata)
1116{
1117 m->group_namelistchange = function;
1118 m->group_namelistchange_userdata = userdata;
1119}
1120
1121static int get_chat_num(const Messenger *m, const Group_Chat *chat)
1122{
1123 uint32_t i;
1124
1125 for (i = 0; i < m->numchats; ++i) { //TODO: remove this
1126 if (m->chats[i] == chat)
1127 return i;
1128 }
1129
1130 return -1;
1131}
1132
1133static void group_message_function(Group_Chat *chat, int peer_number, const uint8_t *message, uint16_t length,
1134 void *userdata)
1135{
1136 Messenger *m = userdata;
1137 int i = get_chat_num(m, chat);
1138
1139 if (i == -1)
1140 return;
1141
1142 uint8_t message_terminated[length + 1];
1143 memcpy(message_terminated, message, length);
1144 message_terminated[length] = 0; /* Force NULL terminator */
1145
1146 if (m->group_message)
1147 (*m->group_message)(m, i, peer_number, message_terminated, length, m->group_message_userdata);
1148}
1149
1150static void group_action_function(Group_Chat *chat, int peer_number, const uint8_t *action, uint16_t length,
1151 void *userdata)
1152{
1153 Messenger *m = userdata;
1154 int i = get_chat_num(m, chat);
1155
1156 if (i == -1)
1157 return;
1158
1159 uint8_t action_terminated[length + 1];
1160 memcpy(action_terminated, action, length);
1161 action_terminated[length] = 0; /* Force NULL terminator */
1162
1163 if (m->group_action)
1164 (*m->group_action)(m, i, peer_number, action_terminated, length, m->group_action_userdata);
1165}
1166
1167static void group_namelistchange_function(Group_Chat *chat, int peer, uint8_t change, void *userdata)
1168{
1169 Messenger *m = userdata;
1170 int i = get_chat_num(m, chat);
1171
1172 if (i == -1)
1173 return;
1174
1175 if (m->group_namelistchange)
1176 (*m->group_namelistchange)(m, i, peer, change, m->group_namelistchange_userdata);
1177}
1178
1179
1180/* Creates a new groupchat and puts it in the chats array.
1181 *
1182 * return group number on success.
1183 * return -1 on failure.
1184 */
1185int add_groupchat(Messenger *m)
1186{
1187 uint32_t i;
1188
1189 for (i = 0; i < m->numchats; ++i) {
1190 if (m->chats[i] == NULL) {
1191 Group_Chat *newchat = new_groupchat(m->net);
1192
1193 if (newchat == NULL)
1194 return -1;
1195
1196 callback_groupmessage(newchat, &group_message_function, m);
1197 callback_groupaction(newchat, &group_action_function, m);
1198 callback_namelistchange(newchat, &group_namelistchange_function, m);
1199 /* TODO: remove this (group nicks should not be tied to the global one) */
1200 set_nick(newchat, m->name, m->name_length);
1201 m->chats[i] = newchat;
1202 return i;
1203 }
1204 }
1205
1206 Group_Chat **temp;
1207 temp = realloc(m->chats, sizeof(Group_Chat *) * (m->numchats + 1));
1208
1209 if (temp == NULL)
1210 return -1;
1211
1212 m->chats = temp;
1213 temp[m->numchats] = new_groupchat(m->net);
1214
1215 if (temp[m->numchats] == NULL)
1216 return -1;
1217
1218 callback_groupmessage(temp[m->numchats], &group_message_function, m);
1219 callback_groupaction(temp[m->numchats], &group_action_function, m);
1220 callback_namelistchange(temp[m->numchats], &group_namelistchange_function, m);
1221 /* TODO: remove this (group nicks should not be tied to the global one) */
1222 set_nick(temp[m->numchats], m->name, m->name_length);
1223 ++m->numchats;
1224 return (m->numchats - 1);
1225}
1226
1227/* Delete a groupchat from the chats array.
1228 *
1229 * return 0 on success.
1230 * return -1 if failure.
1231 */
1232int del_groupchat(Messenger *m, int groupnumber)
1233{
1234 if ((unsigned int)groupnumber >= m->numchats)
1235 return -1;
1236
1237 if (m->chats == NULL)
1238 return -1;
1239
1240 if (m->chats[groupnumber] == NULL)
1241 return -1;
1242
1243 kill_groupchat(m->chats[groupnumber]);
1244 m->chats[groupnumber] = NULL;
1245
1246 uint32_t i;
1247
1248 for (i = m->numchats; i != 0; --i) {
1249 if (m->chats[i - 1] != NULL)
1250 break;
1251 }
1252
1253 m->numchats = i;
1254
1255 if (i == 0) {
1256 free(m->chats);
1257 m->chats = NULL;
1258 } else {
1259 Group_Chat **temp = realloc(m->chats, sizeof(Group_Chat *) * i);
1260
1261 if (temp != NULL)
1262 m->chats = temp;
1263 }
1264
1265 return 0;
1266}
1267
1268/* Copy the name of peernumber who is in groupnumber to name.
1269 * name must be at least MAX_NICK_BYTES long.
1270 *
1271 * return length of name if success
1272 * return -1 if failure
1273 */
1274int m_group_peername(const Messenger *m, int groupnumber, int peernumber, uint8_t *name)
1275{
1276 if ((unsigned int)groupnumber >= m->numchats)
1277 return -1;
1278
1279 if (m->chats == NULL)
1280 return -1;
1281
1282 if (m->chats[groupnumber] == NULL)
1283 return -1;
1284
1285 return group_peername(m->chats[groupnumber], peernumber, name);
1286}
1287
1288/* Store the fact that we invited a specific friend.
1289 */
1290static void group_store_friendinvite(Messenger *m, int32_t friendnumber, int groupnumber)
1291{
1292 /* Add 1 to the groupchat number because 0 (default value in invited_groups) is a valid groupchat number */
1293 m->friendlist[friendnumber].invited_groups[m->friendlist[friendnumber].invited_groups_num % MAX_INVITED_GROUPS] =
1294 groupnumber + 1;
1295 ++m->friendlist[friendnumber].invited_groups_num;
1296}
1297
1298/* return 1 if that friend was invited to the group
1299 * return 0 if the friend was not or error.
1300 */
1301static uint8_t group_invited(const Messenger *m, int32_t friendnumber, int groupnumber)
1302{
1303
1304 uint32_t i;
1305 uint16_t num = MAX_INVITED_GROUPS;
1306
1307 if (MAX_INVITED_GROUPS > m->friendlist[friendnumber].invited_groups_num)
1308 num = m->friendlist[friendnumber].invited_groups_num;
1309
1310 for (i = 0; i < num; ++i) {
1311 if (m->friendlist[friendnumber].invited_groups[i] == groupnumber + 1) {
1312 return 1;
1313 }
1314 }
1315
1316 return 0;
1317}
1318
1319/* invite friendnumber to groupnumber
1320 * return 0 on success
1321 * return -1 on failure
1322 */
1323int invite_friend(Messenger *m, int32_t friendnumber, int groupnumber)
1324{
1325 if (friend_not_valid(m, friendnumber) || (unsigned int)groupnumber >= m->numchats)
1326 return -1;
1327
1328 if (m->chats == NULL)
1329 return -1;
1330
1331 if (m->friendlist[friendnumber].status == NOFRIEND || m->chats[groupnumber] == NULL)
1332 return -1;
1333
1334 group_store_friendinvite(m, friendnumber, groupnumber);
1335
1336 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, m->chats[groupnumber]->self_public_key,
1337 crypto_box_PUBLICKEYBYTES, 0) == 0)
1338 return -1;
1339
1340 return 0;
1341}
1342
1343
1344/* Join a group (you need to have been invited first.)
1345 *
1346 * returns group number on success
1347 * returns -1 on failure.
1348 */
1349int join_groupchat(Messenger *m, int32_t friendnumber, const uint8_t *friend_group_public_key)
1350{
1351 if (friend_not_valid(m, friendnumber))
1352 return -1;
1353
1354 uint8_t data[crypto_box_PUBLICKEYBYTES * 2];
1355 int groupnum = add_groupchat(m);
1356
1357 if (groupnum == -1)
1358 return -1;
1359
1360 IP_Port friend_ip = get_friend_ipport(m, friendnumber);
1361
1362 if (friend_ip.ip.family == 0) {
1363 del_groupchat(m, groupnum);
1364 return -1;
1365 }
1366
1367 id_copy(data, friend_group_public_key);
1368 id_copy(data + crypto_box_PUBLICKEYBYTES, m->chats[groupnum]->self_public_key);
1369
1370 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_JOIN_GROUPCHAT, data, sizeof(data), 0)) {
1371 chat_bootstrap_nonlazy(m->chats[groupnum], get_friend_ipport(m, friendnumber),
1372 friend_group_public_key); //TODO: check if ip returned is zero?
1373 return groupnum;
1374 }
1375
1376 del_groupchat(m, groupnum);
1377 return -1;
1378}
1379
1380
1381/* send a group message
1382 * return 0 on success
1383 * return -1 on failure
1384 */
1385int group_message_send(const Messenger *m, int groupnumber, const uint8_t *message, uint32_t length)
1386{
1387 if (groupnumber_not_valid(m, groupnumber))
1388 return -1;
1389
1390 if (group_sendmessage(m->chats[groupnumber], message, length) > 0)
1391 return 0;
1392
1393 return -1;
1394}
1395
1396/* send a group action
1397 * return 0 on success
1398 * return -1 on failure
1399 */
1400int group_action_send(const Messenger *m, int groupnumber, const uint8_t *action, uint32_t length)
1401{
1402 if (groupnumber_not_valid(m, groupnumber))
1403 return -1;
1404
1405 if (group_sendaction(m->chats[groupnumber], action, length) > 0)
1406 return 0;
1407
1408 return -1;
1409}
1410
1411/* Return the number of peers in the group chat on success.
1412 * return -1 on failure
1413 */ 1039 */
1414int group_number_peers(const Messenger *m, int groupnumber) 1040int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
1415{ 1041{
1416 if (groupnumber_not_valid(m, groupnumber)) 1042 return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, data, length, 0);
1417 return -1;
1418
1419 return group_numpeers(m->chats[groupnumber]);
1420} 1043}
1421 1044
1422/* List all the peers in the group chat. 1045/* Send a group message packet.
1423 *
1424 * Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
1425 * 1046 *
1426 * Copies the lengths of the names to lengths[length] 1047 * return 1 on success
1427 * 1048 * return 0 on failure
1428 * returns the number of peers on success.
1429 *
1430 * return -1 on failure.
1431 */ 1049 */
1432int group_names(const Messenger *m, int groupnumber, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[], 1050int send_group_message_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
1433 uint16_t length)
1434{
1435 if (groupnumber_not_valid(m, groupnumber))
1436 return -1;
1437
1438 return group_client_names(m->chats[groupnumber], names, lengths, length);
1439}
1440
1441static int handle_group(void *object, IP_Port source, const uint8_t *packet, uint32_t length)
1442{ 1051{
1443 Messenger *m = object; 1052 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MESSAGE_GROUPCHAT, data, length, 0);
1444
1445 if (length < crypto_box_PUBLICKEYBYTES + 1) {
1446 return 1;
1447 }
1448
1449 uint32_t i;
1450
1451 for (i = 0; i < m->numchats; ++i) {
1452 if (m->chats[i] == NULL)
1453 continue;
1454
1455 if (id_equal(packet + 1, m->chats[i]->self_public_key))
1456 return handle_groupchatpacket(m->chats[i], source, packet, length);
1457 }
1458
1459 return 1;
1460} 1053}
1461 1054
1462static void do_allgroupchats(Messenger *m)
1463{
1464 uint32_t i;
1465
1466 for (i = 0; i < m->numchats; ++i) {
1467 if (m->chats[i] != NULL)
1468 do_groupchat(m->chats[i]);
1469 }
1470}
1471 1055
1472/****************FILE SENDING*****************/ 1056/****************FILE SENDING*****************/
1473 1057
@@ -2061,21 +1645,13 @@ Messenger *new_messenger(Messenger_Options *options)
2061 set_nospam(&(m->fr), random_int()); 1645 set_nospam(&(m->fr), random_int());
2062 set_filter_function(&(m->fr), &friend_already_added, m); 1646 set_filter_function(&(m->fr), &friend_already_added, m);
2063 1647
2064 networking_registerhandler(m->net, NET_PACKET_GROUP_CHATS, &handle_group, m);
2065
2066 return m; 1648 return m;
2067} 1649}
2068 1650
2069/* Run this before closing shop. */ 1651/* Run this before closing shop. */
2070void kill_messenger(Messenger *m) 1652void kill_messenger(Messenger *m)
2071{ 1653{
2072 /* FIXME TODO: ideally cleanupMessenger will mirror initMessenger. 1654 uint32_t i;
2073 * This requires the other modules to expose cleanup functions.
2074 */
2075 uint32_t i, numchats = m->numchats;
2076
2077 for (i = 0; i < numchats; ++i)
2078 del_groupchat(m, i);
2079 1655
2080 kill_onion(m->onion); 1656 kill_onion(m->onion);
2081 kill_onion_announce(m->onion_a); 1657 kill_onion_announce(m->onion_a);
@@ -2599,30 +2175,21 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2599 } 2175 }
2600 2176
2601 case PACKET_ID_INVITE_GROUPCHAT: { 2177 case PACKET_ID_INVITE_GROUPCHAT: {
2602 if (data_length != crypto_box_PUBLICKEYBYTES) 2178 if (data_length == 0)
2603 break; 2179 break;
2604 2180
2605 if (m->group_invite) 2181 if (m->group_invite)
2606 (*m->group_invite)(m, i, data, m->group_invite_userdata); 2182 (*m->group_invite)(m, i, temp, len, m->group_invite_number);
2607 2183
2608 break; 2184 break;
2609 } 2185 }
2610 2186
2611 case PACKET_ID_JOIN_GROUPCHAT: { 2187 case PACKET_ID_MESSAGE_GROUPCHAT: {
2612 if (data_length != crypto_box_PUBLICKEYBYTES * 2) 2188 if (data_length == 0)
2613 break;
2614
2615 int groupnum = group_num(m, data);
2616
2617 if (groupnum == -1)
2618 break;
2619
2620 if (!group_invited(m, i, groupnum))
2621 break; 2189 break;
2622 2190
2623 group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); 2191 if (m->group_message)
2624 /* This is just there to speedup joining. */ 2192 (*m->group_message)(m, i, temp, len, m->group_message_number);
2625 chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES);
2626 break; 2193 break;
2627 } 2194 }
2628 2195
@@ -2902,7 +2469,6 @@ void do_messenger(Messenger *m)
2902 do_net_crypto(m->net_crypto); 2469 do_net_crypto(m->net_crypto);
2903 do_onion_client(m->onion_c); 2470 do_onion_client(m->onion_c);
2904 do_friends(m); 2471 do_friends(m);
2905 do_allgroupchats(m);
2906 LANdiscovery(m); 2472 LANdiscovery(m);
2907 2473
2908#ifdef LOGGING 2474#ifdef LOGGING
@@ -2913,16 +2479,6 @@ void do_messenger(Messenger *m)
2913 Assoc_status(m->dht->assoc); 2479 Assoc_status(m->dht->assoc);
2914#endif 2480#endif
2915 2481
2916 if (m->numchats > 0) {
2917 size_t c;
2918
2919 for (c = 0; c < m->numchats; c++) {
2920 if (m->chats[c])
2921 Assoc_status(m->chats[c]->assoc);
2922 }
2923 }
2924
2925
2926 lastdump = unix_time(); 2482 lastdump = unix_time();
2927 uint32_t client, last_pinged; 2483 uint32_t client, last_pinged;
2928 2484
@@ -3429,51 +2985,3 @@ int get_friendlist(const Messenger *m, int32_t **out_list, uint32_t *out_list_le
3429 2985
3430 return 0; 2986 return 0;
3431} 2987}
3432
3433/* Return the number of chats in the instance m.
3434 * You should use this to determine how much memory to allocate
3435 * for copy_chatlist. */
3436uint32_t count_chatlist(const Messenger *m)
3437{
3438 uint32_t ret = 0;
3439 uint32_t i;
3440
3441 for (i = 0; i < m->numchats; i++) {
3442 if (m->chats[i]) {
3443 ret++;
3444 }
3445 }
3446
3447 return ret;
3448}
3449
3450/* Copy a list of valid chat IDs into the array out_list.
3451 * If out_list is NULL, returns 0.
3452 * Otherwise, returns the number of elements copied.
3453 * If the array was too small, the contents
3454 * of out_list will be truncated to list_size. */
3455uint32_t copy_chatlist(const Messenger *m, int *out_list, uint32_t list_size)
3456{
3457 if (!out_list)
3458 return 0;
3459
3460 if (m->numchats == 0) {
3461 return 0;
3462 }
3463
3464 uint32_t i;
3465 uint32_t ret = 0;
3466
3467 for (i = 0; i < m->numchats; i++) {
3468 if (ret >= list_size) {
3469 break; /* Abandon ship */
3470 }
3471
3472 if (m->chats[i]) {
3473 out_list[ret] = i;
3474 ret++;
3475 }
3476 }
3477
3478 return ret;
3479}
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index e6877002..82edd17f 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -30,7 +30,6 @@
30#include "DHT.h" 30#include "DHT.h"
31#include "friend_requests.h" 31#include "friend_requests.h"
32#include "LAN_discovery.h" 32#include "LAN_discovery.h"
33#include "group_chats.h"
34#include "onion_client.h" 33#include "onion_client.h"
35 34
36#define MAX_NAME_LENGTH 128 35#define MAX_NAME_LENGTH 128
@@ -61,12 +60,9 @@
61#define PACKET_ID_FILE_SENDREQUEST 80 60#define PACKET_ID_FILE_SENDREQUEST 80
62#define PACKET_ID_FILE_CONTROL 81 61#define PACKET_ID_FILE_CONTROL 81
63#define PACKET_ID_FILE_DATA 82 62#define PACKET_ID_FILE_DATA 82
64#define PACKET_ID_INVITE_GROUPCHAT 144 63#define PACKET_ID_INVITE_GROUPCHAT 96
65#define PACKET_ID_JOIN_GROUPCHAT 145 64#define PACKET_ID_MESSAGE_GROUPCHAT 97
66#define PACKET_ID_ACCEPT_GROUPCHAT 146
67 65
68/* Max number of groups we can invite someone at the same time to. */
69#define MAX_INVITED_GROUPS 64
70 66
71/* Max number of tcp relays sent to friends */ 67/* Max number of tcp relays sent to friends */
72#define MAX_SHARED_RELAYS 16 68#define MAX_SHARED_RELAYS 16
@@ -227,8 +223,6 @@ typedef struct {
227 uint64_t share_relays_lastsent; 223 uint64_t share_relays_lastsent;
228 struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES]; 224 struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
229 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; 225 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
230 int invited_groups[MAX_INVITED_GROUPS];
231 uint16_t invited_groups_num;
232 226
233 AVATAR_SENDDATA avatar_send_data; 227 AVATAR_SENDDATA avatar_send_data;
234 AVATAR_RECEIVEDATA *avatar_recv_data; // We are receiving avatar data from this friend. 228 AVATAR_RECEIVEDATA *avatar_recv_data; // We are receiving avatar data from this friend.
@@ -274,9 +268,6 @@ typedef struct Messenger {
274 268
275 uint32_t numonline_friends; 269 uint32_t numonline_friends;
276 270
277 Group_Chat **chats;
278 uint32_t numchats;
279
280 uint64_t last_LANdiscovery; 271 uint64_t last_LANdiscovery;
281 272
282#define NUM_SAVED_TCP_RELAYS 8 273#define NUM_SAVED_TCP_RELAYS 8
@@ -308,14 +299,11 @@ typedef struct Messenger {
308 void *avatar_data_recv_userdata; 299 void *avatar_data_recv_userdata;
309 void (*avatar_data_recv)(struct Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *); 300 void (*avatar_data_recv)(struct Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *);
310 301
311 void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, void *); 302 void *group_chat_object; /* Set by new_groupchats()*/
312 void *group_invite_userdata; 303 void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t);
313 void (*group_message)(struct Messenger *m, int, int, const uint8_t *, uint16_t, void *); 304 uint32_t group_invite_number;
314 void *group_message_userdata; 305 void (*group_message)(struct Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t);
315 void (*group_action)(struct Messenger *m, int, int, const uint8_t *, uint16_t, void *); 306 uint32_t group_message_number;
316 void *group_action_userdata;
317 void (*group_namelistchange)(struct Messenger *m, int, int, uint8_t, void *);
318 void *group_namelistchange_userdata;
319 307
320 void (*file_sendrequest)(struct Messenger *m, int32_t, uint8_t, uint64_t, const uint8_t *, uint16_t, void *); 308 void (*file_sendrequest)(struct Messenger *m, int32_t, uint8_t, uint64_t, const uint8_t *, uint16_t, void *);
321 void *file_sendrequest_userdata; 309 void *file_sendrequest_userdata;
@@ -747,97 +735,29 @@ void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t
747 735
748/* Set the callback for group invites. 736/* Set the callback for group invites.
749 * 737 *
750 * Function(Messenger *m, int32_t friendnumber, uint8_t *group_public_key, void *userdata) 738 * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number)
751 */ 739 */
752void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, void *), 740void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number);
753 void *userdata);
754 741
755/* Set the callback for group messages. 742/* Set the callback for group messages.
756 * 743 *
757 * Function(Tox *tox, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 744 * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length, uint32_t number)
758 */
759void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *),
760 void *userdata);
761
762/* Set the callback for group actions.
763 *
764 * Function(Tox *tox, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
765 */
766void m_callback_group_action(Messenger *m, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *),
767 void *userdata);
768
769/* Set callback function for peer name list changes.
770 *
771 * It gets called every time the name list changes(new peer/name, deleted peer)
772 * Function(Tox *tox, int groupnumber, void *userdata)
773 */
774void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *),
775 void *userdata);
776
777/* Creates a new groupchat and puts it in the chats array.
778 *
779 * return group number on success.
780 * return -1 on failure.
781 */
782int add_groupchat(Messenger *m);
783
784/* Delete a groupchat from the chats array.
785 *
786 * return 0 on success.
787 * return -1 if failure.
788 */
789int del_groupchat(Messenger *m, int groupnumber);
790
791/* Copy the name of peernumber who is in groupnumber to name.
792 * name must be at least MAX_NICK_BYTES long.
793 *
794 * return length of name if success
795 * return -1 if failure
796 */
797int m_group_peername(const Messenger *m, int groupnumber, int peernumber, uint8_t *name);
798
799/* invite friendnumber to groupnumber
800 * return 0 on success
801 * return -1 on failure
802 */ 745 */
803int invite_friend(Messenger *m, int32_t friendnumber, int groupnumber); 746void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t, uint32_t), uint32_t number);
804 747
805/* Join a group (you need to have been invited first.) 748/* Send a group invite packet.
806 * 749 *
807 * returns group number on success 750 * return 1 on success
808 * returns -1 on failure. 751 * return 0 on failure
809 */
810int join_groupchat(Messenger *m, int32_t friendnumber, const uint8_t *friend_group_public_key);
811
812/* send a group message
813 * return 0 on success
814 * return -1 on failure
815 */
816int group_message_send(const Messenger *m, int groupnumber, const uint8_t *message, uint32_t length);
817
818/* send a group action
819 * return 0 on success
820 * return -1 on failure
821 */
822int group_action_send(const Messenger *m, int groupnumber, const uint8_t *action, uint32_t length);
823
824/* Return the number of peers in the group chat on success.
825 * return -1 on failure
826 */ 752 */
827int group_number_peers(const Messenger *m, int groupnumber); 753int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
828 754
829/* List all the peers in the group chat. 755/* Send a group message packet.
830 *
831 * Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
832 *
833 * Copies the lengths of the names to lengths[length]
834 * 756 *
835 * returns the number of peers on success. 757 * return 1 on success
836 * 758 * return 0 on failure
837 * return -1 on failure.
838 */ 759 */
839int group_names(const Messenger *m, int groupnumber, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[], 760int send_group_message_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
840 uint16_t length);
841 761
842/****************FILE SENDING*****************/ 762/****************FILE SENDING*****************/
843 763
@@ -1013,16 +933,4 @@ uint32_t copy_friendlist(const Messenger *m, int32_t *out_list, uint32_t list_si
1013 */ 933 */
1014int get_friendlist(const Messenger *m, int **out_list, uint32_t *out_list_length); 934int get_friendlist(const Messenger *m, int **out_list, uint32_t *out_list_length);
1015 935
1016/* Return the number of chats in the instance m.
1017 * You should use this to determine how much memory to allocate
1018 * for copy_chatlist. */
1019uint32_t count_chatlist(const Messenger *m);
1020
1021/* Copy a list of valid chat IDs into the array out_list.
1022 * If out_list is NULL, returns 0.
1023 * Otherwise, returns the number of elements copied.
1024 * If the array was too small, the contents
1025 * of out_list will be truncated to list_size. */
1026uint32_t copy_chatlist(const Messenger *m, int *out_list, uint32_t list_size);
1027
1028#endif 936#endif
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c
deleted file mode 100644
index 949ec53a..00000000
--- a/toxcore/group_chats.c
+++ /dev/null
@@ -1,837 +0,0 @@
1/* group_chats.c
2 *
3 * An implementation of massive text only group chats.
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include "DHT.h"
30#include "assoc.h"
31#include "group_chats.h"
32#include "LAN_discovery.h"
33#include "util.h"
34
35#define GROUPCHAT_MAXDATA_LENGTH (MAX_CRYPTO_REQUEST_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES))
36#define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES)
37
38#define GROUP_MAX_SENDNODES (GROUP_CLOSE_CONNECTIONS * 2)
39
40typedef struct {
41 uint64_t pingid;
42 //uint8_t client_id[crypto_box_PUBLICKEYBYTES];
43
44} getnodes_data;
45
46typedef struct {
47 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
48 IP_Port ip_port;
49
50} groupchat_nodes;
51
52typedef struct {
53 uint64_t pingid;
54 groupchat_nodes nodes[GROUP_CLOSE_CONNECTIONS];
55 //uint8_t client_id[crypto_box_PUBLICKEYBYTES];
56
57} sendnodes_data;
58
59/*
60 * check if peer with client_id is in peer array.
61 *
62 * return peer number if peer is in chat.
63 * return -1 if peer is not in chat.
64 *
65 * TODO: make this more efficient.
66 */
67
68static int peer_in_chat(const Group_Chat *chat, const uint8_t *client_id)
69{
70 uint32_t i;
71
72 for (i = 0; i < chat->numpeers; ++i)
73 if (id_equal(chat->group[i].client_id, client_id))
74 return i;
75
76 return -1;
77}
78
79/* Compares client_id1 and client_id2 with client_id.
80 *
81 * return 0 if both are same distance.
82 * return 1 if client_id1 is closer.
83 * return 2 if client_id2 is closer.
84 */
85static int id_closest_groupchats(const uint8_t *id, const uint8_t *id1, const uint8_t *id2)
86{
87 size_t i;
88 uint8_t distance1, distance2;
89
90 for (i = 0; i < CLIENT_ID_SIZE; ++i) {
91
92 distance1 = abs(((int8_t *)id)[i] - ((int8_t *)id1)[i]);
93 distance2 = abs(((int8_t *)id)[i] - ((int8_t *)id2)[i]);
94
95 if (distance1 < distance2)
96 return 1;
97
98 if (distance1 > distance2)
99 return 2;
100 }
101
102 return 0;
103}
104
105#define BAD_GROUPNODE_TIMEOUT 30
106
107/*
108 * Check if peer is closer to us that the other peers in the list and if the peer is in the list.
109 * Return the number of peers it is closer to if it is not in the closelist.
110 * Return -1 if the peer is in the closelist.
111 */
112
113static int peer_okping(const Group_Chat *chat, const uint8_t *client_id)
114{
115 uint32_t i, j = 0;
116
117 if (id_equal(chat->self_public_key, client_id))
118 return -1;
119
120 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
121 if (is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) {
122 ++j;
123 continue;
124 }
125
126 /* Equal */
127 if (id_equal(chat->close[i].client_id, client_id))
128 return -1;
129
130 if (id_closest_groupchats(chat->self_public_key, chat->close[i].client_id, client_id) == 2)
131 ++j;
132 }
133
134 return j;
135}
136
137
138
139/* Attempt to add a peer to the close list.
140 * Update last_recv if it is in list.
141 * Attempt to add it to list if it is not.
142 *
143 * Return 0 if success.
144 * Return -1 if peer was not put in list/updated.
145 */
146static int add_closepeer(Group_Chat *chat, const uint8_t *client_id, IP_Port ip_port)
147{
148 uint32_t i;
149
150 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Check if node is already in list, if it is update its last_recv */
151 if (id_equal(chat->close[i].client_id, client_id)) {
152 chat->close[i].last_recv = unix_time();
153 return 0;
154 }
155 }
156
157 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Try replacing bad nodes first */
158 if (is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) {
159 id_copy(chat->close[i].client_id, client_id);
160 chat->close[i].ip_port = ip_port;
161 chat->close[i].last_recv = unix_time();
162 return 0;
163 }
164 }
165
166 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Replace nodes if given one is closer. */
167 if (id_closest_groupchats(chat->self_public_key, chat->close[i].client_id, client_id) == 2) {
168 id_copy(chat->close[i].client_id, client_id);
169 chat->close[i].ip_port = ip_port;
170 chat->close[i].last_recv = unix_time();
171 return 0;
172 }
173 }
174
175 return -1;
176}
177
178static int send_groupchatpacket(const Group_Chat *chat, IP_Port ip_port, const uint8_t *public_key, const uint8_t *data,
179 uint32_t length, uint8_t request_id)
180{
181 if (id_equal(chat->self_public_key, public_key))
182 return -1;
183
184 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
185 int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id);
186 packet[0] = NET_PACKET_GROUP_CHATS;
187
188 if (len == -1)
189 return -1;
190
191 if (sendpacket(chat->net, ip_port, packet, len) == len)
192 return 0;
193
194 return -1;
195
196}
197
198/*
199 * Send data to all peers in close peer list.
200 *
201 * return the number of peers the packet was sent to.
202 */
203static uint8_t sendto_allpeers(const Group_Chat *chat, const uint8_t *data, uint16_t length, uint8_t request_id)
204{
205 uint16_t sent = 0;
206 uint32_t i;
207
208 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
209 if (ip_isset(&chat->close[i].ip_port.ip) &&
210 !is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) {
211 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id,
212 data, length, request_id) == 0)
213 ++sent;
214 }
215 }
216
217 return sent;
218}
219
220
221/*
222 * Add a peer to the group chat.
223 *
224 * return peernum if success or peer already in chat.
225 * return -1 if error.
226 */
227static int addpeer(Group_Chat *chat, const uint8_t *client_id)
228{
229 int peernum = peer_in_chat(chat, client_id);
230
231 if (peernum != -1)
232 return peernum;
233
234 Group_Peer *temp;
235 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1));
236
237 if (temp == NULL)
238 return -1;
239
240 memset(&(temp[chat->numpeers]), 0, sizeof(Group_Peer));
241 chat->group = temp;
242
243 id_copy(chat->group[chat->numpeers].client_id, client_id);
244 chat->group[chat->numpeers].last_recv = unix_time();
245 chat->group[chat->numpeers].last_recv_msgping = unix_time();
246 ++chat->numpeers;
247
248 if (chat->peer_namelistchange != NULL)
249 (*chat->peer_namelistchange)(chat, chat->numpeers - 1, CHAT_CHANGE_PEER_ADD, chat->group_namelistchange_userdata);
250
251 return (chat->numpeers - 1);
252}
253
254/*
255 * Set a peer from the group chat to deleted.
256 *
257 * return 0 if success
258 * return -1 if error.
259 */
260static int del_peer_set(Group_Chat *chat, int peernum)
261{
262 if ((uint32_t)peernum >= chat->numpeers)
263 return -1;
264
265 chat->group[peernum].deleted = 1;
266 chat->group[peernum].deleted_time = unix_time();
267 return 0;
268}
269
270/*
271 * Delete a peer from the group chat.
272 *
273 * return 0 if success
274 * return -1 if error.
275 */
276static int delpeer(Group_Chat *chat, int peernum)
277{
278 if ((uint32_t)peernum >= chat->numpeers)
279 return -1;
280
281 uint32_t i;
282
283 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* If peer is in close list, time it out forcefully. */
284 if (id_equal(chat->close[i].client_id, chat->group[peernum].client_id)) {
285 chat->close[i].last_recv = 0;
286 break;
287 }
288 }
289
290 Group_Peer *temp;
291 --chat->numpeers;
292
293 if (chat->numpeers == 0) {
294 free(chat->group);
295 chat->group = NULL;
296 return 0;
297 }
298
299 if (chat->numpeers != (uint32_t)peernum)
300 memcpy(&chat->group[peernum], &chat->group[chat->numpeers], sizeof(Group_Peer));
301
302 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers));
303
304 if (temp == NULL)
305 return -1;
306
307 chat->group = temp;
308
309 if (chat->peer_namelistchange != NULL) {
310 (*chat->peer_namelistchange)(chat, peernum, CHAT_CHANGE_PEER_DEL, chat->group_namelistchange_userdata);
311 }
312
313 return 0;
314}
315
316/* Copy the name of peernum to name.
317 * name must be at least MAX_NICK_BYTES long.
318 *
319 * return length of name if success
320 * return -1 if failure
321 */
322int group_peername(const Group_Chat *chat, int peernum, uint8_t *name)
323{
324 if ((uint32_t)peernum >= chat->numpeers)
325 return -1;
326
327 if (chat->group[peernum].nick_len == 0) {
328 /* memcpy(name, "NSA agent", 10); */ /* Srsly? */ /* Kindly remind the user that someone with no name might be a moronic NSA agent.*/
329 name[0] = 0;
330 return 0;
331 }
332
333 memcpy(name, chat->group[peernum].nick, chat->group[peernum].nick_len);
334 return chat->group[peernum].nick_len;
335}
336
337static void setnick(Group_Chat *chat, int peernum, const uint8_t *contents, uint16_t contents_len)
338{
339 if (contents_len > MAX_NICK_BYTES || contents_len == 0)
340 return;
341
342 /* same name as already stored? */
343 if (chat->group[peernum].nick_len == contents_len)
344 if (!memcmp(chat->group[peernum].nick, contents, contents_len))
345 return;
346
347 memcpy(chat->group[peernum].nick, contents, contents_len);
348 chat->group[peernum].nick_len = contents_len;
349
350 if (chat->peer_namelistchange != NULL)
351 (*chat->peer_namelistchange)(chat, peernum, CHAT_CHANGE_PEER_NAME, chat->group_namelistchange_userdata);
352}
353
354/* min time between pings sent to one peer in seconds */
355/* TODO: move this to global section */
356#define GROUP_PING_TIMEOUT 5
357
358static int send_getnodes(const Group_Chat *chat, IP_Port ip_port, int peernum)
359{
360 if ((uint32_t)peernum >= chat->numpeers)
361 return -1;
362
363 if (!is_timeout(chat->group[peernum].last_pinged, GROUP_PING_TIMEOUT))
364 return -1;
365
366 getnodes_data contents;
367 contents.pingid = random_64b();
368
369 chat->group[peernum].last_pinged = unix_time();
370 chat->group[peernum].pingid = contents.pingid;
371 chat->group[peernum].ping_via = ip_port;
372
373 if (chat->assoc) {
374 IPPTs ippts;
375 ippts.timestamp = unix_time();
376 ippts.ip_port = ip_port;
377
378 Assoc_add_entry(chat->assoc, chat->group[peernum].client_id, &ippts, NULL, 1);
379 }
380
381 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents),
382 CRYPTO_PACKET_GROUP_CHAT_GET_NODES);
383}
384
385static int send_sendnodes(const Group_Chat *chat, IP_Port ip_port, int peernum, uint64_t pingid)
386{
387 if ((uint32_t)peernum >= chat->numpeers)
388 return -1;
389
390 sendnodes_data contents;
391 contents.pingid = pingid;
392 uint32_t i, j = 0;
393
394 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
395 if (!is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) {
396 id_copy(contents.nodes[j].client_id, chat->close[i].client_id);
397 contents.nodes[j].ip_port = chat->close[i].ip_port;
398 to_net_family(&contents.nodes[j].ip_port.ip);
399 ++j;
400 }
401 }
402
403 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents,
404 sizeof(contents.pingid) + sizeof(groupchat_nodes) * j, CRYPTO_PACKET_GROUP_CHAT_SEND_NODES);
405}
406
407static int handle_getnodes(const Group_Chat *chat, IP_Port source, int peernum, const uint8_t *data, uint32_t len)
408{
409 if (len != sizeof(getnodes_data))
410 return 1;
411
412 if ((uint32_t)peernum >= chat->numpeers)
413 return 1;
414
415 getnodes_data contents;
416 memcpy(&contents, data, sizeof(contents));
417 send_sendnodes(chat, source, peernum, contents.pingid);
418
419 if (peer_okping(chat, chat->group[peernum].client_id) > 0)
420 send_getnodes(chat, source, peernum);
421
422 return 0;
423}
424
425static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, const uint8_t *data, uint32_t len)
426{
427 if ((uint32_t)peernum >= chat->numpeers)
428 return 1;
429
430 if (len > sizeof(sendnodes_data) || len < sizeof(uint64_t))
431 return 1;
432
433 if ((len - sizeof(uint64_t)) % sizeof(groupchat_nodes) != 0)
434 return 1;
435
436 if (is_timeout(chat->group[peernum].last_pinged, GROUP_PING_TIMEOUT))
437 return 1;
438
439 sendnodes_data contents;
440 memcpy(&contents, data, len);
441
442 if (contents.pingid != chat->group[peernum].pingid)
443 return 1;
444
445 uint16_t numnodes = (len - sizeof(contents.pingid)) / sizeof(groupchat_nodes);
446 uint32_t i;
447
448 IPPTs ippts_send;
449 ippts_send.timestamp = unix_time();
450
451 for (i = 0; i < numnodes; ++i) {
452 if (peer_okping(chat, contents.nodes[i].client_id) > 0) {
453 int peern = peer_in_chat(chat, contents.nodes[i].client_id);
454
455 if (peern == -1) { /*NOTE: This is just for testing and will be removed later.*/
456 peern = addpeer(chat, contents.nodes[i].client_id);
457 }
458
459 if (peern == -1)
460 continue;
461
462 to_host_family(&contents.nodes[i].ip_port.ip);
463 send_getnodes(chat, contents.nodes[i].ip_port, peern);
464
465 if (chat->assoc) {
466 ippts_send.ip_port = contents.nodes[i].ip_port;
467 Assoc_add_entry(chat->assoc, contents.nodes[i].client_id, &ippts_send, NULL, 0);
468 }
469 }
470 }
471
472 add_closepeer(chat, chat->group[peernum].client_id, source);
473
474 return 0;
475}
476
477#define GROUP_DATA_MIN_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + 1)
478static void send_names_new_peer(Group_Chat *chat);
479
480static int handle_data(Group_Chat *chat, const uint8_t *data, uint32_t len)
481{
482 if (len < GROUP_DATA_MIN_SIZE)
483 return 1;
484
485//TODO:
486 int peernum = peer_in_chat(chat, data);
487
488 if (peernum == -1) { /*NOTE: This is just for testing and will be removed later.*/
489 if (data[crypto_box_PUBLICKEYBYTES + sizeof(uint32_t)] != GROUP_CHAT_QUIT)
490 peernum = addpeer(chat, data);
491 }
492
493 if (peernum == -1)
494 return 1;
495
496 if (chat->group[peernum].deleted)
497 return 1;
498
499 /* Spam prevention (1 message per peer per second limit.)
500
501 if (chat->group[peernum].last_recv == temp_time)
502 return 1;
503 */
504 chat->group[peernum].last_recv = unix_time();
505
506 uint32_t message_num;
507 memcpy(&message_num, data + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
508 message_num = ntohl(message_num);
509
510 if (chat->group[peernum].last_message_number == 0) {
511 chat->group[peernum].last_message_number = message_num;
512 } else if (message_num - chat->group[peernum].last_message_number > 64 ||
513 message_num == chat->group[peernum].last_message_number)
514 return 1;
515
516 chat->group[peernum].last_message_number = message_num;
517
518 int handled = 1;
519 const uint8_t *contents = data + GROUP_DATA_MIN_SIZE;
520 uint16_t contents_len = len - GROUP_DATA_MIN_SIZE;
521
522 switch (data[crypto_box_PUBLICKEYBYTES + sizeof(message_num)]) {
523 case GROUP_CHAT_PING: /* If message is ping */
524 if (contents_len != 0)
525 return 1;
526
527 chat->group[peernum].last_recv_msgping = unix_time();
528 break;
529
530 case GROUP_CHAT_NEW_PEER: /* If message is new peer */
531 if (contents_len != crypto_box_PUBLICKEYBYTES)
532 return 1;
533
534 addpeer(chat, contents);
535 send_names_new_peer(chat);
536 break;
537
538 case GROUP_CHAT_QUIT: /* If peer tells us he is quitting */
539 if (contents_len != 0)
540 return 1;
541
542 del_peer_set(chat, peernum);
543 break;
544
545 case GROUP_CHAT_PEER_NICK:
546 if (contents_len > MAX_NICK_BYTES || contents_len == 0)
547 return 1;
548
549 setnick(chat, peernum, contents, contents_len);
550 break;
551
552 case GROUP_CHAT_CHAT_MESSAGE: /* If message is chat message */
553 if (chat->group_message != NULL)
554 (*chat->group_message)(chat, peernum, contents, contents_len, chat->group_message_userdata);
555
556 break;
557
558 case GROUP_CHAT_ACTION: /* if message is a peer action */
559 if (chat->group_action != NULL)
560 (*chat->group_action)(chat, peernum, contents, contents_len, chat->group_action_userdata);
561
562 break;
563
564 default:
565 handled = 0;
566 break;
567
568 }
569
570 if (handled == 1) {
571 sendto_allpeers(chat, data, len, CRYPTO_PACKET_GROUP_CHAT_BROADCAST);
572 return 0;
573 }
574
575 return 1;
576}
577
578static uint8_t send_data(Group_Chat *chat, const uint8_t *data, uint32_t len, uint8_t message_id)
579{
580 if (len + GROUP_DATA_MIN_SIZE > MAX_CRYPTO_REQUEST_SIZE) /*NOTE: not the real maximum len.*/
581 return 1;
582
583 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
584 ++chat->message_number;
585
586 if (chat->message_number == 0)
587 chat->message_number = 1;
588
589 uint32_t message_num = htonl(chat->message_number);
590//TODO
591 id_copy(packet, chat->self_public_key);
592 memcpy(packet + crypto_box_PUBLICKEYBYTES, &message_num, sizeof(message_num));
593
594 if (len != 0)
595 memcpy(packet + GROUP_DATA_MIN_SIZE, data, len);
596
597 packet[crypto_box_PUBLICKEYBYTES + sizeof(message_num)] = message_id;
598 return sendto_allpeers(chat, packet, len + GROUP_DATA_MIN_SIZE, CRYPTO_PACKET_GROUP_CHAT_BROADCAST);
599}
600/*
601 * Handle get nodes group packet.
602 *
603 * return 0 if handled correctly.
604 * return 1 if error.
605 */
606
607int handle_groupchatpacket(Group_Chat *chat, IP_Port source, const uint8_t *packet, uint32_t length)
608{
609 if (length > MAX_CRYPTO_REQUEST_SIZE)
610 return 1;
611
612 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
613 uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
614 uint8_t number;
615 int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length);
616
617 if (len <= 0)
618 return 1;
619
620 if (id_equal(chat->self_public_key, public_key))
621 return 1;
622
623 int peernum = peer_in_chat(chat, public_key);
624
625 if (peernum == -1)
626 return 1;
627
628 switch (number) {
629 case CRYPTO_PACKET_GROUP_CHAT_GET_NODES:
630 return handle_getnodes(chat, source, peernum, data, len);
631
632 case CRYPTO_PACKET_GROUP_CHAT_SEND_NODES:
633 return handle_sendnodes(chat, source, peernum, data, len);
634
635 case CRYPTO_PACKET_GROUP_CHAT_BROADCAST:
636 return handle_data(chat, data, len);
637
638 default:
639 return 1;
640 }
641
642 return 1;
643}
644
645uint32_t group_sendmessage(Group_Chat *chat, const uint8_t *message, uint32_t length)
646{
647 return send_data(chat, message, length, GROUP_CHAT_CHAT_MESSAGE); //TODO: better return values?
648}
649
650uint32_t group_sendaction(Group_Chat *chat, const uint8_t *action, uint32_t length)
651{
652 return send_data(chat, action, length, GROUP_CHAT_ACTION);
653}
654
655/*
656 * Send id/nick combo to the group.
657 *
658 * returns the number of peers it has sent it to.
659 */
660static uint32_t group_send_nick(Group_Chat *chat, uint8_t *nick, uint16_t nick_len)
661{
662 if (nick_len > MAX_NICK_BYTES)
663 return 0;
664
665 return send_data(chat, nick, nick_len, GROUP_CHAT_PEER_NICK);
666}
667
668int set_nick(Group_Chat *chat, const uint8_t *nick, uint16_t nick_len)
669{
670 if (nick_len > MAX_NICK_BYTES || nick_len == 0)
671 return -1;
672
673 memcpy(chat->nick, nick, nick_len);
674 chat->nick_len = nick_len;
675 group_send_nick(chat, chat->nick, chat->nick_len);
676 return 0;
677}
678
679uint32_t group_newpeer(Group_Chat *chat, const uint8_t *client_id)
680{
681 addpeer(chat, client_id);
682 return send_data(chat, client_id, crypto_box_PUBLICKEYBYTES, GROUP_CHAT_NEW_PEER); //TODO: better return values?
683}
684
685void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, const uint8_t *, uint16_t, void *),
686 void *userdata)
687{
688 chat->group_message = function;
689 chat->group_message_userdata = userdata;
690}
691
692void callback_groupaction(Group_Chat *chat, void (*function)(Group_Chat *chat, int, const uint8_t *, uint16_t, void *),
693 void *userdata)
694{
695 chat->group_action = function;
696 chat->group_action_userdata = userdata;
697}
698
699void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *),
700 void *userdata)
701{
702 chat->peer_namelistchange = function;
703 chat->group_namelistchange_userdata = userdata;
704}
705
706uint32_t group_numpeers(const Group_Chat *chat)
707{
708 return chat->numpeers;
709}
710
711uint32_t group_client_names(const Group_Chat *chat, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[],
712 uint16_t length)
713{
714 uint32_t i;
715
716 for (i = 0; i < chat->numpeers && i < length; ++i) {
717 lengths[i] = group_peername(chat, i, names[i]);
718 }
719
720 return i;
721}
722
723Group_Chat *new_groupchat(Networking_Core *net)
724{
725 unix_time_update();
726
727 if (net == 0)
728 return 0;
729
730 Group_Chat *chat = calloc(1, sizeof(Group_Chat));
731 chat->net = net;
732 crypto_box_keypair(chat->self_public_key, chat->self_secret_key);
733
734 /* (2^4) * 5 = 80 entries seems to be a moderate size */
735 chat->assoc = new_Assoc(4, 5, chat->self_public_key);
736
737 return chat;
738}
739
740#define NODE_PING_INTERVAL 10
741
742static void ping_close(Group_Chat *chat)
743{
744 uint32_t i;
745
746 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
747 if (!is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) {
748 int peernum = peer_in_chat(chat, chat->close[i].client_id);
749
750 if (peernum == -1)
751 continue;
752
753 if (is_timeout(chat->group[peernum].last_pinged, NODE_PING_INTERVAL))
754 send_getnodes(chat, chat->close[i].ip_port, peernum);
755 }
756 }
757}
758
759/* Interval in seconds to send ping messages */
760#define GROUP_PING_INTERVAL 30
761
762static void ping_group(Group_Chat *chat)
763{
764 if (is_timeout(chat->last_sent_ping, GROUP_PING_INTERVAL)) {
765 if (send_data(chat, 0, 0, GROUP_CHAT_PING) != 0) /* Ping */
766 chat->last_sent_ping = unix_time();
767 }
768}
769
770#define DEL_PEER_DELAY 3
771static void del_dead_peers(Group_Chat *chat)
772{
773 uint32_t i;
774
775 for (i = 0; i < chat->numpeers; ++i) {
776 if (is_timeout(chat->group[i].last_recv_msgping, GROUP_PING_INTERVAL * 4)) {
777 delpeer(chat, i);
778 }
779
780 if (chat->group == NULL || i >= chat->numpeers)
781 break;
782
783 if (chat->group[i].deleted) {
784 if (is_timeout(chat->group[i].deleted_time, DEL_PEER_DELAY))
785 delpeer(chat, i);
786 }
787 }
788}
789
790#define NICK_SEND_INTERVAL 180
791static void send_names_new_peer(Group_Chat *chat)
792{
793 group_send_nick(chat, chat->nick, chat->nick_len);
794 chat->last_sent_nick = (unix_time() - NICK_SEND_INTERVAL) + 15;
795}
796static void send_names(Group_Chat *chat)
797{
798 /* send own nick from time to time, to let newly added peers be informed
799 * first time only: use a shorter timeframe, because we might not be in our own
800 * peer list yet */
801 if (is_timeout(chat->last_sent_nick, 180))
802 if (group_send_nick(chat, chat->nick, chat->nick_len) > 0) {
803 if (!chat->last_sent_nick)
804 chat->last_sent_nick = (unix_time() - NICK_SEND_INTERVAL) + 10;
805 else
806 chat->last_sent_nick = unix_time();
807 }
808}
809
810void do_groupchat(Group_Chat *chat)
811{
812 unix_time_update();
813 ping_close(chat);
814 ping_group(chat);
815 /* TODO: Maybe run this less? */
816 del_dead_peers(chat);
817 send_names(chat);
818}
819
820void kill_groupchat(Group_Chat *chat)
821{
822 send_data(chat, 0, 0, GROUP_CHAT_QUIT);
823 kill_Assoc(chat->assoc);
824 free(chat->group);
825 free(chat);
826}
827
828void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, const uint8_t *client_id)
829{
830 send_getnodes(chat, ip_port, addpeer(chat, client_id));
831}
832
833void chat_bootstrap_nonlazy(Group_Chat *chat, IP_Port ip_port, const uint8_t *client_id)
834{
835 send_getnodes(chat, ip_port, addpeer(chat, client_id));
836 add_closepeer(chat, client_id, ip_port);
837}
diff --git a/toxcore/group_chats.h b/toxcore/group_chats.h
deleted file mode 100644
index 1a7a2e04..00000000
--- a/toxcore/group_chats.h
+++ /dev/null
@@ -1,199 +0,0 @@
1/* group_chats.h
2 *
3 * An implementation of massive text only group chats.
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#ifndef GROUP_CHATS_H
26#define GROUP_CHATS_H
27
28#define MAX_NICK_BYTES 128
29
30typedef struct {
31 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
32 uint64_t pingid;
33 uint64_t last_pinged;
34 IP_Port ping_via;
35
36 uint64_t last_recv;
37 uint64_t last_recv_msgping;
38 uint32_t last_message_number;
39
40 uint8_t nick[MAX_NICK_BYTES];
41 uint16_t nick_len;
42
43 uint8_t deleted;
44 uint64_t deleted_time;
45} Group_Peer;
46
47typedef struct {
48 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
49 IP_Port ip_port;
50 uint64_t last_recv;
51} Group_Close;
52
53#define GROUP_CLOSE_CONNECTIONS 6
54
55typedef struct Group_Chat {
56 Networking_Core *net;
57 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
58 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
59
60 Group_Peer *group;
61 Group_Close close[GROUP_CLOSE_CONNECTIONS];
62 uint32_t numpeers;
63
64 uint32_t message_number;
65 void (*group_message)(struct Group_Chat *m, int, const uint8_t *, uint16_t, void *);
66 void *group_message_userdata;
67 void (*group_action)(struct Group_Chat *m, int, const uint8_t *, uint16_t, void *);
68 void *group_action_userdata;
69 void (*peer_namelistchange)(struct Group_Chat *m, int peer, uint8_t change, void *);
70 void *group_namelistchange_userdata;
71
72 uint64_t last_sent_ping;
73
74 uint8_t nick[MAX_NICK_BYTES];
75 uint16_t nick_len;
76 uint64_t last_sent_nick;
77
78 struct Assoc *assoc;
79} Group_Chat;
80
81#define GROUP_CHAT_PING 0
82#define GROUP_CHAT_NEW_PEER 16
83#define GROUP_CHAT_QUIT 24
84#define GROUP_CHAT_PEER_NICK 48
85#define GROUP_CHAT_CHAT_MESSAGE 64
86#define GROUP_CHAT_ACTION 63
87
88/* Copy the name of peernum to name.
89 * name must be at least MAX_NICK_BYTES long.
90 *
91 * return length of name if success
92 * return -1 if failure
93 */
94int group_peername(const Group_Chat *chat, int peernum, uint8_t *name);
95
96/*
97 * Set callback function for chat messages.
98 *
99 * format of function is: function(Group_Chat *chat, peer number, message, message length, userdata)
100 */
101void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, const uint8_t *, uint16_t, void *),
102 void *userdata);
103
104/*
105 * Set callback function for actions.
106 *
107 * format of function is: function(Group_Chat *chat, peer number, action, action length, userdata)
108 */
109void callback_groupaction(Group_Chat *chat, void (*function)(Group_Chat *chat, int, const uint8_t *, uint16_t, void *),
110 void *userdata);
111
112/*
113 * Set callback function for peer name list changes.
114 *
115 * It gets called every time the name list changes(new peer/name, deleted peer)
116 *
117 * format of function is: function(Group_Chat *chat, userdata)
118 */
119typedef enum {
120 CHAT_CHANGE_PEER_ADD,
121 CHAT_CHANGE_PEER_DEL,
122 CHAT_CHANGE_PEER_NAME,
123} CHAT_CHANGE;
124
125void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *),
126 void *userdata);
127
128/*
129 * Send a message to the group.
130 *
131 * returns the number of peers it has sent it to.
132 */
133uint32_t group_sendmessage(Group_Chat *chat, const uint8_t *message, uint32_t length);
134
135/*
136 * Send an action to the group.
137 *
138 * returns the number of peers it has sent it to.
139 */
140uint32_t group_sendaction(Group_Chat *chat, const uint8_t *action, uint32_t length);
141
142/*
143 * Set our nick for this group.
144 *
145 * returns -1 on failure, 0 on success.
146 */
147int set_nick(Group_Chat *chat, const uint8_t *nick, uint16_t nick_len);
148
149/*
150 * Tell everyone about a new peer (a person we are inviting for example.)
151 *
152 */
153uint32_t group_newpeer(Group_Chat *chat, const uint8_t *client_id);
154
155
156/* Create a new group chat.
157 *
158 * Returns a new group chat instance if success.
159 *
160 * Returns a NULL pointer if fail.
161 */
162Group_Chat *new_groupchat(Networking_Core *net);
163
164
165/* Return the number of peers in the group chat.
166 */
167uint32_t group_numpeers(const Group_Chat *chat);
168
169/* List all the peers in the group chat.
170 *
171 * Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
172 *
173 * returns the number of peers.
174 */
175uint32_t group_client_names(const Group_Chat *chat, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[],
176 uint16_t length);
177
178/* Kill a group chat
179 *
180 * Frees the memory and everything.
181 */
182void kill_groupchat(Group_Chat *chat);
183
184/*
185 * This is the main loop.
186 */
187void do_groupchat(Group_Chat *chat);
188
189/* if we receive a group chat packet we call this function so it can be handled.
190 return 0 if packet is handled correctly.
191 return 1 if it didn't handle the packet or if the packet was shit. */
192int handle_groupchatpacket(Group_Chat *chat, IP_Port source, const uint8_t *packet, uint32_t length);
193
194
195void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, const uint8_t *client_id);
196void chat_bootstrap_nonlazy(Group_Chat *chat, IP_Port ip_port, const uint8_t *client_id);
197
198
199#endif
diff --git a/toxcore/network.h b/toxcore/network.h
index b250604e..6e1f2244 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -105,7 +105,6 @@ typedef int sock_t;
105#define NET_PACKET_CRYPTO_DATA 27 /* Crypto data packet */ 105#define NET_PACKET_CRYPTO_DATA 27 /* Crypto data packet */
106#define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */ 106#define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */
107#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ 107#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */
108#define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */
109 108
110/* See: docs/Prevent_Tracking.txt and onion.{c, h} */ 109/* See: docs/Prevent_Tracking.txt and onion.{c, h} */
111#define NET_PACKET_ONION_SEND_INITIAL 128 110#define NET_PACKET_ONION_SEND_INITIAL 128
diff --git a/toxcore/tox.c b/toxcore/tox.c
index e8ec593b..39a63fd9 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -550,7 +550,7 @@ void tox_callback_group_invite(Tox *tox, void (*function)(Messenger *tox, int32_
550 void *userdata) 550 void *userdata)
551{ 551{
552 Messenger *m = tox; 552 Messenger *m = tox;
553 m_callback_group_invite(m, function, userdata); 553 //m_callback_group_invite(m, function, userdata);
554} 554}
555 555
556/* Set the callback for group messages. 556/* Set the callback for group messages.
@@ -561,7 +561,7 @@ void tox_callback_group_message(Tox *tox, void (*function)(Messenger *tox, int,
561 void *userdata) 561 void *userdata)
562{ 562{
563 Messenger *m = tox; 563 Messenger *m = tox;
564 m_callback_group_message(m, function, userdata); 564 //m_callback_group_message(m, function, userdata);
565} 565}
566 566
567/* Set the callback for group actions. 567/* Set the callback for group actions.
@@ -572,7 +572,7 @@ void tox_callback_group_action(Tox *tox, void (*function)(Messenger *tox, int, i
572 void *userdata) 572 void *userdata)
573{ 573{
574 Messenger *m = tox; 574 Messenger *m = tox;
575 m_callback_group_action(m, function, userdata); 575 //m_callback_group_action(m, function, userdata);
576} 576}
577 577
578/* Set callback function for peer name list changes. 578/* Set callback function for peer name list changes.
@@ -583,7 +583,7 @@ void tox_callback_group_action(Tox *tox, void (*function)(Messenger *tox, int, i
583void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *), void *userdata) 583void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *), void *userdata)
584{ 584{
585 Messenger *m = tox; 585 Messenger *m = tox;
586 m_callback_group_namelistchange(m, function, userdata); 586 //m_callback_group_namelistchange(m, function, userdata);
587} 587}
588 588
589/* Creates a new groupchat and puts it in the chats array. 589/* Creates a new groupchat and puts it in the chats array.
@@ -594,7 +594,7 @@ void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int
594int tox_add_groupchat(Tox *tox) 594int tox_add_groupchat(Tox *tox)
595{ 595{
596 Messenger *m = tox; 596 Messenger *m = tox;
597 return add_groupchat(m); 597 //return add_groupchat(m);
598} 598}
599/* Delete a groupchat from the chats array. 599/* Delete a groupchat from the chats array.
600 * 600 *
@@ -604,7 +604,7 @@ int tox_add_groupchat(Tox *tox)
604int tox_del_groupchat(Tox *tox, int groupnumber) 604int tox_del_groupchat(Tox *tox, int groupnumber)
605{ 605{
606 Messenger *m = tox; 606 Messenger *m = tox;
607 return del_groupchat(m, groupnumber); 607 //return del_groupchat(m, groupnumber);
608} 608}
609 609
610/* Copy the name of peernumber who is in groupnumber to name. 610/* Copy the name of peernumber who is in groupnumber to name.
@@ -616,7 +616,7 @@ int tox_del_groupchat(Tox *tox, int groupnumber)
616int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name) 616int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name)
617{ 617{
618 const Messenger *m = tox; 618 const Messenger *m = tox;
619 return m_group_peername(m, groupnumber, peernumber, name); 619 //return m_group_peername(m, groupnumber, peernumber, name);
620} 620}
621/* invite friendnumber to groupnumber 621/* invite friendnumber to groupnumber
622 * return 0 on success 622 * return 0 on success
@@ -625,7 +625,7 @@ int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t
625int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber) 625int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber)
626{ 626{
627 Messenger *m = tox; 627 Messenger *m = tox;
628 return invite_friend(m, friendnumber, groupnumber); 628 //return invite_friend(m, friendnumber, groupnumber);
629} 629}
630/* Join a group (you need to have been invited first.) 630/* Join a group (you need to have been invited first.)
631 * 631 *
@@ -635,7 +635,7 @@ int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber)
635int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *friend_group_public_key) 635int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *friend_group_public_key)
636{ 636{
637 Messenger *m = tox; 637 Messenger *m = tox;
638 return join_groupchat(m, friendnumber, friend_group_public_key); 638 //return join_groupchat(m, friendnumber, friend_group_public_key);
639} 639}
640 640
641/* send a group message 641/* send a group message
@@ -645,7 +645,7 @@ int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *friend_gro
645int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint32_t length) 645int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint32_t length)
646{ 646{
647 Messenger *m = tox; 647 Messenger *m = tox;
648 return group_message_send(m, groupnumber, message, length); 648 //return group_message_send(m, groupnumber, message, length);
649} 649}
650 650
651/* send a group action 651/* send a group action
@@ -655,7 +655,7 @@ int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, ui
655int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint32_t length) 655int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint32_t length)
656{ 656{
657 Messenger *m = tox; 657 Messenger *m = tox;
658 return group_action_send(m, groupnumber, action, length); 658 //return group_action_send(m, groupnumber, action, length);
659} 659}
660 660
661/* Return the number of peers in the group chat on success. 661/* Return the number of peers in the group chat on success.
@@ -664,7 +664,7 @@ int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint
664int tox_group_number_peers(const Tox *tox, int groupnumber) 664int tox_group_number_peers(const Tox *tox, int groupnumber)
665{ 665{
666 const Messenger *m = tox; 666 const Messenger *m = tox;
667 return group_number_peers(m, groupnumber); 667 //return group_number_peers(m, groupnumber);
668} 668}
669 669
670/* List all the peers in the group chat. 670/* List all the peers in the group chat.
@@ -681,7 +681,7 @@ int tox_group_get_names(const Tox *tox, int groupnumber, uint8_t names[][TOX_MAX
681 uint16_t length) 681 uint16_t length)
682{ 682{
683 const Messenger *m = tox; 683 const Messenger *m = tox;
684 return group_names(m, groupnumber, names, lengths, length); 684 //return group_names(m, groupnumber, names, lengths, length);
685} 685}
686 686
687/* Return the number of chats in the instance m. 687/* Return the number of chats in the instance m.
@@ -690,7 +690,7 @@ int tox_group_get_names(const Tox *tox, int groupnumber, uint8_t names[][TOX_MAX
690uint32_t tox_count_chatlist(const Tox *tox) 690uint32_t tox_count_chatlist(const Tox *tox)
691{ 691{
692 const Messenger *m = tox; 692 const Messenger *m = tox;
693 return count_chatlist(m); 693 //return count_chatlist(m);
694} 694}
695 695
696/* Copy a list of valid chat IDs into the array out_list. 696/* Copy a list of valid chat IDs into the array out_list.
@@ -701,7 +701,7 @@ uint32_t tox_count_chatlist(const Tox *tox)
701uint32_t tox_get_chatlist(const Tox *tox, int *out_list, uint32_t list_size) 701uint32_t tox_get_chatlist(const Tox *tox, int *out_list, uint32_t list_size)
702{ 702{
703 const Messenger *m = tox; 703 const Messenger *m = tox;
704 return copy_chatlist(m, out_list, list_size); 704 //return copy_chatlist(m, out_list, list_size);
705} 705}
706 706
707 707