summaryrefslogtreecommitdiff
path: root/toxcore/Messenger.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/Messenger.c')
-rw-r--r--toxcore/Messenger.c538
1 files changed, 23 insertions, 515 deletions
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}