Ran the code through: astyle --style=linux

This commit is contained in:
irungentoo 2013-07-27 08:43:36 -04:00
parent 1a6446266c
commit 14b43651c1
14 changed files with 737 additions and 749 deletions

View File

@ -1,5 +1,5 @@
/* DHT.c /* DHT.c
* *
* An implementation of the DHT as seen in docs/DHT.txt * An implementation of the DHT as seen in docs/DHT.txt
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
@ -18,52 +18,48 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "DHT.h" #include "DHT.h"
typedef struct typedef struct {
{
uint8_t client_id[CLIENT_ID_SIZE]; uint8_t client_id[CLIENT_ID_SIZE];
IP_Port ip_port; IP_Port ip_port;
uint32_t timestamp; uint32_t timestamp;
uint32_t last_pinged; uint32_t last_pinged;
IP_Port ret_ip_port;/* The ip_port returned by this node for the friend IP_Port ret_ip_port;/* The ip_port returned by this node for the friend
(for nodes in friends_list) or us (for nodes in close_clientlist) */ (for nodes in friends_list) or us (for nodes in close_clientlist) */
uint32_t ret_timestamp; uint32_t ret_timestamp;
}Client_data; } Client_data;
/* maximum number of clients stored per friend. */ /* maximum number of clients stored per friend. */
#define MAX_FRIEND_CLIENTS 8 #define MAX_FRIEND_CLIENTS 8
typedef struct typedef struct {
{
uint8_t client_id[CLIENT_ID_SIZE]; uint8_t client_id[CLIENT_ID_SIZE];
Client_data client_list[MAX_FRIEND_CLIENTS]; Client_data client_list[MAX_FRIEND_CLIENTS];
uint32_t lastgetnode; /* time at which the last get_nodes request was sent. */ uint32_t lastgetnode; /* time at which the last get_nodes request was sent. */
/*Symetric NAT hole punching stuff*/ /*Symetric NAT hole punching stuff*/
uint8_t hole_punching; /*0 if not hole punching, 1 if currently hole punching */ uint8_t hole_punching; /*0 if not hole punching, 1 if currently hole punching */
uint32_t punching_index; uint32_t punching_index;
uint32_t punching_timestamp; uint32_t punching_timestamp;
uint64_t NATping_id; uint64_t NATping_id;
uint32_t NATping_timestamp; uint32_t NATping_timestamp;
}Friend; } Friend;
typedef struct typedef struct {
{
uint8_t client_id[CLIENT_ID_SIZE]; uint8_t client_id[CLIENT_ID_SIZE];
IP_Port ip_port; IP_Port ip_port;
}Node_format; } Node_format;
typedef struct typedef struct {
{
IP_Port ip_port; IP_Port ip_port;
uint64_t ping_id; uint64_t ping_id;
uint32_t timestamp; uint32_t timestamp;
}Pinged; } Pinged;
/* Our client id/public key */ /* Our client id/public key */
uint8_t self_public_key[CLIENT_ID_SIZE]; uint8_t self_public_key[CLIENT_ID_SIZE];
@ -115,7 +111,7 @@ int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_
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 ip_port is assigned to a different client_id replace it*/
if(list[i].ip_port.ip.i == ip_port.ip.i && 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); memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
} }
@ -167,39 +163,38 @@ int get_close_nodes(uint8_t * client_id, Node_format * nodes_list)
int num_nodes=0; int num_nodes=0;
uint32_t temp_time = unix_time(); 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 && 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 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); 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; nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port;
num_nodes++; num_nodes++;
} } else for(j = 0; j < MAX_SENT_NODES; ++j)
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) {
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);
memcpy(nodes_list[j].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); nodes_list[j].ip_port = close_clientlist[i].ip_port;
nodes_list[j].ip_port = close_clientlist[i].ip_port; break;
break; }
}
} }
for(i = 0; i < num_friends; ++i) for(i = 0; i < num_friends; ++i)
for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) for(j = 0; j < MAX_FRIEND_CLIENTS; ++j)
if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time && 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 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); 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; nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port;
num_nodes++; num_nodes++;
} else for(k = 0; k < MAX_SENT_NODES; ++k) } 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) { 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); 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; nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port;
break; break;
} }
} }
return num_nodes; return num_nodes;
} }
/* replace first bad (or empty) node with this one /* replace first bad (or empty) node with this one
@ -210,7 +205,7 @@ int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Por
uint32_t i; uint32_t i;
uint32_t temp_time = unix_time(); uint32_t temp_time = unix_time();
for(i = 0; i < length; ++i) for(i = 0; i < length; ++i)
if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time) /* if node is bad. */ { if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time) { /* if node is bad. */
memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
list[i].ip_port = ip_port; list[i].ip_port = ip_port;
list[i].timestamp = temp_time; list[i].timestamp = temp_time;
@ -228,7 +223,7 @@ int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Po
{ {
uint32_t i; uint32_t i;
uint32_t temp_time = unix_time(); uint32_t temp_time = unix_time();
for(i = 0; i < length; ++i) for(i = 0; i < length; ++i)
if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) { if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) {
memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
@ -247,7 +242,7 @@ int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Po
void addto_lists(IP_Port ip_port, uint8_t * client_id) void addto_lists(IP_Port ip_port, uint8_t * client_id)
{ {
uint32_t i; uint32_t i;
/* NOTE: current behavior if there are two clients with the same id is to replace the first ip by the second. */ /* 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))
@ -261,7 +256,7 @@ void addto_lists(IP_Port ip_port, uint8_t * client_id)
replace_good(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port, friends_list[i].client_id); replace_good(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port, friends_list[i].client_id);
} }
/* If client_id is a friend or us, update ret_ip_port /* If client_id is a friend or us, update ret_ip_port
nodeclient_id is the id of the node that sent us this info */ nodeclient_id is the id of the node that sent us this info */
void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id) void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id)
{ {
@ -275,14 +270,14 @@ void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient
return; return;
} }
} else } else
for(i = 0; i < num_friends; ++i) for(i = 0; i < num_friends; ++i)
if(memcmp(client_id, friends_list[i].client_id, CLIENT_ID_SIZE) == 0) if(memcmp(client_id, friends_list[i].client_id, CLIENT_ID_SIZE) == 0)
for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) for(j = 0; j < MAX_FRIEND_CLIENTS; ++j)
if(memcmp(nodeclient_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE) == 0) { 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_ip_port = ip_port;
friends_list[i].client_list[j].ret_timestamp = temp_time; friends_list[i].client_list[j].ret_timestamp = temp_time;
return; return;
} }
} }
/* ping timeout in seconds */ /* ping timeout in seconds */
@ -304,13 +299,13 @@ int is_pinging(IP_Port ip_port, uint64_t ping_id)
pinging = 0; 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 && 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; ++pinging;
if(ping_id != 0) if(ping_id != 0)
if(pings[i].ping_id == ping_id) if(pings[i].ping_id == ping_id)
++pinging; ++pinging;
if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) if(pinging == (ping_id != 0) + (ip_port.ip.i != 0))
return 1; return 1;
} }
return 0; return 0;
@ -328,14 +323,14 @@ int is_gettingnodes(IP_Port ip_port, uint64_t ping_id)
pinging = 0; 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 && 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; ++pinging;
if(ping_id != 0) if(ping_id != 0)
if(send_nodes[i].ping_id == ping_id) if(send_nodes[i].ping_id == ping_id)
++pinging; ++pinging;
if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) if(pinging == (ping_id != 0) + (ip_port.ip.i != 0))
return 1; return 1;
} }
return 0; return 0;
@ -354,10 +349,10 @@ uint64_t add_pinging(IP_Port ip_port)
for(i = 0; i < PING_TIMEOUT; ++i ) for(i = 0; i < PING_TIMEOUT; ++i )
for(j = 0; j < LPING_ARRAY; ++j ) for(j = 0; j < LPING_ARRAY; ++j )
if((pings[j].timestamp + PING_TIMEOUT - i) < temp_time) { if((pings[j].timestamp + PING_TIMEOUT - i) < temp_time) {
pings[j].timestamp = temp_time; pings[j].timestamp = temp_time;
pings[j].ip_port = ip_port; pings[j].ip_port = ip_port;
pings[j].ping_id = ping_id; pings[j].ping_id = ping_id;
return ping_id; return ping_id;
} }
return 0; return 0;
@ -373,10 +368,10 @@ uint64_t add_gettingnodes(IP_Port ip_port)
for(i = 0; i < PING_TIMEOUT; ++i ) for(i = 0; i < PING_TIMEOUT; ++i )
for(j = 0; j < LSEND_NODES_ARRAY; ++j ) for(j = 0; j < LSEND_NODES_ARRAY; ++j )
if((send_nodes[j].timestamp + PING_TIMEOUT - i) < temp_time) { if((send_nodes[j].timestamp + PING_TIMEOUT - i) < temp_time) {
send_nodes[j].timestamp = temp_time; send_nodes[j].timestamp = temp_time;
send_nodes[j].ip_port = ip_port; send_nodes[j].ip_port = ip_port;
send_nodes[j].ping_id = ping_id; send_nodes[j].ping_id = ping_id;
return ping_id; return ping_id;
} }
return 0; return 0;
@ -415,7 +410,7 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key)
/* send a ping response */ /* send a ping response */
static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
{ {
/* 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) if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0)
return 1; return 1;
@ -431,7 +426,7 @@ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
return sendpacket(ip_port, data, sizeof(data)); return sendpacket(ip_port, data, sizeof(data));
} }
@ -441,26 +436,26 @@ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id)
/* 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) if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0)
return 1; return 1;
if(is_gettingnodes(ip_port, 0)) if(is_gettingnodes(ip_port, 0))
return 1; return 1;
uint64_t ping_id = add_gettingnodes(ip_port); uint64_t ping_id = add_gettingnodes(ip_port);
if(ping_id == 0) if(ping_id == 0)
return 1; return 1;
uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING]; uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING];
uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE];
uint8_t encrypt[sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING]; uint8_t encrypt[sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING];
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
random_nonce(nonce); random_nonce(nonce);
memcpy(plain, &ping_id, sizeof(ping_id)); memcpy(plain, &ping_id, sizeof(ping_id));
memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE);
int len = encrypt_data(public_key, self_secret_key, nonce, plain, sizeof(ping_id) + CLIENT_ID_SIZE, encrypt); 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; return -1;
data[0] = 2; data[0] = 2;
@ -476,8 +471,8 @@ static int sendnodes(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 */ if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */
return 1; return 1;
uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
+ sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING];
Node_format nodes_list[MAX_SENT_NODES]; Node_format nodes_list[MAX_SENT_NODES];
int num_nodes = get_close_nodes(client_id, nodes_list); int num_nodes = get_close_nodes(client_id, nodes_list);
@ -489,16 +484,16 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id,
uint8_t encrypt[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; uint8_t encrypt[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING];
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
random_nonce(nonce); random_nonce(nonce);
memcpy(plain, &ping_id, sizeof(ping_id)); memcpy(plain, &ping_id, sizeof(ping_id));
memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format));
int len = encrypt_data(public_key, self_secret_key, nonce, plain, int len = encrypt_data(public_key, self_secret_key, nonce, plain,
sizeof(ping_id) + num_nodes * sizeof(Node_format), encrypt); 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; return -1;
data[0] = 3; data[0] = 3;
memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
@ -515,13 +510,13 @@ int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source)
uint64_t ping_id; 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; return 1;
/* check if packet is from ourself. */ /* check if packet is from ourself. */
if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0)
return 1; return 1;
int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE,
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id);
if(len != sizeof(ping_id)) if(len != sizeof(ping_id))
return 1; return 1;
@ -540,18 +535,18 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
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; return 1;
int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE,
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id);
if(len != sizeof(ping_id)) if(len != sizeof(ping_id))
return 1; return 1;
if(is_pinging(source, ping_id)) { if(is_pinging(source, ping_id)) {
addto_lists(source, packet + 1); addto_lists(source, packet + 1);
return 0; return 0;
} }
return 1; return 1;
} }
int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
@ -559,15 +554,15 @@ int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
uint64_t ping_id; 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; return 1;
/* check if packet is from ourself. */ /* check if packet is from ourself. */
if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0)
return 1; return 1;
uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE];
int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE,
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, plain); 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; return 1;
@ -578,7 +573,7 @@ int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
pingreq(source, packet + 1); /* TODO: make this smarter? */ pingreq(source, packet + 1); /* TODO: make this smarter? */
return 0; return 0;
} }
int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
@ -586,21 +581,21 @@ int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
uint64_t ping_id; uint64_t ping_id;
/* TODO: make this more readable */ /* TODO: make this more readable */
if(length > (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) if(length > (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
+ sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING) || + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING) ||
(length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
+ ENCRYPTION_PADDING)) % (sizeof(Node_format)) != 0 || + ENCRYPTION_PADDING)) % (sizeof(Node_format)) != 0 ||
length < 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) length < 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
+ sizeof(Node_format) + ENCRYPTION_PADDING) { + sizeof(Node_format) + ENCRYPTION_PADDING) {
return 1; return 1;
} }
uint32_t num_nodes = (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES uint32_t num_nodes = (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
+ sizeof(ping_id) + ENCRYPTION_PADDING)) / sizeof(Node_format); + sizeof(ping_id) + ENCRYPTION_PADDING)) / sizeof(Node_format);
uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES];
int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE,
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain); 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; return 1;
@ -648,7 +643,7 @@ int DHT_delfriend(uint8_t * client_id)
uint32_t i; uint32_t i;
Friend * temp; Friend * temp;
for(i = 0; i < num_friends; ++i) for(i = 0; i < num_friends; ++i)
/* Equal */ /* Equal */
if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) {
--num_friends; --num_friends;
if(num_friends != i) if(num_friends != i)
@ -669,18 +664,18 @@ IP_Port DHT_getfriendip(uint8_t * client_id)
IP_Port empty = {{{0}}, 0}; IP_Port empty = {{{0}}, 0};
uint32_t temp_time = unix_time(); uint32_t temp_time = unix_time();
for(i = 0; i < num_friends; ++i) for(i = 0; i < num_friends; ++i)
/* Equal */ /* Equal */
if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) {
for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) for(j = 0; j < MAX_FRIEND_CLIENTS; ++j)
if(memcmp(friends_list[i].client_list[j].client_id, client_id, CLIENT_ID_SIZE) == 0 && 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 friends_list[i].client_list[j].ip_port;
return empty; return empty;
} }
empty.ip.i = 1; empty.ip.i = 1;
return empty; return empty;
} }
/* The timeout after which a node is discarded completely. */ /* The timeout after which a node is discarded completely. */
@ -700,24 +695,24 @@ void doDHTFriends()
uint32_t temp_time = unix_time(); uint32_t temp_time = unix_time();
uint32_t rand_node; uint32_t rand_node;
uint32_t index[MAX_FRIEND_CLIENTS]; 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; uint32_t num_nodes = 0;
for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 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].timestamp + Kill_NODE_TIMEOUT > temp_time) { /* if node is not dead. */
if((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { 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); 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; 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; index[num_nodes] = j;
++num_nodes; ++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; rand_node = rand() % num_nodes;
getnodes(friends_list[i].client_list[index[rand_node]].ip_port, getnodes(friends_list[i].client_list[index[rand_node]].ip_port,
friends_list[i].client_list[index[rand_node]].client_id, friends_list[i].client_list[index[rand_node]].client_id,
friends_list[i].client_id); friends_list[i].client_id);
friends_list[i].lastgetnode = temp_time; friends_list[i].lastgetnode = temp_time;
} }
@ -735,25 +730,25 @@ void doClose() /* tested */
uint32_t num_nodes = 0; uint32_t num_nodes = 0;
uint32_t rand_node; uint32_t rand_node;
uint32_t index[LCLIENT_LIST]; uint32_t index[LCLIENT_LIST];
for(i = 0; i < LCLIENT_LIST; ++i) for(i = 0; i < LCLIENT_LIST; ++i)
/* if node is not dead. */ /* if node is not dead. */
if(close_clientlist[i].timestamp + Kill_NODE_TIMEOUT > temp_time) { if(close_clientlist[i].timestamp + Kill_NODE_TIMEOUT > temp_time) {
if((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { if((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
pingreq(close_clientlist[i].ip_port, close_clientlist[i].client_id); pingreq(close_clientlist[i].ip_port, close_clientlist[i].client_id);
close_clientlist[i].last_pinged = temp_time; close_clientlist[i].last_pinged = temp_time;
} }
/* if node is good. */ /* if node is good. */
if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) { if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) {
index[num_nodes] = i; index[num_nodes] = i;
++num_nodes; ++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; rand_node = rand() % num_nodes;
getnodes(close_clientlist[index[rand_node]].ip_port, getnodes(close_clientlist[index[rand_node]].ip_port,
close_clientlist[index[rand_node]].client_id, close_clientlist[index[rand_node]].client_id,
self_public_key); self_public_key);
close_lastgetnodes = temp_time; close_lastgetnodes = temp_time;
} }
@ -761,7 +756,7 @@ void doClose() /* tested */
void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key) void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key)
{ {
getnodes(ip_port, public_key, self_public_key); getnodes(ip_port, public_key, self_public_key);
} }
/* send the given packet to node with client_id /* send the given packet to node with client_id
@ -775,7 +770,7 @@ int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length)
return -1; return -1;
} }
/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist /* 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 ip_portlist must be at least MAX_FRIEND_CLIENTS big
returns the number of ips returned returns the number of ips returned
return 0 if we are connected to friend or if no ips were found. return 0 if we are connected to friend or if no ips were found.
@ -788,9 +783,9 @@ static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num)
if(friend_num >= num_friends) if(friend_num >= num_friends)
return -1; return -1;
for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) for(i = 0; i < MAX_FRIEND_CLIENTS; ++i)
/*If ip is not zero and node is good */ /*If ip is not zero and node is good */
if(friends_list[friend_num].client_list[i].ret_ip_port.ip.i != 0 && 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) { 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 ) if(memcmp(friends_list[friend_num].client_list[i].client_id, friends_list[friend_num].client_id, CLIENT_ID_SIZE) == 0 )
return 0; return 0;
ip_portlist[num_ips] = friends_list[friend_num].client_list[i].ret_ip_port; ip_portlist[num_ips] = friends_list[friend_num].client_list[i].ret_ip_port;
@ -807,11 +802,11 @@ int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
uint32_t sent = 0; uint32_t sent = 0;
uint32_t temp_time = unix_time(); uint32_t temp_time = unix_time();
for(i = 0; i < num_friends; ++i) for(i = 0; i < num_friends; ++i)
/* Equal */ /* Equal */
if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) { if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) {
for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) for(j = 0; j < MAX_FRIEND_CLIENTS; ++j)
/*If ip is not zero and node is good */ /*If ip is not zero and node is good */
if(friends_list[i].client_list[j].ret_ip_port.ip.i != 0 && 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) 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) if(sendpacket(friends_list[i].client_list[j].ip_port, packet, length) == length)
++sent; ++sent;
@ -827,15 +822,15 @@ int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
int num = friend_number(friend_id); int num = friend_number(friend_id);
if(num == -1) if(num == -1)
return 0; return 0;
IP_Port ip_list[MAX_FRIEND_CLIENTS]; IP_Port ip_list[MAX_FRIEND_CLIENTS];
int n = 0; int n = 0;
uint32_t i; uint32_t i;
uint32_t temp_time = unix_time(); uint32_t temp_time = unix_time();
for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) for(i = 0; i < MAX_FRIEND_CLIENTS; ++i)
/*If ip is not zero and node is good */ /*If ip is not zero and node is good */
if(friends_list[num].client_list[i].ret_ip_port.ip.i != 0 && 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) { friends_list[num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) {
ip_list[n] = friends_list[num].client_list[i].ip_port; ip_list[n] = friends_list[num].client_list[i].ip_port;
++n; ++n;
} }
@ -846,7 +841,7 @@ int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
return 0; return 0;
} }
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist /* 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 ip_portlist must be at least MAX_FRIEND_CLIENTS big
returns the number of ips returned returns the number of ips returned
return 0 if we are connected to friend or if no ips were found. return 0 if we are connected to friend or if no ips were found.
@ -856,7 +851,7 @@ int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id)
uint32_t i; uint32_t i;
for(i = 0; i < num_friends; ++i) for(i = 0; i < num_friends; ++i)
/* Equal */ /* Equal */
if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0)
return friend_iplist(ip_portlist, i); return friend_iplist(ip_portlist, i);
return -1; return -1;
@ -869,7 +864,7 @@ int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
uint8_t data[sizeof(uint64_t) + 1]; uint8_t data[sizeof(uint64_t) + 1];
data[0] = type; data[0] = type;
memcpy(data + 1, &ping_id, sizeof(uint64_t)); memcpy(data + 1, &ping_id, sizeof(uint64_t));
uint8_t packet[MAX_DATA_SIZE]; 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 */ int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254); /* 254 is NAT ping request packet id */
if(len == -1) if(len == -1)
@ -890,9 +885,9 @@ int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source)
{ {
if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING &&
length > MAX_DATA_SIZE + ENCRYPTION_PADDING) length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
return 1; return 1;
/* check if request is for us. */ /* check if request is for us. */
if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES];
uint8_t data[MAX_DATA_SIZE]; uint8_t data[MAX_DATA_SIZE];
@ -901,11 +896,11 @@ int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source)
return 1; return 1;
uint64_t ping_id; uint64_t ping_id;
memcpy(&ping_id, data + 1, sizeof(uint64_t)); memcpy(&ping_id, data + 1, sizeof(uint64_t));
int friendnumber = friend_number(public_key); int friendnumber = friend_number(public_key);
if(friendnumber == -1) if(friendnumber == -1)
return 1; return 1;
if(data[0] == 0) { if(data[0] == 0) {
send_NATping(public_key, ping_id, 1); /*1 is reply*/ send_NATping(public_key, ping_id, 1); /*1 is reply*/
return 0; return 0;
@ -917,10 +912,9 @@ int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source)
} }
return 1; return 1;
} }
/* if request is not for us, try routing it. */ /* if request is not for us, try routing it. */
else else if(route_packet(packet + 1, packet, length) == length)
if(route_packet(packet + 1, packet, length) == length) return 0;
return 0;
return 0; return 0;
} }
@ -933,7 +927,7 @@ static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num)
IP zero = {{0}}; IP zero = {{0}};
if(len > MAX_FRIEND_CLIENTS) if(len > MAX_FRIEND_CLIENTS)
return zero; return zero;
uint32_t i, j; uint32_t i, j;
uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
for(i = 0; i < len; ++i) { for(i = 0; i < len; ++i) {
@ -998,8 +992,7 @@ static void doNAT()
send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/
friends_list[i].NATping_timestamp = temp_time; friends_list[i].NATping_timestamp = temp_time;
} }
} } else if(friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time) {
else if(friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time) {
IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2); IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2);
if(ip.i == 0) if(ip.i == 0)
continue; continue;
@ -1020,23 +1013,23 @@ int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
{ {
switch (packet[0]) { switch (packet[0]) {
case 0: case 0:
return handle_pingreq(packet, length, source); return handle_pingreq(packet, length, source);
case 1: case 1:
return handle_pingres(packet, length, source); return handle_pingres(packet, length, source);
case 2: case 2:
return handle_getnodes(packet, length, source); return handle_getnodes(packet, length, source);
case 3: case 3:
return handle_sendnodes(packet, length, source); return handle_sendnodes(packet, length, source);
case 254: case 254:
return handle_NATping(packet, length, source); return handle_NATping(packet, length, source);
default: default:
return 1; return 1;
} }
return 0; return 0;
@ -1074,17 +1067,17 @@ int DHT_load(uint8_t * data, uint32_t size)
uint32_t i, j; uint32_t i, j;
/* uint32_t temp_time = unix_time(); */ /* uint32_t temp_time = unix_time(); */
uint16_t temp; uint16_t temp;
temp = (size - sizeof(close_clientlist))/sizeof(Friend); temp = (size - sizeof(close_clientlist))/sizeof(Friend);
if(temp != 0) { if(temp != 0) {
Friend * tempfriends_list = (Friend *)(data + sizeof(close_clientlist)); 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); DHT_addfriend(tempfriends_list[i].client_id);
for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) for(j = 0; j < MAX_FRIEND_CLIENTS; ++j)
if(tempfriends_list[i].client_list[j].timestamp != 0) { if(tempfriends_list[i].client_list[j].timestamp != 0) {
getnodes(tempfriends_list[i].client_list[j].ip_port, getnodes(tempfriends_list[i].client_list[j].ip_port,
tempfriends_list[i].client_list[j].client_id, tempfriends_list[i].client_id); tempfriends_list[i].client_list[j].client_id, tempfriends_list[i].client_id);
} }
} }

View File

@ -1,7 +1,7 @@
/* DHT.h /* DHT.h
* *
* An implementation of the DHT as seen in docs/DHT.txt * An implementation of the DHT as seen in docs/DHT.txt
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -18,11 +18,11 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifndef DHT_H #ifndef DHT_H
#define DHT_H #define DHT_H
#include "net_crypto.h" #include "net_crypto.h"
@ -30,79 +30,79 @@
extern "C" { extern "C" {
#endif #endif
/* Current time, unix format */ /* Current time, unix format */
#define unix_time() ((uint32_t)time(NULL)) #define unix_time() ((uint32_t)time(NULL))
/* size of the client_id in bytes */ /* size of the client_id in bytes */
#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
/* Add a new friend to the friends list /* Add a new friend to the friends list
client_id must be CLIENT_ID_SIZE bytes long. client_id must be CLIENT_ID_SIZE bytes long.
returns 0 if success returns 0 if success
returns 1 if failure (friends list is full) */ returns 1 if failure (friends list is full) */
int DHT_addfriend(uint8_t *client_id); int DHT_addfriend(uint8_t *client_id);
/* Delete a friend from the friends list /* Delete a friend from the friends list
client_id must be CLIENT_ID_SIZE bytes long. client_id must be CLIENT_ID_SIZE bytes long.
returns 0 if success returns 0 if success
returns 1 if failure (client_id not in friends list) */ returns 1 if failure (client_id not in friends list) */
int DHT_delfriend(uint8_t *client_id); int DHT_delfriend(uint8_t *client_id);
/* Get ip of friend /* Get ip of friend
client_id must be CLIENT_ID_SIZE bytes long. client_id must be CLIENT_ID_SIZE bytes long.
ip must be 4 bytes long. ip must be 4 bytes long.
port must be 2 bytes long. port must be 2 bytes long.
returns ip if success returns ip if success
returns ip of 0 if failure (This means the friend is either offline or we have not found him yet.) returns ip of 0 if failure (This means the friend is either offline or we have not found him yet.)
returns ip of 1 if friend is not in list. */ returns ip of 1 if friend is not in list. */
IP_Port DHT_getfriendip(uint8_t *client_id); IP_Port DHT_getfriendip(uint8_t *client_id);
/* Run this function at least a couple times per second (It's the main loop) */ /* Run this function at least a couple times per second (It's the main loop) */
void doDHT(); void doDHT();
/* if we receive a DHT packet we call this function so it can be handled. /* if we receive a DHT packet we call this function so it can be handled.
return 0 if packet is handled correctly. return 0 if packet is handled correctly.
return 1 if it didn't handle the packet or if the packet was shit. */ return 1 if it didn't handle the packet or if the packet was shit. */
int DHT_handlepacket(uint8_t *packet, uint32_t length, IP_Port source); int DHT_handlepacket(uint8_t *packet, uint32_t length, IP_Port source);
/* Use this function to bootstrap the client /* Use this function to bootstrap the client
Sends a get nodes request to the given node with ip port and public_key */ 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); void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key);
/* ROUTING FUNCTIONS */ /* ROUTING FUNCTIONS */
/* send the given packet to node with client_id /* send the given packet to node with client_id
returns -1 if failure */ returns -1 if failure */
int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length); int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length);
/* Send the following packet to everyone who tells us they are connected to friend_id /* 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 */ returns the number of nodes it sent the packet to */
int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length); int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length);
/* NAT PUNCHING FUNCTIONS */ /* NAT PUNCHING FUNCTIONS */
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist /* 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 ip_portlist must be at least MAX_FRIEND_CLIENTS big
returns the number of ips returned returns the number of ips returned
returns -1 if no such friend*/ returns -1 if no such friend*/
int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id); int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id);
/* SAVE/LOAD functions */ /* SAVE/LOAD functions */
/* get the size of the DHT (for saving) */ /* get the size of the DHT (for saving) */
uint32_t DHT_size(); uint32_t DHT_size();
/* save the DHT in data where data is an array of size DHT_size() */ /* save the DHT in data where data is an array of size DHT_size() */
void DHT_save(uint8_t *data); void DHT_save(uint8_t *data);
/* load the DHT from data of size size; /* load the DHT from data of size size;
return -1 if failure return -1 if failure
return 0 if success */ return 0 if success */
int DHT_load(uint8_t *data, uint32_t size); int DHT_load(uint8_t *data, uint32_t size);
/* returns 0 if we are not connected to the DHT /* returns 0 if we are not connected to the DHT
returns 1 if we are */ returns 1 if we are */
int DHT_isconnected(); int DHT_isconnected();
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,7 +1,7 @@
/* LAN_discovery.c /* LAN_discovery.c
* *
* LAN discovery implementation. * LAN discovery implementation.
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -18,7 +18,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "LAN_discovery.h" #include "LAN_discovery.h"

View File

@ -1,7 +1,7 @@
/* LAN_discovery.h /* LAN_discovery.h
* *
* LAN discovery implementation. * LAN discovery implementation.
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -18,12 +18,12 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifndef LAN_DISCOVERY_H #ifndef LAN_DISCOVERY_H
#define LAN_DISCOVERY_H #define LAN_DISCOVERY_H
#include "DHT.h" #include "DHT.h"
@ -32,14 +32,14 @@
extern "C" { extern "C" {
#endif #endif
/*Send a LAN discovery pcaket to the broadcast address with port port*/ /*Send a LAN discovery pcaket to the broadcast address with port port*/
int send_LANdiscovery(uint16_t port); int send_LANdiscovery(uint16_t port);
/* if we receive a packet we call this function so it can be handled. /* if we receive a packet we call this function so it can be handled.
return 0 if packet is handled correctly. return 0 if packet is handled correctly.
return 1 if it didn't handle the packet or if the packet was shit. */ 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); int LANdiscovery_handlepacket(uint8_t *packet, uint32_t length, IP_Port source);

View File

@ -1,7 +1,7 @@
/* Lossless_UDP.c /* Lossless_UDP.c
* *
* An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -18,7 +18,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
/* TODO: clean this file a bit. /* TODO: clean this file a bit.
@ -47,18 +47,18 @@ timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION
typedef struct { typedef struct {
uint8_t data[MAX_DATA_SIZE]; uint8_t data[MAX_DATA_SIZE];
uint16_t size; uint16_t size;
}Data; } Data;
typedef struct { typedef struct {
IP_Port ip_port; IP_Port ip_port;
uint8_t status; /* 0 if connection is dead, 1 if attempting handshake, uint8_t status; /* 0 if connection is dead, 1 if attempting handshake,
2 if handshake is done (we start sending SYNC packets) 2 if handshake is done (we start sending SYNC packets)
3 if we are sending SYNC packets and can send data 3 if we are sending SYNC packets and can send data
4 if the connection has timed out. */ 4 if the connection has timed out. */
uint8_t inbound; /* 1 or 2 if connection was initiated by someone else, 0 if not. uint8_t inbound; /* 1 or 2 if connection was initiated by someone else, 0 if not.
2 if incoming_connection() has not returned it yet, 1 if it has. */ 2 if incoming_connection() has not returned it yet, 1 if it has. */
uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */ uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */
uint16_t data_rate; /* current data packet send rate packets per second. */ uint16_t data_rate; /* current data packet send rate packets per second. */
uint64_t last_SYNC; /* time at which our last SYNC packet was sent. */ uint64_t last_SYNC; /* time at which our last SYNC packet was sent. */
@ -82,7 +82,7 @@ typedef struct {
uint8_t recv_counter; uint8_t recv_counter;
uint8_t send_counter; uint8_t send_counter;
uint8_t timeout; /* connection timeout in seconds. */ uint8_t timeout; /* connection timeout in seconds. */
}Connection; } Connection;
#define MAX_CONNECTIONS 256 #define MAX_CONNECTIONS 256
@ -95,10 +95,11 @@ static Connection connections[MAX_CONNECTIONS];
/* get connection id from IP_Port /* get connection id from IP_Port
return -1 if there are no connections like we are looking for return -1 if there are no connections like we are looking for
return id if it found it */ return id if it found it */
int getconnection_id(IP_Port ip_port) { int getconnection_id(IP_Port ip_port)
{
uint32_t i; uint32_t i;
for (i = 0; i < MAX_CONNECTIONS; ++i) { for (i = 0; i < MAX_CONNECTIONS; ++i) {
if (connections[i].ip_port.ip.i == ip_port.ip.i && if (connections[i].ip_port.ip.i == ip_port.ip.i &&
connections[i].ip_port.port == ip_port.port && connections[i].status > 0) connections[i].ip_port.port == ip_port.port && connections[i].status > 0)
return i; return i;
} }
@ -384,10 +385,10 @@ int send_data_packet(uint32_t connection_id, uint32_t packet_num)
packet[0] = 18; packet[0] = 18;
temp = htonl(packet_num); temp = htonl(packet_num);
memcpy(packet + 1, &temp, 4); memcpy(packet + 1, &temp, 4);
memcpy(packet + 5, connections[connection_id].sendbuffer[index].data, memcpy(packet + 5, connections[connection_id].sendbuffer[index].data,
connections[connection_id].sendbuffer[index].size); connections[connection_id].sendbuffer[index].size);
return sendpacket(connections[connection_id].ip_port, packet, return sendpacket(connections[connection_id].ip_port, packet,
1 + 4 + connections[connection_id].sendbuffer[index].size); 1 + 4 + connections[connection_id].sendbuffer[index].size);
} }
/* sends 1 data packet */ /* sends 1 data packet */
@ -395,7 +396,7 @@ int send_DATA(uint32_t connection_id)
{ {
int ret; int ret;
uint32_t buffer[BUFFER_PACKET_NUM]; 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]); ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]);
connections[connection_id].num_req_paquets--; connections[connection_id].num_req_paquets--;
memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4); memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4);
@ -416,9 +417,9 @@ int send_DATA(uint32_t connection_id)
One to handle each type of packets we receive One to handle each type of packets we receive
return 0 if handled correctly, 1 if packet is bad. */ return 0 if handled correctly, 1 if packet is bad. */
int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
{ {
if (length != (1 + 4 + 4)) if (length != (1 + 4 + 4))
return 1; return 1;
uint32_t temp; uint32_t temp;
uint32_t handshake_id1, handshake_id2; uint32_t handshake_id1, handshake_id2;
int connection = getconnection_id(source); int connection = getconnection_id(source);
@ -426,7 +427,7 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
handshake_id1 = ntohl(temp); handshake_id1 = ntohl(temp);
memcpy(&temp, packet + 5, 4); memcpy(&temp, packet + 5, 4);
handshake_id2 = ntohl(temp); handshake_id2 = ntohl(temp);
if (handshake_id2 == 0) { if (handshake_id2 == 0) {
send_handshake(source, handshake_id(source), handshake_id1); send_handshake(source, handshake_id(source), handshake_id1);
return 0; return 0;
@ -452,7 +453,7 @@ int SYNC_valid(uint32_t length)
{ {
if (length < 4 + 4 + 2) if (length < 4 + 4 + 2)
return 0; return 0;
if (length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) || if (length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) ||
((length - 4 - 4 - 2) % 4) != 0) ((length - 4 - 4 - 2) % 4) != 0)
return 0; return 0;
return 1; return 1;
@ -482,7 +483,7 @@ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnu
int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) 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) */ /* && sent_packetnum == connections[connection_id].osent_packetnum) */
connections[connection_id].status = 3; connections[connection_id].status = 3;
connections[connection_id].recv_counter = counter; connections[connection_id].recv_counter = counter;
++connections[connection_id].send_counter; ++connections[connection_id].send_counter;
@ -522,14 +523,14 @@ int handle_SYNC(uint8_t *packet, uint32_t length, IP_Port source)
{ {
if (!SYNC_valid(length)) if (!SYNC_valid(length))
return 1; return 1;
int connection = getconnection_id(source); int connection = getconnection_id(source);
uint8_t counter; uint8_t counter;
uint32_t temp; uint32_t temp;
uint32_t recv_packetnum, sent_packetnum; uint32_t recv_packetnum, sent_packetnum;
uint32_t req_packets[BUFFER_PACKET_NUM]; uint32_t req_packets[BUFFER_PACKET_NUM];
uint16_t number = (length - 4 - 4 - 2)/ 4; uint16_t number = (length - 4 - 4 - 2)/ 4;
memcpy(&counter, packet + 1, 1); memcpy(&counter, packet + 1, 1);
memcpy(&temp, packet + 2, 4); memcpy(&temp, packet + 2, 4);
recv_packetnum = ntohl(temp); recv_packetnum = ntohl(temp);
@ -556,7 +557,7 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
uint32_t i; uint32_t i;
uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM;
uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum;
for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
if (i == data_num) { if (i == data_num) {
memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); 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].recvbuffer[i % MAX_QUEUE_NUM].size = size;
@ -568,7 +569,7 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
} }
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) if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0)
connections[connection_id].recv_packetnum = i; connections[connection_id].recv_packetnum = i;
else else
break; break;
} }
@ -603,15 +604,15 @@ int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source)
{ {
switch (packet[0]) { //TODO: check if no break statement is correct??? switch (packet[0]) { //TODO: check if no break statement is correct???
case 16: case 16:
return handle_handshake(packet, length, source); return handle_handshake(packet, length, source);
case 17: case 17:
return handle_SYNC(packet, length, source); return handle_SYNC(packet, length, source);
case 18: case 18:
return handle_data(packet, length, source); return handle_data(packet, length, source);
default: default:
return 1; return 1;
} }
@ -627,13 +628,13 @@ void doNew()
for (i = 0; i < MAX_CONNECTIONS; ++i) { for (i = 0; i < MAX_CONNECTIONS; ++i) {
if (connections[i].status == 1) 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); send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0);
connections[i].last_sent = temp_time; connections[i].last_sent = temp_time;
} }
/* kill all timed out connections */ /* kill all timed out connections */
if ( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && if ( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time &&
connections[i].status != 4) connections[i].status != 4)
/* kill_connection(i); */ /* kill_connection(i); */
connections[i].status = 4; connections[i].status = 4;
if (connections[i].status > 0 && connections[i].killat < temp_time) if (connections[i].status > 0 && connections[i].killat < temp_time)
@ -648,8 +649,8 @@ void doSYNC()
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].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); send_SYNC(i);
connections[i].last_SYNC = temp_time; connections[i].last_SYNC = temp_time;
} }
} }
} }
@ -682,10 +683,9 @@ void adjustRates()
connections[i].SYNC_rate = MAX_SYNC_RATE; connections[i].SYNC_rate = MAX_SYNC_RATE;
if (connections[i].status == 3) { if (connections[i].status == 3) {
if (sendqueue(i) != 0) { if (sendqueue(i) != 0) {
connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE; connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE;
connections[i].SYNC_rate = MAX_SYNC_RATE; connections[i].SYNC_rate = MAX_SYNC_RATE;
} } else if (connections[i].last_recvdata + 1000000UL > temp_time)
else if (connections[i].last_recvdata + 1000000UL > temp_time)
connections[i].SYNC_rate = MAX_SYNC_RATE; connections[i].SYNC_rate = MAX_SYNC_RATE;
else else
connections[i].SYNC_rate = SYNC_RATE; connections[i].SYNC_rate = SYNC_RATE;

View File

@ -1,7 +1,7 @@
/* Lossless_UDP.h /* Lossless_UDP.h
* *
* An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -18,11 +18,11 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifndef LOSSLESS_UDP_H #ifndef LOSSLESS_UDP_H
#define LOSSLESS_UDP_H #define LOSSLESS_UDP_H
#include "network.h" #include "network.h"
@ -30,74 +30,74 @@
extern "C" { extern "C" {
#endif #endif
/* maximum length of the data in the data packets */ /* maximum length of the data in the data packets */
#define MAX_DATA_SIZE 1024 #define MAX_DATA_SIZE 1024
/* Functions */ /* Functions */
/* initialize a new connection to ip_port /* initialize a new connection to ip_port
returns an integer corresponding to the connection id. returns an integer corresponding to the connection id.
return -1 if it could not initialize the connection. return -1 if it could not initialize the connection.
if there already was an existing connection to that ip_port return its number. */ if there already was an existing connection to that ip_port return its number. */
int new_connection(IP_Port ip_port); int new_connection(IP_Port ip_port);
/* get connection id from IP_Port /* get connection id from IP_Port
return -1 if there are no connections like we are looking for return -1 if there are no connections like we are looking for
return id if it found it */ return id if it found it */
int getconnection_id(IP_Port ip_port); int getconnection_id(IP_Port ip_port);
/* returns an integer corresponding to the next connection in our imcoming connection list /* returns an integer corresponding to the next connection in our imcoming connection list
return -1 if there are no new incoming connections in the list. */ return -1 if there are no new incoming connections in the list. */
int incoming_connection(); int incoming_connection();
/* return -1 if it could not kill the connection. /* return -1 if it could not kill the connection.
return 0 if killed successfully */ return 0 if killed successfully */
int kill_connection(int connection_id); int kill_connection(int connection_id);
/* kill connection in seconds seconds. /* kill connection in seconds seconds.
return -1 if it can not kill the connection. return -1 if it can not kill the connection.
return 0 if it will kill it */ return 0 if it will kill it */
int kill_connection_in(int connection_id, uint32_t seconds); int kill_connection_in(int connection_id, uint32_t seconds);
/* returns the ip_port of the corresponding connection. /* returns the ip_port of the corresponding connection.
return 0 if there is no such connection. */ return 0 if there is no such connection. */
IP_Port connection_ip(int connection_id); IP_Port connection_ip(int connection_id);
/* returns the id of the next packet in the queue /* returns the id of the next packet in the queue
return -1 if no packet in queue */ return -1 if no packet in queue */
char id_packet(int connection_id); char id_packet(int connection_id);
/* return 0 if there is no received data in the buffer. /* return 0 if there is no received data in the buffer.
return length of received packet if successful */ return length of received packet if successful */
int read_packet(int connection_id, uint8_t *data); int read_packet(int connection_id, uint8_t *data);
/* return 0 if data could not be put in packet queue /* return 0 if data could not be put in packet queue
return 1 if data was put into the queue */ return 1 if data was put into the queue */
int write_packet(int connection_id, uint8_t *data, uint32_t length); 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. */ /* returns the number of packets in the queue waiting to be successfully sent. */
uint32_t sendqueue(int connection_id); uint32_t sendqueue(int connection_id);
/* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */ /* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */
uint32_t recvqueue(int connection_id); uint32_t recvqueue(int connection_id);
/* check if connection is connected /* check if connection is connected
return 0 no. return 0 no.
return 1 if attempting handshake return 1 if attempting handshake
return 2 if handshake is done return 2 if handshake is done
return 3 if fully connected return 3 if fully connected
return 4 if timed out and wating to be killed */ return 4 if timed out and wating to be killed */
int is_connected(int connection_id); int is_connected(int connection_id);
/* Call this function a couple times per second /* Call this function a couple times per second
It's the main loop. */ It's the main loop. */
void doLossless_UDP(); void doLossless_UDP();
/* if we receive a Lossless_UDP packet we call this function so it can be handled. /* if we receive a Lossless_UDP packet we call this function so it can be handled.
return 0 if packet is handled correctly. return 0 if packet is handled correctly.
return 1 if it didn't handle the packet or if the packet was shit. */ return 1 if it didn't handle the packet or if the packet was shit. */
int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source); int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -18,12 +18,12 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "Messenger.h" #include "Messenger.h"
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b))
typedef struct { typedef struct {
uint8_t client_id[CLIENT_ID_SIZE]; uint8_t client_id[CLIENT_ID_SIZE];
int crypt_connection_id; int crypt_connection_id;
@ -49,7 +49,7 @@ static uint16_t self_userstatus_len;
static Friend friendlist[MAX_NUM_FRIENDS]; static Friend friendlist[MAX_NUM_FRIENDS];
static uint32_t numfriends; static uint32_t numfriends;
/* 1 if we are online /* 1 if we are online
0 if we are offline 0 if we are offline
static uint8_t online; */ static uint8_t online; */
@ -95,7 +95,7 @@ int getclient_id(int friend_id, uint8_t *client_id)
int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
{ {
if (length == 0 || length >= if (length == 0 || length >=
(MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES))
return -1; return -1;
if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
return -1; return -1;
@ -113,7 +113,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
friendlist[i].userstatus_length = 1; friendlist[i].userstatus_length = 1;
memcpy(friendlist[i].info, data, length); memcpy(friendlist[i].info, data, length);
friendlist[i].info_size = length; friendlist[i].info_size = length;
++numfriends; ++numfriends;
return i; return i;
} }
@ -183,7 +183,7 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length)
if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS) if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS)
return 0; return 0;
if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) 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. */ /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */
return 0; return 0;
uint8_t temp[MAX_DATA_SIZE]; uint8_t temp[MAX_DATA_SIZE];
temp[0] = PACKET_ID_MESSAGE; temp[0] = PACKET_ID_MESSAGE;
@ -349,7 +349,8 @@ int initMessenger()
//TODO: make this function not suck. //TODO: make this function not suck.
static void doFriends() static void doFriends()
{/* TODO: add incoming connections and some other stuff. */ {
/* TODO: add incoming connections and some other stuff. */
uint32_t i; uint32_t i;
int len; int len;
uint8_t temp[MAX_DATA_SIZE]; uint8_t temp[MAX_DATA_SIZE];
@ -370,19 +371,19 @@ static void doFriends()
} }
IP_Port friendip = DHT_getfriendip(friendlist[i].client_id); 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: case 0:
if (friendip.ip.i > 1) if (friendip.ip.i > 1)
friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip); friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip);
break; break;
case 3: /* Connection is established */ case 3: /* Connection is established */
friendlist[i].status = 4; friendlist[i].status = 4;
break; break;
case 4: case 4:
crypto_kill(friendlist[i].crypt_connection_id); crypto_kill(friendlist[i].crypt_connection_id);
friendlist[i].crypt_connection_id = -1; friendlist[i].crypt_connection_id = -1;
break; break;
default: default:
break; break;
} }
} }
while (friendlist[i].status == 4) { /* friend is online */ while (friendlist[i].status == 4) { /* friend is online */
@ -397,38 +398,37 @@ static void doFriends()
len = read_cryptpacket(friendlist[i].crypt_connection_id, temp); len = read_cryptpacket(friendlist[i].crypt_connection_id, temp);
if (len > 0) { if (len > 0) {
switch (temp[0]) { switch (temp[0]) {
case PACKET_ID_NICKNAME: { case PACKET_ID_NICKNAME: {
if (len != MAX_NAME_LENGTH + 1) if (len != MAX_NAME_LENGTH + 1)
break;
if(friend_namechange_isset)
friend_namechange(i, temp + 1, MAX_NAME_LENGTH); /* TODO: use the actual length */
memcpy(friendlist[i].name, temp + 1, MAX_NAME_LENGTH);
friendlist[i].name[MAX_NAME_LENGTH - 1] = 0; /* make sure the NULL terminator is present. */
break; break;
} if(friend_namechange_isset)
case PACKET_ID_USERSTATUS: { friend_namechange(i, temp + 1, MAX_NAME_LENGTH); /* TODO: use the actual length */
uint8_t *status = calloc(MIN(len - 1, MAX_USERSTATUS_LENGTH), 1); memcpy(friendlist[i].name, temp + 1, MAX_NAME_LENGTH);
memcpy(status, temp + 1, MIN(len - 1, MAX_USERSTATUS_LENGTH)); friendlist[i].name[MAX_NAME_LENGTH - 1] = 0; /* make sure the NULL terminator is present. */
if (friend_statuschange_isset) break;
friend_statuschange(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH));
set_friend_userstatus(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH));
free(status);
break;
}
case PACKET_ID_MESSAGE: {
if (friend_message_isset)
(*friend_message)(i, temp + 1, len - 1);
break;
}
} }
} case PACKET_ID_USERSTATUS: {
else { uint8_t *status = calloc(MIN(len - 1, MAX_USERSTATUS_LENGTH), 1);
if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ memcpy(status, temp + 1, MIN(len - 1, MAX_USERSTATUS_LENGTH));
crypto_kill(friendlist[i].crypt_connection_id); if (friend_statuschange_isset)
friendlist[i].crypt_connection_id = -1; friend_statuschange(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH));
friendlist[i].status = 3; set_friend_userstatus(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH));
} free(status);
break; break;
}
case PACKET_ID_MESSAGE: {
if (friend_message_isset)
(*friend_message)(i, temp + 1, len - 1);
break;
}
}
} else {
if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
crypto_kill(friendlist[i].crypt_connection_id);
friendlist[i].crypt_connection_id = -1;
friendlist[i].status = 3;
}
break;
} }
} }
} }
@ -443,11 +443,11 @@ static void doInbound()
if (inconnection != -1) { if (inconnection != -1) {
int friend_id = getfriend_id(public_key); int friend_id = getfriend_id(public_key);
if (friend_id != -1) { if (friend_id != -1) {
crypto_kill(friendlist[friend_id].crypt_connection_id); crypto_kill(friendlist[friend_id].crypt_connection_id);
friendlist[friend_id].crypt_connection_id = friendlist[friend_id].crypt_connection_id =
accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key); accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key);
friendlist[friend_id].status = 3; friendlist[friend_id].status = 3;
} }
} }
} }
@ -477,8 +477,8 @@ void doMessenger()
#ifdef DEBUG #ifdef DEBUG
/* if(rand() % 3 != 1) //simulate packet loss */ /* if(rand() % 3 != 1) //simulate packet loss */
/* { */ /* { */
if (DHT_handlepacket(data, length, ip_port) && LosslessUDP_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)) friendreq_handlepacket(data, length, ip_port) && LANdiscovery_handlepacket(data, length, ip_port))
/* if packet is discarded */ /* if packet is discarded */
printf("Received unhandled packet with length: %u\n", length); printf("Received unhandled packet with length: %u\n", length);
else else
@ -505,7 +505,7 @@ void doMessenger()
uint32_t Messenger_size() uint32_t Messenger_size()
{ {
return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
+ sizeof(uint32_t) + DHT_size() + sizeof(uint32_t) + sizeof(Friend) * numfriends; + sizeof(uint32_t) + DHT_size() + sizeof(uint32_t) + sizeof(Friend) * numfriends;
} }
/* save the messenger in data of size Messenger_size() */ /* save the messenger in data of size Messenger_size() */
@ -537,7 +537,7 @@ int Messenger_load(uint8_t * data, uint32_t length)
uint32_t size; uint32_t size;
memcpy(&size, data, sizeof(size)); memcpy(&size, data, sizeof(size));
data += sizeof(size); data += sizeof(size);
if (length < size) if (length < size)
return -1; return -1;
length -= size; length -= size;
@ -548,12 +548,12 @@ int Messenger_load(uint8_t * data, uint32_t length)
data += sizeof(size); data += sizeof(size);
if (length != size || length % sizeof(Friend) != 0) if (length != size || length % sizeof(Friend) != 0)
return -1; return -1;
Friend * temp = malloc(size); Friend * temp = malloc(size);
memcpy(temp, data, size); memcpy(temp, data, size);
uint16_t num = size / sizeof(Friend); uint16_t num = size / sizeof(Friend);
uint32_t i; uint32_t i;
for (i = 0; i < num; ++i) { for (i = 0; i < num; ++i) {
if(temp[i].status != 0) { if(temp[i].status != 0) {

View File

@ -3,7 +3,7 @@
* An implementation of a simple text chat only messenger on the tox network core. * 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 * NOTE: All the text in the messages must be encoded using UTF-8
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -20,8 +20,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifndef MESSENGER_H #ifndef MESSENGER_H
#define MESSENGER_H #define MESSENGER_H
@ -42,111 +42,111 @@ extern "C" {
#define PACKET_ID_USERSTATUS 49 #define PACKET_ID_USERSTATUS 49
#define PACKET_ID_MESSAGE 64 #define PACKET_ID_MESSAGE 64
/* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased /* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased
to an absurdly large number later */ to an absurdly large number later */
/* add a friend /* add a friend
set the data that will be sent along with friend request set the data that will be sent along with friend request
client_id is the client id of the friend client_id is the client id of the friend
data is the data and length is the length data is the data and length is the length
returns the friend number if success returns the friend number if success
return -1 if failure. */ return -1 if failure. */
int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length);
/* add a friend without sending a friendrequest. /* add a friend without sending a friendrequest.
returns the friend number if success returns the friend number if success
return -1 if failure. */ return -1 if failure. */
int m_addfriend_norequest(uint8_t *client_id); int m_addfriend_norequest(uint8_t *client_id);
/* return the friend id associated to that client id. /* return the friend id associated to that client id.
return -1 if no such friend */ return -1 if no such friend */
int getfriend_id(uint8_t *client_id); int getfriend_id(uint8_t *client_id);
/* copies the public key associated to that friend id into client_id buffer. /* copies the public key associated to that friend id into client_id buffer.
make sure that client_id is of size CLIENT_ID_SIZE. make sure that client_id is of size CLIENT_ID_SIZE.
return 0 if success return 0 if success
return -1 if failure */ return -1 if failure */
int getclient_id(int friend_id, uint8_t *client_id); int getclient_id(int friend_id, uint8_t *client_id);
/* remove a friend */ /* remove a friend */
int m_delfriend(int friendnumber); int m_delfriend(int friendnumber);
/* return 4 if friend is online /* return 4 if friend is online
return 3 if friend is confirmed return 3 if friend is confirmed
return 2 if the friend request was sent return 2 if the friend request was sent
return 1 if the friend was added return 1 if the friend was added
return 0 if there is no friend with that number */ return 0 if there is no friend with that number */
int m_friendstatus(int friendnumber); int m_friendstatus(int friendnumber);
/* send a text chat message to an online friend /* send a text chat message to an online friend
returns 1 if packet was successfully put into the send queue returns 1 if packet was successfully put into the send queue
return 0 if it was not */ return 0 if it was not */
int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length);
/* Set our nickname /* Set our nickname
name must be a string of maximum MAX_NAME_LENGTH length. name must be a string of maximum MAX_NAME_LENGTH length.
return 0 if success return 0 if success
return -1 if failure */ return -1 if failure */
int setname(uint8_t *name, uint16_t length); int setname(uint8_t *name, uint16_t length);
/* get name of friendnumber /* get name of friendnumber
put it in name put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
return 0 if success return 0 if success
return -1 if failure */ return -1 if failure */
int getname(int friendnumber, uint8_t *name); int getname(int friendnumber, uint8_t *name);
/* set our user status /* set our user status
you are responsible for freeing status after you are responsible for freeing status after
returns 0 on success, -1 on failure */ returns 0 on success, -1 on failure */
int m_set_userstatus(uint8_t *status, uint16_t length); int m_set_userstatus(uint8_t *status, uint16_t length);
/* return the length of friendnumber's user status, /* return the length of friendnumber's user status,
including null including null
pass it into malloc */ pass it into malloc */
int m_get_userstatus_size(int friendnumber); int m_get_userstatus_size(int friendnumber);
/* copy friendnumber's userstatus into buf, truncating if size is over maxlen /* copy friendnumber's userstatus into buf, truncating if size is over maxlen
get the size you need to allocate from m_get_userstatus_size */ get the size you need to allocate from m_get_userstatus_size */
int m_copy_userstatus(int friendnumber, uint8_t *buf, uint32_t maxlen); int m_copy_userstatus(int friendnumber, uint8_t *buf, uint32_t maxlen);
/* set the function that will be executed when a friend request is received. /* set the function that will be executed when a friend request is received.
function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ 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)); 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. /* 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) */ function format is: function(int friendnumber, uint8_t * message, uint32_t length) */
void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t));
/* set the callback for name changes /* set the callback for name changes
function(int friendnumber, uint8_t *newname, uint16_t length) function(int friendnumber, uint8_t *newname, uint16_t length)
you are not responsible for freeing newname */ you are not responsible for freeing newname */
void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)); void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t));
/* set the callback for user status changes /* set the callback for user status changes
function(int friendnumber, uint8_t *newstatus, uint16_t length) function(int friendnumber, uint8_t *newstatus, uint16_t length)
you are not responsible for freeing newstatus */ you are not responsible for freeing newstatus */
void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)); void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t));
/* run this at startup /* run this at startup
returns 0 if no connection problems returns 0 if no connection problems
returns -1 if there are problems */ returns -1 if there are problems */
int initMessenger(); int initMessenger();
/* the main loop that needs to be run at least 200 times per second */ /* the main loop that needs to be run at least 200 times per second */
void doMessenger(); void doMessenger();
/* SAVING AND LOADING FUNCTIONS: */ /* SAVING AND LOADING FUNCTIONS: */
/* returns the size of the messenger data (for saving) */ /* returns the size of the messenger data (for saving) */
uint32_t Messenger_size(); uint32_t Messenger_size();
/* save the messenger in data (must be allocated memory of size Messenger_size()) */ /* save the messenger in data (must be allocated memory of size Messenger_size()) */
void Messenger_save(uint8_t *data); void Messenger_save(uint8_t *data);
/* load the messenger from data of size length */ /* load the messenger from data of size length */
int Messenger_load(uint8_t *data, uint32_t length); int Messenger_load(uint8_t *data, uint32_t length);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,7 +1,7 @@
/* friend_requests.c /* friend_requests.c
* *
* Handle friend requests. * Handle friend requests.
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -18,7 +18,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "friend_requests.h" #include "friend_requests.h"
@ -26,7 +26,7 @@
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
/* Try to send a friendrequest to peer with public_key /* Try to send a friendrequest to peer with public_key
data is the data in the request and length is the length. data is the data in the request and length is the length.
return -1 if failure. return -1 if failure.
return 0 if it sent the friend request directly to the friend. return 0 if it sent the friend request directly to the friend.
return the number of peers it was routed through if it did not send it directly.*/ return the number of peers it was routed through if it did not send it directly.*/
@ -34,7 +34,7 @@ int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length)
{ {
uint8_t packet[MAX_DATA_SIZE]; uint8_t packet[MAX_DATA_SIZE];
int len = create_request(packet, public_key, data, length, 32); /* 32 is friend request packet id */ int len = create_request(packet, public_key, data, length, 32); /* 32 is friend request packet id */
if (len == -1) if (len == -1)
return -1; return -1;
@ -48,7 +48,7 @@ int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length)
return 0; return 0;
return -1; return -1;
} }
int num = route_tofriend(public_key, packet, len); int num = route_tofriend(public_key, packet, len);
if (num == 0) if (num == 0)
@ -61,7 +61,8 @@ static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t);
static uint8_t handle_friendrequest_isset = 0; static uint8_t handle_friendrequest_isset = 0;
/* set the function that will be executed when a friend request is received. */ /* set the function that will be executed when a friend request is received. */
void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)) { void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t))
{
handle_friendrequest = function; handle_friendrequest = function;
handle_friendrequest_isset = 1; handle_friendrequest_isset = 1;
} }
@ -76,17 +77,19 @@ static uint8_t recieved_requests[MAX_RECIEVED_STORED][crypto_box_PUBLICKEYBYTES]
static uint16_t recieved_requests_index; static uint16_t recieved_requests_index;
/*Add to list of recieved friend requests*/ /*Add to list of recieved friend requests*/
static void addto_recievedlist(uint8_t * client_id) { static void addto_recievedlist(uint8_t * client_id)
{
if (recieved_requests_index >= MAX_RECIEVED_STORED) if (recieved_requests_index >= MAX_RECIEVED_STORED)
recieved_requests_index = 0; recieved_requests_index = 0;
memcpy(recieved_requests[recieved_requests_index], client_id, crypto_box_PUBLICKEYBYTES); memcpy(recieved_requests[recieved_requests_index], client_id, crypto_box_PUBLICKEYBYTES);
++recieved_requests_index; ++recieved_requests_index;
} }
/* Check if a friend request was already recieved /* Check if a friend request was already recieved
return 0 if not, 1 if we did */ return 0 if not, 1 if we did */
static int request_recieved(uint8_t * client_id) { static int request_recieved(uint8_t * client_id)
{
uint32_t i; uint32_t i;
for (i = 0; i < MAX_RECIEVED_STORED; ++i) { for (i = 0; i < MAX_RECIEVED_STORED; ++i) {
@ -98,7 +101,8 @@ static int request_recieved(uint8_t * client_id) {
} }
int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) { int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
{
if (packet[0] == 32) { if (packet[0] == 32) {
if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING &&
length > MAX_DATA_SIZE + ENCRYPTION_PADDING) length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
@ -118,11 +122,10 @@ int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) {
addto_recievedlist(public_key); addto_recievedlist(public_key);
(*handle_friendrequest)(public_key, data, len); (*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) if(route_packet(packet + 1, packet, length) == length)
return 0; return 0;
} }
} }
return 1; return 1;
} }

View File

@ -1,7 +1,7 @@
/* friend_requests.h /* friend_requests.h
* *
* Handle friend requests. * Handle friend requests.
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -18,11 +18,11 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifndef FRIEND_REQUESTS_H #ifndef FRIEND_REQUESTS_H
#define FRIEND_REQUESTS_H #define FRIEND_REQUESTS_H
#include "DHT.h" #include "DHT.h"
#include "net_crypto.h" #include "net_crypto.h"
@ -31,18 +31,18 @@
extern "C" { extern "C" {
#endif #endif
/* Try to send a friendrequest to peer with public_key /* Try to send a friendrequest to peer with public_key
data is the data in the request and length is the length. */ 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); 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. /* 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) */ 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)); void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t));
/* if we receive a packet we call this function so it can be handled. /* if we receive a packet we call this function so it can be handled.
return 0 if packet is handled correctly. return 0 if packet is handled correctly.
return 1 if it didn't handle the packet or if the packet was shit. */ 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); int friendreq_handlepacket(uint8_t *packet, uint32_t length, IP_Port source);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,10 +1,10 @@
/* net_crypto.c /* net_crypto.c
* *
* Functions for the core network crypto. * Functions for the core network crypto.
* See also: docs/Crypto.txt * See also: docs/Crypto.txt
* *
* NOTE: This code has to be perfect. We don't mess around with encryption. * NOTE: This code has to be perfect. We don't mess around with encryption.
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -21,7 +21,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "net_crypto.h" #include "net_crypto.h"
@ -37,11 +37,11 @@ typedef struct {
uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */ uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */
uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */ uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */
uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
(we have received a handshake but no empty data packet), 3 if the connection is established. (we have received a handshake but no empty data packet), 3 if the connection is established.
4 if the connection is timed out. */ 4 if the connection is timed out. */
uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */
} Crypto_Connection; } Crypto_Connection;
#define MAX_CRYPTO_CONNECTIONS 256 #define MAX_CRYPTO_CONNECTIONS 256
@ -53,24 +53,24 @@ static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS];
/* keeps track of the connection numbers for friends request so we can check later if they were sent */ /* keeps track of the connection numbers for friends request so we can check later if they were sent */
static int incoming_connections[MAX_INCOMING]; static int incoming_connections[MAX_INCOMING];
/* encrypts plain of length length to encrypted of length + 16 using the /* encrypts plain of length length to encrypted of length + 16 using the
public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce
return -1 if there was a problem. return -1 if there was a problem.
return length of encrypted data if everything was fine. */ return length of encrypted data if everything was fine. */
int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
uint8_t *plain, uint32_t length, uint8_t *encrypted) uint8_t *plain, uint32_t length, uint8_t *encrypted)
{ {
if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0) if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0)
return -1; return -1;
uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0}; uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0};
uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES];
uint8_t zeroes[crypto_box_BOXZEROBYTES] = {0}; uint8_t zeroes[crypto_box_BOXZEROBYTES] = {0};
memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */ memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */
crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, secret_key); crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, secret_key);
/* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero */ /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero */
if (memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0) if (memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0)
return -1; return -1;
@ -84,8 +84,8 @@ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce
return -1 if there was a problem(decryption failed) return -1 if there was a problem(decryption failed)
return length of plain data if everything was fine. */ return length of plain data if everything was fine. */
int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
uint8_t *encrypted, uint32_t length, uint8_t *plain) uint8_t *encrypted, uint32_t length, uint8_t *plain)
{ {
if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES)
return -1; return -1;
@ -93,11 +93,11 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES]; 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 temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0};
uint8_t zeroes[crypto_box_ZEROBYTES] = {0}; uint8_t zeroes[crypto_box_ZEROBYTES] = {0};
memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */
if (crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, if (crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES,
nonce, public_key, secret_key) == -1) nonce, public_key, secret_key) == -1)
return -1; return -1;
/* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */ /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */
@ -130,13 +130,13 @@ void random_nonce(uint8_t *nonce)
} }
} }
/* return 0 if there is no received data in the buffer /* return 0 if there is no received data in the buffer
return -1 if the packet was discarded. return -1 if the packet was discarded.
return length of received data if successful */ return length of received data if successful */
int read_cryptpacket(int crypt_connection_id, uint8_t *data) int read_cryptpacket(int crypt_connection_id, uint8_t *data)
{ {
if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
return 0; return 0;
if (crypto_connections[crypt_connection_id].status != 3) if (crypto_connections[crypt_connection_id].status != 3)
return 0; return 0;
uint8_t temp_data[MAX_DATA_SIZE]; uint8_t temp_data[MAX_DATA_SIZE];
@ -145,7 +145,7 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data)
return 0; return 0;
if (temp_data[0] != 3) if (temp_data[0] != 3)
return -1; return -1;
int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key,
crypto_connections[crypt_connection_id].sessionsecret_key, crypto_connections[crypt_connection_id].sessionsecret_key,
crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data); crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data);
if (len != -1) { if (len != -1) {
@ -160,13 +160,13 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data)
int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length) int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length)
{ {
if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
return 0; return 0;
if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
return 0; return 0;
if (crypto_connections[crypt_connection_id].status != 3) if (crypto_connections[crypt_connection_id].status != 3)
return 0; return 0;
uint8_t temp_data[MAX_DATA_SIZE]; uint8_t temp_data[MAX_DATA_SIZE];
int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key,
crypto_connections[crypt_connection_id].sessionsecret_key, crypto_connections[crypt_connection_id].sessionsecret_key,
crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1);
if (len == -1) if (len == -1)
@ -190,7 +190,7 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t
return -1; return -1;
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
random_nonce(nonce); random_nonce(nonce);
int len = encrypt_data(public_key, self_secret_key, nonce, data, length, int len = encrypt_data(public_key, self_secret_key, nonce, data, length,
1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet);
if (len == -1) if (len == -1)
return -1; return -1;
@ -198,11 +198,11 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t
memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES);
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES);
return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES;
} }
/* puts the senders public key in the request in public_key, the data from the request /* 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. 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 packet is the request packet and length is its length
return -1 if not valid request. */ return -1 if not valid request. */
@ -210,19 +210,17 @@ int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *packet, uint16_t
{ {
if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING &&
length <= MAX_DATA_SIZE + ENCRYPTION_PADDING && length <= MAX_DATA_SIZE + ENCRYPTION_PADDING &&
memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
{
memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES);
int len1 = decrypt_data(public_key, self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, 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); length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), data);
if(len1 == -1) if(len1 == -1)
return -1; return -1;
return len1; return len1;
} } else
else
return -1; return -1;
} }
@ -234,13 +232,13 @@ int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t *secret
uint8_t temp_data[MAX_DATA_SIZE]; uint8_t temp_data[MAX_DATA_SIZE];
uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
random_nonce(nonce); random_nonce(nonce);
memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); memcpy(temp, secret_nonce, crypto_box_NONCEBYTES);
memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES);
int len = encrypt_data(public_key, self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 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); 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data);
if (len == -1) if (len == -1)
return 0; return 0;
temp_data[0] = 2; temp_data[0] = 2;
@ -252,28 +250,27 @@ int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t *secret
/* Extract secret nonce, session public key and public_key from a packet(data) with length length /* Extract secret nonce, session public key and public_key from a packet(data) with length length
return 1 if successful return 1 if successful
return 0 if failure */ return 0 if failure */
int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce, int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce,
uint8_t *session_key, uint8_t *data, uint16_t length) uint8_t *session_key, uint8_t *data, uint16_t length)
{ {
int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES);
if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES
+ crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) {
{
return 0; return 0;
} }
if (data[0] != 2) if (data[0] != 2)
return 0; return 0;
uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES);
int len = decrypt_data(public_key, self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, int len = decrypt_data(public_key, self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES,
data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp);
if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES) if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES)
return 0; return 0;
memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); memcpy(secret_nonce, temp, crypto_box_NONCEBYTES);
memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES);
return 1; return 1;
@ -316,9 +313,8 @@ int crypto_connect(uint8_t *public_key, IP_Port ip_port)
memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key); crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key);
if (send_cryptohandshake(id, public_key, crypto_connections[i].recv_nonce, if (send_cryptohandshake(id, public_key, crypto_connections[i].recv_nonce,
crypto_connections[i].sessionpublic_key) == 1) crypto_connections[i].sessionpublic_key) == 1) {
{
increment_nonce(crypto_connections[i].recv_nonce); increment_nonce(crypto_connections[i].recv_nonce);
return i; return i;
} }
@ -363,9 +359,9 @@ int crypto_inbound(uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_
return 0 if killed successfully return 0 if killed successfully
return 1 if there was a problem. */ return 1 if there was a problem. */
int crypto_kill(int crypt_connection_id) int crypto_kill(int crypt_connection_id)
{ {
if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
return 1; 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; crypto_connections[crypt_connection_id].status = 0;
kill_connection(crypto_connections[crypt_connection_id].number); kill_connection(crypto_connections[crypt_connection_id].number);
@ -400,9 +396,8 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre
crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key); crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key);
if (send_cryptohandshake(connection_id, public_key, crypto_connections[i].recv_nonce, if (send_cryptohandshake(connection_id, public_key, crypto_connections[i].recv_nonce,
crypto_connections[i].sessionpublic_key) == 1) crypto_connections[i].sessionpublic_key) == 1) {
{
increment_nonce(crypto_connections[i].recv_nonce); increment_nonce(crypto_connections[i].recv_nonce);
uint32_t zero = 0; uint32_t zero = 0;
crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */ crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */
@ -413,10 +408,10 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre
return -1; /* this should never happen. */ return -1; /* this should never happen. */
} }
} }
return -1; return -1;
} }
/* return 0 if no connection, 1 we have sent a handshake, 2 if connection 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. (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 */ 4 if the connection is timed out and waiting to be killed */
int is_cryptoconnected(int crypt_connection_id) int is_cryptoconnected(int crypt_connection_id)
@ -471,9 +466,9 @@ static void handle_incomings()
{ {
int income; int income;
while (1) { while (1) {
income = incoming_connection(); income = incoming_connection();
if(income == -1 || new_incoming(income) ) if(income == -1 || new_incoming(income) )
break; break;
} }
} }
@ -488,8 +483,8 @@ static void receive_crypto()
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES];
uint8_t session_key[crypto_box_PUBLICKEYBYTES]; uint8_t session_key[crypto_box_PUBLICKEYBYTES];
uint16_t len; uint16_t len;
if (id_packet(crypto_connections[i].number) == 1) if (id_packet(crypto_connections[i].number) == 1)
/* if the packet is a friend request drop it (because we are already friends) */ /* if the packet is a friend request drop it (because we are already friends) */
len = read_packet(crypto_connections[i].number, temp_data); 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); len = read_packet(crypto_connections[i].number, temp_data);
@ -504,31 +499,28 @@ static void receive_crypto()
crypto_connections[i].status = 2; /* set it to its proper value right after. */ crypto_connections[i].status = 2; /* set it to its proper value right after. */
} }
} }
} } else if (id_packet(crypto_connections[i].number) != -1) // This should not happen kill the connection if it does
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); crypto_kill(crypto_connections[i].number);
} }
if (crypto_connections[i].status == 2) { 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 temp_data[MAX_DATA_SIZE];
uint8_t data[MAX_DATA_SIZE]; uint8_t data[MAX_DATA_SIZE];
int length = read_packet(crypto_connections[i].number, temp_data); int length = read_packet(crypto_connections[i].number, temp_data);
int len = decrypt_data(crypto_connections[i].peersessionpublic_key, int len = decrypt_data(crypto_connections[i].peersessionpublic_key,
crypto_connections[i].sessionsecret_key, crypto_connections[i].sessionsecret_key,
crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
uint32_t zero = 0; 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); increment_nonce(crypto_connections[i].recv_nonce);
crypto_connections[i].status = 3; crypto_connections[i].status = 3;
/* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */ /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
kill_connection_in(crypto_connections[i].number, 3000000); kill_connection_in(crypto_connections[i].number, 3000000);
} } else
else
crypto_kill(crypto_connections[i].number); // This should not happen kill the connection if it does crypto_kill(crypto_connections[i].number); // This should not happen kill the connection if it does
} } else if(id_packet(crypto_connections[i].number) != -1)
else if(id_packet(crypto_connections[i].number) != -1)
/* This should not happen /* This should not happen
kill the connection if it does */ kill the connection if it does */
crypto_kill(crypto_connections[i].number); crypto_kill(crypto_connections[i].number);

View File

@ -1,5 +1,5 @@
/* net_crypto.h /* net_crypto.h
* *
* Functions for the core network crypto. * Functions for the core network crypto.
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
@ -18,11 +18,11 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifndef NET_CRYPTO_H #ifndef NET_CRYPTO_H
#define NET_CRYPTO_H #define NET_CRYPTO_H
#include "Lossless_UDP.h" #include "Lossless_UDP.h"
@ -30,102 +30,102 @@
extern "C" { extern "C" {
#endif #endif
/* Our public key. */ /* Our public key. */
extern uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; extern uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
#define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
/* encrypts plain of length length to encrypted of length + 16 using the /* encrypts plain of length length to encrypted of length + 16 using the
public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce
return -1 if there was a problem. return -1 if there was a problem.
return length of encrypted data if everything was fine. */ return length of encrypted data if everything was fine. */
int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
uint8_t *plain, uint32_t length, uint8_t *encrypted); uint8_t *plain, uint32_t length, uint8_t *encrypted);
/* decrypts encrypted of length length to plain of length length - 16 using the /* decrypts encrypted of length length to plain of length length - 16 using the
public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce
return -1 if there was a problem(decryption failed) return -1 if there was a problem(decryption failed)
return length of plain data if everything was fine. */ return length of plain data if everything was fine. */
int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
uint8_t *encrypted, uint32_t length, uint8_t *plain); uint8_t *encrypted, uint32_t length, uint8_t *plain);
/* fill the given nonce with random bytes. */ /* fill the given nonce with random bytes. */
void random_nonce(uint8_t *nonce); void random_nonce(uint8_t *nonce);
/* return 0 if there is no received data in the buffer /* return 0 if there is no received data in the buffer
return -1 if the packet was discarded. return -1 if the packet was discarded.
return length of received data if successful */ return length of received data if successful */
int read_cryptpacket(int crypt_connection_id, uint8_t *data); int read_cryptpacket(int crypt_connection_id, uint8_t *data);
/* return 0 if data could not be put in packet queue /* return 0 if data could not be put in packet queue
return 1 if data was put into the queue */ return 1 if data was put into the queue */
int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length); int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length);
/* create a request to peer with public_key. /* create a request to peer with public_key.
packet must be an array of MAX_DATA_SIZE big. packet must be an array of MAX_DATA_SIZE big.
Data represents the data we send with the request with length being the length of the data. Data represents the data we send with the request with length being the length of the data.
request_id is the id of the request (32 = friend request, 254 = ping request) request_id is the id of the request (32 = friend request, 254 = ping request)
returns -1 on failure returns -1 on failure
returns the length of the created packet on success */ 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); 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 /* 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. 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 packet is the request packet and length is its length
return -1 if not valid request. */ return -1 if not valid request. */
int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *packet, uint16_t length); 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 /* Start a secure connection with other peer who has public_key and ip_port
returns -1 if failure returns -1 if failure
returns crypt_connection_id of the initialized connection if everything went well. */ returns crypt_connection_id of the initialized connection if everything went well. */
int crypto_connect(uint8_t *public_key, IP_Port ip_port); int crypto_connect(uint8_t *public_key, IP_Port ip_port);
/* kill a crypto connection /* kill a crypto connection
return 0 if killed successfully return 0 if killed successfully
return 1 if there was a problem. */ return 1 if there was a problem. */
int crypto_kill(int crypt_connection_id); int crypto_kill(int crypt_connection_id);
/* handle an incoming connection /* handle an incoming connection
return -1 if no crypto inbound connection return -1 if no crypto inbound connection
return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection
Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
and the session public key for the connection in session_key and the session public key for the connection in session_key
to accept it see: accept_crypto_inbound(...) to accept it see: accept_crypto_inbound(...)
to refuse it just call kill_connection(...) on the 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); 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 /* accept an incoming connection using the parameters provided by crypto_inbound
return -1 if not successful return -1 if not successful
returns the crypt_connection_id if successful */ returns the crypt_connection_id if successful */
int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t * secret_nonce, uint8_t *session_key); int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t * secret_nonce, uint8_t *session_key);
/* 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 connexion is not confirmed yet
(we have received a handshake but no empty data packet), 3 if the connection is established. (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 */ 4 if the connection is timed out and waiting to be killed */
int is_cryptoconnected(int crypt_connection_id); int is_cryptoconnected(int crypt_connection_id);
/* Generate our public and private keys /* Generate our public and private keys
Only call this function the first time the program starts. */ Only call this function the first time the program starts. */
void new_keys(); void new_keys();
/* save the public and private keys to the keys array /* save the public and private keys to the keys array
Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
void save_keys(uint8_t * keys); void save_keys(uint8_t * keys);
/* load the public and private keys from the keys array /* load the public and private keys from the keys array
Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
void load_keys(uint8_t * keys); void load_keys(uint8_t * keys);
/* run this to (re)initialize net_crypto /* run this to (re)initialize net_crypto
sets all the global connection variables to their default values. */ sets all the global connection variables to their default values. */
void initNetCrypto(); void initNetCrypto();
/* main loop */ /* main loop */
void doNetCrypto(); void doNetCrypto();
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,7 +1,7 @@
/* network.h /* network.h
* *
* Functions for the core networking. * Functions for the core networking.
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
* *
* This file is part of Tox. * This file is part of Tox.
@ -18,7 +18,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "network.h" #include "network.h"
@ -27,7 +27,7 @@
uint64_t current_time() uint64_t current_time()
{ {
uint64_t time; uint64_t time;
#ifdef WIN32 #ifdef WIN32
/* This probably works fine */ /* This probably works fine */
FILETIME ft; FILETIME ft;
GetSystemTimeAsFileTime(&ft); GetSystemTimeAsFileTime(&ft);
@ -36,24 +36,24 @@ uint64_t current_time()
time |= ft.dwLowDateTime; time |= ft.dwLowDateTime;
time -= 116444736000000000UL; time -= 116444736000000000UL;
return time/10; return time/10;
#else #else
struct timeval a; struct timeval a;
gettimeofday(&a, NULL); gettimeofday(&a, NULL);
time = 1000000UL*a.tv_sec + a.tv_usec; time = 1000000UL*a.tv_sec + a.tv_usec;
return time; return time;
#endif #endif
} }
/* return a random number /* return a random number
NOTE: this function should probably not be used where cryptographic randomness is absolutely necessary */ NOTE: this function should probably not be used where cryptographic randomness is absolutely necessary */
uint32_t random_int() uint32_t random_int()
{ {
#ifndef VANILLA_NACL #ifndef VANILLA_NACL
//NOTE: this function comes from libsodium //NOTE: this function comes from libsodium
return randombytes_random(); return randombytes_random();
#else #else
return random(); return random();
#endif #endif
} }
/* our UDP socket, a global variable. */ /* our UDP socket, a global variable. */
@ -63,7 +63,7 @@ static int sock;
Function to send packet(data) of length length to ip_port */ Function to send packet(data) of length length to ip_port */
int sendpacket(IP_Port ip_port, uint8_t * data, uint32_t length) int sendpacket(IP_Port ip_port, uint8_t * data, uint32_t length)
{ {
ADDR addr = {AF_INET, ip_port.port, ip_port.ip}; ADDR addr = {AF_INET, ip_port.port, ip_port.ip};
return sendto(sock,(char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); return sendto(sock,(char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr));
} }
@ -74,15 +74,15 @@ int sendpacket(IP_Port ip_port, uint8_t * data, uint32_t length)
int receivepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length) int receivepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length)
{ {
ADDR addr; ADDR addr;
#ifdef WIN32 #ifdef WIN32
int addrlen = sizeof(addr); int addrlen = sizeof(addr);
#else #else
uint32_t addrlen = sizeof(addr); uint32_t addrlen = sizeof(addr);
#endif #endif
(*(int32_t*)length) = recvfrom(sock,(char*) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr*)&addr, &addrlen); (*(int32_t*)length) = recvfrom(sock,(char*) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr*)&addr, &addrlen);
if (*(int32_t*)length <= 0) if (*(int32_t*)length <= 0)
return -1; /* nothing received or empty packet */ return -1; /* nothing received or empty packet */
ip_port->ip = addr.ip; ip_port->ip = addr.ip;
ip_port->port = addr.port; ip_port->port = addr.port;
return 0; return 0;
@ -92,30 +92,30 @@ int receivepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length)
bind to ip and port bind to ip and port
ip must be in network order EX: 127.0.0.1 = (7F000001) ip must be in network order EX: 127.0.0.1 = (7F000001)
port is in host byte order (this means don't worry about it) port is in host byte order (this means don't worry about it)
returns 0 if no problems returns 0 if no problems
returns -1 if there are 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 #ifdef WIN32
WSADATA wsaData; WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)
return -1; return -1;
#else #else
srandom((uint32_t)current_time()); srandom((uint32_t)current_time());
#endif #endif
srand((uint32_t)current_time()); srand((uint32_t)current_time());
/* initialize our socket */ /* initialize our socket */
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
/* Check for socket error */ /* Check for socket error */
#ifdef WIN32 #ifdef WIN32
if (sock == INVALID_SOCKET) /* MSDN recommends this */ if (sock == INVALID_SOCKET) /* MSDN recommends this */
return -1; return -1;
#else #else
if (sock < 0) if (sock < 0)
return -1; return -1;
#endif #endif
/* Functions to increase the size of the send and receive UDP buffers /* Functions to increase the size of the send and receive UDP buffers
NOTE: uncomment if necessary */ NOTE: uncomment if necessary */
@ -129,23 +129,23 @@ int init_networking(IP ip, uint16_t port)
if(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&n, sizeof(n)) == -1) if(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&n, sizeof(n)) == -1)
return -1; return -1;
*/ */
/* Enable broadcast on socket */ /* Enable broadcast on socket */
int broadcast = 1; int broadcast = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof(broadcast)); setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof(broadcast));
/* Set socket nonblocking */ /* Set socket nonblocking */
#ifdef WIN32 #ifdef WIN32
/* I think this works for windows */ /* I think this works for windows */
u_long mode = 1; u_long mode = 1;
/* ioctl(sock, FIONBIO, &mode); */ /* ioctl(sock, FIONBIO, &mode); */
ioctlsocket(sock, FIONBIO, &mode); ioctlsocket(sock, FIONBIO, &mode);
#else #else
fcntl(sock, F_SETFL, O_NONBLOCK, 1); fcntl(sock, F_SETFL, O_NONBLOCK, 1);
#endif #endif
/* Bind our socket to port PORT and address 0.0.0.0 */ /* Bind our socket to port PORT and address 0.0.0.0 */
ADDR addr = {AF_INET, htons(port), ip}; ADDR addr = {AF_INET, htons(port), ip};
bind(sock, (struct sockaddr*)&addr, sizeof(addr)); bind(sock, (struct sockaddr*)&addr, sizeof(addr));
return 0; return 0;
@ -155,12 +155,12 @@ int init_networking(IP ip, uint16_t port)
/* function to cleanup networking stuff */ /* function to cleanup networking stuff */
void shutdown_networking() void shutdown_networking()
{ {
#ifdef WIN32 #ifdef WIN32
closesocket(sock); closesocket(sock);
WSACleanup(); WSACleanup();
#else #else
close(sock); close(sock);
#endif #endif
return; return;
} }

View File

@ -1,5 +1,5 @@
/* network.h /* network.h
* *
* Datatypes, functions and includes for the core networking. * Datatypes, functions and includes for the core networking.
* *
* Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
@ -18,11 +18,11 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifndef NETWORK_H #ifndef NETWORK_H
#define NETWORK_H #define NETWORK_H
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -46,7 +46,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <errno.h> #include <errno.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <netdb.h> #include <netdb.h>
#include <unistd.h> #include <unistd.h>
@ -69,63 +69,63 @@ extern "C" {
#define MAX_UDP_PACKET_SIZE 65507 #define MAX_UDP_PACKET_SIZE 65507
typedef union { typedef union {
uint8_t c[4]; uint8_t c[4];
uint16_t s[2]; uint16_t s[2];
uint32_t i; uint32_t i;
} IP; } IP;
typedef struct { typedef struct {
IP ip; IP ip;
uint16_t port; uint16_t port;
/* not used for anything right now */ /* not used for anything right now */
uint16_t padding; uint16_t padding;
} IP_Port; } IP_Port;
typedef struct { typedef struct {
int16_t family; int16_t family;
uint16_t port; uint16_t port;
IP ip; IP ip;
uint8_t zeroes[8]; uint8_t zeroes[8];
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
uint8_t zeroes2[12]; uint8_t zeroes2[12];
#endif #endif
} ADDR; } ADDR;
/* returns current time in milleseconds since the epoch. */ /* returns current time in milleseconds since the epoch. */
uint64_t current_time(); uint64_t current_time();
/* return a random number /* return a random number
NOTE: this function should probably not be used where cryptographic randomness is absolutely necessary */ NOTE: this function should probably not be used where cryptographic randomness is absolutely necessary */
uint32_t random_int(); uint32_t random_int();
/* Basic network functions: */ /* Basic network functions: */
/* Function to send packet(data) of length length to ip_port */ /* Function to send packet(data) of length length to ip_port */
int sendpacket(IP_Port ip_port, uint8_t *data, uint32_t length); int sendpacket(IP_Port ip_port, uint8_t *data, uint32_t length);
/* Function to receive data, ip and port of sender is put into ip_port /* Function to receive data, ip and port of sender is put into ip_port
the packet data into data the packet data into data
the packet length into length. */ the packet length into length. */
int receivepacket(IP_Port *ip_port, uint8_t *data, uint32_t *length); int receivepacket(IP_Port *ip_port, uint8_t *data, uint32_t *length);
/* initialize networking /* initialize networking
bind to ip and port bind to ip and port
ip must be in network order EX: 127.0.0.1 = (7F000001) ip must be in network order EX: 127.0.0.1 = (7F000001)
port is in host byte order (this means don't worry about it) port is in host byte order (this means don't worry about it)
returns 0 if no problems returns 0 if no problems
returns -1 if there were problems */ returns -1 if there were problems */
int init_networking(IP ip, uint16_t port); int init_networking(IP ip, uint16_t port);
/* function to cleanup networking stuff(doesn't do much right now) */ /* function to cleanup networking stuff(doesn't do much right now) */
void shutdown_networking(); void shutdown_networking();
/* resolves provided address to a binary data in network byte order /* resolves provided address to a binary data in network byte order
address is ASCII null terminated string address is ASCII null terminated string
address should represent IPv4, IPv6 or a hostname address should represent IPv4, IPv6 or a hostname
on success returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i on success returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
on failure returns -1 */ on failure returns -1 */
int resolve_addr(char *address); int resolve_addr(char *address);
#ifdef __cplusplus #ifdef __cplusplus
} }