summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml2
-rw-r--r--INSTALL.md2
-rw-r--r--Makefile.am2
-rw-r--r--README.md8
-rw-r--r--auto_tests/TCP_test.c16
-rw-r--r--auto_tests/assoc_test.c2
-rw-r--r--auto_tests/encryptsave_test.c10
-rw-r--r--auto_tests/onion_test.c55
-rw-r--r--auto_tests/toxav_basic_test.c8
-rw-r--r--configure.ac3
-rw-r--r--docs/Avatars.md170
-rw-r--r--docs/TODO19
-rw-r--r--docs/Tox_middle_level_network_protocol.txt68
-rw-r--r--other/bootstrap_daemon/README.md70
-rw-r--r--other/bootstrap_daemon/tox-bootstrapd.conf53
-rw-r--r--other/bootstrap_daemon/tox-bootstrapd.service19
-rw-r--r--other/bootstrap_node_packets.c2
-rwxr-xr-xother/fun/make-funny-savefile.py122
-rw-r--r--other/osx_build_script_toxcore.sh (renamed from osx_build_script_toxcore.txt)0
-rw-r--r--testing/test_avatars.c50
-rw-r--r--tox.spec.in67
-rw-r--r--toxav/Makefile.inc1
-rw-r--r--toxav/av_test.c270
-rw-r--r--toxav/codec.c1
-rw-r--r--toxav/msi.c2
-rw-r--r--toxav/toxav_new_1.c688
-rw-r--r--toxav/toxav_new_1.h329
-rw-r--r--toxcore/DHT.c104
-rw-r--r--toxcore/DHT.h2
-rw-r--r--toxcore/LAN_discovery.c5
-rw-r--r--toxcore/Messenger.c233
-rw-r--r--toxcore/Messenger.h14
-rw-r--r--toxcore/TCP_server.c81
-rw-r--r--toxcore/crypto_core.h1
-rw-r--r--toxcore/friend_requests.c14
-rw-r--r--toxcore/friend_requests.h4
-rw-r--r--toxcore/group.c6
-rw-r--r--toxcore/logger.c36
-rw-r--r--toxcore/logger.h12
-rw-r--r--toxcore/net_crypto.c83
-rw-r--r--toxcore/net_crypto.h13
-rw-r--r--toxcore/onion.c59
-rw-r--r--toxcore/onion_announce.c2
-rw-r--r--toxcore/onion_client.c227
-rw-r--r--toxcore/onion_client.h41
-rw-r--r--toxcore/ping.c10
-rw-r--r--toxcore/tox.c30
-rw-r--r--toxcore/tox.h25
-rw-r--r--toxencryptsave/toxencryptsave.c4
50 files changed, 1345 insertions, 1703 deletions
diff --git a/.gitignore b/.gitignore
index 4397a1c1..4d92363b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,3 +71,6 @@ toxcore-android-*
71 71
72# cscope files list 72# cscope files list
73cscope.files 73cscope.files
74
75# rpm
76tox.spec
diff --git a/.travis.yml b/.travis.yml
index 304c52e5..c90a92f2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,7 @@ before_script:
7 #installing libsodium, needed for Core 7 #installing libsodium, needed for Core
8 - git clone git://github.com/jedisct1/libsodium.git > /dev/null 8 - git clone git://github.com/jedisct1/libsodium.git > /dev/null
9 - cd libsodium 9 - cd libsodium
10 - git checkout tags/0.7.0 > /dev/null 10 - git checkout tags/1.0.0 > /dev/null
11 - ./autogen.sh > /dev/null 11 - ./autogen.sh > /dev/null
12 - ./configure > /dev/null 12 - ./configure > /dev/null
13 - make check -j3 > /dev/null 13 - make check -j3 > /dev/null
diff --git a/INSTALL.md b/INSTALL.md
index 22865264..c2a8c0d9 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -105,6 +105,8 @@ sudo make install
105You need the latest XCode with the Developer Tools (Preferences -> Downloads -> Command Line Tools). 105You need the latest XCode with the Developer Tools (Preferences -> Downloads -> Command Line Tools).
106The following libraries are required along with libsodium and cmake for Mountain Lion and XCode 4.6.3 install libtool, automake and autoconf. You can download them with Homebrew, or install them manually. 106The following libraries are required along with libsodium and cmake for Mountain Lion and XCode 4.6.3 install libtool, automake and autoconf. You can download them with Homebrew, or install them manually.
107 107
108**Note: OS X users can also install Toxcore using [osx_build_script_toxcore.sh](other/osx_build_script_toxcore.sh)**
109
108There are no binaries/executables going to /bin/ or /usr/bin/ now. Everything is compiled and ran from the inside your local branch. See [Usage](#usage) below. 110There are no binaries/executables going to /bin/ or /usr/bin/ now. Everything is compiled and ran from the inside your local branch. See [Usage](#usage) below.
109<a name="homebrew" /> 111<a name="homebrew" />
110####Homebrew: 112####Homebrew:
diff --git a/Makefile.am b/Makefile.am
index 6b28280e..995620ef 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,7 +11,9 @@ CLEANFILES = $(top_builddir)/libtoxcore.pc
11 11
12 12
13EXTRA_DIST = \ 13EXTRA_DIST = \
14 README.md \
14 libtoxcore.pc.in \ 15 libtoxcore.pc.in \
16 tox.spec \
15 dist-build/android-arm.sh \ 17 dist-build/android-arm.sh \
16 dist-build/android-armv7.sh \ 18 dist-build/android-armv7.sh \
17 dist-build/android-x86.sh \ 19 dist-build/android-x86.sh \
diff --git a/README.md b/README.md
index e48d7ddb..2a7945f9 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,8 @@
3 3
4With the rise of governmental monitoring programs, Tox, a FOSS initiative, aims to be an easy to use, all-in-one communication platform that ensures their users full privacy and secure message delivery.<br /> <br /> 4With the rise of governmental monitoring programs, Tox, a FOSS initiative, aims to be an easy to use, all-in-one communication platform that ensures their users full privacy and secure message delivery.<br /> <br />
5 5
6[**Website**](https://tox.im) **|** [**Download**](https://wiki.tox.im/Binaries) **|** [**Wiki**](https://wiki.tox.im/) **|** [**Blog**](https://blog.libtoxcore.so/) **|** [**FAQ**](https://wiki.tox.im/FAQ) **|** [**Binaries**](https://wiki.tox.im/Binaries) **|** [**Clients**](https://wiki.tox.im/Client) **|** [**Compiling**](/INSTALL.md) **|** 6[**Website**](https://tox.im) **|** [**Wiki**](https://wiki.tox.im/) **|** [**Blog**](https://blog.tox.im/) **|** [**FAQ**](https://wiki.tox.im/FAQ) **|** [**Binaries/Downloads**](https://wiki.tox.im/Binaries) **|** [**Clients**](https://wiki.tox.im/Client) **|** [**Compiling**](/INSTALL.md) **|**
7[**API**](https://libtoxcore.so/) **|** [**bugs**](http://tox.lighthouseapp.com/projects/123754-tox/tickets) **|** [**help and suggestions**](http://support.libtoxcore.so) **|** 7[**API**](https://libtoxcore.so/) **|** [**Bugs**](http://tox.lighthouseapp.com/) **|** [**Help and Suggestions**](http://support.libtoxcore.so) **|** **IRC Channel:** [#tox@freenode](https://webchat.freenode.net/?channels=tox)
8**IRC:** #tox@freenode
9 8
10 9
11## The Complex Stuff: 10## The Complex Stuff:
@@ -38,6 +37,7 @@ The goal of this project is to create a configuration-free P2P Skype replacement
38- [Compiling](/INSTALL.md) 37- [Compiling](/INSTALL.md)
39- [DHT Protocol](/docs/updates/DHT.md)<br /> 38- [DHT Protocol](/docs/updates/DHT.md)<br />
40- [Crypto](/docs/updates/Crypto.md)<br /> 39- [Crypto](/docs/updates/Crypto.md)<br />
41- [Ideas](https://wiki.tox.im/index.php/Ideas) 40
41Additional developer documentation can be found at [Libtoxcore.so](https://libtoxcore.so/)
42 42
43[String]: https://en.wikipedia.org/wiki/String_(computer_science) 43[String]: https://en.wikipedia.org/wiki/String_(computer_science)
diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c
index 566013d7..e222cf01 100644
--- a/auto_tests/TCP_test.c
+++ b/auto_tests/TCP_test.c
@@ -118,6 +118,7 @@ START_TEST(test_basic)
118 ck_assert_msg(packet_resp_plain[0] == 1, "wrong packet id %u", packet_resp_plain[0]); 118 ck_assert_msg(packet_resp_plain[0] == 1, "wrong packet id %u", packet_resp_plain[0]);
119 ck_assert_msg(packet_resp_plain[1] == 0, "connection not refused %u", packet_resp_plain[1]); 119 ck_assert_msg(packet_resp_plain[1] == 0, "connection not refused %u", packet_resp_plain[1]);
120 ck_assert_msg(memcmp(packet_resp_plain + 2, f_public_key, crypto_box_PUBLICKEYBYTES) == 0, "key in packet wrong"); 120 ck_assert_msg(memcmp(packet_resp_plain + 2, f_public_key, crypto_box_PUBLICKEYBYTES) == 0, "key in packet wrong");
121 kill_TCP_server(tcp_s);
121} 122}
122END_TEST 123END_TEST
123 124
@@ -175,6 +176,12 @@ struct sec_TCP_con *new_TCP_con(TCP_Server *tcp_s)
175 return sec_c; 176 return sec_c;
176} 177}
177 178
179void kill_TCP_con(struct sec_TCP_con *con)
180{
181 kill_sock(con->sock);
182 free(con);
183}
184
178int write_packet_TCP_secure_connection(struct sec_TCP_con *con, uint8_t *data, uint16_t length) 185int write_packet_TCP_secure_connection(struct sec_TCP_con *con, uint8_t *data, uint16_t length)
179{ 186{
180 uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; 187 uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES];
@@ -290,6 +297,10 @@ START_TEST(test_some)
290 ck_assert_msg(len == sizeof(ping_packet), "wrong len %u", len); 297 ck_assert_msg(len == sizeof(ping_packet), "wrong len %u", len);
291 ck_assert_msg(data[0] == 5, "wrong packet id %u", data[0]); 298 ck_assert_msg(data[0] == 5, "wrong packet id %u", data[0]);
292 ck_assert_msg(memcmp(ping_packet + 1, data + 1, sizeof(uint64_t)) == 0, "wrong packet data"); 299 ck_assert_msg(memcmp(ping_packet + 1, data + 1, sizeof(uint64_t)) == 0, "wrong packet data");
300 kill_TCP_server(tcp_s);
301 kill_TCP_con(con1);
302 kill_TCP_con(con2);
303 kill_TCP_con(con3);
293} 304}
294END_TEST 305END_TEST
295 306
@@ -457,6 +468,9 @@ START_TEST(test_client)
457 do_TCP_connection(conn2); 468 do_TCP_connection(conn2);
458 ck_assert_msg(status_callback_good == 1, "status callback not called"); 469 ck_assert_msg(status_callback_good == 1, "status callback not called");
459 ck_assert_msg(status_callback_status == 1, "wrong status"); 470 ck_assert_msg(status_callback_status == 1, "wrong status");
471 kill_TCP_server(tcp_s);
472 kill_TCP_connection(conn);
473 kill_TCP_connection(conn2);
460} 474}
461END_TEST 475END_TEST
462 476
@@ -488,6 +502,8 @@ START_TEST(test_client_invalid)
488 do_TCP_connection(conn); 502 do_TCP_connection(conn);
489 ck_assert_msg(conn->status == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_DISCONNECTED, 503 ck_assert_msg(conn->status == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_DISCONNECTED,
490 conn->status); 504 conn->status);
505
506 kill_TCP_connection(conn);
491} 507}
492END_TEST 508END_TEST
493 509
diff --git a/auto_tests/assoc_test.c b/auto_tests/assoc_test.c
index b377cadf..bcf5d3fa 100644
--- a/auto_tests/assoc_test.c
+++ b/auto_tests/assoc_test.c
@@ -55,6 +55,7 @@ START_TEST(test_basics)
55 55
56 uint8_t found = Assoc_get_close_entries(assoc, &close_entries); 56 uint8_t found = Assoc_get_close_entries(assoc, &close_entries);
57 ck_assert_msg(found == 1, "get_close_entries(): expected %u, got %u", 1, found); 57 ck_assert_msg(found == 1, "get_close_entries(): expected %u, got %u", 1, found);
58 kill_Assoc(assoc);
58} 59}
59END_TEST 60END_TEST
60 61
@@ -130,6 +131,7 @@ START_TEST(test_fillup)
130 131
131 ck_assert_msg(good == 8, "Entries found were not the closest ones. Only %u/8 were.", good); 132 ck_assert_msg(good == 8, "Entries found were not the closest ones. Only %u/8 were.", good);
132 //printf("good: %u %u %u\n", good, a, ((uint32_t)current_time() - a)); 133 //printf("good: %u %u %u\n", good, a, ((uint32_t)current_time() - a));
134 kill_Assoc(assoc);
133} 135}
134END_TEST 136END_TEST
135 137
diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c
index aa5bef3f..338c9ef1 100644
--- a/auto_tests/encryptsave_test.c
+++ b/auto_tests/encryptsave_test.c
@@ -114,6 +114,12 @@ START_TEST(test_save_friend)
114 test = tox_get_client_id(tox4, 0, address5); 114 test = tox_get_client_id(tox4, 0, address5);
115 ck_assert_msg(test == 0, "no friends! the third"); 115 ck_assert_msg(test == 0, "no friends! the third");
116 ck_assert_msg(memcmp(address, address2, TOX_CLIENT_ID_SIZE) == 0, "addresses don't match! the third"); 116 ck_assert_msg(memcmp(address, address2, TOX_CLIENT_ID_SIZE) == 0, "addresses don't match! the third");
117
118 tox_kill(tox1);
119 tox_kill(tox2);
120 tox_kill(tox3);
121 tox_kill(tox4);
122 tox_kill(tox5);
117} 123}
118END_TEST 124END_TEST
119 125
@@ -160,8 +166,8 @@ Suite *encryptsave_suite(void)
160 Suite *s = suite_create("encryptsave"); 166 Suite *s = suite_create("encryptsave");
161 167
162 DEFTESTCASE_SLOW(known_kdf, 60); /* is 5-10 seconds on my computer, but is directly dependent on CPU */ 168 DEFTESTCASE_SLOW(known_kdf, 60); /* is 5-10 seconds on my computer, but is directly dependent on CPU */
163 DEFTESTCASE(save_friend); 169 DEFTESTCASE_SLOW(save_friend, 20);
164 DEFTESTCASE(keys); 170 DEFTESTCASE_SLOW(keys, 30);
165 171
166 return s; 172 return s;
167} 173}
diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c
index 8e10eb11..f27fefb8 100644
--- a/auto_tests/onion_test.c
+++ b/auto_tests/onion_test.c
@@ -138,12 +138,12 @@ START_TEST(test_basic)
138 138
139 IP_Port on1 = {ip, onion1->net->port}; 139 IP_Port on1 = {ip, onion1->net->port};
140 Node_format n1; 140 Node_format n1;
141 memcpy(n1.client_id, onion1->dht->self_public_key, crypto_box_PUBLICKEYBYTES); 141 memcpy(n1.public_key, onion1->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
142 n1.ip_port = on1; 142 n1.ip_port = on1;
143 143
144 IP_Port on2 = {ip, onion2->net->port}; 144 IP_Port on2 = {ip, onion2->net->port};
145 Node_format n2; 145 Node_format n2;
146 memcpy(n2.client_id, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES); 146 memcpy(n2.public_key, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
147 n2.ip_port = on2; 147 n2.ip_port = on2;
148 148
149 Node_format nodes[4]; 149 Node_format nodes[4];
@@ -180,7 +180,7 @@ START_TEST(test_basic)
180 randombytes(sb_data, sizeof(sb_data)); 180 randombytes(sb_data, sizeof(sb_data));
181 uint64_t s; 181 uint64_t s;
182 memcpy(&s, sb_data, sizeof(uint64_t)); 182 memcpy(&s, sb_data, sizeof(uint64_t));
183 memcpy(test_3_pub_key, nodes[3].client_id, crypto_box_PUBLICKEYBYTES); 183 memcpy(test_3_pub_key, nodes[3].public_key, crypto_box_PUBLICKEYBYTES);
184 ret = send_announce_request(onion1->net, &path, nodes[3], onion1->dht->self_public_key, 184 ret = send_announce_request(onion1->net, &path, nodes[3], onion1->dht->self_public_key,
185 onion1->dht->self_secret_key, 185 onion1->dht->self_secret_key,
186 zeroes, onion1->dht->self_public_key, onion1->dht->self_public_key, s); 186 zeroes, onion1->dht->self_public_key, onion1->dht->self_public_key, s);
@@ -224,6 +224,39 @@ START_TEST(test_basic)
224 do_onion(onion2); 224 do_onion(onion2);
225 c_sleep(50); 225 c_sleep(50);
226 } 226 }
227
228 kill_onion_announce(onion1_a);
229 kill_onion_announce(onion2_a);
230
231 {
232 Onion *onion = onion1;
233
234 Networking_Core *net = onion->dht->net;
235 DHT *dht = onion->dht;
236 kill_onion(onion);
237 kill_DHT(dht);
238 kill_networking(net);
239 }
240
241 {
242 Onion *onion = onion2;
243
244 Networking_Core *net = onion->dht->net;
245 DHT *dht = onion->dht;
246 kill_onion(onion);
247 kill_DHT(dht);
248 kill_networking(net);
249 }
250
251 {
252 Onion *onion = onion3;
253
254 Networking_Core *net = onion->dht->net;
255 DHT *dht = onion->dht;
256 kill_onion(onion);
257 kill_DHT(dht);
258 kill_networking(net);
259 }
227} 260}
228END_TEST 261END_TEST
229 262
@@ -257,6 +290,18 @@ void do_onions(Onions *on)
257 do_onion_client(on->onion_c); 290 do_onion_client(on->onion_c);
258} 291}
259 292
293void kill_onions(Onions *on)
294{
295 Networking_Core *net = on->onion->dht->net;
296 DHT *dht = on->onion->dht;
297 kill_onion_client(on->onion_c);
298 kill_onion_announce(on->onion_a);
299 kill_onion(on->onion);
300 kill_DHT(dht);
301 kill_networking(net);
302 free(on);
303}
304
260#define NUM_ONIONS 50 305#define NUM_ONIONS 50
261 306
262START_TEST(test_announce) 307START_TEST(test_announce)
@@ -334,6 +379,10 @@ START_TEST(test_announce)
334 } 379 }
335 380
336 ck_assert_msg(ip_port.port == onions[7]->onion->net->port, "Port in returned ip not correct."); 381 ck_assert_msg(ip_port.port == onions[7]->onion->net->port, "Port in returned ip not correct.");
382
383 for (i = 0; i < NUM_ONIONS; ++i) {
384 kill_onions(onions[i]);
385 }
337} 386}
338END_TEST 387END_TEST
339 388
diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c
index db1db3fb..3139c844 100644
--- a/auto_tests/toxav_basic_test.c
+++ b/auto_tests/toxav_basic_test.c
@@ -595,8 +595,12 @@ START_TEST(test_AV_flows)
595 printf("\n"); 595 printf("\n");
596 } 596 }
597 597
598 598 vpx_img_free(sample_image);
599 599 toxav_kill(status_control.Alice.av);
600 toxav_kill(status_control.Bob.av);
601 tox_kill(bootstrap_node);
602 tox_kill(Alice);
603 tox_kill(Bob);
600 604
601 printf("Calls ended!\n"); 605 printf("Calls ended!\n");
602} 606}
diff --git a/configure.ac b/configure.ac
index 3a45b35d..e43e8f78 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ AC_INIT([tox], [0.0.0], [https://tox.im])
6AC_CONFIG_AUX_DIR(configure_aux) 6AC_CONFIG_AUX_DIR(configure_aux)
7AC_CONFIG_SRCDIR([toxcore/net_crypto.c]) 7AC_CONFIG_SRCDIR([toxcore/net_crypto.c])
8AC_CONFIG_HEADERS([config.h]) 8AC_CONFIG_HEADERS([config.h])
9AM_INIT_AUTOMAKE([1.10 -Wall subdir-objects]) 9AM_INIT_AUTOMAKE([1.10 -Wall subdir-objects tar-ustar])
10m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 10m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
11AC_CONFIG_MACRO_DIR([m4]) 11AC_CONFIG_MACRO_DIR([m4])
12 12
@@ -693,6 +693,7 @@ AM_CONDITIONAL(WIN32, test "x$WIN32" = "xyes")
693AC_CONFIG_FILES([Makefile 693AC_CONFIG_FILES([Makefile
694 build/Makefile 694 build/Makefile
695 libtoxcore.pc 695 libtoxcore.pc
696 tox.spec
696 ]) 697 ])
697 698
698AM_COND_IF(BUILD_AV, 699AM_COND_IF(BUILD_AV,
diff --git a/docs/Avatars.md b/docs/Avatars.md
index 1dcbba96..9dd43079 100644
--- a/docs/Avatars.md
+++ b/docs/Avatars.md
@@ -11,8 +11,8 @@ way for one user to identify another in the friend list.
11This document describes the implementation of avatars in the Tox protocol, 11This document describes the implementation of avatars in the Tox protocol,
12according to the following design considerations: 12according to the following design considerations:
13 13
14 - Avatars are handled as private information, i.e., they are only exchanged over 14 - Avatars are handled as private information, i.e., they are only exchanged
15 Tox encrypted channels among previously authenticated friends; 15 over Tox encrypted channels among previously authenticated friends.
16 16
17 - The library treats all images as blobs and does not interpret or 17 - The library treats all images as blobs and does not interpret or
18 understand image formats. It only ensures that the avatar data sent by 18 understand image formats. It only ensures that the avatar data sent by
@@ -33,7 +33,7 @@ according to the following design considerations:
33 - The protocol MUST provide means to allow caching and avoid unnecessary 33 - The protocol MUST provide means to allow caching and avoid unnecessary
34 data transfers. 34 data transfers.
35 35
36 - Avatars are transfered between clients in a background operation. 36 - Avatars are transferred between clients in a background operation.
37 37
38 - Avatars are served on a "best effort" basis, without breaking clients 38 - Avatars are served on a "best effort" basis, without breaking clients
39 which do not support them. 39 which do not support them.
@@ -76,7 +76,7 @@ protocol. Moving this feature to the core protocol also:
76This is a very high level description. The usage patterns expected from 76This is a very high level description. The usage patterns expected from
77client applications are described in the section "Using Avatars in Client 77client applications are described in the section "Using Avatars in Client
78Applications", and a low level protocol description is available in the 78Applications", and a low level protocol description is available in the
79section "Internal Protocol Description".) 79section "Internal Protocol Description").
80The avatar exchange is implemented with the following new elements in the 80The avatar exchange is implemented with the following new elements in the
81Tox protocol: 81Tox protocol:
82 82
@@ -84,15 +84,16 @@ Tox protocol:
84 a user to another anytime, but are usually sent after one of them 84 a user to another anytime, but are usually sent after one of them
85 connects to the network, changes his avatar, or in reply to an **avatar 85 connects to the network, changes his avatar, or in reply to an **avatar
86 information request**. They are delivered by a very lightweight message 86 information request**. They are delivered by a very lightweight message
87 but with information enough to allow a user to validate or discard an 87 but with enough information to allow a user to validate or discard an
88 avatar from the local cache and to decide if it is interesting to request the 88 avatar from the local cache and to decide if it is interesting to request
89 avatar data from the peer. 89 the avatar data from the peer.
90 90
91 This event contains two data fields: (1) the image format, and (2) the 91 This event contains two data fields: (1) the image format, and (2) the
92 cryptographic hash of the actual image data. The image format may be NONE 92 cryptographic hash of the current image data. The image format may be
93 (for users who have no avatar or removed their avatars) or PNG. The 93 NONE (for users who have no avatar or removed their avatars) or PNG. The
94 cryptographic hash is intended to be compared with the hash of the 94 cryptographic hash is intended to be compared with the hash of the
95 currently cached avatar (if any) in order to check if it is still up to date. 95 currently cached avatar (if any) in order to check if it is still up to
96 date.
96 97
97 - **Avatar Information Requests** are very lightweight messages sent by a 98 - **Avatar Information Requests** are very lightweight messages sent by a
98 user asking for an **avatar information notification**. They may be sent 99 user asking for an **avatar information notification**. They may be sent
@@ -114,7 +115,7 @@ Tox protocol:
114 115
115 This event contains three data fields: (1) the image format, (2) the 116 This event contains three data fields: (1) the image format, (2) the
116 cryptographic hash of the image data, and (3) the raw image data. If the 117 cryptographic hash of the image data, and (3) the raw image data. If the
117 image format is NONE (i.e. no avatar) the hash is zeroed and the image 118 image format is NONE (i.e. no avatar), the hash is zeroed and the image
118 data is empty. The raw image data is locally validated and ensured to 119 data is empty. The raw image data is locally validated and ensured to
119 match the hash (the event is **not** triggered otherwise). 120 match the hash (the event is **not** triggered otherwise).
120 121
@@ -145,10 +146,13 @@ TOX_AVATAR_FORMAT;
145/* Set the user avatar image data. */ 146/* Set the user avatar image data. */
146int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length); 147int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length);
147 148
149/* Remove the user avatar image data. */
150int tox_unset_avatar(Tox *tox);
151
148/* Get avatar data from the current user. */ 152/* Get avatar data from the current user. */
149int tox_get_self_avatar(const Tox *tox, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen, uint8_t *hash); 153int tox_get_self_avatar(const Tox *tox, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen, uint8_t *hash);
150 154
151/* Generates a cryptographic hash of the given data (usually a cached avatar). */ 155/* Generate a cryptographic hash of the given data (usually a cached avatar). */
152int tox_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen); 156int tox_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen);
153 157
154/* Request avatar information from a friend. */ 158/* Request avatar information from a friend. */
@@ -177,17 +181,17 @@ void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint
177 181
178 - Clients MUST NOT imply the availability of avatars in other users. 182 - Clients MUST NOT imply the availability of avatars in other users.
179 Avatars are an optional feature and not all users and clients may 183 Avatars are an optional feature and not all users and clients may
180 support them; 184 support them.
181 185
182 - Clients MUST NOT block waiting for avatar information and avatar data 186 - Clients MUST NOT block waiting for avatar information and avatar data
183 packets; 187 packets.
184 188
185 - Clients MUST treat avatar data as insecure and potentially malicious; 189 - Clients MUST treat avatar data as insecure and potentially malicious.
186 For example, users may accidentally use corrupted images as avatars, 190 For example, users may accidentally use corrupted images as avatars,
187 a malicious user may send a specially crafted image to exploit a know 191 a malicious user may send a specially crafted image to exploit a known
188 vulnerability in an image decoding library, etc. It is recommended to 192 vulnerability in an image decoding library, etc. It is recommended to
189 handle the avatar image data in the same way as an image downloaded 193 handle the avatar image data in the same way as an image downloaded
190 from an unknown Internet source; 194 from an unknown Internet source.
191 195
192 - The peers MUST NOT assume any coupling between the operations of 196 - The peers MUST NOT assume any coupling between the operations of
193 receiving an avatar information packet, sending unrequested avatar 197 receiving an avatar information packet, sending unrequested avatar
@@ -196,31 +200,36 @@ void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint
196 For example, the following situations are valid: 200 For example, the following situations are valid:
197 201
198 * A text-mode client may send avatars to other users, but never 202 * A text-mode client may send avatars to other users, but never
199 request them; 203 request them.
200 204
201 * A client may not understand a particular image format and ignore 205 * A client may not understand a particular image format and ignore
202 avatars using it, but request and handle other formats; 206 avatars using it, but request and handle other formats.
207
208 * A client on a slow mobile network may ask for avatar information to
209 ensure its cached avatars are still valid, but not request avatar
210 data. The same client may start asking for avatar data once it
211 connects through a fast network.
203 212
204 - Clients SHOULD implement a local cache of avatars and do not request 213 - Clients SHOULD implement a local cache of avatars and not request
205 avatar data from other peers unless necessary; 214 avatar data from other peers unless necessary.
206 215
207 - When an avatar information is received, the client should delete the 216 - When avatar information is received, the client should delete the
208 avatar if the new avatar format is NONE or compare the hash received 217 avatar if the new avatar format is NONE or compare the hash received
209 from the peer with the hash of the currently cached avatar. If they 218 from the peer with the hash of the currently cached avatar. If they
210 differ, send an avatar data request; 219 differ, send an avatar data request.
211 220
212 - If the cached avatar is older than a given threshold, the client may 221 - If the cached avatar is older than a given threshold, the client may
213 also send an avatar info request to that friend once he is online and 222 also send an avatar info request to that friend once he is online and
214 mark the avatar as updated *before* any avatar information is received 223 mark the avatar as updated *before* any avatar information is received
215 (to not spam the peer with such requests); 224 (to not spam the peer with such requests).
216 225
217 - When an avatar data notification is received, the client must update 226 - When an avatar data notification is received, the client must update
218 the cached avatar with the new one; 227 the cached avatar with the new one.
219 228
220 - Clients should resize or crop the image to the way it better adapts 229 - Clients should resize or crop the image such that it better adapts
221 to the client user interface; 230 to the client's user interface.
222 231
223 - If the user already have an avatar defined in the client configuration, 232 - If the user already has an avatar defined in the client configuration,
224 it must be set before connecting to the network to avoid spurious avatar 233 it must be set before connecting to the network to avoid spurious avatar
225 change notifications and unnecessary data transfers. 234 change notifications and unnecessary data transfers.
226 235
@@ -232,10 +241,10 @@ void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint
232### Interoperability and sharing avatars among different clients 241### Interoperability and sharing avatars among different clients
233 242
234**This section is a tentative recommendation of how clients should store 243**This section is a tentative recommendation of how clients should store
235avatars to ensure local interoperability and should be revised if this 244avatars to ensure local interoperability, and should be revised if this
236code is accepted into Tox core.** 245code is accepted into Tox core.**
237 246
238It is desirable that the user avatar and the cached friends avatars could be 247It is desirable that the user avatar and the cached friends' avatars could be
239shared among different Tox clients in the same system, in the spirit of the 248shared among different Tox clients in the same system, in the spirit of the
240proposed Single Tox Standard. This not only makes switching from one client 249proposed Single Tox Standard. This not only makes switching from one client
241to another easier, but also minimizes the need of data transfers, as avatars 250to another easier, but also minimizes the need of data transfers, as avatars
@@ -244,7 +253,7 @@ already downloaded by other clients can be reused.
244Given the Tox data directory described in STS Draft v0.1.0: 253Given the Tox data directory described in STS Draft v0.1.0:
245 254
246 - Avatars are stored in a directory called "avatars" and named 255 - Avatars are stored in a directory called "avatars" and named
247 as "xxxxx.png", where "xxxxx" is the complete client id (but not friend 256 as "xxxxx.png", where "xxxxx" is the complete public key (but not friend
248 address!) encoded as an uppercase hexadecimal string and "png" is the 257 address!) encoded as an uppercase hexadecimal string and "png" is the
249 extension for the PNG avatar. As new image formats may be used in the 258 extension for the PNG avatar. As new image formats may be used in the
250 future, clients should ensure no other file "xxxxx.*" exists. No file 259 future, clients should ensure no other file "xxxxx.*" exists. No file
@@ -253,10 +262,10 @@ Given the Tox data directory described in STS Draft v0.1.0:
253 - The client's own avatar is not special and is stored like any other. This 262 - The client's own avatar is not special and is stored like any other. This
254 is partially for simplicity, and partially in anticipation of profiles. 263 is partially for simplicity, and partially in anticipation of profiles.
255 264
256 - The avatar should be stored as its recieved, before any modifications by 265 - The avatar should be stored as it was received, before any modifications by
257 the client for display purposes. 266 the client for display purposes.
258 267
259 - The hash, as calculated by toxcore and passed in to the data callback, 268 - The hash, as calculated by toxcore and passed into the data callback,
260 should be saved in "avatars/xxxxx.hash" where "xxxxx" means the 269 should be saved in "avatars/xxxxx.hash" where "xxxxx" means the
261 same thing as for avatars. (The filename is longer than the file :) ) 270 same thing as for avatars. (The filename is longer than the file :) )
262 271
@@ -264,12 +273,12 @@ Given the Tox data directory described in STS Draft v0.1.0:
264 upper case strings, but lower case file names are more usual. 273 upper case strings, but lower case file names are more usual.
265 274
266 275
267Example for Linux and other Unix systems, assuming an user called "gildor": 276Example for Linux and other Unix systems, assuming a user called "gildor":
268 277
269 Tox data directory: /home/gildor/.config/tox/ 278 Tox data directory: /home/gildor/.config/tox/
270 Tox data file: /home/gildor/.config/tox/data 279 Tox data file: /home/gildor/.config/tox/data
271 Avatar data dir: /home/gildor/.config/tox/avatars/ 280 Avatar data dir: /home/gildor/.config/tox/avatars/
272 Gildor's avatar: /home/gildor/.config/tox/avatars/E5809EEF5F11AB29B9BDF543C05B58DDF454AB9CA176C235C7699FDC2757DC33.png 281 Gildor's avatar: /home/gildor/.config/tox/avatars/446F4E6F744D6564646C65496E546865416666616972734F6657697A61726473.png
273 Elrond's avatar: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.png 282 Elrond's avatar: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.png
274 Elrond's hash: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.hash 283 Elrond's hash: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.hash
275 Elladan's avatar: /home/gildor/.config/tox/avatars/49486174655768656E48756D616E735468696E6B49416D4D7942726F74686572.png 284 Elladan's avatar: /home/gildor/.config/tox/avatars/49486174655768656E48756D616E735468696E6B49416D4D7942726F74686572.png
@@ -285,13 +294,13 @@ This recommendation is partially implemented by "testing/test_avatars.c".
285 294
286### Common operations 295### Common operations
287 296
288These are minimal examples of how perform common operations with avatar 297These are minimal examples of how to perform common operations with avatar
289functions. For a complete, working, example, see `testing/test_avatars.c`. 298functions. For a complete working example, see `testing/test_avatars.c`.
290 299
291 300
292#### Setting an avatar for the current user 301#### Setting an avatar for the current user
293 302
294In this example `load_data_file` is just an hypothetical function that loads 303In this example, `load_data_file` is just a hypothetical function that loads
295data from a file into the buffer and sets the length accordingly. 304data from a file into the buffer and sets the length accordingly.
296 305
297 uint8_t buf[TOX_AVATAR_MAX_DATA_LENGTH]; 306 uint8_t buf[TOX_AVATAR_MAX_DATA_LENGTH];
@@ -304,7 +313,7 @@ data from a file into the buffer and sets the length accordingly.
304If the user is connected, this function will also notify all connected 313If the user is connected, this function will also notify all connected
305friends about the avatar change. 314friends about the avatar change.
306 315
307If the user already have an avatar defined in the client configuration, it 316If the user already has an avatar defined in the client configuration, it
308must be set before connecting to the network to avoid spurious avatar change 317must be set before connecting to the network to avoid spurious avatar change
309notifications and unnecessary data transfers. 318notifications and unnecessary data transfers.
310 319
@@ -313,7 +322,12 @@ notifications and unnecessary data transfers.
313 322
314#### Removing the avatar from the current user 323#### Removing the avatar from the current user
315 324
316To remove an avatar, an application must set it to `TOX_AVATAR_FORMAT_NONE`. 325To remove the current avatar, an application must call
326
327 tox_unset_avatar(tox);
328
329the effect is the same as setting the avatar format to `TOX_AVATAR_FORMAT_NONE`
330with no data:
317 331
318 tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0); 332 tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0);
319 333
@@ -343,7 +357,7 @@ As in this example:
343 printf("\n"); 357 printf("\n");
344 } 358 }
345 359
346And, somewhere in the Tox initialization calls, set if as the callback to be 360And, somewhere in the Tox initialization calls, set it as the callback to be
347triggered when an avatar information event arrives: 361triggered when an avatar information event arrives:
348 362
349 tox_callback_avatar_info(tox, avatar_info_cb, NULL); 363 tox_callback_avatar_info(tox, avatar_info_cb, NULL);
@@ -356,7 +370,7 @@ in the avatar information event and, if needed, request the avatar data.
356 370
357#### Receiving avatar data from friends 371#### Receiving avatar data from friends
358 372
359Avatar data events are only delivered in reply of avatar data requests which 373Avatar data events are only delivered in reply to avatar data requests, which
360**should** only be sent after getting the user avatar information (format 374**should** only be sent after getting the user avatar information (format
361and hash) from an avatar information event and checking it against a local 375and hash) from an avatar information event and checking it against a local
362cache. 376cache.
@@ -374,7 +388,7 @@ checks the local avatar cache and emits an avatar data request if necessary:
374 delete_avatar_from_cache(tox, friendnumber); 388 delete_avatar_from_cache(tox, friendnumber);
375 } else { 389 } else {
376 /* Use the received hash to check if the cached avatar is 390 /* Use the received hash to check if the cached avatar is
377 still updated. */ 391 still up to date. */
378 if (!is_user_cached_avatar_updated(tox, friendnumber, hash)) { 392 if (!is_user_cached_avatar_updated(tox, friendnumber, hash)) {
379 /* User avatar is outdated, send data request */ 393 /* User avatar is outdated, send data request */
380 tox_request_avatar_data(tox, friendnumber); 394 tox_request_avatar_data(tox, friendnumber);
@@ -406,9 +420,9 @@ calls:
406 tox_callback_avatar_data(tox, avatar_data_cb, NULL); 420 tox_callback_avatar_data(tox, avatar_data_cb, NULL);
407 421
408 422
409In the previous examples, implementation of the functions to check, store 423In the previous examples, implementation of the functions to check, store,
410and retrieve data from the cache were omitted for brevity. These functions 424and retrieve data from the cache were omitted for brevity. These functions
411will also need to get the friend client ID (public key) from they friend 425will also need to get the friend public key (client id) from the friend
412number and, usually, convert it from a byte string to a hexadecimal 426number and, usually, convert it from a byte string to a hexadecimal
413string. A complete, yet more complex, example is available in the file 427string. A complete, yet more complex, example is available in the file
414`testing/test_avatars.c`. 428`testing/test_avatars.c`.
@@ -440,7 +454,7 @@ The avatar transfer protocol adds the following new packet types and ids:
440 454
441### Requesting avatar information 455### Requesting avatar information
442 456
443To request avatar information, an user must send a packet of type 457To request avatar information, a user must send a packet of type
444`PACKET_ID_AVATAR_INFO_REQ`. This packet has no data fields. Upon 458`PACKET_ID_AVATAR_INFO_REQ`. This packet has no data fields. Upon
445receiving this packet, a client which supports avatars should answer with 459receiving this packet, a client which supports avatars should answer with
446a `PACKET_ID_AVATAR_INFO`. The sender must accept that the friend may 460a `PACKET_ID_AVATAR_INFO`. The sender must accept that the friend may
@@ -458,7 +472,7 @@ the following structure:
458 Packet data size: 33 bytes 472 Packet data size: 33 bytes
459 [1: uint8_t format][32: uint8_t hash] 473 [1: uint8_t format][32: uint8_t hash]
460 474
461Where 'format' is the image data format, one of the following: 475where 'format' is the image data format, one of the following:
462 476
463 0 = AVATAR_FORMAT_NONE (no avatar set) 477 0 = AVATAR_FORMAT_NONE (no avatar set)
464 1 = AVATAR_FORMAT_PNG 478 1 = AVATAR_FORMAT_PNG
@@ -478,21 +492,21 @@ connects, in the same way Tox sends name, status and action information.
478Transmission of avatar data is a multi-step procedure using three new packet 492Transmission of avatar data is a multi-step procedure using three new packet
479types. 493types.
480 494
481 - Packet `PACKET_ID_AVATAR_DATA_CONTROL` have the format: 495 - Packet `PACKET_ID_AVATAR_DATA_CONTROL` has the format:
482 496
483 PACKET_ID_AVATAR_DATA_CONTROL (54) 497 PACKET_ID_AVATAR_DATA_CONTROL (54)
484 Packet data size: 1 byte 498 Packet data size: 1 byte
485 [1: uint8_t op] 499 [1: uint8_t op]
486 500
487 where 'op' is a code signaling both an operation request or a status 501 where 'op' is a code signaling either an operation request or a status
488 return, which semantics are explained bellow. The following values are 502 return, the semantics of which are explained below. The following values are
489 defined: 503 defined:
490 504
491 0 = AVATAR_DATACONTROL_REQ 505 0 = AVATAR_DATACONTROL_REQ
492 1 = AVATAR_DATACONTROL_ERROR 506 1 = AVATAR_DATACONTROL_ERROR
493 507
494 508
495 - Packet `PACKET_ID_AVATAR_DATA_START` have the following format: 509 - Packet `PACKET_ID_AVATAR_DATA_START` has the following format:
496 510
497 PACKET_ID_AVATAR_DATA_START (55) 511 PACKET_ID_AVATAR_DATA_START (55)
498 Packet data size: 37 bytes 512 Packet data size: 37 bytes
@@ -501,13 +515,13 @@ types.
501 515
502 where 'format' is the image format, with the same values accepted for 516 where 'format' is the image format, with the same values accepted for
503 the field 'format' in packet type `PACKET_ID_AVATAR_INFO`, 'hash' is 517 the field 'format' in packet type `PACKET_ID_AVATAR_INFO`, 'hash' is
504 the SHA-256 cryptographic hash of the avatar raw data and 'data_length' 518 the SHA-256 cryptographic hash of the avatar raw data, and 'data_length'
505 is the total number of bytes the raw avatar data. 519 is the total number of bytes the raw avatar data.
506 520
507 521
508 - Packet `PACKET_ID_AVATAR_DATA_PUSH` has no format structure, just up 522 - Packet `PACKET_ID_AVATAR_DATA_PUSH` has no format structure, just up
509 to `AVATAR_DATA_MAX_CHUNK_SIZE` bytes of raw avatar image data; this 523 to `AVATAR_DATA_MAX_CHUNK_SIZE` bytes of raw avatar image data; this
510 value is defined according to the maximum amount of data a Tox crypted 524 value is defined according to the maximum amount of data a Tox encrypted
511 packet can hold. 525 packet can hold.
512 526
513 527
@@ -520,9 +534,9 @@ from a client "B":
520 packet `PACKET_ID_AVATAR_DATA_CONTROL` with 'op' set to 534 packet `PACKET_ID_AVATAR_DATA_CONTROL` with 'op' set to
521 `AVATAR_DATACONTROL_REQ`. 535 `AVATAR_DATACONTROL_REQ`.
522 536
523 - If "B" accepts this transfer, it answers by sending an 537 - If "B" accepts this transfer, it answers by sending a
524 `PACKET_ID_AVATAR_DATA_START` with the fields 'format', 'hash' and 538 `PACKET_ID_AVATAR_DATA_START` with the fields 'format', 'hash', and
525 'data_length' set to the respective values from the current avatar. 539 'data_length' set to the respective values of the current avatar.
526 If "B" has no avatar set, 'format' must be `AVATAR_FORMAT_NONE`, 'hash' 540 If "B" has no avatar set, 'format' must be `AVATAR_FORMAT_NONE`, 'hash'
527 must be zeroed and 'data_length' must be zero. 541 must be zeroed and 'data_length' must be zero.
528 542
@@ -531,12 +545,12 @@ from a client "B":
531 `AVATAR_DATACONTROL_ERROR` or simply ignore this request. "A" must cope 545 `AVATAR_DATACONTROL_ERROR` or simply ignore this request. "A" must cope
532 with this. 546 with this.
533 547
534 If "B" have an avatar, it sends a variable number of 548 If "B" has an avatar, it sends a variable number of
535 `PACKET_ID_AVATAR_DATA_PUSH` packets with the avatar data in a single 549 `PACKET_ID_AVATAR_DATA_PUSH` packets with the avatar data in a single
536 shot. 550 shot.
537 551
538 - Upon receiving a `PACKET_ID_AVATAR_DATA_START`, "A" checks if it 552 - Upon receiving a `PACKET_ID_AVATAR_DATA_START`, "A" checks if it
539 has sent a data request to "B". If not, just ignores the packet. 553 has sent a data request to "B". If not, it simply ignores the packet.
540 554
541 If "A" really requested avatar data and the format is `AVATAR_FORMAT_NONE`, 555 If "A" really requested avatar data and the format is `AVATAR_FORMAT_NONE`,
542 it triggers the avatar data callback, and clears all the temporary data, 556 it triggers the avatar data callback, and clears all the temporary data,
@@ -545,36 +559,36 @@ from a client "B":
545 559
546 - Upon receiving a `PACKET_ID_AVATAR_DATA_PUSH`, "A" checks if it really 560 - Upon receiving a `PACKET_ID_AVATAR_DATA_PUSH`, "A" checks if it really
547 sent an avatar data request and if the `PACKET_ID_AVATAR_DATA_START` was 561 sent an avatar data request and if the `PACKET_ID_AVATAR_DATA_START` was
548 already received. If this conditions are valid, it checks if the total 562 already received. If these conditions were met, it checks if the total
549 length of the data already stored in the receiving buffer plus the data 563 length of the data already stored in the receiving buffer plus the data
550 present in the push packet is still less or equal than 564 present in the push packet is still less or equal than
551 `TOX_AVATAR_MAX_DATA_LENGTH`. If invalid, it replies with a 565 `TOX_AVATAR_MAX_DATA_LENGTH`. If that is not the case, it replies with a
552 `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to 566 `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to
553 `AVATAR_DATACONTROL_ERROR`. 567 `AVATAR_DATACONTROL_ERROR`.
554 568
555 If valid, "A" updates the 'bytes_received' counter and concatenates the 569 If valid, "A" updates the 'bytes_received' counter and concatenates the
556 newly arrived data to the buffer. 570 newly arrived data to the buffer.
557 571
558 The "A" checks if all the data was already received by comparing the 572 Then "A" checks if all the data has already been received, by comparing the
559 counter 'bytes_received' with the field 'total_length'. If they are 573 counter 'bytes_received' with the field 'total_length'. If they are
560 equal, "A" takes a SHA-256 hash of the data and compares it with the 574 equal, "A" takes a SHA-256 hash of the data and compares it with the
561 hash stored in the field 'hash' received from the first 575 hash stored in the field 'hash' received with the first
562 `PACKET_ID_AVATAR_DATA_START`. 576 `PACKET_ID_AVATAR_DATA_START`.
563 577
564 If the hashes match, the avatar data was correctly received and "A" 578 If the hashes match, the avatar data was correctly received, and "A"
565 triggers the avatar data callback, and clears all the temporary data, 579 triggers the avatar data callback and clears all the temporary data,
566 finishing the process. 580 finishing the process.
567 581
568 If not all data was received, "A" simply waits for more data. 582 If not all data was received, "A" simply waits for more data.
569 583
570 Client "A" is always responsible for controlling the transfer and 584 Client "A" is always responsible for controlling the transfer and
571 validating the data received. "B" don't need to keep any state for the 585 validating the data received. "B" doesn't need to keep any state for the
572 protocol, have full control over the data sent and should implement 586 protocol, have full control over the data sent and should implement
573 some transfer limit for the data it sends. 587 some transfer limit for the data it sends.
574 588
575 - Any peer receiving a `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' 589 - Any peer receiving a `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op'
576 set to `AVATAR_DATACONTROL_ERROR` clears any existing control state and 590 set to `AVATAR_DATACONTROL_ERROR` clears any existing control state and
577 finishes sending or receiving data. 591 aborts sending or receiving data.
578 592
579 593
580 594
@@ -583,33 +597,33 @@ from a client "B":
583## Security considerations 597## Security considerations
584 598
585The major security implication of background data transfers of large objects, 599The major security implication of background data transfers of large objects,
586like avatars, is the possibility of exhausting the network resources from a 600like avatars, is the possibility of exhausting the network resources of a
587client. This problem is exacerbated when there is the possibility of an 601client. This problem is exacerbated when there is the possibility of an
588amplification attack as happens, for example, when sending a very small 602amplification attack, as happens, for example, when sending a very small
589avatar request message will force the user to reply with a larger avatar 603avatar request message will force the user to reply with a larger avatar
590data message. 604data message.
591 605
592The present proposal mitigates this situation by: 606The present proposal mitigates this situation by:
593 607
594 - Only transferring data between previously authenticated friends; 608 - only transferring data between previously authenticated friends,
595 609
596 - Enforcing strict limits on the avatar data size; 610 - enforcing strict limits on the avatar data size,
597 611
598 - Providing an alternate, smaller, message to cooperative users refresh 612 - providing an alternate, smaller message for cooperative users to refresh
599 avatar information when nothing has changed (`PACKET_ID_AVATAR_INFO`); 613 avatar information when nothing has changed (`PACKET_ID_AVATAR_INFO`),
600 614
601 - Having per-friend data transfer limit. As the current protocol still 615 - having a per-friend data transfer limit. As the current protocol still
602 allows an user to request avatar data again and again, the implementation 616 allows a user to request avatar data again and again, the implementation
603 limits the amount of data a particular user can request for some time. The 617 limits the amount of data a particular user can request for some time. The
604 exact values are defined in constants `AVATAR_DATA_TRANSFER_LIMIT` and 618 exact values are defined in constants `AVATAR_DATA_TRANSFER_LIMIT` and
605 `AVATAR_DATA_TRANSFER_TIMEOUT` in file `Messenger.c`. 619 `AVATAR_DATA_TRANSFER_TIMEOUT` in file `Messenger.c`.
606 620
607 - Making the requester responsible for storing partial data and state 621 - making the requester responsible for storing partial data and state
608 information; 622 information
609 623
610Another problem present in the avatars is the possibility of a friend send 624Another problem present in avatars is the possibility of a friend sending
611a maliciously crafted image intended to exploit vulnerabilities in image 625a maliciously crafted image intended to exploit vulnerabilities in image
612decoders. Without an intermediate server to recompress and validate and 626decoders. Without an intermediate server to recompress, validate, and
613convert the images to neutral formats, the client applications must handle 627convert the images to neutral formats, the client applications must handle
614this situation by themselves using stable and secure image libraries and 628this situation by themselves using stable and secure image libraries and
615imposing limits on the maximum amount of system resources the decoding 629imposing limits on the maximum amount of system resources the decoding
diff --git a/docs/TODO b/docs/TODO
index 16380c20..54137d0d 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -11,9 +11,11 @@ DHT:
11 [IN PROGRESS] Hardening against attacks. 11 [IN PROGRESS] Hardening against attacks.
12 [IN PROGRESS] Optimizing the code. 12 [IN PROGRESS] Optimizing the code.
13 13
14[IN PROGRESS] Friend only group chats 14[DONE] Friend only group chats
15 [IN PROGRESS] Networking base. 15 [DONE] Networking base.
16 [IN PROGRESS] Syncing chat state between clients (nicknames, list of who is in chat, etc...) 16 [MOSTLY DONE] Syncing chat state between clients (nicknames, list of who is in chat, etc...)
17 [NOT STARTED] Private messages. (and adding friends from group chats using those private messages.)
18 [NOT STARTED] File transfers.
17 19
18[IN PROGRESS] Audio/Video 20[IN PROGRESS] Audio/Video
19 [DONE] encoding/streaming/decoding 21 [DONE] encoding/streaming/decoding
@@ -22,7 +24,7 @@ DHT:
22 [IN PROGRESS] Auditing. 24 [IN PROGRESS] Auditing.
23 [NEEDS TESTING] Video packet splitting. 25 [NEEDS TESTING] Video packet splitting.
24 [IN PROGRESS] Prevent audio skew (seems to be easily solvable client side.) 26 [IN PROGRESS] Prevent audio skew (seems to be easily solvable client side.)
25 [IN PROGRESS] Group chats. 27 [IN PROGRESS] Group chats, audio done.
26 28
27Friend_requests.c: 29Friend_requests.c:
28 [NOT STARTED] What happens when a friend request is received needs to be changed. 30 [NOT STARTED] What happens when a friend request is received needs to be changed.
@@ -30,7 +32,7 @@ Friend_requests.c:
30 32
31[DONE] File transfers 33[DONE] File transfers
32[NOT STARTED] Offline messaging 34[NOT STARTED] Offline messaging
33[NOT STARTED] Friends list syncing 35[IN PROGRESS] Friends list syncing
34[DONE] IPV6 support 36[DONE] IPV6 support
35 37
36[IN PROGRESS] Make toxcore thread safe. 38[IN PROGRESS] Make toxcore thread safe.
@@ -38,14 +40,9 @@ Friend_requests.c:
38[NOT STARTED] Make the core save/datafile portable across client versions/different processor architectures. 40[NOT STARTED] Make the core save/datafile portable across client versions/different processor architectures.
39 41
40[MOSTLY DONE] A way for people to connect to people on Tox if they are behind a bad NAT that 42[MOSTLY DONE] A way for people to connect to people on Tox if they are behind a bad NAT that
41blocks UDP (or is just unpunchable) (docs/TCP_Network.txt) 43blocks UDP (or is just unpunchable) (docs/TCP_Network.txt) (Current way doesn't scale very well.)
42 44
43[DONE] Encrypted Saves. (see: toxencryptsave) 45[DONE] Encrypted Saves. (see: toxencryptsave)
44 46
45 47
46[IN PROGRESS] GUI (no official one chosen yet, a list of promising ones follows)
47https://github.com/notsecure/uTox
48https://github.com/tux3/qTox
49https://github.com/Reverp/Toxy
50
51[NOT STARTED] Security audit from professionals 48[NOT STARTED] Security audit from professionals
diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt
index ca561474..69ab9858 100644
--- a/docs/Tox_middle_level_network_protocol.txt
+++ b/docs/Tox_middle_level_network_protocol.txt
@@ -3,58 +3,58 @@ feature complete. Why doesn't Tox support TCP yet even if those parts are
3complete? 3complete?
4 4
5The answer is that a way to ensure a smooth switchover between the TCP and UDP 5The answer is that a way to ensure a smooth switchover between the TCP and UDP
6needs to be added. If Tox first connects to the other user using TCP but then 6needs to be added. If Tox first connects to the other user using TCP but then,
7due to pure chance manages to connect using the faster direct UDP connection 7due to pure chance, manages to connect using the faster direct UDP connection,
8Tox must switch seamlessly from the TCP to the UDP connection without there 8Tox must switch seamlessly from the TCP to the UDP connection without there
9being any data loss or the other user going offline and then back online. The 9being any data loss or the other user going offline and then back online. The
10transition must be seamless whatever both connected users are doing be it 10transition must be seamless whatever both connected users are doing - be it
11transferring files or simply chatting together. 11transferring files or simply chatting together.
12 12
13Possible evil/bad or simply TCP relays going offline must not impact the 13Possible evil/bad or simply TCP relays going offline must not impact the
14connection between both clients. 14connection between both clients.
15 15
16Typically Tox will use more than one TCP relay to connect to other peers for 16Typically, Tox will use more than one TCP relay to connect to other peers for
17maximum connection stability which means there must be a way for Tox to take 17maximum connection stability, which means there must be a way for Tox to take
18advantage of multiple relays in a way that the user will never be aware if one 18advantage of multiple relays in a way that the user will never be aware of, if one
19of them goes offline/tries to slow down the connection/decides to corrupt 19of them goes offline/tries to slow down the connection/decides to corrupt
20packets/etc.. 20packets/etc.
21 21
22To accomplish this Tox needs something between the low level protocol (TCP) and 22To accomplish this, Tox needs something between the low level protocol (TCP) and
23high level Tox messaging protocol hence the name middle level. 23high level Tox messaging protocol; hence the name middle level.
24 24
25The plan is to move some functionality from lossless_UDP to a higher level: 25The plan is to move some functionality from lossless_UDP to a higher level:
26more specifically the functionality for detecting which packets a peer is 26more specifically, the functionality for detecting which packets a peer is
27missing and the ability to request and send them again. lossless UDP uses plain 27missing, and the ability to request and send them again. Lossless UDP uses plain
28text packets to request missing packets from the other peer while Tox is 28text packets to request missing packets from the other peer, while Tox is
29currently designed to kill the connection if any packet tampering is detected. 29currently designed to kill the connection if any packet tampering is detected.
30This works very well when connecting directly with someone because if the 30This works very well when connecting directly with someone because if the
31attacker can modify packets it means he can kill your connection anyways. With 31attacker can modify packets, it means he can kill your connection anyway. With
32TCP relays however that is not the case as such the packets used to request 32TCP relays, however, that is not the case. As such the packets used to request
33missing packets must be encrypted. If it is detected that a packet has been 33missing packets must be encrypted. If it is detected that a packet has been
34tampered, the connection must stay intact while the evil relay must be 34tampered, the connection must stay intact while the evil relay must be
35disconnected from and replaced with a good relay, the behavior must be the same 35disconnected from and replaced with a good relay; the behavior must be the same
36as if the relay had just suddenly gone online. Of course something to protect 36as if the relay had just suddenly gone offline. Of course, something to protect
37from evil "friends" framing relays must also be implemented. 37from evil "friends" framing relays must also be implemented.
38 38
39Detailed implementation details: 39Detailed implementation details:
40 40
41cookie request packet: 41cookie request packet:
42[uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 42[uint8_t 24][Sender's DHT Public key (32 bytes)][Random nonce (24
43bytes)][Encrypted message containing: [Senders real public key (32 43bytes)][Encrypted message containing: [Sender's real public key (32
44bytes)][padding (32 bytes)][uint64_t number (must be sent 44bytes)][padding (32 bytes)][uint64_t number (must be sent
45back untouched in cookie response)]] 45back untouched in cookie response)]]
46Encrypted message is encrypted with sender DHT private key, receivers DHT 46Encrypted message is encrypted with sender's DHT private key, receiver's DHT
47public key and the nonce. 47public key and the nonce.
48 48
49cookie response packet: 49cookie response packet:
50[uint8_t 25][Random nonce (24 bytes)][Encrypted message containing: 50[uint8_t 25][Random nonce (24 bytes)][Encrypted message containing:
51[Cookie][uint64_t number (that was sent in the request)]] 51[Cookie][uint64_t number (that was sent in the request)]]
52Encrypted message is encrypted with sender DHT private key, receivers DHT 52Encrypted message is encrypted with sender's DHT private key, receiver's DHT
53public key and the nonce. 53public key and the nonce.
54 54
55The Cookie should be basically: 55The Cookie should be basically:
56[nonce][encrypted data:[uint64_t time][Senders real public key (32 56[nonce][encrypted data:[uint64_t time][Sender's real public key (32
57bytes)][Senders dht public key (32 bytes)]] 57bytes)][Sender's DHT public key (32 bytes)]]
58 58
59Handshake packet: 59Handshake packet:
60[uint8_t 26][Cookie][nonce][Encrypted message containing: [random 24 bytes base 60[uint8_t 26][Cookie][nonce][Encrypted message containing: [random 24 bytes base
@@ -66,25 +66,25 @@ The handshake packet is encrypted using the real private key of the sender, the
66real public key of the receiver and the nonce. 66real public key of the receiver and the nonce.
67 67
68 68
69Alice wants to connect to bob. 69Alice wants to connect to Bob:
70 70
71Alice sends a cookie request packet to bob and gets a cookie response back. 71Alice sends a cookie request packet to Bob and gets a cookie response back.
72 72
73Alice then generates a nonce and a temporary public/private keypair. 73Alice then generates a nonce and a temporary public/private keypair.
74 74
75Alice then takes that nonce and just generated private key, the obtained 75Alice then takes that nonce and just generated private key, the obtained
76cookie, creates a new cookie and puts them in a handshake packet which she 76cookie, creates a new cookie and puts them in a handshake packet, which she
77sends to bob. 77sends to Bob.
78 78
79Bob gets the handshake packet, accepts the connection request, then generates a 79Bob gets the handshake packet, accepts the connection request, then generates a
80nonce and a temporary public/private keypair and sends a handshake packet back 80nonce and a temporary public/private keypair and sends a handshake packet back
81with this just generated information and with the cookie field being the Other 81with this just generated information and with the cookie field being the Other
82Cookie contained in the received handshake. 82Cookie contained in the received handshake.
83 83
84Both then use these temporary keys to generate the session key with which every 84Both then use these temporary keys to generate the session key, with which every
85data packet sent and received will be encrypted and decrypted. The nonce sent 85data packet sent and received will be encrypted and decrypted. The nonce sent
86in the handshake will be used to encrypt the first data packet sent, the nonce 86in the handshake will be used to encrypt the first data packet sent, the nonce
87+ 1 the second, the nonce + 2 the third and so on. 87+ 1 for the second, the nonce + 2 for the third, and so on.
88 88
89Data packets: 89Data packets:
90 90
@@ -109,12 +109,12 @@ data ids:
109packet request packet: [uint8_t (1)][uint8_t num][uint8_t num][uint8_t 109packet request packet: [uint8_t (1)][uint8_t num][uint8_t num][uint8_t
110num]...[uint8_t num] 110num]...[uint8_t num]
111 111
112the list of nums are a list of packet numbers the other is requesting. 112The list of nums are a list of packet numbers the other is requesting.
113to get the real packet numbers from this list take the recvbuffers buffer_start 113In order to get the real packet numbers from this list, take the recvbuffers buffer_start
114from the packet, subtract 1 to it and put it in packet_num then start from the 114from the packet, subtract 1 from it and put it in packet_num, then start from the
115beginning of the num list: if num is zero, add 255 to packet_num then do the 115beginning of the num list: if num is zero, add 255 to packet_num, then do the
116next num. if num isn't zero, add its value to packet_num, note that the other 116next num. If num isn't zero, add its value to packet_num, note that the other
117has requested we send this packet again to them then continue to the next num in 117has requested we send this packet again to them, then continue to the next num in
118the list. 118the list.
119 119
120 120
diff --git a/other/bootstrap_daemon/README.md b/other/bootstrap_daemon/README.md
index 9a2dff4b..d0c16eb1 100644
--- a/other/bootstrap_daemon/README.md
+++ b/other/bootstrap_daemon/README.md
@@ -1,29 +1,32 @@
1##Instructions for Debian 1##Instructions
2
3This instruction primarily tested on Linux but, may be, will work on other POSIX-compliant systems.
2 4
3For security reasons we run the daemon under its own user. 5For security reasons we run the daemon under its own user.
6
4Create a new user by executing the following: 7Create a new user by executing the following:
5```sh 8```sh
6sudo useradd --system --shell /sbin/nologin --comment "Account to run Tox's DHT bootstrap daemon" --user-group tox-bootstrapd 9sudo useradd --home-dir /var/lib/tox-bootstrapd --create-home --system --shell /sbin/nologin --comment "Account to run Tox's DHT bootstrap daemon" --user-group tox-bootstrapd
7``` 10```
8 11
9Create a directory where the daemon will store its keys: 12Copy `tox-bootstrapd.conf` file to where `CFGFILE` variable from `tox-bootstrapd.sh` tells (for `init.d` users) or `ExecStart=` from `tox-bootstrap.service` ( for `systemd` users). By default it's `/etc/tox-bootstrapd.conf`.
10```sh 13
11sudo mkdir /var/lib/tox-bootstrapd/ 14Go over everything in `tox-bootstrapd.conf`. Make sure `pid_file_path` matches `PIDFILE` from `tox-bootstrapd.sh` (`init.d`) or `PIDFile=` from `tox-bootstrap.service` AND file in `ExecStartPre`(`systemd`).
12``` 15
13 16
14Restrain other users from accessing the directory: 17Restrict access to home directory:
15```sh 18```sh
16sudo chown tox-bootstrapd:tox-bootstrapd /var/lib/tox-bootstrapd/ 19sudo chmod 700 /var/lib/tox-bootstrapd
17sudo chmod 700 /var/lib/tox-bootstrapd/
18``` 20```
19 21
20Look at the variable declarations in the beginning of `tox-bootstrapd.sh` init script to see if you need to change anything for it to work for you. The default values must be fine for most users and we assume that you use those next. 22##For `init.d` users:
21
22Go over everything in `tox-bootstrapd.conf`. Make sure `pid_file_path` matches `PIDFILE` from `tox-bootstrapd.sh`.
23 23
24Place `tox-bootstrapd.conf` file to where `CFGFILE` variable from `tox-bootstrapd.sh` tells. By default it's `/etc/tox-bootstrapd.conf`. 24Look at the variable declarations in the beginning of `tox-bootstrapd.sh` init script to see if you need to change anything for it to work for you. The default values must be fine for most users and we assume that you use those next.
25 25
26Place `tox-bootstrapd.sh` init file at `/etc/init.d/tox-bootstrapd` (note the disappearance of ".sh" ending). 26Copy `tox-bootstrapd.sh` init file to `/etc/init.d/tox-bootstrapd` (note the disappearance of ".sh" ending).
27```sh
28sudo cp tox-bootstrapd.sh /etc/init.d/tox-bootstrapd
29```
27 30
28Set permissions for the init system to run the script: 31Set permissions for the init system to run the script:
29```sh 32```sh
@@ -50,23 +53,56 @@ Get your public key and check that the daemon initialized correctly:
50sudo grep "tox-bootstrapd" /var/log/syslog 53sudo grep "tox-bootstrapd" /var/log/syslog
51``` 54```
52 55
56##For `systemd` users:
57
58Copy tox-bootstrap.service to /etc/systemd/system/:
59```sh
60sudo cp tox-bootstrap.service /etc/systemd/system/
61```
62
63Make sure, that path to `chown` and `mkdir` is correct in `tox-bootstrap.service` (they may be different in some distributions, by default `/bin/chown` and `/bin/mkdir`)
64
65You must uncomment the next line in tox-bootstrap.service, if you want to use port number <1024
66
67 #CapabilityBoundingSet=CAP_NET_BIND_SERVICE
68
69and, possibly, install `libcap2-bin` or `libcap2` package, depending of your distribution.
70
53 71
72Reload systemd units definitions, enable service for automatic start (if needed), and start it:
73```sh
74sudo systemctl daemon-reload
75sudo systemctl enable tox-bootstrap.service
76sudo systemctl start tox-bootstrap.service
77```
54###Troubleshooting: 78###Troubleshooting:
55 79
56- Check daemon's status: 80- Check daemon's status:
57```sh 81```sh
82#init.d
58sudo service tox-bootstrapd status 83sudo service tox-bootstrapd status
84
85#systemd
86sudo systemctl status tox-bootstrap.service
59``` 87```
60 88
61- Check the log for errors: 89- Check the log for errors:
62```sh 90```sh
91#init.d
63sudo grep "tox-bootstrapd" /var/log/syslog 92sudo grep "tox-bootstrapd" /var/log/syslog
93
94#systemd
95sudo journalctl -f _SYSTEMD_UNIT=tox-bootstrap.service
64``` 96```
65 97
98`init.d`:
66- Check that variables in the beginning of `/etc/init.d/tox-bootstrapd` are valid. 99- Check that variables in the beginning of `/etc/init.d/tox-bootstrapd` are valid.
67 100
68- Make sure `pid_file_path` in `/etc/tox-bootstrapd.conf` matches `PIDFILE` from `/etc/init.d/tox-bootstrapd`.
69 101
70- Make sure you have write permission for keys and pid files. 102Common:
103
104- Make sure tox-bootstrapd user has write permission for keys and pid files (in systemd pid file insured by unit definition).
105
106- Make sure tox-bootstrapd has read permission for the config file.
71 107
72- Make sure you have read permission for the config file. 108- Make sure tox-bootstrapd location matches its path in init scripts, if you specified non-default `--prefix`, when building.
diff --git a/other/bootstrap_daemon/tox-bootstrapd.conf b/other/bootstrap_daemon/tox-bootstrapd.conf
index 4547d83d..d02eb3d0 100644
--- a/other/bootstrap_daemon/tox-bootstrapd.conf
+++ b/other/bootstrap_daemon/tox-bootstrapd.conf
@@ -24,8 +24,8 @@ enable_lan_discovery = true
24 24
25enable_tcp_relay = true 25enable_tcp_relay = true
26 26
27// Tox uses 443, 3389 and 33445 ports by default, so it's highly encouraged to keep 27// While Tox uses 33445 port by default, 443 (https) and 3389 (rdp) ports are very
28// them. 28// common among nodes, so it's encouraged to keep them in place.
29tcp_relay_ports = [443, 3389, 33445] 29tcp_relay_ports = [443, 3389, 33445]
30 30
31// Reply to MOTD (Message Of The Day) requests. 31// Reply to MOTD (Message Of The Day) requests.
@@ -45,48 +45,21 @@ motd = "tox-bootstrapd"
45// in both cases this will be interpreted as if you don't want to bootstrap 45// in both cases this will be interpreted as if you don't want to bootstrap
46// from anyone. 46// from anyone.
47// 47//
48// address = any ipv4 or ipv6 address and also any US-ASCII domain name. 48// address = any IPv4 or IPv6 address and also any US-ASCII domain name.
49bootstrap_nodes = ( 49bootstrap_nodes = (
50 { 50 { // Example Node 1 (IPv4)
51 // NikolaiToryzin - US 51 address = "127.0.0.1"
52 address = "192.254.75.98"
53 port = 33445 52 port = 33445
54 public_key = "951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F" 53 public_key = "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854"
55 }, 54 },
56 { 55 { // Example Node 2 (IPv6)
57 // Proplex - US 56 address = "::1/128"
58 address = "107.161.17.51"
59 port = 33445 57 port = 33445
60 public_key = "7BE3951B97CA4B9ECDDA768E8C52BA19E9E2690AB584787BF4C90E04DBB75111" 58 public_key = "3E78BACF0F84235B30054B54898F56793E1DEF8BD46B1038B9D822E8460FAB67"
61 }, 59 },
62 { 60 { // Example Node 3 (US-ASCII domain name)
63 // SonOfRa - DE 61 address = "example.org"
64 address = "144.76.60.215"
65 port = 33445 62 port = 33445
66 public_key = "04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F" 63 public_key = "8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858"
67 },
68 {
69 // Astonex - FR
70 address = "37.59.102.176"
71 port = 33445
72 public_key = "B98A2CEAA6C6A2FADC2C3632D284318B60FE5375CCB41EFA081AB67F500C1B0B"
73 },
74 {
75 // SylvieLorxu - NL
76 address = "178.21.112.187"
77 port = 33445
78 public_key = "4B2C19E924972CB9B57732FB172F8A8604DE13EEDA2A6234E348983344B23057"
79 },
80 {
81 // aitjcize - JP
82 address = "54.199.139.199"
83 port = 33445
84 public_key = "7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029"
85 },
86 {
87 // NikolaiToryzin - CH
88 address = "31.7.57.236"
89 port = 443
90 public_key = "2A4B50D1D525DA2E669592A20C327B5FAD6C7E5962DC69296F9FEC77C4436E4E"
91 } 64 }
92) 65) \ No newline at end of file
diff --git a/other/bootstrap_daemon/tox-bootstrapd.service b/other/bootstrap_daemon/tox-bootstrapd.service
new file mode 100644
index 00000000..4b499311
--- /dev/null
+++ b/other/bootstrap_daemon/tox-bootstrapd.service
@@ -0,0 +1,19 @@
1[Unit]
2Description=Tox DHT Bootstrap Daemon
3After=network.target
4
5[Service]
6Type=forking
7PermissionsStartOnly=true
8ExecStartPre=-/bin/mkdir /var/run/tox-bootstrapd -p
9ExecStartPre=/bin/chown tox-bootstrapd:tox-bootstrapd -R /var/run/tox-bootstrapd
10WorkingDirectory=/var/lib/tox-bootstrapd
11ExecStart=/usr/local/bin/tox-bootstrapd /etc/tox-bootstrapd.conf
12User=tox-bootstrapd
13Group=tox-bootstrapd
14PIDFile=/var/run/tox-bootstrapd/tox-bootstrapd.pid
15#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
16
17[Install]
18WantedBy=multi-user.target
19
diff --git a/other/bootstrap_node_packets.c b/other/bootstrap_node_packets.c
index e8df3289..0bf9b9b0 100644
--- a/other/bootstrap_node_packets.c
+++ b/other/bootstrap_node_packets.c
@@ -34,7 +34,7 @@ static uint16_t bootstrap_motd_length;
34/* To request this packet just send a packet of length INFO_REQUEST_PACKET_LENGTH 34/* To request this packet just send a packet of length INFO_REQUEST_PACKET_LENGTH
35 * with the first byte being BOOTSTRAP_INFO_PACKET_ID 35 * with the first byte being BOOTSTRAP_INFO_PACKET_ID
36 */ 36 */
37static int handle_info_request(void *object, IP_Port source, const uint8_t *packet, uint32_t length) 37static int handle_info_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length)
38{ 38{
39 if (length != INFO_REQUEST_PACKET_LENGTH) 39 if (length != INFO_REQUEST_PACKET_LENGTH)
40 return 1; 40 return 1;
diff --git a/other/fun/make-funny-savefile.py b/other/fun/make-funny-savefile.py
new file mode 100755
index 00000000..43f14a6e
--- /dev/null
+++ b/other/fun/make-funny-savefile.py
@@ -0,0 +1,122 @@
1#!/usr/bin/python
2
3"""
4Generate a new (and empty) save file with predefined keys. Used to play
5with externally generated keys.
6
7(c) 2015 Alexandre Erwin Ittner
8
9Distributed under the GNU GPL v3 or later, WITHOUT ANY WARRANTY. See the
10file "COPYING" for license information.
11
12
13Usage:
14
15 ./make-funny-savefile.py <public key> <private key> <user name> <out file>
16
17 The new user profile will be saved to <out file>.
18
19 The keys must be an hex-encoded valid key pair generated by any means
20 (eg. strkey.c); username may be anything. A random nospam value will be
21 generated.
22
23 Once the savefile is done, load it in your favorite client to get some
24 DHT nodes, set status and status messages, add friends, etc.
25
26
27Example (of course, do not try using this key for anything real):
28
29 ./make-funny-savefile.py 123411DC8B1A4760B648E0C7243B65F01069E4858F45C612CE1A6F673B603830 CC39440CFC063E4A95B7F2FB2580210558BE5C073AFC1C9604D431CCA3132238 "Test user" test.tox
30
31
32"""
33
34
35PUBLIC_KEY_LENGTH = 32
36PRIVATE_KEY_LENGTH = 32
37
38# Constants taken from messenger.c
39MESSENGER_STATE_COOKIE_GLOBAL = 0x15ed1b1f
40MESSENGER_STATE_COOKIE_TYPE = 0x01ce
41MESSENGER_STATE_TYPE_NOSPAMKEYS = 1
42MESSENGER_STATE_TYPE_DHT = 2
43MESSENGER_STATE_TYPE_FRIENDS = 3
44MESSENGER_STATE_TYPE_NAME = 4
45MESSENGER_STATE_TYPE_STATUSMESSAGE = 5
46MESSENGER_STATE_TYPE_STATUS = 6
47MESSENGER_STATE_TYPE_TCP_RELAY = 10
48MESSENGER_STATE_TYPE_PATH_NODE = 11
49
50STATUS_MESSAGE = "New user".encode("utf-8")
51
52
53
54import sys
55import struct
56import os
57
58def abort(msg):
59 print(msg)
60 exit(1)
61
62
63
64if len(sys.argv) != 5:
65 abort("Usage: %s <public key> <private key> <user name> <out file>" % (sys.argv[0]))
66
67try:
68 public_key = sys.argv[1].decode("hex")
69except:
70 abort("Bad public key")
71
72try:
73 private_key = sys.argv[2].decode("hex")
74except:
75 abort("Bad private key")
76
77if len(public_key) != PUBLIC_KEY_LENGTH:
78 abort("Public key with wrong length")
79
80if len(private_key) != PRIVATE_KEY_LENGTH:
81 abort("Private key with wrong length")
82
83user_name = sys.argv[3].encode("utf-8")
84
85if len(user_name) > 32:
86 abort("User name too long (for this script, at least)")
87
88out_file_name = sys.argv[4]
89nospam = os.urandom(4)
90
91
92def make_subheader(h_type, h_length):
93 return (
94 struct.pack("<I", h_length) +
95 struct.pack("<H", h_type) +
96 struct.pack("<H", MESSENGER_STATE_COOKIE_TYPE))
97
98data = (
99 # Main header
100 struct.pack("<I", 0) +
101 struct.pack("<I", MESSENGER_STATE_COOKIE_GLOBAL) +
102
103 # Keys
104 make_subheader(MESSENGER_STATE_TYPE_NOSPAMKEYS,
105 len(nospam) + PUBLIC_KEY_LENGTH + PRIVATE_KEY_LENGTH) +
106 nospam + public_key + private_key +
107
108 # Name (not really needed, but helps)
109 make_subheader(MESSENGER_STATE_TYPE_NAME, len(user_name)) +
110 user_name +
111
112 # Status message (not really needed, but helps)
113 make_subheader(MESSENGER_STATE_TYPE_STATUSMESSAGE, len(STATUS_MESSAGE)) +
114 STATUS_MESSAGE
115)
116
117
118try:
119 with open(out_file_name, "wb") as fp:
120 fp.write(data)
121except Exception as e:
122 abort(str(e))
diff --git a/osx_build_script_toxcore.txt b/other/osx_build_script_toxcore.sh
index 8aea0d1c..8aea0d1c 100644
--- a/osx_build_script_toxcore.txt
+++ b/other/osx_build_script_toxcore.sh
diff --git a/testing/test_avatars.c b/testing/test_avatars.c
index 71a0330e..b4adc48f 100644
--- a/testing/test_avatars.c
+++ b/testing/test_avatars.c
@@ -18,7 +18,7 @@
18 * Data dir MAY have: 18 * Data dir MAY have:
19 * 19 *
20 * - A directory named "avatars" with the user's avatar and cached avatars. 20 * - A directory named "avatars" with the user's avatar and cached avatars.
21 * The user avatar must be named in the format: "<uppercase user id>.png" 21 * The user avatar must be named in the format: "<uppercase pub key>.png"
22 * 22 *
23 * 23 *
24 * The bot will answer to these commands: 24 * The bot will answer to these commands:
@@ -163,14 +163,14 @@ static void byte_to_hex_str(const uint8_t *buf, const size_t buflen, char *dst)
163 dst[j++] = '\0'; 163 dst[j++] = '\0';
164} 164}
165 165
166/* Make the cache file name for a avatar of the given format for the given 166/* Make the cache file name for an avatar of the given format for the given
167 * client id. 167 * public key.
168 */ 168 */
169static int make_avatar_file_name(char *dst, size_t dst_len, const char *base_dir, 169static int make_avatar_file_name(char *dst, size_t dst_len, const char *base_dir,
170 const uint8_t format, uint8_t *client_id) 170 const uint8_t format, uint8_t *public_key)
171{ 171{
172 char client_id_str[2 * TOX_CLIENT_ID_SIZE + 1]; 172 char public_key_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
173 byte_to_hex_str(client_id, TOX_CLIENT_ID_SIZE, client_id_str); 173 byte_to_hex_str(public_key, TOX_PUBLIC_KEY_SIZE, public_key_str);
174 174
175 const char *suffix = get_avatar_suffix_from_format(format); 175 const char *suffix = get_avatar_suffix_from_format(format);
176 176
@@ -178,7 +178,7 @@ static int make_avatar_file_name(char *dst, size_t dst_len, const char *base_dir
178 return -1; /* Error */ 178 return -1; /* Error */
179 179
180 int n = snprintf(dst, dst_len, "%s/%s/%s.%s", base_dir, AVATAR_DIR_NAME, 180 int n = snprintf(dst, dst_len, "%s/%s/%s.%s", base_dir, AVATAR_DIR_NAME,
181 client_id_str, suffix); 181 public_key_str, suffix);
182 dst[dst_len - 1] = '\0'; 182 dst[dst_len - 1] = '\0';
183 183
184 if (n >= dst_len) 184 if (n >= dst_len)
@@ -196,7 +196,7 @@ static int make_avatar_file_name(char *dst, size_t dst_len, const char *base_dir
196static int load_user_avatar(Tox *tox, char *base_dir, int friendnum, 196static int load_user_avatar(Tox *tox, char *base_dir, int friendnum,
197 uint8_t format, uint8_t *hash, uint8_t *data, uint32_t *datalen) 197 uint8_t format, uint8_t *hash, uint8_t *data, uint32_t *datalen)
198{ 198{
199 uint8_t addr[TOX_CLIENT_ID_SIZE]; 199 uint8_t addr[TOX_PUBLIC_KEY_SIZE];
200 200
201 if (tox_get_client_id(tox, friendnum, addr) != 0) { 201 if (tox_get_client_id(tox, friendnum, addr) != 0) {
202 DEBUG("Bad client id, friendnumber=%d", friendnum); 202 DEBUG("Bad client id, friendnumber=%d", friendnum);
@@ -224,14 +224,14 @@ static int load_user_avatar(Tox *tox, char *base_dir, int friendnum,
224 return 0; 224 return 0;
225} 225}
226 226
227/* Save a user avatar into the cache. Gets the file name from client id and 227/* Save a user avatar into the cache. Gets the file name from the public key
228 * the given data format. 228 * and the given data format.
229 * Returns 0 on success, or -1 on error. 229 * Returns 0 on success, or -1 on error.
230 */ 230 */
231static int save_user_avatar(Tox *tox, char *base_dir, int friendnum, 231static int save_user_avatar(Tox *tox, char *base_dir, int friendnum,
232 uint8_t format, uint8_t *data, uint32_t datalen) 232 uint8_t format, uint8_t *data, uint32_t datalen)
233{ 233{
234 uint8_t addr[TOX_CLIENT_ID_SIZE]; 234 uint8_t addr[TOX_PUBLIC_KEY_SIZE];
235 235
236 if (tox_get_client_id(tox, friendnum, addr) != 0) { 236 if (tox_get_client_id(tox, friendnum, addr) != 0) {
237 DEBUG("Bad client id, friendnumber=%d", friendnum); 237 DEBUG("Bad client id, friendnumber=%d", friendnum);
@@ -252,7 +252,7 @@ static int save_user_avatar(Tox *tox, char *base_dir, int friendnum,
252/* Delete all cached avatars for a given user */ 252/* Delete all cached avatars for a given user */
253static int delete_user_avatar(Tox *tox, char *base_dir, int friendnum) 253static int delete_user_avatar(Tox *tox, char *base_dir, int friendnum)
254{ 254{
255 uint8_t addr[TOX_CLIENT_ID_SIZE]; 255 uint8_t addr[TOX_PUBLIC_KEY_SIZE];
256 256
257 if (tox_get_client_id(tox, friendnum, addr) != 0) { 257 if (tox_get_client_id(tox, friendnum, addr) != 0) {
258 DEBUG("Bad client id, friendnumber=%d", friendnum); 258 DEBUG("Bad client id, friendnumber=%d", friendnum);
@@ -288,11 +288,11 @@ static int delete_user_avatar(Tox *tox, char *base_dir, int friendnum)
288 288
289static void friend_status_cb(Tox *tox, int n, uint8_t status, void *ud) 289static void friend_status_cb(Tox *tox, int n, uint8_t status, void *ud)
290{ 290{
291 uint8_t addr[TOX_CLIENT_ID_SIZE]; 291 uint8_t addr[TOX_PUBLIC_KEY_SIZE];
292 char addr_str[2 * TOX_CLIENT_ID_SIZE + 1]; 292 char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
293 293
294 if (tox_get_client_id(tox, n, addr) == 0) { 294 if (tox_get_client_id(tox, n, addr) == 0) {
295 byte_to_hex_str(addr, TOX_CLIENT_ID_SIZE, addr_str); 295 byte_to_hex_str(addr, TOX_PUBLIC_KEY_SIZE, addr_str);
296 printf("Receiving status from %s: %u\n", addr_str, status); 296 printf("Receiving status from %s: %u\n", addr_str, status);
297 } 297 }
298} 298}
@@ -300,12 +300,12 @@ static void friend_status_cb(Tox *tox, int n, uint8_t status, void *ud)
300static void friend_avatar_info_cb(Tox *tox, int32_t n, uint8_t format, uint8_t *hash, void *ud) 300static void friend_avatar_info_cb(Tox *tox, int32_t n, uint8_t format, uint8_t *hash, void *ud)
301{ 301{
302 char *base_dir = (char *) ud; 302 char *base_dir = (char *) ud;
303 uint8_t addr[TOX_CLIENT_ID_SIZE]; 303 uint8_t addr[TOX_PUBLIC_KEY_SIZE];
304 char addr_str[2 * TOX_CLIENT_ID_SIZE + 1]; 304 char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
305 char hash_str[2 * TOX_HASH_LENGTH + 1]; 305 char hash_str[2 * TOX_HASH_LENGTH + 1];
306 306
307 if (tox_get_client_id(tox, n, addr) == 0) { 307 if (tox_get_client_id(tox, n, addr) == 0) {
308 byte_to_hex_str(addr, TOX_CLIENT_ID_SIZE, addr_str); 308 byte_to_hex_str(addr, TOX_PUBLIC_KEY_SIZE, addr_str);
309 printf("Receiving avatar information from %s.\n", addr_str); 309 printf("Receiving avatar information from %s.\n", addr_str);
310 } else { 310 } else {
311 DEBUG("tox_get_client_id failed"); 311 DEBUG("tox_get_client_id failed");
@@ -350,12 +350,12 @@ static void friend_avatar_data_cb(Tox *tox, int32_t n, uint8_t format,
350 uint8_t *hash, uint8_t *data, uint32_t datalen, void *ud) 350 uint8_t *hash, uint8_t *data, uint32_t datalen, void *ud)
351{ 351{
352 char *base_dir = (char *) ud; 352 char *base_dir = (char *) ud;
353 uint8_t addr[TOX_CLIENT_ID_SIZE]; 353 uint8_t addr[TOX_PUBLIC_KEY_SIZE];
354 char addr_str[2 * TOX_CLIENT_ID_SIZE + 1]; 354 char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
355 char hash_str[2 * TOX_HASH_LENGTH + 1]; 355 char hash_str[2 * TOX_HASH_LENGTH + 1];
356 356
357 if (tox_get_client_id(tox, n, addr) == 0) { 357 if (tox_get_client_id(tox, n, addr) == 0) {
358 byte_to_hex_str(addr, TOX_CLIENT_ID_SIZE, addr_str); 358 byte_to_hex_str(addr, TOX_PUBLIC_KEY_SIZE, addr_str);
359 printf("Receiving avatar data from %s.\n", addr_str); 359 printf("Receiving avatar data from %s.\n", addr_str);
360 } else { 360 } else {
361 DEBUG("tox_get_client_id failed"); 361 DEBUG("tox_get_client_id failed");
@@ -382,8 +382,8 @@ static void friend_msg_cb(Tox *tox, int n, const uint8_t *msg, uint16_t len, voi
382{ 382{
383 const char *base_dir = (char *) ud; 383 const char *base_dir = (char *) ud;
384 const char *msg_str = (char *) msg; 384 const char *msg_str = (char *) msg;
385 uint8_t addr[TOX_CLIENT_ID_SIZE]; 385 uint8_t addr[TOX_PUBLIC_KEY_SIZE];
386 char addr_str[2 * TOX_CLIENT_ID_SIZE + 1]; 386 char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
387 387
388 if (tox_get_client_id(tox, n, addr) == 0) { 388 if (tox_get_client_id(tox, n, addr) == 0) {
389 byte_to_hex_str(addr, TOX_FRIEND_ADDRESS_SIZE, addr_str); 389 byte_to_hex_str(addr, TOX_FRIEND_ADDRESS_SIZE, addr_str);
@@ -428,8 +428,8 @@ static void friend_msg_cb(Tox *tox, int n, const uint8_t *msg, uint16_t len, voi
428static void friend_request_cb(Tox *tox, const uint8_t *public_key, 428static void friend_request_cb(Tox *tox, const uint8_t *public_key,
429 const uint8_t *data, uint16_t length, void *ud) 429 const uint8_t *data, uint16_t length, void *ud)
430{ 430{
431 char addr_str[2 * TOX_CLIENT_ID_SIZE + 1]; 431 char addr_str[2 * TOX_PUBLIC_KEY_SIZE + 1];
432 byte_to_hex_str(public_key, TOX_CLIENT_ID_SIZE, addr_str); 432 byte_to_hex_str(public_key, TOX_PUBLIC_KEY_SIZE, addr_str);
433 printf("Accepting friend request from %s.\n %s\n", addr_str, data); 433 printf("Accepting friend request from %s.\n %s\n", addr_str, data);
434 tox_add_friend_norequest(tox, public_key); 434 tox_add_friend_norequest(tox, public_key);
435} 435}
diff --git a/tox.spec.in b/tox.spec.in
new file mode 100644
index 00000000..f6136dc7
--- /dev/null
+++ b/tox.spec.in
@@ -0,0 +1,67 @@
1Name: @PACKAGE_NAME@
2Version: @VERSION@
3Release: 1%{?dist}
4Summary: All-in-one secure communication platform
5
6License: GPLv3
7URL: https://github.com/irungentoo/toxcore
8Source0: https://github.com/irungentoo/toxcore/releases/tox-%{version}.tar.gz
9
10BuildRequires: autoconf automake libtool libvpx-devel opus-devel
11BuildRequires: libsodium-devel libconfig-devel
12
13%description
14With the rise of governmental monitoring programs, Tox, a FOSS initiative, aims to be an easy to use, all-in-one communication platform that ensures their users full privacy and secure message delivery.
15
16%package devel
17Summary: Development files for @PACKAGE_NAME@
18Requires: %{name} = %{version}-%{release}
19
20%description devel
21Development package for @PACKAGE_NAME@
22
23%prep
24%setup -q
25
26
27%build
28%configure \
29 --enable-shared \
30 --disable-static \
31 --enable-av \
32 --disable-ntox \
33 --disable-daemon \
34 --disable-testing
35
36make %{?_smp_mflags}
37
38
39%install
40%make_install
41
42# remove la files
43find %{buildroot} -name '*.la' -delete -print
44
45# not handling DHT_bootstrap yet
46rm -f %{buildroot}%{_bindir}/DHT_bootstrap
47
48%post
49/sbin/ldconfig
50
51%postun
52/sbin/ldconfig
53
54%files
55%defattr(-,root,root)
56%doc COPYING README.md
57%{_libdir}/libtox*.so.*
58
59%files devel
60%defattr(-, root, root)
61%{_includedir}/tox/
62%{_libdir}/libtox*.so
63%{_libdir}/pkgconfig/libtox*.pc
64
65%changelog
66* Tue Mar 3 2015 Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc> - 0.0.0-1
67- initial package
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc
index 6458260d..b61c1ea0 100644
--- a/toxav/Makefile.inc
+++ b/toxav/Makefile.inc
@@ -49,6 +49,7 @@ av_test_LDADD = $(LIBSODIUM_LDFLAGS) \
49 libtoxcore.la \ 49 libtoxcore.la \
50 $(LIBSODIUM_LIBS) \ 50 $(LIBSODIUM_LIBS) \
51 $(NACL_OBJECTS) \ 51 $(NACL_OBJECTS) \
52 -lopenal \
52 $(NACL_LIBS) 53 $(NACL_LIBS)
53 54
54 55
diff --git a/toxav/av_test.c b/toxav/av_test.c
index bb79eedc..01484249 100644
--- a/toxav/av_test.c
+++ b/toxav/av_test.c
@@ -1,6 +1,18 @@
1#include "toxav.h" 1#include "toxav.h"
2#include "../toxcore/tox.h" 2#include "../toxcore/tox.h"
3 3
4#ifdef __APPLE__
5# include <OpenAL/al.h>
6# include <OpenAL/alc.h>
7#else
8# include <AL/al.h>
9# include <AL/alc.h>
10/* compatibility with older versions of OpenAL */
11# ifndef ALC_ALL_DEVICES_SPECIFIER
12# include <AL/alext.h>
13# endif /* ALC_ALL_DEVICES_SPECIFIER */
14#endif /* __APPLE__ */
15
4#include <assert.h> 16#include <assert.h>
5#include <stdio.h> 17#include <stdio.h>
6#include <stdlib.h> 18#include <stdlib.h>
@@ -14,6 +26,16 @@
14#define c_sleep(x) usleep(1000*x) 26#define c_sleep(x) usleep(1000*x)
15#endif 27#endif
16 28
29/* Enable/disable tests */
30#define TEST_REGULAR_AV 0
31#define TEST_REGULAR_A 0
32#define TEST_REGULAR_V 0
33#define TEST_REJECT 0
34#define TEST_CANCEL 0
35#define TEST_MUTE_UNMUTE 0
36#define TEST_TRANSFER_A 1
37
38
17typedef struct { 39typedef struct {
18 bool incoming; 40 bool incoming;
19 uint32_t state; 41 uint32_t state;
@@ -134,9 +156,201 @@ void iterate(Tox* Bsn, ToxAV* AliceAV, ToxAV* BobAV)
134 c_sleep(20); 156 c_sleep(20);
135} 157}
136 158
159int device_read_frame(ALCdevice* device, int32_t frame_dur, int16_t* PCM, size_t max_size)
160{
161 int f_size = (48000 * frame_dur / 1000);
162
163 if (max_size < f_size)
164 return -1;
165
166 /* Don't block if not enough data */
167 int32_t samples;
168 alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, sizeof(int32_t), &samples);
169 if (samples < f_size)
170 return 0;
171
172 alcCaptureSamples(device, PCM, f_size);
173 return f_size;
174}
175
176int device_play_frame(uint32_t source, int16_t* PCM, size_t size)
177{
178 uint32_t bufid;
179 int32_t processed, queued;
180 alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
181 alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
182
183 if(processed) {
184 uint32_t bufids[processed];
185 alSourceUnqueueBuffers(source, processed, bufids);
186 alDeleteBuffers(processed - 1, bufids + 1);
187 bufid = bufids[0];
188 }
189 else if(queued < 16)
190 alGenBuffers(1, &bufid);
191 else
192 return 0;
193
194
195 alBufferData(bufid, AL_FORMAT_STEREO16, PCM, size * 2 * 2, 48000);
196 alSourceQueueBuffers(source, 1, &bufid);
197
198 int32_t state;
199 alGetSourcei(source, AL_SOURCE_STATE, &state);
200
201 if(state != AL_PLAYING)
202 alSourcePlay(source);
203 return 1;
204}
205
206int print_devices()
207{
208 const char* default_input;
209 const char* default_output;
210
211 const char *device;
212
213 printf("Default input device: %s\n", alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
214 printf("Default output device: %s\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
215
216 printf("\n");
217
218 printf("Input devices:\n");
219
220 int i = 0;
221 for(device = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); *device;
222 device += strlen( device ) + 1, ++i) {
223 printf("%d) %s\n", i, device);
224 }
225
226 printf("\n");
227 printf("Output devices:\n");
228
229 i = 0;
230 for(device = alcGetString(NULL, ALC_DEVICE_SPECIFIER); *device;
231 device += strlen( device ) + 1, ++i) {
232 printf("%d) %s\n", i, device);
233 }
234
235 return 0;
236}
237
238int print_help(const char* name, int rc)
239{
240 fprintf(stderr, "Usage: %s [-h] <in device> <out device>\n", name);
241 return rc;
242}
243
244long get_device_idx(const char* arg)
245{
246 if (strcmp(arg, "-") == 0)
247 return -1; /* Default */
248
249 char *p;
250 long res = strtol(arg, &p, 10);
251
252 if (*p) {
253 fprintf(stderr, "Invalid device!");
254 exit(1);
255 }
256
257 return res;
258}
137 259
138int main (int argc, char** argv) 260int main (int argc, char** argv)
139{ 261{
262 if (argc == 2) {
263 if (strcmp(argv[1], "-d") == 0 || strcmp(argv[1], "--devices") == 0) {
264 return print_devices();
265 }
266 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
267 return print_help(argv[0], 0);
268 }
269 }
270
271 if (argc != 3) {
272 fprintf(stderr, "Invalid input!\n");
273 return print_help(argv[0], 1);
274 }
275
276 int i;
277
278 const char* in_device_name = "";
279 const char* out_device_name = "";
280
281 {
282 long dev = get_device_idx(argv[1]);
283 if (dev == -1)
284 in_device_name = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
285 else
286 {
287 const char* tmp;
288 i = -1;
289 for(tmp = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); *tmp && i != dev;
290 tmp += strlen( tmp ) + 1, ++i)
291 in_device_name = tmp;
292 }
293
294 printf("Input device: %s\n", in_device_name);
295 }
296
297 {
298 long dev = get_device_idx(argv[1]);
299 if (dev == -1)
300 out_device_name = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
301 else
302 {
303 const char* tmp;
304 i = -1;
305 for(tmp = alcGetString(NULL, ALC_DEVICE_SPECIFIER); *tmp && i != dev;
306 tmp += strlen( tmp ) + 1, ++i)
307 out_device_name = tmp;
308 }
309
310 printf("Output device: %s\n", out_device_name);
311 }
312
313 ALCdevice* out_device;
314 ALCcontext* out_ctx;
315 uint32_t source;
316 uint32_t buffers[5];
317
318 { /* Open output device */
319 out_device = alcOpenDevice(out_device_name);
320 if ( !out_device ) {
321 fprintf(stderr, "Failed to open playback device: %s: %d\n", out_device_name, alGetError());
322 return 1;
323 }
324
325 out_ctx = alcCreateContext(out_device, NULL);
326 alcMakeContextCurrent(out_ctx);
327
328 alGenBuffers(5, buffers);
329 alGenSources((uint32_t)1, &source);
330 alSourcei(source, AL_LOOPING, AL_FALSE);
331
332 uint16_t zeros[10000];
333 memset(zeros, 0, 10000);
334
335 for ( i = 0; i < 5; ++i )
336 alBufferData(buffers[i], AL_FORMAT_STEREO16, zeros, 10000, 48000);
337
338 alSourceQueueBuffers(source, 5, buffers);
339 alSourcePlay(source);
340 }
341
342 ALCdevice* in_device;
343
344 { /* Open input device */
345 in_device = alcCaptureOpenDevice(in_device_name, 48000, AL_FORMAT_STEREO16, 10000);
346 if ( !in_device ) {
347 fprintf(stderr, "Failed to open capture device: %s: %d\n", in_device_name, alGetError());
348 return 1;
349 }
350
351 alcCaptureStart(in_device);
352 }
353
140 Tox *Bsn = tox_new(0); 354 Tox *Bsn = tox_new(0);
141 Tox *Alice = tox_new(0); 355 Tox *Alice = tox_new(0);
142 Tox *Bob = tox_new(0); 356 Tox *Bob = tox_new(0);
@@ -163,7 +377,7 @@ int main (int argc, char** argv)
163 377
164 378
165#define REGULAR_CALL_FLOW(A_BR, V_BR) \ 379#define REGULAR_CALL_FLOW(A_BR, V_BR) \
166 { \ 380 do { \
167 memset(&AliceCC, 0, sizeof(CallControl)); \ 381 memset(&AliceCC, 0, sizeof(CallControl)); \
168 memset(&BobCC, 0, sizeof(CallControl)); \ 382 memset(&BobCC, 0, sizeof(CallControl)); \
169 \ 383 \
@@ -208,20 +422,26 @@ int main (int argc, char** argv)
208 iterate(Bsn, AliceAV, BobAV); \ 422 iterate(Bsn, AliceAV, BobAV); \
209 } \ 423 } \
210 printf("Success!\n");\ 424 printf("Success!\n");\
211 } 425 } while(0)
212
213 printf("\nTrying regular call (Audio and Video)...\n");
214 REGULAR_CALL_FLOW(48, 4000);
215
216 printf("\nTrying regular call (Audio only)...\n");
217 REGULAR_CALL_FLOW(48, 0);
218
219 printf("\nTrying regular call (Video only)...\n");
220 REGULAR_CALL_FLOW(0, 4000);
221 426
427 if (TEST_REGULAR_AV) {
428 printf("\nTrying regular call (Audio and Video)...\n");
429 REGULAR_CALL_FLOW(48, 4000);
430 }
431
432 if (TEST_REGULAR_A) {
433 printf("\nTrying regular call (Audio only)...\n");
434 REGULAR_CALL_FLOW(48, 0);
435 }
436
437 if (TEST_REGULAR_V) {
438 printf("\nTrying regular call (Video only)...\n");
439 REGULAR_CALL_FLOW(0, 4000);
440 }
441
222#undef REGULAR_CALL_FLOW 442#undef REGULAR_CALL_FLOW
223 443
224 { /* Alice calls; Bob rejects */ 444 if (TEST_REJECT) { /* Alice calls; Bob rejects */
225 printf("\nTrying reject flow...\n"); 445 printf("\nTrying reject flow...\n");
226 446
227 memset(&AliceCC, 0, sizeof(CallControl)); 447 memset(&AliceCC, 0, sizeof(CallControl));
@@ -257,7 +477,7 @@ int main (int argc, char** argv)
257 printf("Success!\n"); 477 printf("Success!\n");
258 } 478 }
259 479
260 { /* Alice calls; Alice cancels while ringing */ 480 if (TEST_CANCEL) { /* Alice calls; Alice cancels while ringing */
261 printf("\nTrying cancel (while ringing) flow...\n"); 481 printf("\nTrying cancel (while ringing) flow...\n");
262 482
263 memset(&AliceCC, 0, sizeof(CallControl)); 483 memset(&AliceCC, 0, sizeof(CallControl));
@@ -294,10 +514,9 @@ int main (int argc, char** argv)
294 printf("Success!\n"); 514 printf("Success!\n");
295 } 515 }
296 516
297 { /* Check Mute-Unmute etc */ 517 if (TEST_MUTE_UNMUTE) { /* Check Mute-Unmute etc */
298 printf("\nTrying mute functionality...\n"); 518 printf("\nTrying mute functionality...\n");
299 519
300
301 memset(&AliceCC, 0, sizeof(CallControl)); 520 memset(&AliceCC, 0, sizeof(CallControl));
302 memset(&BobCC, 0, sizeof(CallControl)); 521 memset(&BobCC, 0, sizeof(CallControl));
303 522
@@ -382,7 +601,23 @@ int main (int argc, char** argv)
382 printf("Success!\n"); 601 printf("Success!\n");
383 } 602 }
384 603
385 604 if (TEST_TRANSFER_A) { /* Audio encoding/decoding and transfer */
605 printf("\nTrying audio enc/dec...\n");
606
607 int16_t PCM[10000];
608 time_t start_time = time(NULL);
609
610 /* Run for 5 seconds */
611 while ( start_time + 10 > time(NULL) ) {
612 int frame_size = device_read_frame(in_device, 20, PCM, sizeof(PCM));
613 if (frame_size > 0)
614 device_play_frame(source, PCM, frame_size);
615// c_sleep(20);
616 }
617
618 printf("Success!");
619 }
620
386 toxav_kill(BobAV); 621 toxav_kill(BobAV);
387 toxav_kill(AliceAV); 622 toxav_kill(AliceAV);
388 tox_kill(Bob); 623 tox_kill(Bob);
@@ -390,5 +625,8 @@ int main (int argc, char** argv)
390 tox_kill(Bsn); 625 tox_kill(Bsn);
391 626
392 printf("\nTest successful!\n"); 627 printf("\nTest successful!\n");
628
629 alcCloseDevice(out_device);
630 alcCaptureCloseDevice(in_device);
393 return 0; 631 return 0;
394} \ No newline at end of file 632} \ No newline at end of file
diff --git a/toxav/codec.c b/toxav/codec.c
index 95e0beb4..bf94115e 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -41,7 +41,6 @@
41#define DEFAULT_JBUF 6 41#define DEFAULT_JBUF 6
42 42
43/* Good quality encode. */ 43/* Good quality encode. */
44#define MAX_ENCODE_TIME_US VPX_DL_GOOD_QUALITY
45#define MAX_DECODE_TIME_US 0 44#define MAX_DECODE_TIME_US 0
46 45
47#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */ 46#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */
diff --git a/toxav/msi.c b/toxav/msi.c
index ac900dac..e21ec948 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -783,4 +783,4 @@ void handle_msi_packet ( Messenger *m, int friend_id, const uint8_t *data, uint1
783 handle_pop(call, &msg); /* always kills the call */ 783 handle_pop(call, &msg); /* always kills the call */
784 784
785 pthread_mutex_unlock(session->mutex); 785 pthread_mutex_unlock(session->mutex);
786} \ No newline at end of file 786}
diff --git a/toxav/toxav_new_1.c b/toxav/toxav_new_1.c
deleted file mode 100644
index 145dcf48..00000000
--- a/toxav/toxav_new_1.c
+++ /dev/null
@@ -1,688 +0,0 @@
1/** toxav.c
2 *
3 * Copyright (C) 2013 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif /* HAVE_CONFIG_H */
25
26#define __TOX_DEFINED__
27typedef struct Messenger Tox;
28
29#define _GNU_SOURCE /* implicit declaration warning */
30
31#include "codec.h"
32#include "msi.h"
33#include "group.h"
34
35#include "../toxcore/logger.h"
36#include "../toxcore/util.h"
37
38#include <assert.h>
39#include <stdlib.h>
40#include <string.h>
41
42/* Assume 24 fps*/
43#define MAX_ENCODE_TIME_US ((1000 / 24) * 1000)
44
45/* true if invalid call index */
46#define CALL_INVALID_INDEX(idx, max) (idx < 0 || idx >= max)
47
48const ToxAvCSettings av_DefaultSettings = {
49 av_TypeAudio,
50
51 500,
52 1280,
53 720,
54
55 32000,
56 20,
57 48000,
58 1
59};
60
61static const uint32_t jbuf_capacity = 6;
62static const uint8_t audio_index = 0, video_index = 1;
63
64typedef struct _ToxAvCall {
65 pthread_mutex_t mutex_control[1];
66 pthread_mutex_t mutex_encoding_audio[1];
67 pthread_mutex_t mutex_encoding_video[1];
68 pthread_mutex_t mutex_do[1];
69 RTPSession *crtps[2]; /** Audio is first and video is second */
70 CSSession *cs;
71 _Bool active;
72} ToxAvCall;
73
74struct _ToxAv {
75 Messenger *messenger;
76 MSISession *msi_session; /** Main msi session */
77 ToxAvCall *calls; /** Per-call params */
78 uint32_t max_calls;
79
80 PAIR(ToxAvAudioCallback, void *) acb;
81 PAIR(ToxAvVideoCallback, void *) vcb;
82
83 /* Decode time measure */
84 int32_t dectmsscount; /** Measure count */
85 int32_t dectmsstotal; /** Last cycle total */
86 int32_t avgdectms; /** Average decoding time in ms */
87};
88
89static const MSICSettings *msicsettings_cast (const ToxAvCSettings *from)
90{
91 assert(sizeof(MSICSettings) == sizeof(ToxAvCSettings));
92 return (const MSICSettings *) from;
93}
94
95static const ToxAvCSettings *toxavcsettings_cast (const MSICSettings *from)
96{
97 assert(sizeof(MSICSettings) == sizeof(ToxAvCSettings));
98 return (const ToxAvCSettings *) from;
99
100}
101
102ToxAv *toxav_new( Tox *messenger, int32_t max_calls)
103{
104 ToxAv *av = calloc ( sizeof(ToxAv), 1);
105
106 if (av == NULL) {
107 LOGGER_WARNING("Allocation failed!");
108 return NULL;
109 }
110
111 av->messenger = (Messenger *)messenger;
112 av->msi_session = msi_new(av->messenger, max_calls);
113 av->msi_session->agent_handler = av;
114 av->calls = calloc(sizeof(ToxAvCall), max_calls);
115 av->max_calls = max_calls;
116
117 unsigned int i;
118
119 for (i = 0; i < max_calls; ++i) {
120 if (create_recursive_mutex(av->calls[i].mutex_control) != 0 ) {
121 LOGGER_WARNING("Failed to init call(%u) mutex!", i);
122 msi_kill(av->msi_session);
123
124 free(av->calls);
125 free(av);
126 return NULL;
127 }
128 }
129
130 return av;
131}
132
133void toxav_kill ( ToxAv *av )
134{
135 uint32_t i;
136
137 for (i = 0; i < av->max_calls; i ++) {
138 if ( av->calls[i].crtps[audio_index] )
139 rtp_kill(av->calls[i].crtps[audio_index], av->msi_session->messenger_handle);
140
141
142 if ( av->calls[i].crtps[video_index] )
143 rtp_kill(av->calls[i].crtps[video_index], av->msi_session->messenger_handle);
144
145 if ( av->calls[i].cs )
146 cs_kill(av->calls[i].cs);
147
148 pthread_mutex_destroy(av->calls[i].mutex_control);
149 }
150
151 msi_kill(av->msi_session);
152
153 free(av->calls);
154 free(av);
155}
156
157uint32_t toxav_do_interval(ToxAv *av)
158{
159 int i = 0;
160 uint32_t rc = 200 + av->avgdectms; /* Return 200 if no call is active */
161
162 for (; i < av->max_calls; i ++) {
163 pthread_mutex_lock(av->calls[i].mutex_control);
164
165 if (av->calls[i].active) {
166 /* This should work. Video payload will always come in greater intervals */
167 rc = MIN(av->calls[i].cs->audio_decoder_frame_duration, rc);
168 }
169
170 pthread_mutex_unlock(av->calls[i].mutex_control);
171 }
172
173 return rc < av->avgdectms ? 0 : rc - av->avgdectms;
174}
175
176void toxav_do(ToxAv *av)
177{
178 msi_do(av->msi_session);
179
180 uint64_t start = current_time_monotonic();
181
182 uint32_t i = 0;
183
184 for (; i < av->max_calls; i ++) {
185 pthread_mutex_lock(av->calls[i].mutex_control);
186
187 if (av->calls[i].active) {
188 pthread_mutex_lock(av->calls[i].mutex_do);
189 pthread_mutex_unlock(av->calls[i].mutex_control);
190 cs_do(av->calls[i].cs);
191 pthread_mutex_unlock(av->calls[i].mutex_do);
192 } else {
193 pthread_mutex_unlock(av->calls[i].mutex_control);
194 }
195 }
196
197 uint64_t end = current_time_monotonic();
198
199 /* TODO maybe use variable for sizes */
200 av->dectmsstotal += end - start;
201
202 if (++av->dectmsscount == 3) {
203 av->avgdectms = av->dectmsstotal / 3 + 2 /* NOTE Magic Offset */;
204 av->dectmsscount = 0;
205 av->dectmsstotal = 0;
206 }
207}
208
209void toxav_register_callstate_callback ( ToxAv *av, ToxAVCallback cb, ToxAvCallbackID id, void *userdata )
210{
211 msi_register_callback(av->msi_session, (MSICallbackType)cb, (MSICallbackID) id, userdata);
212}
213
214void toxav_register_audio_callback(ToxAv *av, ToxAvAudioCallback cb, void *userdata)
215{
216 av->acb.first = cb;
217 av->acb.second = userdata;
218}
219
220void toxav_register_video_callback(ToxAv *av, ToxAvVideoCallback cb, void *userdata)
221{
222 av->vcb.first = cb;
223 av->vcb.second = userdata;
224}
225
226int toxav_call (ToxAv *av,
227 int32_t *call_index,
228 int user,
229 const ToxAvCSettings *csettings,
230 int ringing_seconds )
231{
232 return msi_invite(av->msi_session, call_index, msicsettings_cast(csettings), ringing_seconds * 1000, user);
233}
234
235int toxav_hangup ( ToxAv *av, int32_t call_index )
236{
237 return msi_hangup(av->msi_session, call_index);
238}
239
240int toxav_answer ( ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings )
241{
242 return msi_answer(av->msi_session, call_index, msicsettings_cast(csettings));
243}
244
245int toxav_reject ( ToxAv *av, int32_t call_index, const char *reason )
246{
247 return msi_reject(av->msi_session, call_index, reason);
248}
249
250int toxav_cancel ( ToxAv *av, int32_t call_index, int peer_id, const char *reason )
251{
252 return msi_cancel(av->msi_session, call_index, peer_id, reason);
253}
254
255int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings)
256{
257 return msi_change_csettings(av->msi_session, call_index, msicsettings_cast(csettings));
258}
259
260int toxav_stop_call ( ToxAv *av, int32_t call_index )
261{
262 return msi_stopcall(av->msi_session, call_index);
263}
264
265int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, int support_video )
266{
267 if ( !av->msi_session || CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) ||
268 !av->msi_session->calls[call_index] || !av->msi_session->calls[call_index]->csettings_peer) {
269 LOGGER_ERROR("Error while starting RTP session: invalid call!\n");
270 return av_ErrorNoCall;
271 }
272
273 ToxAvCall *call = &av->calls[call_index];
274
275 pthread_mutex_lock(call->mutex_control);
276
277 if (call->active) {
278 pthread_mutex_unlock(call->mutex_control);
279 LOGGER_ERROR("Error while starting RTP session: call already active!\n");
280 return av_ErrorAlreadyInCallWithPeer;
281 }
282
283 if (pthread_mutex_init(call->mutex_encoding_audio, NULL) != 0
284 || pthread_mutex_init(call->mutex_encoding_video, NULL) != 0 || pthread_mutex_init(call->mutex_do, NULL) != 0) {
285 pthread_mutex_unlock(call->mutex_control);
286 LOGGER_ERROR("Error while starting RTP session: mutex initializing failed!\n");
287 return av_ErrorUnknown;
288 }
289
290 const ToxAvCSettings *c_peer = toxavcsettings_cast
291 (&av->msi_session->calls[call_index]->csettings_peer[0]);
292 const ToxAvCSettings *c_self = toxavcsettings_cast
293 (&av->msi_session->calls[call_index]->csettings_local);
294
295 LOGGER_DEBUG(
296 "Type: %u(s) %u(p)\n"
297 "Video bitrate: %u(s) %u(p)\n"
298 "Video height: %u(s) %u(p)\n"
299 "Video width: %u(s) %u(p)\n"
300 "Audio bitrate: %u(s) %u(p)\n"
301 "Audio framedur: %u(s) %u(p)\n"
302 "Audio sample rate: %u(s) %u(p)\n"
303 "Audio channels: %u(s) %u(p)\n",
304 c_self->call_type, c_peer->call_type,
305 c_self->video_bitrate, c_peer->video_bitrate,
306 c_self->max_video_height, c_peer->max_video_height,
307 c_self->max_video_width, c_peer->max_video_width,
308 c_self->audio_bitrate, c_peer->audio_bitrate,
309 c_self->audio_frame_duration, c_peer->audio_frame_duration,
310 c_self->audio_sample_rate, c_peer->audio_sample_rate,
311 c_self->audio_channels, c_peer->audio_channels );
312
313 if ( !(call->cs = cs_new(c_self, c_peer, jbuf_capacity, support_video)) ) {
314 LOGGER_ERROR("Error while starting Codec State!\n");
315 pthread_mutex_unlock(call->mutex_control);
316 return av_ErrorInitializingCodecs;
317 }
318
319 call->cs->agent = av;
320
321 call->cs->acb.first = av->acb.first;
322 call->cs->acb.second = av->acb.second;
323
324 call->cs->vcb.first = av->vcb.first;
325 call->cs->vcb.second = av->vcb.second;
326
327
328 call->crtps[audio_index] =
329 rtp_new(msi_TypeAudio, av->messenger, av->msi_session->calls[call_index]->peers[0]);
330
331 if ( !call->crtps[audio_index] ) {
332 LOGGER_ERROR("Error while starting audio RTP session!\n");
333 goto error;
334 }
335
336 call->crtps[audio_index]->cs = call->cs;
337
338 if ( support_video ) {
339 call->crtps[video_index] =
340 rtp_new(msi_TypeVideo, av->messenger, av->msi_session->calls[call_index]->peers[0]);
341
342 if ( !call->crtps[video_index] ) {
343 LOGGER_ERROR("Error while starting video RTP session!\n");
344 goto error;
345 }
346
347 call->crtps[video_index]->cs = call->cs;
348 }
349
350 call->active = 1;
351 pthread_mutex_unlock(call->mutex_control);
352 return av_ErrorNone;
353error:
354 rtp_kill(call->crtps[audio_index], av->messenger);
355 call->crtps[audio_index] = NULL;
356 rtp_kill(call->crtps[video_index], av->messenger);
357 call->crtps[video_index] = NULL;
358 cs_kill(call->cs);
359 call->cs = NULL;
360 call->active = 0;
361 pthread_mutex_destroy(call->mutex_encoding_audio);
362 pthread_mutex_destroy(call->mutex_encoding_video);
363 pthread_mutex_destroy(call->mutex_do);
364
365 pthread_mutex_unlock(call->mutex_control);
366 return av_ErrorCreatingRtpSessions;
367}
368
369int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
370{
371 if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls)) {
372 LOGGER_WARNING("Invalid call index: %d", call_index);
373 return av_ErrorNoCall;
374 }
375
376 ToxAvCall *call = &av->calls[call_index];
377
378 pthread_mutex_lock(call->mutex_control);
379
380 if (!call->active) {
381 pthread_mutex_unlock(call->mutex_control);
382 LOGGER_WARNING("Action on inactive call: %d", call_index);
383 return av_ErrorInvalidState;
384 }
385
386 call->active = 0;
387
388 pthread_mutex_lock(call->mutex_encoding_audio);
389 pthread_mutex_unlock(call->mutex_encoding_audio);
390 pthread_mutex_lock(call->mutex_encoding_video);
391 pthread_mutex_unlock(call->mutex_encoding_video);
392 pthread_mutex_lock(call->mutex_do);
393 pthread_mutex_unlock(call->mutex_do);
394
395 rtp_kill(call->crtps[audio_index], av->messenger);
396 call->crtps[audio_index] = NULL;
397 rtp_kill(call->crtps[video_index], av->messenger);
398 call->crtps[video_index] = NULL;
399 cs_kill(call->cs);
400 call->cs = NULL;
401
402 pthread_mutex_destroy(call->mutex_encoding_audio);
403 pthread_mutex_destroy(call->mutex_encoding_video);
404 pthread_mutex_destroy(call->mutex_do);
405
406 pthread_mutex_unlock(call->mutex_control);
407
408 return av_ErrorNone;
409}
410
411static int toxav_send_rtp_payload(ToxAv *av,
412 ToxAvCall *call,
413 ToxAvCallType type,
414 const uint8_t *payload,
415 unsigned int length)
416{
417 if (call->crtps[type - av_TypeAudio]) {
418
419 /* Audio */
420 if (type == av_TypeAudio)
421 return rtp_send_msg(call->crtps[audio_index], av->messenger, payload, length);
422
423 /* Video */
424 int parts = cs_split_video_payload(call->cs, payload, length);
425
426 if (parts < 0) return parts;
427
428 uint16_t part_size;
429 const uint8_t *iter;
430
431 int i;
432
433 for (i = 0; i < parts; i++) {
434 iter = cs_iterate_split_video_frame(call->cs, &part_size);
435
436 if (rtp_send_msg(call->crtps[video_index], av->messenger, iter, part_size) < 0)
437 return av_ErrorSendingPayload;
438 }
439
440 return av_ErrorNone;
441
442 } else return av_ErrorNoRtpSession;
443}
444
445int toxav_prepare_video_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input)
446{
447 if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls)) {
448 LOGGER_WARNING("Invalid call index: %d", call_index);
449 return av_ErrorNoCall;
450 }
451
452
453 ToxAvCall *call = &av->calls[call_index];
454 pthread_mutex_lock(call->mutex_control);
455
456 if (!call->active) {
457 pthread_mutex_unlock(call->mutex_control);
458 LOGGER_WARNING("Action on inactive call: %d", call_index);
459 return av_ErrorInvalidState;
460 }
461
462 if (cs_set_sending_video_resolution(call->cs, input->d_w, input->d_h) < 0) {
463 pthread_mutex_unlock(call->mutex_control);
464 return av_ErrorSettingVideoResolution;
465 }
466
467 pthread_mutex_lock(call->mutex_encoding_video);
468 pthread_mutex_unlock(call->mutex_control);
469
470 int rc = vpx_codec_encode(call->cs->v_encoder, input, call->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US);
471
472 if ( rc != VPX_CODEC_OK) {
473 LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));
474 pthread_mutex_unlock(call->mutex_encoding_video);
475 return av_ErrorEncodingVideo;
476 }
477
478 ++call->cs->frame_counter;
479
480 vpx_codec_iter_t iter = NULL;
481 const vpx_codec_cx_pkt_t *pkt;
482 int copied = 0;
483
484 while ( (pkt = vpx_codec_get_cx_data(call->cs->v_encoder, &iter)) ) {
485 if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
486 if ( copied + pkt->data.frame.sz > dest_max ) {
487 pthread_mutex_unlock(call->mutex_encoding_video);
488 return av_ErrorPacketTooLarge;
489 }
490
491 memcpy(dest + copied, pkt->data.frame.buf, pkt->data.frame.sz);
492 copied += pkt->data.frame.sz;
493 }
494 }
495
496 pthread_mutex_unlock(call->mutex_encoding_video);
497 return copied;
498}
499
500int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, unsigned int frame_size)
501{
502
503 if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls)) {
504 LOGGER_WARNING("Invalid call index: %d", call_index);
505 return av_ErrorNoCall;
506 }
507
508 ToxAvCall *call = &av->calls[call_index];
509 pthread_mutex_lock(call->mutex_control);
510
511
512 if (!call->active) {
513 pthread_mutex_unlock(call->mutex_control);
514 LOGGER_WARNING("Action on inactive call: %d", call_index);
515 return av_ErrorInvalidState;
516 }
517
518 int rc = toxav_send_rtp_payload(av, call, av_TypeVideo, frame, frame_size);
519 pthread_mutex_unlock(call->mutex_control);
520
521 return rc;
522}
523
524int toxav_prepare_audio_frame ( ToxAv *av,
525 int32_t call_index,
526 uint8_t *dest,
527 int dest_max,
528 const int16_t *frame,
529 int frame_size)
530{
531 if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls)) {
532 LOGGER_WARNING("Action on nonexisting call: %d", call_index);
533 return av_ErrorNoCall;
534 }
535
536 ToxAvCall *call = &av->calls[call_index];
537 pthread_mutex_lock(call->mutex_control);
538
539 if (!call->active) {
540 pthread_mutex_unlock(call->mutex_control);
541 LOGGER_WARNING("Action on inactive call: %d", call_index);
542 return av_ErrorInvalidState;
543 }
544
545 pthread_mutex_lock(call->mutex_encoding_audio);
546 pthread_mutex_unlock(call->mutex_control);
547 int32_t rc = opus_encode(call->cs->audio_encoder, frame, frame_size, dest, dest_max);
548 pthread_mutex_unlock(call->mutex_encoding_audio);
549
550 if (rc < 0) {
551 LOGGER_ERROR("Failed to encode payload: %s\n", opus_strerror(rc));
552 return av_ErrorEncodingAudio;
553 }
554
555 return rc;
556}
557
558int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *data, unsigned int size)
559{
560 if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls)) {
561 LOGGER_WARNING("Action on nonexisting call: %d", call_index);
562 return av_ErrorNoCall;
563 }
564
565 ToxAvCall *call = &av->calls[call_index];
566 pthread_mutex_lock(call->mutex_control);
567
568
569 if (!call->active) {
570 pthread_mutex_unlock(call->mutex_control);
571 LOGGER_WARNING("Action on inactive call: %d", call_index);
572 return av_ErrorInvalidState;
573 }
574
575 int rc = toxav_send_rtp_payload(av, call, av_TypeAudio, data, size);
576 pthread_mutex_unlock(call->mutex_control);
577 return rc;
578}
579
580int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings *dest )
581{
582 if ( peer < 0 || CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) ||
583 !av->msi_session->calls[call_index] || av->msi_session->calls[call_index]->peer_count <= peer )
584 return av_ErrorNoCall;
585
586 *dest = *toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_peer[peer]);
587 return av_ErrorNone;
588}
589
590int toxav_get_peer_id ( ToxAv *av, int32_t call_index, int peer )
591{
592 if ( peer < 0 || CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) || !av->msi_session->calls[call_index]
593 || av->msi_session->calls[call_index]->peer_count <= peer )
594 return av_ErrorNoCall;
595
596 return av->msi_session->calls[call_index]->peers[peer];
597}
598
599ToxAvCallState toxav_get_call_state(ToxAv *av, int32_t call_index)
600{
601 if ( CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) || !av->msi_session->calls[call_index] )
602 return av_CallNonExistent;
603
604 return av->msi_session->calls[call_index]->state;
605
606}
607
608int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCapabilities capability )
609{
610}
611
612Tox *toxav_get_tox(ToxAv *av)
613{
614 return (Tox *)av->messenger;
615}
616
617int toxav_get_active_count(ToxAv *av)
618{
619 if (!av) return -1;
620
621 int rc = 0, i = 0;
622
623 for (; i < av->max_calls; i++) {
624 pthread_mutex_lock(av->calls[i].mutex_control);
625
626 if (av->calls[i].active) rc++;
627
628 pthread_mutex_unlock(av->calls[i].mutex_control);
629 }
630
631 return rc;
632}
633
634/* Create a new toxav group.
635 *
636 * return group number on success.
637 * return -1 on failure.
638 *
639 * Audio data callback format:
640 * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
641 *
642 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
643 */
644int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int,
645 uint8_t, unsigned int, void *), void *userdata)
646{
647 Messenger *m = tox;
648 return add_av_groupchat(m->group_chat_object, audio_callback, userdata);
649}
650
651/* Join a AV group (you need to have been invited first.)
652 *
653 * returns group number on success
654 * returns -1 on failure.
655 *
656 * Audio data callback format (same as the one for toxav_add_av_groupchat()):
657 * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
658 *
659 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
660 */
661int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length,
662 void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *),
663 void *userdata)
664{
665 Messenger *m = tox;
666 return join_av_groupchat(m->group_chat_object, friendnumber, data, length, audio_callback, userdata);
667}
668
669/* Send audio to the group chat.
670 *
671 * return 0 on success.
672 * return -1 on failure.
673 *
674 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
675 *
676 * Valid number of samples are ((sample rate) * (audio length (Valid ones are: 2.5, 5, 10, 20, 40 or 60 ms)) / 1000)
677 * Valid number of channels are 1 or 2.
678 * Valid sample rates are 8000, 12000, 16000, 24000, or 48000.
679 *
680 * Recommended values are: samples = 960, channels = 1, sample_rate = 48000
681 */
682int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
683 unsigned int sample_rate)
684{
685 Messenger *m = tox;
686 return group_send_audio(m->group_chat_object, groupnumber, pcm, samples, channels, sample_rate);
687}
688
diff --git a/toxav/toxav_new_1.h b/toxav/toxav_new_1.h
deleted file mode 100644
index 3696f961..00000000
--- a/toxav/toxav_new_1.h
+++ /dev/null
@@ -1,329 +0,0 @@
1/** toxav.h
2 *
3 * Copyright (C) 2013 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22
23#ifndef __TOXAV
24#define __TOXAV
25#include <inttypes.h>
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31typedef struct _ToxAv ToxAv;
32
33/* vpx_image_t */
34#include <vpx/vpx_image.h>
35
36typedef void ( *ToxAVCallback ) ( void *agent, int32_t call_idx, void *arg );
37typedef void ( *ToxAvAudioCallback ) (void *agent, int32_t call_idx, const int16_t *PCM, uint16_t size, void *data);
38typedef void ( *ToxAvVideoCallback ) (void *agent, int32_t call_idx, const vpx_image_t *img, void *data);
39
40#ifndef __TOX_DEFINED__
41#define __TOX_DEFINED__
42typedef struct Tox Tox;
43#endif
44
45#define RTP_PAYLOAD_SIZE 65535
46
47
48/**
49 * Callbacks ids that handle the call states.
50 */
51typedef enum {
52 av_OnInvite, /* Incoming call */
53 av_OnRinging, /* When peer is ready to accept/reject the call */
54 av_OnStart, /* Call (RTP transmission) started */
55 av_OnCancel, /* The side that initiated call canceled invite */
56 av_OnReject, /* The side that was invited rejected the call */
57 av_OnEnd, /* Call that was active ended */
58 av_OnRequestTimeout, /* When the requested action didn't get response in specified time */
59 av_OnPeerTimeout, /* Peer timed out; stop the call */
60 av_OnPeerCSChange, /* Peer changing Csettings. Prepare for changed AV */
61 av_OnSelfCSChange /* Csettings change confirmation. Once triggered peer is ready to recv changed AV */
62} ToxAvCallbackID;
63
64
65/**
66 * Call type identifier.
67 */
68typedef enum {
69 av_TypeAudio = 192,
70 av_TypeVideo
71} ToxAvCallType;
72
73
74typedef enum {
75 av_CallNonExistent = -1,
76 av_CallInviting, /* when sending call invite */
77 av_CallStarting, /* when getting call invite */
78 av_CallActive,
79 av_CallHold,
80 av_CallHungUp
81} ToxAvCallState;
82
83/**
84 * Error indicators. Values under -20 are reserved for toxcore.
85 */
86typedef enum {
87 av_ErrorNone = 0,
88 av_ErrorUnknown = -1, /* Unknown error */
89 av_ErrorNoCall = -20, /* Trying to perform call action while not in a call */
90 av_ErrorInvalidState = -21, /* Trying to perform call action while in invalid state*/
91 av_ErrorAlreadyInCallWithPeer = -22, /* Trying to call peer when already in a call with peer */
92 av_ErrorReachedCallLimit = -23, /* Cannot handle more calls */
93 av_ErrorInitializingCodecs = -30, /* Failed creating CSSession */
94 av_ErrorSettingVideoResolution = -31, /* Error setting resolution */
95 av_ErrorSettingVideoBitrate = -32, /* Error setting bitrate */
96 av_ErrorSplittingVideoPayload = -33, /* Error splitting video payload */
97 av_ErrorEncodingVideo = -34, /* vpx_codec_encode failed */
98 av_ErrorEncodingAudio = -35, /* opus_encode failed */
99 av_ErrorSendingPayload = -40, /* Sending lossy packet failed */
100 av_ErrorCreatingRtpSessions = -41, /* One of the rtp sessions failed to initialize */
101 av_ErrorNoRtpSession = -50, /* Trying to perform rtp action on invalid session */
102 av_ErrorInvalidCodecState = -51, /* Codec state not initialized */
103 av_ErrorPacketTooLarge = -52, /* Split packet exceeds it's limit */
104} ToxAvError;
105
106
107/**
108 * Locally supported capabilities.
109 */
110typedef enum {
111 av_AudioEncoding = 1 << 0,
112 av_AudioDecoding = 1 << 1,
113 av_VideoEncoding = 1 << 2,
114 av_VideoDecoding = 1 << 3
115} ToxAvCapabilities;
116
117
118/**
119 * Encoding settings.
120 */
121typedef struct _ToxAvCSettings {
122 ToxAvCallType call_type;
123
124 uint32_t video_bitrate; /* In kbits/s */
125 uint16_t max_video_width; /* In px */
126 uint16_t max_video_height; /* In px */
127
128 uint32_t audio_bitrate; /* In bits/s */
129 uint16_t audio_frame_duration; /* In ms */
130 uint32_t audio_sample_rate; /* In Hz */
131 uint32_t audio_channels;
132} ToxAvCSettings;
133
134extern const ToxAvCSettings av_DefaultSettings;
135
136/**
137 * Start new A/V session. There can only be one session at the time.
138 */
139ToxAv *toxav_new(Tox *messenger, int32_t max_calls);
140
141/**
142 * Remove A/V session.
143 */
144void toxav_kill(ToxAv *av);
145
146/**
147 * Returns the interval in milliseconds when the next toxav_do() should be called.
148 * If no call is active at the moment returns 200.
149 */
150uint32_t toxav_do_interval(ToxAv *av);
151
152/**
153 * Main loop for the session. Best called right after tox_do();
154 */
155void toxav_do(ToxAv *av);
156
157/**
158 * Register callback for call state.
159 */
160void toxav_register_callstate_callback (ToxAv *av, ToxAVCallback cb, ToxAvCallbackID id, void *userdata);
161
162/**
163 * Register callback for audio data.
164 */
165void toxav_register_audio_callback (ToxAv *av, ToxAvAudioCallback cb, void *userdata);
166
167/**
168 * Register callback for video data.
169 */
170void toxav_register_video_callback (ToxAv *av, ToxAvVideoCallback cb, void *userdata);
171
172/**
173 * Call user. Use its friend_id.
174 */
175int toxav_call(ToxAv *av,
176 int32_t *call_index,
177 int friend_id,
178 const ToxAvCSettings *csettings,
179 int ringing_seconds);
180
181/**
182 * Hangup active call.
183 */
184int toxav_hangup(ToxAv *av, int32_t call_index);
185
186/**
187 * Answer incoming call. Pass the csettings that you will use.
188 */
189int toxav_answer(ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings );
190
191/**
192 * Reject incoming call.
193 */
194int toxav_reject(ToxAv *av, int32_t call_index, const char *reason);
195
196/**
197 * Cancel outgoing request.
198 */
199int toxav_cancel(ToxAv *av, int32_t call_index, int peer_id, const char *reason);
200
201/**
202 * Notify peer that we are changing codec settings.
203 */
204int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings);
205
206/**
207 * Terminate transmission. Note that transmission will be
208 * terminated without informing remote peer. Usually called when we can't inform peer.
209 */
210int toxav_stop_call(ToxAv *av, int32_t call_index);
211
212/**
213 * Allocates transmission data. Must be call before calling toxav_prepare_* and toxav_send_*.
214 * Also, it must be called when call is started
215 */
216int toxav_prepare_transmission(ToxAv *av, int32_t call_index, int support_video);
217
218/**
219 * Clears transmission data. Call this at the end of the transmission.
220 */
221int toxav_kill_transmission(ToxAv *av, int32_t call_index);
222
223/**
224 * Encode video frame.
225 */
226int toxav_prepare_video_frame ( ToxAv *av,
227 int32_t call_index,
228 uint8_t *dest,
229 int dest_max,
230 vpx_image_t *input);
231
232/**
233 * Send encoded video packet.
234 */
235int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, uint32_t frame_size);
236
237/**
238 * Encode audio frame.
239 */
240int toxav_prepare_audio_frame ( ToxAv *av,
241 int32_t call_index,
242 uint8_t *dest,
243 int dest_max,
244 const int16_t *frame,
245 int frame_size);
246
247/**
248 * Send encoded audio frame.
249 */
250int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *frame, unsigned int size);
251
252/**
253 * Get codec settings from the peer. These were exchanged during call initialization
254 * or when peer send us new csettings.
255 */
256int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings *dest );
257
258/**
259 * Get friend id of peer participating in conversation.
260 */
261int toxav_get_peer_id ( ToxAv *av, int32_t call_index, int peer );
262
263/**
264 * Get current call state.
265 */
266ToxAvCallState toxav_get_call_state ( ToxAv *av, int32_t call_index );
267
268/**
269 * Is certain capability supported. Used to determine if encoding/decoding is ready.
270 */
271int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCapabilities capability );
272
273/**
274 * Returns tox reference.
275 */
276Tox *toxav_get_tox (ToxAv *av);
277
278/**
279 * Returns number of active calls or -1 on error.
280 */
281int toxav_get_active_count (ToxAv *av);
282
283/* Create a new toxav group.
284 *
285 * return group number on success.
286 * return -1 on failure.
287 *
288 * Audio data callback format:
289 * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
290 *
291 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
292 */
293int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Tox *, int, int, const int16_t *, unsigned int, uint8_t,
294 unsigned int, void *), void *userdata);
295
296/* Join a AV group (you need to have been invited first.)
297 *
298 * returns group number on success
299 * returns -1 on failure.
300 *
301 * Audio data callback format (same as the one for toxav_add_av_groupchat()):
302 * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
303 *
304 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
305 */
306int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length,
307 void (*audio_callback)(Tox *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata);
308
309/* Send audio to the group chat.
310 *
311 * return 0 on success.
312 * return -1 on failure.
313 *
314 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
315 *
316 * Valid number of samples are ((sample rate) * (audio length (Valid ones are: 2.5, 5, 10, 20, 40 or 60 ms)) / 1000)
317 * Valid number of channels are 1 or 2.
318 * Valid sample rates are 8000, 12000, 16000, 24000, or 48000.
319 *
320 * Recommended values are: samples = 960, channels = 1, sample_rate = 48000
321 */
322int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
323 unsigned int sample_rate);
324
325#ifdef __cplusplus
326}
327#endif
328
329#endif /* __TOXAV */
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 919655a2..2d3d6ffe 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -207,7 +207,7 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_
207 } 207 }
208 208
209 if (ipv6 == 0) { 209 if (ipv6 == 0) {
210 uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; 210 uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES;
211 211
212 if (packed_length + size > length) 212 if (packed_length + size > length)
213 return -1; 213 return -1;
@@ -215,10 +215,10 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_
215 data[packed_length] = net_family; 215 data[packed_length] = net_family;
216 memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, sizeof(IP4)); 216 memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, sizeof(IP4));
217 memcpy(data + packed_length + 1 + sizeof(IP4), &nodes[i].ip_port.port, sizeof(uint16_t)); 217 memcpy(data + packed_length + 1 + sizeof(IP4), &nodes[i].ip_port.port, sizeof(uint16_t));
218 memcpy(data + packed_length + 1 + sizeof(IP4) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); 218 memcpy(data + packed_length + 1 + sizeof(IP4) + sizeof(uint16_t), nodes[i].public_key, crypto_box_PUBLICKEYBYTES);
219 packed_length += size; 219 packed_length += size;
220 } else if (ipv6 == 1) { 220 } else if (ipv6 == 1) {
221 uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; 221 uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES;
222 222
223 if (packed_length + size > length) 223 if (packed_length + size > length)
224 return -1; 224 return -1;
@@ -226,7 +226,7 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_
226 data[packed_length] = net_family; 226 data[packed_length] = net_family;
227 memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, sizeof(IP6)); 227 memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, sizeof(IP6));
228 memcpy(data + packed_length + 1 + sizeof(IP6), &nodes[i].ip_port.port, sizeof(uint16_t)); 228 memcpy(data + packed_length + 1 + sizeof(IP6), &nodes[i].ip_port.port, sizeof(uint16_t));
229 memcpy(data + packed_length + 1 + sizeof(IP6) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); 229 memcpy(data + packed_length + 1 + sizeof(IP6) + sizeof(uint16_t), nodes[i].public_key, crypto_box_PUBLICKEYBYTES);
230 packed_length += size; 230 packed_length += size;
231 } else { 231 } else {
232 return -1; 232 return -1;
@@ -275,7 +275,7 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
275 } 275 }
276 276
277 if (ipv6 == 0) { 277 if (ipv6 == 0) {
278 uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; 278 uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES;
279 279
280 if (len_processed + size > length) 280 if (len_processed + size > length)
281 return -1; 281 return -1;
@@ -283,11 +283,11 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
283 nodes[num].ip_port.ip.family = host_family; 283 nodes[num].ip_port.ip.family = host_family;
284 memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, sizeof(IP4)); 284 memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, sizeof(IP4));
285 memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP4), sizeof(uint16_t)); 285 memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP4), sizeof(uint16_t));
286 memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP4) + sizeof(uint16_t), CLIENT_ID_SIZE); 286 memcpy(nodes[num].public_key, data + len_processed + 1 + sizeof(IP4) + sizeof(uint16_t), crypto_box_PUBLICKEYBYTES);
287 len_processed += size; 287 len_processed += size;
288 ++num; 288 ++num;
289 } else if (ipv6 == 1) { 289 } else if (ipv6 == 1) {
290 uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; 290 uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES;
291 291
292 if (len_processed + size > length) 292 if (len_processed + size > length)
293 return -1; 293 return -1;
@@ -295,7 +295,7 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
295 nodes[num].ip_port.ip.family = host_family; 295 nodes[num].ip_port.ip.family = host_family;
296 memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, sizeof(IP6)); 296 memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, sizeof(IP6));
297 memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP6), sizeof(uint16_t)); 297 memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP6), sizeof(uint16_t));
298 memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP6) + sizeof(uint16_t), CLIENT_ID_SIZE); 298 memcpy(nodes[num].public_key, data + len_processed + 1 + sizeof(IP6) + sizeof(uint16_t), crypto_box_PUBLICKEYBYTES);
299 len_processed += size; 299 len_processed += size;
300 ++num; 300 ++num;
301 } else { 301 } else {
@@ -397,12 +397,12 @@ static int client_or_ip_port_in_list(Client_data *list, uint16_t length, const u
397 * return 1 if true. 397 * return 1 if true.
398 * return 0 if false. 398 * return 0 if false.
399 */ 399 */
400static int client_in_nodelist(const Node_format *list, uint16_t length, const uint8_t *client_id) 400static int client_in_nodelist(const Node_format *list, uint16_t length, const uint8_t *public_key)
401{ 401{
402 uint32_t i; 402 uint32_t i;
403 403
404 for (i = 0; i < length; ++i) { 404 for (i = 0; i < length; ++i) {
405 if (id_equal(list[i].client_id, client_id)) 405 if (id_equal(list[i].public_key, public_key))
406 return 1; 406 return 1;
407 } 407 }
408 408
@@ -484,9 +484,9 @@ static void get_close_nodes_inner(const uint8_t *client_id, Node_format *nodes_l
484 continue; 484 continue;
485 485
486 if (num_nodes < MAX_SENT_NODES) { 486 if (num_nodes < MAX_SENT_NODES) {
487 memcpy(nodes_list[num_nodes].client_id, 487 memcpy(nodes_list[num_nodes].public_key,
488 client->client_id, 488 client->client_id,
489 CLIENT_ID_SIZE ); 489 crypto_box_PUBLICKEYBYTES );
490 490
491 nodes_list[num_nodes].ip_port = ipptp->ip_port; 491 nodes_list[num_nodes].ip_port = ipptp->ip_port;
492 num_nodes++; 492 num_nodes++;
@@ -497,14 +497,14 @@ static void get_close_nodes_inner(const uint8_t *client_id, Node_format *nodes_l
497 */ 497 */
498 for (j = 0; j < MAX_SENT_NODES; ++j) { 498 for (j = 0; j < MAX_SENT_NODES; ++j) {
499 closest = id_closest( client_id, 499 closest = id_closest( client_id,
500 nodes_list[j].client_id, 500 nodes_list[j].public_key,
501 client->client_id ); 501 client->client_id );
502 502
503 /* second client_id is closer than current: change to it */ 503 /* second client_id is closer than current: change to it */
504 if (closest == 2) { 504 if (closest == 2) {
505 memcpy( nodes_list[j].client_id, 505 memcpy( nodes_list[j].public_key,
506 client->client_id, 506 client->client_id,
507 CLIENT_ID_SIZE); 507 crypto_box_PUBLICKEYBYTES);
508 508
509 nodes_list[j].ip_port = ipptp->ip_port; 509 nodes_list[j].ip_port = ipptp->ip_port;
510 break; 510 break;
@@ -583,7 +583,7 @@ int get_close_nodes(const DHT *dht, const uint8_t *client_id, Node_format *nodes
583 Client_data *client = result[i]; 583 Client_data *client = result[i];
584 584
585 if (client) { 585 if (client) {
586 id_copy(nodes_list[num_returned].client_id, client->client_id); 586 id_copy(nodes_list[num_returned].public_key, client->client_id);
587 587
588 if (sa_family == AF_INET) 588 if (sa_family == AF_INET)
589 if (ipport_isset(&client->assoc4.ip_port)) { 589 if (ipport_isset(&client->assoc4.ip_port)) {
@@ -647,6 +647,21 @@ static int cmp_dht_entry(const void *a, const void *b)
647 return 0; 647 return 0;
648} 648}
649 649
650/* Is it ok to store node with client_id in client.
651 *
652 * return 0 if node can't be stored.
653 * return 1 if it can.
654 */
655static unsigned int store_node_ok(const Client_data *client, const uint8_t *client_id, const uint8_t *comp_client_id)
656{
657 if ((is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT))
658 || (id_closest(comp_client_id, client->client_id, client_id) == 2)) {
659 return 1;
660 } else {
661 return 0;
662 }
663}
664
650/* Replace a first bad (or empty) node with this one 665/* Replace a first bad (or empty) node with this one
651 * or replace a possibly bad node (tests failed or not done yet) 666 * or replace a possibly bad node (tests failed or not done yet)
652 * that is further than any other in the list 667 * that is further than any other in the list
@@ -674,8 +689,7 @@ static int replace_all( Client_data *list,
674 689
675 Client_data *client = &list[0]; 690 Client_data *client = &list[0];
676 691
677 if ((is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) 692 if (store_node_ok(client, client_id, comp_client_id)) {
678 || (id_closest(comp_client_id, client->client_id, client_id) == 2)) {
679 IPPTsPng *ipptp_write = NULL; 693 IPPTsPng *ipptp_write = NULL;
680 IPPTsPng *ipptp_clear = NULL; 694 IPPTsPng *ipptp_clear = NULL;
681 695
@@ -704,6 +718,29 @@ static int replace_all( Client_data *list,
704 return 0; 718 return 0;
705} 719}
706 720
721/* Check if the node obtained with a get_nodes with client_id should be pinged.
722 * NOTE: for best results call it after addto_lists;
723 *
724 * return 0 if the node should not be pinged.
725 * return 1 if it should.
726 */
727static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *client_id)
728{
729 if (store_node_ok(&dht->close_clientlist[0], client_id, dht->self_public_key)) {
730 return 1;
731 }
732
733 unsigned int i;
734
735 for (i = 0; i < dht->num_friends; ++i) {
736 if (store_node_ok(&dht->friends_list[i].client_list[0], client_id, dht->self_public_key)) {
737 return 1;
738 }
739 }
740
741 return 0;
742}
743
707/* Attempt to add client with ip_port and client_id to the friends client list 744/* Attempt to add client with ip_port and client_id to the friends client list
708 * and close_clientlist. 745 * and close_clientlist.
709 * 746 *
@@ -860,7 +897,7 @@ static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const
860 uint8_t plain_message[sizeof(Node_format) * 2] = {0}; 897 uint8_t plain_message[sizeof(Node_format) * 2] = {0};
861 898
862 Node_format receiver; 899 Node_format receiver;
863 memcpy(receiver.client_id, public_key, CLIENT_ID_SIZE); 900 memcpy(receiver.public_key, public_key, CLIENT_ID_SIZE);
864 receiver.ip_port = ip_port; 901 receiver.ip_port = ip_port;
865 memcpy(plain_message, &receiver, sizeof(receiver)); 902 memcpy(plain_message, &receiver, sizeof(receiver));
866 903
@@ -1004,7 +1041,7 @@ static uint8_t sent_getnode_to_node(DHT *dht, const uint8_t *client_id, IP_Port
1004 Node_format test; 1041 Node_format test;
1005 memcpy(&test, data, sizeof(Node_format)); 1042 memcpy(&test, data, sizeof(Node_format));
1006 1043
1007 if (!ipport_equal(&test.ip_port, &node_ip_port) || memcmp(test.client_id, client_id, CLIENT_ID_SIZE) != 0) 1044 if (!ipport_equal(&test.ip_port, &node_ip_port) || memcmp(test.public_key, client_id, CLIENT_ID_SIZE) != 0)
1008 return 0; 1045 return 0;
1009 1046
1010 return 1; 1047 return 1;
@@ -1091,9 +1128,10 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *pa
1091 uint32_t i; 1128 uint32_t i;
1092 1129
1093 for (i = 0; i < num_nodes; i++) { 1130 for (i = 0; i < num_nodes; i++) {
1094 if (ipport_isset(&plain_nodes[i].ip_port)) { 1131 if (ipport_isset(&plain_nodes[i].ip_port) && (LAN_ip(plain_nodes[i].ip_port.ip) == 0
1095 send_ping_request(dht->ping, plain_nodes[i].ip_port, plain_nodes[i].client_id); 1132 || ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key))) {
1096 returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].client_id, packet + 1); 1133 send_ping_request(dht->ping, plain_nodes[i].ip_port, plain_nodes[i].public_key);
1134 returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1);
1097 } 1135 }
1098 } 1136 }
1099 1137
@@ -1847,7 +1885,7 @@ static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8
1847 uint8_t data[HARDREQ_DATA_SIZE] = {0}; 1885 uint8_t data[HARDREQ_DATA_SIZE] = {0};
1848 data[0] = type; 1886 data[0] = type;
1849 memcpy(data + 1, contents, length); 1887 memcpy(data + 1, contents, length);
1850 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, 1888 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data,
1851 sizeof(data), CRYPTO_PACKET_HARDENING); 1889 sizeof(data), CRYPTO_PACKET_HARDENING);
1852 1890
1853 if (len == -1) 1891 if (len == -1)
@@ -1877,7 +1915,7 @@ static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto,
1877 data[0] = CHECK_TYPE_GETNODE_RES; 1915 data[0] = CHECK_TYPE_GETNODE_RES;
1878 memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE); 1916 memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE);
1879 memcpy(data + 1 + CLIENT_ID_SIZE, nodes_data, nodes_data_length); 1917 memcpy(data + 1 + CLIENT_ID_SIZE, nodes_data, nodes_data_length);
1880 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, 1918 int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data,
1881 sizeof(data), CRYPTO_PACKET_HARDENING); 1919 sizeof(data), CRYPTO_PACKET_HARDENING);
1882 1920
1883 if (len == -1) 1921 if (len == -1)
@@ -1914,12 +1952,12 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
1914 uint32_t i; 1952 uint32_t i;
1915 1953
1916 for (i = 0; i < num; ++i) { 1954 for (i = 0; i < num; ++i) {
1917 if (id_equal(nodes[i].client_id, dht->self_public_key)) { 1955 if (id_equal(nodes[i].public_key, dht->self_public_key)) {
1918 ++counter; 1956 ++counter;
1919 continue; 1957 continue;
1920 } 1958 }
1921 1959
1922 IPPTsPng *temp = get_closelist_IPPTsPng(dht, nodes[i].client_id, nodes[i].ip_port.ip.family); 1960 IPPTsPng *temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family);
1923 1961
1924 if (temp) { 1962 if (temp) {
1925 if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) { 1963 if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) {
@@ -1952,10 +1990,10 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_
1952 1990
1953 Node_format node, tocheck_node; 1991 Node_format node, tocheck_node;
1954 node.ip_port = source; 1992 node.ip_port = source;
1955 memcpy(node.client_id, source_pubkey, CLIENT_ID_SIZE); 1993 memcpy(node.public_key, source_pubkey, crypto_box_PUBLICKEYBYTES);
1956 memcpy(&tocheck_node, packet + 1, sizeof(Node_format)); 1994 memcpy(&tocheck_node, packet + 1, sizeof(Node_format));
1957 1995
1958 if (getnodes(dht, tocheck_node.ip_port, tocheck_node.client_id, packet + 1 + sizeof(Node_format), &node) == -1) 1996 if (getnodes(dht, tocheck_node.ip_port, tocheck_node.public_key, packet + 1 + sizeof(Node_format), &node) == -1)
1959 return 1; 1997 return 1;
1960 1998
1961 return 0; 1999 return 0;
@@ -2052,7 +2090,7 @@ uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
2052 } 2090 }
2053 2091
2054 if (assoc != NULL) { 2092 if (assoc != NULL) {
2055 memcpy(nodes[count].client_id, list[i - 1].client_id, CLIENT_ID_SIZE); 2093 memcpy(nodes[count].public_key, list[i - 1].client_id, CLIENT_ID_SIZE);
2056 nodes[count].ip_port = assoc->ip_port; 2094 nodes[count].ip_port = assoc->ip_port;
2057 ++count; 2095 ++count;
2058 2096
@@ -2091,16 +2129,16 @@ void do_hardening(DHT *dht)
2091 if (!ipport_isset(&rand_node.ip_port)) 2129 if (!ipport_isset(&rand_node.ip_port))
2092 continue; 2130 continue;
2093 2131
2094 if (id_equal(client_id, rand_node.client_id)) 2132 if (id_equal(client_id, rand_node.public_key))
2095 continue; 2133 continue;
2096 2134
2097 Node_format to_test; 2135 Node_format to_test;
2098 to_test.ip_port = cur_iptspng->ip_port; 2136 to_test.ip_port = cur_iptspng->ip_port;
2099 memcpy(to_test.client_id, client_id, CLIENT_ID_SIZE); 2137 memcpy(to_test.public_key, client_id, crypto_box_PUBLICKEYBYTES);
2100 2138
2101 //TODO: The search id should maybe not be ours? 2139 //TODO: The search id should maybe not be ours?
2102 if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) { 2140 if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) {
2103 memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.client_id, CLIENT_ID_SIZE); 2141 memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, crypto_box_PUBLICKEYBYTES);
2104 cur_iptspng->hardening.send_nodes_timestamp = unix_time(); 2142 cur_iptspng->hardening.send_nodes_timestamp = unix_time();
2105 } 2143 }
2106 } 2144 }
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index 47a828d7..318a6002 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -148,7 +148,7 @@ typedef struct {
148} DHT_Friend; 148} DHT_Friend;
149 149
150typedef struct { 150typedef struct {
151 uint8_t client_id[CLIENT_ID_SIZE]; 151 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
152 IP_Port ip_port; 152 IP_Port ip_port;
153} 153}
154Node_format; 154Node_format;
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index f87f1348..bc020d87 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -152,6 +152,11 @@ static void fetch_broadcast_info(uint16_t port)
152 IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; 152 IP_Port *ip_port = &broadcast_ip_port[broadcast_count];
153 ip_port->ip.family = AF_INET; 153 ip_port->ip.family = AF_INET;
154 ip_port->ip.ip4.in_addr = sock4->sin_addr; 154 ip_port->ip.ip4.in_addr = sock4->sin_addr;
155
156 if (ip_port->ip.ip4.uint32 == 0) {
157 continue;
158 }
159
155 ip_port->port = port; 160 ip_port->port = port;
156 broadcast_count++; 161 broadcast_count++;
157 } 162 }
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index c310412d..4cf0edeb 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -89,32 +89,32 @@ int realloc_friendlist(Messenger *m, uint32_t num)
89/* return the friend id associated to that public key. 89/* return the friend id associated to that public key.
90 * return -1 if no such friend. 90 * return -1 if no such friend.
91 */ 91 */
92int32_t getfriend_id(const Messenger *m, const uint8_t *client_id) 92int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk)
93{ 93{
94 uint32_t i; 94 uint32_t i;
95 95
96 for (i = 0; i < m->numfriends; ++i) { 96 for (i = 0; i < m->numfriends; ++i) {
97 if (m->friendlist[i].status > 0) 97 if (m->friendlist[i].status > 0)
98 if (id_equal(client_id, m->friendlist[i].client_id)) 98 if (id_equal(real_pk, m->friendlist[i].real_pk))
99 return i; 99 return i;
100 } 100 }
101 101
102 return -1; 102 return -1;
103} 103}
104 104
105/* Copies the public key associated to that friend id into client_id buffer. 105/* Copies the public key associated to that friend id into real_pk buffer.
106 * Make sure that client_id is of size CLIENT_ID_SIZE. 106 * Make sure that real_pk is of size crypto_box_PUBLICKEYBYTES.
107 * 107 *
108 * return 0 if success. 108 * return 0 if success.
109 * return -1 if failure. 109 * return -1 if failure.
110 */ 110 */
111int getclient_id(const Messenger *m, int32_t friendnumber, uint8_t *client_id) 111int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk)
112{ 112{
113 if (friend_not_valid(m, friendnumber)) 113 if (friend_not_valid(m, friendnumber))
114 return -1; 114 return -1;
115 115
116 if (m->friendlist[friendnumber].status > 0) { 116 if (m->friendlist[friendnumber].status > 0) {
117 memcpy(client_id, m->friendlist[friendnumber].client_id, CLIENT_ID_SIZE); 117 memcpy(real_pk, m->friendlist[friendnumber].real_pk, crypto_box_PUBLICKEYBYTES);
118 return 0; 118 return 0;
119 } 119 }
120 120
@@ -149,7 +149,7 @@ static uint16_t address_checksum(const uint8_t *address, uint32_t len)
149 return check; 149 return check;
150} 150}
151 151
152/* Format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] 152/* Format: [real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
153 * 153 *
154 * return FRIEND_ADDRESS_SIZE byte address to give to others. 154 * return FRIEND_ADDRESS_SIZE byte address to give to others.
155 */ 155 */
@@ -183,6 +183,54 @@ static int handle_status(void *object, int i, uint8_t status);
183static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len); 183static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len);
184static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length); 184static int handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length);
185 185
186static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t status)
187{
188 /* Resize the friend list if necessary. */
189 if (realloc_friendlist(m, m->numfriends + 1) != 0)
190 return FAERR_NOMEM;
191
192 memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
193
194 int friendcon_id = new_friend_connection(m->fr_c, real_pk);
195
196 if (friendcon_id == -1)
197 return FAERR_UNKNOWN;
198
199 uint32_t i;
200
201 for (i = 0; i <= m->numfriends; ++i) {
202 if (m->friendlist[i].status == NOFRIEND) {
203 m->friendlist[i].status = status;
204 m->friendlist[i].friendcon_id = friendcon_id;
205 m->friendlist[i].friendrequest_lastsent = 0;
206 id_copy(m->friendlist[i].real_pk, real_pk);
207 m->friendlist[i].statusmessage = calloc(1, 1);
208 m->friendlist[i].statusmessage_length = 1;
209 m->friendlist[i].userstatus = USERSTATUS_NONE;
210 m->friendlist[i].avatar_info_sent = 0;
211 m->friendlist[i].avatar_recv_data = NULL;
212 m->friendlist[i].avatar_send_data.bytes_sent = 0;
213 m->friendlist[i].avatar_send_data.last_reset = 0;
214 m->friendlist[i].is_typing = 0;
215 m->friendlist[i].message_id = 0;
216 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
217 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
218 &handle_custom_lossy_packet, m, i);
219
220 if (m->numfriends == i)
221 ++m->numfriends;
222
223 if (friend_con_connected(m->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
224 send_online_packet(m, i);
225 }
226
227 return i;
228 }
229 }
230
231 return FAERR_UNKNOWN;
232}
233
186/* 234/*
187 * Add a friend. 235 * Add a friend.
188 * Set the data that will be sent along with friend request. 236 * Set the data that will be sent along with friend request.
@@ -205,10 +253,10 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
205 if (length > MAX_FRIEND_REQUEST_DATA_SIZE) 253 if (length > MAX_FRIEND_REQUEST_DATA_SIZE)
206 return FAERR_TOOLONG; 254 return FAERR_TOOLONG;
207 255
208 uint8_t client_id[crypto_box_PUBLICKEYBYTES]; 256 uint8_t real_pk[crypto_box_PUBLICKEYBYTES];
209 id_copy(client_id, address); 257 id_copy(real_pk, address);
210 258
211 if (!public_key_valid(client_id)) 259 if (!public_key_valid(real_pk))
212 return FAERR_BADCHECKSUM; 260 return FAERR_BADCHECKSUM;
213 261
214 uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 262 uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
@@ -220,10 +268,10 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
220 if (length < 1) 268 if (length < 1)
221 return FAERR_NOMESSAGE; 269 return FAERR_NOMESSAGE;
222 270
223 if (id_equal(client_id, m->net_crypto->self_public_key)) 271 if (id_equal(real_pk, m->net_crypto->self_public_key))
224 return FAERR_OWNKEY; 272 return FAERR_OWNKEY;
225 273
226 int32_t friend_id = getfriend_id(m, client_id); 274 int32_t friend_id = getfriend_id(m, real_pk);
227 275
228 if (friend_id != -1) { 276 if (friend_id != -1) {
229 if (m->friendlist[friend_id].status >= FRIEND_CONFIRMED) 277 if (m->friendlist[friend_id].status >= FRIEND_CONFIRMED)
@@ -239,111 +287,38 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
239 return FAERR_SETNEWNOSPAM; 287 return FAERR_SETNEWNOSPAM;
240 } 288 }
241 289
242 /* Resize the friend list if necessary. */ 290 int32_t ret = init_new_friend(m, real_pk, FRIEND_ADDED);
243 if (realloc_friendlist(m, m->numfriends + 1) != 0)
244 return FAERR_NOMEM;
245
246 memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
247
248 int friendcon_id = new_friend_connection(m->fr_c, client_id);
249 291
250 if (friendcon_id == -1) 292 if (ret < 0) {
251 return -1; 293 return ret;
252
253 uint32_t i;
254
255 for (i = 0; i <= m->numfriends; ++i) {
256 if (m->friendlist[i].status == NOFRIEND) {
257 m->friendlist[i].status = FRIEND_ADDED;
258 m->friendlist[i].friendcon_id = friendcon_id;
259 m->friendlist[i].friendrequest_lastsent = 0;
260 m->friendlist[i].friendrequest_timeout = FRIENDREQUEST_TIMEOUT;
261 id_copy(m->friendlist[i].client_id, client_id);
262 m->friendlist[i].statusmessage = calloc(1, 1);
263 m->friendlist[i].statusmessage_length = 1;
264 m->friendlist[i].userstatus = USERSTATUS_NONE;
265 m->friendlist[i].avatar_info_sent = 0;
266 m->friendlist[i].avatar_recv_data = NULL;
267 m->friendlist[i].avatar_send_data.bytes_sent = 0;
268 m->friendlist[i].avatar_send_data.last_reset = 0;
269 m->friendlist[i].is_typing = 0;
270 memcpy(m->friendlist[i].info, data, length);
271 m->friendlist[i].info_size = length;
272 m->friendlist[i].message_id = 0;
273 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
274 memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
275 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
276 &handle_custom_lossy_packet, m, i);
277
278 if (m->numfriends == i)
279 ++m->numfriends;
280
281 if (friend_con_connected(m->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
282 send_online_packet(m, i);
283 }
284
285 return i;
286 }
287 } 294 }
288 295
289 return FAERR_UNKNOWN; 296 m->friendlist[ret].friendrequest_timeout = FRIENDREQUEST_TIMEOUT;
297 memcpy(m->friendlist[ret].info, data, length);
298 m->friendlist[ret].info_size = length;
299 memcpy(&(m->friendlist[ret].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
300
301 return ret;
290} 302}
291 303
292int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id) 304int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk)
293{ 305{
294 if (getfriend_id(m, client_id) != -1) 306 if (getfriend_id(m, real_pk) != -1)
295 return -1; 307 return -1;
296 308
297 if (!public_key_valid(client_id)) 309 if (!public_key_valid(real_pk))
298 return -1; 310 return -1;
299 311
300 /* Resize the friend list if necessary. */ 312 if (id_equal(real_pk, m->net_crypto->self_public_key))
301 if (realloc_friendlist(m, m->numfriends + 1) != 0)
302 return -1; 313 return -1;
303 314
304 if (id_equal(client_id, m->net_crypto->self_public_key)) 315 int32_t ret = init_new_friend(m, real_pk, FRIEND_CONFIRMED);
305 return -1;
306
307 memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
308
309 int friendcon_id = new_friend_connection(m->fr_c, client_id);
310 316
311 if (friendcon_id == -1) 317 if (ret < 0) {
312 return -1; 318 return -1;
313 319 } else {
314 uint32_t i; 320 return ret;
315
316 for (i = 0; i <= m->numfriends; ++i) {
317 if (m->friendlist[i].status == NOFRIEND) {
318 m->friendlist[i].status = FRIEND_CONFIRMED;
319 m->friendlist[i].friendcon_id = friendcon_id;
320 m->friendlist[i].friendrequest_lastsent = 0;
321 id_copy(m->friendlist[i].client_id, client_id);
322 m->friendlist[i].statusmessage = calloc(1, 1);
323 m->friendlist[i].statusmessage_length = 1;
324 m->friendlist[i].userstatus = USERSTATUS_NONE;
325 m->friendlist[i].avatar_info_sent = 0;
326 m->friendlist[i].avatar_recv_data = NULL;
327 m->friendlist[i].avatar_send_data.bytes_sent = 0;
328 m->friendlist[i].avatar_send_data.last_reset = 0;
329 m->friendlist[i].is_typing = 0;
330 m->friendlist[i].message_id = 0;
331 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
332 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
333 &handle_custom_lossy_packet, m, i);
334
335 if (m->numfriends == i)
336 ++m->numfriends;
337
338 if (friend_con_connected(m->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
339 send_online_packet(m, i);
340 }
341
342 return i;
343 }
344 } 321 }
345
346 return -1;
347} 322}
348 323
349/* Remove a friend. 324/* Remove a friend.
@@ -361,7 +336,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
361 336
362 free(m->friendlist[friendnumber].statusmessage); 337 free(m->friendlist[friendnumber].statusmessage);
363 free(m->friendlist[friendnumber].avatar_recv_data); 338 free(m->friendlist[friendnumber].avatar_recv_data);
364 remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id); 339 remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk);
365 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0); 340 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
366 kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id); 341 kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
367 342
@@ -513,6 +488,9 @@ int setname(Messenger *m, const uint8_t *name, uint16_t length)
513 if (length > MAX_NAME_LENGTH || length == 0) 488 if (length > MAX_NAME_LENGTH || length == 0)
514 return -1; 489 return -1;
515 490
491 if (m->name_length == length && memcmp(name, m->name, length) == 0)
492 return 0;
493
516 memcpy(m->name, name, length); 494 memcpy(m->name, name, length);
517 m->name_length = length; 495 m->name_length = length;
518 uint32_t i; 496 uint32_t i;
@@ -572,6 +550,9 @@ int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length)
572 if (length > MAX_STATUSMESSAGE_LENGTH) 550 if (length > MAX_STATUSMESSAGE_LENGTH)
573 return -1; 551 return -1;
574 552
553 if (m->statusmessage_length == length && memcmp(m->statusmessage, status, length) == 0)
554 return 0;
555
575 memcpy(m->statusmessage, status, length); 556 memcpy(m->statusmessage, status, length);
576 m->statusmessage_length = length; 557 m->statusmessage_length = length;
577 558
@@ -585,9 +566,11 @@ int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length)
585 566
586int m_set_userstatus(Messenger *m, uint8_t status) 567int m_set_userstatus(Messenger *m, uint8_t status)
587{ 568{
588 if (status >= USERSTATUS_INVALID) { 569 if (status >= USERSTATUS_INVALID)
589 return -1; 570 return -1;
590 } 571
572 if (m->userstatus == status)
573 return 0;
591 574
592 m->userstatus = status; 575 m->userstatus = status;
593 uint32_t i; 576 uint32_t i;
@@ -813,13 +796,15 @@ uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber)
813int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing) 796int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing)
814 797
815{ 798{
816 if (is_typing != 0 && is_typing != 1) { 799 if (is_typing != 0 && is_typing != 1)
817 return -1; 800 return -1;
818 }
819 801
820 if (friend_not_valid(m, friendnumber)) 802 if (friend_not_valid(m, friendnumber))
821 return -1; 803 return -1;
822 804
805 if (m->friendlist[friendnumber].user_istyping == is_typing)
806 return 0;
807
823 m->friendlist[friendnumber].user_istyping = is_typing; 808 m->friendlist[friendnumber].user_istyping = is_typing;
824 m->friendlist[friendnumber].user_istyping_sent = 0; 809 m->friendlist[friendnumber].user_istyping_sent = 0;
825 810
@@ -1543,11 +1528,11 @@ int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const
1543} 1528}
1544 1529
1545/* Function to filter out some friend requests*/ 1530/* Function to filter out some friend requests*/
1546static int friend_already_added(const uint8_t *client_id, void *data) 1531static int friend_already_added(const uint8_t *real_pk, void *data)
1547{ 1532{
1548 const Messenger *m = data; 1533 const Messenger *m = data;
1549 1534
1550 if (getfriend_id(m, client_id) == -1) 1535 if (getfriend_id(m, real_pk) == -1)
1551 return 0; 1536 return 0;
1552 1537
1553 return -1; 1538 return -1;
@@ -1684,6 +1669,8 @@ static int handle_status(void *object, int i, uint8_t status)
1684 m->friendlist[i].name_sent = 0; 1669 m->friendlist[i].name_sent = 0;
1685 m->friendlist[i].userstatus_sent = 0; 1670 m->friendlist[i].userstatus_sent = 0;
1686 m->friendlist[i].statusmessage_sent = 0; 1671 m->friendlist[i].statusmessage_sent = 0;
1672 m->friendlist[i].user_istyping_sent = 0;
1673 m->friendlist[i].avatar_info_sent = 0;
1687 m->friendlist[i].ping_lastrecv = temp_time; 1674 m->friendlist[i].ping_lastrecv = temp_time;
1688 } else { /* Went offline. */ 1675 } else { /* Went offline. */
1689 if (m->friendlist[i].status == FRIEND_ONLINE) { 1676 if (m->friendlist[i].status == FRIEND_ONLINE) {
@@ -2259,7 +2246,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2259 int i; 2246 int i;
2260 2247
2261 for (i = 0; i < n; i++) { 2248 for (i = 0; i < n; i++) {
2262 add_tcp_relay(m->net_crypto, nodes[i].ip_port, nodes[i].client_id); 2249 add_tcp_relay(m->net_crypto, nodes[i].ip_port, nodes[i].public_key);
2263 } 2250 }
2264 2251
2265 break; 2252 break;
@@ -2341,15 +2328,15 @@ void do_friends(Messenger *m)
2341#ifdef LOGGING 2328#ifdef LOGGING
2342#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL 2329#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL
2343static time_t lastdump = 0; 2330static time_t lastdump = 0;
2344static char IDString[CLIENT_ID_SIZE * 2 + 1]; 2331static char IDString[crypto_box_PUBLICKEYBYTES * 2 + 1];
2345static char *ID2String(const uint8_t *client_id) 2332static char *ID2String(const uint8_t *pk)
2346{ 2333{
2347 uint32_t i; 2334 uint32_t i;
2348 2335
2349 for (i = 0; i < CLIENT_ID_SIZE; i++) 2336 for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++)
2350 sprintf(&IDString[i * 2], "%02X", client_id[i]); 2337 sprintf(&IDString[i * 2], "%02X", pk[i]);
2351 2338
2352 IDString[CLIENT_ID_SIZE * 2] = 0; 2339 IDString[crypto_box_PUBLICKEYBYTES * 2] = 0;
2353 return IDString; 2340 return IDString;
2354} 2341}
2355#endif 2342#endif
@@ -2384,7 +2371,7 @@ void do_messenger(Messenger *m)
2384 int i; 2371 int i;
2385 2372
2386 for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) { 2373 for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) {
2387 add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].client_id); 2374 add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key);
2388 } 2375 }
2389 } 2376 }
2390 2377
@@ -2446,7 +2433,7 @@ void do_messenger(Messenger *m)
2446 continue; 2433 continue;
2447 2434
2448 for (dhtfriend = 0; dhtfriend < m->dht->num_friends; dhtfriend++) 2435 for (dhtfriend = 0; dhtfriend < m->dht->num_friends; dhtfriend++)
2449 if (id_equal(m->friendlist[friend].client_id, m->dht->friends_list[dhtfriend].client_id)) { 2436 if (id_equal(m->friendlist[friend].real_pk, m->dht->friends_list[dhtfriend].client_id)) {
2450 m2dht[friend] = dhtfriend; 2437 m2dht[friend] = dhtfriend;
2451 break; 2438 break;
2452 } 2439 }
@@ -2480,7 +2467,7 @@ void do_messenger(Messenger *m)
2480 2467
2481 LOGGER_TRACE("F[%2u:%2u] <%s> [%03u] %s", 2468 LOGGER_TRACE("F[%2u:%2u] <%s> [%03u] %s",
2482 dht2m[friend], friend, msgfptr->name, 2469 dht2m[friend], friend, msgfptr->name,
2483 ping_lastrecv, ID2String(msgfptr->client_id)); 2470 ping_lastrecv, ID2String(msgfptr->real_pk));
2484 } else { 2471 } else {
2485 LOGGER_TRACE("F[--:%2u] %s", friend, ID2String(dhtfptr->client_id)); 2472 LOGGER_TRACE("F[--:%2u] %s", friend, ID2String(dhtfptr->client_id));
2486 } 2473 }
@@ -2527,7 +2514,7 @@ void do_messenger(Messenger *m)
2527#define NUM_SAVED_PATH_NODES 8 2514#define NUM_SAVED_PATH_NODES 8
2528struct SAVED_FRIEND { 2515struct SAVED_FRIEND {
2529 uint8_t status; 2516 uint8_t status;
2530 uint8_t client_id[CLIENT_ID_SIZE]; 2517 uint8_t real_pk[crypto_box_PUBLICKEYBYTES];
2531 uint8_t info[SAVED_FRIEND_REQUEST_SIZE]; // the data that is sent during the friend requests we do. 2518 uint8_t info[SAVED_FRIEND_REQUEST_SIZE]; // the data that is sent during the friend requests we do.
2532 uint16_t info_size; // Length of the info. 2519 uint16_t info_size; // Length of the info.
2533 uint8_t name[MAX_NAME_LENGTH]; 2520 uint8_t name[MAX_NAME_LENGTH];
@@ -2554,7 +2541,7 @@ static uint32_t friends_list_save(const Messenger *m, uint8_t *data)
2554 struct SAVED_FRIEND temp; 2541 struct SAVED_FRIEND temp;
2555 memset(&temp, 0, sizeof(struct SAVED_FRIEND)); 2542 memset(&temp, 0, sizeof(struct SAVED_FRIEND));
2556 temp.status = m->friendlist[i].status; 2543 temp.status = m->friendlist[i].status;
2557 memcpy(temp.client_id, m->friendlist[i].client_id, CLIENT_ID_SIZE); 2544 memcpy(temp.real_pk, m->friendlist[i].real_pk, crypto_box_PUBLICKEYBYTES);
2558 2545
2559 if (temp.status < 3) { 2546 if (temp.status < 3) {
2560 if (m->friendlist[i].info_size > SAVED_FRIEND_REQUEST_SIZE) { 2547 if (m->friendlist[i].info_size > SAVED_FRIEND_REQUEST_SIZE) {
@@ -2600,7 +2587,7 @@ static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)
2600 memcpy(&temp, data + i * sizeof(struct SAVED_FRIEND), sizeof(struct SAVED_FRIEND)); 2587 memcpy(&temp, data + i * sizeof(struct SAVED_FRIEND), sizeof(struct SAVED_FRIEND));
2601 2588
2602 if (temp.status >= 3) { 2589 if (temp.status >= 3) {
2603 int fnum = m_addfriend_norequest(m, temp.client_id); 2590 int fnum = m_addfriend_norequest(m, temp.real_pk);
2604 2591
2605 if (fnum < 0) 2592 if (fnum < 0)
2606 continue; 2593 continue;
@@ -2615,7 +2602,7 @@ static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)
2615 } else if (temp.status != 0) { 2602 } else if (temp.status != 0) {
2616 /* TODO: This is not a good way to do this. */ 2603 /* TODO: This is not a good way to do this. */
2617 uint8_t address[FRIEND_ADDRESS_SIZE]; 2604 uint8_t address[FRIEND_ADDRESS_SIZE];
2618 id_copy(address, temp.client_id); 2605 id_copy(address, temp.real_pk);
2619 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp.friendrequest_nospam), sizeof(uint32_t)); 2606 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp.friendrequest_nospam), sizeof(uint32_t));
2620 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 2607 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
2621 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); 2608 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum));
@@ -2792,7 +2779,7 @@ static int messenger_load_state_callback(void *outer, const uint8_t *data, uint3
2792 uint32_t i; 2779 uint32_t i;
2793 2780
2794 for (i = 0; i < NUM_SAVED_PATH_NODES; ++i) { 2781 for (i = 0; i < NUM_SAVED_PATH_NODES; ++i) {
2795 onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].client_id); 2782 onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key);
2796 } 2783 }
2797 2784
2798 break; 2785 break;
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 3851edf7..a9931d1f 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -191,7 +191,7 @@ enum {
191typedef struct Messenger Messenger; 191typedef struct Messenger Messenger;
192 192
193typedef struct { 193typedef struct {
194 uint8_t client_id[crypto_box_PUBLICKEYBYTES]; 194 uint8_t real_pk[crypto_box_PUBLICKEYBYTES];
195 int friendcon_id; 195 int friendcon_id;
196 196
197 uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. 197 uint64_t friendrequest_lastsent; // Time at which the last friend request was sent.
@@ -313,7 +313,7 @@ struct Messenger {
313 Messenger_Options options; 313 Messenger_Options options;
314}; 314};
315 315
316/* Format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] 316/* Format: [real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
317 * 317 *
318 * return FRIEND_ADDRESS_SIZE byte address to give to others. 318 * return FRIEND_ADDRESS_SIZE byte address to give to others.
319 */ 319 */
@@ -342,20 +342,20 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
342 * return the friend number if success. 342 * return the friend number if success.
343 * return -1 if failure. 343 * return -1 if failure.
344 */ 344 */
345int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id); 345int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk);
346 346
347/* return the friend number associated to that client id. 347/* return the friend number associated to that client id.
348 * return -1 if no such friend. 348 * return -1 if no such friend.
349 */ 349 */
350int32_t getfriend_id(const Messenger *m, const uint8_t *client_id); 350int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk);
351 351
352/* Copies the public key associated to that friend id into client_id buffer. 352/* Copies the public key associated to that friend id into real_pk buffer.
353 * Make sure that client_id is of size CLIENT_ID_SIZE. 353 * Make sure that real_pk is of size crypto_box_PUBLICKEYBYTES.
354 * 354 *
355 * return 0 if success 355 * return 0 if success
356 * return -1 if failure 356 * return -1 if failure
357 */ 357 */
358int getclient_id(const Messenger *m, int32_t friendnumber, uint8_t *client_id); 358int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk);
359 359
360/* return friend connection id on success. 360/* return friend connection id on success.
361 * return -1 if failure. 361 * return -1 if failure.
diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c
index 250d6c44..e85a506d 100644
--- a/toxcore/TCP_server.c
+++ b/toxcore/TCP_server.c
@@ -812,6 +812,7 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint
812 source.port = 0; // dummy initialise 812 source.port = 0; // dummy initialise
813 source.ip.family = TCP_ONION_FAMILY; 813 source.ip.family = TCP_ONION_FAMILY;
814 source.ip.ip6.uint32[0] = con_id; 814 source.ip.ip6.uint32[0] = con_id;
815 source.ip.ip6.uint32[1] = 0;
815 source.ip.ip6.uint64[1] = con->identifier; 816 source.ip.ip6.uint64[1] = con->identifier;
816 onion_send_1(TCP_server->onion, data + 1 + crypto_box_NONCEBYTES, length - (1 + crypto_box_NONCEBYTES), source, 817 onion_send_1(TCP_server->onion, data + 1 + crypto_box_NONCEBYTES, length - (1 + crypto_box_NONCEBYTES), source,
817 data + 1); 818 data + 1);
@@ -862,36 +863,42 @@ static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection
862{ 863{
863 int index = add_accepted(TCP_server, con); 864 int index = add_accepted(TCP_server, con);
864 865
865 if (index == -1) 866 if (index == -1) {
867 kill_TCP_connection(con);
866 return -1; 868 return -1;
869 }
870
871 memset(con, 0, sizeof(TCP_Secure_Connection));
867 872
868 if (handle_TCP_packet(TCP_server, index, data, length) == -1) { 873 if (handle_TCP_packet(TCP_server, index, data, length) == -1) {
869 kill_accepted(TCP_server, index); 874 kill_accepted(TCP_server, index);
875 return -1;
870 } 876 }
871 877
872 return index; 878 return index;
873} 879}
874 880
875/* return 1 on success 881/* return index on success
876 * return 0 on failure 882 * return -1 on failure
877 */ 883 */
878static int accept_connection(TCP_Server *TCP_server, sock_t sock) 884static int accept_connection(TCP_Server *TCP_server, sock_t sock)
879{ 885{
880 if (!sock_valid(sock)) 886 if (!sock_valid(sock))
881 return 0; 887 return -1;
882 888
883 if (!set_socket_nonblock(sock)) { 889 if (!set_socket_nonblock(sock)) {
884 kill_sock(sock); 890 kill_sock(sock);
885 return 0; 891 return -1;
886 } 892 }
887 893
888 if (!set_socket_nosigpipe(sock)) { 894 if (!set_socket_nosigpipe(sock)) {
889 kill_sock(sock); 895 kill_sock(sock);
890 return 0; 896 return -1;
891 } 897 }
892 898
893 TCP_Secure_Connection *conn = 899 uint16_t index = TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS;
894 &TCP_server->incomming_connection_queue[TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS]; 900
901 TCP_Secure_Connection *conn = &TCP_server->incomming_connection_queue[index];
895 902
896 if (conn->status != TCP_STATUS_NO_STATUS) 903 if (conn->status != TCP_STATUS_NO_STATUS)
897 kill_TCP_connection(conn); 904 kill_TCP_connection(conn);
@@ -901,7 +908,7 @@ static int accept_connection(TCP_Server *TCP_server, sock_t sock)
901 conn->next_packet_length = 0; 908 conn->next_packet_length = 0;
902 909
903 ++TCP_server->incomming_connection_queue_index; 910 ++TCP_server->incomming_connection_queue_index;
904 return 1; 911 return index;
905} 912}
906 913
907static sock_t new_listening_TCP_socket(int family, uint16_t port) 914static sock_t new_listening_TCP_socket(int family, uint16_t port)
@@ -912,11 +919,7 @@ static sock_t new_listening_TCP_socket(int family, uint16_t port)
912 return ~0; 919 return ~0;
913 } 920 }
914 921
915#ifndef TCP_SERVER_USE_EPOLL
916 int ok = set_socket_nonblock(sock); 922 int ok = set_socket_nonblock(sock);
917#else
918 int ok = 1;
919#endif
920 923
921 if (ok && family == AF_INET6) { 924 if (ok && family == AF_INET6) {
922 ok = set_socket_dualstack(sock); 925 ok = set_socket_dualstack(sock);
@@ -983,7 +986,7 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uin
983 986
984 if (sock_valid(sock)) { 987 if (sock_valid(sock)) {
985#ifdef TCP_SERVER_USE_EPOLL 988#ifdef TCP_SERVER_USE_EPOLL
986 ev.events = EPOLLIN; 989 ev.events = EPOLLIN | EPOLLET;
987 ev.data.u64 = sock | ((uint64_t)TCP_SOCKET_LISTENING << 32); 990 ev.data.u64 = sock | ((uint64_t)TCP_SOCKET_LISTENING << 32);
988 991
989 if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, sock, &ev) == -1) { 992 if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, sock, &ev) == -1) {
@@ -1027,7 +1030,7 @@ static void do_TCP_accept_new(TCP_Server *TCP_server)
1027 1030
1028 do { 1031 do {
1029 sock = accept(TCP_server->socks_listening[i], (struct sockaddr *)&addr, &addrlen); 1032 sock = accept(TCP_server->socks_listening[i], (struct sockaddr *)&addr, &addrlen);
1030 } while (accept_connection(TCP_server, sock)); 1033 } while (accept_connection(TCP_server, sock) != -1);
1031 } 1034 }
1032} 1035}
1033 1036
@@ -1075,15 +1078,7 @@ static int do_unconfirmed(TCP_Server *TCP_server, uint32_t i)
1075 kill_TCP_connection(conn); 1078 kill_TCP_connection(conn);
1076 return -1; 1079 return -1;
1077 } else { 1080 } else {
1078 int index_new; 1081 return confirm_TCP_connection(TCP_server, conn, packet, len);
1079
1080 if ((index_new = confirm_TCP_connection(TCP_server, conn, packet, len)) == -1) {
1081 kill_TCP_connection(conn);
1082 } else {
1083 memset(conn, 0, sizeof(TCP_Secure_Connection));
1084 }
1085
1086 return index_new;
1087 } 1082 }
1088} 1083}
1089 1084
@@ -1194,7 +1189,7 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1194 sock_t sock = events[n].data.u64 & 0xFFFFFFFF; 1189 sock_t sock = events[n].data.u64 & 0xFFFFFFFF;
1195 int status = (events[n].data.u64 >> 32) & 0xFFFF, index = (events[n].data.u64 >> 48); 1190 int status = (events[n].data.u64 >> 32) & 0xFFFF, index = (events[n].data.u64 >> 48);
1196 1191
1197 if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP)) { 1192 if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP) || (events[n].events & EPOLLRDHUP)) {
1198 switch (status) { 1193 switch (status) {
1199 case TCP_SOCKET_LISTENING: { 1194 case TCP_SOCKET_LISTENING: {
1200 //should never happen 1195 //should never happen
@@ -1230,24 +1225,29 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1230 //socket is from socks_listening, accept connection 1225 //socket is from socks_listening, accept connection
1231 struct sockaddr_storage addr; 1226 struct sockaddr_storage addr;
1232 unsigned int addrlen = sizeof(addr); 1227 unsigned int addrlen = sizeof(addr);
1233 sock_t sock_new;
1234 1228
1235 sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen); 1229 while (1) {
1230 sock_t sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen);
1236 1231
1237 int index_new = TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS; 1232 if (!sock_valid(sock_new)) {
1233 break;
1234 }
1238 1235
1239 if (!accept_connection(TCP_server, sock_new)) { 1236 int index_new = accept_connection(TCP_server, sock_new);
1240 break;
1241 }
1242 1237
1243 struct epoll_event ev = { 1238 if (index_new == -1) {
1244 .events = EPOLLIN | EPOLLET, 1239 continue;
1245 .data.u64 = sock_new | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 48) 1240 }
1246 };
1247 1241
1248 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_ADD, sock_new, &ev) == -1) { 1242 struct epoll_event ev = {
1249 kill_TCP_connection(&TCP_server->incomming_connection_queue[index_new]); 1243 .events = EPOLLIN | EPOLLET | EPOLLRDHUP,
1250 break; 1244 .data.u64 = sock_new | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 48)
1245 };
1246
1247 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_ADD, sock_new, &ev) == -1) {
1248 kill_TCP_connection(&TCP_server->incomming_connection_queue[index_new]);
1249 continue;
1250 }
1251 } 1251 }
1252 1252
1253 break; 1253 break;
@@ -1257,7 +1257,7 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1257 int index_new; 1257 int index_new;
1258 1258
1259 if ((index_new = do_incoming(TCP_server, index)) != -1) { 1259 if ((index_new = do_incoming(TCP_server, index)) != -1) {
1260 events[n].events = EPOLLIN | EPOLLET; 1260 events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
1261 events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 48); 1261 events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 48);
1262 1262
1263 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) { 1263 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) {
@@ -1273,7 +1273,7 @@ static void do_TCP_epoll(TCP_Server *TCP_server)
1273 int index_new; 1273 int index_new;
1274 1274
1275 if ((index_new = do_unconfirmed(TCP_server, index)) != -1) { 1275 if ((index_new = do_unconfirmed(TCP_server, index)) != -1) {
1276 events[n].events = EPOLLIN | EPOLLET; 1276 events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
1277 events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 48); 1277 events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 48);
1278 1278
1279 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) { 1279 if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) {
@@ -1333,5 +1333,6 @@ void kill_TCP_server(TCP_Server *TCP_server)
1333#endif 1333#endif
1334 1334
1335 free(TCP_server->socks_listening); 1335 free(TCP_server->socks_listening);
1336 free(TCP_server->accepted_connection_array);
1336 free(TCP_server); 1337 free(TCP_server);
1337} 1338}
diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h
index 58bdc2f3..afd2f7b8 100644
--- a/toxcore/crypto_core.h
+++ b/toxcore/crypto_core.h
@@ -122,6 +122,7 @@ void new_nonce(uint8_t *nonce);
122 122
123#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ 123#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
124#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */ 124#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
125#define CRYPTO_PACKET_FAKEID 156
125#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */ 126#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
126 127
127/* Create a request to peer. 128/* Create a request to peer.
diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c
index 98937131..e4a10008 100644
--- a/toxcore/friend_requests.c
+++ b/toxcore/friend_requests.c
@@ -58,12 +58,12 @@ void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, v
58} 58}
59 59
60/* Add to list of received friend requests. */ 60/* Add to list of received friend requests. */
61static void addto_receivedlist(Friend_Requests *fr, const uint8_t *client_id) 61static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk)
62{ 62{
63 if (fr->received_requests_index >= MAX_RECEIVED_STORED) 63 if (fr->received_requests_index >= MAX_RECEIVED_STORED)
64 fr->received_requests_index = 0; 64 fr->received_requests_index = 0;
65 65
66 id_copy(fr->received_requests[fr->received_requests_index], client_id); 66 id_copy(fr->received_requests[fr->received_requests_index], real_pk);
67 ++fr->received_requests_index; 67 ++fr->received_requests_index;
68} 68}
69 69
@@ -72,28 +72,28 @@ static void addto_receivedlist(Friend_Requests *fr, const uint8_t *client_id)
72 * return 0 if it did not. 72 * return 0 if it did not.
73 * return 1 if it did. 73 * return 1 if it did.
74 */ 74 */
75static int request_received(Friend_Requests *fr, const uint8_t *client_id) 75static int request_received(Friend_Requests *fr, const uint8_t *real_pk)
76{ 76{
77 uint32_t i; 77 uint32_t i;
78 78
79 for (i = 0; i < MAX_RECEIVED_STORED; ++i) 79 for (i = 0; i < MAX_RECEIVED_STORED; ++i)
80 if (id_equal(fr->received_requests[i], client_id)) 80 if (id_equal(fr->received_requests[i], real_pk))
81 return 1; 81 return 1;
82 82
83 return 0; 83 return 0;
84} 84}
85 85
86/* Remove client id from received_requests list. 86/* Remove real pk from received_requests list.
87 * 87 *
88 * return 0 if it removed it successfully. 88 * return 0 if it removed it successfully.
89 * return -1 if it didn't find it. 89 * return -1 if it didn't find it.
90 */ 90 */
91int remove_request_received(Friend_Requests *fr, const uint8_t *client_id) 91int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk)
92{ 92{
93 uint32_t i; 93 uint32_t i;
94 94
95 for (i = 0; i < MAX_RECEIVED_STORED; ++i) { 95 for (i = 0; i < MAX_RECEIVED_STORED; ++i) {
96 if (id_equal(fr->received_requests[i], client_id)) { 96 if (id_equal(fr->received_requests[i], real_pk)) {
97 memset(fr->received_requests[i], 0, crypto_box_PUBLICKEYBYTES); 97 memset(fr->received_requests[i], 0, crypto_box_PUBLICKEYBYTES);
98 return 0; 98 return 0;
99 } 99 }
diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h
index b7e07af4..86069f3b 100644
--- a/toxcore/friend_requests.h
+++ b/toxcore/friend_requests.h
@@ -51,12 +51,12 @@ typedef struct {
51void set_nospam(Friend_Requests *fr, uint32_t num); 51void set_nospam(Friend_Requests *fr, uint32_t num);
52uint32_t get_nospam(const Friend_Requests *fr); 52uint32_t get_nospam(const Friend_Requests *fr);
53 53
54/* Remove client id from received_requests list. 54/* Remove real_pk from received_requests list.
55 * 55 *
56 * return 0 if it removed it successfully. 56 * return 0 if it removed it successfully.
57 * return -1 if it didn't find it. 57 * return -1 if it didn't find it.
58 */ 58 */
59int remove_request_received(Friend_Requests *fr, const uint8_t *client_id); 59int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk);
60 60
61/* Set the function that will be executed when a friend request for us is received. 61/* Set the function that will be executed when a friend request for us is received.
62 * Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length, void * userdata) 62 * Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length, void * userdata)
diff --git a/toxcore/group.c b/toxcore/group.c
index eb795721..c1a60851 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -447,7 +447,7 @@ static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id
447 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 447 if (g->close[i].type == GROUPCHAT_CLOSE_NONE)
448 continue; 448 continue;
449 449
450 if (g->close[i].number == friendcon_id) { 450 if (g->close[i].number == (unsigned int)friendcon_id) {
451 g->close[i].type = GROUPCHAT_CLOSE_NONE; 451 g->close[i].type = GROUPCHAT_CLOSE_NONE;
452 kill_friend_connection(g_c->fr_c, friendcon_id); 452 kill_friend_connection(g_c->fr_c, friendcon_id);
453 return 0; 453 return 0;
@@ -576,7 +576,7 @@ static void set_conns_type_close(Group_Chats *g_c, int groupnumber, int friendco
576 if (g->close[i].type == GROUPCHAT_CLOSE_NONE) 576 if (g->close[i].type == GROUPCHAT_CLOSE_NONE)
577 continue; 577 continue;
578 578
579 if (g->close[i].number != friendcon_id) 579 if (g->close[i].number != (unsigned int)friendcon_id)
580 continue; 580 continue;
581 581
582 if (type == GROUPCHAT_CLOSE_ONLINE) { 582 if (type == GROUPCHAT_CLOSE_ONLINE) {
@@ -789,7 +789,7 @@ int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAM
789 if (!g) 789 if (!g)
790 return -1; 790 return -1;
791 791
792 int i; 792 unsigned int i;
793 793
794 for (i = 0; i < g->numpeers && i < length; ++i) { 794 for (i = 0; i < g->numpeers && i < length; ++i) {
795 lengths[i] = group_peername(g_c, groupnumber, i, names[i]); 795 lengths[i] = group_peername(g_c, groupnumber, i, names[i]);
diff --git a/toxcore/logger.c b/toxcore/logger.c
index ac81a900..e8aef7e0 100644
--- a/toxcore/logger.c
+++ b/toxcore/logger.c
@@ -1,6 +1,6 @@
1/* logger.c 1/* logger.c
2 * 2 *
3 * Copyright (C) 2013 Tox project All Rights Reserved. 3 * Copyright (C) 2013, 2015 Tox project All Rights Reserved.
4 * 4 *
5 * This file is part of Tox. 5 * This file is part of Tox.
6 * 6 *
@@ -37,8 +37,10 @@
37#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 37#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
38# define getpid() ((unsigned) GetCurrentProcessId()) 38# define getpid() ((unsigned) GetCurrentProcessId())
39# define SFILE(FILE__M) (strrchr(FILE__M, '\\') ? strrchr(FILE__M, '\\') + 1 : FILE__M) 39# define SFILE(FILE__M) (strrchr(FILE__M, '\\') ? strrchr(FILE__M, '\\') + 1 : FILE__M)
40# define WIN_CR "\r"
40#else 41#else
41# define SFILE(FILE__M) (strrchr(FILE__M, '/') ? strrchr(FILE__M, '/') + 1 : FILE__M) 42# define SFILE(FILE__M) (strrchr(FILE__M, '/') ? strrchr(FILE__M, '/') + 1 : FILE__M)
43# define WIN_CR ""
42#endif 44#endif
43 45
44 46
@@ -57,7 +59,7 @@ struct logger {
57 pthread_mutex_t mutex[1]; 59 pthread_mutex_t mutex[1];
58}; 60};
59 61
60logger *global = NULL; 62Logger *global = NULL;
61 63
62const char *LOG_LEVEL_STR [] = { 64const char *LOG_LEVEL_STR [] = {
63 [LOG_TRACE] = "TRACE", 65 [LOG_TRACE] = "TRACE",
@@ -83,13 +85,13 @@ char *strtime(char *dest, size_t max_len)
83/** 85/**
84 * Public Functions 86 * Public Functions
85 */ 87 */
86logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id) 88Logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id)
87{ 89{
88#ifndef LOGGING /* Disabled */ 90#ifndef LOGGING /* Disabled */
89 return NULL; 91 return NULL;
90#endif 92#endif
91 93
92 logger *retu = calloc(1, sizeof(logger)); 94 Logger *retu = calloc(1, sizeof(Logger));
93 95
94 if (!retu) 96 if (!retu)
95 return NULL; 97 return NULL;
@@ -100,7 +102,7 @@ logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id)
100 } 102 }
101 103
102 if (!(retu->log_file = fopen(file_name, "ab"))) { 104 if (!(retu->log_file = fopen(file_name, "ab"))) {
103 fprintf(stderr, "Error opening logger file: %s; info: %s\n", file_name, strerror(errno)); 105 fprintf(stderr, "Error opening logger file: %s; info: %s" WIN_CR "\n", file_name, strerror(errno));
104 free(retu); 106 free(retu);
105 pthread_mutex_destroy(retu->mutex); 107 pthread_mutex_destroy(retu->mutex);
106 return NULL; 108 return NULL;
@@ -109,16 +111,16 @@ logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id)
109 if (!(retu->tstr = calloc(16, sizeof (char))) || 111 if (!(retu->tstr = calloc(16, sizeof (char))) ||
110 !(retu->posstr = calloc(300, sizeof (char))) || 112 !(retu->posstr = calloc(300, sizeof (char))) ||
111 !(retu->msg = calloc(4096, sizeof (char))) ) 113 !(retu->msg = calloc(4096, sizeof (char))) )
112 goto ERROR; 114 goto FAILURE;
113 115
114 if (id) { 116 if (id) {
115 if (!(retu->id = calloc(strlen(id) + 1, 1))) 117 if (!(retu->id = calloc(strlen(id) + 1, 1)))
116 goto ERROR; 118 goto FAILURE;
117 119
118 strcpy(retu->id, id); 120 strcpy(retu->id, id);
119 } else { 121 } else {
120 if (!(retu->id = malloc(8))) 122 if (!(retu->id = malloc(8)))
121 goto ERROR; 123 goto FAILURE;
122 124
123 snprintf(retu->id, 8, "%u", random_int()); 125 snprintf(retu->id, 8, "%u", random_int());
124 } 126 }
@@ -126,13 +128,13 @@ logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id)
126 retu->level = level; 128 retu->level = level;
127 retu->start_time = current_time_monotonic(); 129 retu->start_time = current_time_monotonic();
128 130
129 fprintf(retu->log_file, "Successfully created and running logger id: %s; time: %s\n", 131 fprintf(retu->log_file, "Successfully created and running logger id: %s; time: %s" WIN_CR "\n",
130 retu->id, strtime(retu->tstr, 16)); 132 retu->id, strtime(retu->tstr, 16));
131 133
132 return retu; 134 return retu;
133 135
134ERROR: 136FAILURE:
135 fprintf(stderr, "Failed to create logger!\n"); 137 fprintf(stderr, "Failed to create logger!" WIN_CR "\n");
136 pthread_mutex_destroy(retu->mutex); 138 pthread_mutex_destroy(retu->mutex);
137 fclose(retu->log_file); 139 fclose(retu->log_file);
138 free(retu->tstr); 140 free(retu->tstr);
@@ -143,7 +145,7 @@ ERROR:
143 return NULL; 145 return NULL;
144} 146}
145 147
146void logger_kill(logger *log) 148void logger_kill(Logger *log)
147{ 149{
148#ifndef LOGGING /* Disabled */ 150#ifndef LOGGING /* Disabled */
149 return; 151 return;
@@ -173,7 +175,7 @@ void logger_kill_global(void)
173 global = NULL; 175 global = NULL;
174} 176}
175 177
176void logger_set_global(logger *log) 178void logger_set_global(Logger *log)
177{ 179{
178#ifndef LOGGING /* Disabled */ 180#ifndef LOGGING /* Disabled */
179 return; 181 return;
@@ -182,7 +184,7 @@ void logger_set_global(logger *log)
182 global = log; 184 global = log;
183} 185}
184 186
185logger *logger_get_global(void) 187Logger *logger_get_global(void)
186{ 188{
187#ifndef LOGGING /* Disabled */ 189#ifndef LOGGING /* Disabled */
188 return NULL; 190 return NULL;
@@ -191,7 +193,7 @@ logger *logger_get_global(void)
191 return global; 193 return global;
192} 194}
193 195
194void logger_write (logger *log, LOG_LEVEL level, const char *file, int line, const char *format, ...) 196void logger_write (Logger *log, LOG_LEVEL level, const char *file, int line, const char *format, ...)
195{ 197{
196#ifndef LOGGING /* Disabled */ 198#ifndef LOGGING /* Disabled */
197 return; 199 return;
@@ -204,10 +206,10 @@ void logger_write (logger *log, LOG_LEVEL level, const char *file, int line, con
204 "%-5s " /* Logger lever string */ 206 "%-5s " /* Logger lever string */
205 "%-20s " /* File:line string */ 207 "%-20s " /* File:line string */
206 "- %s" /* Output message */ 208 "- %s" /* Output message */
207 "\n"; /* Every new print new line */ 209 WIN_CR "\n"; /* Every new print new line */
208 210
209 211
210 logger *this_log = log ? log : global; 212 Logger *this_log = log ? log : global;
211 213
212 if (!this_log) 214 if (!this_log)
213 return; 215 return;
diff --git a/toxcore/logger.h b/toxcore/logger.h
index 6f1f6075..0513b32c 100644
--- a/toxcore/logger.h
+++ b/toxcore/logger.h
@@ -43,26 +43,26 @@ typedef enum {
43 LOG_ERROR 43 LOG_ERROR
44} LOG_LEVEL; 44} LOG_LEVEL;
45 45
46typedef struct logger logger; 46typedef struct logger Logger;
47 47
48/** 48/**
49 * Set 'level' as the lowest printable level. If id == NULL, random number is used. 49 * Set 'level' as the lowest printable level. If id == NULL, random number is used.
50 */ 50 */
51logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id); 51Logger *logger_new (const char *file_name, LOG_LEVEL level, const char *id);
52 52
53void logger_kill (logger *log); 53void logger_kill (Logger *log);
54void logger_kill_global (void); 54void logger_kill_global (void);
55 55
56/** 56/**
57 * Global logger setter and getter. 57 * Global logger setter and getter.
58 */ 58 */
59void logger_set_global (logger *log); 59void logger_set_global (Logger *log);
60logger *logger_get_global (void); 60Logger *logger_get_global (void);
61 61
62/** 62/**
63 * Main write function. If logging disabled does nothing. If log == NULL uses global logger. 63 * Main write function. If logging disabled does nothing. If log == NULL uses global logger.
64 */ 64 */
65void logger_write (logger *log, LOG_LEVEL level, const char *file, int line, const char *format, ...); 65void logger_write (Logger *log, LOG_LEVEL level, const char *file, int line, const char *format, ...);
66 66
67 67
68/* To do some checks or similar only when logging, use this */ 68/* To do some checks or similar only when logging, use this */
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index 8af3cbbc..bd5616a2 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -608,6 +608,23 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number)
608 return 0; 608 return 0;
609} 609}
610 610
611static int clear_buffer(Packets_Array *array)
612{
613 uint32_t i;
614
615 for (i = array->buffer_start; i != array->buffer_end; ++i) {
616 uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
617
618 if (array->buffer[num]) {
619 free(array->buffer[num]);
620 array->buffer[num] = NULL;
621 }
622 }
623
624 array->buffer_start = i;
625 return 0;
626}
627
611/* Set array buffer end to number. 628/* Set array buffer end to number.
612 * 629 *
613 * return -1 on failure. 630 * return -1 on failure.
@@ -1378,12 +1395,18 @@ static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id)
1378 return -1; 1395 return -1;
1379 1396
1380 uint32_t i; 1397 uint32_t i;
1381 pthread_mutex_destroy(&c->crypto_connections[crypt_connection_id].mutex); 1398
1399 /* Keep mutex, only destroy it when connection is realloced out. */
1400 pthread_mutex_t mutex = c->crypto_connections[crypt_connection_id].mutex;
1382 memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); 1401 memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection));
1402 c->crypto_connections[crypt_connection_id].mutex = mutex;
1383 1403
1384 for (i = c->crypto_connections_length; i != 0; --i) { 1404 for (i = c->crypto_connections_length; i != 0; --i) {
1385 if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION) 1405 if (c->crypto_connections[i - 1].status == CRYPTO_CONN_NO_CONNECTION) {
1406 pthread_mutex_destroy(&c->crypto_connections[i - 1].mutex);
1407 } else {
1386 break; 1408 break;
1409 }
1387 } 1410 }
1388 1411
1389 if (c->crypto_connections_length != i) { 1412 if (c->crypto_connections_length != i) {
@@ -1798,7 +1821,7 @@ static int tcp_response_callback(void *object, uint8_t connection_id, const uint
1798 uint32_t i; 1821 uint32_t i;
1799 1822
1800 for (i = 0; i < conn->num_tcp_relays; ++i) { 1823 for (i = 0; i < conn->num_tcp_relays; ++i) {
1801 if (memcmp(TCP_con->public_key, conn->tcp_relays[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) { 1824 if (memcmp(TCP_con->public_key, conn->tcp_relays[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
1802 set_conn_tcp_status(conn, location, STATUS_TCP_INVISIBLE); 1825 set_conn_tcp_status(conn, location, STATUS_TCP_INVISIBLE);
1803 return 0; 1826 return 0;
1804 } 1827 }
@@ -1977,7 +2000,7 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,
1977 uint32_t i; 2000 uint32_t i;
1978 2001
1979 for (i = 0; i < conn->num_tcp_relays; ++i) { 2002 for (i = 0; i < conn->num_tcp_relays; ++i) {
1980 if (memcmp(conn->tcp_relays[i].client_id, public_key, crypto_box_PUBLICKEYBYTES) == 0) { 2003 if (memcmp(conn->tcp_relays[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
1981 conn->tcp_relays[i].ip_port = ip_port; 2004 conn->tcp_relays[i].ip_port = ip_port;
1982 return 0; 2005 return 0;
1983 } 2006 }
@@ -1986,10 +2009,10 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port,
1986 if (conn->num_tcp_relays == MAX_TCP_RELAYS_PEER) { 2009 if (conn->num_tcp_relays == MAX_TCP_RELAYS_PEER) {
1987 uint16_t index = rand() % MAX_TCP_RELAYS_PEER; 2010 uint16_t index = rand() % MAX_TCP_RELAYS_PEER;
1988 conn->tcp_relays[index].ip_port = ip_port; 2011 conn->tcp_relays[index].ip_port = ip_port;
1989 memcpy(conn->tcp_relays[index].client_id, public_key, crypto_box_PUBLICKEYBYTES); 2012 memcpy(conn->tcp_relays[index].public_key, public_key, crypto_box_PUBLICKEYBYTES);
1990 } else { 2013 } else {
1991 conn->tcp_relays[conn->num_tcp_relays].ip_port = ip_port; 2014 conn->tcp_relays[conn->num_tcp_relays].ip_port = ip_port;
1992 memcpy(conn->tcp_relays[conn->num_tcp_relays].client_id, public_key, crypto_box_PUBLICKEYBYTES); 2015 memcpy(conn->tcp_relays[conn->num_tcp_relays].public_key, public_key, crypto_box_PUBLICKEYBYTES);
1993 ++conn->num_tcp_relays; 2016 ++conn->num_tcp_relays;
1994 } 2017 }
1995 2018
@@ -2039,29 +2062,50 @@ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key)
2039 return -1; 2062 return -1;
2040} 2063}
2041 2064
2042/* Send an onion packet via a random connected TCP relay. 2065/* Return a random TCP connection number for use in send_tcp_onion_request.
2043 * 2066 *
2044 * return 0 on success. 2067 * TODO: This number is just the index of an array that the elements can
2068 * change without warning.
2069 *
2070 * return TCP connection number on success.
2045 * return -1 on failure. 2071 * return -1 on failure.
2046 */ 2072 */
2047int send_tcp_onion_request(Net_Crypto *c, const uint8_t *data, uint16_t length) 2073int get_random_tcp_con_number(Net_Crypto *c)
2048{ 2074{
2049 unsigned int i, r = rand(); 2075 unsigned int i, r = rand();
2050 2076
2051 for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { 2077 for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) {
2052 if (c->tcp_connections[(i + r) % MAX_TCP_CONNECTIONS]) { 2078 if (c->tcp_connections[(i + r) % MAX_TCP_CONNECTIONS]) {
2053 pthread_mutex_lock(&c->tcp_mutex); 2079 return (i + r) % MAX_TCP_CONNECTIONS;
2054 int ret = send_onion_request(c->tcp_connections[(i + r) % MAX_TCP_CONNECTIONS], data, length);
2055 pthread_mutex_unlock(&c->tcp_mutex);
2056
2057 if (ret == 1)
2058 return 0;
2059 } 2080 }
2060 } 2081 }
2061 2082
2062 return -1; 2083 return -1;
2063} 2084}
2064 2085
2086/* Send an onion packet via the TCP relay corresponding to TCP_conn_number.
2087 *
2088 * return 0 on success.
2089 * return -1 on failure.
2090 */
2091int send_tcp_onion_request(Net_Crypto *c, unsigned int TCP_conn_number, const uint8_t *data, uint16_t length)
2092{
2093 if (TCP_conn_number > MAX_TCP_CONNECTIONS) {
2094 return -1;
2095 }
2096
2097 if (c->tcp_connections[TCP_conn_number]) {
2098 pthread_mutex_lock(&c->tcp_mutex);
2099 int ret = send_onion_request(c->tcp_connections[TCP_conn_number], data, length);
2100 pthread_mutex_unlock(&c->tcp_mutex);
2101
2102 if (ret == 1)
2103 return 0;
2104 }
2105
2106 return -1;
2107}
2108
2065/* Set the function to be called when an onion response packet is received by one of the TCP connections. 2109/* Set the function to be called when an onion response packet is received by one of the TCP connections.
2066 */ 2110 */
2067void tcp_onion_response_handler(Net_Crypto *c, int (*tcp_onion_callback)(void *object, const uint8_t *data, 2111void tcp_onion_response_handler(Net_Crypto *c, int (*tcp_onion_callback)(void *object, const uint8_t *data,
@@ -2087,7 +2131,7 @@ unsigned int copy_connected_tcp_relays(const Net_Crypto *c, Node_format *tcp_rel
2087 2131
2088 for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { 2132 for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) {
2089 if (c->tcp_connections[i] != NULL) { 2133 if (c->tcp_connections[i] != NULL) {
2090 memcpy(tcp_relays[copied].client_id, c->tcp_connections[i]->public_key, crypto_box_PUBLICKEYBYTES); 2134 memcpy(tcp_relays[copied].public_key, c->tcp_connections[i]->public_key, crypto_box_PUBLICKEYBYTES);
2091 tcp_relays[copied].ip_port = c->tcp_connections[i]->ip_port; 2135 tcp_relays[copied].ip_port = c->tcp_connections[i]->ip_port;
2092 2136
2093 if (tcp_relays[copied].ip_port.ip.family == AF_INET) { 2137 if (tcp_relays[copied].ip_port.ip.family == AF_INET) {
@@ -2391,7 +2435,7 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet
2391 2435
2392/* The dT for the average packet receiving rate calculations. 2436/* The dT for the average packet receiving rate calculations.
2393 Also used as the */ 2437 Also used as the */
2394#define PACKET_COUNTER_AVERAGE_INTERVAL 100 2438#define PACKET_COUNTER_AVERAGE_INTERVAL 50
2395 2439
2396/* Ratio of recv queue size / recv packet rate (in seconds) times 2440/* Ratio of recv queue size / recv packet rate (in seconds) times
2397 * the number of ms between request packets to send at that ratio 2441 * the number of ms between request packets to send at that ratio
@@ -2474,7 +2518,7 @@ static void send_crypto_packets(Net_Crypto *c)
2474 double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) * 2518 double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) *
2475 PACKET_COUNTER_AVERAGE_INTERVAL)); 2519 PACKET_COUNTER_AVERAGE_INTERVAL));
2476 2520
2477 conn->packet_send_rate = min_speed * 1.3; 2521 conn->packet_send_rate = min_speed * 1.2;
2478 2522
2479 if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) { 2523 if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) {
2480 conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; 2524 conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
@@ -2678,6 +2722,9 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id)
2678 2722
2679 disconnect_peer_tcp(c, crypt_connection_id); 2723 disconnect_peer_tcp(c, crypt_connection_id);
2680 bs_list_remove(&c->ip_port_list, &conn->ip_port, crypt_connection_id); 2724 bs_list_remove(&c->ip_port_list, &conn->ip_port, crypt_connection_id);
2725 clear_temp_packet(c, crypt_connection_id);
2726 clear_buffer(&conn->send_array);
2727 clear_buffer(&conn->recv_array);
2681 ret = wipe_crypto_connection(c, crypt_connection_id); 2728 ret = wipe_crypto_connection(c, crypt_connection_id);
2682 } 2729 }
2683 2730
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index b9fb1747..7e59475e 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -86,7 +86,7 @@
86 86
87/* Base current transfer speed on last CONGESTION_QUEUE_ARRAY_SIZE number of points taken 87/* Base current transfer speed on last CONGESTION_QUEUE_ARRAY_SIZE number of points taken
88 at the dT defined in net_crypto.c */ 88 at the dT defined in net_crypto.c */
89#define CONGESTION_QUEUE_ARRAY_SIZE 8 89#define CONGESTION_QUEUE_ARRAY_SIZE 24
90 90
91typedef struct { 91typedef struct {
92 uint64_t time; 92 uint64_t time;
@@ -364,12 +364,19 @@ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key);
364void tcp_onion_response_handler(Net_Crypto *c, int (*tcp_onion_callback)(void *object, const uint8_t *data, 364void tcp_onion_response_handler(Net_Crypto *c, int (*tcp_onion_callback)(void *object, const uint8_t *data,
365 uint16_t length), void *object); 365 uint16_t length), void *object);
366 366
367/* Send an onion packet via a random connected TCP relay. 367/* Return a random TCP connection number for use in send_tcp_onion_request.
368 *
369 * return TCP connection number on success.
370 * return -1 on failure.
371 */
372int get_random_tcp_con_number(Net_Crypto *c);
373
374/* Send an onion packet via the TCP relay corresponding to TCP_conn_number.
368 * 375 *
369 * return 0 on success. 376 * return 0 on success.
370 * return -1 on failure. 377 * return -1 on failure.
371 */ 378 */
372int send_tcp_onion_request(Net_Crypto *c, const uint8_t *data, uint16_t length); 379int send_tcp_onion_request(Net_Crypto *c, unsigned int TCP_conn_number, const uint8_t *data, uint16_t length);
373 380
374/* Copy a maximum of num TCP relays we are connected to to tcp_relays. 381/* Copy a maximum of num TCP relays we are connected to to tcp_relays.
375 * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. 382 * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
diff --git a/toxcore/onion.c b/toxcore/onion.c
index 05dbaae6..c6093f0c 100644
--- a/toxcore/onion.c
+++ b/toxcore/onion.c
@@ -61,7 +61,7 @@ static void ip_pack(uint8_t *data, IP source)
61} 61}
62 62
63/* return 0 on success, -1 on failure. */ 63/* return 0 on success, -1 on failure. */
64static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size) 64static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, _Bool disable_family_check)
65{ 65{
66 if (data_size < (1 + SIZE_IP6)) 66 if (data_size < (1 + SIZE_IP6))
67 return -1; 67 return -1;
@@ -74,7 +74,12 @@ static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size)
74 memcpy(target->ip6.uint8, data + 1, SIZE_IP6); 74 memcpy(target->ip6.uint8, data + 1, SIZE_IP6);
75 } 75 }
76 76
77 return to_host_family(target); 77 if (!disable_family_check) {
78 return to_host_family(target);
79 } else {
80 to_host_family(target);
81 return 0;
82 }
78} 83}
79 84
80static void ipport_pack(uint8_t *data, const IP_Port *source) 85static void ipport_pack(uint8_t *data, const IP_Port *source)
@@ -84,12 +89,12 @@ static void ipport_pack(uint8_t *data, const IP_Port *source)
84} 89}
85 90
86/* return 0 on success, -1 on failure. */ 91/* return 0 on success, -1 on failure. */
87static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size) 92static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size, _Bool disable_family_check)
88{ 93{
89 if (data_size < (SIZE_IP + SIZE_PORT)) 94 if (data_size < (SIZE_IP + SIZE_PORT))
90 return -1; 95 return -1;
91 96
92 if (ip_unpack(&target->ip, data, data_size) == -1) 97 if (ip_unpack(&target->ip, data, data_size, disable_family_check) == -1)
93 return -1; 98 return -1;
94 99
95 memcpy(&target->port, data + SIZE_IP, SIZE_PORT); 100 memcpy(&target->port, data + SIZE_IP, SIZE_PORT);
@@ -111,27 +116,27 @@ int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *n
111 if (!new_path || !nodes) 116 if (!new_path || !nodes)
112 return -1; 117 return -1;
113 118
114 encrypt_precompute(nodes[0].client_id, dht->self_secret_key, new_path->shared_key1); 119 encrypt_precompute(nodes[0].public_key, dht->self_secret_key, new_path->shared_key1);
115 memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES); 120 memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
116 121
117 uint8_t random_public_key[crypto_box_PUBLICKEYBYTES]; 122 uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
118 uint8_t random_secret_key[crypto_box_SECRETKEYBYTES]; 123 uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
119 124
120 crypto_box_keypair(random_public_key, random_secret_key); 125 crypto_box_keypair(random_public_key, random_secret_key);
121 encrypt_precompute(nodes[1].client_id, random_secret_key, new_path->shared_key2); 126 encrypt_precompute(nodes[1].public_key, random_secret_key, new_path->shared_key2);
122 memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES); 127 memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES);
123 128
124 crypto_box_keypair(random_public_key, random_secret_key); 129 crypto_box_keypair(random_public_key, random_secret_key);
125 encrypt_precompute(nodes[2].client_id, random_secret_key, new_path->shared_key3); 130 encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3);
126 memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES); 131 memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES);
127 132
128 new_path->ip_port1 = nodes[0].ip_port; 133 new_path->ip_port1 = nodes[0].ip_port;
129 new_path->ip_port2 = nodes[1].ip_port; 134 new_path->ip_port2 = nodes[1].ip_port;
130 new_path->ip_port3 = nodes[2].ip_port; 135 new_path->ip_port3 = nodes[2].ip_port;
131 136
132 memcpy(new_path->node_public_key1, nodes[0].client_id, crypto_box_PUBLICKEYBYTES); 137 memcpy(new_path->node_public_key1, nodes[0].public_key, crypto_box_PUBLICKEYBYTES);
133 memcpy(new_path->node_public_key2, nodes[1].client_id, crypto_box_PUBLICKEYBYTES); 138 memcpy(new_path->node_public_key2, nodes[1].public_key, crypto_box_PUBLICKEYBYTES);
134 memcpy(new_path->node_public_key3, nodes[2].client_id, crypto_box_PUBLICKEYBYTES); 139 memcpy(new_path->node_public_key3, nodes[2].public_key, crypto_box_PUBLICKEYBYTES);
135 140
136 return 0; 141 return 0;
137} 142}
@@ -150,9 +155,9 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_
150 nodes[1].ip_port = path->ip_port2; 155 nodes[1].ip_port = path->ip_port2;
151 nodes[2].ip_port = path->ip_port3; 156 nodes[2].ip_port = path->ip_port3;
152 157
153 memcpy(nodes[0].client_id, path->node_public_key1, crypto_box_PUBLICKEYBYTES); 158 memcpy(nodes[0].public_key, path->node_public_key1, crypto_box_PUBLICKEYBYTES);
154 memcpy(nodes[1].client_id, path->node_public_key2, crypto_box_PUBLICKEYBYTES); 159 memcpy(nodes[1].public_key, path->node_public_key2, crypto_box_PUBLICKEYBYTES);
155 memcpy(nodes[2].client_id, path->node_public_key3, crypto_box_PUBLICKEYBYTES); 160 memcpy(nodes[2].public_key, path->node_public_key3, crypto_box_PUBLICKEYBYTES);
156 return 0; 161 return 0;
157} 162}
158 163
@@ -186,7 +191,7 @@ int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion
186 int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1), 191 int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1),
187 step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); 192 step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES);
188 193
189 if ((uint32_t)len != SIZE_IPPORT + length + crypto_box_MACBYTES) 194 if (len != SIZE_IPPORT + length + crypto_box_MACBYTES)
190 return -1; 195 return -1;
191 196
192 uint8_t step3[SIZE_IPPORT + SEND_BASE * 2 + length]; 197 uint8_t step3[SIZE_IPPORT + SEND_BASE * 2 + length];
@@ -195,7 +200,7 @@ int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion
195 len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2), 200 len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2),
196 step3 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); 201 step3 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES);
197 202
198 if ((uint32_t)len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES) 203 if (len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES)
199 return -1; 204 return -1;
200 205
201 packet[0] = NET_PACKET_ONION_SEND_INITIAL; 206 packet[0] = NET_PACKET_ONION_SEND_INITIAL;
@@ -205,7 +210,7 @@ int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion
205 len = encrypt_data_symmetric(path->shared_key1, nonce, step3, sizeof(step3), 210 len = encrypt_data_symmetric(path->shared_key1, nonce, step3, sizeof(step3),
206 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); 211 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
207 212
208 if ((uint32_t)len != SIZE_IPPORT + SEND_BASE * 2 + length + crypto_box_MACBYTES) 213 if (len != SIZE_IPPORT + SEND_BASE * 2 + length + crypto_box_MACBYTES)
209 return -1; 214 return -1;
210 215
211 return 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + len; 216 return 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + len;
@@ -241,7 +246,7 @@ int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const O
241 int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1), 246 int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1),
242 step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); 247 step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES);
243 248
244 if ((uint32_t)len != SIZE_IPPORT + length + crypto_box_MACBYTES) 249 if (len != SIZE_IPPORT + length + crypto_box_MACBYTES)
245 return -1; 250 return -1;
246 251
247 ipport_pack(packet + crypto_box_NONCEBYTES, &path->ip_port2); 252 ipport_pack(packet + crypto_box_NONCEBYTES, &path->ip_port2);
@@ -249,7 +254,7 @@ int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const O
249 len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2), 254 len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2),
250 packet + crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); 255 packet + crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES);
251 256
252 if ((uint32_t)len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES) 257 if (len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES)
253 return -1; 258 return -1;
254 259
255 memcpy(packet, nonce, crypto_box_NONCEBYTES); 260 memcpy(packet, nonce, crypto_box_NONCEBYTES);
@@ -319,7 +324,7 @@ static int handle_send_initial(void *object, IP_Port source, const uint8_t *pack
319 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 324 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
320 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); 325 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain);
321 326
322 if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)) 327 if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES))
323 return 1; 328 return 1;
324 329
325 return onion_send_1(onion, plain, len, source, packet + 1); 330 return onion_send_1(onion, plain, len, source, packet + 1);
@@ -335,7 +340,7 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port
335 340
336 IP_Port send_to; 341 IP_Port send_to;
337 342
338 if (ipport_unpack(&send_to, plain, len) == -1) 343 if (ipport_unpack(&send_to, plain, len, 0) == -1)
339 return 1; 344 return 1;
340 345
341 uint8_t ip_port[SIZE_IPPORT]; 346 uint8_t ip_port[SIZE_IPPORT];
@@ -380,12 +385,12 @@ static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, ui
380 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 385 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
381 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); 386 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain);
382 387
383 if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES)) 388 if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES))
384 return 1; 389 return 1;
385 390
386 IP_Port send_to; 391 IP_Port send_to;
387 392
388 if (ipport_unpack(&send_to, plain, len) == -1) 393 if (ipport_unpack(&send_to, plain, len, 0) == -1)
389 return 1; 394 return 1;
390 395
391 uint8_t data[ONION_MAX_PACKET_SIZE]; 396 uint8_t data[ONION_MAX_PACKET_SIZE];
@@ -430,12 +435,12 @@ static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, ui
430 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 435 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
431 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); 436 length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain);
432 437
433 if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES)) 438 if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES))
434 return 1; 439 return 1;
435 440
436 IP_Port send_to; 441 IP_Port send_to;
437 442
438 if (ipport_unpack(&send_to, plain, len) == -1) 443 if (ipport_unpack(&send_to, plain, len, 0) == -1)
439 return 1; 444 return 1;
440 445
441 uint8_t data[ONION_MAX_PACKET_SIZE]; 446 uint8_t data[ONION_MAX_PACKET_SIZE];
@@ -482,7 +487,7 @@ static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, ui
482 487
483 IP_Port send_to; 488 IP_Port send_to;
484 489
485 if (ipport_unpack(&send_to, plain, len) == -1) 490 if (ipport_unpack(&send_to, plain, len, 0) == -1)
486 return 1; 491 return 1;
487 492
488 uint8_t data[ONION_MAX_PACKET_SIZE]; 493 uint8_t data[ONION_MAX_PACKET_SIZE];
@@ -518,7 +523,7 @@ static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, ui
518 523
519 IP_Port send_to; 524 IP_Port send_to;
520 525
521 if (ipport_unpack(&send_to, plain, len) == -1) 526 if (ipport_unpack(&send_to, plain, len, 0) == -1)
522 return 1; 527 return 1;
523 528
524 uint8_t data[ONION_MAX_PACKET_SIZE]; 529 uint8_t data[ONION_MAX_PACKET_SIZE];
@@ -554,7 +559,7 @@ static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, ui
554 559
555 IP_Port send_to; 560 IP_Port send_to;
556 561
557 if (ipport_unpack(&send_to, plain, len) == -1) 562 if (ipport_unpack(&send_to, plain, len, 1) == -1)
558 return 1; 563 return 1;
559 564
560 uint16_t data_len = length - (1 + RETURN_1); 565 uint16_t data_len = length - (1 + RETURN_1);
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c
index 32442797..25f3e0f8 100644
--- a/toxcore/onion_announce.c
+++ b/toxcore/onion_announce.c
@@ -134,7 +134,7 @@ int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_for
134 uint64_t sendback_data) 134 uint64_t sendback_data)
135{ 135{
136 uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE]; 136 uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];
137 int len = create_announce_request(request, sizeof(request), dest.client_id, public_key, secret_key, ping_id, client_id, 137 int len = create_announce_request(request, sizeof(request), dest.public_key, public_key, secret_key, ping_id, client_id,
138 data_public_key, sendback_data); 138 data_public_key, sendback_data);
139 139
140 if (len != sizeof(request)) 140 if (len != sizeof(request))
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index b02b7c24..61034167 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -38,7 +38,7 @@
38 * return -1 on failure 38 * return -1 on failure
39 * return 0 on success 39 * return 0 on success
40 */ 40 */
41int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *client_id) 41int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key)
42{ 42{
43 if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) 43 if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6)
44 return -1; 44 return -1;
@@ -46,12 +46,12 @@ int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t
46 unsigned int i; 46 unsigned int i;
47 47
48 for (i = 0; i < MAX_PATH_NODES; ++i) { 48 for (i = 0; i < MAX_PATH_NODES; ++i) {
49 if (memcmp(client_id, onion_c->path_nodes_bs[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) 49 if (memcmp(public_key, onion_c->path_nodes_bs[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
50 return -1; 50 return -1;
51 } 51 }
52 52
53 onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = ip_port; 53 onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = ip_port;
54 memcpy(onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].client_id, client_id, 54 memcpy(onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].public_key, public_key,
55 crypto_box_PUBLICKEYBYTES); 55 crypto_box_PUBLICKEYBYTES);
56 56
57 uint16_t last = onion_c->path_nodes_index_bs; 57 uint16_t last = onion_c->path_nodes_index_bs;
@@ -68,7 +68,7 @@ int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t
68 * return -1 on failure 68 * return -1 on failure
69 * return 0 on success 69 * return 0 on success
70 */ 70 */
71static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *client_id) 71static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key)
72{ 72{
73 if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) 73 if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6)
74 return -1; 74 return -1;
@@ -76,12 +76,13 @@ static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uin
76 unsigned int i; 76 unsigned int i;
77 77
78 for (i = 0; i < MAX_PATH_NODES; ++i) { 78 for (i = 0; i < MAX_PATH_NODES; ++i) {
79 if (memcmp(client_id, onion_c->path_nodes[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) 79 if (memcmp(public_key, onion_c->path_nodes[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
80 return -1; 80 return -1;
81 } 81 }
82 82
83 onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = ip_port; 83 onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = ip_port;
84 memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].client_id, client_id, crypto_box_PUBLICKEYBYTES); 84 memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].public_key, public_key,
85 crypto_box_PUBLICKEYBYTES);
85 86
86 uint16_t last = onion_c->path_nodes_index; 87 uint16_t last = onion_c->path_nodes_index;
87 ++onion_c->path_nodes_index; 88 ++onion_c->path_nodes_index;
@@ -140,8 +141,15 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format
140 nodes[i] = onion_c->path_nodes[rand() % num_nodes]; 141 nodes[i] = onion_c->path_nodes[rand() % num_nodes];
141 } 142 }
142 } else { 143 } else {
144 int random_tcp = get_random_tcp_con_number(onion_c->c);
145
146 if (random_tcp == -1) {
147 return 0;
148 }
149
143 if (num_nodes >= 2) { 150 if (num_nodes >= 2) {
144 nodes[0].ip_port.ip.family = TCP_FAMILY; 151 nodes[0].ip_port.ip.family = TCP_FAMILY;
152 nodes[0].ip_port.ip.ip4.uint32 = random_tcp;
145 153
146 for (i = 1; i < max_num; ++i) { 154 for (i = 1; i < max_num; ++i) {
147 nodes[i] = onion_c->path_nodes[rand() % num_nodes]; 155 nodes[i] = onion_c->path_nodes[rand() % num_nodes];
@@ -154,6 +162,7 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format
154 return 0; 162 return 0;
155 163
156 nodes[0].ip_port.ip.family = TCP_FAMILY; 164 nodes[0].ip_port.ip.family = TCP_FAMILY;
165 nodes[0].ip_port.ip.ip4.uint32 = random_tcp;
157 166
158 for (i = 1; i < max_num; ++i) { 167 for (i = 1; i < max_num; ++i) {
159 nodes[i] = onion_c->path_nodes_bs[rand() % num_nodes_bs]; 168 nodes[i] = onion_c->path_nodes_bs[rand() % num_nodes_bs];
@@ -249,9 +258,9 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t
249 Onion_Client_Paths *onion_paths; 258 Onion_Client_Paths *onion_paths;
250 259
251 if (num == 0) { 260 if (num == 0) {
252 onion_paths = &onion_c->onion_paths; 261 onion_paths = &onion_c->onion_paths_self;
253 } else { 262 } else {
254 onion_paths = &onion_c->friends_list[num - 1].onion_paths; 263 onion_paths = &onion_c->onion_paths_friends;
255 } 264 }
256 265
257 if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) { 266 if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) {
@@ -265,7 +274,7 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t
265 unsigned int i; 274 unsigned int i;
266 275
267 for (i = 0; i < path_len; ++i) { 276 for (i = 0; i < path_len; ++i) {
268 onion_add_path_node(onion_c, nodes[i].ip_port, nodes[i].client_id); 277 onion_add_path_node(onion_c, nodes[i].ip_port, nodes[i].public_key);
269 } 278 }
270 } 279 }
271 280
@@ -301,7 +310,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa
301 if (len == -1) 310 if (len == -1)
302 return -1; 311 return -1;
303 312
304 return send_tcp_onion_request(onion_c->c, packet, len); 313 return send_tcp_onion_request(onion_c->c, path->ip_port1.ip.ip4.uint32, packet, len);
305 } else { 314 } else {
306 return -1; 315 return -1;
307 } 316 }
@@ -377,10 +386,10 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
377 Onion_Path path; 386 Onion_Path path;
378 387
379 if (num == 0) { 388 if (num == 0) {
380 if (random_path(onion_c, &onion_c->onion_paths, pathnum, &path) == -1) 389 if (random_path(onion_c, &onion_c->onion_paths_self, pathnum, &path) == -1)
381 return -1; 390 return -1;
382 } else { 391 } else {
383 if (random_path(onion_c, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1) 392 if (random_path(onion_c, &onion_c->onion_paths_friends, pathnum, &path) == -1)
384 return -1; 393 return -1;
385 } 394 }
386 395
@@ -401,7 +410,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
401 410
402 } else { 411 } else {
403 len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->friends_list[num - 1].temp_public_key, 412 len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->friends_list[num - 1].temp_public_key,
404 onion_c->friends_list[num - 1].temp_secret_key, ping_id, onion_c->friends_list[num - 1].real_client_id, zero_ping_id, 413 onion_c->friends_list[num - 1].temp_secret_key, ping_id, onion_c->friends_list[num - 1].real_public_key, zero_ping_id,
405 sendback); 414 sendback);
406 } 415 }
407 416
@@ -430,7 +439,7 @@ static int cmp_entry(const void *a, const void *b)
430 if (t2) 439 if (t2)
431 return 1; 440 return 1;
432 441
433 int close = id_closest(cmp_public_key, entry1.client_id, entry2.client_id); 442 int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
434 443
435 if (close == 1) 444 if (close == 1)
436 return 1; 445 return 1;
@@ -463,7 +472,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
463 return -1; 472 return -1;
464 473
465 list_nodes = onion_c->friends_list[num - 1].clients_list; 474 list_nodes = onion_c->friends_list[num - 1].clients_list;
466 reference_id = onion_c->friends_list[num - 1].real_client_id; 475 reference_id = onion_c->friends_list[num - 1].real_public_key;
467 } 476 }
468 477
469 memcpy(cmp_public_key, reference_id, crypto_box_PUBLICKEYBYTES); 478 memcpy(cmp_public_key, reference_id, crypto_box_PUBLICKEYBYTES);
@@ -473,12 +482,12 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
473 unsigned int i; 482 unsigned int i;
474 483
475 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) 484 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
476 || id_closest(reference_id, list_nodes[0].client_id, public_key) == 2) { 485 || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) {
477 index = 0; 486 index = 0;
478 } 487 }
479 488
480 for (i = 0; i < MAX_ONION_CLIENTS; ++i) { 489 for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
481 if (memcmp(list_nodes[i].client_id, public_key, crypto_box_PUBLICKEYBYTES) == 0) { 490 if (memcmp(list_nodes[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
482 index = i; 491 index = i;
483 stored = 1; 492 stored = 1;
484 break; 493 break;
@@ -488,7 +497,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
488 if (index == -1) 497 if (index == -1)
489 return 0; 498 return 0;
490 499
491 memcpy(list_nodes[index].client_id, public_key, CLIENT_ID_SIZE); 500 memcpy(list_nodes[index].public_key, public_key, crypto_box_PUBLICKEYBYTES);
492 list_nodes[index].ip_port = ip_port; 501 list_nodes[index].ip_port = ip_port;
493 502
494 //TODO: remove this and find a better source of nodes to use for paths. 503 //TODO: remove this and find a better source of nodes to use for paths.
@@ -510,17 +519,17 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t
510 return 0; 519 return 0;
511} 520}
512 521
513static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *client_id) 522static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *public_key)
514{ 523{
515 unsigned int i; 524 unsigned int i;
516 525
517 for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) { 526 for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) {
518 if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME)) 527 if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME))
519 if (memcmp(last_pinged[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) 528 if (memcmp(last_pinged[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0)
520 return 0; 529 return 0;
521 } 530 }
522 531
523 memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].client_id, client_id, crypto_box_PUBLICKEYBYTES); 532 memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, crypto_box_PUBLICKEYBYTES);
524 last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time(); 533 last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time();
525 ++*last_pinged_index; 534 ++*last_pinged_index;
526 return 1; 535 return 1;
@@ -548,7 +557,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for
548 last_pinged_index = &onion_c->last_pinged_index; 557 last_pinged_index = &onion_c->last_pinged_index;
549 } else { 558 } else {
550 list_nodes = onion_c->friends_list[num - 1].clients_list; 559 list_nodes = onion_c->friends_list[num - 1].clients_list;
551 reference_id = onion_c->friends_list[num - 1].real_client_id; 560 reference_id = onion_c->friends_list[num - 1].real_public_key;
552 last_pinged = onion_c->friends_list[num - 1].last_pinged; 561 last_pinged = onion_c->friends_list[num - 1].last_pinged;
553 last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index; 562 last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index;
554 } 563 }
@@ -563,16 +572,16 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_for
563 continue; 572 continue;
564 573
565 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) 574 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
566 || id_closest(reference_id, list_nodes[0].client_id, nodes[i].client_id) == 2) { 575 || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2) {
567 /* check if node is already in list. */ 576 /* check if node is already in list. */
568 for (j = 0; j < MAX_ONION_CLIENTS; ++j) { 577 for (j = 0; j < MAX_ONION_CLIENTS; ++j) {
569 if (memcmp(list_nodes[j].client_id, nodes[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) { 578 if (memcmp(list_nodes[j].public_key, nodes[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
570 break; 579 break;
571 } 580 }
572 } 581 }
573 582
574 if (j == MAX_ONION_CLIENTS && good_to_ping(last_pinged, last_pinged_index, nodes[i].client_id)) { 583 if (j == MAX_ONION_CLIENTS && good_to_ping(last_pinged, last_pinged_index, nodes[i].public_key)) {
575 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0); 584 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, NULL, ~0);
576 } 585 }
577 } 586 }
578 } 587 }
@@ -670,17 +679,16 @@ static int handle_data_response(void *object, IP_Port source, const uint8_t *pac
670 sizeof(plain)); 679 sizeof(plain));
671} 680}
672 681
673#define FAKEID_DATA_ID 156 682#define DHTPK_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES)
674#define FAKEID_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES) 683#define DHTPK_DATA_MAX_LENGTH (DHTPK_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES)
675#define FAKEID_DATA_MAX_LENGTH (FAKEID_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES) 684static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length)
676static int handle_fakeid_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length)
677{ 685{
678 Onion_Client *onion_c = object; 686 Onion_Client *onion_c = object;
679 687
680 if (length < FAKEID_DATA_MIN_LENGTH) 688 if (length < DHTPK_DATA_MIN_LENGTH)
681 return 1; 689 return 1;
682 690
683 if (length > FAKEID_DATA_MAX_LENGTH) 691 if (length > DHTPK_DATA_MAX_LENGTH)
684 return 1; 692 return 1;
685 693
686 int friend_num = onion_friend_num(onion_c, source_pubkey); 694 int friend_num = onion_friend_num(onion_c, source_pubkey);
@@ -704,7 +712,7 @@ static int handle_fakeid_announce(void *object, const uint8_t *source_pubkey, co
704 onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t)); 712 onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t));
705 onion_c->friends_list[friend_num].last_seen = unix_time(); 713 onion_c->friends_list[friend_num].last_seen = unix_time();
706 714
707 uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH; 715 uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH;
708 716
709 if (len_nodes != 0) { 717 if (len_nodes != 0) {
710 Node_format nodes[MAX_SENT_NODES]; 718 Node_format nodes[MAX_SENT_NODES];
@@ -720,12 +728,12 @@ static int handle_fakeid_announce(void *object, const uint8_t *source_pubkey, co
720 uint8_t family = nodes[i].ip_port.ip.family; 728 uint8_t family = nodes[i].ip_port.ip.family;
721 729
722 if (family == AF_INET || family == AF_INET6) { 730 if (family == AF_INET || family == AF_INET6) {
723 DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); 731 DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key);
724 } else if (family == TCP_INET || family == TCP_INET6) { 732 } else if (family == TCP_INET || family == TCP_INET6) {
725 if (onion_c->friends_list[friend_num].tcp_relay_node_callback) { 733 if (onion_c->friends_list[friend_num].tcp_relay_node_callback) {
726 void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object; 734 void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
727 uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number; 735 uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number;
728 onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].client_id); 736 onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].public_key);
729 } 737 }
730 } 738 }
731 } 739 }
@@ -759,7 +767,7 @@ static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length)
759 * return the number of packets sent on success 767 * return the number of packets sent on success
760 * return -1 on failure. 768 * return -1 on failure.
761 */ 769 */
762int send_onion_data(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length) 770int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
763{ 771{
764 if ((uint32_t)friend_num >= onion_c->num_friends) 772 if ((uint32_t)friend_num >= onion_c->num_friends)
765 return -1; 773 return -1;
@@ -770,19 +778,7 @@ int send_onion_data(const Onion_Client *onion_c, int friend_num, const uint8_t *
770 if (length == 0) 778 if (length == 0)
771 return -1; 779 return -1;
772 780
773 uint8_t nonce[crypto_box_NONCEBYTES];
774 random_nonce(nonce);
775
776 uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length];
777 memcpy(packet, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES);
778 int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data,
779 length, packet + crypto_box_PUBLICKEYBYTES);
780
781 if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet))
782 return -1;
783
784 unsigned int i, good_nodes[MAX_ONION_CLIENTS], num_good = 0, num_nodes = 0; 781 unsigned int i, good_nodes[MAX_ONION_CLIENTS], num_good = 0, num_nodes = 0;
785 Onion_Path path[MAX_ONION_CLIENTS];
786 Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list; 782 Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
787 783
788 for (i = 0; i < MAX_ONION_CLIENTS; ++i) { 784 for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
@@ -792,9 +788,6 @@ int send_onion_data(const Onion_Client *onion_c, int friend_num, const uint8_t *
792 ++num_nodes; 788 ++num_nodes;
793 789
794 if (list_nodes[i].is_stored) { 790 if (list_nodes[i].is_stored) {
795 if (random_path(onion_c, &onion_c->friends_list[friend_num].onion_paths, ~0, &path[num_good]) == -1)
796 continue;
797
798 good_nodes[num_good] = i; 791 good_nodes[num_good] = i;
799 ++num_good; 792 ++num_good;
800 } 793 }
@@ -803,36 +796,52 @@ int send_onion_data(const Onion_Client *onion_c, int friend_num, const uint8_t *
803 if (num_good < (num_nodes / 4) + 1) 796 if (num_good < (num_nodes / 4) + 1)
804 return -1; 797 return -1;
805 798
799 uint8_t nonce[crypto_box_NONCEBYTES];
800 random_nonce(nonce);
801
802 uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length];
803 memcpy(packet, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES);
804 int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, onion_c->c->self_secret_key, nonce, data,
805 length, packet + crypto_box_PUBLICKEYBYTES);
806
807 if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet))
808 return -1;
809
806 unsigned int good = 0; 810 unsigned int good = 0;
807 811
808 for (i = 0; i < num_good; ++i) { 812 for (i = 0; i < num_good; ++i) {
813 Onion_Path path;
814
815 if (random_path(onion_c, &onion_c->onion_paths_friends, ~0, &path) == -1)
816 continue;
817
809 uint8_t o_packet[ONION_MAX_PACKET_SIZE]; 818 uint8_t o_packet[ONION_MAX_PACKET_SIZE];
810 len = create_data_request(o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_client_id, 819 len = create_data_request(o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
811 list_nodes[good_nodes[i]].data_public_key, nonce, packet, sizeof(packet)); 820 list_nodes[good_nodes[i]].data_public_key, nonce, packet, sizeof(packet));
812 821
813 if (len == -1) 822 if (len == -1)
814 continue; 823 continue;
815 824
816 if (send_onion_packet_tcp_udp(onion_c, &path[i], list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0) 825 if (send_onion_packet_tcp_udp(onion_c, &path, list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0)
817 ++good; 826 ++good;
818 } 827 }
819 828
820 return good; 829 return good;
821} 830}
822 831
823/* Try to send the fakeid via the DHT instead of onion 832/* Try to send the dht public key via the DHT instead of onion
824 * 833 *
825 * Even if this function succeeds, the friend might not receive any data. 834 * Even if this function succeeds, the friend might not receive any data.
826 * 835 *
827 * return the number of packets sent on success 836 * return the number of packets sent on success
828 * return -1 on failure. 837 * return -1 on failure.
829 */ 838 */
830static int send_dht_fakeid(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length) 839static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
831{ 840{
832 if ((uint32_t)friend_num >= onion_c->num_friends) 841 if ((uint32_t)friend_num >= onion_c->num_friends)
833 return -1; 842 return -1;
834 843
835 if (!onion_c->friends_list[friend_num].is_fake_clientid) 844 if (!onion_c->friends_list[friend_num].know_dht_public_key)
836 return -1; 845 return -1;
837 846
838 uint8_t nonce[crypto_box_NONCEBYTES]; 847 uint8_t nonce[crypto_box_NONCEBYTES];
@@ -841,7 +850,7 @@ static int send_dht_fakeid(const Onion_Client *onion_c, int friend_num, const ui
841 uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length]; 850 uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length];
842 memcpy(temp, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES); 851 memcpy(temp, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES);
843 memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); 852 memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
844 int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data, 853 int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, onion_c->c->self_secret_key, nonce, data,
845 length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); 854 length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
846 855
847 if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp)) 856 if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp))
@@ -849,37 +858,37 @@ static int send_dht_fakeid(const Onion_Client *onion_c, int friend_num, const ui
849 858
850 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; 859 uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
851 len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet, 860 len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet,
852 onion_c->friends_list[friend_num].fake_client_id, temp, sizeof(temp), FAKEID_DATA_ID); 861 onion_c->friends_list[friend_num].dht_public_key, temp, sizeof(temp), CRYPTO_PACKET_FAKEID);
853 862
854 if (len == -1) 863 if (len == -1)
855 return -1; 864 return -1;
856 865
857 return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, packet, len); 866 return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, packet, len);
858} 867}
859 868
860static int handle_dht_fakeid(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet, 869static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
861 uint16_t length) 870 uint16_t length)
862{ 871{
863 Onion_Client *onion_c = object; 872 Onion_Client *onion_c = object;
864 873
865 if (length < FAKEID_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES) 874 if (length < DHTPK_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)
866 return 1; 875 return 1;
867 876
868 if (length > FAKEID_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES) 877 if (length > DHTPK_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)
869 return 1; 878 return 1;
870 879
871 uint8_t plain[FAKEID_DATA_MAX_LENGTH]; 880 uint8_t plain[DHTPK_DATA_MAX_LENGTH];
872 int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES, 881 int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES,
873 packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, 882 packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
874 length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain); 883 length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain);
875 884
876 if ((uint32_t)len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)) 885 if (len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES))
877 return 1; 886 return 1;
878 887
879 if (memcmp(source_pubkey, plain + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES) != 0) 888 if (memcmp(source_pubkey, plain + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES) != 0)
880 return 1; 889 return 1;
881 890
882 return handle_fakeid_announce(onion_c, packet, plain, len); 891 return handle_dhtpk_announce(onion_c, packet, plain, len);
883} 892}
884/* Send the packets to tell our friends what our DHT public key is. 893/* Send the packets to tell our friends what our DHT public key is.
885 * 894 *
@@ -890,13 +899,13 @@ static int handle_dht_fakeid(void *object, IP_Port source, const uint8_t *source
890 * return the number of packets sent on success 899 * return the number of packets sent on success
891 * return -1 on failure. 900 * return -1 on failure.
892 */ 901 */
893static int send_fakeid_announce(const Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both) 902static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both)
894{ 903{
895 if (friend_num >= onion_c->num_friends) 904 if (friend_num >= onion_c->num_friends)
896 return -1; 905 return -1;
897 906
898 uint8_t data[FAKEID_DATA_MAX_LENGTH]; 907 uint8_t data[DHTPK_DATA_MAX_LENGTH];
899 data[0] = FAKEID_DATA_ID; 908 data[0] = ONION_DATA_DHTPK;
900 uint64_t no_replay = unix_time(); 909 uint64_t no_replay = unix_time();
901 host_to_net((uint8_t *)&no_replay, sizeof(no_replay)); 910 host_to_net((uint8_t *)&no_replay, sizeof(no_replay));
902 memcpy(data + 1, &no_replay, sizeof(no_replay)); 911 memcpy(data + 1, &no_replay, sizeof(no_replay));
@@ -908,7 +917,7 @@ static int send_fakeid_announce(const Onion_Client *onion_c, uint16_t friend_num
908 int nodes_len = 0; 917 int nodes_len = 0;
909 918
910 if (num_nodes != 0) { 919 if (num_nodes != 0) {
911 nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes, 920 nodes_len = pack_nodes(data + DHTPK_DATA_MIN_LENGTH, DHTPK_DATA_MAX_LENGTH - DHTPK_DATA_MIN_LENGTH, nodes,
912 num_nodes); 921 num_nodes);
913 922
914 if (nodes_len <= 0) 923 if (nodes_len <= 0)
@@ -918,10 +927,10 @@ static int send_fakeid_announce(const Onion_Client *onion_c, uint16_t friend_num
918 int num1 = -1, num2 = -1; 927 int num1 = -1, num2 = -1;
919 928
920 if (onion_dht_both != 1) 929 if (onion_dht_both != 1)
921 num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); 930 num1 = send_onion_data(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
922 931
923 if (onion_dht_both != 0) 932 if (onion_dht_both != 0)
924 num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); 933 num2 = send_dht_dhtpk(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
925 934
926 if (num1 == -1) 935 if (num1 == -1)
927 return num2; 936 return num2;
@@ -937,7 +946,7 @@ static int send_fakeid_announce(const Onion_Client *onion_c, uint16_t friend_num
937 * return -1 on failure. 946 * return -1 on failure.
938 * return friend number on success. 947 * return friend number on success.
939 */ 948 */
940int onion_friend_num(const Onion_Client *onion_c, const uint8_t *client_id) 949int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key)
941{ 950{
942 unsigned int i; 951 unsigned int i;
943 952
@@ -945,7 +954,7 @@ int onion_friend_num(const Onion_Client *onion_c, const uint8_t *client_id)
945 if (onion_c->friends_list[i].status == 0) 954 if (onion_c->friends_list[i].status == 0)
946 continue; 955 continue;
947 956
948 if (memcmp(client_id, onion_c->friends_list[i].real_client_id, crypto_box_PUBLICKEYBYTES) == 0) 957 if (memcmp(public_key, onion_c->friends_list[i].real_public_key, crypto_box_PUBLICKEYBYTES) == 0)
949 return i; 958 return i;
950 } 959 }
951 960
@@ -979,9 +988,9 @@ static int realloc_onion_friends(Onion_Client *onion_c, uint32_t num)
979 * return -1 on failure. 988 * return -1 on failure.
980 * return the friend number on success or if the friend was already added. 989 * return the friend number on success or if the friend was already added.
981 */ 990 */
982int onion_addfriend(Onion_Client *onion_c, const uint8_t *client_id) 991int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key)
983{ 992{
984 int num = onion_friend_num(onion_c, client_id); 993 int num = onion_friend_num(onion_c, public_key);
985 994
986 if (num != -1) 995 if (num != -1)
987 return num; 996 return num;
@@ -1005,7 +1014,7 @@ int onion_addfriend(Onion_Client *onion_c, const uint8_t *client_id)
1005 } 1014 }
1006 1015
1007 onion_c->friends_list[index].status = 1; 1016 onion_c->friends_list[index].status = 1;
1008 memcpy(onion_c->friends_list[index].real_client_id, client_id, crypto_box_PUBLICKEYBYTES); 1017 memcpy(onion_c->friends_list[index].real_public_key, public_key, crypto_box_PUBLICKEYBYTES);
1009 crypto_box_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key); 1018 crypto_box_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key);
1010 return index; 1019 return index;
1011} 1020}
@@ -1020,8 +1029,8 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num)
1020 if ((uint32_t)friend_num >= onion_c->num_friends) 1029 if ((uint32_t)friend_num >= onion_c->num_friends)
1021 return -1; 1030 return -1;
1022 1031
1023 //if (onion_c->friends_list[friend_num].is_fake_clientid) 1032 //if (onion_c->friends_list[friend_num].know_dht_public_key)
1024 // DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, 0); 1033 // DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, 0);
1025 1034
1026 memset(&(onion_c->friends_list[friend_num]), 0, sizeof(Onion_Friend)); 1035 memset(&(onion_c->friends_list[friend_num]), 0, sizeof(Onion_Friend));
1027 unsigned int i; 1036 unsigned int i;
@@ -1092,17 +1101,17 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uin
1092 if (onion_c->friends_list[friend_num].status == 0) 1101 if (onion_c->friends_list[friend_num].status == 0)
1093 return -1; 1102 return -1;
1094 1103
1095 if (onion_c->friends_list[friend_num].is_fake_clientid) { 1104 if (onion_c->friends_list[friend_num].know_dht_public_key) {
1096 if (memcmp(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) == 0) { 1105 if (memcmp(dht_key, onion_c->friends_list[friend_num].dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
1097 return -1; 1106 return -1;
1098 } 1107 }
1099 1108
1100 onion_c->friends_list[friend_num].is_fake_clientid = 0; 1109 onion_c->friends_list[friend_num].know_dht_public_key = 0;
1101 } 1110 }
1102 1111
1103 onion_c->friends_list[friend_num].last_seen = unix_time(); 1112 onion_c->friends_list[friend_num].last_seen = unix_time();
1104 onion_c->friends_list[friend_num].is_fake_clientid = 1; 1113 onion_c->friends_list[friend_num].know_dht_public_key = 1;
1105 memcpy(onion_c->friends_list[friend_num].fake_client_id, dht_key, crypto_box_PUBLICKEYBYTES); 1114 memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, crypto_box_PUBLICKEYBYTES);
1106 1115
1107 return 0; 1116 return 0;
1108} 1117}
@@ -1120,18 +1129,18 @@ unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_
1120 if (onion_c->friends_list[friend_num].status == 0) 1129 if (onion_c->friends_list[friend_num].status == 0)
1121 return 0; 1130 return 0;
1122 1131
1123 if (!onion_c->friends_list[friend_num].is_fake_clientid) 1132 if (!onion_c->friends_list[friend_num].know_dht_public_key)
1124 return 0; 1133 return 0;
1125 1134
1126 memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES); 1135 memcpy(dht_key, onion_c->friends_list[friend_num].dht_public_key, crypto_box_PUBLICKEYBYTES);
1127 return 1; 1136 return 1;
1128} 1137}
1129 1138
1130/* Get the ip of friend friendnum and put it in ip_port 1139/* Get the ip of friend friendnum and put it in ip_port
1131 * 1140 *
1132 * return -1, -- if client_id does NOT refer to a friend 1141 * return -1, -- if public_key does NOT refer to a friend
1133 * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) 1142 * return 0, -- if public_key refers to a friend and we failed to find the friend (yet)
1134 * return 1, ip if client_id refers to a friend and we found him 1143 * return 1, ip if public_key refers to a friend and we found him
1135 * 1144 *
1136 */ 1145 */
1137int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port) 1146int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
@@ -1176,15 +1185,15 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
1176static void populate_path_nodes(Onion_Client *onion_c) 1185static void populate_path_nodes(Onion_Client *onion_c)
1177{ 1186{
1178 Node_format nodes_list[MAX_SENT_NODES]; 1187 Node_format nodes_list[MAX_SENT_NODES];
1179 uint8_t client_id[crypto_box_PUBLICKEYBYTES]; 1188 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
1180 uint32_t random_num = rand(); 1189 uint32_t random_num = rand();
1181 memcpy(client_id, &random_num, sizeof(random_num)); 1190 memcpy(public_key, &random_num, sizeof(random_num));
1182 1191
1183 unsigned int num_nodes = get_close_nodes(onion_c->dht, client_id, nodes_list, (rand() % 2) ? AF_INET : AF_INET6, 1, 0); 1192 unsigned int num_nodes = get_close_nodes(onion_c->dht, public_key, nodes_list, (rand() % 2) ? AF_INET : AF_INET6, 1, 0);
1184 unsigned int i; 1193 unsigned int i;
1185 1194
1186 for (i = 0; i < num_nodes; ++i) { 1195 for (i = 0; i < num_nodes; ++i) {
1187 onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].client_id); 1196 onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
1188 } 1197 }
1189} 1198}
1190 1199
@@ -1196,7 +1205,7 @@ static void populate_path_nodes_tcp(Onion_Client *onion_c)
1196 unsigned int i; 1205 unsigned int i;
1197 1206
1198 for (i = 0; i < num_nodes; ++i) { 1207 for (i = 0; i < num_nodes; ++i) {
1199 onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].client_id); 1208 onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
1200 } 1209 }
1201} 1210}
1202 1211
@@ -1236,7 +1245,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1236 } 1245 }
1237 1246
1238 if (is_timeout(list_nodes[i].last_pinged, interval)) { 1247 if (is_timeout(list_nodes[i].last_pinged, interval)) {
1239 if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) { 1248 if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].public_key, 0, ~0) == 0) {
1240 list_nodes[i].last_pinged = unix_time(); 1249 list_nodes[i].last_pinged = unix_time();
1241 } 1250 }
1242 } 1251 }
@@ -1256,7 +1265,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1256 for (j = 0; j < n; ++j) { 1265 for (j = 0; j < n; ++j) {
1257 unsigned int num = rand() % num_nodes; 1266 unsigned int num = rand() % num_nodes;
1258 client_send_announce_request(onion_c, friendnum + 1, onion_c->path_nodes[num].ip_port, 1267 client_send_announce_request(onion_c, friendnum + 1, onion_c->path_nodes[num].ip_port,
1259 onion_c->path_nodes[num].client_id, 0, ~0); 1268 onion_c->path_nodes[num].public_key, 0, ~0);
1260 } 1269 }
1261 1270
1262 ++onion_c->friends_list[friendnum].run_count; 1271 ++onion_c->friends_list[friendnum].run_count;
@@ -1265,14 +1274,14 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1265 ++onion_c->friends_list[friendnum].run_count; 1274 ++onion_c->friends_list[friendnum].run_count;
1266 } 1275 }
1267 1276
1268 /* send packets to friend telling them our fake DHT id. */ 1277 /* send packets to friend telling them our DHT public key. */
1269 if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_onion_sent, ONION_FAKEID_INTERVAL)) 1278 if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_onion_sent, ONION_DHTPK_SEND_INTERVAL))
1270 if (send_fakeid_announce(onion_c, friendnum, 0) >= 1) 1279 if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1)
1271 onion_c->friends_list[friendnum].last_fakeid_onion_sent = unix_time(); 1280 onion_c->friends_list[friendnum].last_dht_pk_onion_sent = unix_time();
1272 1281
1273 if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_dht_sent, DHT_FAKEID_INTERVAL)) 1282 if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_dht_sent, DHT_DHTPK_SEND_INTERVAL))
1274 if (send_fakeid_announce(onion_c, friendnum, 1) >= 1) 1283 if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1)
1275 onion_c->friends_list[friendnum].last_fakeid_dht_sent = unix_time(); 1284 onion_c->friends_list[friendnum].last_dht_pk_dht_sent = unix_time();
1276 1285
1277 } 1286 }
1278} 1287}
@@ -1312,7 +1321,7 @@ static void do_announce(Onion_Client *onion_c)
1312 } 1321 }
1313 1322
1314 if (is_timeout(list_nodes[i].last_pinged, interval)) { 1323 if (is_timeout(list_nodes[i].last_pinged, interval)) {
1315 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id, 1324 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key,
1316 list_nodes[i].ping_id, list_nodes[i].path_used) == 0) { 1325 list_nodes[i].ping_id, list_nodes[i].path_used) == 0) {
1317 list_nodes[i].last_pinged = unix_time(); 1326 list_nodes[i].last_pinged = unix_time();
1318 } 1327 }
@@ -1335,7 +1344,7 @@ static void do_announce(Onion_Client *onion_c)
1335 if (num_nodes != 0) { 1344 if (num_nodes != 0) {
1336 for (i = 0; i < (MAX_ONION_CLIENTS / 2); ++i) { 1345 for (i = 0; i < (MAX_ONION_CLIENTS / 2); ++i) {
1337 unsigned int num = rand() % num_nodes; 1346 unsigned int num = rand() % num_nodes;
1338 client_send_announce_request(onion_c, 0, path_nodes[num].ip_port, path_nodes[num].client_id, 0, ~0); 1347 client_send_announce_request(onion_c, 0, path_nodes[num].ip_port, path_nodes[num].public_key, 0, ~0);
1339 } 1348 }
1340 } 1349 }
1341 } 1350 }
@@ -1386,8 +1395,8 @@ Onion_Client *new_onion_client(Net_Crypto *c)
1386 crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key); 1395 crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
1387 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c); 1396 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
1388 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c); 1397 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
1389 oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c); 1398 oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c);
1390 cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c); 1399 cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_FAKEID, &handle_dht_dhtpk, onion_c);
1391 tcp_onion_response_handler(onion_c->c, &handle_tcp_onion, onion_c); 1400 tcp_onion_response_handler(onion_c->c, &handle_tcp_onion, onion_c);
1392 1401
1393 return onion_c; 1402 return onion_c;
@@ -1402,8 +1411,8 @@ void kill_onion_client(Onion_Client *onion_c)
1402 realloc_onion_friends(onion_c, 0); 1411 realloc_onion_friends(onion_c, 0);
1403 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); 1412 networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL);
1404 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); 1413 networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL);
1405 oniondata_registerhandler(onion_c, FAKEID_DATA_ID, NULL, NULL); 1414 oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, NULL, NULL);
1406 cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, NULL, NULL); 1415 cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_FAKEID, NULL, NULL);
1407 tcp_onion_response_handler(onion_c->c, NULL, NULL); 1416 tcp_onion_response_handler(onion_c->c, NULL, NULL);
1408 memset(onion_c, 0, sizeof(Onion_Client)); 1417 memset(onion_c, 0, sizeof(Onion_Client));
1409 free(onion_c); 1418 free(onion_c);
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h
index fe586c5b..b4e7a1b7 100644
--- a/toxcore/onion_client.h
+++ b/toxcore/onion_client.h
@@ -33,8 +33,8 @@
33#define ONION_NODE_TIMEOUT (ONION_NODE_PING_INTERVAL * 3) 33#define ONION_NODE_TIMEOUT (ONION_NODE_PING_INTERVAL * 3)
34 34
35/* The interval in seconds at which to tell our friends where we are */ 35/* The interval in seconds at which to tell our friends where we are */
36#define ONION_FAKEID_INTERVAL 30 36#define ONION_DHTPK_SEND_INTERVAL 30
37#define DHT_FAKEID_INTERVAL 20 37#define DHT_DHTPK_SEND_INTERVAL 20
38 38
39#define NUMBER_ONION_PATHS 6 39#define NUMBER_ONION_PATHS 6
40 40
@@ -55,8 +55,12 @@
55 */ 55 */
56#define ONION_OFFLINE_TIMEOUT (ONION_NODE_PING_INTERVAL * 1.25) 56#define ONION_OFFLINE_TIMEOUT (ONION_NODE_PING_INTERVAL * 1.25)
57 57
58/* Onion data packet ids. */
59#define ONION_DATA_FRIEND_REQ CRYPTO_PACKET_FRIEND_REQ
60#define ONION_DATA_DHTPK CRYPTO_PACKET_FAKEID
61
58typedef struct { 62typedef struct {
59 uint8_t client_id[CLIENT_ID_SIZE]; 63 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
60 IP_Port ip_port; 64 IP_Port ip_port;
61 uint8_t ping_id[ONION_PING_ID_SIZE]; 65 uint8_t ping_id[ONION_PING_ID_SIZE];
62 uint8_t data_public_key[crypto_box_PUBLICKEYBYTES]; 66 uint8_t data_public_key[crypto_box_PUBLICKEYBYTES];
@@ -79,7 +83,7 @@ typedef struct {
79} Onion_Client_Paths; 83} Onion_Client_Paths;
80 84
81typedef struct { 85typedef struct {
82 uint8_t client_id[CLIENT_ID_SIZE]; 86 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
83 uint64_t timestamp; 87 uint64_t timestamp;
84} Last_Pinged; 88} Last_Pinged;
85 89
@@ -87,23 +91,21 @@ typedef struct {
87 uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/ 91 uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
88 uint8_t is_online; /* Set by the onion_set_friend_status function. */ 92 uint8_t is_online; /* Set by the onion_set_friend_status function. */
89 93
90 uint8_t is_fake_clientid; /* 0 if we don't know the fake client id of the other 1 if we do. */ 94 uint8_t know_dht_public_key; /* 0 if we don't know the dht public key of the other, 1 if we do. */
91 uint8_t fake_client_id[crypto_box_PUBLICKEYBYTES]; 95 uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES];
92 uint8_t real_client_id[crypto_box_PUBLICKEYBYTES]; 96 uint8_t real_public_key[crypto_box_PUBLICKEYBYTES];
93 97
94 Onion_Node clients_list[MAX_ONION_CLIENTS]; 98 Onion_Node clients_list[MAX_ONION_CLIENTS];
95 uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES]; 99 uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES];
96 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; 100 uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
97 101
98 uint64_t last_fakeid_onion_sent; 102 uint64_t last_dht_pk_onion_sent;
99 uint64_t last_fakeid_dht_sent; 103 uint64_t last_dht_pk_dht_sent;
100 104
101 uint64_t last_noreplay; 105 uint64_t last_noreplay;
102 106
103 uint64_t last_seen; 107 uint64_t last_seen;
104 108
105 Onion_Client_Paths onion_paths;
106
107 Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; 109 Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
108 uint8_t last_pinged_index; 110 uint8_t last_pinged_index;
109 111
@@ -130,7 +132,8 @@ typedef struct {
130 132
131 Onion_Node clients_announce_list[MAX_ONION_CLIENTS]; 133 Onion_Node clients_announce_list[MAX_ONION_CLIENTS];
132 134
133 Onion_Client_Paths onion_paths; 135 Onion_Client_Paths onion_paths_self;
136 Onion_Client_Paths onion_paths_friends;
134 137
135 uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; 138 uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
136 uint64_t last_run; 139 uint64_t last_run;
@@ -162,7 +165,7 @@ typedef struct {
162 * return -1 on failure 165 * return -1 on failure
163 * return 0 on success 166 * return 0 on success
164 */ 167 */
165int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *client_id); 168int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key);
166 169
167/* Put up to max_num nodes in nodes. 170/* Put up to max_num nodes in nodes.
168 * 171 *
@@ -175,14 +178,14 @@ uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uin
175 * return -1 on failure. 178 * return -1 on failure.
176 * return the friend number on success or if the friend was already added. 179 * return the friend number on success or if the friend was already added.
177 */ 180 */
178int onion_friend_num(const Onion_Client *onion_c, const uint8_t *client_id); 181int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key);
179 182
180/* Add a friend who we want to connect to. 183/* Add a friend who we want to connect to.
181 * 184 *
182 * return -1 on failure. 185 * return -1 on failure.
183 * return the friend number on success. 186 * return the friend number on success.
184 */ 187 */
185int onion_addfriend(Onion_Client *onion_c, const uint8_t *client_id); 188int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key);
186 189
187/* Delete a friend. 190/* Delete a friend.
188 * 191 *
@@ -204,9 +207,9 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
204 207
205/* Get the ip of friend friendnum and put it in ip_port 208/* Get the ip of friend friendnum and put it in ip_port
206 * 209 *
207 * return -1, -- if client_id does NOT refer to a friend 210 * return -1, -- if public_key does NOT refer to a friend
208 * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) 211 * return 0, -- if public_key refers to a friend and we failed to find the friend (yet)
209 * return 1, ip if client_id refers to a friend and we found him 212 * return 1, ip if public_key refers to a friend and we found him
210 * 213 *
211 */ 214 */
212int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port); 215int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
@@ -262,7 +265,7 @@ unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_
262 * return the number of packets sent on success 265 * return the number of packets sent on success
263 * return -1 on failure. 266 * return -1 on failure.
264 */ 267 */
265int send_onion_data(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length); 268int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length);
266 269
267/* Function to call when onion data packet with contents beginning with byte is received. */ 270/* Function to call when onion data packet with contents beginning with byte is received. */
268void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object); 271void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object);
diff --git a/toxcore/ping.c b/toxcore/ping.c
index a29c1a12..1c3564a3 100644
--- a/toxcore/ping.c
+++ b/toxcore/ping.c
@@ -269,12 +269,12 @@ int add_to_ping(PING *ping, const uint8_t *client_id, IP_Port ip_port)
269 269
270 for (i = 0; i < MAX_TO_PING; ++i) { 270 for (i = 0; i < MAX_TO_PING; ++i) {
271 if (!ip_isset(&ping->to_ping[i].ip_port.ip)) { 271 if (!ip_isset(&ping->to_ping[i].ip_port.ip)) {
272 memcpy(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE); 272 memcpy(ping->to_ping[i].public_key, client_id, CLIENT_ID_SIZE);
273 ipport_copy(&ping->to_ping[i].ip_port, &ip_port); 273 ipport_copy(&ping->to_ping[i].ip_port, &ip_port);
274 return 0; 274 return 0;
275 } 275 }
276 276
277 if (memcmp(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 277 if (memcmp(ping->to_ping[i].public_key, client_id, CLIENT_ID_SIZE) == 0) {
278 return -1; 278 return -1;
279 } 279 }
280 } 280 }
@@ -282,8 +282,8 @@ int add_to_ping(PING *ping, const uint8_t *client_id, IP_Port ip_port)
282 uint32_t r = rand(); 282 uint32_t r = rand();
283 283
284 for (i = 0; i < MAX_TO_PING; ++i) { 284 for (i = 0; i < MAX_TO_PING; ++i) {
285 if (id_closest(ping->dht->self_public_key, ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id) == 2) { 285 if (id_closest(ping->dht->self_public_key, ping->to_ping[(i + r) % MAX_TO_PING].public_key, client_id) == 2) {
286 memcpy(ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id, CLIENT_ID_SIZE); 286 memcpy(ping->to_ping[(i + r) % MAX_TO_PING].public_key, client_id, CLIENT_ID_SIZE);
287 ipport_copy(&ping->to_ping[(i + r) % MAX_TO_PING].ip_port, &ip_port); 287 ipport_copy(&ping->to_ping[(i + r) % MAX_TO_PING].ip_port, &ip_port);
288 return 0; 288 return 0;
289 } 289 }
@@ -311,7 +311,7 @@ void do_to_ping(PING *ping)
311 if (!ip_isset(&ping->to_ping[i].ip_port.ip)) 311 if (!ip_isset(&ping->to_ping[i].ip_port.ip))
312 return; 312 return;
313 313
314 send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].client_id); 314 send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key);
315 ip_reset(&ping->to_ping[i].ip_port.ip); 315 ip_reset(&ping->to_ping[i].ip_port.ip);
316 } 316 }
317} 317}
diff --git a/toxcore/tox.c b/toxcore/tox.c
index a4a73838..82beb561 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -36,7 +36,7 @@ typedef struct Messenger Tox;
36 36
37/* 37/*
38 * returns a FRIEND_ADDRESS_SIZE byte address to give to others. 38 * returns a FRIEND_ADDRESS_SIZE byte address to give to others.
39 * Format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] 39 * Format: [public_key (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
40 * 40 *
41 */ 41 */
42void tox_get_address(const Tox *tox, uint8_t *address) 42void tox_get_address(const Tox *tox, uint8_t *address)
@@ -73,31 +73,31 @@ int32_t tox_add_friend(Tox *tox, const uint8_t *address, const uint8_t *data, ui
73 * return the friend number if success. 73 * return the friend number if success.
74 * return -1 if failure. 74 * return -1 if failure.
75 */ 75 */
76int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *client_id) 76int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *public_key)
77{ 77{
78 Messenger *m = tox; 78 Messenger *m = tox;
79 return m_addfriend_norequest(m, client_id); 79 return m_addfriend_norequest(m, public_key);
80} 80}
81 81
82/* return the friend number associated to that client id. 82/* return the friend number associated to that client id.
83 * return -1 if no such friend. 83 * return -1 if no such friend.
84 */ 84 */
85int32_t tox_get_friend_number(const Tox *tox, const uint8_t *client_id) 85int32_t tox_get_friend_number(const Tox *tox, const uint8_t *public_key)
86{ 86{
87 const Messenger *m = tox; 87 const Messenger *m = tox;
88 return getfriend_id(m, client_id); 88 return getfriend_id(m, public_key);
89} 89}
90 90
91/* Copies the public key associated to that friend id into client_id buffer. 91/* Copies the public key associated to that friend id into public_key buffer.
92 * Make sure that client_id is of size CLIENT_ID_SIZE. 92 * Make sure that public_key is of size crypto_box_PUBLICKEYBYTES.
93 * 93 *
94 * return 0 if success. 94 * return 0 if success.
95 * return -1 if failure. 95 * return -1 if failure.
96 */ 96 */
97int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *client_id) 97int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *public_key)
98{ 98{
99 const Messenger *m = tox; 99 const Messenger *m = tox;
100 return getclient_id(m, friendnumber, client_id); 100 return get_real_pk(m, friendnumber, public_key);
101} 101}
102 102
103/* Remove a friend. */ 103/* Remove a friend. */
@@ -643,16 +643,16 @@ int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t
643 return group_peername(m->group_chat_object, groupnumber, peernumber, name); 643 return group_peername(m->group_chat_object, groupnumber, peernumber, name);
644} 644}
645 645
646/* Copy the public key of peernumber who is in groupnumber to pk. 646/* Copy the public key of peernumber who is in groupnumber to public_key.
647 * pk must be TOX_CLIENT_ID_SIZE long. 647 * public_key must be crypto_box_PUBLICKEYBYTES long.
648 * 648 *
649 * returns 0 on success 649 * returns 0 on success
650 * returns -1 on failure 650 * returns -1 on failure
651 */ 651 */
652int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *pk) 652int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *public_key)
653{ 653{
654 const Messenger *m = tox; 654 const Messenger *m = tox;
655 return group_peer_pubkey(m->group_chat_object, groupnumber, peernumber, pk); 655 return group_peer_pubkey(m->group_chat_object, groupnumber, peernumber, public_key);
656} 656}
657 657
658/* invite friendnumber to groupnumber 658/* invite friendnumber to groupnumber
@@ -1012,8 +1012,8 @@ uint32_t tox_do_interval(Tox *tox)
1012 */ 1012 */
1013Tox *tox_new(Tox_Options *options) 1013Tox *tox_new(Tox_Options *options)
1014{ 1014{
1015 logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore")); 1015 if (!logger_get_global())
1016 1016 logger_set_global(logger_new(LOGGER_OUTPUT_FILE, LOGGER_LEVEL, "toxcore"));
1017 1017
1018 Messenger_Options m_options = {0}; 1018 Messenger_Options m_options = {0};
1019 1019
diff --git a/toxcore/tox.h b/toxcore/tox.h
index db1b1033..ee678cc1 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -38,11 +38,14 @@ extern "C" {
38#define TOX_MAX_STATUSMESSAGE_LENGTH 1007 38#define TOX_MAX_STATUSMESSAGE_LENGTH 1007
39#define TOX_MAX_FRIENDREQUEST_LENGTH 1016 39#define TOX_MAX_FRIENDREQUEST_LENGTH 1016
40 40
41#define TOX_CLIENT_ID_SIZE 32 41#define TOX_PUBLIC_KEY_SIZE 32
42/* TODO: remove */
43#define TOX_CLIENT_ID_SIZE TOX_PUBLIC_KEY_SIZE
44
42#define TOX_AVATAR_MAX_DATA_LENGTH 16384 45#define TOX_AVATAR_MAX_DATA_LENGTH 16384
43#define TOX_HASH_LENGTH /*crypto_hash_sha256_BYTES*/ 32 46#define TOX_HASH_LENGTH /*crypto_hash_sha256_BYTES*/ 32
44 47
45#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) 48#define TOX_FRIEND_ADDRESS_SIZE (TOX_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
46 49
47#define TOX_ENABLE_IPV6_DEFAULT 1 50#define TOX_ENABLE_IPV6_DEFAULT 1
48 51
@@ -97,7 +100,7 @@ typedef struct Tox Tox;
97 */ 100 */
98 101
99/* return TOX_FRIEND_ADDRESS_SIZE byte address to give to others. 102/* return TOX_FRIEND_ADDRESS_SIZE byte address to give to others.
100 * format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] 103 * format: [public_key (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
101 */ 104 */
102void tox_get_address(const Tox *tox, uint8_t *address); 105void tox_get_address(const Tox *tox, uint8_t *address);
103 106
@@ -124,18 +127,18 @@ int32_t tox_add_friend(Tox *tox, const uint8_t *address, const uint8_t *data, ui
124 * return the friend number if success. 127 * return the friend number if success.
125 * return -1 if failure. 128 * return -1 if failure.
126 */ 129 */
127int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *client_id); 130int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *public_key);
128 131
129/* return the friend number associated to that client id. 132/* return the friend number associated to that client id.
130 return -1 if no such friend */ 133 return -1 if no such friend */
131int32_t tox_get_friend_number(const Tox *tox, const uint8_t *client_id); 134int32_t tox_get_friend_number(const Tox *tox, const uint8_t *public_key);
132 135
133/* Copies the public key associated to that friend id into client_id buffer. 136/* Copies the public key associated to that friend id into public_key buffer.
134 * Make sure that client_id is of size CLIENT_ID_SIZE. 137 * Make sure that public_key is of size TOX_PUBLIC_KEY_SIZE.
135 * return 0 if success. 138 * return 0 if success.
136 * return -1 if failure. 139 * return -1 if failure.
137 */ 140 */
138int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *client_id); 141int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *public_key);
139 142
140/* Remove a friend. 143/* Remove a friend.
141 * 144 *
@@ -500,13 +503,13 @@ int tox_del_groupchat(Tox *tox, int groupnumber);
500 */ 503 */
501int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name); 504int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name);
502 505
503/* Copy the public key of peernumber who is in groupnumber to pk. 506/* Copy the public key of peernumber who is in groupnumber to public_key.
504 * pk must be TOX_CLIENT_ID_SIZE long. 507 * public_key must be TOX_PUBLIC_KEY_SIZE long.
505 * 508 *
506 * returns 0 on success 509 * returns 0 on success
507 * returns -1 on failure 510 * returns -1 on failure
508 */ 511 */
509int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *pk); 512int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *public_key);
510 513
511/* invite friendnumber to groupnumber 514/* invite friendnumber to groupnumber
512 * return 0 on success 515 * return 0 on success
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c
index b6453a89..9172f512 100644
--- a/toxencryptsave/toxencryptsave.c
+++ b/toxencryptsave/toxencryptsave.c
@@ -121,7 +121,7 @@ int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *sa
121 /* note that, according to the documentation, a generic pwhash interface will be created 121 /* note that, according to the documentation, a generic pwhash interface will be created
122 * once the pwhash competition (https://password-hashing.net/) is over */ 122 * once the pwhash competition (https://password-hashing.net/) is over */
123 if (crypto_pwhash_scryptsalsa208sha256( 123 if (crypto_pwhash_scryptsalsa208sha256(
124 key, sizeof(key), passkey, sizeof(passkey), salt, 124 key, sizeof(key), (char *)passkey, sizeof(passkey), salt,
125 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ 125 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
126 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { 126 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
127 /* out of memory most likely */ 127 /* out of memory most likely */
@@ -280,7 +280,7 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase,
280 280
281 if (crypto_pwhash_scryptsalsa208sha256( 281 if (crypto_pwhash_scryptsalsa208sha256(
282 key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, 282 key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
283 crypto_box_KEYBYTES, passkey, sizeof(passkey), salt, 283 crypto_box_KEYBYTES, (char *)passkey, sizeof(passkey), salt,
284 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ 284 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
285 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { 285 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
286 /* out of memory most likely */ 286 /* out of memory most likely */