diff options
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/Makefile.inc | 2 | ||||
-rw-r--r-- | toxcore/Messenger.c | 538 | ||||
-rw-r--r-- | toxcore/Messenger.h | 130 | ||||
-rw-r--r-- | toxcore/group_chats.c | 837 | ||||
-rw-r--r-- | toxcore/group_chats.h | 199 | ||||
-rw-r--r-- | toxcore/network.h | 1 | ||||
-rw-r--r-- | toxcore/tox.c | 30 |
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 | */ | ||
1021 | static 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 | */ | ||
1039 | static 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 | */ | ||
1063 | static 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 | */ |
1080 | void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, void *), | 1019 | void 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 | */ |
1091 | void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *), | 1029 | void 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 |
1102 | void 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 | */ | ||
1114 | void 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 | |||
1121 | static 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 | |||
1133 | static 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 | |||
1150 | static 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 | |||
1167 | static 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 | */ | ||
1185 | int 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 | */ | ||
1232 | int 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 | */ | ||
1274 | int 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 | */ | ||
1290 | static 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 | */ | ||
1301 | static 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 | */ | ||
1323 | int 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 | */ | ||
1349 | int 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 | */ | ||
1385 | int 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 | */ | ||
1400 | int 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 | */ |
1414 | int group_number_peers(const Messenger *m, int groupnumber) | 1040 | int 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 | */ |
1432 | int group_names(const Messenger *m, int groupnumber, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[], | 1050 | int 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 | |||
1441 | static 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 | ||
1462 | static 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. */ |
2070 | void kill_messenger(Messenger *m) | 1652 | void 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. */ | ||
3436 | uint32_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. */ | ||
3455 | uint32_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 | */ |
752 | void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, void *), | 740 | void 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 | */ | ||
759 | void 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 | */ | ||
766 | void 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 | */ | ||
774 | void 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 | */ | ||
782 | int 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 | */ | ||
789 | int 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 | */ | ||
797 | int 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 | */ |
803 | int invite_friend(Messenger *m, int32_t friendnumber, int groupnumber); | 746 | void 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 | */ | ||
810 | int 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 | */ | ||
816 | int 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 | */ | ||
822 | int 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 | */ |
827 | int group_number_peers(const Messenger *m, int groupnumber); | 753 | int 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 | */ |
839 | int group_names(const Messenger *m, int groupnumber, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[], | 760 | int 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 | */ |
1014 | int get_friendlist(const Messenger *m, int **out_list, uint32_t *out_list_length); | 934 | int 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. */ | ||
1019 | uint32_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. */ | ||
1026 | uint32_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 | |||
40 | typedef struct { | ||
41 | uint64_t pingid; | ||
42 | //uint8_t client_id[crypto_box_PUBLICKEYBYTES]; | ||
43 | |||
44 | } getnodes_data; | ||
45 | |||
46 | typedef struct { | ||
47 | uint8_t client_id[crypto_box_PUBLICKEYBYTES]; | ||
48 | IP_Port ip_port; | ||
49 | |||
50 | } groupchat_nodes; | ||
51 | |||
52 | typedef 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 | |||
68 | static 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 | */ | ||
85 | static 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 | |||
113 | static 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 | */ | ||
146 | static 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 | |||
178 | static 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 | */ | ||
203 | static 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 | */ | ||
227 | static 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 | */ | ||
260 | static 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 | */ | ||
276 | static 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 | */ | ||
322 | int 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 | |||
337 | static 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 | |||
358 | static 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 | |||
385 | static 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 | |||
407 | static 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 | |||
425 | static 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) | ||
478 | static void send_names_new_peer(Group_Chat *chat); | ||
479 | |||
480 | static 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 | |||
578 | static 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 | |||
607 | int 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 | |||
645 | uint32_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 | |||
650 | uint32_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 | */ | ||
660 | static 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 | |||
668 | int 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 | |||
679 | uint32_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 | |||
685 | void 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 | |||
692 | void 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 | |||
699 | void 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 | |||
706 | uint32_t group_numpeers(const Group_Chat *chat) | ||
707 | { | ||
708 | return chat->numpeers; | ||
709 | } | ||
710 | |||
711 | uint32_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 | |||
723 | Group_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 | |||
742 | static 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 | |||
762 | static 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 | ||
771 | static 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 | ||
791 | static 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 | } | ||
796 | static 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 | |||
810 | void 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 | |||
820 | void 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 | |||
828 | void 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 | |||
833 | void 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 | |||
30 | typedef 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 | |||
47 | typedef 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 | |||
55 | typedef 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 | */ | ||
94 | int 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 | */ | ||
101 | void 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 | */ | ||
109 | void 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 | */ | ||
119 | typedef enum { | ||
120 | CHAT_CHANGE_PEER_ADD, | ||
121 | CHAT_CHANGE_PEER_DEL, | ||
122 | CHAT_CHANGE_PEER_NAME, | ||
123 | } CHAT_CHANGE; | ||
124 | |||
125 | void 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 | */ | ||
133 | uint32_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 | */ | ||
140 | uint32_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 | */ | ||
147 | int 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 | */ | ||
153 | uint32_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 | */ | ||
162 | Group_Chat *new_groupchat(Networking_Core *net); | ||
163 | |||
164 | |||
165 | /* Return the number of peers in the group chat. | ||
166 | */ | ||
167 | uint32_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 | */ | ||
175 | uint32_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 | */ | ||
182 | void kill_groupchat(Group_Chat *chat); | ||
183 | |||
184 | /* | ||
185 | * This is the main loop. | ||
186 | */ | ||
187 | void 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. */ | ||
192 | int handle_groupchatpacket(Group_Chat *chat, IP_Port source, const uint8_t *packet, uint32_t length); | ||
193 | |||
194 | |||
195 | void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, const uint8_t *client_id); | ||
196 | void 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 | |||
583 | void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *), void *userdata) | 583 | void 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 | |||
594 | int tox_add_groupchat(Tox *tox) | 594 | int 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) | |||
604 | int tox_del_groupchat(Tox *tox, int groupnumber) | 604 | int 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) | |||
616 | int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name) | 616 | int 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 | |||
625 | int tox_invite_friend(Tox *tox, int32_t friendnumber, int groupnumber) | 625 | int 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) | |||
635 | int tox_join_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *friend_group_public_key) | 635 | int 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 | |||
645 | int tox_group_message_send(Tox *tox, int groupnumber, const uint8_t *message, uint32_t length) | 645 | int 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 | |||
655 | int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint32_t length) | 655 | int 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 | |||
664 | int tox_group_number_peers(const Tox *tox, int groupnumber) | 664 | int 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 | |||
690 | uint32_t tox_count_chatlist(const Tox *tox) | 690 | uint32_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) | |||
701 | uint32_t tox_get_chatlist(const Tox *tox, int *out_list, uint32_t list_size) | 701 | uint32_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 | ||