diff --git a/.travis.yml b/.travis.yml
index c90a92f2b..ef9bdcb36 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -32,7 +32,7 @@ before_script:
- sudo make install > /dev/null
- cd ..
#installing vpx
- - git clone http://git.chromium.org/webm/libvpx.git > /dev/null
+ - git clone https://chromium.googlesource.com/webm/libvpx > /dev/null
- cd libvpx
- ./configure --enable-shared > /dev/null
- make -j3 >/dev/null
diff --git a/README.md b/README.md
index 67a877c1b..1844fbd5c 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,8 @@
With 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.
-[**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) **|**
-[**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)
+[**Website**](http://utox.org) **|** [**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) **|**
+[**API**](https://libtoxcore.so/) **|** **IRC Channel:** [#tox@freenode](https://webchat.freenode.net/?channels=tox)
## The Complex Stuff:
@@ -39,5 +39,3 @@ The goal of this project is to create a configuration-free P2P Skype replacement
- [Crypto](/docs/updates/Crypto.md)
Additional developer documentation can be found at [Libtoxcore.so](https://libtoxcore.so/)
-
-[String]: https://en.wikipedia.org/wiki/String_(computer_science)
diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c
index 501c93dc7..fa1d43e1b 100644
--- a/auto_tests/tox_test.c
+++ b/auto_tests/tox_test.c
@@ -286,6 +286,16 @@ void tox_connection_status(Tox *tox, TOX_CONNECTION connection_status, void *use
START_TEST(test_one)
{
+ {
+ TOX_ERR_OPTIONS_NEW o_err;
+ struct Tox_Options *o1 = tox_options_new(&o_err);
+ struct Tox_Options o2;
+ tox_options_default(&o2);
+ ck_assert_msg(o_err == TOX_ERR_OPTIONS_NEW_OK, "tox_options_new wrong error");
+ ck_assert_msg(memcmp(o1, &o2, sizeof(struct Tox_Options)) == 0, "tox_options_new error");
+ tox_options_free(o1);
+ }
+
Tox *tox1 = tox_new(0, 0);
Tox *tox2 = tox_new(0, 0);
@@ -468,6 +478,44 @@ START_TEST(test_few_clients)
printf("tox clients messaging succeeded\n");
+ unsigned int save_size1 = tox_get_savedata_size(tox2);
+ ck_assert_msg(save_size1 != 0 && save_size1 < 4096, "save is invalid size %u", save_size1);
+ printf("%u\n", save_size1);
+ uint8_t save1[save_size1];
+ tox_get_savedata(tox2, save1);
+ tox_kill(tox2);
+
+ struct Tox_Options options;
+ tox_options_default(&options);
+ options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
+ options.savedata_data = save1;
+ options.savedata_length = save_size1;
+ tox2 = tox_new(&options, NULL);
+ cur_time = time(NULL);
+ off = 1;
+
+ while (1) {
+ tox_iterate(tox1);
+ tox_iterate(tox2);
+ tox_iterate(tox3);
+
+ if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
+ && tox_self_get_connection_status(tox3)) {
+ if (off) {
+ printf("Toxes are online again after reloading, took %llu seconds\n", time(NULL) - cur_time);
+ con_time = time(NULL);
+ off = 0;
+ }
+
+ if (tox_friend_get_connection_status(tox2, 0, 0) == TOX_CONNECTION_UDP
+ && tox_friend_get_connection_status(tox3, 0, 0) == TOX_CONNECTION_UDP)
+ break;
+ }
+
+ c_sleep(50);
+ }
+
+ printf("tox clients connected took %llu seconds\n", time(NULL) - con_time);
tox_callback_friend_name(tox3, print_nickchange, &to_compare);
TOX_ERR_SET_INFO err_n;
bool succ = tox_self_set_name(tox2, (uint8_t *)"Gentoo", sizeof("Gentoo"), &err_n);
@@ -785,6 +833,14 @@ START_TEST(test_many_clients)
uint8_t address[TOX_ADDRESS_SIZE];
+ unsigned int num_f = 0;
+
+ for (i = 0; i < NUM_TOXES; ++i) {
+ num_f += tox_self_get_friend_list_size(toxes[i]);
+ }
+
+ ck_assert_msg(num_f == 0, "bad num friends: %u", num_f);
+
for (i = 0; i < NUM_FRIENDS; ++i) {
loop_top:
pairs[i].tox1 = rand() % NUM_TOXES;
@@ -807,6 +863,12 @@ loop_top:
ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
}
+ for (i = 0; i < NUM_TOXES; ++i) {
+ num_f += tox_self_get_friend_list_size(toxes[i]);
+ }
+
+ ck_assert_msg(num_f == NUM_FRIENDS, "bad num friends: %u", num_f);
+
while (1) {
uint16_t counter = 0;
@@ -1210,7 +1272,7 @@ Suite *tox_suite(void)
Suite *s = suite_create("Tox");
DEFTESTCASE(one);
- DEFTESTCASE_SLOW(few_clients, 50);
+ DEFTESTCASE_SLOW(few_clients, 80);
DEFTESTCASE_SLOW(many_clients, 80);
DEFTESTCASE_SLOW(many_clients_tcp, 20);
DEFTESTCASE_SLOW(many_clients_tcp_b, 20);
diff --git a/other/apidsl/README.md b/other/apidsl/README.md
index 0b3e776db..3c194df53 100644
--- a/other/apidsl/README.md
+++ b/other/apidsl/README.md
@@ -1,11 +1,49 @@
-This folder contains the input file that can be used to generate the tox.h api
-with: https://github.com/iphydf/apidsl
+This folder contains the input file (``tox.in.h``) that has to be used to generate the ``tox.h`` api with: https://github.com/iphydf/apidsl
-You can also use the following command if you can't install it:
+# Minimal requirements
-```
-curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl < tox.in.h > tox.h
+There are some minimal requirements to contribute to ``tox.h``:
+* unix environment
+* ``astyle`` ``>=2.03``
+* [``apidsl``](https://github.com/iphydf/apidsl) (you can use provided service with curl instead)
+
+## Quick way
+
+If you want to do it quickly and you don't have time for anything other than copypasting commands, you should have ``curl`` installed.
+
+
+1. Make sure that you have ``curl`` and ``>=astyle-2.03`` installed
+2. Modify [``tox.in.h``](/other/apidsl/tox.in.h)
+3. Run command below ↓
+
+Command to run from ``toxcore`` directory (quick way, involves using curl):
+```bash
+rm toxcore/tox.h && \
+( curl -X POST --data-binary @- https://criticism.herokuapp.com/apidsl < ./other/apidsl/tox.in.h > ./toxcore/tox.h ) && \
+astyle --options=./other/astyle/astylerc ./toxcore/tox.h
```
-Note that the output must be passed through astyle with the config in
-other/astyle/astylerc to generate the exact same file.
+When formatting will be complete, you should see output like:
+```
+Formatted ./toxcore/tox.h
+```
+
+You may want to make sure with ``git diff`` that changes made in ``tox.h`` reflect changes in ``tox.in.h``.
+
+And you're done.
+
+
+## Manually
+
+If you prefer to have more control over what is happening, there are steps below:
+
+1. Install [``apidsl``](https://github.com/iphydf/apidsl)
+2. Install ``astyle``, version 2.03 or later.
+3. Modify [``tox.in.h``](/other/apidsl/tox.in.h)
+4. Use ``apidsl`` ``??``
+5. Parse generated ``tox.h`` with astyle, minimal command for it would be:
+```bash
+astyle --options=./other/astyle/astylerc ./toxcore/tox.h
+```
+
+**Always pass output from ``apidsl`` through astyle.**
\ No newline at end of file
diff --git a/other/apidsl/tox.in.h b/other/apidsl/tox.in.h
index 30c78e445..4a0ab9509 100644
--- a/other/apidsl/tox.in.h
+++ b/other/apidsl/tox.in.h
@@ -34,6 +34,14 @@ extern "C" {
#endif
%}
+
+/*****************************************************************************
+ * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to *
+ * `tox.in.h`, located in `other/apidsl/`. For instructions on how to *
+ * generate `tox.h` from `tox.in.h` please refer to `other/apidsl/README.md` *
+ *****************************************************************************/
+
+
/** \page core Public core API for Tox clients.
*
* Every function that can fail takes a function-specific error code pointer
@@ -431,7 +439,15 @@ static class options {
uint16_t end_port;
/**
- * The port to use for the TCP server. If 0, the tcp server is disabled.
+ * The port to use for the TCP server (relay). If 0, the TCP server is
+ * disabled.
+ *
+ * Enabling it is not required for Tox to function properly.
+ *
+ * When enabled, your Tox instance can act as a TCP relay for other Tox
+ * instance. This leads to increased traffic, thus when writing a client
+ * it is recommended to enable TCP server only if the user has an option
+ * to disable it.
*/
uint16_t tcp_port;
diff --git a/other/astyle/README b/other/astyle/README
deleted file mode 100644
index 26802ec73..000000000
--- a/other/astyle/README
+++ /dev/null
@@ -1,11 +0,0 @@
-This directory can house various tools and utilities.
-
-astylerc
- - This file can be used in the precommit hook to try its best
- at making the code conform to the coding style document.
-
-pre-commit (*NIX only at the moment)
- - Lints your file in adherence to the coding style doucment as
- best as possible in terms of spacing, indenting, etc.
- - Requires you to have astyle installed.
- - To use, copy this file to ProjectTox-Core/.git/hooks
diff --git a/other/astyle/README.md b/other/astyle/README.md
new file mode 100644
index 000000000..f68edf68f
--- /dev/null
+++ b/other/astyle/README.md
@@ -0,0 +1,32 @@
+This directory can house various tools and utilities.
+
+# How to use astyle
+
+## Manually
+
+### For all files
+
+Run from ``toxcore`` directory:
+```bash
+astyle --options=./other/astyle/astylerc ./toxcore/*.c ./toxcore/*.h ./toxdns/*.c ./toxdns/*.h ./testing/*.c ./toxav/*.c ./toxav/*.h ./other/*.c ./other/bootstrap_daemon/*.c ./toxencryptsave/*.c ./toxencryptsave/*.h ./auto_tests/*.c
+```
+
+### For selected file
+
+Run from ``toxcore`` directory, e.g. for [``tox.h``](/toxcore/tox.h) file:
+```bash
+astyle --options=./other/astyle/astylerc ./toxcore/tox.h
+```
+
+
+## Automatically, as pre-commit hook (*NIX only)
+
+Copy [``astylerc``](/other/astyle/astylerc) to ``toxcore/.git/hooks``
+
+
+
+# Why
+
+``astylerc`` - this file can be used in the pre-commit hook to try its best at making the code conform to the coding style of toxcore.
+
+Furthermore, it is being used to format ``tox.h`` after using [``apidsl``](/other/apidsl) to generate it.
\ No newline at end of file
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 8cd8852c0..2236fe61b 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -47,7 +47,7 @@
#include "util.h"
/* The timeout after which a node is discarded completely. */
-#define KILL_NODE_TIMEOUT 300
+#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
/* Ping interval in seconds for each random sending of a get nodes request. */
#define GET_NODE_INTERVAL 20
@@ -2244,18 +2244,17 @@ DHT *new_DHT(Networking_Core *net)
void do_DHT(DHT *dht)
{
- // Load friends/clients if first call to do_DHT
- if (dht->has_loaded_friends_clients == 0) {
- dht->has_loaded_friends_clients = 1;
- DHT_connect_after_load(dht);
- }
-
unix_time_update();
if (dht->last_run == unix_time()) {
return;
}
+ // Load friends/clients if first call to do_DHT
+ if (dht->loaded_num_nodes) {
+ DHT_connect_after_load(dht);
+ }
+
do_Close(dht);
do_DHT_friends(dht);
do_NAT(dht);
@@ -2282,33 +2281,37 @@ void kill_DHT(DHT *dht)
ping_array_free_all(&dht->dht_harden_ping_array);
kill_ping(dht->ping);
free(dht->friends_list);
- free(dht->loaded_friends_list);
- free(dht->loaded_clients_list);
+ free(dht->loaded_nodes_list);
free(dht);
}
/* new DHT format for load/save, more robust and forward compatible */
-
+//TODO: Move this closer to Messenger.
#define DHT_STATE_COOKIE_GLOBAL 0x159000d
#define DHT_STATE_COOKIE_TYPE 0x11ce
-#define DHT_STATE_TYPE_FRIENDS_ASSOC46 3
-#define DHT_STATE_TYPE_CLIENTS_ASSOC46 4
+#define DHT_STATE_TYPE_NODES 4
/* Get the size of the DHT (for saving). */
uint32_t DHT_size(const DHT *dht)
{
- uint32_t num = 0, i;
+ uint32_t num = 0, i, j;
- for (i = 0; i < LCLIENT_LIST; ++i)
- if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
- (dht->close_clientlist[i].assoc6.timestamp != 0))
- num++;
+ for (i = 0; i < LCLIENT_LIST; ++i) {
+ num += (dht->close_clientlist[i].assoc4.timestamp != 0) + (dht->close_clientlist[i].assoc6.timestamp != 0);
+ }
+
+ for (i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
+ DHT_Friend *fr = &dht->friends_list[i];
+
+ for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
+ num += (fr->client_list[j].assoc4.timestamp != 0) + (fr->client_list[j].assoc6.timestamp != 0);
+ }
+ }
uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
return size32
- + sizesubhead + sizeof(DHT_Friend) * dht->num_friends
- + sizesubhead + sizeof(Client_data) * num;
+ + sizesubhead + sizeof(Node_format) * num;
}
static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
@@ -2323,97 +2326,80 @@ static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t typ
/* Save the DHT in data where data is an array of size DHT_size(). */
void DHT_save(DHT *dht, uint8_t *data)
{
- uint32_t len;
- uint16_t type;
*(uint32_t *)data = DHT_STATE_COOKIE_GLOBAL;
data += sizeof(uint32_t);
- len = sizeof(DHT_Friend) * dht->num_friends;
- type = DHT_STATE_TYPE_FRIENDS_ASSOC46;
- data = z_state_save_subheader(data, len, type);
- memcpy(data, dht->friends_list, len);
- data += len;
+ uint32_t num, i, j;
- uint32_t num = 0, i;
+ uint8_t *old_data = data;
- for (i = 0; i < LCLIENT_LIST; ++i)
- if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
- (dht->close_clientlist[i].assoc6.timestamp != 0))
- num++;
+ /* get right offset. we write the actual header later. */
+ data = z_state_save_subheader(data, 0, 0);
- len = num * sizeof(Client_data);
- type = DHT_STATE_TYPE_CLIENTS_ASSOC46;
- data = z_state_save_subheader(data, len, type);
+ Node_format *clients = (Node_format *)data;
- if (num) {
- Client_data *clients = (Client_data *)data;
+ for (num = 0, i = 0; i < LCLIENT_LIST; ++i) {
+ if (dht->close_clientlist[i].assoc4.timestamp != 0) {
+ memcpy(clients[num].public_key, dht->close_clientlist[i].client_id, crypto_box_PUBLICKEYBYTES);
+ clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port;
+ ++num;
+ }
- for (num = 0, i = 0; i < LCLIENT_LIST; ++i)
- if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
- (dht->close_clientlist[i].assoc6.timestamp != 0))
- memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data));
- }
-}
-
-static void DHT_bootstrap_loaded_clients(DHT *dht)
-{
- if (!dht->loaded_clients_list)
- return;
-
- uint32_t i;
-
- Client_data *client_list = dht->loaded_clients_list;
- uint32_t client_count = dht->loaded_num_clients;
-
- for (i = 0; i < client_count; ++i) {
- if (client_list[i].assoc4.timestamp != 0)
- DHT_bootstrap(dht, client_list[i].assoc4.ip_port, client_list[i].client_id);
-
- if (client_list[i].assoc6.timestamp != 0)
- DHT_bootstrap(dht, client_list[i].assoc6.ip_port, client_list[i].client_id);
- }
-}
-
-static void getnodes_of_loaded_friend_clients(DHT *dht)
-{
- if (!dht->loaded_friends_list)
- return;
-
- uint32_t i, j;
-
- DHT_Friend *friend_list = dht->loaded_friends_list;
- uint32_t friend_count = dht->loaded_num_friends;
-
- for (i = 0; i < friend_count; ++i) {
- for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
- Client_data *client = &friend_list[i].client_list[j];
-
- if (client->assoc4.timestamp != 0)
- getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id, NULL);
-
- if (client->assoc6.timestamp != 0)
- getnodes(dht, client->assoc6.ip_port, client->client_id, friend_list[i].client_id, NULL);
+ if (dht->close_clientlist[i].assoc6.timestamp != 0) {
+ memcpy(clients[num].public_key, dht->close_clientlist[i].client_id, crypto_box_PUBLICKEYBYTES);
+ clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port;
+ ++num;
}
}
+
+ for (i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
+ DHT_Friend *fr = &dht->friends_list[i];
+
+ for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
+ if (fr->client_list[j].assoc4.timestamp != 0) {
+ memcpy(clients[num].public_key, fr->client_list[j].client_id, crypto_box_PUBLICKEYBYTES);
+ clients[num].ip_port = fr->client_list[j].assoc4.ip_port;
+ ++num;
+ }
+
+ if (fr->client_list[j].assoc6.timestamp != 0) {
+ memcpy(clients[num].public_key, fr->client_list[j].client_id, crypto_box_PUBLICKEYBYTES);
+ clients[num].ip_port = fr->client_list[j].assoc6.ip_port;
+ ++num;
+ }
+ }
+ }
+
+ z_state_save_subheader(old_data, num * sizeof(Node_format), DHT_STATE_TYPE_NODES);
}
+/* Bootstrap from this number of nodes every time DHT_connect_after_load() is called */
+#define SAVE_BOOTSTAP_FREQUENCY 8
+
/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */
int DHT_connect_after_load(DHT *dht)
{
if (dht == NULL)
return -1;
- getnodes_of_loaded_friend_clients(dht);
- DHT_bootstrap_loaded_clients(dht);
+ if (!dht->loaded_nodes_list)
+ return -1;
- // Loaded lists were allocd, free them
- free(dht->loaded_friends_list);
- dht->loaded_friends_list = NULL;
- dht->loaded_num_friends = 0;
+ /* DHT is connected, stop. */
+ if (DHT_non_lan_connected(dht)) {
+ free(dht->loaded_nodes_list);
+ dht->loaded_nodes_list = NULL;
+ dht->loaded_num_nodes = 0;
+ return 0;
+ }
- free(dht->loaded_clients_list);
- dht->loaded_clients_list = NULL;
- dht->loaded_num_clients = 0;
+ unsigned int i;
+
+ for (i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {
+ unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
+ DHT_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);
+ ++dht->loaded_nodes_index;
+ }
return 0;
}
@@ -2424,46 +2410,23 @@ static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t le
uint32_t num, i;
switch (type) {
- case DHT_STATE_TYPE_FRIENDS_ASSOC46:
- if (length % sizeof(DHT_Friend) != 0)
+ case DHT_STATE_TYPE_NODES:
+ if ((length % sizeof(Node_format)) != 0)
break;
{ /* localize declarations */
- DHT_Friend *friend_list = (DHT_Friend *)data;
- num = length / sizeof(DHT_Friend);
+ num = length / sizeof(Node_format);
+ Node_format *client_list = (Node_format *)data;
- free(dht->loaded_friends_list);
- // Copy to loaded_friends_list
- dht->loaded_friends_list = calloc(num, sizeof(DHT_Friend));
-
- for (i = 0; i < num; i++)
- memcpy(&(dht->loaded_friends_list[i]), &(friend_list[i]), sizeof(DHT_Friend));
-
- dht->loaded_num_friends = num;
-
- dht->has_loaded_friends_clients = 1;
- } /* localize declarations */
-
- break;
-
- case DHT_STATE_TYPE_CLIENTS_ASSOC46:
- if ((length % sizeof(Client_data)) != 0)
- break;
-
- { /* localize declarations */
- num = length / sizeof(Client_data);
- Client_data *client_list = (Client_data *)data;
-
- free(dht->loaded_clients_list);
+ free(dht->loaded_nodes_list);
// Copy to loaded_clients_list
- dht->loaded_clients_list = calloc(num, sizeof(Client_data));
+ dht->loaded_nodes_list = calloc(num, sizeof(Node_format));
for (i = 0; i < num; i++)
- memcpy(&(dht->loaded_clients_list[i]), &(client_list[i]), sizeof(Client_data));
+ memcpy(&(dht->loaded_nodes_list[i]), &(client_list[i]), sizeof(Node_format));
- dht->loaded_num_clients = num;
+ dht->loaded_num_nodes = num;
- dht->has_loaded_friends_clients = 1;
} /* localize declarations */
break;
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index 318a60022..c612c287f 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -211,13 +211,9 @@ typedef struct {
DHT_Friend *friends_list;
uint16_t num_friends;
- // Used after loading of file (tox_load), but no longer needed after connect (tox_connect)
- // Unsure if friends_list and num_friends could just be used instead?
- int has_loaded_friends_clients; // Whether or not we have loaded on the first do_DHT
- DHT_Friend *loaded_friends_list;
- uint32_t loaded_num_friends;
- Client_data *loaded_clients_list;
- uint32_t loaded_num_clients;
+ Node_format *loaded_nodes_list;
+ uint32_t loaded_num_nodes;
+ unsigned int loaded_nodes_index;
Shared_Keys shared_keys_recv;
Shared_Keys shared_keys_sent;
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 4d4b82c1f..381ee7371 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1103,7 +1103,7 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_
int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber,
uint8_t control_type, uint8_t *data, uint16_t data_length)
{
- if (1 + 3 + data_length > MAX_CRYPTO_DATA_SIZE)
+ if ((unsigned int)(1 + 3 + data_length) > MAX_CRYPTO_DATA_SIZE)
return -1;
uint8_t packet[3 + data_length];
@@ -1435,7 +1435,7 @@ static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber)
}
/* TODO: if file is too slow, switch to the next. */
- if (ft->slots_allocated > free_slots) {
+ if (ft->slots_allocated > (unsigned int)free_slots) {
free_slots = 0;
} else {
free_slots -= ft->slots_allocated;
diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c
index b0b26d209..d26a60de1 100644
--- a/toxcore/TCP_connection.c
+++ b/toxcore/TCP_connection.c
@@ -691,7 +691,7 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec
uint8_t relay_pk[crypto_box_PUBLICKEYBYTES];
memcpy(relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES);
kill_TCP_connection(tcp_con->connection);
- tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->dht->self_public_key, tcp_c->dht->self_secret_key,
+ tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key,
&tcp_c->proxy_info);
if (!tcp_con->connection) {
@@ -776,8 +776,8 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti
if (tcp_con->status != TCP_CONN_SLEEPING)
return -1;
- tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->dht->self_public_key,
- tcp_c->dht->self_secret_key, &tcp_c->proxy_info);
+ tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key,
+ tcp_c->self_secret_key, &tcp_c->proxy_info);
if (!tcp_con->connection) {
kill_tcp_relay_connection(tcp_c, tcp_connections_number);
@@ -1025,7 +1025,7 @@ static int add_tcp_relay(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t
TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number];
- tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->dht->self_public_key, tcp_c->dht->self_secret_key,
+ tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key,
&tcp_c->proxy_info);
if (!tcp_con->connection)
@@ -1237,9 +1237,9 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status)
return 0;
}
-TCP_Connections *new_tcp_connections(DHT *dht, TCP_Proxy_Info *proxy_info)
+TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info)
{
- if (dht == NULL)
+ if (secret_key == NULL)
return NULL;
TCP_Connections *temp = calloc(1, sizeof(TCP_Connections));
@@ -1247,7 +1247,8 @@ TCP_Connections *new_tcp_connections(DHT *dht, TCP_Proxy_Info *proxy_info)
if (temp == NULL)
return NULL;
- temp->dht = dht;
+ memcpy(temp->self_secret_key, secret_key, crypto_box_SECRETKEYBYTES);
+ crypto_scalarmult_curve25519_base(temp->self_public_key, temp->self_secret_key);
temp->proxy_info = *proxy_info;
return temp;
diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h
index 29fbdee06..140d6de35 100644
--- a/toxcore/TCP_connection.h
+++ b/toxcore/TCP_connection.h
@@ -81,6 +81,9 @@ typedef struct {
typedef struct {
DHT *dht;
+ uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
+ uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
+
TCP_Connection_to *connections;
uint32_t connections_length; /* Length of connections array. */
@@ -223,7 +226,7 @@ int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t
*/
unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num);
-TCP_Connections *new_tcp_connections(DHT *dht, TCP_Proxy_Info *proxy_info);
+TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info);
void do_tcp_connections(TCP_Connections *tcp_c);
void kill_tcp_connections(TCP_Connections *tcp_c);
diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c
index 418edcad7..d1549b2ac 100644
--- a/toxcore/crypto_core.c
+++ b/toxcore/crypto_core.c
@@ -235,26 +235,26 @@ int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_ke
int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
uint8_t *request_id, const uint8_t *packet, uint16_t length)
{
- if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES &&
- length <= MAX_CRYPTO_REQUEST_SIZE) {
- if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
- memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
- uint8_t nonce[crypto_box_NONCEBYTES];
- uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
- memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES);
- int len1 = decrypt_data(public_key, self_secret_key, nonce,
- packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
- length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp);
+ if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES ||
+ length > MAX_CRYPTO_REQUEST_SIZE)
+ return -1;
- if (len1 == -1 || len1 == 0)
- return -1;
+ if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) != 0)
+ return -1;
- request_id[0] = temp[0];
- --len1;
- memcpy(data, temp + 1, len1);
- return len1;
- }
- }
+ memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
+ uint8_t nonce[crypto_box_NONCEBYTES];
+ uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
+ memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES);
+ int len1 = decrypt_data(public_key, self_secret_key, nonce,
+ packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
+ length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp);
- return -1;
+ if (len1 == -1 || len1 == 0)
+ return -1;
+
+ request_id[0] = temp[0];
+ --len1;
+ memcpy(data, temp + 1, len1);
+ return len1;
}
diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c
index 1656def00..04deaf81c 100644
--- a/toxcore/friend_connection.c
+++ b/toxcore/friend_connection.c
@@ -220,7 +220,7 @@ static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)
n = copy_connected_tcp_relays(fr_c->net_crypto, nodes, MAX_SHARED_RELAYS);
- unsigned int i;
+ int i;
for (i = 0; i < n; ++i) {
/* Associated the relays being sent with this connection.
diff --git a/toxcore/group.c b/toxcore/group.c
index af2cb4920..2eadaf742 100644
--- a/toxcore/group.c
+++ b/toxcore/group.c
@@ -1514,7 +1514,7 @@ static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *d
const uint8_t *d = data;
- while ((length - (d - data)) >= sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2 + 1) {
+ while ((unsigned int)(length - (d - data)) >= sizeof(uint16_t) + crypto_box_PUBLICKEYBYTES * 2 + 1) {
uint16_t peer_num;
memcpy(&peer_num, d, sizeof(peer_num));
peer_num = ntohs(peer_num);
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index 96be059de..a826f77ad 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -659,7 +659,8 @@ static int generate_request_packet(uint8_t *data, uint16_t length, const Packets
* return -1 on failure.
* return number of requested packets on success.
*/
-static int handle_request_packet(Packets_Array *send_array, const uint8_t *data, uint16_t length)
+static int handle_request_packet(Packets_Array *send_array, const uint8_t *data, uint16_t length,
+ uint64_t *latest_send_time, uint64_t rtt_time)
{
if (length < 1)
return -1;
@@ -677,6 +678,7 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
uint32_t requested = 0;
uint64_t temp_time = current_time_monotonic();
+ uint64_t l_sent_time = ~0;
for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) {
if (length == 0)
@@ -688,7 +690,7 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
if (send_array->buffer[num]) {
uint64_t sent_time = send_array->buffer[num]->sent_time;
- if ((sent_time + DEFAULT_PING_CONNECTION) < temp_time) {
+ if ((sent_time + rtt_time) < temp_time) {
send_array->buffer[num]->sent_time = 0;
}
}
@@ -698,6 +700,11 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
n = 0;
++requested;
} else {
+ uint64_t sent_time = send_array->buffer[num]->sent_time;
+
+ if (l_sent_time < sent_time)
+ l_sent_time = sent_time;
+
free(send_array->buffer[num]);
send_array->buffer[num] = NULL;
}
@@ -715,6 +722,9 @@ static int handle_request_packet(Packets_Array *send_array, const uint8_t *data,
}
}
+ if (*latest_send_time < l_sent_time)
+ *latest_send_time = l_sent_time;
+
return requested;
}
@@ -1146,8 +1156,19 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
buffer_start = ntohl(buffer_start);
num = ntohl(num);
- if (buffer_start != conn->send_array.buffer_start && clear_buffer_until(&conn->send_array, buffer_start) != 0)
- return -1;
+ uint64_t rtt_calc_time = 0;
+
+ if (buffer_start != conn->send_array.buffer_start) {
+ Packet_Data *packet_time;
+
+ if (get_data_pointer(&conn->send_array, &packet_time, conn->send_array.buffer_start) == 1) {
+ rtt_calc_time = packet_time->sent_time;
+ }
+
+ if (clear_buffer_until(&conn->send_array, buffer_start) != 0) {
+ return -1;
+ }
+ }
uint8_t *real_data = data + (sizeof(uint32_t) * 2);
uint16_t real_length = len - (sizeof(uint32_t) * 2);
@@ -1174,7 +1195,7 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
}
if (real_data[0] == PACKET_ID_REQUEST) {
- int requested = handle_request_packet(&conn->send_array, real_data, real_length);
+ int requested = handle_request_packet(&conn->send_array, real_data, real_length, &rtt_calc_time, conn->rtt_time);
if (requested == -1) {
return -1;
@@ -1226,6 +1247,13 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, con
return -1;
}
+ if (rtt_calc_time != 0) {
+ uint64_t rtt_time = current_time_monotonic() - rtt_calc_time;
+
+ if (rtt_time < conn->rtt_time)
+ conn->rtt_time = rtt_time;
+ }
+
return 0;
}
@@ -1580,6 +1608,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c)
memcpy(conn->dht_public_key, n_c->dht_public_key, crypto_box_PUBLICKEYBYTES);
conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
+ conn->rtt_time = DEFAULT_PING_CONNECTION;
crypto_connection_add_source(c, crypt_connection_id, n_c->source);
return crypt_connection_id;
}
@@ -1621,6 +1650,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
conn->status = CRYPTO_CONN_COOKIE_REQUESTING;
conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
+ conn->rtt_time = DEFAULT_PING_CONNECTION;
memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES);
conn->cookie_request_number = random_64b();
@@ -2003,7 +2033,7 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet
#define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0)
/* Multiplier for maximum allowed resends. */
-#define PACKET_RESEND_MULTIPLIER 2
+#define PACKET_RESEND_MULTIPLIER 3
/* Timeout for increasing speed after congestion event (in ms). */
#define CONGESTION_EVENT_TIMEOUT 2000
@@ -2392,7 +2422,7 @@ Net_Crypto *new_net_crypto(DHT *dht, TCP_Proxy_Info *proxy_info)
if (temp == NULL)
return NULL;
- temp->tcp_c = new_tcp_connections(dht, proxy_info);
+ temp->tcp_c = new_tcp_connections(dht->self_secret_key, proxy_info);
if (temp->tcp_c == NULL) {
free(temp);
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index 56f43cc44..0ab6446e6 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -82,8 +82,8 @@
at the dT defined in net_crypto.c */
#define CONGESTION_QUEUE_ARRAY_SIZE 24
-/* Connection ping in ms. TODO: calculate it per connection. */
-#define DEFAULT_PING_CONNECTION 50
+/* Default connection ping in ms. */
+#define DEFAULT_PING_CONNECTION 200
typedef struct {
uint64_t sent_time;
@@ -150,6 +150,7 @@ typedef struct {
long signed int last_num_packets_sent[CONGESTION_QUEUE_ARRAY_SIZE];
uint32_t packets_sent;
uint64_t last_congestion_event;
+ uint64_t rtt_time;
/* TCP_connection connection_number */
unsigned int connection_number_tcp;
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index 6575f632b..4f049fbc5 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -198,6 +198,16 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format
return -1;
}
+/* is path timed out */
+static _Bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum)
+{
+ pathnum = pathnum % NUMBER_ONION_PATHS;
+
+ return ((onion_paths->last_path_success[pathnum] + ONION_PATH_TIMEOUT < onion_paths->last_path_used[pathnum]
+ && onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES)
+ || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME));
+}
+
/* Create a new path or use an old suitable one (if pathnum is valid)
* or a random one from onion_paths.
*
@@ -209,12 +219,13 @@ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format
*/
static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
{
- if (pathnum >= NUMBER_ONION_PATHS)
+ if (pathnum == UINT32_MAX) {
pathnum = rand() % NUMBER_ONION_PATHS;
+ } else {
+ pathnum = pathnum % NUMBER_ONION_PATHS;
+ }
- if ((onion_paths->last_path_success[pathnum] + ONION_PATH_TIMEOUT < onion_paths->last_path_used[pathnum]
- && onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES)
- || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)) {
+ if (path_timed_out(onion_paths, pathnum)) {
Node_format nodes[ONION_PATH_LENGTH];
if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH)
@@ -247,6 +258,15 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
return 0;
}
+/* Does path with path_num exist. */
+static _Bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num)
+{
+ if (path_timed_out(onion_paths, path_num))
+ return 0;
+
+ return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num;
+}
+
/* Set path timeouts, return the path number.
*
*/
@@ -277,7 +297,7 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t
}
}
- return path_num % NUMBER_ONION_PATHS;
+ return path_num;
}
return ~0;
@@ -1315,7 +1335,7 @@ static void do_announce(Onion_Client *onion_c)
unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
- if (list_nodes[i].is_stored) {
+ if (list_nodes[i].is_stored && path_exists(&onion_c->onion_paths_self, list_nodes[i].path_used)) {
interval = ANNOUNCE_INTERVAL_ANNOUNCED;
}
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 14c9f6163..3b2da2f72 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -32,6 +32,15 @@
extern "C" {
#endif
+
+/*******************************************************************************
+ * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to *
+ * `tox.in.h`, located in `other/apidsl/`. For instructions on how to *
+ * generate `tox.h` from `tox.in.h` please refer to `other/apidsl/README.md` *
+ ******************************************************************************/
+
+
+
/** \page core Public core API for Tox clients.
*
* Every function that can fail takes a function-specific error code pointer
@@ -451,7 +460,15 @@ struct Tox_Options {
/**
- * The port to use for the TCP server. If 0, the tcp server is disabled.
+ * The port to use for the TCP server (relay). If 0, the TCP server is
+ * disabled.
+ *
+ * Enabling it is not required for Tox to function properly.
+ *
+ * When enabled, your Tox instance can act as a TCP relay for other Tox
+ * instance. This leads to increased traffic, thus when writing a client
+ * it is recommended to enable TCP server only if the user has an option
+ * to disable it.
*/
uint16_t tcp_port;