summaryrefslogtreecommitdiff
path: root/toxcore/Messenger.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/Messenger.c')
-rw-r--r--toxcore/Messenger.c719
1 files changed, 42 insertions, 677 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 99b95f67..c3f85beb 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -153,20 +153,9 @@ void getaddress(const Messenger *m, uint8_t *address)
153 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum)); 153 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum));
154} 154}
155 155
156/* callback for recv TCP relay nodes. */ 156static int handle_status(void *object, int i, uint8_t status);
157static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key) 157static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len);
158{ 158static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length);
159 Messenger *m = object;
160
161 if (friend_not_valid(m, number))
162 return -1;
163
164 if (m->friendlist[number].crypt_connection_id != -1) {
165 return add_tcp_relay_peer(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port, public_key);
166 } else {
167 return add_tcp_relay(m->net_crypto, ip_port, public_key);
168 }
169}
170 159
171/* 160/*
172 * Add a friend. 161 * Add a friend.
@@ -230,18 +219,17 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
230 219
231 memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); 220 memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
232 221
233 int32_t onion_friendnum = onion_addfriend(m->onion_c, client_id); 222 int friendcon_id = new_friend_connection(m->fr_c, client_id);
234 223
235 if (onion_friendnum == -1) 224 if (friendcon_id == -1)
236 return FAERR_UNKNOWN; 225 return -1;
237 226
238 uint32_t i; 227 uint32_t i;
239 228
240 for (i = 0; i <= m->numfriends; ++i) { 229 for (i = 0; i <= m->numfriends; ++i) {
241 if (m->friendlist[i].status == NOFRIEND) { 230 if (m->friendlist[i].status == NOFRIEND) {
242 m->friendlist[i].onion_friendnum = onion_friendnum;
243 m->friendlist[i].status = FRIEND_ADDED; 231 m->friendlist[i].status = FRIEND_ADDED;
244 m->friendlist[i].crypt_connection_id = -1; 232 m->friendlist[i].friendcon_id = friendcon_id;
245 m->friendlist[i].friendrequest_lastsent = 0; 233 m->friendlist[i].friendrequest_lastsent = 0;
246 m->friendlist[i].friendrequest_timeout = FRIENDREQUEST_TIMEOUT; 234 m->friendlist[i].friendrequest_timeout = FRIENDREQUEST_TIMEOUT;
247 id_copy(m->friendlist[i].client_id, client_id); 235 id_copy(m->friendlist[i].client_id, client_id);
@@ -258,7 +246,9 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
258 m->friendlist[i].message_id = 0; 246 m->friendlist[i].message_id = 0;
259 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ 247 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
260 memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); 248 memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
261 recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); 249 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
250 &handle_custom_lossy_packet, m, i);
251
262 252
263 if (m->numfriends == i) 253 if (m->numfriends == i)
264 ++m->numfriends; 254 ++m->numfriends;
@@ -287,18 +277,17 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id)
287 277
288 memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); 278 memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
289 279
290 int32_t onion_friendnum = onion_addfriend(m->onion_c, client_id); 280 int friendcon_id = new_friend_connection(m->fr_c, client_id);
291 281
292 if (onion_friendnum == -1) 282 if (friendcon_id == -1)
293 return -1; 283 return -1;
294 284
295 uint32_t i; 285 uint32_t i;
296 286
297 for (i = 0; i <= m->numfriends; ++i) { 287 for (i = 0; i <= m->numfriends; ++i) {
298 if (m->friendlist[i].status == NOFRIEND) { 288 if (m->friendlist[i].status == NOFRIEND) {
299 m->friendlist[i].onion_friendnum = onion_friendnum;
300 m->friendlist[i].status = FRIEND_CONFIRMED; 289 m->friendlist[i].status = FRIEND_CONFIRMED;
301 m->friendlist[i].crypt_connection_id = -1; 290 m->friendlist[i].friendcon_id = friendcon_id;
302 m->friendlist[i].friendrequest_lastsent = 0; 291 m->friendlist[i].friendrequest_lastsent = 0;
303 id_copy(m->friendlist[i].client_id, client_id); 292 id_copy(m->friendlist[i].client_id, client_id);
304 m->friendlist[i].statusmessage = calloc(1, 1); 293 m->friendlist[i].statusmessage = calloc(1, 1);
@@ -311,7 +300,8 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id)
311 m->friendlist[i].is_typing = 0; 300 m->friendlist[i].is_typing = 0;
312 m->friendlist[i].message_id = 0; 301 m->friendlist[i].message_id = 0;
313 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ 302 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
314 recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); 303 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
304 &handle_custom_lossy_packet, m, i);
315 305
316 if (m->numfriends == i) 306 if (m->numfriends == i)
317 ++m->numfriends; 307 ++m->numfriends;
@@ -336,11 +326,11 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
336 if (m->friendlist[friendnumber].status == FRIEND_ONLINE) 326 if (m->friendlist[friendnumber].status == FRIEND_ONLINE)
337 remove_online_friend(m, friendnumber); 327 remove_online_friend(m, friendnumber);
338 328
339 onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum);
340 crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id);
341 free(m->friendlist[friendnumber].statusmessage); 329 free(m->friendlist[friendnumber].statusmessage);
342 free(m->friendlist[friendnumber].avatar_recv_data); 330 free(m->friendlist[friendnumber].avatar_recv_data);
343 remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id); 331 remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id);
332 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
333 kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
344 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); 334 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
345 uint32_t i; 335 uint32_t i;
346 336
@@ -492,10 +482,6 @@ int setname(Messenger *m, const uint8_t *name, uint16_t length)
492 for (i = 0; i < m->numfriends; ++i) 482 for (i = 0; i < m->numfriends; ++i)
493 m->friendlist[i].name_sent = 0; 483 m->friendlist[i].name_sent = 0;
494 484
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; 485 return 0;
500} 486}
501 487
@@ -811,16 +797,6 @@ static int send_user_istyping(const Messenger *m, int32_t friendnumber, uint8_t
811 return write_cryptpacket_id(m, friendnumber, PACKET_ID_TYPING, &typing, sizeof(typing), 0); 797 return write_cryptpacket_id(m, friendnumber, PACKET_ID_TYPING, &typing, sizeof(typing), 0);
812} 798}
813 799
814static int send_ping(const Messenger *m, int32_t friendnumber)
815{
816 int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_ALIVE, 0, 0, 0);
817
818 if (ret == 1)
819 m->friendlist[friendnumber].ping_lastsent = unix_time();
820
821 return ret;
822}
823
824static int send_relays(const Messenger *m, int32_t friendnumber) 800static int send_relays(const Messenger *m, int32_t friendnumber)
825{ 801{
826 Node_format nodes[MAX_SHARED_RELAYS]; 802 Node_format nodes[MAX_SHARED_RELAYS];
@@ -967,8 +943,6 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui
967 const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE; 943 const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE;
968 const uint8_t is_online = status == FRIEND_ONLINE; 944 const uint8_t is_online = status == FRIEND_ONLINE;
969 945
970 onion_set_friend_online(m->onion_c, m->friendlist[friendnumber].onion_friendnum, is_online);
971
972 if (is_online != was_online) { 946 if (is_online != was_online) {
973 if (was_online) { 947 if (was_online) {
974 break_files(m, friendnumber); 948 break_files(m, friendnumber);
@@ -1009,464 +983,31 @@ static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_
1009 if (length != 0) 983 if (length != 0)
1010 memcpy(packet + 1, data, length); 984 memcpy(packet + 1, data, length);
1011 985
1012 return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1, 986 return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1013 congestion_control) != -1; 987 m->friendlist[friendnumber].friendcon_id), packet, length + 1, congestion_control) != -1;
1014} 988}
1015 989
1016/**********GROUP CHATS************/ 990/**********GROUP CHATS************/
1017 991
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 992
1076/* Set the callback for group invites. 993/* Set the callback for group invites.
1077 * 994 *
1078 * Function(Messenger *m, int32_t friendnumber, uint8_t *group_public_key, void *userdata) 995 * Function(Messenger *m, int32_t friendnumber, uint8_t *data, uint16_t length)
1079 */ 996 */
1080void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, void *), 997void m_callback_group_invite(Messenger *m, void (*function)(Messenger *m, int32_t, const uint8_t *, uint16_t))
1081 void *userdata)
1082{ 998{
1083 m->group_invite = function; 999 m->group_invite = function;
1084 m->group_invite_userdata = userdata;
1085} 1000}
1086 1001
1087/* Set the callback for group messages.
1088 *
1089 * Function(Tox *tox, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
1090 */
1091void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int, int, const uint8_t *, uint16_t, void *),
1092 void *userdata)
1093{
1094 m->group_message = function;
1095 m->group_message_userdata = userdata;
1096}
1097 1002
1098/* Set the callback for group actions. 1003/* Send a group invite packet.
1099 * 1004 *
1100 * Function(Tox *tox, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata) 1005 * return 1 on success
1101 */ 1006 * 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 */
1414int group_number_peers(const Messenger *m, int groupnumber)
1415{
1416 if (groupnumber_not_valid(m, groupnumber))
1417 return -1;
1418
1419 return group_numpeers(m->chats[groupnumber]);
1420}
1421
1422/* List all the peers in the group chat.
1423 *
1424 * Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
1425 *
1426 * Copies the lengths of the names to lengths[length]
1427 *
1428 * returns the number of peers on success.
1429 *
1430 * return -1 on failure.
1431 */ 1007 */
1432int group_names(const Messenger *m, int groupnumber, uint8_t names[][MAX_NICK_BYTES], uint16_t lengths[], 1008int send_group_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
1433 uint16_t length)
1434{ 1009{
1435 if (groupnumber_not_valid(m, groupnumber)) 1010 return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, data, length, 0);
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{
1443 Messenger *m = object;
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}
1461
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} 1011}
1471 1012
1472/****************FILE SENDING*****************/ 1013/****************FILE SENDING*****************/
@@ -1669,8 +1210,9 @@ int file_data(const Messenger *m, int32_t friendnumber, uint8_t filenumber, cons
1669 if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_TRANSFERRING) 1210 if (m->friendlist[friendnumber].file_sending[filenumber].status != FILESTATUS_TRANSFERRING)
1670 return -1; 1211 return -1;
1671 1212
1672 /* Prevent file sending from filling up the entire buffer preventing messages from being sent. */ 1213 /* Prevent file sending from filling up the entire buffer preventing messages from being sent. TODO: remove */
1673 if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) 1214 if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1215 m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE)
1674 return -1; 1216 return -1;
1675 1217
1676 uint8_t packet[MAX_CRYPTO_DATA_SIZE]; 1218 uint8_t packet[MAX_CRYPTO_DATA_SIZE];
@@ -1876,10 +1418,8 @@ int send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uin
1876 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 1418 if (m->friendlist[friendnumber].status != FRIEND_ONLINE)
1877 return -1; 1419 return -1;
1878 1420
1879 if (m->friendlist[friendnumber].crypt_connection_id == -1) 1421 return send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1880 return -1; 1422 m->friendlist[friendnumber].friendcon_id), data, length);
1881
1882 return send_lossy_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, data, length);
1883} 1423}
1884 1424
1885static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length) 1425static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length)
@@ -1937,10 +1477,8 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const
1937 if (m->friendlist[friendnumber].status != FRIEND_ONLINE) 1477 if (m->friendlist[friendnumber].status != FRIEND_ONLINE)
1938 return -1; 1478 return -1;
1939 1479
1940 if (m->friendlist[friendnumber].crypt_connection_id == -1) 1480 if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
1941 return -1; 1481 m->friendlist[friendnumber].friendcon_id), data, length, 1) == -1) {
1942
1943 if (write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, data, length, 1) == -1) {
1944 return -1; 1482 return -1;
1945 } else { 1483 } else {
1946 return 0; 1484 return 0;
@@ -1967,31 +1505,6 @@ static void LANdiscovery(Messenger *m)
1967 } 1505 }
1968} 1506}
1969 1507
1970static int handle_status(void *object, int i, uint8_t status);
1971static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len);
1972
1973static int handle_new_connections(void *object, New_Connection *n_c)
1974{
1975 Messenger *m = object;
1976 int friend_id = getfriend_id(m, n_c->public_key);
1977
1978 if (friend_id != -1) {
1979 if (m->friendlist[friend_id].crypt_connection_id != -1)
1980 return -1;
1981
1982 int id = accept_crypto_connection(m->net_crypto, n_c);
1983 connection_status_handler(m->net_crypto, id, &handle_status, m, friend_id);
1984 connection_data_handler(m->net_crypto, id, &handle_packet, m, friend_id);
1985 connection_lossy_data_handler(m->net_crypto, id, &handle_custom_lossy_packet, m, friend_id);
1986 m->friendlist[friend_id].crypt_connection_id = id;
1987 set_friend_status(m, friend_id, FRIEND_CONFIRMED);
1988 return 0;
1989 }
1990
1991 return -1;
1992}
1993
1994
1995/* Run this at startup. */ 1508/* Run this at startup. */
1996Messenger *new_messenger(Messenger_Options *options) 1509Messenger *new_messenger(Messenger_Options *options)
1997{ 1510{
@@ -2038,13 +1551,13 @@ Messenger *new_messenger(Messenger_Options *options)
2038 return NULL; 1551 return NULL;
2039 } 1552 }
2040 1553
2041 new_connection_handler(m->net_crypto, &handle_new_connections, m);
2042
2043 m->onion = new_onion(m->dht); 1554 m->onion = new_onion(m->dht);
2044 m->onion_a = new_onion_announce(m->dht); 1555 m->onion_a = new_onion_announce(m->dht);
2045 m->onion_c = new_onion_client(m->net_crypto); 1556 m->onion_c = new_onion_client(m->net_crypto);
1557 m->fr_c = new_friend_connections(m->onion_c);
2046 1558
2047 if (!(m->onion && m->onion_a && m->onion_c)) { 1559 if (!(m->onion && m->onion_a && m->onion_c)) {
1560 kill_friend_connections(m->fr_c);
2048 kill_onion(m->onion); 1561 kill_onion(m->onion);
2049 kill_onion_announce(m->onion_a); 1562 kill_onion_announce(m->onion_a);
2050 kill_onion_client(m->onion_c); 1563 kill_onion_client(m->onion_c);
@@ -2061,22 +1574,15 @@ Messenger *new_messenger(Messenger_Options *options)
2061 set_nospam(&(m->fr), random_int()); 1574 set_nospam(&(m->fr), random_int());
2062 set_filter_function(&(m->fr), &friend_already_added, m); 1575 set_filter_function(&(m->fr), &friend_already_added, m);
2063 1576
2064 networking_registerhandler(m->net, NET_PACKET_GROUP_CHATS, &handle_group, m);
2065
2066 return m; 1577 return m;
2067} 1578}
2068 1579
2069/* Run this before closing shop. */ 1580/* Run this before closing shop. */
2070void kill_messenger(Messenger *m) 1581void kill_messenger(Messenger *m)
2071{ 1582{
2072 /* FIXME TODO: ideally cleanupMessenger will mirror initMessenger. 1583 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 1584
1585 kill_friend_connections(m->fr_c);
2080 kill_onion(m->onion); 1586 kill_onion(m->onion);
2081 kill_onion_announce(m->onion_a); 1587 kill_onion_announce(m->onion_a);
2082 kill_onion_client(m->onion_c); 1588 kill_onion_client(m->onion_c);
@@ -2124,8 +1630,6 @@ static int handle_status(void *object, int i, uint8_t status)
2124 m->friendlist[i].statusmessage_sent = 0; 1630 m->friendlist[i].statusmessage_sent = 0;
2125 m->friendlist[i].ping_lastrecv = temp_time; 1631 m->friendlist[i].ping_lastrecv = temp_time;
2126 } else { /* Went offline. */ 1632 } else { /* Went offline. */
2127 m->friendlist[i].crypt_connection_id = -1;
2128
2129 if (m->friendlist[i].status == FRIEND_ONLINE) { 1633 if (m->friendlist[i].status == FRIEND_ONLINE) {
2130 set_friend_status(m, i, FRIEND_CONFIRMED); 1634 set_friend_status(m, i, FRIEND_CONFIRMED);
2131 } 1635 }
@@ -2425,11 +1929,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2425 return -1; 1929 return -1;
2426 1930
2427 switch (packet_id) { 1931 switch (packet_id) {
2428 case PACKET_ID_ALIVE: {
2429 m->friendlist[i].ping_lastrecv = temp_time;
2430 break;
2431 }
2432
2433 case PACKET_ID_NICKNAME: { 1932 case PACKET_ID_NICKNAME: {
2434 if (data_length > MAX_NAME_LENGTH || data_length == 0) 1933 if (data_length > MAX_NAME_LENGTH || data_length == 0)
2435 break; 1934 break;
@@ -2599,33 +2098,15 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2599 } 2098 }
2600 2099
2601 case PACKET_ID_INVITE_GROUPCHAT: { 2100 case PACKET_ID_INVITE_GROUPCHAT: {
2602 if (data_length != crypto_box_PUBLICKEYBYTES) 2101 if (data_length == 0)
2603 break; 2102 break;
2604 2103
2605 if (m->group_invite) 2104 if (m->group_invite)
2606 (*m->group_invite)(m, i, data, m->group_invite_userdata); 2105 (*m->group_invite)(m, i, data, data_length);
2607 2106
2608 break; 2107 break;
2609 } 2108 }
2610 2109
2611 case PACKET_ID_JOIN_GROUPCHAT: {
2612 if (data_length != crypto_box_PUBLICKEYBYTES * 2)
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;
2622
2623 group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES);
2624 /* This is just there to speedup joining. */
2625 chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES);
2626 break;
2627 }
2628
2629 case PACKET_ID_FILE_SENDREQUEST: { 2110 case PACKET_ID_FILE_SENDREQUEST: {
2630 if (data_length < 1 + sizeof(uint64_t) + 1) 2111 if (data_length < 1 + sizeof(uint64_t) + 1)
2631 break; 2112 break;
@@ -2720,27 +2201,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2720 return 0; 2201 return 0;
2721} 2202}
2722 2203
2723static int friend_new_connection(Messenger *m, int32_t friendnumber, const uint8_t *real_public_key)
2724{
2725 if (friend_not_valid(m, friendnumber))
2726 return -1;
2727
2728 if (m->friendlist[friendnumber].crypt_connection_id != -1) {
2729 return -1;
2730 }
2731
2732 int id = new_crypto_connection(m->net_crypto, real_public_key);
2733
2734 if (id == -1)
2735 return -1;
2736
2737 m->friendlist[friendnumber].crypt_connection_id = id;
2738 connection_status_handler(m->net_crypto, id, &handle_status, m, friendnumber);
2739 connection_data_handler(m->net_crypto, id, &handle_packet, m, friendnumber);
2740 connection_lossy_data_handler(m->net_crypto, id, &handle_custom_lossy_packet, m, friendnumber);
2741 return 0;
2742}
2743
2744/* TODO: Make this function not suck. */ 2204/* TODO: Make this function not suck. */
2745void do_friends(Messenger *m) 2205void do_friends(Messenger *m)
2746{ 2206{
@@ -2767,32 +2227,6 @@ void do_friends(Messenger *m)
2767 */ 2227 */
2768 check_friend_request_timed_out(m, i, temp_time); 2228 check_friend_request_timed_out(m, i, temp_time);
2769 } 2229 }
2770
2771 friend_new_connection(m, i, m->friendlist[i].client_id);
2772 }
2773
2774 if (m->friendlist[i].crypt_connection_id != -1) {
2775 uint8_t dht_public_key1[crypto_box_PUBLICKEYBYTES];
2776 uint64_t timestamp1 = onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key1);
2777 uint8_t dht_public_key2[crypto_box_PUBLICKEYBYTES];
2778 uint64_t timestamp2 = get_connection_dht_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key2);
2779
2780 if (timestamp1 > timestamp2) {
2781 set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key1, timestamp1);
2782 } else if (timestamp1 < timestamp2) {
2783 onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key2, timestamp2);
2784 }
2785
2786 uint8_t direct_connected;
2787 unsigned int status = crypto_connection_status(m->net_crypto, m->friendlist[i].crypt_connection_id, &direct_connected);
2788
2789 if (direct_connected == 0 || status == CRYPTO_CONN_COOKIE_REQUESTING) {
2790 IP_Port friendip;
2791
2792 if (onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip) == 1) {
2793 set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, friendip);
2794 }
2795 }
2796 } 2230 }
2797 2231
2798 if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ 2232 if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
@@ -2821,17 +2255,6 @@ void do_friends(Messenger *m)
2821 m->friendlist[i].user_istyping_sent = 1; 2255 m->friendlist[i].user_istyping_sent = 1;
2822 } 2256 }
2823 2257
2824 if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
2825 send_ping(m, i);
2826 }
2827
2828 if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
2829 /* If we stopped receiving ping packets, kill it. */
2830 crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
2831 m->friendlist[i].crypt_connection_id = -1;
2832 set_friend_status(m, i, FRIEND_CONFIRMED);
2833 }
2834
2835 if (m->friendlist[i].share_relays_lastsent + FRIEND_SHARE_RELAYS_INTERVAL < temp_time) { 2258 if (m->friendlist[i].share_relays_lastsent + FRIEND_SHARE_RELAYS_INTERVAL < temp_time) {
2836 send_relays(m, i); 2259 send_relays(m, i);
2837 } 2260 }
@@ -2901,8 +2324,8 @@ void do_messenger(Messenger *m)
2901 2324
2902 do_net_crypto(m->net_crypto); 2325 do_net_crypto(m->net_crypto);
2903 do_onion_client(m->onion_c); 2326 do_onion_client(m->onion_c);
2327 do_friend_connections(m->fr_c);
2904 do_friends(m); 2328 do_friends(m);
2905 do_allgroupchats(m);
2906 LANdiscovery(m); 2329 LANdiscovery(m);
2907 2330
2908#ifdef LOGGING 2331#ifdef LOGGING
@@ -2913,16 +2336,6 @@ void do_messenger(Messenger *m)
2913 Assoc_status(m->dht->assoc); 2336 Assoc_status(m->dht->assoc);
2914#endif 2337#endif
2915 2338
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(); 2339 lastdump = unix_time();
2927 uint32_t client, last_pinged; 2340 uint32_t client, last_pinged;
2928 2341
@@ -2992,8 +2405,8 @@ void do_messenger(Messenger *m)
2992 if (ping_lastrecv > 999) 2405 if (ping_lastrecv > 999)
2993 ping_lastrecv = 999; 2406 ping_lastrecv = 999;
2994 2407
2995 LOGGER_INFO("F[%2u:%2u] <%s> %02i [%03u] %s", 2408 LOGGER_INFO("F[%2u:%2u] <%s> [%03u] %s",
2996 dht2m[friend], friend, msgfptr->name, msgfptr->crypt_connection_id, 2409 dht2m[friend], friend, msgfptr->name,
2997 ping_lastrecv, ID2String(msgfptr->client_id)); 2410 ping_lastrecv, ID2String(msgfptr->client_id));
2998 } else { 2411 } else {
2999 LOGGER_INFO("F[--:%2u] %s", friend, ID2String(dhtfptr->client_id)); 2412 LOGGER_INFO("F[--:%2u] %s", friend, ID2String(dhtfptr->client_id));
@@ -3429,51 +2842,3 @@ int get_friendlist(const Messenger *m, int32_t **out_list, uint32_t *out_list_le
3429 2842
3430 return 0; 2843 return 0;
3431} 2844}
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}