summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/network_test.c11
-rw-r--r--docs/Hardening_docs.txt21
-rw-r--r--docs/updates/DHT.md113
-rw-r--r--toxcore/DHT.c28
-rw-r--r--toxcore/Messenger.c9
-rw-r--r--toxcore/Messenger.h5
-rw-r--r--toxcore/assoc.c4
-rw-r--r--toxcore/group_chats.c8
-rw-r--r--toxcore/group_chats.h3
-rw-r--r--toxcore/network.h4
-rw-r--r--toxcore/tox.c12
-rw-r--r--toxcore/tox.h13
12 files changed, 197 insertions, 34 deletions
diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c
index 2383c0cb..d65b8100 100644
--- a/auto_tests/network_test.c
+++ b/auto_tests/network_test.c
@@ -122,6 +122,16 @@ START_TEST(test_ip_equal)
122} 122}
123END_TEST 123END_TEST
124 124
125START_TEST(test_struct_sizes)
126{
127 ck_assert_msg(sizeof(IP4) == 4, "sizeof(IP4): expected result 4, got %u.", sizeof(IP4));
128 ck_assert_msg(sizeof(IP6) == 16, "sizeof(IP6): expected result 16, got %u.", sizeof(IP6));
129 ck_assert_msg(sizeof(IP) == 20, "sizeof(IP): expected result 20, got %u.", sizeof(IP));
130 ck_assert_msg(sizeof(IP_Port) == 24, "sizeof(IP_Port): expected result 24, got %u.", sizeof(IP_Port));
131 ck_assert_msg(sizeof(IP4_Port) == 8, "sizeof(IP4_Port): expected result 8, got %u.", sizeof(IP4_Port));
132}
133END_TEST
134
125#define DEFTESTCASE(NAME) \ 135#define DEFTESTCASE(NAME) \
126 TCase *tc_##NAME = tcase_create(#NAME); \ 136 TCase *tc_##NAME = tcase_create(#NAME); \
127 tcase_add_test(tc_##NAME, test_##NAME); \ 137 tcase_add_test(tc_##NAME, test_##NAME); \
@@ -133,6 +143,7 @@ Suite *network_suite(void)
133 143
134 DEFTESTCASE(addr_resolv_localhost); 144 DEFTESTCASE(addr_resolv_localhost);
135 DEFTESTCASE(ip_equal); 145 DEFTESTCASE(ip_equal);
146 DEFTESTCASE(struct_sizes);
136 147
137 return s; 148 return s;
138} 149}
diff --git a/docs/Hardening_docs.txt b/docs/Hardening_docs.txt
new file mode 100644
index 00000000..08c6ef13
--- /dev/null
+++ b/docs/Hardening_docs.txt
@@ -0,0 +1,21 @@
1Hardening request packets are sent as crypto request packets (see crypto docs.)
2NOTE: currently only get nodes requests are tested in the code which is why there is only one test (more will be added soon.)
3
4All hardening requests must contain exactly 768 bytes of data. (The data sent must be padded with zeros if it is smaller than that.)
5
61. Get the information (IP_port, client_id) of the node we want to test.
72. Find a couple random nodes that is not that node (one for each test.)
83. Send crypto request packets to each of these random nodes with the data being:
9
10[byte with value: 02 (get nodes test request)][struct Node_format (the node to test.)][client_id(32 bytes) the id to query the node with.][padding]
11
124. The random node receives a packet.
13-The packet is a get nodes test request:
14 send a get_node request to that node with the id to query in the request.
15 when a send_node response is received, send the following response to the person who sent us the get nodes test request packet:
16 [byte with value: 03 (get nodes test response)][client_id(32 bytes): the id that the node was queried with][The list of nodes it responded with in IPv6 Node format (struct Node_Format)]
17 PROTIP: (get node requests and response contain an encrypted part that you can use to store information so that you don't
18 have to store in your memory where/if to send back the response from the send node)
19
205. Receive the test responses.
21-If the test(s) pass (the nodes behave in a satisfactory manner), make these nodes have priority over those who don't pass the test(s).
diff --git a/docs/updates/DHT.md b/docs/updates/DHT.md
new file mode 100644
index 00000000..79ec8c4b
--- /dev/null
+++ b/docs/updates/DHT.md
@@ -0,0 +1,113 @@
1DHT protocol
2============
3
4Follows pretty much the principle of the torrent DHT: http://www.bittorrent.org/beps/bep_0005.html (READ IT)
5
6But:
7Vastly simplified packet format and encryption.
8
9Boostrapping:
10The first time you install the client we bootstrap it with a node on our servers.(bandwidth should not be a problem as the client only needs to be sent one reply.)
11
12
13Basics
14------
15(All the numbers here are just guesses and are probably not optimal values)
16
17client list: A list of node ids closest (mathematically see bittorrent doc) to ours matched with ip addresses + port number corresponding to that id and a timestamp containing the time or time since the client was successfully pinged.
18
19"friends" list: A list containing the node_ids of all our "friends" or clients we want to connect to.
20Also contains the ip addresses + port + node_ids + timestamp(of last ping like in the client list) of the 8 clients closest (mathematically see bittorrent doc) to each "friend"
21
22One pinged lists:
23-One for storing a list of ips along with their ping_ids and a timestamp for the ping requests
24Entries in the pinged lists expire after 5 seconds.
25If one of the lists becomes full, the expire rate reduces itself one second or the new ping takes the place of the oldest one.
26
27
28Entries in client list and "friends" list expire after 300 seconds without ping response.
29Each client stores a maximum of 32 entries in its client list.
30Each client in the client list and "friends" list is pinged every 60 seconds.
31Each client in the client list and "friends" list has a timestamp which denote the last time it was successfully pinged.
32If the corresponding clients timestamp is more than 130 seconds old it is considered bad.
33Send a get nodes request every 20 seconds to a random good node for each "friend" in our "friends" list.
34Send a get nodes request every 20 seconds to a random good node in the client list.
35
36
37When a client receives any request from another
38-----------------------------------------------
39-Respond to the request
40 -Ping request is replied to with with a ping response containing the same encrypted data
41 -Get nodes request is replied with a send nodes reply containing the same encrypted data and the good nodes from the client list and/or the "friends" list that are closest to the requested_node_id
42
43-If the requesting client is not in the client list:
44 -If there are no bad clients in the list and the list is full:
45 -If the id of the other client is closer (mathematically see bittorrent doc) than at least one of the clients in the list or our "friends" list:
46 -Send a ping request to the client.
47 -if not forget about the client.
48
49 -If there are bad clients and/or the list isn't full:
50 -Send a ping request to the client
51
52When a client receives a response
53---------------------------------
54-Ping response
55 -If the node was previously pinged with a matching ping_id (check in the corresponding pinged list.)
56 -If the node is in the client list the matching client's timestamp is set to current time.
57 -If the node is in the "friends" list the matching client's timestamp is set to current time for every occurrence.
58 -If the node is not in the client list:
59 -If the list isn't full, add it to the list.
60 -If the list is full, the furthest away (mathematically see bittorrent doc) bad client is replaced by the new one.
61 -If the list is filled with good nodes replace the furthest client with it only if it is closer than the replaced node.
62 -for each friend in the "friends" list:
63 -If that friend's client list isn't full, add that client to it
64 -If that friend's client list contains bad clients, replace the furthest one with that client.
65 -If that friend's client list contains only good clients
66 -If the client is closer to the friend than one of the other clients, it replaces the farthest one
67 -If not, nothing happens.
68
69 -Send nodes
70 -If the ping_id matches what we sent previously (check in the corresponding pinged list.):
71 -Each node in the response is pinged.
72
73
74
75
76
77Protocol
78--------
79
80Node format:
81```
82[char array (node_id), length=32 bytes][ip (in network byte order), length=4 bytes][port (in network byte order), length=2 bytes][Padding , length=2 bytes]
83```
84see also: DHT.h (Node4_format struct)
85
86IPv6 Node format:
87see: DHT.h (Node_format struct)
88
89Valid queries and Responses:
90
91Ping(Request and response):
92```
93[byte with value: 00 for request, 01 for response][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender: [random 8 byte (ping_id)]]
94```
95ping_id = a random integer, the response must contain the exact same number as the request
96
97
98Get nodes (Request):
99Packet contents:
100```
101[byte with value: 02][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[char array: requested_node_id (node_id of which we want the ip), length=32 bytes][Encrypted data (must be sent back unmodified by in the response), length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
102```
103Valid replies: a send_nodes packet
104
105Send_nodes (response (for ipv4 addresses)):
106```
107[byte with value: 03][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=40 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
108```
109
110Send_nodes_IPv6 (response (for ipv6 addresses)):
111```
112[byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in ipv6_node format, length=56 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]]
113```
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index fb059f5b..40ad3929 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -351,7 +351,8 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
351 * 351 *
352 * want_good : do we want only good nodes as checked with the hardening returned or not? 352 * want_good : do we want only good nodes as checked with the hardening returned or not?
353 */ 353 */
354static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN, uint8_t want_good) 354static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family,
355 uint8_t is_LAN, uint8_t want_good)
355{ 356{
356 uint32_t num_nodes = 0, i; 357 uint32_t num_nodes = 0, i;
357 get_close_nodes_inner(dht, client_id, nodes_list, sa_family, 358 get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
@@ -365,7 +366,8 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
365 return num_nodes; 366 return num_nodes;
366} 367}
367 368
368static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN, uint8_t want_good) 369static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN,
370 uint8_t want_good)
369{ 371{
370 if (!dht->assoc) 372 if (!dht->assoc)
371 return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); 373 return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good);
@@ -492,10 +494,10 @@ static void sort_list(Client_data *list, uint32_t length, uint8_t *comp_client_i
492 * return 1 if not (list contains no bad nodes). 494 * return 1 if not (list contains no bad nodes).
493 */ 495 */
494static int replace_possible_bad( Client_data *list, 496static int replace_possible_bad( Client_data *list,
495 uint32_t length, 497 uint32_t length,
496 uint8_t *client_id, 498 uint8_t *client_id,
497 IP_Port ip_port, 499 IP_Port ip_port,
498 uint8_t *comp_client_id ) 500 uint8_t *comp_client_id )
499{ 501{
500 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) 502 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
501 return 1; 503 return 1;
@@ -626,10 +628,10 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
626 if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 628 if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
627 if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 629 if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
628 if (replace_possible_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port, 630 if (replace_possible_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
629 dht->c->self_public_key)) { 631 dht->c->self_public_key)) {
630 /* If we can't replace bad nodes we try replacing good ones. */ 632 /* If we can't replace bad nodes we try replacing good ones. */
631 if (!replace_good(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port, 633 if (!replace_good(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
632 dht->c->self_public_key)) 634 dht->c->self_public_key))
633 used++; 635 used++;
634 } else 636 } else
635 used++; 637 used++;
@@ -647,9 +649,10 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
647 /*if (replace_possible_bad(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 649 /*if (replace_possible_bad(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
648 client_id, ip_port, dht->friends_list[i].client_id)) {*/ 650 client_id, ip_port, dht->friends_list[i].client_id)) {*/
649 /* If we can't replace bad nodes we try replacing good ones. */ 651 /* If we can't replace bad nodes we try replacing good ones. */
650 if (!replace_good(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 652 if (!replace_good(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
651 client_id, ip_port, dht->friends_list[i].client_id)) 653 client_id, ip_port, dht->friends_list[i].client_id))
652 used++; 654 used++;
655
653 /*} else 656 /*} else
654 used++;*/ 657 used++;*/
655 } else 658 } else
@@ -801,7 +804,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
801 new_nonce(nonce); 804 new_nonce(nonce);
802 805
803 Node4_format *nodes4_list = (Node4_format *)(plain); 806 Node4_format *nodes4_list = (Node4_format *)(plain);
804 int i, num_nodes_ok = 0; 807 uint32_t i, num_nodes_ok = 0;
805 808
806 for (i = 0; i < num_nodes; i++) { 809 for (i = 0; i < num_nodes; i++) {
807 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); 810 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
@@ -1042,6 +1045,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
1042 1045
1043 memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); 1046 memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
1044 ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port); 1047 ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port);
1048
1045 if (dht->assoc) 1049 if (dht->assoc)
1046 Assoc_add_entry(dht->assoc, nodes4_list[i].client_id, &ippts, NULL, used ? 1 : 0); 1050 Assoc_add_entry(dht->assoc, nodes4_list[i].client_id, &ippts, NULL, used ? 1 : 0);
1047 } 1051 }
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 32234784..2eebd772 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -720,6 +720,7 @@ static uint8_t groupnumber_not_valid(Messenger *m, int groupnumber)
720 720
721 if (m->chats[groupnumber] == NULL) 721 if (m->chats[groupnumber] == NULL)
722 return 1; 722 return 1;
723
723 return 0; 724 return 0;
724} 725}
725 726
@@ -785,7 +786,8 @@ void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int,
785 * It gets called every time the name list changes(new peer/name, deleted peer) 786 * It gets called every time the name list changes(new peer/name, deleted peer)
786 * Function(Tox *tox, int groupnumber, void *userdata) 787 * Function(Tox *tox, int groupnumber, void *userdata)
787 */ 788 */
788void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *), void *userdata) 789void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *),
790 void *userdata)
789{ 791{
790 m->group_namelistchange = function; 792 m->group_namelistchange = function;
791 m->group_namelistchange_userdata = userdata; 793 m->group_namelistchange_userdata = userdata;
@@ -794,10 +796,12 @@ void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m
794static int get_chat_num(Messenger *m, Group_Chat *chat) 796static int get_chat_num(Messenger *m, Group_Chat *chat)
795{ 797{
796 uint32_t i; 798 uint32_t i;
799
797 for (i = 0; i < m->numchats; ++i) { //TODO: remove this 800 for (i = 0; i < m->numchats; ++i) { //TODO: remove this
798 if (m->chats[i] == chat) 801 if (m->chats[i] == chat)
799 return i; 802 return i;
800 } 803 }
804
801 return -1; 805 return -1;
802} 806}
803 807
@@ -805,6 +809,7 @@ static void group_message_function(Group_Chat *chat, int peer_number, uint8_t *m
805{ 809{
806 Messenger *m = userdata; 810 Messenger *m = userdata;
807 int i = get_chat_num(m, chat); 811 int i = get_chat_num(m, chat);
812
808 if (i == -1) 813 if (i == -1)
809 return; 814 return;
810 815
@@ -816,6 +821,7 @@ static void group_namelistchange_function(Group_Chat *chat, int peer, uint8_t ch
816{ 821{
817 Messenger *m = userdata; 822 Messenger *m = userdata;
818 int i = get_chat_num(m, chat); 823 int i = get_chat_num(m, chat);
824
819 if (i == -1) 825 if (i == -1)
820 return; 826 return;
821 827
@@ -1528,6 +1534,7 @@ void kill_messenger(Messenger *m)
1528 * This requires the other modules to expose cleanup functions. 1534 * This requires the other modules to expose cleanup functions.
1529 */ 1535 */
1530 uint32_t i, numchats = m->numchats; 1536 uint32_t i, numchats = m->numchats;
1537
1531 for (i = 0; i < numchats; ++i) 1538 for (i = 0; i < numchats; ++i)
1532 del_groupchat(m, i); 1539 del_groupchat(m, i);
1533 1540
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 6fc23db4..579516f8 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -462,7 +462,8 @@ void m_callback_group_message(Messenger *m, void (*function)(Messenger *m, int,
462 * It gets called every time the name list changes(new peer/name, deleted peer) 462 * It gets called every time the name list changes(new peer/name, deleted peer)
463 * Function(Tox *tox, int groupnumber, void *userdata) 463 * Function(Tox *tox, int groupnumber, void *userdata)
464 */ 464 */
465void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *), void *userdata); 465void m_callback_group_namelistchange(Messenger *m, void (*function)(Messenger *m, int, int, uint8_t, void *),
466 void *userdata);
466 467
467/* Creates a new groupchat and puts it in the chats array. 468/* Creates a new groupchat and puts it in the chats array.
468 * 469 *
@@ -512,7 +513,7 @@ int group_message_send(Messenger *m, int groupnumber, uint8_t *message, uint32_t
512int group_number_peers(Messenger *m, int groupnumber); 513int group_number_peers(Messenger *m, int groupnumber);
513 514
514/* List all the peers in the group chat. 515/* List all the peers in the group chat.
515 * 516 *
516 * Copies the names of the peers to the name[length][MAX_NICK_BYTES] array. 517 * Copies the names of the peers to the name[length][MAX_NICK_BYTES] array.
517 * 518 *
518 * returns the number of peers on success. 519 * returns the number of peers on success.
diff --git a/toxcore/assoc.c b/toxcore/assoc.c
index 4dc91671..0177ea0c 100644
--- a/toxcore/assoc.c
+++ b/toxcore/assoc.c
@@ -908,8 +908,8 @@ void Assoc_status(Assoc *assoc)
908 entry->used_at ? (int)(unix_time() - entry->used_at) : 0, 908 entry->used_at ? (int)(unix_time() - entry->used_at) : 0,
909 entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0, 909 entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0,
910 entry->seen_at ? (entry->seen_family == AF_INET ? '4' : (entry->seen_family == AF_INET6 ? '6' : '?')) : '?', 910 entry->seen_at ? (entry->seen_family == AF_INET ? '4' : (entry->seen_family == AF_INET6 ? '6' : '?')) : '?',
911 entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0, 911 entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0,
912 entry->heard_at ? (entry->heard_family == AF_INET ? '4' : (entry->heard_family == AF_INET6 ? '6' : '?')) : '?'); 912 entry->heard_at ? (entry->heard_family == AF_INET ? '4' : (entry->heard_family == AF_INET6 ? '6' : '?')) : '?');
913 loglog(logbuffer); 913 loglog(logbuffer);
914 total++; 914 total++;
915 } 915 }
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c
index 16d8f344..f6574ae9 100644
--- a/toxcore/group_chats.c
+++ b/toxcore/group_chats.c
@@ -236,6 +236,7 @@ static int delpeer(Group_Chat *chat, int peernum)
236 return -1; 236 return -1;
237 237
238 uint32_t i; 238 uint32_t i;
239
239 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* If peer is in close list, time it out forcefully. */ 240 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* If peer is in close list, time it out forcefully. */
240 if (id_equal(chat->close[i].client_id, chat->group[peernum].client_id)) { 241 if (id_equal(chat->close[i].client_id, chat->group[peernum].client_id)) {
241 chat->close[i].last_recv = 0; 242 chat->close[i].last_recv = 0;
@@ -641,7 +642,8 @@ void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat,
641 chat->group_message_userdata = userdata; 642 chat->group_message_userdata = userdata;
642} 643}
643 644
644void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *), void *userdata) 645void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *),
646 void *userdata)
645{ 647{
646 chat->peer_namelistchange = function; 648 chat->peer_namelistchange = function;
647 chat->group_namelistchange_userdata = userdata; 649 chat->group_namelistchange_userdata = userdata;
@@ -655,9 +657,11 @@ uint32_t group_numpeers(Group_Chat *chat)
655uint32_t group_client_names(Group_Chat *chat, uint8_t names[][MAX_NICK_BYTES], uint16_t length) 657uint32_t group_client_names(Group_Chat *chat, uint8_t names[][MAX_NICK_BYTES], uint16_t length)
656{ 658{
657 uint32_t i; 659 uint32_t i;
660
658 for (i = 0; i < chat->numpeers && i < length; ++i) { 661 for (i = 0; i < chat->numpeers && i < length; ++i) {
659 group_peername(chat, i, names[i]); 662 group_peername(chat, i, names[i]);
660 } 663 }
664
661 return i; 665 return i;
662} 666}
663 667
diff --git a/toxcore/group_chats.h b/toxcore/group_chats.h
index 33773785..a43173ab 100644
--- a/toxcore/group_chats.h
+++ b/toxcore/group_chats.h
@@ -109,7 +109,8 @@ typedef enum {
109 CHAT_CHANGE_PEER_NAME, 109 CHAT_CHANGE_PEER_NAME,
110} CHAT_CHANGE; 110} CHAT_CHANGE;
111 111
112void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *), void *userdata); 112void callback_namelistchange(Group_Chat *chat, void (*function)(Group_Chat *chat, int peer, uint8_t change, void *),
113 void *userdata);
113 114
114/* 115/*
115 * Send a message to the group. 116 * Send a message to the group.
diff --git a/toxcore/network.h b/toxcore/network.h
index 88cfaf17..060240f4 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -129,7 +129,7 @@ typedef union {
129} IP6; 129} IP6;
130 130
131typedef struct { 131typedef struct {
132 sa_family_t family; 132 uint16_t family;
133 union { 133 union {
134 IP4 ip4; 134 IP4 ip4;
135 IP6 ip6; 135 IP6 ip6;
@@ -238,9 +238,9 @@ typedef struct {
238typedef struct { 238typedef struct {
239 Packet_Handles packethandlers[256]; 239 Packet_Handles packethandlers[256];
240 240
241 /* Our UDP socket. */
242 sa_family_t family; 241 sa_family_t family;
243 uint16_t port; 242 uint16_t port;
243 /* Our UDP socket. */
244 sock_t sock; 244 sock_t sock;
245 uint64_t send_fail_eagain; 245 uint64_t send_fail_eagain;
246} Networking_Core; 246} Networking_Core;
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 487f2517..a8d41d7f 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -314,7 +314,7 @@ void tox_callback_friend_request(Tox *tox, void (*function)(uint8_t *, uint8_t *
314 * Function format is: function(int friendnumber, uint8_t * message, uint32_t length) 314 * Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
315 */ 315 */
316void tox_callback_friend_message(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *), 316void tox_callback_friend_message(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
317 void *userdata) 317 void *userdata)
318{ 318{
319 Messenger *m = tox; 319 Messenger *m = tox;
320 m_callback_friendmessage(m, function, userdata); 320 m_callback_friendmessage(m, function, userdata);
@@ -334,7 +334,7 @@ void tox_callback_action(Tox *tox, void (*function)(Messenger *tox, int, uint8_t
334 * You are not responsible for freeing newname. 334 * You are not responsible for freeing newname.
335 */ 335 */
336void tox_callback_name_change(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *), 336void tox_callback_name_change(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
337 void *userdata) 337 void *userdata)
338{ 338{
339 Messenger *m = tox; 339 Messenger *m = tox;
340 m_callback_namechange(m, function, userdata); 340 m_callback_namechange(m, function, userdata);
@@ -345,7 +345,7 @@ void tox_callback_name_change(Tox *tox, void (*function)(Messenger *tox, int, ui
345 * You are not responsible for freeing newstatus. 345 * You are not responsible for freeing newstatus.
346 */ 346 */
347void tox_callback_status_message(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *), 347void tox_callback_status_message(Tox *tox, void (*function)(Messenger *tox, int, uint8_t *, uint16_t, void *),
348 void *userdata) 348 void *userdata)
349{ 349{
350 Messenger *m = tox; 350 Messenger *m = tox;
351 m_callback_statusmessage(m, function, userdata); 351 m_callback_statusmessage(m, function, userdata);
@@ -542,8 +542,8 @@ uint32_t tox_get_chatlist(Tox *tox, int *out_list, uint32_t list_size)
542 * Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata) 542 * Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
543 */ 543 */
544void tox_callback_file_send_request(Tox *tox, void (*function)(Messenger *tox, int, uint8_t, uint64_t, uint8_t *, 544void tox_callback_file_send_request(Tox *tox, void (*function)(Messenger *tox, int, uint8_t, uint64_t, uint8_t *,
545 uint16_t, 545 uint16_t,
546 void *), void *userdata) 546 void *), void *userdata)
547{ 547{
548 Messenger *m = tox; 548 Messenger *m = tox;
549 callback_file_sendrequest(m, function, userdata); 549 callback_file_sendrequest(m, function, userdata);
@@ -589,7 +589,7 @@ int tox_new_file_sender(Tox *tox, int friendnumber, uint64_t filesize, uint8_t *
589 * return -1 on failure 589 * return -1 on failure
590 */ 590 */
591int tox_file_send_control(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, 591int tox_file_send_control(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
592 uint8_t *data, uint16_t length) 592 uint8_t *data, uint16_t length)
593{ 593{
594 Messenger *m = tox; 594 Messenger *m = tox;
595 return file_control(m, friendnumber, send_receive, filenumber, message_id, data, length); 595 return file_control(m, friendnumber, send_receive, filenumber, message_id, data, length);
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 9f84876e..d19548fb 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -298,7 +298,7 @@ void tox_callback_friend_request(Tox *tox, void (*function)(uint8_t *, uint8_t *
298 * Function format is: function(int friendnumber, uint8_t * message, uint32_t length) 298 * Function format is: function(int friendnumber, uint8_t * message, uint32_t length)
299 */ 299 */
300void tox_callback_friend_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *), 300void tox_callback_friend_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
301 void *userdata); 301 void *userdata);
302 302
303/* Set the function that will be executed when an action from a friend is received. 303/* Set the function that will be executed when an action from a friend is received.
304 * Function format is: function(int friendnumber, uint8_t * action, uint32_t length) 304 * Function format is: function(int friendnumber, uint8_t * action, uint32_t length)
@@ -310,14 +310,14 @@ void tox_callback_action(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, ui
310 * You are not responsible for freeing newname 310 * You are not responsible for freeing newname
311 */ 311 */
312void tox_callback_name_change(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *), 312void tox_callback_name_change(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
313 void *userdata); 313 void *userdata);
314 314
315/* Set the callback for status message changes. 315/* Set the callback for status message changes.
316 * function(int friendnumber, uint8_t *newstatus, uint16_t length) 316 * function(int friendnumber, uint8_t *newstatus, uint16_t length)
317 * You are not responsible for freeing newstatus. 317 * You are not responsible for freeing newstatus.
318 */ 318 */
319void tox_callback_status_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *), 319void tox_callback_status_message(Tox *tox, void (*function)(Tox *tox, int, uint8_t *, uint16_t, void *),
320 void *userdata); 320 void *userdata);
321 321
322/* Set the callback for status type changes. 322/* Set the callback for status type changes.
323 * function(int friendnumber, USERSTATUS kind) 323 * function(int friendnumber, USERSTATUS kind)
@@ -374,7 +374,8 @@ typedef enum {
374 TOX_CHAT_CHANGE_PEER_NAME, 374 TOX_CHAT_CHANGE_PEER_NAME,
375} TOX_CHAT_CHANGE; 375} TOX_CHAT_CHANGE;
376 376
377void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *), void *userdata); 377void tox_callback_group_namelist_change(Tox *tox, void (*function)(Tox *tox, int, int, uint8_t, void *),
378 void *userdata);
378 379
379/* Creates a new groupchat and puts it in the chats array. 380/* Creates a new groupchat and puts it in the chats array.
380 * 381 *
@@ -485,7 +486,7 @@ enum {
485 * Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata) 486 * Function(Tox *tox, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *userdata)
486 */ 487 */
487void tox_callback_file_send_request(Tox *tox, void (*function)(Tox *m, int, uint8_t, uint64_t, uint8_t *, uint16_t, 488void tox_callback_file_send_request(Tox *tox, void (*function)(Tox *m, int, uint8_t, uint64_t, uint8_t *, uint16_t,
488 void *), void *userdata); 489 void *), void *userdata);
489 490
490/* Set the callback for file control requests. 491/* Set the callback for file control requests.
491 * 492 *
@@ -523,7 +524,7 @@ int tox_new_file_sender(Tox *tox, int friendnumber, uint64_t filesize, uint8_t *
523 * return -1 on failure 524 * return -1 on failure
524 */ 525 */
525int tox_file_send_control(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, 526int tox_file_send_control(Tox *tox, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
526 uint8_t *data, uint16_t length); 527 uint8_t *data, uint16_t length);
527 528
528/* Send file data. 529/* Send file data.
529 * 530 *