diff options
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/group.c | 227 | ||||
-rw-r--r-- | toxcore/group.h | 2 | ||||
-rw-r--r-- | toxcore/tox.c | 6 |
3 files changed, 224 insertions, 11 deletions
diff --git a/toxcore/group.c b/toxcore/group.c index 90e968c3..d94349f4 100644 --- a/toxcore/group.c +++ b/toxcore/group.c | |||
@@ -205,6 +205,12 @@ static uint16_t calculate_comp_value(const uint8_t *pk1, const uint8_t *pk2) | |||
205 | return (cmp1 << 8) + cmp2; | 205 | return (cmp1 << 8) + cmp2; |
206 | } | 206 | } |
207 | 207 | ||
208 | enum { | ||
209 | GROUPCHAT_CLOSEST_NONE, | ||
210 | GROUPCHAT_CLOSEST_ADDED, | ||
211 | GROUPCHAT_CLOSEST_REMOVED | ||
212 | }; | ||
213 | |||
208 | static int friend_in_close(Group_c *g, int friendcon_id); | 214 | static int friend_in_close(Group_c *g, int friendcon_id); |
209 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest); | 215 | static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest); |
210 | 216 | ||
@@ -215,10 +221,19 @@ static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real | |||
215 | if (!g) | 221 | if (!g) |
216 | return -1; | 222 | return -1; |
217 | 223 | ||
224 | if (memcmp(g->real_pk, real_pk, crypto_box_PUBLICKEYBYTES) == 0) | ||
225 | return -1; | ||
226 | |||
218 | unsigned int i; | 227 | unsigned int i; |
219 | unsigned int index = DESIRED_CLOSE_CONNECTIONS; | 228 | unsigned int index = DESIRED_CLOSE_CONNECTIONS; |
220 | 229 | ||
221 | for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { | 230 | for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { |
231 | if (g->closest_peers[i].entry && memcmp(real_pk, g->closest_peers[i].real_pk, crypto_box_PUBLICKEYBYTES) == 0) { | ||
232 | return 0; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { | ||
222 | if (g->closest_peers[i].entry == 0) { | 237 | if (g->closest_peers[i].entry == 0) { |
223 | index = i; | 238 | index = i; |
224 | break; | 239 | break; |
@@ -246,7 +261,9 @@ static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real | |||
246 | g->closest_peers[index].entry = 1; | 261 | g->closest_peers[index].entry = 1; |
247 | memcpy(g->closest_peers[index].real_pk, real_pk, crypto_box_PUBLICKEYBYTES); | 262 | memcpy(g->closest_peers[index].real_pk, real_pk, crypto_box_PUBLICKEYBYTES); |
248 | memcpy(g->closest_peers[index].temp_pk, temp_pk, crypto_box_PUBLICKEYBYTES); | 263 | memcpy(g->closest_peers[index].temp_pk, temp_pk, crypto_box_PUBLICKEYBYTES); |
249 | g->changed = 1; | 264 | |
265 | if (!g->changed) | ||
266 | g->changed = GROUPCHAT_CLOSEST_ADDED; | ||
250 | 267 | ||
251 | return 0; | 268 | return 0; |
252 | } | 269 | } |
@@ -281,6 +298,12 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber) | |||
281 | 298 | ||
282 | unsigned int i; | 299 | unsigned int i; |
283 | 300 | ||
301 | if (g->changed == GROUPCHAT_CLOSEST_REMOVED) { | ||
302 | for (i = 0; i < g->numpeers; ++i) { | ||
303 | add_to_closest(g_c, groupnumber, g->group[i].real_pk, g->group[i].temp_pk); | ||
304 | } | ||
305 | } | ||
306 | |||
284 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | 307 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { |
285 | if (g->close[i].type == GROUPCHAT_CLOSE_NONE) | 308 | if (g->close[i].type == GROUPCHAT_CLOSE_NONE) |
286 | continue; | 309 | continue; |
@@ -315,12 +338,13 @@ static int connect_to_closest(Group_Chats *g_c, int groupnumber) | |||
315 | } | 338 | } |
316 | 339 | ||
317 | add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1); | 340 | add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1); |
341 | |||
318 | if (friend_con_connected(g_c->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { | 342 | if (friend_con_connected(g_c->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { |
319 | send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier); | 343 | send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier); |
320 | } | 344 | } |
321 | } | 345 | } |
322 | 346 | ||
323 | g->changed = 0; | 347 | g->changed = GROUPCHAT_CLOSEST_NONE; |
324 | 348 | ||
325 | return 0; | 349 | return 0; |
326 | } | 350 | } |
@@ -380,6 +404,55 @@ static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, co | |||
380 | return (g->numpeers - 1); | 404 | return (g->numpeers - 1); |
381 | } | 405 | } |
382 | 406 | ||
407 | /* | ||
408 | * Delete a peer from the group chat. | ||
409 | * | ||
410 | * return 0 if success | ||
411 | * return -1 if error. | ||
412 | */ | ||
413 | static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index) | ||
414 | { | ||
415 | Group_c *g = get_group_c(g_c, groupnumber); | ||
416 | |||
417 | if (!g) | ||
418 | return -1; | ||
419 | |||
420 | uint32_t i; | ||
421 | |||
422 | for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { /* If peer is in closest_peers list, remove it. */ | ||
423 | if (g->closest_peers[i].entry && id_equal(g->closest_peers[i].real_pk, g->group[peer_index].real_pk)) { | ||
424 | g->closest_peers[i].entry = 0; | ||
425 | g->changed = GROUPCHAT_CLOSEST_REMOVED; | ||
426 | break; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | Group_Peer *temp; | ||
431 | --g->numpeers; | ||
432 | |||
433 | if (g->numpeers == 0) { | ||
434 | free(g->group); | ||
435 | g->group = NULL; | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | if (g->numpeers != (uint32_t)peer_index) | ||
440 | memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer)); | ||
441 | |||
442 | temp = realloc(g->group, sizeof(Group_Peer) * (g->numpeers)); | ||
443 | |||
444 | if (temp == NULL) | ||
445 | return -1; | ||
446 | |||
447 | g->group = temp; | ||
448 | /* | ||
449 | if (g->peer_namelistchange != NULL) { | ||
450 | (*g->peer_namelistchange)(g, peer_index, CHAT_CHANGE_PEER_DEL, g->group_namelistchange_userdata); | ||
451 | } | ||
452 | */ | ||
453 | return 0; | ||
454 | } | ||
455 | |||
383 | static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id) | 456 | static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id) |
384 | { | 457 | { |
385 | Group_c *g = get_group_c(g_c, groupnumber); | 458 | Group_c *g = get_group_c(g_c, groupnumber); |
@@ -475,8 +548,6 @@ static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnu | |||
475 | if (g->close[i].number == (uint32_t)friendcon_id) { | 548 | if (g->close[i].number == (uint32_t)friendcon_id) { |
476 | return i; /* Already in list. */ | 549 | return i; /* Already in list. */ |
477 | } | 550 | } |
478 | |||
479 | break; | ||
480 | } | 551 | } |
481 | 552 | ||
482 | if (ind == MAX_GROUP_CONNECTIONS) | 553 | if (ind == MAX_GROUP_CONNECTIONS) |
@@ -515,6 +586,7 @@ int add_groupchat(Group_Chats *g_c) | |||
515 | return groupnumber; | 586 | return groupnumber; |
516 | } | 587 | } |
517 | 588 | ||
589 | static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num); | ||
518 | /* Delete a groupchat from the chats array. | 590 | /* Delete a groupchat from the chats array. |
519 | * | 591 | * |
520 | * return 0 on success. | 592 | * return 0 on success. |
@@ -527,6 +599,8 @@ int del_groupchat(Group_Chats *g_c, int groupnumber) | |||
527 | if (!g) | 599 | if (!g) |
528 | return -1; | 600 | return -1; |
529 | 601 | ||
602 | group_kill_peer_send(g_c, groupnumber, g->peer_number); | ||
603 | |||
530 | unsigned int i; | 604 | unsigned int i; |
531 | 605 | ||
532 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { | 606 | for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { |
@@ -541,6 +615,44 @@ int del_groupchat(Group_Chats *g_c, int groupnumber) | |||
541 | return wipe_group_chat(g_c, groupnumber); | 615 | return wipe_group_chat(g_c, groupnumber); |
542 | } | 616 | } |
543 | 617 | ||
618 | /* Copy the name of peernumber who is in groupnumber to name. | ||
619 | * name must be at least MAX_NAME_LENGTH long. | ||
620 | * | ||
621 | * return length of name if success | ||
622 | * return -1 if failure | ||
623 | */ | ||
624 | int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name) | ||
625 | { | ||
626 | Group_c *g = get_group_c(g_c, groupnumber); | ||
627 | |||
628 | if (!g) | ||
629 | return -1; | ||
630 | |||
631 | if ((uint32_t)peernumber >= g->numpeers) | ||
632 | return -1; | ||
633 | |||
634 | if (g->group[peernumber].nick_len == 0) { | ||
635 | memcpy(name, "Tox User", 8); | ||
636 | return 8; | ||
637 | } | ||
638 | |||
639 | memcpy(name, g->group[peernumber].nick, g->group[peernumber].nick_len); | ||
640 | return g->group[peernumber].nick_len; | ||
641 | } | ||
642 | |||
643 | /* Return the number of peers in the group chat on success. | ||
644 | * return -1 on failure | ||
645 | */ | ||
646 | int group_number_peers(const Group_Chats *g_c, int groupnumber) | ||
647 | { | ||
648 | Group_c *g = get_group_c(g_c, groupnumber); | ||
649 | |||
650 | if (!g) | ||
651 | return -1; | ||
652 | |||
653 | return g->numpeers; | ||
654 | } | ||
655 | |||
544 | /* Send a group packet to friendcon_id. | 656 | /* Send a group packet to friendcon_id. |
545 | * | 657 | * |
546 | * return 1 on success | 658 | * return 1 on success |
@@ -671,9 +783,20 @@ void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, i | |||
671 | 783 | ||
672 | static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, | 784 | static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, |
673 | uint16_t len); | 785 | uint16_t len); |
786 | |||
787 | #define GROUP_MESSAGE_PING_ID 0 | ||
788 | int group_ping_send(const Group_Chats *g_c, int groupnumber) | ||
789 | { | ||
790 | if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, 0, 0)) { | ||
791 | return 0; | ||
792 | } else { | ||
793 | return -1; | ||
794 | } | ||
795 | } | ||
796 | |||
674 | #define GROUP_MESSAGE_NEW_PEER_ID 16 | 797 | #define GROUP_MESSAGE_NEW_PEER_ID 16 |
675 | #define GROUP_MESSAGE_NEW_PEER_LENGTH (sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2) | 798 | #define GROUP_MESSAGE_NEW_PEER_LENGTH (sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2) |
676 | /* send a group message | 799 | /* send a new_peer message |
677 | * return 0 on success | 800 | * return 0 on success |
678 | * return -1 on failure | 801 | * return -1 on failure |
679 | */ | 802 | */ |
@@ -694,6 +817,28 @@ int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_n | |||
694 | } | 817 | } |
695 | } | 818 | } |
696 | 819 | ||
820 | #define GROUP_MESSAGE_KILL_PEER_ID 17 | ||
821 | #define GROUP_MESSAGE_KILL_PEER_LENGTH (sizeof(uint16_t)) | ||
822 | |||
823 | /* send a kill_peer message | ||
824 | * return 0 on success | ||
825 | * return -1 on failure | ||
826 | */ | ||
827 | int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num) | ||
828 | { | ||
829 | |||
830 | uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH]; | ||
831 | |||
832 | peer_num = htons(peer_num); | ||
833 | memcpy(packet, &peer_num, sizeof(uint16_t)); | ||
834 | |||
835 | if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet))) { | ||
836 | return 0; | ||
837 | } else { | ||
838 | return -1; | ||
839 | } | ||
840 | } | ||
841 | |||
697 | static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) | 842 | static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) |
698 | { | 843 | { |
699 | Group_Chats *g_c = m->group_chat_object; | 844 | Group_Chats *g_c = m->group_chat_object; |
@@ -1067,6 +1212,14 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const | |||
1067 | uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1); | 1212 | uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1); |
1068 | 1213 | ||
1069 | switch (message_id) { | 1214 | switch (message_id) { |
1215 | case GROUP_MESSAGE_PING_ID: { | ||
1216 | if (msg_data_len != 0) | ||
1217 | return; | ||
1218 | |||
1219 | g->group[index].last_recv = unix_time(); | ||
1220 | } | ||
1221 | break; | ||
1222 | |||
1070 | case GROUP_MESSAGE_NEW_PEER_ID: { | 1223 | case GROUP_MESSAGE_NEW_PEER_ID: { |
1071 | if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) | 1224 | if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) |
1072 | return; | 1225 | return; |
@@ -1079,6 +1232,25 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const | |||
1079 | } | 1232 | } |
1080 | break; | 1233 | break; |
1081 | 1234 | ||
1235 | case GROUP_MESSAGE_KILL_PEER_ID: { | ||
1236 | if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) | ||
1237 | return; | ||
1238 | |||
1239 | uint16_t kill_peer_number; | ||
1240 | memcpy(&kill_peer_number, msg_data, sizeof(uint16_t)); | ||
1241 | kill_peer_number = ntohs(kill_peer_number); | ||
1242 | |||
1243 | if (peer_number == kill_peer_number) { | ||
1244 | delpeer(g_c, groupnumber, index); | ||
1245 | return; | ||
1246 | } else { | ||
1247 | //TODO | ||
1248 | } | ||
1249 | |||
1250 | return; | ||
1251 | } | ||
1252 | break; | ||
1253 | |||
1082 | case PACKET_ID_MESSAGE: { | 1254 | case PACKET_ID_MESSAGE: { |
1083 | if (msg_data_len == 0) | 1255 | if (msg_data_len == 0) |
1084 | return; | 1256 | return; |
@@ -1094,7 +1266,7 @@ static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const | |||
1094 | return; | 1266 | return; |
1095 | } | 1267 | } |
1096 | 1268 | ||
1097 | send_message_all_close(g_c, groupnumber, data, length, close_index); | 1269 | send_message_all_close(g_c, groupnumber, data, length, -1/*TODO close_index*/); |
1098 | } | 1270 | } |
1099 | 1271 | ||
1100 | static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length) | 1272 | static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length) |
@@ -1143,6 +1315,44 @@ static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t | |||
1143 | return 0; | 1315 | return 0; |
1144 | } | 1316 | } |
1145 | 1317 | ||
1318 | /* Interval in seconds to send ping messages */ | ||
1319 | #define GROUP_PING_INTERVAL 30 | ||
1320 | |||
1321 | static int ping_groupchat(Group_Chats *g_c, int groupnumber) | ||
1322 | { | ||
1323 | Group_c *g = get_group_c(g_c, groupnumber); | ||
1324 | |||
1325 | if (!g) | ||
1326 | return -1; | ||
1327 | |||
1328 | if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) { | ||
1329 | if (group_ping_send(g_c, groupnumber) != -1) /* Ping */ | ||
1330 | g->last_sent_ping = unix_time(); | ||
1331 | } | ||
1332 | |||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | static int groupchat_clear_timedout(Group_Chats *g_c, int groupnumber) | ||
1337 | { | ||
1338 | Group_c *g = get_group_c(g_c, groupnumber); | ||
1339 | |||
1340 | if (!g) | ||
1341 | return -1; | ||
1342 | |||
1343 | uint32_t i; | ||
1344 | |||
1345 | for (i = 0; i < g->numpeers; ++i) { | ||
1346 | if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 2)) { | ||
1347 | delpeer(g_c, groupnumber, i); | ||
1348 | } | ||
1349 | |||
1350 | if (g->group == NULL || i >= g->numpeers) | ||
1351 | break; | ||
1352 | } | ||
1353 | |||
1354 | return 0; | ||
1355 | } | ||
1146 | 1356 | ||
1147 | /* Create new groupchat instance. */ | 1357 | /* Create new groupchat instance. */ |
1148 | Group_Chats *new_groupchats(Messenger *m) | 1358 | Group_Chats *new_groupchats(Messenger *m) |
@@ -1174,8 +1384,11 @@ void do_groupchats(Group_Chats *g_c) | |||
1174 | if (!g) | 1384 | if (!g) |
1175 | continue; | 1385 | continue; |
1176 | 1386 | ||
1177 | if (g->status == GROUPCHAT_STATUS_CONNECTED) | 1387 | if (g->status == GROUPCHAT_STATUS_CONNECTED) { |
1178 | connect_to_closest(g_c, i); | 1388 | connect_to_closest(g_c, i); |
1389 | ping_groupchat(g_c, i); | ||
1390 | groupchat_clear_timedout(g_c, i); | ||
1391 | } | ||
1179 | } | 1392 | } |
1180 | 1393 | ||
1181 | //TODO | 1394 | //TODO |
diff --git a/toxcore/group.h b/toxcore/group.h index 94ae28bf..c91edd7b 100644 --- a/toxcore/group.h +++ b/toxcore/group.h | |||
@@ -88,6 +88,8 @@ typedef struct { | |||
88 | 88 | ||
89 | uint32_t message_number; | 89 | uint32_t message_number; |
90 | uint16_t peer_number; | 90 | uint16_t peer_number; |
91 | |||
92 | uint64_t last_sent_ping; | ||
91 | } Group_c; | 93 | } Group_c; |
92 | 94 | ||
93 | typedef struct { | 95 | typedef struct { |
diff --git a/toxcore/tox.c b/toxcore/tox.c index 30630cf2..35587c2b 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -620,8 +620,7 @@ int tox_del_groupchat(Tox *tox, int groupnumber) | |||
620 | int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name) | 620 | int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name) |
621 | { | 621 | { |
622 | const Messenger *m = tox; | 622 | const Messenger *m = tox; |
623 | //return m_group_peername(m, groupnumber, peernumber, name); | 623 | return group_peername(m->group_chat_object, groupnumber, peernumber, name); |
624 | return -1; | ||
625 | } | 624 | } |
626 | 625 | ||
627 | /* invite friendnumber to groupnumber | 626 | /* invite friendnumber to groupnumber |
@@ -673,8 +672,7 @@ int tox_group_action_send(Tox *tox, int groupnumber, const uint8_t *action, uint | |||
673 | int tox_group_number_peers(const Tox *tox, int groupnumber) | 672 | int tox_group_number_peers(const Tox *tox, int groupnumber) |
674 | { | 673 | { |
675 | const Messenger *m = tox; | 674 | const Messenger *m = tox; |
676 | //return group_number_peers(m, groupnumber); | 675 | return group_number_peers(m->group_chat_object, groupnumber); |
677 | return -1; | ||
678 | } | 676 | } |
679 | 677 | ||
680 | /* List all the peers in the group chat. | 678 | /* List all the peers in the group chat. |