summaryrefslogtreecommitdiff
path: root/toxcore/Messenger.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-12-06 22:51:17 -0500
committerirungentoo <irungentoo@gmail.com>2013-12-06 22:51:17 -0500
commit7cd43ecc76cd08c5c2c16b9f9169908ef4674762 (patch)
tree5b5ba5b61b5591222e2c4682d750c71469f1086c /toxcore/Messenger.c
parent1473126f9a459f31f4c33262a21987a3bb7dde65 (diff)
parent4207b73ca9432aeacfa72e5b7610cbb0ba9324c8 (diff)
Merge branch 'master' into harden
Diffstat (limited to 'toxcore/Messenger.c')
-rw-r--r--toxcore/Messenger.c339
1 files changed, 270 insertions, 69 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 08e3c70c..32234784 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -26,9 +26,11 @@
26#endif 26#endif
27 27
28#include "Messenger.h" 28#include "Messenger.h"
29#include "assoc.h"
29#include "network.h" 30#include "network.h"
30#include "util.h" 31#include "util.h"
31 32
33
32#define MIN(a,b) (((a)<(b))?(a):(b)) 34#define MIN(a,b) (((a)<(b))?(a):(b))
33 35
34 36
@@ -435,6 +437,10 @@ int setname(Messenger *m, uint8_t *name, uint16_t length)
435 for (i = 0; i < m->numfriends; ++i) 437 for (i = 0; i < m->numfriends; ++i)
436 m->friendlist[i].name_sent = 0; 438 m->friendlist[i].name_sent = 0;
437 439
440 for (i = 0; i < m->numchats; i++)
441 if (m->chats[i] != NULL)
442 set_nick(m->chats[i], name, length); /* TODO: remove this (group nicks should not be tied to the global one) */
443
438 return 0; 444 return 0;
439} 445}
440 446
@@ -701,6 +707,23 @@ int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint
701 707
702/**********GROUP CHATS************/ 708/**********GROUP CHATS************/
703 709
710/* return 1 if the groupnumber is not valid.
711 * return 0 if the groupnumber is valid.
712 */
713static uint8_t groupnumber_not_valid(Messenger *m, int groupnumber)
714{
715 if ((unsigned int)groupnumber >= m->numchats)
716 return 1;
717
718 if (m->chats == NULL)
719 return 1;
720
721 if (m->chats[groupnumber] == NULL)
722 return 1;
723 return 0;
724}
725
726
704/* returns valid ip port of connected friend on success 727/* returns valid ip port of connected friend on success
705 * returns zeroed out IP_Port on failure 728 * returns zeroed out IP_Port on failure
706 */ 729 */
@@ -728,8 +751,9 @@ static int group_num(Messenger *m, uint8_t *group_public_key)
728 uint32_t i; 751 uint32_t i;
729 752
730 for (i = 0; i < m->numchats; ++i) { 753 for (i = 0; i < m->numchats; ++i) {
731 if (id_equal(m->chats[i]->self_public_key, group_public_key)) 754 if (m->chats[i] != NULL)
732 return i; 755 if (id_equal(m->chats[i]->self_public_key, group_public_key))
756 return i;
733 } 757 }
734 758
735 return -1; 759 return -1;
@@ -755,20 +779,51 @@ void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int,
755 m->group_message = function; 779 m->group_message = function;
756 m->group_message_userdata = userdata; 780 m->group_message_userdata = userdata;
757} 781}
758static void group_message_function(Group_Chat *chat, int peer_number, uint8_t *message, uint16_t length, void *userdata) 782
783/* Set callback function for peer name list changes.
784 *
785 * It gets called every time the name list changes(new peer/name, deleted peer)
786 * Function(Tox *tox, int groupnumber, void *userdata)
787 */
788void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *), void *userdata)
759{ 789{
760 Messenger *m = userdata; 790 m->group_namelistchange = function;
761 uint32_t i; 791 m->group_namelistchange_userdata = userdata;
792}
762 793
794static int get_chat_num(Messenger *m, Group_Chat *chat)
795{
796 uint32_t i;
763 for (i = 0; i < m->numchats; ++i) { //TODO: remove this 797 for (i = 0; i < m->numchats; ++i) { //TODO: remove this
764 if (m->chats[i] == chat) 798 if (m->chats[i] == chat)
765 break; 799 return i;
766 } 800 }
801 return -1;
802}
803
804static void group_message_function(Group_Chat *chat, int peer_number, uint8_t *message, uint16_t length, void *userdata)
805{
806 Messenger *m = userdata;
807 int i = get_chat_num(m, chat);
808 if (i == -1)
809 return;
767 810
768 if (m->group_message) 811 if (m->group_message)
769 (*m->group_message)(m, i, peer_number, message, length, m->group_message_userdata); 812 (*m->group_message)(m, i, peer_number, message, length, m->group_message_userdata);
770} 813}
771 814
815static void group_namelistchange_function(Group_Chat *chat, int peer, uint8_t change, void *userdata)
816{
817 Messenger *m = userdata;
818 int i = get_chat_num(m, chat);
819 if (i == -1)
820 return;
821
822 if (m->group_namelistchange)
823 (*m->group_namelistchange)(m, i, peer, change, m->group_namelistchange_userdata);
824}
825
826
772/* Creates a new groupchat and puts it in the chats array. 827/* Creates a new groupchat and puts it in the chats array.
773 * 828 *
774 * return group number on success. 829 * return group number on success.
@@ -786,6 +841,9 @@ int add_groupchat(Messenger *m)
786 return -1; 841 return -1;
787 842
788 callback_groupmessage(newchat, &group_message_function, m); 843 callback_groupmessage(newchat, &group_message_function, m);
844 callback_namelistchange(newchat, &group_namelistchange_function, m);
845 /* TODO: remove this (group nicks should not be tied to the global one) */
846 set_nick(newchat, m->name, m->name_length);
789 m->chats[i] = newchat; 847 m->chats[i] = newchat;
790 return i; 848 return i;
791 } 849 }
@@ -804,6 +862,9 @@ int add_groupchat(Messenger *m)
804 862
805 m->chats = temp; 863 m->chats = temp;
806 callback_groupmessage(temp[m->numchats], &group_message_function, m); 864 callback_groupmessage(temp[m->numchats], &group_message_function, m);
865 callback_namelistchange(temp[m->numchats], &group_namelistchange_function, m);
866 /* TODO: remove this (group nicks should not be tied to the global one) */
867 set_nick(temp[m->numchats], m->name, m->name_length);
807 ++m->numchats; 868 ++m->numchats;
808 return (m->numchats - 1); 869 return (m->numchats - 1);
809} 870}
@@ -953,6 +1014,7 @@ int join_groupchat(Messenger *m, int friendnumber, uint8_t *friend_group_public_
953 return -1; 1014 return -1;
954} 1015}
955 1016
1017
956/* send a group message 1018/* send a group message
957 * return 0 on success 1019 * return 0 on success
958 * return -1 on failure 1020 * return -1 on failure
@@ -960,13 +1022,7 @@ int join_groupchat(Messenger *m, int friendnumber, uint8_t *friend_group_public_
960 1022
961int group_message_send(Messenger *m, int groupnumber, uint8_t *message, uint32_t length) 1023int group_message_send(Messenger *m, int groupnumber, uint8_t *message, uint32_t length)
962{ 1024{
963 if ((unsigned int)groupnumber >= m->numchats) 1025 if (groupnumber_not_valid(m, groupnumber))
964 return -1;
965
966 if (m->chats == NULL)
967 return -1;
968
969 if (m->chats[groupnumber] == NULL)
970 return -1; 1026 return -1;
971 1027
972 if (group_sendmessage(m->chats[groupnumber], message, length) > 0) 1028 if (group_sendmessage(m->chats[groupnumber], message, length) > 0)
@@ -975,6 +1031,33 @@ int group_message_send(Messenger *m, int groupnumber, uint8_t *message, uint32_t
975 return -1; 1031 return -1;
976} 1032}
977 1033
1034/* Return the number of peers in the group chat on success.
1035 * return -1 on failure
1036 */
1037int group_number_peers(Messenger *m, int groupnumber)
1038{
1039 if (groupnumber_not_valid(m, groupnumber))
1040 return -1;
1041
1042 return group_numpeers(m->chats[groupnumber]);
1043}
1044
1045/* List all the peers in the group chat.
1046 *
1047 * Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
1048 *
1049 * returns the number of peers on success.
1050 *
1051 * return -1 on failure.
1052 */
1053int group_names(Messenger *m, int groupnumber, uint8_t names[][MAX_NICK_BYTES], uint16_t length)
1054{
1055 if (groupnumber_not_valid(m, groupnumber))
1056 return -1;
1057
1058 return group_client_names(m->chats[groupnumber], names, length);
1059}
1060
978static int handle_group(void *object, IP_Port source, uint8_t *packet, uint32_t length) 1061static int handle_group(void *object, IP_Port source, uint8_t *packet, uint32_t length)
979{ 1062{
980 Messenger *m = object; 1063 Messenger *m = object;
@@ -1078,7 +1161,7 @@ int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_
1078int new_filesender(Messenger *m, int friendnumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length) 1161int new_filesender(Messenger *m, int friendnumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length)
1079{ 1162{
1080 if (friend_not_valid(m, friendnumber)) 1163 if (friend_not_valid(m, friendnumber))
1081 return 0; 1164 return -1;
1082 1165
1083 uint32_t i; 1166 uint32_t i;
1084 1167
@@ -1102,28 +1185,28 @@ int new_filesender(Messenger *m, int friendnumber, uint64_t filesize, uint8_t *f
1102/* Send a file control request. 1185/* Send a file control request.
1103 * send_receive is 0 if we want the control packet to target a sending file, 1 if it targets a receiving file. 1186 * send_receive is 0 if we want the control packet to target a sending file, 1 if it targets a receiving file.
1104 * 1187 *
1105 * return 1 on success 1188 * return 0 on success
1106 * return 0 on failure 1189 * return -1 on failure
1107 */ 1190 */
1108int file_control(Messenger *m, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, 1191int file_control(Messenger *m, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
1109 uint8_t *data, uint16_t length) 1192 uint8_t *data, uint16_t length)
1110{ 1193{
1111 if (length > MAX_DATA_SIZE - 3) 1194 if (length > MAX_DATA_SIZE - 3)
1112 return 0; 1195 return -1;
1113 1196
1114 if (friend_not_valid(m, friendnumber)) 1197 if (friend_not_valid(m, friendnumber))
1115 return 0; 1198 return -1;
1116 1199
1117 if (send_receive == 1) { 1200 if (send_receive == 1) {
1118 if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE) 1201 if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE)
1119 return 0; 1202 return -1;
1120 } else { 1203 } else {
1121 if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE) 1204 if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE)
1122 return 0; 1205 return -1;
1123 } 1206 }
1124 1207
1125 if (send_receive > 1) 1208 if (send_receive > 1)
1126 return 0; 1209 return -1;
1127 1210
1128 uint8_t packet[MAX_DATA_SIZE]; 1211 uint8_t packet[MAX_DATA_SIZE];
1129 packet[0] = send_receive; 1212 packet[0] = send_receive;
@@ -1133,7 +1216,7 @@ int file_control(Messenger *m, int friendnumber, uint8_t send_receive, uint8_t f
1133 1216
1134 if (message_id == FILECONTROL_RESUME_BROKEN) { 1217 if (message_id == FILECONTROL_RESUME_BROKEN) {
1135 if (length != sizeof(uint64_t)) 1218 if (length != sizeof(uint64_t))
1136 return 0; 1219 return -1;
1137 1220
1138 uint8_t remaining[sizeof(uint64_t)]; 1221 uint8_t remaining[sizeof(uint64_t)];
1139 memcpy(remaining, data, sizeof(uint64_t)); 1222 memcpy(remaining, data, sizeof(uint64_t));
@@ -1181,32 +1264,32 @@ int file_control(Messenger *m, int friendnumber, uint8_t send_receive, uint8_t f
1181 break; 1264 break;
1182 } 1265 }
1183 1266
1184 return 1;
1185 } else {
1186 return 0; 1267 return 0;
1268 } else {
1269 return -1;
1187 } 1270 }
1188} 1271}
1189 1272
1190#define MIN_SLOTS_FREE 4 1273#define MIN_SLOTS_FREE 4
1191/* Send file data. 1274/* Send file data.
1192 * 1275 *
1193 * return 1 on success 1276 * return 0 on success
1194 * return 0 on failure 1277 * return -1 on failure
1195 */ 1278 */
1196int file_data(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length) 1279int file_data(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length)
1197{ 1280{
1198 if (length > MAX_DATA_SIZE - 1) 1281 if (length > MAX_DATA_SIZE - 1)
1199 return 0; 1282 return -1;
1200 1283
1201 if (friend_not_valid(m, friendnumber)) 1284 if (friend_not_valid(m, friendnumber))
1202 return 0; 1285 return -1;
1203 1286
1204 if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_TRANSFERRING) 1287 if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_TRANSFERRING)
1205 return 0; 1288 return -1;
1206 1289
1207 /* Prevent file sending from filling up the entire buffer preventing messages from being sent. */ 1290 /* Prevent file sending from filling up the entire buffer preventing messages from being sent. */
1208 if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) 1291 if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE)
1209 return 0; 1292 return -1;
1210 1293
1211 uint8_t packet[MAX_DATA_SIZE]; 1294 uint8_t packet[MAX_DATA_SIZE];
1212 packet[0] = filenumber; 1295 packet[0] = filenumber;
@@ -1214,10 +1297,10 @@ int file_data(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t *data,
1214 1297
1215 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_DATA, packet, length + 1)) { 1298 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_DATA, packet, length + 1)) {
1216 m->friendlist[friendnumber].file_sending[filenumber].transferred += length; 1299 m->friendlist[friendnumber].file_sending[filenumber].transferred += length;
1217 return 1; 1300 return 0;
1218 } 1301 }
1219 1302
1220 return 0; 1303 return -1;
1221 1304
1222} 1305}
1223 1306
@@ -1371,6 +1454,17 @@ int m_msi_packet(Messenger *m, int friendnumber, uint8_t *data, uint16_t length)
1371 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length); 1454 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length);
1372} 1455}
1373 1456
1457/* Function to filter out some friend requests*/
1458static int friend_already_added(uint8_t *client_id, void *data)
1459{
1460 Messenger *m = data;
1461
1462 if (getfriend_id(m, client_id) == -1)
1463 return 0;
1464
1465 return -1;
1466}
1467
1374/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ 1468/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
1375static void LANdiscovery(Messenger *m) 1469static void LANdiscovery(Messenger *m)
1376{ 1470{
@@ -1420,6 +1514,8 @@ Messenger *new_messenger(uint8_t ipv6enabled)
1420 friendreq_init(&(m->fr), m->net_crypto); 1514 friendreq_init(&(m->fr), m->net_crypto);
1421 LANdiscovery_init(m->dht); 1515 LANdiscovery_init(m->dht);
1422 set_nospam(&(m->fr), random_int()); 1516 set_nospam(&(m->fr), random_int());
1517 set_filter_function(&(m->fr), &friend_already_added, m);
1518
1423 networking_registerhandler(m->net, NET_PACKET_GROUP_CHATS, &handle_group, m); 1519 networking_registerhandler(m->net, NET_PACKET_GROUP_CHATS, &handle_group, m);
1424 1520
1425 return m; 1521 return m;
@@ -1431,6 +1527,10 @@ void kill_messenger(Messenger *m)
1431 /* FIXME TODO: ideally cleanupMessenger will mirror initMessenger. 1527 /* FIXME TODO: ideally cleanupMessenger will mirror initMessenger.
1432 * This requires the other modules to expose cleanup functions. 1528 * This requires the other modules to expose cleanup functions.
1433 */ 1529 */
1530 uint32_t i, numchats = m->numchats;
1531 for (i = 0; i < numchats; ++i)
1532 del_groupchat(m, i);
1533
1434 kill_DHT(m->dht); 1534 kill_DHT(m->dht);
1435 kill_net_crypto(m->net_crypto); 1535 kill_net_crypto(m->net_crypto);
1436 kill_networking(m->net); 1536 kill_networking(m->net);
@@ -1438,6 +1538,24 @@ void kill_messenger(Messenger *m)
1438 free(m); 1538 free(m);
1439} 1539}
1440 1540
1541/* Check for and handle a timed-out friend request. If the request has
1542 * timed-out then the friend status is set back to FRIEND_ADDED.
1543 * i: friendlist index of the timed-out friend
1544 * t: time
1545 */
1546static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t)
1547{
1548 Friend *f = &m->friendlist[i];
1549
1550 if (f->friendrequest_lastsent + f->friendrequest_timeout < t) {
1551 set_friend_status(m, i, FRIEND_ADDED);
1552 /* Double the default timeout everytime if friendrequest is assumed
1553 * to have been sent unsuccessfully.
1554 */
1555 f->friendrequest_timeout *= 2;
1556 }
1557}
1558
1441/* TODO: Make this function not suck. */ 1559/* TODO: Make this function not suck. */
1442void do_friends(Messenger *m) 1560void do_friends(Messenger *m)
1443{ 1561{
@@ -1465,13 +1583,7 @@ void do_friends(Messenger *m)
1465 /* If we didn't connect to friend after successfully sending him a friend request the request is deemed 1583 /* If we didn't connect to friend after successfully sending him a friend request the request is deemed
1466 * unsuccessful so we set the status back to FRIEND_ADDED and try again. 1584 * unsuccessful so we set the status back to FRIEND_ADDED and try again.
1467 */ 1585 */
1468 if (m->friendlist[i].friendrequest_lastsent + m->friendlist[i].friendrequest_timeout < temp_time) { 1586 check_friend_request_timed_out(m, i, temp_time);
1469 set_friend_status(m, i, FRIEND_ADDED);
1470 /* Double the default timeout everytime if friendrequest is assumed to have been
1471 * sent unsuccessfully.
1472 */
1473 m->friendlist[i].friendrequest_timeout *= 2;
1474 }
1475 } 1587 }
1476 1588
1477 IP_Port friendip; 1589 IP_Port friendip;
@@ -1539,12 +1651,15 @@ void do_friends(Messenger *m)
1539 if (data_length >= MAX_NAME_LENGTH || data_length == 0) 1651 if (data_length >= MAX_NAME_LENGTH || data_length == 0)
1540 break; 1652 break;
1541 1653
1542 memcpy(m->friendlist[i].name, data, data_length); 1654 /* Make sure the NULL terminator is present. */
1543 m->friendlist[i].name_length = data_length; 1655 data[data_length - 1] = 0;
1544 m->friendlist[i].name[data_length - 1] = 0; /* Make sure the NULL terminator is present. */
1545 1656
1657 /* inform of namechange before we overwrite the old name */
1546 if (m->friend_namechange) 1658 if (m->friend_namechange)
1547 m->friend_namechange(m, i, m->friendlist[i].name, data_length, m->friend_namechange_userdata); 1659 m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata);
1660
1661 memcpy(m->friendlist[i].name, data, data_length);
1662 m->friendlist[i].name_length = data_length;
1548 1663
1549 break; 1664 break;
1550 } 1665 }
@@ -1658,7 +1773,7 @@ void do_friends(Messenger *m)
1658 break; 1773 break;
1659 1774
1660 group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); 1775 group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES);
1661 1776 chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES);
1662 break; 1777 break;
1663 } 1778 }
1664 1779
@@ -1808,6 +1923,18 @@ void do_messenger(Messenger *m)
1808 1923
1809 if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { 1924 if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
1810 loglog(" = = = = = = = = \n"); 1925 loglog(" = = = = = = = = \n");
1926 Assoc_status(m->dht->assoc);
1927
1928 if (m->numchats > 0) {
1929 size_t c;
1930
1931 for (c = 0; c < m->numchats; c++) {
1932 loglog("---------------- \n");
1933 Assoc_status(m->chats[c]->assoc);
1934 }
1935 }
1936
1937 loglog(" = = = = = = = = \n");
1811 1938
1812 lastdump = unix_time(); 1939 lastdump = unix_time();
1813 uint32_t client, last_pinged; 1940 uint32_t client, last_pinged;
@@ -1833,7 +1960,30 @@ void do_messenger(Messenger *m)
1833 1960
1834 loglog(" = = = = = = = = \n"); 1961 loglog(" = = = = = = = = \n");
1835 1962
1836 uint32_t num_friends = MIN(m->numfriends, m->dht->num_friends); 1963 uint32_t friend, dhtfriend;
1964
1965 /* dht contains additional "friends" (requests) */
1966 uint32_t num_dhtfriends = m->dht->num_friends;
1967 int32_t m2dht[num_dhtfriends];
1968 int32_t dht2m[num_dhtfriends];
1969
1970 for (friend = 0; friend < num_dhtfriends; friend++) {
1971 m2dht[friend] = -1;
1972 dht2m[friend] = -1;
1973
1974 if (friend >= m->numfriends)
1975 continue;
1976
1977 for (dhtfriend = 0; dhtfriend < m->dht->num_friends; dhtfriend++)
1978 if (id_equal(m->friendlist[friend].client_id, m->dht->friends_list[dhtfriend].client_id)) {
1979 m2dht[friend] = dhtfriend;
1980 break;
1981 }
1982 }
1983
1984 for (friend = 0; friend < num_dhtfriends; friend++)
1985 if (m2dht[friend] >= 0)
1986 dht2m[m2dht[friend]] = friend;
1837 1987
1838 if (m->numfriends != m->dht->num_friends) { 1988 if (m->numfriends != m->dht->num_friends) {
1839 sprintf(logbuffer, "Friend num in DHT %u != friend num in msger %u\n", 1989 sprintf(logbuffer, "Friend num in DHT %u != friend num in msger %u\n",
@@ -1841,33 +1991,33 @@ void do_messenger(Messenger *m)
1841 loglog(logbuffer); 1991 loglog(logbuffer);
1842 } 1992 }
1843 1993
1844 uint32_t friend, ping_lastrecv; 1994 uint32_t ping_lastrecv;
1845 1995 Friend *msgfptr;
1846 for (friend = 0; friend < num_friends; friend++) { 1996 DHT_Friend *dhtfptr;
1847 Friend *msgfptr = &m->friendlist[friend];
1848 DHT_Friend *dhtfptr = &m->dht->friends_list[friend];
1849 1997
1850 if (memcmp(msgfptr->client_id, dhtfptr->client_id, CLIENT_ID_SIZE)) { 1998 for (friend = 0; friend < num_dhtfriends; friend++) {
1851 if (sizeof(logbuffer) > 2 * CLIENT_ID_SIZE + 64) { 1999 if (dht2m[friend] >= 0)
1852 sprintf(logbuffer, "F[%2u] ID(m) %s != ID(d) ", friend, 2000 msgfptr = &m->friendlist[dht2m[friend]];
1853 ID2String(msgfptr->client_id)); 2001 else
1854 strcat(logbuffer + strlen(logbuffer), ID2String(dhtfptr->client_id)); 2002 msgfptr = NULL;
1855 strcat(logbuffer + strlen(logbuffer), "\n");
1856 } else
1857 sprintf(logbuffer, "F[%2u] ID(m) != ID(d) ", friend);
1858 2003
1859 loglog(logbuffer); 2004 dhtfptr = &m->dht->friends_list[friend];
1860 }
1861 2005
1862 ping_lastrecv = lastdump - msgfptr->ping_lastrecv; 2006 if (msgfptr) {
2007 ping_lastrecv = lastdump - msgfptr->ping_lastrecv;
1863 2008
1864 if (ping_lastrecv > 999) 2009 if (ping_lastrecv > 999)
1865 ping_lastrecv = 999; 2010 ping_lastrecv = 999;
1866 2011
1867 snprintf(logbuffer, sizeof(logbuffer), "F[%2u] <%s> %02u [%03u] %s\n", 2012 snprintf(logbuffer, sizeof(logbuffer), "F[%2u:%2u] <%s> %02i [%03u] %s\n",
1868 friend, msgfptr->name, msgfptr->crypt_connection_id, 2013 dht2m[friend], friend, msgfptr->name, msgfptr->crypt_connection_id,
1869 ping_lastrecv, ID2String(msgfptr->client_id)); 2014 ping_lastrecv, ID2String(msgfptr->client_id));
1870 loglog(logbuffer); 2015 loglog(logbuffer);
2016 } else {
2017 snprintf(logbuffer, sizeof(logbuffer), "F[--:%2u] %s\n",
2018 friend, ID2String(dhtfptr->client_id));
2019 loglog(logbuffer);
2020 }
1871 2021
1872 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { 2022 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) {
1873 Client_data *cptr = &dhtfptr->client_list[client]; 2023 Client_data *cptr = &dhtfptr->client_list[client];
@@ -1995,6 +2145,9 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le
1995 if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) { 2145 if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) {
1996 set_nospam(&(m->fr), *(uint32_t *)data); 2146 set_nospam(&(m->fr), *(uint32_t *)data);
1997 load_keys(m->net_crypto, &data[sizeof(uint32_t)]); 2147 load_keys(m->net_crypto, &data[sizeof(uint32_t)]);
2148
2149 if (m->dht->assoc)
2150 Assoc_self_client_id_changed(m->dht->assoc, m->net_crypto->self_public_key);
1998 } else 2151 } else
1999 return -1; /* critical */ 2152 return -1; /* critical */
2000 2153
@@ -2100,12 +2253,12 @@ uint32_t copy_friendlist(Messenger *m, int *out_list, uint32_t list_size)
2100 uint32_t ret = 0; 2253 uint32_t ret = 0;
2101 2254
2102 for (i = 0; i < m->numfriends; i++) { 2255 for (i = 0; i < m->numfriends; i++) {
2103 if (i >= list_size) { 2256 if (ret >= list_size) {
2104 break; /* Abandon ship */ 2257 break; /* Abandon ship */
2105 } 2258 }
2106 2259
2107 if (m->friendlist[i].status > 0) { 2260 if (m->friendlist[i].status > 0) {
2108 out_list[i] = i; 2261 out_list[ret] = i;
2109 ret++; 2262 ret++;
2110 } 2263 }
2111 } 2264 }
@@ -2146,3 +2299,51 @@ int get_friendlist(Messenger *m, int **out_list, uint32_t *out_list_length)
2146 return 0; 2299 return 0;
2147} 2300}
2148 2301
2302/* Return the number of chats in the instance m.
2303 * You should use this to determine how much memory to allocate
2304 * for copy_chatlist. */
2305uint32_t count_chatlist(Messenger *m)
2306{
2307 uint32_t ret = 0;
2308 uint32_t i;
2309
2310 for (i = 0; i < m->numchats; i++) {
2311 if (m->chats[i]) {
2312 ret++;
2313 }
2314 }
2315
2316 return ret;
2317}
2318
2319/* Copy a list of valid chat IDs into the array out_list.
2320 * If out_list is NULL, returns 0.
2321 * Otherwise, returns the number of elements copied.
2322 * If the array was too small, the contents
2323 * of out_list will be truncated to list_size. */
2324uint32_t copy_chatlist(Messenger *m, int *out_list, uint32_t list_size)
2325{
2326 if (!out_list)
2327 return 0;
2328
2329 if (m->numchats == 0) {
2330 return 0;
2331 }
2332
2333 uint32_t i;
2334 uint32_t ret = 0;
2335
2336 for (i = 0; i < m->numchats; i++) {
2337 if (ret >= list_size) {
2338 break; /* Abandon ship */
2339 }
2340
2341 if (m->chats[i]) {
2342 out_list[ret] = i;
2343 ret++;
2344 }
2345 }
2346
2347 return ret;
2348}
2349