summaryrefslogtreecommitdiff
path: root/toxcore/group.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-10-02 16:29:03 -0400
committerirungentoo <irungentoo@gmail.com>2014-10-02 16:29:03 -0400
commit92f804d0f5545a405b5d0816510cbf8058f7f605 (patch)
tree562f31eb1c059ce6aa53a4d89fd0822d28ea3361 /toxcore/group.c
parent1ac1522c39a1bd49aeef0be3d339f1740fffb663 (diff)
Peers now time out and delete themselves from group chats.
Some other work done.
Diffstat (limited to 'toxcore/group.c')
-rw-r--r--toxcore/group.c227
1 files changed, 220 insertions, 7 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
208enum {
209 GROUPCHAT_CLOSEST_NONE,
210 GROUPCHAT_CLOSEST_ADDED,
211 GROUPCHAT_CLOSEST_REMOVED
212};
213
208static int friend_in_close(Group_c *g, int friendcon_id); 214static int friend_in_close(Group_c *g, int friendcon_id);
209static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest); 215static 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 */
413static 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
383static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id) 456static 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
589static 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 */
624int 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 */
646int 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
672static unsigned int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data, 784static 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
788int 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 */
827int 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
697static void handle_friend_invite_packet(Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) 842static 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
1100static int handle_packet(void *object, int friendcon_id, uint8_t *data, uint16_t length) 1272static 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
1321static 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
1336static 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. */
1148Group_Chats *new_groupchats(Messenger *m) 1358Group_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