diff --git a/.travis.yml b/.travis.yml index 0a294bf1..4d49f5fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ compiler: - clang before_script: +# installing libsodium, needed for Core - git clone git://github.com/jedisct1/libsodium.git - cd libsodium - git checkout tags/0.4.2 @@ -12,6 +13,10 @@ before_script: - sudo make install - sudo ldconfig - cd .. +# installing libconfig, needed for DHT_bootstrap_daemon + - sudo sed -i 's/precise/quantal/' /etc/apt/sources.list # needed for libconfig-dev + - sudo apt-get update -qq + - yes | sudo apt-get install libconfig-dev script: - mkdir build && cd build diff --git a/INSTALL.md b/INSTALL.md index bc027c0b..a550e47b 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -56,6 +56,8 @@ You should install: - [MinGW](http://sourceforge.net/projects/mingw/)'s C compiler - [CMake](http://www.cmake.org/cmake/resources/software.html) +You have to [modify your PATH environment variable](http://www.computerhope.com/issues/ch000549.htm) so that it contains MinGW's bin folder path. With default settings, the bin folder is located at `C:\MinGW\bin`, which means that you would have to append `;C:\MinGW\bin` to the PATH variable. + Then you should either clone this repo by using git, or just download a [zip of current Master branch](https://github.com/irungentoo/ProjectTox-Core/archive/master.zip) and extract it somewhere. After that you should get precompiled packages of libsodium from [here](https://download.libsodium.org/libsodium/releases/) and extract the archive into this repo's root. That is, `sodium` folder should be along with `core`, `testing` and other folders. diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index ab4ff4bc..6ddd5b9b 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -11,6 +11,7 @@ set(core_sources Lossless_UDP.c net_crypto.c friend_requests.c + LAN_discovery.c Messenger.c) add_library(core ${core_sources}) diff --git a/core/DHT.c b/core/DHT.c index 030c578e..857ac5e8 100644 --- a/core/DHT.c +++ b/core/DHT.c @@ -1,33 +1,28 @@ /* DHT.c -* -* An implementation of the DHT as seen in docs/DHT.txt -* - - Copyright (C) 2013 Tox project All Rights Reserved. - - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ - - - + * + * An implementation of the DHT as seen in docs/DHT.txt + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ #include "DHT.h" - typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; @@ -38,17 +33,24 @@ typedef struct (for nodes in friends_list) or us (for nodes in close_clientlist) */ uint32_t ret_timestamp; }Client_data; + /* maximum number of clients stored per friend. */ #define MAX_FRIEND_CLIENTS 8 + typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; Client_data client_list[MAX_FRIEND_CLIENTS]; uint32_t lastgetnode; /* time at which the last get_nodes request was sent. */ + /*Symetric NAT hole punching stuff*/ + uint8_t hole_punching; /*0 if not hole punching, 1 if currently hole punching */ + uint32_t punching_index; + uint32_t punching_timestamp; + uint64_t NATping_id; + uint32_t NATping_timestamp; }Friend; - typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; @@ -72,13 +74,11 @@ uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; #define LCLIENT_LIST 32 static Client_data close_clientlist[LCLIENT_LIST]; - - static Friend * friends_list; static uint16_t num_friends; /* The list of ip ports along with the ping_id of what we sent them and a timestamp */ -#define LPING_ARRAY 128 +#define LPING_ARRAY 256 static Pinged pings[LPING_ARRAY]; @@ -86,7 +86,6 @@ static Pinged pings[LPING_ARRAY]; static Pinged send_nodes[LSEND_NODES_ARRAY]; - /* Compares client_id1 and client_id2 with client_id return 0 if both are same distance return 1 if client_id1 is closer @@ -94,17 +93,12 @@ static Pinged send_nodes[LSEND_NODES_ARRAY]; int id_closest(uint8_t * client_id, uint8_t * client_id1, uint8_t * client_id2) /* tested */ { uint32_t i; - for(i = 0; i < CLIENT_ID_SIZE; ++i) - { - if(abs(client_id[i] ^ client_id1[i]) < abs(client_id[i] ^ client_id2[i])) - { + for(i = 0; i < CLIENT_ID_SIZE; ++i) { + if(abs(client_id[i] ^ client_id1[i]) < abs(client_id[i] ^ client_id2[i])) { return 1; - } - else if(abs(client_id[i] ^ client_id1[i]) > abs(client_id[i] ^ client_id2[i])) - { + } else if(abs(client_id[i] ^ client_id1[i]) > abs(client_id[i] ^ client_id2[i])) { return 2; } - } return 0; @@ -121,17 +115,14 @@ int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_ uint32_t i; uint32_t temp_time = unix_time(); - for(i = 0; i < length; ++i) - { + for(i = 0; i < length; ++i) { /*If ip_port is assigned to a different client_id replace it*/ if(list[i].ip_port.ip.i == ip_port.ip.i && - list[i].ip_port.port == ip_port.port) - { + list[i].ip_port.port == ip_port.port) { memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); } - if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) - { + if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { /* Refresh the client timestamp. */ list[i].timestamp = temp_time; list[i].ip_port.ip.i = ip_port.ip.i; @@ -148,10 +139,8 @@ int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_ int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id) { uint32_t i; - for(i = 0; i < length; ++i) - { - if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) - { + for(i = 0; i < length; ++i) { + if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { return 1; } @@ -160,14 +149,25 @@ int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id) } - +/*Return the friend number from the client_id + Return -1 if failure, number of friend if success*/ +static int friend_number(uint8_t * client_id) +{ + uint32_t i; + for(i = 0; i < num_friends; ++i) { + if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) /* Equal */ + { + return i; + } + } + return -1; +} /* the number of seconds for a non responsive node to become bad. */ -#define BAD_NODE_TIMEOUT 130 +#define BAD_NODE_TIMEOUT 70 /* the max number of nodes to send with send nodes. */ #define MAX_SENT_NODES 8 - /* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: put them in the nodes_list and return how many were found. TODO: Make this function much more efficient. */ @@ -176,48 +176,35 @@ int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) uint32_t i, j, k; int num_nodes=0; uint32_t temp_time = unix_time(); - for(i = 0; i < LCLIENT_LIST; ++i) - { + for(i = 0; i < LCLIENT_LIST; ++i) { if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time && - !client_in_nodelist(nodes_list, MAX_SENT_NODES,close_clientlist[i].client_id)) + !client_in_nodelist(nodes_list, MAX_SENT_NODES,close_clientlist[i].client_id)) { /* if node is good and not already in list. */ - { - if(num_nodes < MAX_SENT_NODES) - { + if(num_nodes < MAX_SENT_NODES) { memcpy(nodes_list[num_nodes].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port; num_nodes++; } - else for(j = 0; j < MAX_SENT_NODES; ++j) - { - if(id_closest(client_id, nodes_list[j].client_id, close_clientlist[i].client_id) == 2) - { + else for(j = 0; j < MAX_SENT_NODES; ++j) { + if(id_closest(client_id, nodes_list[j].client_id, close_clientlist[i].client_id) == 2) { memcpy(nodes_list[j].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); nodes_list[j].ip_port = close_clientlist[i].ip_port; break; } } - } - + } } - for(i = 0; i < num_friends; ++i) - { - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) - { + for(i = 0; i < num_friends; ++i) { + for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) { if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time && - !client_in_nodelist(nodes_list, MAX_SENT_NODES,friends_list[i].client_list[j].client_id)) + !client_in_nodelist(nodes_list, MAX_SENT_NODES,friends_list[i].client_list[j].client_id)) { /* if node is good and not already in list. */ - { - if(num_nodes < MAX_SENT_NODES) - { + if(num_nodes < MAX_SENT_NODES) { memcpy(nodes_list[num_nodes].client_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE); nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port; num_nodes++; - } - else for(k = 0; k < MAX_SENT_NODES; ++k) - { - if(id_closest(client_id, nodes_list[k].client_id, friends_list[i].client_list[j].client_id) == 2) - { + } else for(k = 0; k < MAX_SENT_NODES; ++k) { + if(id_closest(client_id, nodes_list[k].client_id, friends_list[i].client_list[j].client_id) == 2) { memcpy(nodes_list[k].client_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE); nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port; break; @@ -227,12 +214,9 @@ int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) } } - return num_nodes; - + return num_nodes; } - - /* replace first bad (or empty) node with this one return 0 if successful return 1 if not (list contains no bad nodes) */ @@ -240,10 +224,8 @@ int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Por { uint32_t i; uint32_t temp_time = unix_time(); - for(i = 0; i < length; ++i) - { - if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time) /* if node is bad. */ - { + for(i = 0; i < length; ++i) { + if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time) /* if node is bad. */ { memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); list[i].ip_port = ip_port; list[i].timestamp = temp_time; @@ -263,10 +245,8 @@ int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Po uint32_t i; uint32_t temp_time = unix_time(); - for(i = 0; i < length; ++i) - { - if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) - { + for(i = 0; i < length; ++i) { + if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) { memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); list[i].ip_port = ip_port; list[i].timestamp = temp_time; @@ -286,23 +266,16 @@ void addto_lists(IP_Port ip_port, uint8_t * client_id) uint32_t i; /* NOTE: current behavior if there are two clients with the same id is to replace the first ip by the second. */ - if(!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) - { + if(!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) { - if(replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) - { + if(replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) { /* if we can't replace bad nodes we try replacing good ones */ replace_good(close_clientlist, LCLIENT_LIST, client_id, ip_port, self_public_key); - } - + } } - for(i = 0; i < num_friends; ++i) - { - if(!client_in_list(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) - { - - if(replace_bad(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) - { + for(i = 0; i < num_friends; ++i) { + if(!client_in_list(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) { + if(replace_bad(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) { /* if we can't replace bad nodes we try replacing good ones. */ replace_good(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port, friends_list[i].client_id); } @@ -316,12 +289,9 @@ void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient { uint32_t i, j; uint32_t temp_time = unix_time(); - if(memcmp(client_id, self_public_key, CLIENT_ID_SIZE) == 0) - { - for(i = 0; i < LCLIENT_LIST; ++i) - { - if(memcmp(nodeclient_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) - { + if(memcmp(client_id, self_public_key, CLIENT_ID_SIZE) == 0) { + for(i = 0; i < LCLIENT_LIST; ++i) { + if(memcmp(nodeclient_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) { close_clientlist[i].ret_ip_port = ip_port; close_clientlist[i].ret_timestamp = temp_time; return; @@ -329,14 +299,10 @@ void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient } } else - for(i = 0; i < num_friends; ++i) - { - if(memcmp(client_id, friends_list[i].client_id, CLIENT_ID_SIZE) == 0) - { - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) - { - if(memcmp(nodeclient_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE) == 0) - { + for(i = 0; i < num_friends; ++i) { + if(memcmp(client_id, friends_list[i].client_id, CLIENT_ID_SIZE) == 0) { + for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) { + if(memcmp(nodeclient_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE) == 0) { friends_list[i].client_list[j].ret_ip_port = ip_port; friends_list[i].client_list[j].ret_timestamp = temp_time; return; @@ -348,6 +314,7 @@ void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient /* ping timeout in seconds */ #define PING_TIMEOUT 5 + /* check if we are currently pinging an ip_port and/or a ping_id variables with values of zero will not be checked. if we are already, return 1 @@ -359,28 +326,22 @@ int is_pinging(IP_Port ip_port, uint64_t ping_id) uint8_t pinging; uint32_t temp_time = unix_time(); - for(i = 0; i < LPING_ARRAY; ++i ) - { - if((pings[i].timestamp + PING_TIMEOUT) > temp_time) - { + for(i = 0; i < LPING_ARRAY; ++i ) { + if((pings[i].timestamp + PING_TIMEOUT) > temp_time) { pinging = 0; - if(ip_port.ip.i != 0) - { + if(ip_port.ip.i != 0) { if(pings[i].ip_port.ip.i == ip_port.ip.i && - pings[i].ip_port.port == ip_port.port) - { + pings[i].ip_port.port == ip_port.port) { ++pinging; } } - if(ping_id != 0) - { + if(ping_id != 0) { if(pings[i].ping_id == ping_id) { ++pinging; } } - if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) - { + if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) { return 1; } @@ -391,7 +352,6 @@ int is_pinging(IP_Port ip_port, uint64_t ping_id) } - /* Same as last function but for get_node requests. */ int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) { @@ -399,28 +359,21 @@ int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) uint8_t pinging; uint32_t temp_time = unix_time(); - for(i = 0; i < LSEND_NODES_ARRAY; ++i ) - { - if((send_nodes[i].timestamp + PING_TIMEOUT) > temp_time) - { + for(i = 0; i < LSEND_NODES_ARRAY; ++i ) { + if((send_nodes[i].timestamp + PING_TIMEOUT) > temp_time) { pinging = 0; - if(ip_port.ip.i != 0) - { + if(ip_port.ip.i != 0) { if(send_nodes[i].ip_port.ip.i == ip_port.ip.i && - send_nodes[i].ip_port.port == ip_port.port) - { + send_nodes[i].ip_port.port == ip_port.port) { ++pinging; } } - if(ping_id != 0) - { - if(send_nodes[i].ping_id == ping_id) - { + if(ping_id != 0) { + if(send_nodes[i].ping_id == ping_id) { ++pinging; } } - if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) - { + if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) { return 1; } @@ -431,7 +384,6 @@ int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) } - /* Add a new ping request to the list of ping requests returns the ping_id to put in the ping request returns 0 if problem. @@ -442,12 +394,9 @@ uint64_t add_pinging(IP_Port ip_port) uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); uint32_t temp_time = unix_time(); - for(i = 0; i < PING_TIMEOUT; ++i ) - { - for(j = 0; j < LPING_ARRAY; ++j ) - { - if((pings[j].timestamp + PING_TIMEOUT - i) < temp_time) - { + for(i = 0; i < PING_TIMEOUT; ++i ) { + for(j = 0; j < LPING_ARRAY; ++j ) { + if((pings[j].timestamp + PING_TIMEOUT - i) < temp_time) { pings[j].timestamp = temp_time; pings[j].ip_port = ip_port; pings[j].ping_id = ping_id; @@ -466,12 +415,9 @@ uint64_t add_gettingnodes(IP_Port ip_port) uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); uint32_t temp_time = unix_time(); - for(i = 0; i < PING_TIMEOUT; ++i ) - { - for(j = 0; j < LSEND_NODES_ARRAY; ++j ) - { - if((send_nodes[j].timestamp + PING_TIMEOUT - i) < temp_time) - { + for(i = 0; i < PING_TIMEOUT; ++i ) { + for(j = 0; j < LSEND_NODES_ARRAY; ++j ) { + if((send_nodes[j].timestamp + PING_TIMEOUT - i) < temp_time) { send_nodes[j].timestamp = temp_time; send_nodes[j].ip_port = ip_port; send_nodes[j].ping_id = ping_id; @@ -483,25 +429,20 @@ uint64_t add_gettingnodes(IP_Port ip_port) } - - /* send a ping request Ping request only works if none has been sent to that ip/port in the last 5 seconds. */ static int pingreq(IP_Port ip_port, uint8_t * public_key) { - if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ - { + if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ { return 1; } - if(is_pinging(ip_port, 0)) - { + if(is_pinging(ip_port, 0)) { return 1; } uint64_t ping_id = add_pinging(ip_port); - if(ping_id == 0) - { + if(ping_id == 0) { return 1; } @@ -511,8 +452,7 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key) random_nonce(nonce); int len = encrypt_data(public_key, self_secret_key, nonce, (uint8_t *)&ping_id, sizeof(ping_id), encrypt); - if(len != sizeof(ping_id) + ENCRYPTION_PADDING) - { + if(len != sizeof(ping_id) + ENCRYPTION_PADDING) { return -1; } data[0] = 0; @@ -524,12 +464,11 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key) } - /* send a ping response */ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) { - if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ - { + /* check if packet is gonna be sent to ourself */ + if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) { return 1; } @@ -539,8 +478,7 @@ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) random_nonce(nonce); int len = encrypt_data(public_key, self_secret_key, nonce, (uint8_t *)&ping_id, sizeof(ping_id), encrypt); - if(len != sizeof(ping_id) + ENCRYPTION_PADDING) - { + if(len != sizeof(ping_id) + ENCRYPTION_PADDING) { return -1; } data[0] = 1; @@ -555,20 +493,18 @@ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) /* send a getnodes request */ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) { - if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ - { + /* check if packet is gonna be sent to ourself */ + if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) { return 1; } - if(is_gettingnodes(ip_port, 0)) - { + if(is_gettingnodes(ip_port, 0)) { return 1; } uint64_t ping_id = add_gettingnodes(ip_port); - if(ping_id == 0) - { + if(ping_id == 0) { return 1; } @@ -583,8 +519,7 @@ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) int len = encrypt_data(public_key, self_secret_key, nonce, plain, sizeof(ping_id) + CLIENT_ID_SIZE, encrypt); - if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) - { + if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) { return -1; } data[0] = 2; @@ -595,12 +530,10 @@ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) } - /* send a send nodes response */ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id) { - if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ - { + if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ { return 1; } @@ -610,8 +543,7 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, Node_format nodes_list[MAX_SENT_NODES]; int num_nodes = get_close_nodes(client_id, nodes_list); - if(num_nodes == 0) - { + if(num_nodes == 0) { return 0; } @@ -626,8 +558,7 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, int len = encrypt_data(public_key, self_secret_key, nonce, plain, sizeof(ping_id) + num_nodes * sizeof(Node_format), encrypt); - if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) - { + if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) { return -1; } @@ -640,20 +571,17 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, } - - /* Packet handling functions One to handle each types of packets we receive return 0 if handled correctly, 1 if packet is bad. */ int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) { uint64_t ping_id; - if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) - { + if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) { return 1; } - if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is from ourself. */ - { + /* check if packet is from ourself. */ + if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) { return 1; } @@ -662,8 +590,7 @@ int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); - if(len != sizeof(ping_id)) - { + if(len != sizeof(ping_id)) { return 1; } @@ -679,12 +606,10 @@ int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source) { uint64_t ping_id; - if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) - { + if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) { return 1; } - if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is from ourself. */ - { + if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is from ourself. */ { return 1; } @@ -693,13 +618,11 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source) int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); - if(len != sizeof(ping_id)) - { + if(len != sizeof(ping_id)) { return 1; } - if(is_pinging(source, ping_id)) - { + if(is_pinging(source, ping_id)) { addto_lists(source, packet + 1); return 0; } @@ -710,12 +633,11 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source) int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) { uint64_t ping_id; - if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) - { + if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) { return 1; } - if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is from ourself. */ - { + /* check if packet is from ourself. */ + if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) { return 1; } @@ -725,8 +647,7 @@ int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, plain); - if(len != sizeof(ping_id) + CLIENT_ID_SIZE) - { + if(len != sizeof(ping_id) + CLIENT_ID_SIZE) { return 1; } @@ -748,8 +669,7 @@ int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)) % (sizeof(Node_format)) != 0 || length < 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) - + sizeof(Node_format) + ENCRYPTION_PADDING) - { + + sizeof(Node_format) + ENCRYPTION_PADDING) { return 1; } uint32_t num_nodes = (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES @@ -762,14 +682,12 @@ int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain); - if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) - { + if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) { return 1; } memcpy(&ping_id, plain, sizeof(ping_id)); - if(!is_gettingnodes(source, ping_id)) - { + if(!is_gettingnodes(source, ping_id)) { return 1; } @@ -779,8 +697,7 @@ int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) addto_lists(source, packet + 1); uint32_t i; - for(i = 0; i < num_nodes; ++i) - { + for(i = 0; i < num_nodes; ++i) { pingreq(nodes_list[i].ip_port, nodes_list[i].client_id); returnedip_ports(nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); } @@ -793,44 +710,36 @@ int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) int DHT_addfriend(uint8_t * client_id) { Friend * temp; - if(num_friends == 0) - { + if(num_friends == 0) { temp = malloc(sizeof(Friend)); - } - else - { + } else { temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); } - if(temp == NULL) - { + if(temp == NULL) { return 1; } friends_list = temp; memset(&friends_list[num_friends], 0, sizeof(Friend)); memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE); + friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); ++num_friends; return 0; } - - int DHT_delfriend(uint8_t * client_id) { uint32_t i; Friend * temp; - for(i = 0; i < num_friends; ++i) - { - if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) /* Equal */ - { + for(i = 0; i < num_friends; ++i) { + /* Equal */ + if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0){ --num_friends; - if(num_friends != i) - { + if(num_friends != i) { memcpy(friends_list[i].client_id, friends_list[num_friends].client_id, CLIENT_ID_SIZE); } temp = realloc(friends_list, sizeof(Friend) * (num_friends)); - if(temp != NULL) - { + if(temp != NULL) { friends_list = temp; } return 0; @@ -839,61 +748,27 @@ int DHT_delfriend(uint8_t * client_id) return 1; } - - - /* TODO: Optimize this. */ IP_Port DHT_getfriendip(uint8_t * client_id) { uint32_t i, j; IP_Port empty = {{{0}}, 0}; uint32_t temp_time = unix_time(); - for(i = 0; i < num_friends; ++i) - { - if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) /* Equal */ - { - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) - { + for(i = 0; i < num_friends; ++i) { + /* Equal */ + if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { + for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) { if(memcmp(friends_list[i].client_list[j].client_id, client_id, CLIENT_ID_SIZE) == 0 && - friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) - { + friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) { return friends_list[i].client_list[j].ip_port; - } - - } - + } + } return empty; } } empty.ip.i = 1; return empty; -} - - - -int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) -{ - switch (packet[0]) { - case 0: - return handle_pingreq(packet, length, source); - - case 1: - return handle_pingres(packet, length, source); - - case 2: - return handle_getnodes(packet, length, source); - - case 3: - return handle_sendnodes(packet, length, source); - - default: - return 1; - - } - - return 0; - } /* The timeout after which a node is discarded completely. */ @@ -907,8 +782,6 @@ int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) /* Ping each client in the "friends" list every 60 seconds. Send a get nodes request every 20 seconds to a random good node for each "friend" in our "friends" list. */ - - void doDHTFriends() { uint32_t i, j; @@ -916,27 +789,21 @@ void doDHTFriends() uint32_t rand_node; uint32_t index[MAX_FRIEND_CLIENTS]; - for(i = 0; i < num_friends; ++i) - { + for(i = 0; i < num_friends; ++i) { uint32_t num_nodes = 0; - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) - { - if(friends_list[i].client_list[j].timestamp + Kill_NODE_TIMEOUT > temp_time) /* if node is not dead. */ - { - if((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) - { + for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) { + if(friends_list[i].client_list[j].timestamp + Kill_NODE_TIMEOUT > temp_time) /* if node is not dead. */ { + if((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { pingreq(friends_list[i].client_list[j].ip_port, friends_list[i].client_list[j].client_id); friends_list[i].client_list[j].last_pinged = temp_time; } - if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) /* if node is good. */ - { + if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) /* if node is good. */ { index[num_nodes] = j; ++num_nodes; } } } - if(friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) - { + if(friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { rand_node = rand() % num_nodes; getnodes(friends_list[i].client_list[index[rand_node]].ip_port, friends_list[i].client_list[index[rand_node]].client_id, @@ -958,66 +825,77 @@ void doClose() /* tested */ uint32_t rand_node; uint32_t index[LCLIENT_LIST]; - for(i = 0; i < LCLIENT_LIST; ++i) - { - if(close_clientlist[i].timestamp + Kill_NODE_TIMEOUT > temp_time) /* if node is not dead. */ - { + for(i = 0; i < LCLIENT_LIST; ++i) { + /* if node is not dead. */ + if(close_clientlist[i].timestamp + Kill_NODE_TIMEOUT > temp_time) { if((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { pingreq(close_clientlist[i].ip_port, close_clientlist[i].client_id); close_clientlist[i].last_pinged = temp_time; } - if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) /* if node is good. */ - { + /* if node is good. */ + if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) { index[num_nodes] = i; ++num_nodes; } } } - if(close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) - { + if(close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { rand_node = rand() % num_nodes; getnodes(close_clientlist[index[rand_node]].ip_port, close_clientlist[index[rand_node]].client_id, self_public_key); close_lastgetnodes = temp_time; } - } - - -void doDHT() -{ - doClose(); - doDHTFriends(); -} - - - void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key) { getnodes(ip_port, public_key, self_public_key); } - - /* send the given packet to node with client_id returns -1 if failure */ int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length) { uint32_t i; - for(i = 0; i < LCLIENT_LIST; ++i) - { - if(memcmp(client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) - { + for(i = 0; i < LCLIENT_LIST; ++i) { + if(memcmp(client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) { return sendpacket(close_clientlist[i].ip_port, packet, length); } } return -1; } +/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist + ip_portlist must be at least MAX_FRIEND_CLIENTS big + returns the number of ips returned + return 0 if we are connected to friend or if no ips were found. + returns -1 if no such friend*/ +static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num) +{ + int num_ips = 0; + uint32_t i; + uint32_t temp_time = unix_time(); + if(friend_num >= num_friends) { + return -1; + } + for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) + { + /*If ip is not zero and node is good */ + if(friends_list[friend_num].client_list[i].ret_ip_port.ip.i != 0 && + friends_list[friend_num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { + if(memcmp(friends_list[friend_num].client_list[i].client_id, friends_list[friend_num].client_id, CLIENT_ID_SIZE) == 0 ) { + return 0; + } + ip_portlist[num_ips] = friends_list[friend_num].client_list[i].ret_ip_port; + ++num_ips; + } + } + return num_ips; +} + /* Send the following packet to everyone who tells us they are connected to friend_id returns the number of nodes it sent the packet to */ int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) @@ -1025,18 +903,14 @@ int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) uint32_t i, j; uint32_t sent = 0; uint32_t temp_time = unix_time(); - for(i = 0; i < num_friends; ++i) - { - if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) /* Equal */ - { - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) - { + for(i = 0; i < num_friends; ++i) { + /* Equal */ + if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) { + for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) { + /*If ip is not zero and node is good */ if(friends_list[i].client_list[j].ret_ip_port.ip.i != 0 && - friends_list[i].client_list[j].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) - /*If ip is not zero and node is good */ - { - if(sendpacket(friends_list[i].client_list[j].ip_port, packet, length) == length) - { + friends_list[i].client_list[j].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { + if(sendpacket(friends_list[i].client_list[j].ip_port, packet, length) == length) { ++sent; } } @@ -1047,36 +921,257 @@ int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) return 0; } +/* Send the following packet to one random person who tells us they are connected to friend_id + returns the number of nodes it sent the packet to */ +int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) +{ + int num = friend_number(friend_id); + if(num == -1) { + return 0; + } + + IP_Port ip_list[MAX_FRIEND_CLIENTS]; + int n = 0; + uint32_t i; + uint32_t temp_time = unix_time(); + for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) { + /*If ip is not zero and node is good */ + if(friends_list[num].client_list[i].ret_ip_port.ip.i != 0 && + friends_list[num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { + ip_list[n] = friends_list[num].client_list[i].ip_port; + ++n; + } + } + if(n < 1) { + return 0; + } + if(sendpacket(ip_list[rand() % n], packet, length) == length) { + return 1; + } + return 0; +} + /* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist ip_portlist must be at least MAX_FRIEND_CLIENTS big returns the number of ips returned + return 0 if we are connected to friend or if no ips were found. returns -1 if no such friend*/ int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id) { - int num_ips = 0; - uint32_t i, j; - uint32_t temp_time = unix_time(); - for(i = 0; i < num_friends; ++i) - { - if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) /* Equal */ - { - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) - { - if(friends_list[i].client_list[j].ret_ip_port.ip.i != 0 && - friends_list[i].client_list[j].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) - /*If ip is not zero and node is good */ - { - ip_portlist[num_ips] = friends_list[i].client_list[j].ret_ip_port; - ++num_ips; - } - } - return num_ips; + + uint32_t i; + for(i = 0; i < num_friends; ++i) { + /* Equal */ + if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) { + return friend_iplist(ip_portlist, i); + } + } + return -1; +} + +/*BEGINNING OF NAT PUNCHING FUNCTIONS*/ + +int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) +{ + uint8_t data[sizeof(uint64_t) + 1]; + data[0] = type; + memcpy(data + 1, &ping_id, sizeof(uint64_t)); + + uint8_t packet[MAX_DATA_SIZE]; + int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254); /* 254 is NAT ping request packet id */ + if(len == -1) { + return -1; + } + int num = 0; + if(type == 0) { + num = route_tofriend(public_key, packet, len);/*If packet is request use many people to route it*/ + } + else if(type == 1) { + num = routeone_tofriend(public_key, packet, len);/*If packet is response use only one person to route it*/ + } + if(num == 0) { + return -1; + } + return num; +} + +/* Handle a recieved ping request for */ +int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) +{ + if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && + length > MAX_DATA_SIZE + ENCRYPTION_PADDING) { + return 1; + } + /* check if request is for us. */ + if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { + uint8_t public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t data[MAX_DATA_SIZE]; + int len = handle_request(public_key, data, packet, length); + if(len != sizeof(uint64_t) + 1) { + return 1; + } + uint64_t ping_id; + memcpy(&ping_id, data + 1, sizeof(uint64_t)); + + int friendnumber = friend_number(public_key); + if(friendnumber == -1) { + return 1; } + if(data[0] == 0) { + send_NATping(public_key, ping_id, 1);/*1 is reply*/ + return 0; + } else if (data[0] == 1) { + if(friends_list[friendnumber].NATping_id == ping_id) + { + friends_list[friendnumber].NATping_id = ((uint64_t)random_int() << 32) + random_int(); + friends_list[friendnumber].hole_punching = 1; + return 0; + } + } + return 1; + } + /* if request is not for us, try routing it. */ + else { + if(route_packet(packet + 1, packet, length) == length) { + return 0; + } } return 0; } +/*Get the most common ip in the ip_portlist + Only return ip if it appears in list min_num or more + len must not be bigger than MAX_FRIEND_CLIENTS + return ip of 0 if failure */ +static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) +{ + IP zero = {{0}}; + if(len > MAX_FRIEND_CLIENTS) { + return zero; + } + + uint32_t i, j; + uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; + for(i = 0; i < len; ++i) { + for(j = 0; j < len; ++j) { + if(ip_portlist[i].ip.i == ip_portlist[j].ip.i) { + ++numbers[i]; + } + } + if(numbers[i] >= min_num) { + return ip_portlist[i].ip; + } + } + return zero; +} + +/*Return all the ports for one ip in a list + portlist must be at least len long + where len is the length of ip_portlist + returns the number of ports and puts the list of ports in portlist*/ +static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) +{ + uint32_t i; + uint16_t num = 0; + for(i = 0; i < len; ++i) { + if(ip_portlist[i].ip.i == ip.i) { + portlist[num] = ntohs(ip_portlist[i].port); + ++num; + } + } + return num; +} + +#define MAX_PUNCHING_PORTS 32 + +static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num) +{ + if(numports > MAX_FRIEND_CLIENTS || numports == 0) { + return; + } + uint32_t i; + uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; + for(i = friends_list[friend_num].punching_index; i != top; i++) { + /*TODO: improve port guessing algorithm*/ + uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); + IP_Port pinging = {ip, htons(port)}; + pingreq(pinging, friends_list[friend_num].client_id); + } + friends_list[friend_num].punching_index = i; +} + +/*Interval in seconds between punching attempts*/ +#define PUNCH_INTERVAL 10 + +static void doNAT() +{ + uint32_t i; + uint32_t temp_time = unix_time(); + for(i = 0; i < num_friends; ++i) { + IP_Port ip_list[MAX_FRIEND_CLIENTS]; + int num = friend_iplist(ip_list, i); + /*If we are connected to friend or if friend is not online don't try to hole punch with him*/ + if(num < MAX_FRIEND_CLIENTS/2) { + continue; + } + if(friends_list[i].hole_punching != 1) { + if(friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { + send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ + friends_list[i].NATping_timestamp = temp_time; + } + } + else if(friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time) { + IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2); + if(ip.i == 0) { + continue; + } + uint16_t port_list[MAX_FRIEND_CLIENTS]; + uint16_t numports = NAT_getports(port_list, ip_list, num, ip); + punch_holes(ip, port_list, numports, i); + + friends_list[i].punching_timestamp = temp_time; + friends_list[i].hole_punching = 0; + } + } +} + +/*END OF NAT PUNCHING FUNCTIONS*/ + +int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) +{ + switch (packet[0]) { + case 0: + return handle_pingreq(packet, length, source); + + case 1: + return handle_pingres(packet, length, source); + + case 2: + return handle_getnodes(packet, length, source); + + case 3: + return handle_sendnodes(packet, length, source); + + case 254: + return handle_NATping(packet, length, source); + + default: + return 1; + + } + + return 0; + +} + +void doDHT() +{ + doClose(); + doDHTFriends(); + doNAT(); +} + /* get the size of the DHT (for saving) */ uint32_t DHT_size() { @@ -1095,12 +1190,10 @@ void DHT_save(uint8_t * data) return 0 if success */ int DHT_load(uint8_t * data, uint32_t size) { - if(size < sizeof(close_clientlist)) - { + if(size < sizeof(close_clientlist)) { return -1; } - if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) - { + if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) { return -1; } uint32_t i, j; @@ -1109,17 +1202,13 @@ int DHT_load(uint8_t * data, uint32_t size) temp = (size - sizeof(close_clientlist))/sizeof(Friend); - if(temp != 0) - { + if(temp != 0) { Friend * tempfriends_list = (Friend *)(data + sizeof(close_clientlist)); - for(i = 0; i < temp; ++i) - { + for(i = 0; i < temp; ++i) { DHT_addfriend(tempfriends_list[i].client_id); - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) - { - if(tempfriends_list[i].client_list[j].timestamp != 0) - { + for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) { + if(tempfriends_list[i].client_list[j].timestamp != 0) { getnodes(tempfriends_list[i].client_list[j].ip_port, tempfriends_list[i].client_list[j].client_id, tempfriends_list[i].client_id); } @@ -1128,10 +1217,8 @@ int DHT_load(uint8_t * data, uint32_t size) } Client_data * tempclose_clientlist = (Client_data *)data; - for(i = 0; i < LCLIENT_LIST; ++i) - { - if(tempclose_clientlist[i].timestamp != 0) - { + for(i = 0; i < LCLIENT_LIST; ++i) { + if(tempclose_clientlist[i].timestamp != 0) { DHT_bootstrap(tempclose_clientlist[i].ip_port, tempclose_clientlist[i].client_id); } } @@ -1144,13 +1231,10 @@ int DHT_isconnected() { uint32_t i; uint32_t temp_time = unix_time(); - for(i = 0; i < LCLIENT_LIST; ++i) - { - if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) - { + for(i = 0; i < LCLIENT_LIST; ++i) { + if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) { return 1; } } return 0; -} - +} \ No newline at end of file diff --git a/core/DHT.h b/core/DHT.h index fdb89de6..966645f5 100644 --- a/core/DHT.h +++ b/core/DHT.h @@ -1,27 +1,25 @@ /* DHT.h -* -* An implementation of the DHT as seen in docs/DHT.txt -* - - Copyright (C) 2013 Tox project All Rights Reserved. - - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ - + * + * An implementation of the DHT as seen in docs/DHT.txt + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ #ifndef DHT_H #define DHT_H @@ -38,8 +36,6 @@ extern "C" { /* size of the client_id in bytes */ #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES - - /* Add a new friend to the friends list client_id must be CLIENT_ID_SIZE bytes long. returns 0 if success @@ -52,7 +48,6 @@ int DHT_addfriend(uint8_t * client_id); returns 1 if failure (client_id not in friends list) */ int DHT_delfriend(uint8_t * client_id); - /* Get ip of friend client_id must be CLIENT_ID_SIZE bytes long. ip must be 4 bytes long. @@ -62,7 +57,6 @@ int DHT_delfriend(uint8_t * client_id); returns ip of 1 if friend is not in list. */ IP_Port DHT_getfriendip(uint8_t * client_id); - /* Run this function at least a couple times per second (It's the main loop) */ void doDHT(); @@ -75,8 +69,6 @@ int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source); Sends a get nodes request to the given node with ip port and public_key */ void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key); - - /* ROUTING FUNCTIONS */ /* send the given packet to node with client_id @@ -87,8 +79,6 @@ int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length); returns the number of nodes it sent the packet to */ int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length); - - /* NAT PUNCHING FUNCTIONS */ /* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist @@ -97,8 +87,6 @@ int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length); returns -1 if no such friend*/ int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id); - - /* SAVE/LOAD functions */ /* get the size of the DHT (for saving) */ diff --git a/core/LAN_discovery.c b/core/LAN_discovery.c new file mode 100644 index 00000000..3cfcb067 --- /dev/null +++ b/core/LAN_discovery.c @@ -0,0 +1,79 @@ +/* LAN_discovery.c + * + * LAN discovery implementation. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#include "LAN_discovery.h" + + +/*Return the broadcast ip + TODO: make it return the real one, not the 255.255.255.255 one.*/ +IP broadcast_ip() +{ + IP ip; + ip.i = ~0; + return ip; +} + +/*return 0 if ip is a LAN ip + return -1 if it is not */ +int LAN_ip(IP ip) +{ + if(ip.c[0] == 127)/* Loopback */ + return 0; + if(ip.c[0] == 10)/* 10.0.0.0 to 10.255.255.255 range */ + return 0; + if(ip.c[0] == 172 && ip.c[1] >= 16 && ip.c[1] <= 31)/* 172.16.0.0 to 172.31.255.255 range */ + return 0; + if(ip.c[0] == 192 && ip.c[1] == 168) /* 192.168.0.0 to 192.168.255.255 range */ + return 0; + if(ip.c[0] == 169 && ip.c[1] == 254 && ip.c[2] != 0 && ip.c[2] != 255)/* 169.254.1.0 to 169.254.254.255 range */ + return 0; + return -1; +} + +int handle_LANdiscovery(uint8_t * packet, uint32_t length, IP_Port source) +{ + if(LAN_ip(source.ip) == -1) + return 1; + if(length != crypto_box_PUBLICKEYBYTES + 1) + return 1; + DHT_bootstrap(source, packet + 1); + return 0; +} + + +int send_LANdiscovery(uint16_t port) +{ + uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; + data[0] = 32; + memcpy(data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); + IP_Port ip_port = {broadcast_ip(), port}; + return sendpacket(ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); +} + + +int LANdiscovery_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) +{ + if(packet[0] == 32) + return handle_LANdiscovery(packet, length, source); + return 1; +} diff --git a/core/LAN_discovery.h b/core/LAN_discovery.h new file mode 100644 index 00000000..655830f9 --- /dev/null +++ b/core/LAN_discovery.h @@ -0,0 +1,50 @@ +/* LAN_discovery.h + * + * LAN discovery implementation. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + + +#ifndef LAN_DISCOVERY_H +#define LAN_DISCOVERY_H + + +#include "DHT.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*Send a LAN discovery pcaket to the broadcast address with port port*/ +int send_LANdiscovery(uint16_t port); + + +/* if we receive a packet we call this function so it can be handled. + return 0 if packet is handled correctly. + return 1 if it didn't handle the packet or if the packet was shit. */ +int LANdiscovery_handlepacket(uint8_t * packet, uint32_t length, IP_Port source); + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c index c4c464b6..43f61b5b 100644 --- a/core/Lossless_UDP.c +++ b/core/Lossless_UDP.c @@ -1,32 +1,30 @@ -/* Lossless_UDP.c -* -* An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt -* - - Copyright (C) 2013 Tox project All Rights Reserved. +/* Lossless_UDP.c + * + * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ /* TODO: clean this file a bit. There are a couple of useless variables to get rid of. */ #include "Lossless_UDP.h" - - /* maximum data packets in sent and receive queues. */ #define MAX_QUEUE_NUM 16 @@ -88,7 +86,6 @@ typedef struct uint8_t timeout; /* connection timeout in seconds. */ }Connection; - #define MAX_CONNECTIONS 256 static Connection connections[MAX_CONNECTIONS]; @@ -104,40 +101,31 @@ int getconnection_id(IP_Port ip_port) { uint32_t i; for(i = 0; i < MAX_CONNECTIONS; ++i) - { if(connections[i].ip_port.ip.i == ip_port.ip.i && connections[i].ip_port.port == ip_port.port && connections[i].status > 0) - { return i; - } - } return -1; } /* table of random numbers used below. */ static uint32_t randtable[6][256]; - /* generate a handshake_id which depends on the ip_port. this function will always give one unique handshake_id per ip_port. TODO: make this better */ uint32_t handshake_id(IP_Port source) { uint32_t id = 0, i; - for(i = 0; i < 6; ++i) - { + for(i = 0; i < 6; ++i) { if(randtable[i][((uint8_t *)&source)[i]] == 0) - { randtable[i][((uint8_t *)&source)[i]] = random_int(); - } id ^= randtable[i][((uint8_t *)&source)[i]]; } if(id == 0) /* id can't be zero */ - { id = 1; - } return id; } + /* change the hnshake id associated with that ip_port TODO: make this better */ void change_handshake(IP_Port source) @@ -146,7 +134,6 @@ void change_handshake(IP_Port source) randtable[rand][((uint8_t *)&source)[rand]] = random_int(); } - /* initialize a new connection to ip_port returns an integer corresponding to the connection id. return -1 if it could not initialize the connection. @@ -155,14 +142,10 @@ int new_connection(IP_Port ip_port) { int connect = getconnection_id(ip_port); if(connect != -1) - { return connect; - } uint32_t i; - for(i = 0; i < MAX_CONNECTIONS; ++i) - { - if(connections[i].status == 0) - { + for(i = 0; i < MAX_CONNECTIONS; ++i) { + if(connections[i].status == 0) { memset(&connections[i], 0, sizeof(Connection)); connections[i].ip_port = ip_port; connections[i].status = 1; @@ -191,14 +174,10 @@ int new_connection(IP_Port ip_port) int new_inconnection(IP_Port ip_port) { if(getconnection_id(ip_port) != -1) - { return -1; - } uint32_t i; - for(i = 0; i < MAX_CONNECTIONS; ++i) - { - if(connections[i].status == 0) - { + for(i = 0; i < MAX_CONNECTIONS; ++i) { + if(connections[i].status == 0) { memset(&connections[i], 0, sizeof(Connection)); connections[i].ip_port = ip_port; connections[i].status = 2; @@ -224,13 +203,10 @@ int incoming_connection() { uint32_t i; for(i = 0; i < MAX_CONNECTIONS; ++i) - { - if(connections[i].inbound == 2) - { + if(connections[i].inbound == 2) { connections[i].inbound = 1; return i; } - } return -1; } @@ -239,14 +215,11 @@ int incoming_connection() int kill_connection(int connection_id) { if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) - { - if(connections[connection_id].status > 0) - { + if(connections[connection_id].status > 0) { connections[connection_id].status = 0; change_handshake(connections[connection_id].ip_port); return 0; } - } return -1; } @@ -256,13 +229,10 @@ int kill_connection(int connection_id) int kill_connection_in(int connection_id, uint32_t seconds) { if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) - { - if(connections[connection_id].status > 0) - { + if(connections[connection_id].status > 0) { connections[connection_id].killat = current_time() + 1000000UL*seconds; return 0; } - } return -1; } @@ -275,9 +245,7 @@ int kill_connection_in(int connection_id, uint32_t seconds) int is_connected(int connection_id) { if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) - { return connections[connection_id].status; - } return 0; } @@ -285,9 +253,7 @@ int is_connected(int connection_id) IP_Port connection_ip(int connection_id) { if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) - { return connections[connection_id].ip_port; - } IP_Port zero = {{{0}}, 0}; return zero; } @@ -309,17 +275,15 @@ uint32_t recvqueue(int connection_id) char id_packet(int connection_id) { if(recvqueue(connection_id) != 0 && connections[connection_id].status != 0) - { return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; - } return -1; } + /* return 0 if there is no received data in the buffer. return length of received packet if successful */ int read_packet(int connection_id, uint8_t * data) { - if(recvqueue(connection_id) != 0) - { + if(recvqueue(connection_id) != 0) { uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; uint16_t size = connections[connection_id].recvbuffer[index].size; memcpy(data, connections[connection_id].recvbuffer[index].data, size); @@ -335,15 +299,10 @@ int read_packet(int connection_id, uint8_t * data) int write_packet(int connection_id, uint8_t * data, uint32_t length) { if(length > MAX_DATA_SIZE) - { return 0; - } if(length == 0) - { return 0; - } - if(sendqueue(connection_id) < BUFFER_PACKET_NUM) - { + if(sendqueue(connection_id) < BUFFER_PACKET_NUM) { uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; memcpy(connections[connection_id].sendbuffer[index].data, data, length); connections[connection_id].sendbuffer[index].size = length; @@ -353,9 +312,6 @@ int write_packet(int connection_id, uint8_t * data, uint32_t length) return 0; } - - - /* put the packet numbers the we are missing in requested and return the number */ uint32_t missing_packets(int connection_id, uint32_t * requested) { @@ -363,59 +319,47 @@ uint32_t missing_packets(int connection_id, uint32_t * requested) uint32_t i; uint32_t temp; if(recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1)) /* don't request packets if the buffer is full. */ - { return 0; - } for(i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++ ) - { - if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) - { + if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) { temp = htonl(i); memcpy(requested + number, &temp, 4); ++number; } - } if(number == 0) - { connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; - } return number; - } /* Packet sending functions One per packet type. see docs/Lossless_UDP.txt for more information. */ - - int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) { uint8_t packet[1 + 4 + 4]; uint32_t temp; - + packet[0] = 16; temp = htonl(handshake_id1); memcpy(packet + 1, &temp, 4); temp = htonl(handshake_id2); memcpy(packet + 5, &temp, 4); return sendpacket(ip_port, packet, sizeof(packet)); - } - int send_SYNC(uint32_t connection_id) { - + uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; uint16_t index = 0; - + IP_Port ip_port = connections[connection_id].ip_port; uint8_t counter = connections[connection_id].send_counter; uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum); uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum); uint32_t requested[BUFFER_PACKET_NUM]; uint32_t number = missing_packets(connection_id, requested); - + packet[0] = 17; index += 1; memcpy(packet + index, &counter, 1); @@ -427,7 +371,7 @@ int send_SYNC(uint32_t connection_id) memcpy(packet + index, requested, 4 * number); return sendpacket(ip_port, packet, (number*4 + 4 + 4 + 2)); - + } int send_data_packet(uint32_t connection_id, uint32_t packet_num) @@ -449,16 +393,14 @@ int send_DATA(uint32_t connection_id) { int ret; uint32_t buffer[BUFFER_PACKET_NUM]; - if(connections[connection_id].num_req_paquets > 0) - { + if(connections[connection_id].num_req_paquets > 0) { ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]); connections[connection_id].num_req_paquets--; memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4); memcpy(connections[connection_id].req_packets, buffer, connections[connection_id].num_req_paquets * 4); return ret; } - if(connections[connection_id].sendbuff_packetnum != connections[connection_id].sent_packetnum) - { + if(connections[connection_id].sendbuff_packetnum != connections[connection_id].sent_packetnum) { ret = send_data_packet(connection_id, connections[connection_id].sent_packetnum); connections[connection_id].sent_packetnum++; return ret; @@ -468,17 +410,13 @@ int send_DATA(uint32_t connection_id) /* END of packet sending functions */ - - /* Packet handling functions One to handle each type of packets we receive return 0 if handled correctly, 1 if packet is bad. */ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) { if(length != (1 + 4 + 4)) - { return 1; - } uint32_t temp; uint32_t handshake_id1, handshake_id2; int connection = getconnection_id(source); @@ -487,17 +425,13 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) memcpy(&temp, packet + 5, 4); handshake_id2 = ntohl(temp); - if(handshake_id2 == 0) - { + if(handshake_id2 == 0) { send_handshake(source, handshake_id(source), handshake_id1); return 0; } if(is_connected(connection) != 1) - { return 1; - } - if(handshake_id2 == connections[connection].handshake_id1) /* if handshake_id2 is what we sent previously as handshake_id1 */ - { + if(handshake_id2 == connections[connection].handshake_id1) { /* if handshake_id2 is what we sent previously as handshake_id1 */ connections[connection].status = 2; /* NOTE: is this necessary? connections[connection].handshake_id2 = handshake_id1; */ @@ -515,25 +449,19 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) int SYNC_valid(uint32_t length) { if(length < 4 + 4 + 2) - { return 0; - } if(length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) || ((length - 4 - 4 - 2) % 4) != 0) - { return 0; - } return 1; } /* case 1: */ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) { - if(handshake_id(source) == recv_packetnum) - { + if(handshake_id(source) == recv_packetnum) { int x = new_inconnection(source); - if(x != -1) - { + if(x != -1) { connections[x].orecv_packetnum = recv_packetnum; connections[x].sent_packetnum = recv_packetnum; connections[x].sendbuff_packetnum = recv_packetnum; @@ -551,9 +479,8 @@ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnu /* case 2: */ int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) { - if(recv_packetnum == connections[connection_id].orecv_packetnum) + if(recv_packetnum == connections[connection_id].orecv_packetnum) { /* && sent_packetnum == connections[connection_id].osent_packetnum) */ - { connections[connection_id].status = 3; connections[connection_id].recv_counter = counter; ++connections[connection_id].send_counter; @@ -572,16 +499,14 @@ int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, ui uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */ uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum); uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum); - if(comp_1 <= BUFFER_PACKET_NUM && comp_2 <= BUFFER_PACKET_NUM && comp_counter < 10 && comp_counter != 0) /* packet valid */ - { + if(comp_1 <= BUFFER_PACKET_NUM && comp_2 <= BUFFER_PACKET_NUM && comp_counter < 10 && comp_counter != 0) { /* packet valid */ connections[connection_id].orecv_packetnum = recv_packetnum; connections[connection_id].osent_packetnum = sent_packetnum; connections[connection_id].successful_sent = recv_packetnum; connections[connection_id].last_recvSYNC = current_time(); connections[connection_id].recv_counter = counter; ++connections[connection_id].send_counter; - for(i = 0; i < number; ++i) - { + for(i = 0; i < number; ++i) { temp = ntohl(req_packets[i]); memcpy(connections[connection_id].req_packets + i, &temp, 4 * number); } @@ -595,9 +520,7 @@ int handle_SYNC(uint8_t * packet, uint32_t length, IP_Port source) { if(!SYNC_valid(length)) - { return 1; - } int connection = getconnection_id(source); uint8_t counter; uint32_t temp; @@ -611,21 +534,13 @@ int handle_SYNC(uint8_t * packet, uint32_t length, IP_Port source) memcpy(&temp,packet + 6, 4); sent_packetnum = ntohl(temp); if(number != 0) - { memcpy(req_packets, packet + 10, 4 * number); - } if(connection == -1) - { return handle_SYNC1(source, recv_packetnum, sent_packetnum); - } if(connections[connection].status == 2) - { return handle_SYNC2(connection, counter, recv_packetnum, sent_packetnum); - } if(connections[connection].status == 3) - { return handle_SYNC3(connection, counter, recv_packetnum, sent_packetnum, req_packets, number); - } return 0; } @@ -634,37 +549,26 @@ int handle_SYNC(uint8_t * packet, uint32_t length, IP_Port source) int add_recv(int connection_id, uint32_t data_num, uint8_t * data, uint16_t size) { if(size > MAX_DATA_SIZE) - { return 1; - } uint32_t i; uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; - for(i = connections[connection_id].recv_packetnum; i != maxnum; ++i) - { - if(i == data_num) - { + for(i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { + if(i == data_num) { memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; connections[connection_id].last_recvdata = current_time(); if(sent_packet < BUFFER_PACKET_NUM) - { connections[connection_id].osent_packetnum = data_num; - } break; } } - for(i = connections[connection_id].recv_packetnum; i != maxnum; ++i) - { + for(i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) - { connections[connection_id].recv_packetnum = i; - } else - { break; - } } return 0; @@ -673,54 +577,43 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t * data, uint16_t size int handle_data(uint8_t * packet, uint32_t length, IP_Port source) { int connection = getconnection_id(source); - + if(connection == -1) - { return 1; - } - + if(connections[connection].status != 3) /* Drop the data packet if connection is not connected. */ - { return 1; - } - + if(length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) - { return 1; - } uint32_t temp; uint32_t number; uint16_t size = length - 1 - 4; - + memcpy(&temp, packet + 1, 4); number = ntohl(temp); return add_recv(connection, number, packet + 5, size); - } /* END of packet handling functions */ - int LosslessUDP_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) { - switch (packet[0]) { case 16: return handle_handshake(packet, length, source); - + case 17: return handle_SYNC(packet, length, source); - + case 18: return handle_data(packet, length, source); - + default: return 1; - } - + return 0; - } /* Send handshake requests @@ -729,28 +622,20 @@ void doNew() { uint32_t i; uint64_t temp_time = current_time(); - for(i = 0; i < MAX_CONNECTIONS; ++i) - { + for(i = 0; i < MAX_CONNECTIONS; ++i) { if(connections[i].status == 1) - { - if((connections[i].last_sent + (1000000UL/connections[i].SYNC_rate)) <= temp_time) - { + if((connections[i].last_sent + (1000000UL/connections[i].SYNC_rate)) <= temp_time) { send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0); connections[i].last_sent = temp_time; } - } /* kill all timed out connections */ if( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && connections[i].status != 4) - { /* kill_connection(i); */ connections[i].status = 4; - } if(connections[i].status > 0 && connections[i].killat < temp_time) - { kill_connection(i); - } } } @@ -758,16 +643,12 @@ void doSYNC() { uint32_t i; uint64_t temp_time = current_time(); - for(i = 0; i < MAX_CONNECTIONS; ++i) - { + for(i = 0; i < MAX_CONNECTIONS; ++i) { if(connections[i].status == 2 || connections[i].status == 3) - { - if((connections[i].last_SYNC + (1000000UL/connections[i].SYNC_rate)) <= temp_time) - { + if((connections[i].last_SYNC + (1000000UL/connections[i].SYNC_rate)) <= temp_time) { send_SYNC(i); connections[i].last_SYNC = temp_time; } - } } } @@ -777,19 +658,12 @@ void doData() uint64_t j; uint64_t temp_time = current_time(); for(i = 0; i < MAX_CONNECTIONS; ++i) - { if(connections[i].status == 3 && sendqueue(i) != 0) - { - if((connections[i].last_sent + (1000000UL/connections[i].data_rate)) <= temp_time) - { + if((connections[i].last_sent + (1000000UL/connections[i].data_rate)) <= temp_time) { for(j = connections[i].last_sent; j < temp_time; j += (1000000UL/connections[i].data_rate)) - { send_DATA(i); - } connections[i].last_sent = temp_time; } - } - } } /* TODO: flow control. @@ -801,33 +675,22 @@ void adjustRates() { uint32_t i; uint64_t temp_time = current_time(); - for(i = 0; i < MAX_CONNECTIONS; ++i) - { + for(i = 0; i < MAX_CONNECTIONS; ++i) { if(connections[i].status == 1 || connections[i].status == 2) - { connections[i].SYNC_rate = MAX_SYNC_RATE; - } - if(connections[i].status == 3) - { - if(sendqueue(i) != 0) - { - + if(connections[i].status == 3) { + if(sendqueue(i) != 0) { connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE; - connections[i].SYNC_rate = MAX_SYNC_RATE; - } else if(connections[i].last_recvdata + 1000000UL > temp_time) - { connections[i].SYNC_rate = MAX_SYNC_RATE; - } else - { connections[i].SYNC_rate = SYNC_RATE; - } } - } + } } + /* Call this function a couple times per second It's the main loop. */ void doLossless_UDP() @@ -836,6 +699,4 @@ void doLossless_UDP() doSYNC(); doData(); adjustRates(); - - } diff --git a/core/Lossless_UDP.h b/core/Lossless_UDP.h index 0f5bb119..a9f1bb15 100644 --- a/core/Lossless_UDP.h +++ b/core/Lossless_UDP.h @@ -1,26 +1,25 @@ /* Lossless_UDP.h -* -* An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt -* - - Copyright (C) 2013 Tox project All Rights Reserved. - - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ + * + * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ #ifndef LOSSLESS_UDP_H #define LOSSLESS_UDP_H @@ -34,8 +33,6 @@ extern "C" { /* maximum length of the data in the data packets */ #define MAX_DATA_SIZE 1024 - - /* Functions */ /* initialize a new connection to ip_port @@ -53,7 +50,6 @@ int getconnection_id(IP_Port ip_port); return -1 if there are no new incoming connections in the list. */ int incoming_connection(); - /* return -1 if it could not kill the connection. return 0 if killed successfully */ int kill_connection(int connection_id); @@ -75,21 +71,16 @@ char id_packet(int connection_id); return length of received packet if successful */ int read_packet(int connection_id, uint8_t * data); - /* return 0 if data could not be put in packet queue return 1 if data was put into the queue */ int write_packet(int connection_id, uint8_t * data, uint32_t length); - - /* returns the number of packets in the queue waiting to be successfully sent. */ uint32_t sendqueue(int connection_id); - /* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */ uint32_t recvqueue(int connection_id); - /* check if connection is connected return 0 no. return 1 if attempting handshake @@ -98,7 +89,6 @@ uint32_t recvqueue(int connection_id); return 4 if timed out and wating to be killed */ int is_connected(int connection_id); - /* Call this function a couple times per second It's the main loop. */ void doLossless_UDP(); diff --git a/core/Messenger.c b/core/Messenger.c index 043700e5..69d33172 100644 --- a/core/Messenger.c +++ b/core/Messenger.c @@ -1,26 +1,25 @@ /* Messenger.c -* -* An implementation of a simple text chat only messenger on the tox network core. -* - - Copyright (C) 2013 Tox project All Rights Reserved. - - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ + * + * An implementation of a simple text chat only messenger on the tox network core. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ #include "Messenger.h" #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -39,8 +38,6 @@ typedef struct uint8_t userstatus_sent; uint16_t info_size; /* length of the info */ }Friend; - - uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; @@ -58,26 +55,20 @@ static uint32_t numfriends; 0 if we are offline static uint8_t online; */ - /* return the friend id associated to that public key. return -1 if no such friend */ int getfriend_id(uint8_t * client_id) { uint32_t i; + for(i = 0; i < numfriends; ++i) - { if(friendlist[i].status > 0) - { if(memcmp(client_id, friendlist[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) - { return i; - } - } - } + return -1; } - /* copies the public key associated to that friend id into client_id buffer. make sure that client_id is of size CLIENT_ID_SIZE. return 0 if success @@ -85,19 +76,16 @@ int getfriend_id(uint8_t * client_id) int getclient_id(int friend_id, uint8_t * client_id) { if(friend_id >= numfriends || friend_id < 0) - { return -1; - } - if(friendlist[friend_id].status > 0) - { + if(friendlist[friend_id].status > 0) { memcpy(client_id, friendlist[friend_id].client_id, CLIENT_ID_SIZE); return 0; } + return -1; } - /* add a friend set the data that will be sent along with friend request client_id is the client id of the friend @@ -108,17 +96,11 @@ int m_addfriend(uint8_t * client_id, uint8_t * data, uint16_t length) { if(length == 0 || length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) - { return -1; - } if(memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) - { return -1; - } if(getfriend_id(client_id) != -1) - { return -1; - } uint32_t i; for(i = 0; i <= numfriends; ++i) { @@ -144,9 +126,7 @@ int m_addfriend(uint8_t * client_id, uint8_t * data, uint16_t length) int m_addfriend_norequest(uint8_t * client_id) { if(getfriend_id(client_id) != -1) - { return -1; - } uint32_t i; for(i = 0; i <= numfriends; ++i) { @@ -172,9 +152,7 @@ int m_addfriend_norequest(uint8_t * client_id) int m_delfriend(int friendnumber) { if(friendnumber >= numfriends || friendnumber < 0) - { return -1; - } DHT_delfriend(friendlist[friendnumber].client_id); crypto_kill(friendlist[friendnumber].crypt_connection_id); @@ -182,17 +160,12 @@ int m_delfriend(int friendnumber) memset(&friendlist[friendnumber], 0, sizeof(Friend)); uint32_t i; for(i = numfriends; i != 0; --i) - { if(friendlist[i].status != 0) - { break; - } - } numfriends = i; return 0; } - /* return 4 if friend is online return 3 if friend is confirmed return 2 if the friend request was sent @@ -201,27 +174,20 @@ int m_delfriend(int friendnumber) int m_friendstatus(int friendnumber) { if(friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS) - { return 0; - } return friendlist[friendnumber].status; } - /* send a text chat message to an online friend return 1 if packet was successfully put into the send queue return 0 if it was not */ int m_sendmessage(int friendnumber, uint8_t * message, uint32_t length) { if(friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS) - { return 0; - } if(length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ - { return 0; - } uint8_t temp[MAX_DATA_SIZE]; temp[0] = PACKET_ID_MESSAGE; memcpy(temp + 1, message, length); @@ -240,18 +206,14 @@ static int m_sendname(int friendnumber, uint8_t * name) /* set the name of a friend return 0 if success return -1 if failure */ - static int setfriendname(int friendnumber, uint8_t * name) { if(friendnumber >= numfriends || friendnumber < 0) - { return -1; - } memcpy(friendlist[friendnumber].name, name, MAX_NAME_LENGTH); return 0; } - /* Set our nickname name must be a string of maximum MAX_NAME_LENGTH length. return 0 if success @@ -259,15 +221,11 @@ static int setfriendname(int friendnumber, uint8_t * name) int setname(uint8_t * name, uint16_t length) { if(length > MAX_NAME_LENGTH) - { return -1; - } memcpy(self_name, name, length); uint32_t i; for(i = 0; i < numfriends; ++i) - { friendlist[i].name_sent = 0; - } return 0; } @@ -279,9 +237,7 @@ int setname(uint8_t * name, uint16_t length) int getname(int friendnumber, uint8_t * name) { if(friendnumber >= numfriends || friendnumber < 0) - { return -1; - } memcpy(name, friendlist[friendnumber].name, MAX_NAME_LENGTH); return 0; } @@ -289,9 +245,7 @@ int getname(int friendnumber, uint8_t * name) int m_set_userstatus(uint8_t *status, uint16_t length) { if(length > MAX_USERSTATUS_LENGTH) - { return -1; - } uint8_t *newstatus = calloc(length, 1); memcpy(newstatus, status, length); free(self_userstatus); @@ -300,9 +254,7 @@ int m_set_userstatus(uint8_t *status, uint16_t length) uint32_t i; for(i = 0; i < numfriends; ++i) - { friendlist[i].userstatus_sent = 0; - } return 0; } @@ -311,9 +263,7 @@ int m_set_userstatus(uint8_t *status, uint16_t length) int m_get_userstatus_size(int friendnumber) { if(friendnumber >= numfriends || friendnumber < 0) - { return -1; - } return friendlist[friendnumber].userstatus_length; } @@ -322,9 +272,7 @@ int m_get_userstatus_size(int friendnumber) int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen) { if(friendnumber >= numfriends || friendnumber < 0) - { return -1; - } memset(buf, 0, maxlen); memcpy(buf, friendlist[friendnumber].userstatus, MIN(maxlen, MAX_USERSTATUS_LENGTH) - 1); return 0; @@ -343,9 +291,7 @@ static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length) static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t length) { if(friendnumber >= numfriends || friendnumber < 0) - { return -1; - } uint8_t *newstatus = calloc(length, 1); memcpy(newstatus, status, length); free(friendlist[friendnumber].userstatus); @@ -353,17 +299,15 @@ static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t le friendlist[friendnumber].userstatus_length = length; return 0; } -/* -static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); -static uint8_t friend_request_isset = 0; -*/ + +/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); +static uint8_t friend_request_isset = 0; */ /* set the function that will be executed when a friend request is received. */ void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)) { callback_friendrequest(function); } - static void (*friend_message)(int, uint8_t *, uint16_t); static uint8_t friend_message_isset = 0; @@ -374,7 +318,6 @@ void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)) friend_message_isset = 1; } - static void (*friend_namechange)(int, uint8_t *, uint16_t); static uint8_t friend_namechange_isset = 0; void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)) @@ -402,9 +345,9 @@ int initMessenger() ip.i = 0; if(init_networking(ip,PORT) == -1) - return -1; - - return 0; + return -1; + + return 0; } static void doFriends() @@ -417,16 +360,12 @@ static void doFriends() if(friendlist[i].status == 1) { int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); - if(fr == 0)/*TODO: This needs to be fixed so that it sends the friend requests a couple of times in case - of packet loss*/ - { + if(fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case + of packet loss */ friendlist[i].status = 2; - } else if(fr > 0) - { friendlist[i].status = 2; - } } if(friendlist[i].status == 2 || friendlist[i].status == 3) /* friend is not online */ { @@ -436,12 +375,10 @@ static void doFriends() { send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); friendlist[i].friend_request_id = unix_time(); - } } IP_Port friendip = DHT_getfriendip(friendlist[i].client_id); - switch(is_cryptoconnected(friendlist[i].crypt_connection_id)) - { + switch(is_cryptoconnected(friendlist[i].crypt_connection_id)) { case 0: if (friendip.ip.i > 1) friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip); @@ -460,19 +397,11 @@ static void doFriends() while(friendlist[i].status == 4) /* friend is online */ { if(friendlist[i].name_sent == 0) - { if(m_sendname(i, self_name)) - { friendlist[i].name_sent = 1; - } - } if(friendlist[i].userstatus_sent == 0) - { if(send_userstatus(i, self_userstatus, self_userstatus_len)) - { friendlist[i].userstatus_sent = 1; - } - } len = read_cryptpacket(friendlist[i].crypt_connection_id, temp); if(len > 0) { @@ -500,9 +429,7 @@ static void doFriends() } case PACKET_ID_MESSAGE: { if(friend_message_isset) - { (*friend_message)(i, temp + 1, len - 1); - } break; } } @@ -521,8 +448,6 @@ static void doFriends() } } - - static void doInbound() { uint8_t secret_nonce[crypto_box_NONCEBYTES]; @@ -543,6 +468,22 @@ static void doInbound() } } +/*Interval in seconds between LAN discovery packet sending*/ +#define LAN_DISCOVERY_INTERVAL 60 + +static uint32_t last_LANdiscovery; + +/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/ +static void LANdiscovery() +{ + if(last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) + { + send_LANdiscovery(htons(PORT)); + last_LANdiscovery = unix_time(); + } +} + + /* the main loop that needs to be run at least 200 times per second. */ void doMessenger() { @@ -554,21 +495,19 @@ void doMessenger() #ifdef DEBUG /* if(rand() % 3 != 1) //simulate packet loss */ /* { */ - if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port)) - { + if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port) && + friendreq_handlepacket(data, length, ip_port) && LANdiscovery_handlepacket(data, length, ip_port)) /* if packet is discarded */ printf("Received unhandled packet with length: %u\n", length); - } else - { printf("Received handled packet with length: %u\n", length); - } /* } */ printf("Status: %u %u %u\n",friendlist[0].status ,is_cryptoconnected(friendlist[0].crypt_connection_id), friendlist[0].crypt_connection_id); #else DHT_handlepacket(data, length, ip_port); LosslessUDP_handlepacket(data, length, ip_port); friendreq_handlepacket(data, length, ip_port); + LANdiscovery_handlepacket(data, length, ip_port); #endif } @@ -577,6 +516,7 @@ void doMessenger() doNetCrypto(); doInbound(); doFriends(); + LANdiscovery(); } /* returns the size of the messenger data (for saving) */ @@ -606,13 +546,9 @@ void Messenger_save(uint8_t * data) int Messenger_load(uint8_t * data, uint32_t length) { if(length == ~0) - { return -1; - } if(length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2) - { return -1; - } length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2; load_keys(data); data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; @@ -621,21 +557,15 @@ int Messenger_load(uint8_t * data, uint32_t length) data += sizeof(size); if(length < size) - { return -1; - } length -= size; if(DHT_load(data, size) == -1) - { return -1; - } data += size; memcpy(&size, data, sizeof(size)); data += sizeof(size); if(length != size || length % sizeof(Friend) != 0) - { return -1; - } Friend * temp = malloc(size); memcpy(temp, data, size); diff --git a/core/Messenger.h b/core/Messenger.h index 6afe84ac..1067d156 100644 --- a/core/Messenger.h +++ b/core/Messenger.h @@ -1,35 +1,35 @@ /* Messenger.h -* -* An implementation of a simple text chat only messenger on the tox network core. -* -* NOTE: All the text in the messages must be encoded using UTF-8 - - Copyright (C) 2013 Tox project All Rights Reserved. + * + * An implementation of a simple text chat only messenger on the tox network core. + * + * NOTE: All the text in the messages must be encoded using UTF-8 + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ - - #ifndef MESSENGER_H #define MESSENGER_H #include "net_crypto.h" #include "DHT.h" #include "friend_requests.h" +#include "LAN_discovery.h" #ifdef __cplusplus extern "C" { @@ -79,7 +79,6 @@ int m_delfriend(int friendnumber); return 0 if there is no friend with that number */ int m_friendstatus(int friendnumber); - /* send a text chat message to an online friend returns 1 if packet was successfully put into the send queue return 0 if it was not */ @@ -91,7 +90,6 @@ int m_sendmessage(int friendnumber, uint8_t * message, uint32_t length); return -1 if failure */ int setname(uint8_t * name, uint16_t length); - /* get name of friendnumber put it in name name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. @@ -117,7 +115,6 @@ int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen); function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); - /* set the function that will be executed when a message from a friend is received. function format is: function(int friendnumber, uint8_t * message, uint32_t length) */ void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); @@ -137,11 +134,9 @@ void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)); returns -1 if there are problems */ int initMessenger(); - /* the main loop that needs to be run at least 200 times per second */ void doMessenger(); - /* SAVING AND LOADING FUNCTIONS: */ /* returns the size of the messenger data (for saving) */ diff --git a/core/friend_requests.c b/core/friend_requests.c index 18f0866b..d1b0da57 100644 --- a/core/friend_requests.c +++ b/core/friend_requests.c @@ -2,13 +2,29 @@ * * Handle friend requests. * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ #include "friend_requests.h" uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; - /* Try to send a friendrequest to peer with public_key data is the data in the request and length is the length. return -1 if failure. @@ -18,33 +34,30 @@ int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length) { uint8_t packet[MAX_DATA_SIZE]; int len = create_request(packet, public_key, data, length, 32); /* 32 is friend request packet id */ + if(len == -1) - { return -1; - } + IP_Port ip_port = DHT_getfriendip(public_key); + if(ip_port.ip.i == 1) - { return -1; - } + if(ip_port.ip.i != 0) { if(sendpacket(ip_port, packet, len) != -1) - { return 0; - } return -1; } int num = route_tofriend(public_key, packet, len); + if(num == 0) - { return -1; - } + return num; } - static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t); static uint8_t handle_friendrequest_isset = 0; @@ -56,6 +69,38 @@ void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)) } +/*NOTE: the following is just a temporary fix for the multiple friend requests recieved at the same time problem + TODO: Make this better (This will most likely tie in with the way we will handle spam.)*/ + +#define MAX_RECIEVED_STORED 32 + +static uint8_t recieved_requests[MAX_RECIEVED_STORED][crypto_box_PUBLICKEYBYTES]; +static uint16_t recieved_requests_index; + +/*Add to list of recieved friend requests*/ +static void addto_recievedlist(uint8_t * client_id) +{ + if(recieved_requests_index >= MAX_RECIEVED_STORED) + recieved_requests_index = 0; + + memcpy(recieved_requests[recieved_requests_index], client_id, crypto_box_PUBLICKEYBYTES); + ++recieved_requests_index; +} + +/* Check if a friend request was already recieved + return 0 if not, 1 if we did */ +static int request_recieved(uint8_t * client_id) +{ + uint32_t i; + + for(i = 0; i < MAX_RECIEVED_STORED; ++i) + if(memcmp(recieved_requests[i], client_id, crypto_box_PUBLICKEYBYTES) == 0) + return 1; + + return 0; +} + + int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) { @@ -63,31 +108,27 @@ int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) { if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && length > MAX_DATA_SIZE + ENCRYPTION_PADDING) - { return 1; - } - if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)//check if request is for us. + if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) /* check if request is for us. */ { if(handle_friendrequest_isset == 0) - { return 1; - } + uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; int len = handle_request(public_key, data, packet, length); + if(len == -1) - { return 1; - } + if(request_recieved(public_key)) + return 1; + + addto_recievedlist(public_key); (*handle_friendrequest)(public_key, data, len); } - else//if request is not for us, try routing it. - { + else /* if request is not for us, try routing it. */ if(route_packet(packet + 1, packet, length) == length) - { return 0; - } - } } return 1; -} \ No newline at end of file +} diff --git a/core/friend_requests.h b/core/friend_requests.h index de116b33..29bc2b88 100644 --- a/core/friend_requests.h +++ b/core/friend_requests.h @@ -2,13 +2,28 @@ * * Handle friend requests. * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ - #ifndef FRIEND_REQUESTS_H #define FRIEND_REQUESTS_H - #include "DHT.h" #include "net_crypto.h" @@ -20,7 +35,6 @@ extern "C" { data is the data in the request and length is the length. */ int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length); - /* set the function that will be executed when a friend request for us is received. function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); @@ -30,8 +44,6 @@ void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); return 1 if it didn't handle the packet or if the packet was shit. */ int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source); - - #ifdef __cplusplus } #endif diff --git a/core/net_crypto.c b/core/net_crypto.c index e01ed695..28cb83e8 100644 --- a/core/net_crypto.c +++ b/core/net_crypto.c @@ -1,38 +1,35 @@ /* net_crypto.c -* -* Functions for the core network crypto. -* See also: docs/Crypto.txt -* -* NOTE: This code has to be perfect. We don't mess around with encryption. -* - - Copyright (C) 2013 Tox project All Rights Reserved. - - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ + * + * Functions for the core network crypto. + * See also: docs/Crypto.txt + * + * NOTE: This code has to be perfect. We don't mess around with encryption. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ #include "net_crypto.h" - /* Our public and secret keys. */ uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; - typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */ @@ -65,9 +62,7 @@ int encrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce, uint8_t * plain, uint32_t length, uint8_t * encrypted) { if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0) - { return -1; - } uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0}; uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; @@ -79,9 +74,8 @@ int encrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce, /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero */ if(memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0) - { return -1; - } + /* unpad the encrypted message */ memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES; @@ -95,9 +89,8 @@ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce, uint8_t * encrypted, uint32_t length, uint8_t * plain) { if(length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) - { return -1; - } + uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES]; uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; uint8_t zeroes[crypto_box_ZEROBYTES] = {0}; @@ -106,14 +99,12 @@ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce, if(crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, public_key, secret_key) == -1) - { return -1; - } + /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */ if(memcmp(temp_plain, zeroes, crypto_box_ZEROBYTES) != 0) - { return -1; - } + /* unpad the plain message */ memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES); return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; @@ -123,13 +114,10 @@ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce, void increment_nonce(uint8_t * nonce) { uint32_t i; - for(i = 0; i < crypto_box_NONCEBYTES; ++i) - { + for(i = 0; i < crypto_box_NONCEBYTES; ++i) { ++nonce[i]; if(nonce[i] != 0) - { break; - } } } @@ -137,8 +125,7 @@ void increment_nonce(uint8_t * nonce) void random_nonce(uint8_t * nonce) { uint32_t i, temp; - for (i = 0; i < crypto_box_NONCEBYTES / 4; ++i) - { + for (i = 0; i < crypto_box_NONCEBYTES / 4; ++i) { temp = random_int(); memcpy(nonce + 4 * i, &temp, 4); } @@ -150,64 +137,44 @@ void random_nonce(uint8_t * nonce) int read_cryptpacket(int crypt_connection_id, uint8_t * data) { if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) - { return 0; - } if(crypto_connections[crypt_connection_id].status != 3) - { return 0; - } uint8_t temp_data[MAX_DATA_SIZE]; int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data); if(length == 0) - { return 0; - } if(temp_data[0] != 3) - { return -1; - } int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, crypto_connections[crypt_connection_id].sessionsecret_key, crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data); - if(len != -1) - { + if(len != -1) { increment_nonce(crypto_connections[crypt_connection_id].recv_nonce); return len; } return -1; } - /* return 0 if data could not be put in packet queue return 1 if data was put into the queue */ int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length) { if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) - { return 0; - } if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) - { return 0; - } if(crypto_connections[crypt_connection_id].status != 3) - { return 0; - } uint8_t temp_data[MAX_DATA_SIZE]; int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, crypto_connections[crypt_connection_id].sessionsecret_key, crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); if(len == -1) - { return 0; - } temp_data[0] = 3; if(write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) - { return 0; - } increment_nonce(crypto_connections[crypt_connection_id].sent_nonce); return 1; } @@ -221,17 +188,13 @@ int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length) int create_request(uint8_t * packet, uint8_t * public_key, uint8_t * data, uint32_t length, uint8_t request_id) { if(MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING) - { return -1; - } uint8_t nonce[crypto_box_NONCEBYTES]; random_nonce(nonce); int len = encrypt_data(public_key, self_secret_key, nonce, data, length, 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); if(len == -1) - { return -1; - } packet[0] = request_id; memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES); @@ -257,18 +220,13 @@ int handle_request(uint8_t * public_key, uint8_t * data, uint8_t * packet, uint1 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), data); if(len1 == -1) - { return -1; - } return len1; } else - { return -1; - } } - /* Send a crypto handshake packet containing an encrypted secret nonce and session public key to peer with connection_id and public_key the packet is encrypted with a random nonce which is sent in plain text with the packet */ @@ -285,9 +243,7 @@ int send_cryptohandshake(int connection_id, uint8_t * public_key, uint8_t * secr int len = encrypt_data(public_key, self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); if(len == -1) - { return 0; - } temp_data[0] = 2; memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); @@ -307,9 +263,7 @@ int handle_cryptohandshake(uint8_t * public_key, uint8_t * secret_nonce, return 0; } if(data[0] != 2) - { return 0; - } uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); @@ -319,18 +273,13 @@ int handle_cryptohandshake(uint8_t * public_key, uint8_t * secret_nonce, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); if(len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES) - { return 0; - } memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); return 1; } - - - /* get crypto connection id from public key of peer return -1 if there are no connections like we are looking for return id if it found it */ @@ -338,19 +287,12 @@ int getcryptconnection_id(uint8_t * public_key) { uint32_t i; for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) - { if(crypto_connections[i].status > 0) - { if(memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) - { return i; - } - } - } return -1; } - /* Start a secure connection with other peer who has public_key and ip_port returns -1 if failure returns crypt_connection_id of the initialized connection if everything went well. */ @@ -358,23 +300,17 @@ int crypto_connect(uint8_t * public_key, IP_Port ip_port) { uint32_t i; int id = getcryptconnection_id(public_key); - if(id != -1) - { + if(id != -1) { IP_Port c_ip = connection_ip(crypto_connections[id].number); if(c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port) - { return -1; - } } for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { - if(crypto_connections[i].status == 0) - { + if(crypto_connections[i].status == 0) { int id = new_connection(ip_port); if(id == -1) - { return -1; - } crypto_connections[i].number = id; crypto_connections[i].status = 1; random_nonce(crypto_connections[i].recv_nonce); @@ -405,20 +341,16 @@ int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * sessi uint32_t i; for(i = 0; i < MAX_INCOMING; ++i) { - if(incoming_connections[i] != -1) - { - if(is_connected(incoming_connections[i]) == 4 || is_connected(incoming_connections[i]) == 0) - { + if(incoming_connections[i] != -1) { + if(is_connected(incoming_connections[i]) == 4 || is_connected(incoming_connections[i]) == 0) { kill_connection(incoming_connections[i]); incoming_connections[i] = -1; continue; } - if(id_packet(incoming_connections[i]) == 2) - { + if(id_packet(incoming_connections[i]) == 2) { uint8_t temp_data[MAX_DATA_SIZE]; uint16_t len = read_packet(incoming_connections[i], temp_data); - if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) - { + if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) { int connection_id = incoming_connections[i]; incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */ return connection_id; @@ -435,11 +367,8 @@ int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * sessi int crypto_kill(int crypt_connection_id) { if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) - { return 1; - } - if(crypto_connections[crypt_connection_id].status != 0) - { + if(crypto_connections[crypt_connection_id].status != 0) { crypto_connections[crypt_connection_id].status = 0; kill_connection(crypto_connections[crypt_connection_id].number); crypto_connections[crypt_connection_id].number = ~0; @@ -448,7 +377,6 @@ int crypto_kill(int crypt_connection_id) return 1; } - /* accept an incoming connection using the parameters provided by crypto_inbound return -1 if not successful returns the crypt_connection_id if successful */ @@ -456,9 +384,7 @@ int accept_crypto_inbound(int connection_id, uint8_t * public_key, uint8_t * sec { uint32_t i; if(connection_id == -1) - { return -1; - } /* if(getcryptconnection_id(public_key) != -1) { @@ -466,8 +392,7 @@ int accept_crypto_inbound(int connection_id, uint8_t * public_key, uint8_t * sec }*/ for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { - if(crypto_connections[i].status == 0) - { + if(crypto_connections[i].status == 0) { crypto_connections[i].number = connection_id; crypto_connections[i].status = 2; random_nonce(crypto_connections[i].recv_nonce); @@ -494,19 +419,16 @@ int accept_crypto_inbound(int connection_id, uint8_t * public_key, uint8_t * sec return -1; } -/* return 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet +/* return 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet (we have received a handshake but no empty data packet), 3 if the connection is established. 4 if the connection is timed out and waiting to be killed */ int is_cryptoconnected(int crypt_connection_id) { if(crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS) - { return crypto_connections[crypt_connection_id].status; - } return 0; } - /* Generate our public and private keys Only call this function the first time the program starts. */ void new_keys() @@ -537,10 +459,8 @@ void load_keys(uint8_t * keys) int new_incoming(int id) { uint32_t i; - for(i = 0; i < MAX_INCOMING; ++i) - { - if(incoming_connections[i] == -1) - { + for(i = 0; i < MAX_INCOMING; ++i) { + if(incoming_connections[i] == -1) { incoming_connections[i] = id; return 0; } @@ -553,13 +473,10 @@ int new_incoming(int id) static void handle_incomings() { int income; - while(1) - { + while(1) { income = incoming_connection(); if(income == -1 || new_incoming(income) ) - { break; - } } } @@ -578,17 +495,11 @@ static void receive_crypto() uint16_t len; if(id_packet(crypto_connections[i].number) == 1) /* if the packet is a friend request drop it (because we are already friends) */ - { len = read_packet(crypto_connections[i].number, temp_data); - - } - if(id_packet(crypto_connections[i].number) == 2) /* handle handshake packet. */ - { + if(id_packet(crypto_connections[i].number) == 2) { /* handle handshake packet. */ len = read_packet(crypto_connections[i].number, temp_data); - if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) - { - if(memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) - { + if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) { + if(memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); increment_nonce(crypto_connections[i].sent_nonce); @@ -600,17 +511,14 @@ static void receive_crypto() } } else if(id_packet(crypto_connections[i].number) != -1) - { /* This should not happen kill the connection if it does */ crypto_kill(crypto_connections[i].number); - } } if(crypto_connections[i].status == 2) { - if(id_packet(crypto_connections[i].number) == 3) - { + if(id_packet(crypto_connections[i].number) == 3) { uint8_t temp_data[MAX_DATA_SIZE]; uint8_t data[MAX_DATA_SIZE]; int length = read_packet(crypto_connections[i].number, temp_data); @@ -618,8 +526,7 @@ static void receive_crypto() crypto_connections[i].sessionsecret_key, crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); uint32_t zero = 0; - if(len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) - { + if(len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { increment_nonce(crypto_connections[i].recv_nonce); crypto_connections[i].status = 3; @@ -627,18 +534,14 @@ static void receive_crypto() kill_connection_in(crypto_connections[i].number, 3000000); } else - { /* This should not happen kill the connection if it does */ crypto_kill(crypto_connections[i].number); - } } else if(id_packet(crypto_connections[i].number) != -1) - { /* This should not happen kill the connection if it does */ crypto_kill(crypto_connections[i].number); - } } } } @@ -651,22 +554,16 @@ void initNetCrypto() memset(incoming_connections, -1 ,sizeof(incoming_connections)); uint32_t i; for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) - { crypto_connections[i].number = ~0; - } } static void killTimedout() { uint32_t i; - for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) - { + for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { if(crypto_connections[i].status != 0 && is_connected(crypto_connections[i].number) == 4) - { crypto_connections[i].status = 4; - } - else if(is_connected(crypto_connections[i].number) == 4) - { + else if(is_connected(crypto_connections[i].number) == 4) { kill_connection(crypto_connections[i].number); crypto_connections[i].number = ~0; } diff --git a/core/net_crypto.h b/core/net_crypto.h index b497f1fb..b5bab17a 100644 --- a/core/net_crypto.h +++ b/core/net_crypto.h @@ -1,26 +1,26 @@ /* net_crypto.h -* -* Functions for the core network crypto. -* - - Copyright (C) 2013 Tox project All Rights Reserved. + * + * Functions for the core network crypto. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ #ifndef NET_CRYPTO_H #define NET_CRYPTO_H @@ -55,13 +55,11 @@ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce, /* fill the given nonce with random bytes. */ void random_nonce(uint8_t * nonce); - /* return 0 if there is no received data in the buffer return -1 if the packet was discarded. return length of received data if successful */ int read_cryptpacket(int crypt_connection_id, uint8_t * data); - /* return 0 if data could not be put in packet queue return 1 if data was put into the queue */ int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length); @@ -74,20 +72,17 @@ int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length); returns the length of the created packet on success */ int create_request(uint8_t * packet, uint8_t * public_key, uint8_t * data, uint32_t length, uint8_t request_id); - /* puts the senders public key in the request in public_key, the data from the request in data if a friend or ping request was sent to us and returns the length of the data. packet is the request packet and length is its length return -1 if not valid request. */ int handle_request(uint8_t * public_key, uint8_t * data, uint8_t * packet, uint16_t length); - /* Start a secure connection with other peer who has public_key and ip_port returns -1 if failure returns crypt_connection_id of the initialized connection if everything went well. */ int crypto_connect(uint8_t * public_key, IP_Port ip_port); - /* kill a crypto connection return 0 if killed successfully return 1 if there was a problem. */ @@ -102,7 +97,6 @@ int crypto_kill(int crypt_connection_id); to refuse it just call kill_connection(...) on the connection id */ int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * session_key); - /* accept an incoming connection using the parameters provided by crypto_inbound return -1 if not successful returns the crypt_connection_id if successful */ diff --git a/core/network.c b/core/network.c index d4e25c82..ec234593 100644 --- a/core/network.c +++ b/core/network.c @@ -1,30 +1,28 @@ /* network.h -* -* Functions for the core networking. -* - - Copyright (C) 2013 Tox project All Rights Reserved. - - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ + * + * Functions for the core networking. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ #include "network.h" - /* returns current UNIX time in microseconds (us). */ uint64_t current_time() { @@ -44,8 +42,6 @@ uint64_t current_time() time = 1000000UL*a.tv_sec + a.tv_usec; return time; #endif - - } /* return a random number @@ -69,7 +65,6 @@ int sendpacket(IP_Port ip_port, uint8_t * data, uint32_t length) { ADDR addr = {AF_INET, ip_port.port, ip_port.ip}; return sendto(sock,(char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); - } /* Function to receive data, ip and port of sender is put into ip_port @@ -94,7 +89,6 @@ int receivepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length) ip_port->ip = addr.ip; ip_port->port = addr.port; return 0; - } /* initialize networking @@ -103,32 +97,28 @@ int receivepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length) port is in host byte order (this means don't worry about it) returns 0 if no problems returns -1 if there are problems */ -int init_networking(IP ip ,uint16_t port) +int init_networking(IP ip, uint16_t port) { #ifdef WIN32 WSADATA wsaData; if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) - { return -1; - } - #else srandom((uint32_t)current_time()); #endif srand((uint32_t)current_time()); - + /* initialize our socket */ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - /* Check for socket error */ - #ifdef WIN32 - if (sock == INVALID_SOCKET) //MSDN recommends this - return -1; - #else - if (sock < 0) - return -1; - #endif - + /* Check for socket error */ + #ifdef WIN32 + if (sock == INVALID_SOCKET) /* MSDN recommends this */ + return -1; + #else + if (sock < 0) + return -1; + #endif /* Functions to increase the size of the send and receive UDP buffers NOTE: uncomment if necessary */ @@ -140,10 +130,13 @@ int init_networking(IP ip ,uint16_t port) } if(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&n, sizeof(n)) == -1) - { return -1; - }*/ + */ + /* Enable broadcast on socket */ + int broadcast = 1; + setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof(broadcast)); + /* Set socket nonblocking */ #ifdef WIN32 /* I think this works for windows */ @@ -190,11 +183,9 @@ int resolve_addr(char *address) int success = getaddrinfo(address, "7", &hints, &server); if(success != 0) - { return -1; - } int resolved = ((struct sockaddr_in*)server->ai_addr)->sin_addr.s_addr; freeaddrinfo(server); return resolved; -} \ No newline at end of file +} diff --git a/core/network.h b/core/network.h index 3b999cec..eaf12003 100644 --- a/core/network.h +++ b/core/network.h @@ -1,27 +1,25 @@ /* network.h -* -* Datatypes, functions and includes for the core networking. -* - - Copyright (C) 2013 Tox project All Rights Reserved. - - This file is part of Tox. - - Tox is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Tox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Tox. If not, see . - -*/ - + * + * Datatypes, functions and includes for the core networking. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ #ifndef NETWORK_H #define NETWORK_H @@ -32,8 +30,6 @@ #include #include - - #ifdef WIN32 /* Put win32 includes here */ //Windows XP #define WINVER 0x0501 @@ -99,7 +95,6 @@ typedef struct #endif }ADDR; - /* returns current time in milleseconds since the epoch. */ uint64_t current_time(); diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 0bacccd9..8942c237 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -6,6 +6,25 @@ * gcc -O2 -Wall -D VANILLA_NACL -o bootstrap_server ../core/Lossless_UDP.c ../core/network.c ../core/net_crypto.c ../core/Messenger.c ../core/DHT.c ../core/friend_requests.c ../nacl/build/${HOSTNAME%.*}/lib/amd64/{cpucycles.o,libnacl.a,randombytes.o} DHT_bootstrap.c * * gcc -O2 -Wall -o bootstrap_server ../core/Lossless_UDP.c ../core/network.c ../core/net_crypto.c ../core/Messenger.c ../core/DHT.c ../core/friend_requests.c -lsodium DHT_bootstrap.c + * + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ #include "../core/DHT.h" @@ -22,12 +41,14 @@ #define PORT 33445 +//TODO: rewrite unsigned char * hex_string_to_bin(char hex_string[]) { - unsigned char * val = malloc(strlen(hex_string)); + size_t len = strlen(hex_string); + unsigned char * val = malloc(len); char * pos = hex_string; int i=0; - while(i < strlen(hex_string)) + while(i < len) { sscanf(pos,"%2hhx",&val[i]); pos+=2; @@ -120,4 +141,4 @@ int main(int argc, char *argv[]) } shutdown_networking(); return 0; -} \ No newline at end of file +} diff --git a/other/bootstrap_serverdaemon/CMakeLists.txt b/other/bootstrap_serverdaemon/CMakeLists.txt index bc717d4b..6aa4dbee 100644 --- a/other/bootstrap_serverdaemon/CMakeLists.txt +++ b/other/bootstrap_serverdaemon/CMakeLists.txt @@ -6,4 +6,5 @@ set(exe_name DHT_bootstrap_daemon) add_executable(${exe_name} DHT_bootstrap_daemon.c) +target_link_libraries(${exe_name} config) linkCoreLibraries(${exe_name}) diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c index 4d79c48b..8e278b28 100644 --- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c +++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c @@ -1,50 +1,323 @@ /* DHT boostrap -* -* A simple DHT boostrap server for tox (daemon edition) -*/ - + * + * A simple DHT boostrap server for tox - daemon edition. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + #include /* pid_t */ #include /* umask */ -#include -#include #include /* POSIX things */ #include - + +#include +#include +#include +#include /* htons() */ +#include /* strcpy() */ + #include "../../core/DHT.h" #include "../../core/friend_requests.h" - -/* Sleep function (x = milliseconds) */ -#ifdef WIN32 -#define c_sleep(x) Sleep(1*x) -#else -#include -#define c_sleep(x) usleep(1000*x) -#endif - -#define PORT 33445 -#define USERNAME getenv("USER") -#define PIDFILE "/home/%s/.bootstrap_server.pid" /* %s represents the unser's name */ - +#define DEFAULT_PORT 33445 +#define DEFAULT_PID_FILE "bootstrap_server.pid" +#define DEFAULT_KEYS_FILE "bootstrap_server.keys" + +/* Server info struct */ +struct server_info_s { + int valid; + IP_Port conn; + uint8_t bs_pk[32]; +}; + +/* This is the struct configure_server() uses to return its data to */ +struct server_conf_s { + int err; + int port; + char pid_file[512]; + char keys_file[512]; + struct server_info_s info[32]; +}; + +int b16_to_key(char b16_string[], uint8_t *bs_pubkey) { + + int i; + unsigned int num1 = 0, num2 = 0; + + for(i = 0; i < 32; ++i) + { + sscanf(&b16_string[i*2], "%1X", &num1); + sscanf(&b16_string[i*2+1], "%1X", &num2); + num1 = num1 << 4; + bs_pubkey[i] = bs_pubkey[i] | num1; + bs_pubkey[i] = bs_pubkey[i] | num2; + } + return 0; +} + +/* This unction connects to all specified servers +and connect to them. +returns 1 if the connection to the DHT is up +returns -1 if all attempts failed +*/ +int connect_to_servers(struct server_info_s *info) +{ + int i; + int c; + + IP_Port ip_port; + uint8_t data[MAX_UDP_PACKET_SIZE]; + uint32_t length; + + for(i = 0; i < 32; ++i) { + if(info[i].valid) { + /* Actual bootstrapping code goes here */ + //puts("Calling DHT_bootstrap"); + DHT_bootstrap(info[i].conn, info[i].bs_pk); + } + } + + /* Check if we're connected to the DHT */ + for(c = 0; c != 100; ++c) { + usleep(10000); + if(DHT_isconnected()) { + //puts("Connected"); + return 1; + break; + } + if(DHT_isconnected() == 0 && c == 99) { + //puts("Not connected"); + return -1; + break; + } + + doDHT(); + + while(receivepacket(&ip_port, data, &length) != -1) + { + DHT_handlepacket(data, length, ip_port); + } + } + + /* This probably never happens */ + return 0; +} + +void manage_keys(char *keys_file) +{ + const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; + uint8_t keys[KEYS_SIZE]; + + /* TODO: stat the file before trying to open it. We aren't cave people! */ + FILE *keysf = fopen(keys_file, "r"); + if (keysf != NULL) { + /* if file was opened successfully -- load keys */ + size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keysf); + if (read_size != KEYS_SIZE) { + printf("Error while reading the key file\nExiting.\n"); + exit(1); + } else { + printf("Keys loaded successfully\n"); + } + load_keys(keys); + + } else { + /* otherwise save new keys */ + /* Silly work-around to ignore any errors coming from new_keys() */ + new_keys(); + save_keys(keys); + keysf = fopen(keys_file, "w"); + if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) { + printf("Error while writing the key file.\nExiting.\n"); + exit(1); + } else { + printf("Keys saved successfully\n"); + } + } + + fclose(keysf); +} + +/* This reads the configuration file, and returns a struct server_conf_s with: + *an error number: + *-1 = file wasn't read, for whatever reason + *-2 = no bootstrap servers found + *the port + *the location of the keys file + *the location of the PID file + *the list of bootstrap servers +*/ +struct server_conf_s configure_server(char *cfg_file) +{ + config_t cfg; + config_setting_t *server_list; + + /* This one will be strcpy'd into the pid_file array in server_conf */ + const char *pid_file_tmp; + const char *keys_file_tmp; + + /* Remote bootstrap server variables */ + int bs_port; + const char *bs_ip; + const char *bs_pk; + + /* The big struct */ + static struct server_conf_s server_conf; + + /* Set both to their default values. If there's an error + with opening/reading the config file, we return right away */ + server_conf.port = DEFAULT_PORT; + strcpy(server_conf.pid_file, DEFAULT_PID_FILE); + strcpy(server_conf.keys_file, DEFAULT_KEYS_FILE); + + config_init(&cfg); + + /* Read the file. If there is an error, report it and exit. */ + if(! config_read_file(&cfg, cfg_file)) + { + fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), + config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + server_conf.err = -1; + return server_conf; + } + + /* Get the port to listen on */ + if(config_lookup_int(&cfg, "port", &server_conf.port)) { + //printf("Port: %d\n", port); + } else { + fprintf(stderr, "No 'port' setting in configuration file.\n"); + } + + /* Get PID file location */ + if(config_lookup_string(&cfg, "pid_file", &pid_file_tmp)) { + //printf("PID file: %s\n", pid_file_tmp); + strcpy(server_conf.pid_file, pid_file_tmp); + } else { + fprintf(stderr, "No 'pid_file' setting in configuration file.\n"); + } + + /* Get keys file location */ + if(config_lookup_string(&cfg, "keys_file", &keys_file_tmp)) { + //printf("Keys file: %s\n", keys_file_tmp); + strcpy(server_conf.keys_file, keys_file_tmp); + } else { + fprintf(stderr, "No 'keys_file' setting in configuration file.\n"); + } + + /* Get all the servers in the list */ + server_list = config_lookup(&cfg, "bootstrap_servers"); + if(server_list != NULL) { + int count = config_setting_length(server_list); + int i; + + char tmp_ip[30]; /* IP */ + char tmp_pk[64]; /* bs_pk */ + for(i = 0; i < count; ++i) { + config_setting_t *server = config_setting_get_elem(server_list, i); + /* Get a pointer on the key aray */ + uint8_t *bs_pk_p = server_conf.info[i].bs_pk; + + /* Only output the record if all of the expected fields are present. */ + if(!(config_setting_lookup_string(server, "ip", &bs_ip) + && config_setting_lookup_int(server, "port", &bs_port) + && config_setting_lookup_string(server, "bs_pk", &bs_pk))) + continue; + + /* Converting all that stuff into usable formats and storing + it away in the server_info struct */ + server_conf.info[i].valid = 1; + + if(resolve_addr(strcpy(tmp_ip, bs_ip)) == -1) { + server_conf.info[i].valid = 0; + printf("bootstrap_server %d: Invalid IP\n", i); + } + + if(strlen(bs_pk) != 64) { + server_conf.info[i].valid = 0; + printf("bootstrap_server %d: Invalid public key\n", i); + } + + if(!bs_port) { + server_conf.info[i].valid = 0; + printf("bootstrap_server %d: Invalid port\n", i); + } + + server_conf.info[i].conn.ip.i = resolve_addr(strcpy(tmp_ip, bs_ip)); + server_conf.info[i].conn.port = htons(bs_port); + b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p); + } + + /* Check if at least one server entry is valid */ + for(i = 0; i < 32; ++i) { + if(server_conf.info[i].valid) + break; + else + server_conf.err = -2; + } + + } else { + server_conf.err = -2; + } + + config_destroy(&cfg); + return server_conf; +} + int main(int argc, char *argv[]) { - - char pidfloc[512]; /* Location of the soon-to-be PID file */ + pid_t pid, sid; /* Process- and Session-ID */ - + struct server_conf_s server_conf; + FILE *pidf; /* The PID file */ - - /* Assemble PID file location an try to open the file */ - sprintf(pidfloc, PIDFILE, USERNAME); - pidf = fopen(pidfloc, "w"); - - /* Generate new keypair */ - new_keys(); - + + if(argc < 2) { + printf("Please specify a configuration file.\n"); + exit(EXIT_FAILURE); + } + + /* Read the config file */ + server_conf = configure_server(argv[1]); + + printf("PID file: %s\n", server_conf.pid_file); + printf("Key file: %s\n", server_conf.keys_file); + + if(server_conf.err == -1) + printf("Config file not read.\n"); + + if(server_conf.err == -2) + printf("No valid servers in list.\n"); + + /* Open PID file for writing - if an error happens, + it will be caught down the line */ + pidf = fopen(server_conf.pid_file, "w"); + + /* Manage the keys */ + /* for now, just ignore any errors after this call. */ + int tmperr = errno; + manage_keys(server_conf.keys_file); + errno = tmperr; + /* Public key */ - uint32_t i; - + int i; printf("\nPublic Key: "); - for(i = 0; i < 32; i++) + for(i = 0; i < 32; ++i) { uint8_t ln, hn; ln = 0x0F & self_public_key[i]; @@ -53,84 +326,95 @@ int main(int argc, char *argv[]) { printf("%X%X", hn, ln); } printf("\n"); - + /* initialize networking bind to ip 0.0.0.0:PORT */ IP ip; ip.i = 0; - init_networking(ip, PORT); - + init_networking(ip, server_conf.port); + + /* Bootstrap the DHT + This one throws odd errors, too. Ignore. I assume they come + from somewhere in the core. */ + tmperr = errno; + connect_to_servers(server_conf.info); + errno = tmperr; + + if(!DHT_isconnected()) { + puts("Could not establish DHT connection. Check server settings.\n"); + exit(EXIT_FAILURE); + } else { + printf("Connected to DHT successfully.\n"); + } + /* If there's been an error, exit before forking off */ if (errno != 0) { perror("Error"); printf("Error(s) occured during start-up. Exiting.\n"); exit(EXIT_FAILURE); } - -// /* Assemble the location of the PID file */ -// sprintf(pidfloc, PIDFILE, USERNAME); -// pidf = fopen(pidfloc, "w"); -// /* Check if we can actually open the file */ -// if(pidf == NULL) { -// printf("Couldn't open PID-File %s for writing.\n", pidfloc); -// exit(EXIT_FAILURE); -// } - - /* Fork off the parent process */ + + /* Things that make the daemon work come past here. + There should be nothing here but the daemon code and + the main loop. */ + + /* Fork off from the parent process */ pid = fork(); if (pid < 0) { printf("Forking failed.\n"); exit(EXIT_FAILURE); } - + /* If we got a good PID, then we can exit the parent process. */ if (pid > 0) { printf("Forked successfully: %d\n", pid); - + /* Write the PID file */ fprintf(pidf, "%d\n", pid); fclose(pidf); - + /* Exit parent */ exit(EXIT_SUCCESS); } - + /* Change the file mode mask */ umask(0); - + /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) { printf("SID creation failure.\n"); exit(EXIT_FAILURE); } - + /* Change the current working directory */ if ((chdir("/")) < 0) { exit(EXIT_FAILURE); } - + /* Go quiet */ - close(STDIN_FILENO); close(STDOUT_FILENO); + close(STDIN_FILENO); close(STDERR_FILENO); - + + /* Main loop */ IP_Port ip_port; uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; - - /* Main loop */ - while(1) { + + while(1) + { doDHT(); - while(receivepacket(&ip_port, data, &length) != -1) { + + while(receivepacket(&ip_port, data, &length) != -1) + { DHT_handlepacket(data, length, ip_port); friendreq_handlepacket(data, length, ip_port); } - c_sleep(1); + usleep(10000); } - + shutdown_networking(); exit(EXIT_SUCCESS); } - diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.sh b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.sh new file mode 100755 index 00000000..936bc808 --- /dev/null +++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.sh @@ -0,0 +1,109 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: DHT_bootstrap_daemon +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start the Tox bootstrapping server +# Description: Use this piece of junk to start the Tox +# bootstrap server. +### END INIT INFO + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="ProjectTox bootstrap server daemon" +NAME=DHT_bootstrap_daemon +CFG=/home/$USER/server.cfg +DAEMON=/home/$USER/$NAME +DAEMON_ARGS="$CFG" +PIDFILE=/home/$USER/.$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +#[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 + sleep 1 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + + restart) #|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2 + exit 3 + ;; +esac diff --git a/other/bootstrap_serverdaemon/initscript.sh b/other/bootstrap_serverdaemon/initscript.sh deleted file mode 100644 index aa4b3e77..00000000 --- a/other/bootstrap_serverdaemon/initscript.sh +++ /dev/null @@ -1,109 +0,0 @@ -#! /bin/sh -### BEGIN INIT INFO -# Provides: bootstrap_server -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Start the Tox bootstrapping server -# Description: Use this piece of junk to start the Tox -# bootstrap server. -### END INIT INFO - -# PATH should only include /usr/* if it runs after the mountnfs.sh script -PATH=/sbin:/usr/sbin:/bin:/usr/bin -DESC="ProjectTox bootstrap server daemon" -NAME=bootstrap_server -DAEMON=/home/$USER/$NAME -DAEMON_ARGS="" -PIDFILE=/home/$USER/.$NAME.pid -SCRIPTNAME=/etc/init.d/$NAME - -# Exit if the package is not installed -[ -x "$DAEMON" ] || exit 0 - -# Read configuration variable file if it is present -[ -r /etc/default/$NAME ] && . /etc/default/$NAME - -# Load the VERBOSE setting and other rcS variables -. /lib/init/vars.sh - -# Define LSB log_* functions. -# Depend on lsb-base (>= 3.2-14) to ensure that this file is present -# and status_of_proc is working. -. /lib/lsb/init-functions - -# -# Function that starts the daemon/service -# -do_start() -{ - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ - || return 1 - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ - $DAEMON_ARGS \ - || return 2 - sleep 1 -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON - RETVAL="$?" - [ "$RETVAL" = 2 ] && return 2 - - start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON - [ "$?" = 2 ] && return 2 - # Many daemons don't delete their pidfiles when they exit. - rm -f $PIDFILE - return "$RETVAL" -} - -case "$1" in - start) - [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" - do_start - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - stop) - [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - status) - status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? - ;; - - restart) #|force-reload) - log_daemon_msg "Restarting $DESC" "$NAME" - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2 - exit 3 - ;; -esac - diff --git a/other/bootstrap_serverdaemon/server.cfg b/other/bootstrap_serverdaemon/server.cfg new file mode 100644 index 00000000..8ef516ca --- /dev/null +++ b/other/bootstrap_serverdaemon/server.cfg @@ -0,0 +1,30 @@ +// ProjectTox bootstrap server configuration file + +// The port used by bootstrap_server to listen on +port = 33445; + +// The key file +// make sure that the user who runs the server +// does have permissions to read it/write to it +keys_file = "/home/tom/.bootstrap_server.keys" + +// The PID file written to by bootstrap_server, +// make sure that the user who runs the server +// does have permissions to write to it +pid_file = "/home/tom/.bootstrap_server.pid"; + +// The info of the node bootstap_server will +// bootstrap itself from. +bootstrap_servers = ( + { // Server 1 + ip = "198.46.136.167"; + port = 33445; + bs_pk = "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854"; +// } + }, + { // Server 2 + ip = "192.81.133.111"; + port = 33445; + bs_pk = "8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858"; + } +); diff --git a/testing/DHT_cryptosendfiletest.c b/testing/DHT_cryptosendfiletest.c index 39a928d2..5c3a0256 100644 --- a/testing/DHT_cryptosendfiletest.c +++ b/testing/DHT_cryptosendfiletest.c @@ -15,14 +15,33 @@ * Saves all received data to: received.txt * * EX: ./test 127.0.0.1 33445 filename.txt + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ + #include "../core/network.h" #include "../core/DHT.h" #include "../core/net_crypto.h" #include -//Sleep function (x = milliseconds) +/* Sleep function (x = milliseconds) */ #ifdef WIN32 #define c_sleep(x) Sleep(1*x) @@ -41,15 +60,14 @@ void printip(IP_Port ip_port) printf("\nIP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); } - -//horrible function from one of my first C programs. -//only here because I was too lazy to write a proper one. +//TODO: rewrite unsigned char * hex_string_to_bin(char hex_string[]) { - unsigned char * val = malloc(strlen(hex_string)); + size_t len = strlen(hex_string); + unsigned char * val = malloc(len); char * pos = hex_string; int i=0; - while(i < strlen(hex_string)) + while(i < len) { sscanf(pos,"%2hhx",&val[i]); pos+=2; @@ -69,8 +87,7 @@ int main(int argc, char *argv[]) new_keys(); printf("OUR ID: "); uint32_t i; - for(i = 0; i < 32; i++) - { + for(i = 0; i < 32; i++) { if(self_public_key[i] < 16) printf("0"); printf("%hhX",self_public_key[i]); @@ -86,8 +103,7 @@ int main(int argc, char *argv[]) uint8_t friend_id[32]; memcpy(friend_id, hex_string_to_bin(temp_id), 32); - - //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); + /* memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); */ DHT_addfriend(friend_id); @@ -99,15 +115,13 @@ int main(int argc, char *argv[]) int friendrequest = -1; uint8_t request_data[512]; - //initialize networking - //bind to ip 0.0.0.0:PORT + /* initialize networking + * bind to ip 0.0.0.0:PORT */ IP ip; ip.i = 0; init_networking(ip, PORT); initNetCrypto(); - - perror("Initialization"); IP_Port bootstrap_ip_port; bootstrap_ip_port.port = htons(atoi(argv[2])); @@ -128,125 +142,102 @@ int main(int argc, char *argv[]) if ( file2==NULL ){return 1;} read1 = fread(buffer1, 1, 128, file1); - while(1) - { - - while(receivepacket(&ip_port, data, &length) != -1) - { - if(rand() % 3 != 1)//simulate packet loss - { - if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) - { - //if packet is not recognized + while(1) { + while(receivepacket(&ip_port, data, &length) != -1) { + if(rand() % 3 != 1) { /* simulate packet loss */ + if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) { + /* if packet is not recognized */ printf("Received unhandled packet with length: %u\n", length); - } - else - { + } else { printf("Received handled packet with length: %u\n", length); } } } friend_ip = DHT_getfriendip(friend_id); - if(friend_ip.ip.i != 0) - { - if(connection == -1 && friendrequest == -1) - { + if(friend_ip.ip.i != 0) { + if(connection == -1 && friendrequest == -1) { printf("Sending friend request to peer:"); printip(friend_ip); friendrequest = send_friendrequest(friend_id, friend_ip,(uint8_t *) "Hello World", 12); - //connection = crypto_connect((uint8_t *)friend_id, friend_ip); - //connection = new_connection(friend_ip); + /* connection = crypto_connect((uint8_t *)friend_id, friend_ip); */ + /* connection = new_connection(friend_ip); */ } - if(check_friendrequest(friendrequest) == 1) - { + if(check_friendrequest(friendrequest) == 1) { printf("Started connecting to friend:"); connection = crypto_connect(friend_id, friend_ip); } } - if(inconnection == -1) - { + if(inconnection == -1) { uint8_t secret_nonce[crypto_box_NONCEBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t session_key[crypto_box_PUBLICKEYBYTES]; inconnection = crypto_inbound(public_key, secret_nonce, session_key); inconnection = accept_crypto_inbound(inconnection, acceptedfriend_public_key, secret_nonce, session_key); - //inconnection = incoming_connection(); - if(inconnection != -1) - { + /* inconnection = incoming_connection(); */ + if(inconnection != -1) { printf("Someone connected to us:\n"); - // printip(connection_ip(inconnection)); + /* printip(connection_ip(inconnection)); */ } } - if(handle_friendrequest(acceptedfriend_public_key, request_data) > 1) - { + if(handle_friendrequest(acceptedfriend_public_key, request_data) > 1) { printf("RECIEVED FRIEND REQUEST: %s\n", request_data); } - //if someone connected to us write what he sends to a file - //also send him our file. - if(inconnection != -1) - { - if(write_cryptpacket(inconnection, buffer1, read1)) - { + /* if someone connected to us write what he sends to a file + * also send him our file. */ + if(inconnection != -1) { + if(write_cryptpacket(inconnection, buffer1, read1)) { printf("Wrote data1.\n"); read1 = fread(buffer1, 1, 128, file1); } read2 = read_cryptpacket(inconnection, buffer2); - if(read2 != 0) - { + if(read2 != 0) { printf("Received data1.\n"); - if(!fwrite(buffer2, read2, 1, file2)) - { + if(!fwrite(buffer2, read2, 1, file2)) { printf("file write error1\n"); } - if(read2 < 128) - { + if(read2 < 128) { printf("Closed file1 %u\n", read2); fclose(file2); } } - else if(is_cryptoconnected(inconnection) == 4)//if buffer is empty and the connection timed out. - { + /* if buffer is empty and the connection timed out. */ + else if(is_cryptoconnected(inconnection) == 4) { crypto_kill(inconnection); } } - //if we are connected to a friend send him data from the file. - //also put what he sends us in a file. - if(is_cryptoconnected(connection) >= 3) - { - if(write_cryptpacket(0, buffer1, read1)) - { + /* if we are connected to a friend send him data from the file. + * also put what he sends us in a file. */ + if(is_cryptoconnected(connection) >= 3) { + if(write_cryptpacket(0, buffer1, read1)) { printf("Wrote data2.\n"); read1 = fread(buffer1, 1, 128, file1); } read2 = read_cryptpacket(0, buffer2); - if(read2 != 0) - { + if(read2 != 0) { printf("Received data2.\n"); - if(!fwrite(buffer2, read2, 1, file2)) - { + if(!fwrite(buffer2, read2, 1, file2)) { printf("file write error2\n"); } - if(read2 < 128) - { + if(read2 < 128) { printf("Closed file2 %u\n", read2); fclose(file2); } } - else if(is_cryptoconnected(connection) == 4)//if buffer is empty and the connection timed out. - { + /* if buffer is empty and the connection timed out. */ + else if(is_cryptoconnected(connection) == 4) { crypto_kill(connection); } } doDHT(); doLossless_UDP(); doNetCrypto(); - //print_clientlist(); - //print_friendlist(); - //c_sleep(300); + /*print_clientlist(); + *print_friendlist(); + *c_sleep(300); */ c_sleep(1); } shutdown_networking(); return 0; -} \ No newline at end of file +} diff --git a/testing/DHT_sendfiletest.c b/testing/DHT_sendfiletest.c index 52ee7400..5b5d6c9f 100644 --- a/testing/DHT_sendfiletest.c +++ b/testing/DHT_sendfiletest.c @@ -14,7 +14,26 @@ * Saves all received data to: received.txt * * EX: ./test 127.0.0.1 33445 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef filename.txt ABCDEFGHIJKLMNOPQRSTUVWXYZabcdeg + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ + #include "../core/network.h" #include "../core/DHT.h" #include "../core/Lossless_UDP.h" @@ -82,68 +101,53 @@ int main(int argc, char *argv[]) if ( file2==NULL ){return 1;} read1 = fread(buffer1, 1, 128, file1); - while(1) - { + while(1) { - while(receivepacket(&ip_port, data, &length) != -1) - { - if(rand() % 3 != 1)//simulate packet loss - { - if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) - { - //if packet is not recognized + while(receivepacket(&ip_port, data, &length) != -1) { + if(rand() % 3 != 1) { /* simulate packet loss */ + if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) { + /* if packet is not recognized */ printf("Received unhandled packet with length: %u\n", length); - } - else - { + } else { printf("Received handled packet with length: %u\n", length); } } } friend_ip = DHT_getfriendip((uint8_t *)argv[3]); - if(friend_ip.ip.i != 0) - { - if(connection == -1) - { + if(friend_ip.ip.i != 0) { + if(connection == -1) { printf("Started connecting to friend:"); printip(friend_ip); connection = new_connection(friend_ip); } } - if(inconnection == -1) - { + if(inconnection == -1) { inconnection = incoming_connection(); - if(inconnection != -1) - { + if(inconnection != -1) { printf("Someone connected to us:"); printip(connection_ip(inconnection)); } } - //if someone connected to us write what he sends to a file - //also send him our file. - if(inconnection != -1) - { - if(write_packet(inconnection, buffer1, read1)) - { + /* if someone connected to us write what he sends to a file */ + /* also send him our file. */ + if(inconnection != -1) { + if(write_packet(inconnection, buffer1, read1)) { printf("Wrote data.\n"); read1 = fread(buffer1, 1, 128, file1); } read2 = read_packet(inconnection, buffer2); - if(read2 != 0) - { + if(read2 != 0) { printf("Received data.\n"); - if(!fwrite(buffer2, read2, 1, file2)) - { + if(!fwrite(buffer2, read2, 1, file2)) { printf("file write error\n"); } - if(read2 < 128) - { + if(read2 < 128) { fclose(file2); } } } - //if we are connected to a friend send him data from the file. - //also put what he sends us in a file. + /* if we are connected to a friend send him data from the file. + * also put what he sends us in a file. */ if(is_connected(connection) == 3) { if(write_packet(0, buffer1, read1)) @@ -167,9 +171,9 @@ int main(int argc, char *argv[]) } doDHT(); doLossless_UDP(); - //print_clientlist(); - //print_friendlist(); - //c_sleep(300); + /* print_clientlist(); + * print_friendlist(); + * c_sleep(300); */ c_sleep(1); } diff --git a/testing/DHT_test.c b/testing/DHT_test.c index e194d06b..d14e1577 100644 --- a/testing/DHT_test.c +++ b/testing/DHT_test.c @@ -7,7 +7,26 @@ * EX: ./test 127.0.0.1 33445 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * * The test will then ask you for the id (in hex format) of the friend you wish to add + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ + //#include "../core/network.h" #include "../core/DHT.c" #include "../core/friend_requests.c" @@ -28,17 +47,14 @@ #define PORT 33445 - void print_clientlist() { uint32_t i, j; IP_Port p_ip; printf("___________________CLOSE________________________________\n"); - for(i = 0; i < 4; i++) - { + for(i = 0; i < 4; i++) { printf("ClientID: "); - for(j = 0; j < 32; j++) - { + for(j = 0; j < 32; j++) { printf("%c", close_clientlist[i].client_id[j]); } p_ip = close_clientlist[i].ip_port; @@ -56,12 +72,10 @@ void print_friendlist() uint32_t i, j, k; IP_Port p_ip; printf("_________________FRIENDS__________________________________\n"); - for(k = 0; k < num_friends; k++) - { + for(k = 0; k < num_friends; k++) { printf("FRIEND %u\n", k); printf("ID: "); - for(j = 0; j < 32; j++) - { + for(j = 0; j < 32; j++) { printf("%c", friends_list[k].client_id[j]); } p_ip = DHT_getfriendip(friends_list[k].client_id); @@ -69,11 +83,9 @@ void print_friendlist() printf("\nCLIENTS IN LIST:\n\n"); - for(i = 0; i < 4; i++) - { + for(i = 0; i < 4; i++) { printf("ClientID: "); - for(j = 0; j < 32; j++) - { + for(j = 0; j < 32; j++) { if(0 <= friends_list[k].client_list[i].client_id[j] && friends_list[k].client_list[i].client_id[j] < 16) printf("0"); printf("%hhX", friends_list[k].client_list[i].client_id[j]); @@ -94,8 +106,7 @@ void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port) uint32_t i; printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); printf("--------------------BEGIN-----------------------------\n"); - for(i = 0; i < length; i++) - { + for(i = 0; i < length; i++) { if(data[i] < 16) printf("0"); printf("%hhX",data[i]); @@ -103,14 +114,14 @@ void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port) printf("\n--------------------END-----------------------------\n\n\n"); } -//horrible function from one of my first C programs. -//only here because I was too lazy to write a proper one. +//TODO: rewrite unsigned char * hex_string_to_bin(char hex_string[]) { - unsigned char * val = malloc(strlen(hex_string)); + size_t len = strlen(hex_string); + unsigned char * val = malloc(len); char * pos = hex_string; int i=0; - while(i < strlen(hex_string)) + while(i < len) { sscanf(pos,"%2hhx",&val[i]); pos+=2; @@ -130,8 +141,7 @@ int main(int argc, char *argv[]) new_keys(); printf("OUR ID: "); uint32_t i; - for(i = 0; i < 32; i++) - { + for(i = 0; i < 32; i++) { if(self_public_key[i] < 16) printf("0"); printf("%hhX",self_public_key[i]); @@ -142,8 +152,8 @@ int main(int argc, char *argv[]) scanf("%s", temp_id); DHT_addfriend(hex_string_to_bin(temp_id)); - //initialize networking - //bind to ip 0.0.0.0:PORT + /* initialize networking */ + /* bind to ip 0.0.0.0:PORT */ IP ip; ip.i = 0; init_networking(ip, PORT); @@ -152,10 +162,10 @@ int main(int argc, char *argv[]) perror("Initialization"); IP_Port bootstrap_ip_port; bootstrap_ip_port.port = htons(atoi(argv[2])); - //bootstrap_ip_port.ip.c[0] = 127; - //bootstrap_ip_port.ip.c[1] = 0; - //bootstrap_ip_port.ip.c[2] = 0; - //bootstrap_ip_port.ip.c[3] = 1; + /* bootstrap_ip_port.ip.c[0] = 127; + * bootstrap_ip_port.ip.c[1] = 0; + * bootstrap_ip_port.ip.c[2] = 0; + * bootstrap_ip_port.ip.c[3] = 1; */ bootstrap_ip_port.ip.i = inet_addr(argv[1]); DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); @@ -163,20 +173,15 @@ int main(int argc, char *argv[]) uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; - while(1) - { + while(1) { doDHT(); - while(receivepacket(&ip_port, data, &length) != -1) - { - if(DHT_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port)) - { + while(receivepacket(&ip_port, data, &length) != -1) { + if(DHT_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port)) { //unhandled packet printpacket(data, length, ip_port); - } - else - { + } else { printf("Received handled packet with length: %u\n", length); } } @@ -187,4 +192,4 @@ int main(int argc, char *argv[]) shutdown_networking(); return 0; -} \ No newline at end of file +} diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c index 0c21867d..8f23528c 100644 --- a/testing/Lossless_UDP_testclient.c +++ b/testing/Lossless_UDP_testclient.c @@ -8,6 +8,24 @@ * * Command line arguments are the ip and port to connect and send the file to. * EX: ./testclient 127.0.0.1 33445 filename.txt + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ #include "../core/network.h" @@ -24,7 +42,6 @@ #endif - #define PORT 33446 void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port) @@ -32,8 +49,7 @@ void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port) uint32_t i; printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); printf("--------------------BEGIN-----------------------------\n"); - for(i = 0; i < length; i++) - { + for(i = 0; i < length; i++) { if(data[i] < 16) printf("0"); printf("%hhX",data[i]); @@ -99,39 +115,34 @@ void printconnection(int connection_id) } */ -//recieve packets and send them to the packethandler -//run doLossless_UDP(); + +/*( recieve packets and send them to the packethandler */ +/*run doLossless_UDP(); */ void Lossless_UDP() { IP_Port ip_port; uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; - while(receivepacket(&ip_port, data, &length) != -1) - { + while(receivepacket(&ip_port, data, &length) != -1) { printf("packet with length: %u\n", length); - //if(rand() % 3 != 1)//add packet loss - // { - if(LosslessUDP_handlepacket(data, length, ip_port)) - { + /* if(rand() % 3 != 1)//add packet loss + { */ + if(LosslessUDP_handlepacket(data, length, ip_port)) { printpacket(data, length, ip_port); - } - else - { + } else { //printconnection(0); printf("Received handled packet with length: %u\n", length); } - // } + /* } */ } doLossless_UDP(); } - int main(int argc, char *argv[]) { - if (argc < 4) - { + if (argc < 4) { printf("usage: %s ip port filename\n", argv[0]); exit(0); } @@ -143,8 +154,8 @@ int main(int argc, char *argv[]) if ( file==NULL ){return 1;} - //initialize networking - //bind to ip 0.0.0.0:PORT + /* initialize networking */ + /* bind to ip 0.0.0.0:PORT */ IP ip; ip.i = 0; init_networking(ip, PORT); @@ -155,17 +166,14 @@ int main(int argc, char *argv[]) printip(serverip); int connection = new_connection(serverip); uint64_t timer = current_time(); - while(1) - { - // printconnection(connection); + while(1) { + /* printconnection(connection); */ Lossless_UDP(); - if(is_connected(connection) == 3) - { + if(is_connected(connection) == 3) { printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer)); break; } - if(is_connected(connection) == 0) - { + if(is_connected(connection) == 0) { printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); return 1; } @@ -174,38 +182,32 @@ int main(int argc, char *argv[]) timer = current_time(); - //read first part of file + /*read first part of file */ read = fread(buffer, 1, 512, file); - while(1) - { - //printconnection(connection); + while(1) { + /* printconnection(connection); */ Lossless_UDP(); - if(is_connected(connection) == 3) - { + if(is_connected(connection) == 3) { - if(write_packet(connection, buffer, read)) - { - //printf("Wrote data.\n"); + if(write_packet(connection, buffer, read)) { + /* printf("Wrote data.\n"); */ read = fread(buffer, 1, 512, file); } - //printf("%u\n", sendqueue(connection)); - if(sendqueue(connection) == 0) - { - if(read == 0) - { + /* printf("%u\n", sendqueue(connection)); */ + if(sendqueue(connection) == 0) { + if(read == 0) { printf("Sent file successfully in: %llu us\n", (unsigned long long)(current_time() - timer)); break; } } } - else - { + else { printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); return 0; } - //c_sleep(1); + /* c_sleep(1); */ } return 0; diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c index 8043be25..a8097048 100644 --- a/testing/Lossless_UDP_testserver.c +++ b/testing/Lossless_UDP_testserver.c @@ -8,6 +8,24 @@ * * Command line argument is the name of the file to save what we recieve to. * EX: ./testserver filename1.txt + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ #include "../core/network.h" @@ -25,7 +43,6 @@ #endif - #define PORT 33445 void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port) @@ -33,14 +50,14 @@ void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port) uint32_t i; printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); printf("--------------------BEGIN-----------------------------\n"); - for(i = 0; i < length; i++) - { + for(i = 0; i < length; i++) { if(data[i] < 16) printf("0"); printf("%hhX",data[i]); } printf("\n--------------------END-----------------------------\n\n\n"); } + /* void printpackets(Data test) { @@ -95,23 +112,20 @@ void printconnection(int connection_id) } */ -//recieve packets and send them to the packethandler -//run doLossless_UDP(); + +/* recieve packets and send them to the packethandler + * run doLossless_UDP(); */ void Lossless_UDP() { IP_Port ip_port; uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; - while(receivepacket(&ip_port, data, &length) != -1) - { + while(receivepacket(&ip_port, data, &length) != -1) { //if(rand() % 3 != 1)//add packet loss //{ - if(LosslessUDP_handlepacket(data, length, ip_port)) - { + if(LosslessUDP_handlepacket(data, length, ip_port)) { printpacket(data, length, ip_port); - } - else - { + } else { //printconnection(0); printf("Received handled packet with length: %u\n", length); } @@ -119,14 +133,12 @@ void Lossless_UDP() } doLossless_UDP(); - } int main(int argc, char *argv[]) { - if (argc < 2) - { + if (argc < 2) { printf("usage: %s filename\n", argv[0]); exit(0); } @@ -149,14 +161,11 @@ int main(int argc, char *argv[]) uint64_t timer = current_time(); - while(1) - { + while(1) { Lossless_UDP(); connection = incoming_connection(); - if(connection != -1) - { - if(is_connected(connection) == 2) - { + if(connection != -1) { + if(is_connected(connection) == 2) { printf("Recieved the connection.\n"); } @@ -167,25 +176,20 @@ int main(int argc, char *argv[]) timer = current_time(); - while(1) - { + while(1) { //printconnection(0); Lossless_UDP(); - if(is_connected(connection) >= 2) - { + if(is_connected(connection) >= 2) { kill_connection_in(connection, 3000000); read = read_packet(connection, buffer); - if(read != 0) - { + if(read != 0) { // printf("Recieved data.\n"); - if(!fwrite(buffer, read, 1, file)) - { + if(!fwrite(buffer, read, 1, file)) { printf("file write error\n"); } } } - if(is_connected(connection) == 4) - { + if(is_connected(connection) == 4) { printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); fclose(file); return 1; diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index f9215b44..f38eb962 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -17,7 +17,24 @@ * Or the argument can be the path to the save file. * * EX: ./test Save.bak - * + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * */ #include "../core/Messenger.h" @@ -33,14 +50,14 @@ #endif -//horrible function from one of my first C programs. -//only here because I was too lazy to write a proper one. +//TODO: rewrite unsigned char * hex_string_to_bin(char hex_string[]) { - unsigned char * val = malloc(strlen(hex_string)); + size_t len = strlen(hex_string); + unsigned char * val = malloc(len); char * pos = hex_string; int i=0; - while(i < strlen(hex_string)) + while(i < len) { sscanf(pos,"%2hhx",&val[i]); pos+=2; @@ -87,15 +104,12 @@ int main(int argc, char *argv[]) exit(0); } initMessenger(); - if(argc > 3) - { + if(argc > 3) { IP_Port bootstrap_ip_port; bootstrap_ip_port.port = htons(atoi(argv[2])); bootstrap_ip_port.ip.i = inet_addr(argv[1]); DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); - } - else - { + } else { FILE *file = fopen(argv[1], "rb"); if ( file==NULL ){return 1;} int read; @@ -110,8 +124,7 @@ int main(int argc, char *argv[]) printf("OUR ID: "); uint32_t i; - for(i = 0; i < 32; i++) - { + for(i = 0; i < 32; i++) { if(self_public_key[i] < 16) printf("0"); printf("%hhX",self_public_key[i]); @@ -121,16 +134,14 @@ int main(int argc, char *argv[]) char temp_id[128]; printf("\nEnter the client_id of the friend you wish to add (32 bytes HEX format):\n"); - if(scanf("%s", temp_id) != 1) - { + if(scanf("%s", temp_id) != 1) { return 1; } int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo")); perror("Initialization"); - while(1) - { + while(1) { uint8_t name[128]; getname(num, name); printf("%s\n", name); @@ -145,6 +156,5 @@ int main(int argc, char *argv[]) fwrite(buffer, 1, Messenger_size(), file); free(buffer); fclose(file); - } - + } } diff --git a/testing/nTox.c b/testing/nTox.c index 097c73af..3a5e9bb3 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -1,3 +1,26 @@ +/* nTox.c + * + * Textual frontend for Tox. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + #include "nTox.h" #include #include @@ -23,12 +46,14 @@ void new_lines(char *line) do_refresh(); } +//TODO: rewrite unsigned char * hex_string_to_bin(char hex_string[]) { - unsigned char * val = malloc(strlen(hex_string)); + size_t len = strlen(hex_string); + unsigned char * val = malloc(len); char * pos = hex_string; int i=0; - while(i < strlen(hex_string)) + while(i < len) { sscanf(pos,"%2hhx",&val[i]); pos+=2; @@ -58,7 +83,7 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line) doMessenger(); } else if (line[1] == 'm') { //message command: /m friendnumber messsage int i; - int len = strlen(line); + size_t len = strlen(line); char numstring[len-3]; char message[len-3]; for (i=0; i %s", friendnumber, temp, name, string); // someone please fix this new_lines(msg); } + void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) { char name[MAX_NAME_LENGTH]; getname(friendnumber, (uint8_t*)name); @@ -204,6 +235,7 @@ void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) { sprintf(msg, "[i] [%d] %s is now known as %s.", friendnumber, name, string); new_lines(msg); } + void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) { char name[MAX_NAME_LENGTH]; getname(friendnumber, (uint8_t*)name); @@ -211,6 +243,7 @@ void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) { sprintf(msg, "[i] [%d] %s's status changed to %s.", friendnumber, name, string); new_lines(msg); } + void load_key(){ FILE *data_file = NULL; if ((data_file = fopen("data","r"))) { @@ -237,6 +270,7 @@ void load_key(){ } fclose(data_file); } + int main(int argc, char *argv[]) { if (argc < 4) { @@ -294,9 +328,7 @@ int main(int argc, char *argv[]) DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); nodelay(stdscr, TRUE); while(true) { - - if (on == 0 && DHT_isconnected()) - { + if (on == 0 && DHT_isconnected()) { new_lines("[i] connected to DHT\n[i] define username with /n"); on = 1; } diff --git a/testing/nTox.h b/testing/nTox.h index fbc5d5c0..9b69d959 100644 --- a/testing/nTox.h +++ b/testing/nTox.h @@ -1,3 +1,26 @@ +/* nTox.h + * + *Textual frontend for Tox. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + #ifndef NTOX_H #define NTOX_H