summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2014-02-15 20:44:33 +0100
committermannol <eniz_vukovic@hotmail.com>2014-02-16 19:11:55 -0500
commit393433ce9910c3dffed9090c7965654f23a8e7a8 (patch)
treeb96e08543fa3a647099cb6f3a9e55836453f51bc /toxcore
parent292708c33634ee0b9a2243a2181018565558bc5c (diff)
Public header ready to go
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/DHT.c10
-rw-r--r--toxcore/Messenger.c158
-rw-r--r--toxcore/Messenger.h34
-rwxr-xr-xtoxcore/event.c1
-rw-r--r--toxcore/friend_requests.c3
-rw-r--r--toxcore/group_chats.c30
-rw-r--r--toxcore/network.c4
-rw-r--r--toxcore/network.h9
-rw-r--r--toxcore/onion.c24
-rw-r--r--toxcore/onion.h1
-rw-r--r--toxcore/onion_announce.c2
-rw-r--r--toxcore/onion_client.c29
-rw-r--r--toxcore/onion_client.h2
-rw-r--r--toxcore/tox.c7
-rw-r--r--toxcore/tox.h10
15 files changed, 308 insertions, 16 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 02175c2a..982b06c4 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -379,6 +379,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
379int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN, 379int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN,
380 uint8_t want_good) 380 uint8_t want_good)
381{ 381{
382 memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format));
382#ifdef ENABLE_ASSOC_DHT 383#ifdef ENABLE_ASSOC_DHT
383 384
384 if (!dht->assoc) 385 if (!dht->assoc)
@@ -1249,9 +1250,9 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id)
1249 --dht->num_friends; 1250 --dht->num_friends;
1250 1251
1251 if (dht->num_friends != i) { 1252 if (dht->num_friends != i) {
1252 memcpy( dht->friends_list[i].client_id, 1253 memcpy( &dht->friends_list[i],
1253 dht->friends_list[dht->num_friends].client_id, 1254 &dht->friends_list[dht->num_friends],
1254 CLIENT_ID_SIZE ); 1255 sizeof(DHT_Friend) );
1255 } 1256 }
1256 1257
1257 if (dht->num_friends == 0) { 1258 if (dht->num_friends == 0) {
@@ -1553,7 +1554,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
1553 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1554 IP_Port ip_list[MAX_FRIEND_CLIENTS];
1554 int ip_num = friend_iplist(dht, ip_list, num); 1555 int ip_num = friend_iplist(dht, ip_list, num);
1555 1556
1556 if (ip_num < (MAX_FRIEND_CLIENTS / 2)) 1557 if (ip_num < (MAX_FRIEND_CLIENTS / 4))
1557 return 0; /* Reason for that? */ 1558 return 0; /* Reason for that? */
1558 1559
1559 DHT_Friend *friend = &dht->friends_list[num]; 1560 DHT_Friend *friend = &dht->friends_list[num];
@@ -2394,7 +2395,6 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length,
2394 num = length / sizeof(DHT_Friend); 2395 num = length / sizeof(DHT_Friend);
2395 2396
2396 for (i = 0; i < num; ++i) { 2397 for (i = 0; i < num; ++i) {
2397 DHT_addfriend(dht, friend_list[i].client_id);
2398 2398
2399 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 2399 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2400 Client_data *client = &friend_list[i].client_list[j]; 2400 Client_data *client = &friend_list[i].client_list[j];
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index c1301767..692d3d0e 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -43,6 +43,71 @@ static uint8_t friend_not_valid(Messenger *m, int friendnumber)
43 return (unsigned int)friendnumber >= m->numfriends; 43 return (unsigned int)friendnumber >= m->numfriends;
44} 44}
45 45
46static int add_online_friend(Messenger *m, int friendnumber)
47{
48 if (friend_not_valid(m, friendnumber))
49 return -1;
50
51 IP_Port temp_ip_port = get_friend_ipport(m, friendnumber);
52
53 if (temp_ip_port.port == 0)
54 return -1;
55
56 uint32_t i;
57
58 for (i = 0; i < m->numonline_friends; ++i) {
59 if (m->online_friendlist[i].friend_num == (uint32_t)friendnumber)
60 return 0;
61 }
62
63 Online_Friend *temp;
64 temp = realloc(m->online_friendlist, sizeof(Online_Friend) * (m->numonline_friends + 1));
65
66 if (temp == NULL)
67 return -1;
68
69 m->online_friendlist = temp;
70 m->online_friendlist[m->numonline_friends].friend_num = friendnumber;
71 m->online_friendlist[m->numonline_friends].ip_port = temp_ip_port;
72 ++m->numonline_friends;
73 return 0;
74}
75
76
77static int remove_online_friend(Messenger *m, int friendnumber)
78{
79 uint32_t i;
80 Online_Friend *temp;
81
82 for (i = 0; i < m->numonline_friends; ++i) {
83 /* Equal */
84 if (m->online_friendlist[i].friend_num == (uint32_t)friendnumber) {
85 --m->numonline_friends;
86
87 if (m->numonline_friends != i) {
88 memcpy( &m->online_friendlist[i],
89 &m->online_friendlist[m->numonline_friends],
90 sizeof(Online_Friend) );
91 }
92
93 if (m->numonline_friends == 0) {
94 free(m->online_friendlist);
95 m->online_friendlist = NULL;
96 return 0;
97 }
98
99 temp = realloc(m->online_friendlist, sizeof(Online_Friend) * (m->numonline_friends));
100
101 if (temp == NULL)
102 return -1;
103
104 m->online_friendlist = temp;
105 return 0;
106 }
107 }
108
109 return -1;
110}
46/* Set the size of the friend list to numfriends. 111/* Set the size of the friend list to numfriends.
47 * 112 *
48 * return -1 if realloc fails. 113 * return -1 if realloc fails.
@@ -273,6 +338,9 @@ int m_delfriend(Messenger *m, int friendnumber)
273 if (friend_not_valid(m, friendnumber)) 338 if (friend_not_valid(m, friendnumber))
274 return -1; 339 return -1;
275 340
341 if (m->friendlist[friendnumber].status == FRIEND_ONLINE)
342 remove_online_friend(m, friendnumber);
343
276 onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); 344 onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum);
277 crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); 345 crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id);
278 free(m->friendlist[friendnumber].statusmessage); 346 free(m->friendlist[friendnumber].statusmessage);
@@ -650,12 +718,17 @@ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, in
650 m->friend_connectionstatuschange = function; 718 m->friend_connectionstatuschange = function;
651 m->friend_connectionstatuschange_userdata = userdata; 719 m->friend_connectionstatuschange_userdata = userdata;
652} 720}
721
722void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void *),
723 void *userdata)
724{
725 m->friend_connectionstatuschange_internal = function;
726 m->friend_connectionstatuschange_internal_userdata = userdata;
727}
728
653static void break_files(Messenger *m, int friendnumber); 729static void break_files(Messenger *m, int friendnumber);
654static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status) 730static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status)
655{ 731{
656 if (!m->friend_connectionstatuschange)
657 return;
658
659 if (status == NOFRIEND) 732 if (status == NOFRIEND)
660 return; 733 return;
661 734
@@ -665,10 +738,19 @@ static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_
665 onion_set_friend_online(m->onion_c, m->friendlist[friendnumber].onion_friendnum, is_online); 738 onion_set_friend_online(m->onion_c, m->friendlist[friendnumber].onion_friendnum, is_online);
666 739
667 if (is_online != was_online) { 740 if (is_online != was_online) {
668 if (was_online) 741 if (was_online) {
669 break_files(m, friendnumber); 742 break_files(m, friendnumber);
743 remove_online_friend(m, friendnumber);
744 } else {
745 add_online_friend(m, friendnumber);
746 }
747
748 if (m->friend_connectionstatuschange)
749 m->friend_connectionstatuschange(m, friendnumber, is_online, m->friend_connectionstatuschange_userdata);
670 750
671 m->friend_connectionstatuschange(m, friendnumber, is_online, m->friend_connectionstatuschange_userdata); 751 if (m->friend_connectionstatuschange_internal)
752 m->friend_connectionstatuschange_internal(m, friendnumber, is_online,
753 m->friend_connectionstatuschange_internal_userdata);
672 } 754 }
673} 755}
674 756
@@ -814,6 +896,8 @@ static void group_message_function(Group_Chat *chat, int peer_number, uint8_t *m
814 if (i == -1) 896 if (i == -1)
815 return; 897 return;
816 898
899 message[length - 1] = 0; /* Force NULL terminator */
900
817 if (m->group_message) 901 if (m->group_message)
818 (*m->group_message)(m, i, peer_number, message, length, m->group_message_userdata); 902 (*m->group_message)(m, i, peer_number, message, length, m->group_message_userdata);
819} 903}
@@ -826,6 +910,8 @@ static void group_action_function(Group_Chat *chat, int peer_number, uint8_t *ac
826 if (i == -1) 910 if (i == -1)
827 return; 911 return;
828 912
913 action[length - 1] = 0; /* Force NULL terminator */
914
829 if (m->group_action) 915 if (m->group_action)
830 (*m->group_action)(m, i, peer_number, action, length, m->group_action_userdata); 916 (*m->group_action)(m, i, peer_number, action, length, m->group_action_userdata);
831} 917}
@@ -1489,6 +1575,60 @@ int m_msi_packet(Messenger *m, int friendnumber, uint8_t *data, uint16_t length)
1489 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length); 1575 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length);
1490} 1576}
1491 1577
1578static int friendnum_from_ip_port(Messenger *m, IP_Port ip_port)
1579{
1580 uint32_t i;
1581
1582 for (i = 0; i < m->numonline_friends; ++i) {
1583 if (ipport_equal(&m->online_friendlist[i].ip_port, &ip_port))
1584 return m->online_friendlist[i].friend_num;
1585 }
1586
1587 return -1;
1588}
1589
1590static int handle_custom_user_packet(void *object, IP_Port source, uint8_t *packet, uint32_t length)
1591{
1592 Messenger *m = object;
1593 int friend_num = friendnum_from_ip_port(m, source);
1594
1595 if (friend_num == -1)
1596 return 1;
1597
1598 if (m->friendlist[friend_num].packethandlers[packet[0] % TOTAL_USERPACKETS].function)
1599 return m->friendlist[friend_num].packethandlers[packet[0] % TOTAL_USERPACKETS].function(
1600 m->friendlist[friend_num].packethandlers[packet[0] % TOTAL_USERPACKETS].object, source, packet, length);
1601
1602 return 1;
1603}
1604
1605
1606int custom_user_packet_registerhandler(Messenger *m, int friendnumber, uint8_t byte, packet_handler_callback cb,
1607 void *object)
1608{
1609 if (friend_not_valid(m, friendnumber))
1610 return -1;
1611
1612 if (byte < NET_PACKET_CUSTOM_RANGE_START || byte >= NET_PACKET_CUSTOM_RANGE_END)
1613 return -1;
1614
1615 m->friendlist[friendnumber].packethandlers[byte % TOTAL_USERPACKETS].function = cb;
1616 m->friendlist[friendnumber].packethandlers[byte % TOTAL_USERPACKETS].object = object;
1617 networking_registerhandler(m->net, byte, handle_custom_user_packet, m);
1618 return 0;
1619}
1620
1621int send_custom_user_packet(Messenger *m, int friendnumber, uint8_t *data, uint32_t length)
1622{
1623 IP_Port ip_port = get_friend_ipport(m, friendnumber);
1624
1625 if (ip_port.port == 0)
1626 return -1;
1627
1628 return sendpacket(m->net, ip_port, data, length);
1629}
1630
1631
1492/* Function to filter out some friend requests*/ 1632/* Function to filter out some friend requests*/
1493static int friend_already_added(uint8_t *client_id, void *data) 1633static int friend_already_added(uint8_t *client_id, void *data)
1494{ 1634{
@@ -1841,6 +1981,8 @@ void do_friends(Messenger *m)
1841 m->friendlist[i].file_receiving[filenumber].size = filesize; 1981 m->friendlist[i].file_receiving[filenumber].size = filesize;
1842 m->friendlist[i].file_receiving[filenumber].transferred = 0; 1982 m->friendlist[i].file_receiving[filenumber].transferred = 0;
1843 1983
1984 data[data_length - 1] = 0; /* Force NULL terminate file name. */
1985
1844 if (m->file_sendrequest) 1986 if (m->file_sendrequest)
1845 (*m->file_sendrequest)(m, i, filenumber, filesize, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t), 1987 (*m->file_sendrequest)(m, i, filenumber, filesize, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t),
1846 m->file_sendrequest_userdata); 1988 m->file_sendrequest_userdata);
@@ -2360,6 +2502,12 @@ uint32_t count_friendlist(Messenger *m)
2360 return ret; 2502 return ret;
2361} 2503}
2362 2504
2505/* Return the number of online friends in the instance m. */
2506uint32_t get_num_online_friends(Messenger *m)
2507{
2508 return m->numonline_friends;
2509}
2510
2363/* Copy a list of valid friend IDs into the array out_list. 2511/* Copy a list of valid friend IDs into the array out_list.
2364 * If out_list is NULL, returns 0. 2512 * If out_list is NULL, returns 0.
2365 * Otherwise, returns the number of elements copied. 2513 * Otherwise, returns the number of elements copied.
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index e09b2f30..ccca8fba 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -155,8 +155,15 @@ typedef struct {
155 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; 155 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
156 int invited_groups[MAX_INVITED_GROUPS]; 156 int invited_groups[MAX_INVITED_GROUPS];
157 uint16_t invited_groups_num; 157 uint16_t invited_groups_num;
158
159 Packet_Handles packethandlers[TOTAL_USERPACKETS];
158} Friend; 160} Friend;
159 161
162typedef struct {
163 uint32_t friend_num;
164 IP_Port ip_port;
165} Online_Friend;
166
160typedef struct Messenger { 167typedef struct Messenger {
161 168
162 Networking_Core *net; 169 Networking_Core *net;
@@ -179,6 +186,9 @@ typedef struct Messenger {
179 Friend *friendlist; 186 Friend *friendlist;
180 uint32_t numfriends; 187 uint32_t numfriends;
181 188
189 Online_Friend *online_friendlist;
190 uint32_t numonline_friends;
191
182 Group_Chat **chats; 192 Group_Chat **chats;
183 uint32_t numchats; 193 uint32_t numchats;
184 194
@@ -200,6 +210,8 @@ typedef struct Messenger {
200 void *friend_statuschange_userdata; 210 void *friend_statuschange_userdata;
201 void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void *); 211 void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void *);
202 void *friend_connectionstatuschange_userdata; 212 void *friend_connectionstatuschange_userdata;
213 void (*friend_connectionstatuschange_internal)(struct Messenger *m, int, uint8_t, void *);
214 void *friend_connectionstatuschange_internal_userdata;
203 215
204 void (*group_invite)(struct Messenger *m, int, uint8_t *, void *); 216 void (*group_invite)(struct Messenger *m, int, uint8_t *, void *);
205 void *group_invite_userdata; 217 void *group_invite_userdata;
@@ -450,6 +462,9 @@ void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, u
450 * It's assumed that when adding friends, their connection status is offline. 462 * It's assumed that when adding friends, their connection status is offline.
451 */ 463 */
452void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void *), void *userdata); 464void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void *), void *userdata);
465/* Same as previous but for internal A/V core usage only */
466void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void *),
467 void *userdata);
453 468
454/**********GROUP CHATS************/ 469/**********GROUP CHATS************/
455 470
@@ -627,6 +642,22 @@ int m_msi_packet(Messenger *m, int friendnumber, uint8_t *data, uint16_t length)
627 642
628/**********************************************/ 643/**********************************************/
629 644
645/* Set handlers for custom user packets (RTP packets for example.)
646 *
647 * return -1 on failure.
648 * return 0 on success.
649 */
650int custom_user_packet_registerhandler(Messenger *m, int friendnumber, uint8_t byte, packet_handler_callback cb,
651 void *object);
652
653/* High level function to send custom user packets.
654 *
655 * return -1 on failure.
656 * return number of bytes sent on success.
657 */
658int send_custom_user_packet(Messenger *m, int friendnumber, uint8_t *data, uint32_t length);
659
660/**********************************************/
630/* Run this at startup. 661/* Run this at startup.
631 * return allocated instance of Messenger on success. 662 * return allocated instance of Messenger on success.
632 * return 0 if there are problems. 663 * return 0 if there are problems.
@@ -682,6 +713,9 @@ int messenger_load_encrypted(Messenger *m, uint8_t *data, uint32_t length, uint8
682 * for copy_friendlist. */ 713 * for copy_friendlist. */
683uint32_t count_friendlist(Messenger *m); 714uint32_t count_friendlist(Messenger *m);
684 715
716/* Return the number of online friends in the instance m. */
717uint32_t get_num_online_friends(Messenger *m);
718
685/* Copy a list of valid friend IDs into the array out_list. 719/* Copy a list of valid friend IDs into the array out_list.
686 * If out_list is NULL, returns 0. 720 * If out_list is NULL, returns 0.
687 * Otherwise, returns the number of elements copied. 721 * Otherwise, returns the number of elements copied.
diff --git a/toxcore/event.c b/toxcore/event.c
index 05e2a03c..2fdc9442 100755
--- a/toxcore/event.c
+++ b/toxcore/event.c
@@ -31,6 +31,7 @@
31#include "event.h" 31#include "event.h"
32 32
33#include "util.h" 33#include "util.h"
34#include "network.h"
34 35
35#define _GNU_SOURCE 36#define _GNU_SOURCE
36 37
diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c
index 5c294c76..9ac72097 100644
--- a/toxcore/friend_requests.c
+++ b/toxcore/friend_requests.c
@@ -140,6 +140,9 @@ static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t
140 return 1; 140 return 1;
141 141
142 addto_receivedlist(fr, source_pubkey); 142 addto_receivedlist(fr, source_pubkey);
143
144 packet[length - 1] = 0; /* Force NULL terminator. */
145
143 (*fr->handle_friendrequest)(source_pubkey, packet + 4, length - 4, fr->handle_friendrequest_userdata); 146 (*fr->handle_friendrequest)(source_pubkey, packet + 4, length - 4, fr->handle_friendrequest_userdata);
144 return 0; 147 return 0;
145} 148}
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c
index 90ffdd14..6dff52ef 100644
--- a/toxcore/group_chats.c
+++ b/toxcore/group_chats.c
@@ -75,6 +75,32 @@ static int peer_in_chat(Group_Chat *chat, uint8_t *client_id)
75 return -1; 75 return -1;
76} 76}
77 77
78/* Compares client_id1 and client_id2 with client_id.
79 *
80 * return 0 if both are same distance.
81 * return 1 if client_id1 is closer.
82 * return 2 if client_id2 is closer.
83 */
84static int id_closest_groupchats(uint8_t *id, uint8_t *id1, uint8_t *id2)
85{
86 size_t i;
87 uint8_t distance1, distance2;
88
89 for (i = 0; i < CLIENT_ID_SIZE; ++i) {
90
91 distance1 = abs(((int8_t *)id)[i] - ((int8_t *)id1)[i]);
92 distance2 = abs(((int8_t *)id)[i] - ((int8_t *)id2)[i]);
93
94 if (distance1 < distance2)
95 return 1;
96
97 if (distance1 > distance2)
98 return 2;
99 }
100
101 return 0;
102}
103
78#define BAD_GROUPNODE_TIMEOUT 30 104#define BAD_GROUPNODE_TIMEOUT 30
79 105
80/* 106/*
@@ -100,7 +126,7 @@ static int peer_okping(Group_Chat *chat, uint8_t *client_id)
100 if (id_equal(chat->close[i].client_id, client_id)) 126 if (id_equal(chat->close[i].client_id, client_id))
101 return -1; 127 return -1;
102 128
103 if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) 129 if (id_closest_groupchats(chat->self_public_key, chat->close[i].client_id, client_id) == 2)
104 ++j; 130 ++j;
105 } 131 }
106 132
@@ -137,7 +163,7 @@ static int add_closepeer(Group_Chat *chat, uint8_t *client_id, IP_Port ip_port)
137 } 163 }
138 164
139 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Replace nodes if given one is closer. */ 165 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Replace nodes if given one is closer. */
140 if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) { 166 if (id_closest_groupchats(chat->self_public_key, chat->close[i].client_id, client_id) == 2) {
141 id_copy(chat->close[i].client_id, client_id); 167 id_copy(chat->close[i].client_id, client_id);
142 chat->close[i].ip_port = ip_port; 168 chat->close[i].ip_port = ip_port;
143 chat->close[i].last_recv = unix_time(); 169 chat->close[i].last_recv = unix_time();
diff --git a/toxcore/network.c b/toxcore/network.c
index 1186a468..839618bf 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -540,8 +540,10 @@ Networking_Core *new_networking(IP ip, uint16_t port)
540 addr6->sin6_scope_id = 0; 540 addr6->sin6_scope_id = 0;
541 541
542 portptr = &addr6->sin6_port; 542 portptr = &addr6->sin6_port;
543 } else 543 } else {
544 free(temp);
544 return NULL; 545 return NULL;
546 }
545 547
546 if (ip.family == AF_INET6) { 548 if (ip.family == AF_INET6) {
547 char ipv6only = 0; 549 char ipv6only = 0;
diff --git a/toxcore/network.h b/toxcore/network.h
index 4c7f1a83..aaf89f19 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -129,6 +129,12 @@ typedef int sock_t;
129#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ 129#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */
130#define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ 130#define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */
131 131
132/* Range of ids that custom user packets can use. */
133#define NET_PACKET_CUSTOM_RANGE_START 64
134#define NET_PACKET_CUSTOM_RANGE_END 96
135
136#define TOTAL_USERPACKETS (NET_PACKET_CUSTOM_RANGE_END - NET_PACKET_CUSTOM_RANGE_START)
137
132/* See: docs/Prevent_Tracking.txt and onion.{c, h} */ 138/* See: docs/Prevent_Tracking.txt and onion.{c, h} */
133#define NET_PACKET_ONION_SEND_INITIAL 128 139#define NET_PACKET_ONION_SEND_INITIAL 128
134#define NET_PACKET_ONION_SEND_1 129 140#define NET_PACKET_ONION_SEND_1 129
@@ -143,6 +149,9 @@ typedef int sock_t;
143#define NET_PACKET_ONION_RECV_2 141 149#define NET_PACKET_ONION_RECV_2 141
144#define NET_PACKET_ONION_RECV_1 142 150#define NET_PACKET_ONION_RECV_1 142
145 151
152/* Only used for bootstrap servers */
153#define BOOTSTRAP_INFO_PACKET_ID 240
154
146 155
147#define TOX_PORTRANGE_FROM 33445 156#define TOX_PORTRANGE_FROM 33445
148#define TOX_PORTRANGE_TO 33545 157#define TOX_PORTRANGE_TO 33545
diff --git a/toxcore/onion.c b/toxcore/onion.c
index 961f5bd5..578621cc 100644
--- a/toxcore/onion.c
+++ b/toxcore/onion.c
@@ -24,6 +24,7 @@
24#endif 24#endif
25 25
26#include "onion.h" 26#include "onion.h"
27#include "util.h"
27 28
28#define MAX_ONION_SIZE MAX_DATA_SIZE 29#define MAX_ONION_SIZE MAX_DATA_SIZE
29 30
@@ -36,6 +37,16 @@
36#define SEND_2 ONION_SEND_2 37#define SEND_2 ONION_SEND_2
37#define SEND_1 ONION_SEND_1 38#define SEND_1 ONION_SEND_1
38 39
40/* Change symmetric keys every hour to make paths expire eventually. */
41#define KEY_REFRESH_INTERVAL (60 * 60)
42static void change_symmetric_key(Onion *onion)
43{
44 if (is_timeout(onion->timestamp, KEY_REFRESH_INTERVAL)) {
45 new_symmetric_key(onion->secret_symmetric_key);
46 onion->timestamp = unix_time();
47 }
48}
49
39/* Create and send a onion packet. 50/* Create and send a onion packet.
40 * 51 *
41 * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data 52 * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data
@@ -126,6 +137,8 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui
126 if (length <= 1 + SEND_1) 137 if (length <= 1 + SEND_1)
127 return 1; 138 return 1;
128 139
140 change_symmetric_key(onion);
141
129 uint8_t plain[MAX_ONION_SIZE]; 142 uint8_t plain[MAX_ONION_SIZE];
130 143
131 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1, 144 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1,
@@ -170,6 +183,8 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t
170 if (length <= 1 + SEND_2) 183 if (length <= 1 + SEND_2)
171 return 1; 184 return 1;
172 185
186 change_symmetric_key(onion);
187
173 uint8_t plain[MAX_ONION_SIZE]; 188 uint8_t plain[MAX_ONION_SIZE];
174 189
175 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1, 190 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1,
@@ -217,6 +232,8 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t
217 if (length <= 1 + SEND_3) 232 if (length <= 1 + SEND_3)
218 return 1; 233 return 1;
219 234
235 change_symmetric_key(onion);
236
220 uint8_t plain[MAX_ONION_SIZE]; 237 uint8_t plain[MAX_ONION_SIZE];
221 238
222 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1, 239 int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1,
@@ -263,6 +280,8 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t
263 if (length <= 1 + RETURN_3) 280 if (length <= 1 + RETURN_3)
264 return 1; 281 return 1;
265 282
283 change_symmetric_key(onion);
284
266 uint8_t plain[sizeof(IP_Port) + RETURN_2]; 285 uint8_t plain[sizeof(IP_Port) + RETURN_2];
267 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, 286 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES,
268 sizeof(IP_Port) + RETURN_2 + crypto_secretbox_MACBYTES, plain); 287 sizeof(IP_Port) + RETURN_2 + crypto_secretbox_MACBYTES, plain);
@@ -295,6 +314,8 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t
295 if (length <= 1 + RETURN_2) 314 if (length <= 1 + RETURN_2)
296 return 1; 315 return 1;
297 316
317 change_symmetric_key(onion);
318
298 uint8_t plain[sizeof(IP_Port) + RETURN_1]; 319 uint8_t plain[sizeof(IP_Port) + RETURN_1];
299 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, 320 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES,
300 sizeof(IP_Port) + RETURN_1 + crypto_secretbox_MACBYTES, plain); 321 sizeof(IP_Port) + RETURN_1 + crypto_secretbox_MACBYTES, plain);
@@ -327,6 +348,8 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t
327 if (length <= 1 + RETURN_1) 348 if (length <= 1 + RETURN_1)
328 return 1; 349 return 1;
329 350
351 change_symmetric_key(onion);
352
330 IP_Port send_to; 353 IP_Port send_to;
331 354
332 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, 355 int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES,
@@ -358,6 +381,7 @@ Onion *new_onion(DHT *dht)
358 onion->dht = dht; 381 onion->dht = dht;
359 onion->net = dht->c->lossless_udp->net; 382 onion->net = dht->c->lossless_udp->net;
360 new_symmetric_key(onion->secret_symmetric_key); 383 new_symmetric_key(onion->secret_symmetric_key);
384 onion->timestamp = unix_time();
361 385
362 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion); 386 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion);
363 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion); 387 networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion);
diff --git a/toxcore/onion.h b/toxcore/onion.h
index b46dbdfe..a52bcb86 100644
--- a/toxcore/onion.h
+++ b/toxcore/onion.h
@@ -29,6 +29,7 @@ typedef struct {
29 DHT *dht; 29 DHT *dht;
30 Networking_Core *net; 30 Networking_Core *net;
31 uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; 31 uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
32 uint64_t timestamp;
32} Onion; 33} Onion;
33 34
34#define ONION_RETURN_1 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) 35#define ONION_RETURN_1 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES)
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c
index 2ca53896..da40584d 100644
--- a/toxcore/onion_announce.c
+++ b/toxcore/onion_announce.c
@@ -325,7 +325,7 @@ Onion_Announce *new_onion_announce(DHT *dht)
325 return NULL; 325 return NULL;
326 326
327 onion_a->dht = dht; 327 onion_a->dht = dht;
328 onion_a->net = dht->c->lossless_udp->net; 328 onion_a->net = dht->net;
329 new_symmetric_key(onion_a->secret_bytes); 329 new_symmetric_key(onion_a->secret_bytes);
330 330
331 networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_announce_request, onion_a); 331 networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_announce_request, onion_a);
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index 93697c28..c03dfcea 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -390,6 +390,8 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t
390 crypto_box_PUBLICKEYBYTES) != 0) { 390 crypto_box_PUBLICKEYBYTES) != 0) {
391 DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); 391 DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
392 392
393 onion_c->friends_list[friend_num].last_seen = unix_time();
394
393 if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) { 395 if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) {
394 return 1; 396 return 1;
395 } 397 }
@@ -712,6 +714,9 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
712 if ((uint32_t)friend_num >= onion_c->num_friends) 714 if ((uint32_t)friend_num >= onion_c->num_friends)
713 return -1; 715 return -1;
714 716
717 if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1)
718 onion_c->friends_list[friend_num].last_seen = unix_time();
719
715 onion_c->friends_list[friend_num].is_online = is_online; 720 onion_c->friends_list[friend_num].is_online = is_online;
716 721
717 /* This should prevent some clock related issues */ 722 /* This should prevent some clock related issues */
@@ -767,7 +772,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
767 } 772 }
768 773
769 if (count != MAX_ONION_CLIENTS) { 774 if (count != MAX_ONION_CLIENTS) {
770 if (count < rand() % MAX_ONION_CLIENTS) { 775 if (count < (uint32_t)rand() % MAX_ONION_CLIENTS) {
771 Node_format nodes_list[MAX_SENT_NODES]; 776 Node_format nodes_list[MAX_SENT_NODES];
772 uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->friends_list[friendnum].real_client_id, nodes_list, 777 uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->friends_list[friendnum].real_client_id, nodes_list,
773 rand() % 2 ? AF_INET : AF_INET6, 1, 0); 778 rand() % 2 ? AF_INET : AF_INET6, 1, 0);
@@ -788,6 +793,25 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
788 793
789 } 794 }
790} 795}
796
797/* Timeout before which a peer is considered dead and removed from the DHT search. */
798#define DEAD_ONION_TIMEOUT (10 * 60)
799
800static void cleanup_friend(Onion_Client *onion_c, uint16_t friendnum)
801{
802 if (friendnum >= onion_c->num_friends)
803 return;
804
805 if (onion_c->friends_list[friendnum].status == 0)
806 return;
807
808 if (onion_c->friends_list[friendnum].is_fake_clientid && !onion_c->friends_list[friendnum].is_online
809 && is_timeout(onion_c->friends_list[friendnum].last_seen, DEAD_ONION_TIMEOUT)) {
810 onion_c->friends_list[friendnum].is_fake_clientid = 0;
811 DHT_delfriend(onion_c->dht, onion_c->friends_list[friendnum].fake_client_id);
812 }
813}
814
791/* Function to call when onion data packet with contents beginning with byte is received. */ 815/* Function to call when onion data packet with contents beginning with byte is received. */
792void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object) 816void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object)
793{ 817{
@@ -823,7 +847,7 @@ static void do_announce(Onion_Client *onion_c)
823 } 847 }
824 848
825 if (count != MAX_ONION_CLIENTS) { 849 if (count != MAX_ONION_CLIENTS) {
826 if (count < rand() % MAX_ONION_CLIENTS) { 850 if (count < (uint32_t)rand() % MAX_ONION_CLIENTS) {
827 Node_format nodes_list[MAX_SENT_NODES]; 851 Node_format nodes_list[MAX_SENT_NODES];
828 uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list, 852 uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list,
829 rand() % 2 ? AF_INET : AF_INET6, 1, 0); 853 rand() % 2 ? AF_INET : AF_INET6, 1, 0);
@@ -845,6 +869,7 @@ void do_onion_client(Onion_Client *onion_c)
845 869
846 for (i = 0; i < onion_c->num_friends; ++i) { 870 for (i = 0; i < onion_c->num_friends; ++i) {
847 do_friend(onion_c, i); 871 do_friend(onion_c, i);
872 cleanup_friend(onion_c, i);
848 } 873 }
849 874
850 onion_c->last_run = unix_time(); 875 onion_c->last_run = unix_time();
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h
index 708d9093..36b5b5c3 100644
--- a/toxcore/onion_client.h
+++ b/toxcore/onion_client.h
@@ -61,6 +61,8 @@ typedef struct {
61 uint64_t last_fakeid_dht_sent; 61 uint64_t last_fakeid_dht_sent;
62 62
63 uint64_t last_noreplay; 63 uint64_t last_noreplay;
64
65 uint64_t last_seen;
64} Onion_Friend; 66} Onion_Friend;
65 67
66typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); 68typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 04e412be..f4690080 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -289,6 +289,13 @@ uint32_t tox_count_friendlist(Tox *tox)
289 return count_friendlist(m); 289 return count_friendlist(m);
290} 290}
291 291
292/* Return the number of online friends in the instance m. */
293uint32_t tox_get_num_online_friends(Tox *tox)
294{
295 Messenger *m = tox;
296 return get_num_online_friends(m);
297}
298
292/* Copy a list of valid friend IDs into the array out_list. 299/* Copy a list of valid friend IDs into the array out_list.
293 * If out_list is NULL, returns 0. 300 * If out_list is NULL, returns 0.
294 * Otherwise, returns the number of elements copied. 301 * Otherwise, returns the number of elements copied.
diff --git a/toxcore/tox.h b/toxcore/tox.h
index f3118270..447a1146 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -128,6 +128,13 @@ TOX_USERSTATUS;
128typedef struct Tox Tox; 128typedef struct Tox Tox;
129#endif 129#endif
130 130
131/* NOTE: Strings in Tox are all UTF-8, also the last byte in all strings must be NULL (0).
132 *
133 * The length when passing those strings to the core includes that NULL character.
134 *
135 * If you send non NULL terminated strings Tox will force NULL terminates them when it receives them.
136 */
137
131/* return TOX_FRIEND_ADDRESS_SIZE byte address to give to others. 138/* return TOX_FRIEND_ADDRESS_SIZE byte address to give to others.
132 * format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] 139 * format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
133 */ 140 */
@@ -284,6 +291,9 @@ void tox_set_sends_receipts(Tox *tox, int friendnumber, int yesno);
284 * for copy_friendlist. */ 291 * for copy_friendlist. */
285uint32_t tox_count_friendlist(Tox *tox); 292uint32_t tox_count_friendlist(Tox *tox);
286 293
294/* Return the number of online friends in the instance m. */
295uint32_t tox_get_num_online_friends(Tox *tox);
296
287/* Copy a list of valid friend IDs into the array out_list. 297/* Copy a list of valid friend IDs into the array out_list.
288 * If out_list is NULL, returns 0. 298 * If out_list is NULL, returns 0.
289 * Otherwise, returns the number of elements copied. 299 * Otherwise, returns the number of elements copied.