From a1c40d753ee8faf15aa0dd314bd4249aa3750b2e Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 20 Aug 2013 12:08:55 -0400 Subject: [PATCH] More refactoring done. --- core/DHT.c | 498 +++++++++++++++++--------------------- core/DHT.h | 93 +++++-- core/LAN_discovery.c | 13 +- core/LAN_discovery.h | 4 +- core/Messenger.c | 56 +++-- core/Messenger.h | 2 + core/friend_requests.c | 77 +++--- core/friend_requests.h | 25 +- core/net_crypto.c | 33 ++- core/net_crypto.h | 36 +-- core/network.c | 1 - core/network.h | 1 - core/ping.c | 31 +-- testing/toxic/dhtstatus.c | 2 +- testing/toxic/main.c | 14 +- testing/toxic/prompt.c | 2 +- 16 files changed, 461 insertions(+), 427 deletions(-) diff --git a/core/DHT.c b/core/DHT.c index b2aa44f8..d58c6d2c 100644 --- a/core/DHT.c +++ b/core/DHT.c @@ -27,17 +27,6 @@ #include "packets.h" #include "ping.h" -/* maximum number of clients stored per friend. */ -#define MAX_FRIEND_CLIENTS 8 - -/* A list of the clients mathematically closest to ours. */ -#define LCLIENT_LIST 32 - -/* The list of ip ports along with the ping_id of what we sent them and a timestamp */ -#define LPING_ARRAY 256 - -#define LSEND_NODES_ARRAY LPING_ARRAY/2 - /* the number of seconds for a non responsive node to become bad. */ #define BAD_NODE_TIMEOUT 70 @@ -61,59 +50,13 @@ /*Interval in seconds between punching attempts*/ #define PUNCH_INTERVAL 10 -/*Maximum newly announced nodes to ping per TIME_TOPING seconds*/ -#define MAX_TOPING 16 - +/*Ping newly announced nodes to ping per TIME_TOPING seconds*/ #define TIME_TOPING 5 -/*----------------------------------------------------------------------------------*/ - -typedef struct { - uint8_t client_id[CLIENT_ID_SIZE]; - Client_data client_list[MAX_FRIEND_CLIENTS]; - - /* time at which the last get_nodes request was sent. */ - uint64_t lastgetnode; - - /* Symetric NAT hole punching stuff */ - - /* 1 if currently hole punching, otherwise 0 */ - uint8_t hole_punching; - uint32_t punching_index; - uint64_t punching_timestamp; - uint64_t recvNATping_timestamp; - uint64_t NATping_id; - uint64_t NATping_timestamp; -} Friend; - -typedef struct { - uint8_t client_id[CLIENT_ID_SIZE]; - IP_Port ip_port; -} Node_format; - -typedef struct { - IP_Port ip_port; - uint64_t ping_id; - uint64_t timestamp; -} Pinged; - -/*----------------------------------------------------------------------------------*/ - -/* Our client id/public key */ -uint8_t self_public_key[CLIENT_ID_SIZE]; -uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; -static Client_data close_clientlist[LCLIENT_LIST]; -static Friend *friends_list; -static uint16_t num_friends; -static Pinged send_nodes[LSEND_NODES_ARRAY]; -static Node_format toping[MAX_TOPING]; -static uint64_t last_toping; - -/*----------------------------------------------------------------------------------*/ -Client_data *DHT_get_close_list(void) +Client_data *DHT_get_close_list(DHT * dht) { - return close_clientlist; + return dht->close_clientlist; } /* Compares client_id1 and client_id2 with client_id @@ -203,12 +146,12 @@ static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *clien /* Returns the friend number from the client_id, or -1 if a failure occurs */ -static int friend_number(uint8_t *client_id) +static int friend_number(DHT * dht, uint8_t *client_id) { uint32_t i; - for (i = 0; i < num_friends; ++i) { - if (id_equal(friends_list[i].client_id, client_id)) + for (i = 0; i < dht->num_friends; ++i) { + if (id_equal(dht->friends_list[i].client_id, client_id)) return i; } @@ -220,15 +163,15 @@ static int friend_number(uint8_t *client_id) * * TODO: For the love of based Allah make this function cleaner and much more efficient. */ -static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list) +static int get_close_nodes(DHT * dht, uint8_t *client_id, Node_format *nodes_list) { uint32_t i, j, k; uint64_t temp_time = unix_time(); int num_nodes = 0, closest, tout, inlist; for (i = 0; i < LCLIENT_LIST; ++i) { - tout = is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); - inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, close_clientlist[i].client_id); + tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); + inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); /* if node isn't good or is already in list. */ if (tout || inlist) @@ -237,10 +180,10 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list) if (num_nodes < MAX_SENT_NODES) { memcpy( nodes_list[num_nodes].client_id, - close_clientlist[i].client_id, + dht->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 = dht->close_clientlist[i].ip_port; num_nodes++; } else { @@ -248,27 +191,27 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list) for (j = 0; j < MAX_SENT_NODES; ++j) { closest = id_closest( client_id, nodes_list[j].client_id, - close_clientlist[i].client_id ); + dht->close_clientlist[i].client_id ); if (closest == 2) { memcpy( nodes_list[j].client_id, - close_clientlist[i].client_id, + dht->close_clientlist[i].client_id, CLIENT_ID_SIZE); - nodes_list[j].ip_port = close_clientlist[i].ip_port; + nodes_list[j].ip_port = dht->close_clientlist[i].ip_port; break; } } } } - for (i = 0; i < num_friends; ++i) { + for (i = 0; i < dht->num_friends; ++i) { for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { - tout = is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT); + tout = is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT); inlist = client_in_nodelist( nodes_list, MAX_SENT_NODES, - friends_list[i].client_list[j].client_id); + dht->friends_list[i].client_list[j].client_id); /* if node isn't good or is already in list. */ if (tout || inlist) @@ -277,24 +220,24 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list) if (num_nodes < MAX_SENT_NODES) { memcpy( nodes_list[num_nodes].client_id, - friends_list[i].client_list[j].client_id, + dht->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 = dht->friends_list[i].client_list[j].ip_port; num_nodes++; } else { for (k = 0; k < MAX_SENT_NODES; ++k) { closest = id_closest( client_id, nodes_list[k].client_id, - friends_list[i].client_list[j].client_id ); + dht->friends_list[i].client_list[j].client_id ); if (closest == 2) { memcpy( nodes_list[k].client_id, - friends_list[i].client_list[j].client_id, + dht->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 = dht->friends_list[i].client_list[j].ip_port; break; } } @@ -387,40 +330,40 @@ static int replace_good( Client_data *list, /* Attempt to add client with ip_port and client_id to the friends client list * and close_clientlist */ -void addto_lists(IP_Port ip_port, uint8_t *client_id) +void addto_lists(DHT * dht, IP_Port ip_port, uint8_t *client_id) { uint32_t i; /* NOTE: current behavior if there are two clients with the same id is * to replace the first ip by the second. */ - if (!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) { - if (replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) { + if (!client_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { + if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { /* if we can't replace bad nodes we try replacing good ones */ - replace_good( close_clientlist, + replace_good( dht->close_clientlist, LCLIENT_LIST, client_id, ip_port, - self_public_key ); + dht->c->self_public_key ); } } - for (i = 0; i < num_friends; ++i) { - if (!client_in_list( friends_list[i].client_list, + for (i = 0; i < dht->num_friends; ++i) { + if (!client_in_list( dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port )) { - if (replace_bad( friends_list[i].client_list, + if (replace_bad( dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port )) { /* if we can't replace bad nodes we try replacing good ones. */ - replace_good( friends_list[i].client_list, + replace_good( dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port, - friends_list[i].client_id ); + dht->friends_list[i].client_id ); } } } @@ -429,30 +372,30 @@ void addto_lists(IP_Port ip_port, uint8_t *client_id) /* 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 */ -static void returnedip_ports(IP_Port ip_port, uint8_t *client_id, uint8_t *nodeclient_id) +static void returnedip_ports(DHT * dht, IP_Port ip_port, uint8_t *client_id, uint8_t *nodeclient_id) { uint32_t i, j; uint64_t temp_time = unix_time(); - if (id_equal(client_id, self_public_key)) { + if (id_equal(client_id, dht->c->self_public_key)) { for (i = 0; i < LCLIENT_LIST; ++i) { - if (id_equal(nodeclient_id, close_clientlist[i].client_id)) { - close_clientlist[i].ret_ip_port = ip_port; - close_clientlist[i].ret_timestamp = temp_time; + if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { + dht->close_clientlist[i].ret_ip_port = ip_port; + dht->close_clientlist[i].ret_timestamp = temp_time; return; } } } else { - for (i = 0; i < num_friends; ++i) { - if (id_equal(client_id, friends_list[i].client_id)) { + for (i = 0; i < dht->num_friends; ++i) { + if (id_equal(client_id, dht->friends_list[i].client_id)) { for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { - if (id_equal(nodeclient_id, friends_list[i].client_list[j].client_id)) { - friends_list[i].client_list[j].ret_ip_port = ip_port; - friends_list[i].client_list[j].ret_timestamp = temp_time; + if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) { + dht->friends_list[i].client_list[j].ret_ip_port = ip_port; + dht->friends_list[i].client_list[j].ret_timestamp = temp_time; return; } } @@ -463,20 +406,20 @@ static void returnedip_ports(IP_Port ip_port, uint8_t *client_id, uint8_t *nodec } /* Same as last function but for get_node requests. */ -static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) +static int is_gettingnodes(DHT * dht, IP_Port ip_port, uint64_t ping_id) { uint32_t i; uint8_t pinging; uint64_t temp_time = unix_time(); for (i = 0; i < LSEND_NODES_ARRAY; ++i ) { - if (!is_timeout(temp_time, send_nodes[i].timestamp, PING_TIMEOUT)) { + if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { pinging = 0; - if (ip_port.ip.i != 0 && ipport_equal(send_nodes[i].ip_port, ip_port)) + if (ip_port.ip.i != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port)) ++pinging; - if (ping_id != 0 && send_nodes[i].ping_id == ping_id) + if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) ++pinging; if (pinging == (ping_id != 0) + (ip_port.ip.i != 0)) @@ -488,7 +431,7 @@ static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) } /* Same but for get node requests */ -static uint64_t add_gettingnodes(IP_Port ip_port) +static uint64_t add_gettingnodes(DHT * dht, IP_Port ip_port) { uint32_t i, j; uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); @@ -496,10 +439,10 @@ static uint64_t add_gettingnodes(IP_Port ip_port) for (i = 0; i < PING_TIMEOUT; ++i ) { for (j = 0; j < LSEND_NODES_ARRAY; ++j ) { - if (is_timeout(temp_time, send_nodes[j].timestamp, PING_TIMEOUT - i)) { - send_nodes[j].timestamp = temp_time; - send_nodes[j].ip_port = ip_port; - send_nodes[j].ping_id = ping_id; + if (is_timeout(temp_time, dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) { + dht->send_nodes[j].timestamp = temp_time; + dht->send_nodes[j].ip_port = ip_port; + dht->send_nodes[j].ping_id = ping_id; return ping_id; } } @@ -509,13 +452,13 @@ static uint64_t add_gettingnodes(IP_Port ip_port) } /* send a getnodes request */ -static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id) +static int getnodes(DHT * dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id) { /* check if packet is gonna be sent to ourself */ - if (id_equal(public_key, self_public_key) || is_gettingnodes(ip_port, 0)) + if (id_equal(public_key, dht->c->self_public_key) || is_gettingnodes(dht, ip_port, 0)) return 1; - uint64_t ping_id = add_gettingnodes(ip_port); + uint64_t ping_id = add_gettingnodes(dht, ip_port); if (ping_id == 0) return 1; @@ -530,7 +473,7 @@ static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id) memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); int len = encrypt_data( public_key, - self_secret_key, + dht->c->self_secret_key, nonce, plain, sizeof(ping_id) + CLIENT_ID_SIZE, @@ -540,25 +483,25 @@ static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id) return -1; data[0] = 2; - memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); + memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); - return sendpacket(temp_net->sock, ip_port, data, sizeof(data)); + return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data)); } /* send a send nodes response */ -static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) +static int sendnodes(DHT * dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) { /* check if packet is gonna be sent to ourself */ - if (id_equal(public_key, self_public_key)) + if (id_equal(public_key, dht->c->self_public_key)) return 1; uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; Node_format nodes_list[MAX_SENT_NODES]; - int num_nodes = get_close_nodes(client_id, nodes_list); + int num_nodes = get_close_nodes(dht, client_id, nodes_list); if (num_nodes == 0) return 0; @@ -572,7 +515,7 @@ static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, u memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); int len = encrypt_data( public_key, - self_secret_key, + dht->c->self_secret_key, nonce, plain, sizeof(ping_id) + num_nodes * sizeof(Node_format), @@ -582,15 +525,16 @@ static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, u return -1; data[0] = 3; - memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); + memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); - return sendpacket(temp_net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); + return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); } static int handle_getnodes(void * object, IP_Port source, uint8_t *packet, uint32_t length) { + DHT * dht = object; uint64_t ping_id; if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES @@ -598,13 +542,13 @@ static int handle_getnodes(void * object, IP_Port source, uint8_t *packet, uint3 return 1; /* check if packet is from ourself. */ - if (id_equal(packet + 1, self_public_key)) + if (id_equal(packet + 1, dht->c->self_public_key)) return 1; uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; int len = decrypt_data( packet + 1, - self_secret_key, + dht->c->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, @@ -614,15 +558,16 @@ static int handle_getnodes(void * object, IP_Port source, uint8_t *packet, uint3 return 1; memcpy(&ping_id, plain, sizeof(ping_id)); - sendnodes(source, packet + 1, plain + sizeof(ping_id), ping_id); + sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); - //send_ping_request(source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */ + //send_ping_request(dht, source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */ return 0; } static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint32_t length) { + DHT * dht = object; uint64_t ping_id; uint32_t cid_size = 1 + CLIENT_ID_SIZE; cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; @@ -637,7 +582,7 @@ static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint int len = decrypt_data( packet + 1, - self_secret_key, + dht->c->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); @@ -647,19 +592,19 @@ static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint memcpy(&ping_id, plain, sizeof(ping_id)); - if (!is_gettingnodes(source, ping_id)) + if (!is_gettingnodes(dht, source, ping_id)) return 1; Node_format nodes_list[MAX_SENT_NODES]; memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); - addto_lists(source, packet + 1); + addto_lists(dht, source, packet + 1); uint32_t i; for (i = 0; i < num_nodes; ++i) { send_ping_request(nodes_list[i].ip_port, (clientid_t *) &nodes_list[i].client_id); - returnedip_ports(nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); + returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); } return 0; @@ -668,54 +613,54 @@ static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint /*----------------------------------------------------------------------------------*/ /*------------------------END of packet handling functions--------------------------*/ -int DHT_addfriend(uint8_t *client_id) +int DHT_addfriend(DHT * dht, uint8_t *client_id) { - if (friend_number(client_id) != -1) /*Is friend already in DHT?*/ + if (friend_number(dht, client_id) != -1) /*Is friend already in DHT?*/ return 1; - Friend *temp; - temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); + DHT_Friend *temp; + temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1)); if (temp == NULL) return 1; - friends_list = temp; - memset(&friends_list[num_friends], 0, sizeof(Friend)); - memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE); + dht->friends_list = temp; + memset(&dht->friends_list[dht->num_friends], 0, sizeof(DHT_Friend)); + memcpy(dht->friends_list[dht->num_friends].client_id, client_id, CLIENT_ID_SIZE); - friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); - ++num_friends; + dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); + ++dht->num_friends; return 0; } -int DHT_delfriend(uint8_t *client_id) +int DHT_delfriend(DHT * dht, uint8_t *client_id) { uint32_t i; - Friend *temp; + DHT_Friend *temp; - for (i = 0; i < num_friends; ++i) { + for (i = 0; i < dht->num_friends; ++i) { /* Equal */ - if (id_equal(friends_list[i].client_id, client_id)) { - --num_friends; + if (id_equal(dht->friends_list[i].client_id, client_id)) { + --dht->num_friends; - if (num_friends != i) { - memcpy( friends_list[i].client_id, - friends_list[num_friends].client_id, + if (dht->num_friends != i) { + memcpy( dht->friends_list[i].client_id, + dht->friends_list[dht->num_friends].client_id, CLIENT_ID_SIZE ); } - if (num_friends == 0) { - free(friends_list); - friends_list = NULL; + if (dht->num_friends == 0) { + free(dht->friends_list); + dht->friends_list = NULL; return 0; } - temp = realloc(friends_list, sizeof(Friend) * (num_friends)); + temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends)); if (temp == NULL) return 1; - friends_list = temp; + dht->friends_list = temp; return 0; } } @@ -724,19 +669,19 @@ int DHT_delfriend(uint8_t *client_id) } /* TODO: Optimize this. */ -IP_Port DHT_getfriendip(uint8_t *client_id) +IP_Port DHT_getfriendip(DHT * dht, uint8_t *client_id) { uint32_t i, j; uint64_t temp_time = unix_time(); IP_Port empty = {{{0}}, 0}; - for (i = 0; i < num_friends; ++i) { + for (i = 0; i < dht->num_friends; ++i) { /* Equal */ - if (id_equal(friends_list[i].client_id, client_id)) { + if (id_equal(dht->friends_list[i].client_id, client_id)) { for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { - if (id_equal(friends_list[i].client_list[j].client_id, client_id) - && !is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) - return friends_list[i].client_list[j].ip_port; + if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) + && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) + return dht->friends_list[i].client_list[j].ip_port; } return empty; @@ -750,49 +695,47 @@ IP_Port DHT_getfriendip(uint8_t *client_id) /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list. */ -static void doDHTFriends(void) +static void do_DHT_friends(DHT * dht) { uint32_t i, j; uint64_t temp_time = unix_time(); uint32_t rand_node; uint32_t index[MAX_FRIEND_CLIENTS]; - for (i = 0; i < num_friends; ++i) { + for (i = 0; i < dht->num_friends; ++i) { uint32_t num_nodes = 0; for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { /* if node is not dead. */ - if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { - if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { - send_ping_request( friends_list[i].client_list[j].ip_port, - (clientid_t *) &friends_list[i].client_list[j].client_id ); - friends_list[i].client_list[j].last_pinged = temp_time; + if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { + if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { + send_ping_request( dht->friends_list[i].client_list[j].ip_port, + (clientid_t *) &dht->friends_list[i].client_list[j].client_id ); + dht->friends_list[i].client_list[j].last_pinged = temp_time; } /* if node is good. */ - if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { + if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { index[num_nodes] = j; ++num_nodes; } } } - if (friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { + if (dht->friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { rand_node = rand() % num_nodes; - getnodes( friends_list[i].client_list[index[rand_node]].ip_port, - friends_list[i].client_list[index[rand_node]].client_id, - friends_list[i].client_id ); - friends_list[i].lastgetnode = temp_time; + getnodes(dht, dht->friends_list[i].client_list[index[rand_node]].ip_port, + dht->friends_list[i].client_list[index[rand_node]].client_id, + dht->friends_list[i].client_id ); + dht->friends_list[i].lastgetnode = temp_time; } } } -static uint64_t close_lastgetnodes; - /* Ping each client in the close nodes list every PING_INTERVAL seconds. * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list. */ -static void doClose(void) +static void do_Close(DHT * dht) { uint32_t i; uint64_t temp_time = unix_time(); @@ -802,46 +745,47 @@ static void doClose(void) for (i = 0; i < LCLIENT_LIST; ++i) { /* if node is not dead. */ - if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { - if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { - send_ping_request( close_clientlist[i].ip_port, - (clientid_t *) &close_clientlist[i].client_id ); - close_clientlist[i].last_pinged = temp_time; + if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { + if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { + send_ping_request( dht->close_clientlist[i].ip_port, + (clientid_t *) &dht->close_clientlist[i].client_id ); + dht->close_clientlist[i].last_pinged = temp_time; } /* if node is good. */ - if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) { + if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) { index[num_nodes] = i; ++num_nodes; } } } - if (close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { + if (dht->close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { rand_node = rand() % num_nodes; - getnodes( close_clientlist[index[rand_node]].ip_port, - close_clientlist[index[rand_node]].client_id, - self_public_key ); - close_lastgetnodes = temp_time; + getnodes(dht, dht->close_clientlist[index[rand_node]].ip_port, + dht->close_clientlist[index[rand_node]].client_id, + dht->c->self_public_key ); + dht->close_lastgetnodes = temp_time; } } -void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key) +void DHT_bootstrap(DHT * dht, IP_Port ip_port, uint8_t *public_key) { - getnodes(ip_port, public_key, self_public_key); + getnodes(dht, ip_port, public_key, dht->c->self_public_key); + //send_ping_request(dht, ip_port, (clientid_t *) public_key); send_ping_request(ip_port, (clientid_t *) public_key); } /* send the given packet to node with client_id * returns -1 if failure */ -int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length) +int route_packet(DHT * dht, uint8_t *client_id, uint8_t *packet, uint32_t length) { uint32_t i; for (i = 0; i < LCLIENT_LIST; ++i) { - if (id_equal(client_id, close_clientlist[i].client_id)) - return sendpacket(temp_net->sock, close_clientlist[i].ip_port, packet, length); + if (id_equal(client_id, dht->close_clientlist[i].client_id)) + return sendpacket(dht->c->lossless_udp->net->sock, dht->close_clientlist[i].ip_port, packet, length); } return -1; @@ -853,16 +797,16 @@ int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length) * return 0 if we are connected to friend or if no ips were found. * returns -1 if no such friend */ -static int friend_iplist(IP_Port *ip_portlist, uint16_t friend_num) +static int friend_iplist(DHT * dht, IP_Port *ip_portlist, uint16_t friend_num) { int num_ips = 0; uint32_t i; uint64_t temp_time = unix_time(); - if (friend_num >= num_friends) + if (friend_num >= dht->num_friends) return -1; - Friend *friend = &friends_list[friend_num]; + DHT_Friend *friend = &dht->friends_list[friend_num]; Client_data *client; for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { @@ -888,9 +832,9 @@ static int friend_iplist(IP_Port *ip_portlist, uint16_t friend_num) * * Only works if more than (MAX_FRIEND_CLIENTS / 2) return an ip for friend. */ -int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) +int route_tofriend(DHT * dht, uint8_t *friend_id, uint8_t *packet, uint32_t length) { - int num = friend_number(friend_id); + int num = friend_number(dht, friend_id); if (num == -1) return 0; @@ -898,13 +842,13 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) uint32_t i, sent = 0; IP_Port ip_list[MAX_FRIEND_CLIENTS]; - int ip_num = friend_iplist(ip_list, num); + int ip_num = friend_iplist(dht, ip_list, num); if (ip_num < (MAX_FRIEND_CLIENTS / 2)) return 0; uint64_t temp_time = unix_time(); - Friend *friend = &friends_list[num]; + DHT_Friend *friend = &dht->friends_list[num]; Client_data *client; for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { @@ -912,7 +856,7 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) /*If ip is not zero and node is good */ if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { - if (sendpacket(temp_net->sock, client->ip_port, packet, length) == length) + if (sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length) == length) ++sent; } } @@ -923,14 +867,14 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) /* Send the following packet to one random person who tells us they are connected to friend_id * returns the number of nodes it sent the packet to */ -static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) +static int routeone_tofriend(DHT * dht, uint8_t *friend_id, uint8_t *packet, uint32_t length) { - int num = friend_number(friend_id); + int num = friend_number(dht, friend_id); if (num == -1) return 0; - Friend *friend = &friends_list[num]; + DHT_Friend *friend = &dht->friends_list[num]; Client_data *client; IP_Port ip_list[MAX_FRIEND_CLIENTS]; @@ -951,7 +895,7 @@ static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t lengt if (n < 1) return 0; - if (sendpacket(temp_net->sock, ip_list[rand() % n], packet, length) == length) + if (sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length) == length) return 1; return 0; @@ -963,14 +907,14 @@ static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t lengt * return 0 if we are connected to friend or if no ips were found. * returns -1 if no such friend */ -int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id) +int friend_ips(DHT * dht, IP_Port *ip_portlist, uint8_t *friend_id) { uint32_t i; - for (i = 0; i < num_friends; ++i) { + for (i = 0; i < dht->num_friends; ++i) { /* Equal */ - if (id_equal(friends_list[i].client_id, friend_id)) - return friend_iplist(ip_portlist, i); + if (id_equal(dht->friends_list[i].client_id, friend_id)) + return friend_iplist(dht, ip_portlist, i); } return -1; @@ -979,7 +923,7 @@ int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id) /*----------------------------------------------------------------------------------*/ /*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/ -static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type) +static int send_NATping(DHT * dht, uint8_t *public_key, uint64_t ping_id, uint8_t type) { uint8_t data[sizeof(uint64_t) + 1]; uint8_t packet[MAX_DATA_SIZE]; @@ -989,15 +933,15 @@ static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type) data[0] = type; memcpy(data + 1, &ping_id, sizeof(uint64_t)); /* 254 is NAT ping request packet id */ - int len = create_request(self_public_key, self_secret_key, packet, public_key, data, sizeof(uint64_t) + 1, 254); + int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, data, sizeof(uint64_t) + 1, 254); if (len == -1) return -1; if (type == 0) /*If packet is request use many people to route it*/ - num = route_tofriend(public_key, packet, len); + num = route_tofriend(dht, public_key, packet, len); else if (type == 1) /*If packet is response use only one person to route it*/ - num = routeone_tofriend(public_key, packet, len); + num = routeone_tofriend(dht, public_key, packet, len); if (num == 0) return -1; @@ -1006,21 +950,22 @@ static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type) } /* Handle a received ping request for */ -static int handle_NATping(IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) +static int handle_NATping(void * object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) { + DHT * dht = object; uint64_t ping_id; memcpy(&ping_id, packet + 1, sizeof(uint64_t)); - int friendnumber = friend_number(source_pubkey); + int friendnumber = friend_number(dht, source_pubkey); if (friendnumber == -1) return 1; - Friend *friend = &friends_list[friendnumber]; + DHT_Friend *friend = &dht->friends_list[friendnumber]; if (packet[0] == 0) { /* 1 is reply */ - send_NATping(source_pubkey, ping_id, 1); + send_NATping(dht, source_pubkey, ping_id, 1); friend->recvNATping_timestamp = unix_time(); return 0; } else if (packet[0] == 1) { @@ -1082,45 +1027,46 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t return num; } -static void punch_holes(IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) +static void punch_holes(DHT * dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) { if (numports > MAX_FRIEND_CLIENTS || numports == 0) return; uint32_t i; - uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; + uint32_t top = dht->friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; - for (i = friends_list[friend_num].punching_index; i != top; i++) { + for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { /*TODO: improve port guessing algorithm*/ uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); IP_Port pinging = {ip, htons(port)}; - send_ping_request(pinging, (clientid_t *) &friends_list[friend_num].client_id); + //send_ping_request(dht, pinging, (clientid_t *) &dht->friends_list[friend_num].client_id); + send_ping_request(pinging, (clientid_t *) &dht->friends_list[friend_num].client_id); } - friends_list[friend_num].punching_index = i; + dht->friends_list[friend_num].punching_index = i; } -static void doNAT(void) +static void do_NAT(DHT * dht) { uint32_t i; uint64_t temp_time = unix_time(); - for (i = 0; i < num_friends; ++i) { + for (i = 0; i < dht->num_friends; ++i) { IP_Port ip_list[MAX_FRIEND_CLIENTS]; - int num = friend_iplist(ip_list, i); + int num = friend_iplist(dht, ip_list, i); /*If already connected or friend is not online don't try to hole punch*/ if (num < MAX_FRIEND_CLIENTS / 2) continue; - if (friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { - send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ - friends_list[i].NATping_timestamp = temp_time; + if (dht->friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { + send_NATping(dht, dht->friends_list[i].client_id, dht->friends_list[i].NATping_id, 0); /*0 is request*/ + dht->friends_list[i].NATping_timestamp = temp_time; } - if (friends_list[i].hole_punching == 1 && - friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && - friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { + if (dht->friends_list[i].hole_punching == 1 && + dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && + dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); @@ -1129,10 +1075,10 @@ static void doNAT(void) uint16_t port_list[MAX_FRIEND_CLIENTS]; uint16_t numports = NAT_getports(port_list, ip_list, num, ip); - punch_holes(ip, port_list, numports, i); + punch_holes(dht, ip, port_list, numports, i); - friends_list[i].punching_timestamp = temp_time; - friends_list[i].hole_punching = 0; + dht->friends_list[i].punching_timestamp = temp_time; + dht->friends_list[i].hole_punching = 0; } } } @@ -1149,7 +1095,7 @@ static void doNAT(void) network while preventing amplification attacks. return 0 if node was added return -1 if node was not added */ -int add_toping(uint8_t *client_id, IP_Port ip_port) +int add_toping(DHT * dht, uint8_t *client_id, IP_Port ip_port) { if (ip_port.ip.i == 0) return -1; @@ -1157,19 +1103,19 @@ int add_toping(uint8_t *client_id, IP_Port ip_port) uint32_t i; for (i = 0; i < MAX_TOPING; ++i) { - if (toping[i].ip_port.ip.i == 0) { - memcpy(toping[i].client_id, client_id, CLIENT_ID_SIZE); - toping[i].ip_port.ip.i = ip_port.ip.i; - toping[i].ip_port.port = ip_port.port; + if (dht->toping[i].ip_port.ip.i == 0) { + memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); + dht->toping[i].ip_port.ip.i = ip_port.ip.i; + dht->toping[i].ip_port.port = ip_port.port; return 0; } } for (i = 0; i < MAX_TOPING; ++i) { - if (id_closest(self_public_key, toping[i].client_id, client_id) == 2) { - memcpy(toping[i].client_id, client_id, CLIENT_ID_SIZE); - toping[i].ip_port.ip.i = ip_port.ip.i; - toping[i].ip_port.port = ip_port.port; + if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { + memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); + dht->toping[i].ip_port.ip.i = ip_port.ip.i; + dht->toping[i].ip_port.port = ip_port.port; return 0; } } @@ -1179,68 +1125,80 @@ int add_toping(uint8_t *client_id, IP_Port ip_port) /*Ping all the valid nodes in the toping list every TIME_TOPING seconds this function must be run at least once every TIME_TOPING seconds*/ -static void do_toping() +static void do_toping(DHT * dht) { uint64_t temp_time = unix_time(); - if (!is_timeout(temp_time, last_toping, TIME_TOPING)) + if (!is_timeout(temp_time, dht->last_toping, TIME_TOPING)) return; - last_toping = temp_time; + dht->last_toping = temp_time; uint32_t i; for (i = 0; i < MAX_TOPING; ++i) { - if (toping[i].ip_port.ip.i == 0) + if (dht->toping[i].ip_port.ip.i == 0) return; - send_ping_request(toping[i].ip_port, (clientid_t *) toping[i].client_id); - toping[i].ip_port.ip.i = 0; + //send_ping_request(dht, dht->toping[i].ip_port, (clientid_t *) dht->toping[i].client_id); + send_ping_request(dht->toping[i].ip_port, (clientid_t *) dht->toping[i].client_id); + dht->toping[i].ip_port.ip.i = 0; } } -void DHT_init(void) +DHT * new_DHT(Net_Crypto *c) { - networking_registerhandler(temp_net, 0, &handle_ping_request, NULL); - networking_registerhandler(temp_net, 1, &handle_ping_response, NULL); - networking_registerhandler(temp_net, 2, &handle_getnodes, NULL); - networking_registerhandler(temp_net, 3, &handle_sendnodes, NULL); - cryptopacket_registerhandler(temp_net_crypto, 254, &handle_NATping); + DHT * temp = calloc(1, sizeof(DHT)); + if (temp == NULL) + return NULL; + temp->c = c; + networking_registerhandler(c->lossless_udp->net, 0, &handle_ping_request, temp); + networking_registerhandler(c->lossless_udp->net, 1, &handle_ping_response, temp); + networking_registerhandler(c->lossless_udp->net, 2, &handle_getnodes, temp); + networking_registerhandler(c->lossless_udp->net, 3, &handle_sendnodes, temp); + cryptopacket_registerhandler(c, 254, &handle_NATping, temp); + temp_DHT = temp; + return temp; } -void doDHT(void) +void do_DHT(DHT * dht) { - doClose(); - doDHTFriends(); - doNAT(); - do_toping(); + do_Close(dht); + do_DHT_friends(dht); + do_NAT(dht); + do_toping(dht); +} +void kill_DHT(DHT * dht) +{ + free(dht->friends_list); + free(dht); } /* get the size of the DHT (for saving) */ -uint32_t DHT_size(void) +uint32_t DHT_size(DHT * dht) { - return sizeof(close_clientlist) + sizeof(Friend) * num_friends; + return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends; } /* save the DHT in data where data is an array of size DHT_size() */ -void DHT_save(uint8_t *data) +void DHT_save(DHT * dht, uint8_t *data) { - memcpy(data, close_clientlist, sizeof(close_clientlist)); - memcpy(data + sizeof(close_clientlist), friends_list, sizeof(Friend) * num_friends); + memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist)); + memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends); } /* load the DHT from data of size size; * return -1 if failure * return 0 if success */ -int DHT_load(uint8_t *data, uint32_t size) +int DHT_load(DHT * dht, uint8_t *data, uint32_t size) { init_ping(); - if (size < sizeof(close_clientlist)) + if (size < sizeof(dht->close_clientlist)) return -1; - if ((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) + if ((size - sizeof(dht->close_clientlist)) % sizeof(DHT_Friend) != 0) return -1; uint32_t i, j; @@ -1249,19 +1207,19 @@ int DHT_load(uint8_t *data, uint32_t size) Client_data *client; - temp = (size - sizeof(close_clientlist)) / sizeof(Friend); + temp = (size - sizeof(dht->close_clientlist)) / sizeof(DHT_Friend); if (temp != 0) { - Friend *tempfriends_list = (Friend *)(data + sizeof(close_clientlist)); + DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); for (i = 0; i < temp; ++i) { - DHT_addfriend(tempfriends_list[i].client_id); + DHT_addfriend(dht, tempfriends_list[i].client_id); for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { client = &tempfriends_list[i].client_list[j]; if (client->timestamp != 0) - getnodes(client->ip_port, client->client_id, tempfriends_list[i].client_id); + getnodes(dht, client->ip_port, client->client_id, tempfriends_list[i].client_id); } } } @@ -1270,7 +1228,7 @@ int DHT_load(uint8_t *data, uint32_t size) for (i = 0; i < LCLIENT_LIST; ++i) { if (tempclose_clientlist[i].timestamp != 0) - DHT_bootstrap( tempclose_clientlist[i].ip_port, + DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, tempclose_clientlist[i].client_id ); } @@ -1280,13 +1238,13 @@ int DHT_load(uint8_t *data, uint32_t size) /* returns 0 if we are not connected to the DHT * returns 1 if we are */ -int DHT_isconnected(void) +int DHT_isconnected(DHT * dht) { uint32_t i; uint64_t temp_time = unix_time(); for (i = 0; i < LCLIENT_LIST; ++i) { - if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) + if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) return 1; } diff --git a/core/DHT.h b/core/DHT.h index 8cb0436a..0ecc0b50 100644 --- a/core/DHT.h +++ b/core/DHT.h @@ -34,6 +34,20 @@ extern "C" { /* size of the client_id in bytes */ #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES +/* maximum number of clients stored per friend. */ +#define MAX_FRIEND_CLIENTS 8 + +/* A list of the clients mathematically closest to ours. */ +#define LCLIENT_LIST 32 + +/* The list of ip ports along with the ping_id of what we sent them and a timestamp */ +#define LPING_ARRAY 256 //NOTE Deprecated (doesn't do anything) + +#define LSEND_NODES_ARRAY LPING_ARRAY/2 + +/*Maximum newly announced nodes to ping per TIME_TOPING seconds*/ +#define MAX_TOPING 16 + typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; IP_Port ip_port; @@ -45,19 +59,64 @@ typedef struct { uint64_t ret_timestamp; } Client_data; -Client_data *DHT_get_close_list(void); +/*----------------------------------------------------------------------------------*/ + +typedef struct { + uint8_t client_id[CLIENT_ID_SIZE]; + Client_data client_list[MAX_FRIEND_CLIENTS]; + + /* time at which the last get_nodes request was sent. */ + uint64_t lastgetnode; + + /* Symetric NAT hole punching stuff */ + + /* 1 if currently hole punching, otherwise 0 */ + uint8_t hole_punching; + uint32_t punching_index; + uint64_t punching_timestamp; + uint64_t recvNATping_timestamp; + uint64_t NATping_id; + uint64_t NATping_timestamp; +} DHT_Friend; + +typedef struct { + uint8_t client_id[CLIENT_ID_SIZE]; + IP_Port ip_port; +} Node_format; + +typedef struct { + IP_Port ip_port; + uint64_t ping_id; + uint64_t timestamp; +} Pinged; + +/*----------------------------------------------------------------------------------*/ +typedef struct { + Net_Crypto *c; + Client_data close_clientlist[LCLIENT_LIST]; + DHT_Friend *friends_list; + uint16_t num_friends; + Pinged send_nodes[LSEND_NODES_ARRAY]; + Node_format toping[MAX_TOPING]; + uint64_t last_toping; + uint64_t close_lastgetnodes; +} DHT; +/*----------------------------------------------------------------------------------*/ +DHT * temp_DHT; //TODO: remove + +Client_data *DHT_get_close_list(DHT * dht); /* Add a new friend to the friends list client_id must be CLIENT_ID_SIZE bytes long. returns 0 if success returns 1 if failure (friends list is full) */ -int DHT_addfriend(uint8_t *client_id); +int DHT_addfriend(DHT * dht, uint8_t *client_id); /* Delete a friend from the friends list client_id must be CLIENT_ID_SIZE bytes long. returns 0 if success returns 1 if failure (client_id not in friends list) */ -int DHT_delfriend(uint8_t *client_id); +int DHT_delfriend(DHT * dht, uint8_t *client_id); /* Get ip of friend client_id must be CLIENT_ID_SIZE bytes long. @@ -66,14 +125,14 @@ int DHT_delfriend(uint8_t *client_id); 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 1 if friend is not in list. */ -IP_Port DHT_getfriendip(uint8_t *client_id); +IP_Port DHT_getfriendip(DHT * dht, uint8_t *client_id); /* Run this function at least a couple times per second (It's the main loop) */ -void doDHT(void); +void do_DHT(DHT * dht); /* Use this function to bootstrap the client 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(DHT * dht, IP_Port ip_port, uint8_t *public_key); /* Add nodes to the toping list all nodes in this list are pinged every TIME_TOPING seconds @@ -83,17 +142,17 @@ void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key); network while preventing amplification attacks. return 0 if node was added return -1 if node was not added */ -int add_toping(uint8_t *client_id, IP_Port ip_port); +int add_toping(DHT * dht, uint8_t *client_id, IP_Port ip_port); /* ROUTING FUNCTIONS */ /* send the given packet to node with client_id returns -1 if failure */ -int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length); +int route_packet(DHT * dht, 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 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(DHT * dht, uint8_t *friend_id, uint8_t *packet, uint32_t length); /* NAT PUNCHING FUNCTIONS */ @@ -101,29 +160,31 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length); ip_portlist must be at least MAX_FRIEND_CLIENTS big returns the number of ips returned returns -1 if no such friend*/ -int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id); +int friend_ips(DHT * dht, IP_Port *ip_portlist, uint8_t *friend_id); /* SAVE/LOAD functions */ /* get the size of the DHT (for saving) */ -uint32_t DHT_size(void); +uint32_t DHT_size(DHT * dht); /* save the DHT in data where data is an array of size DHT_size() */ -void DHT_save(uint8_t *data); +void DHT_save(DHT * dht, uint8_t *data); /* init DHT */ -void DHT_init(void); +DHT * new_DHT(Net_Crypto *c); + +void kill_DHT(DHT * dht); /* load the DHT from data of size size; return -1 if failure return 0 if success */ -int DHT_load(uint8_t *data, uint32_t size); +int DHT_load(DHT * dht, uint8_t *data, uint32_t size); /* returns 0 if we are not connected to the DHT returns 1 if we are */ -int DHT_isconnected(); +int DHT_isconnected(DHT * dht); -void addto_lists(IP_Port ip_port, uint8_t *client_id); +void addto_lists(DHT * dht, IP_Port ip_port, uint8_t *client_id); #ifdef __cplusplus } diff --git a/core/LAN_discovery.c b/core/LAN_discovery.c index 3045e215..07980d26 100644 --- a/core/LAN_discovery.c +++ b/core/LAN_discovery.c @@ -123,28 +123,29 @@ static int LAN_ip(IP ip) static int handle_LANdiscovery(void * object, IP_Port source, uint8_t *packet, uint32_t length) { + DHT *dht = object; if (LAN_ip(source.ip) == -1) return 1; if (length != crypto_box_PUBLICKEYBYTES + 1) return 1; - DHT_bootstrap(source, packet + 1); + DHT_bootstrap(dht, source, packet + 1); return 0; } -int send_LANdiscovery(uint16_t port) +int send_LANdiscovery(uint16_t port, Net_Crypto *c) { uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; data[0] = 33; - memcpy(data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); IP_Port ip_port = {broadcast_ip(), port}; - return sendpacket(temp_net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); + return sendpacket(c->lossless_udp->net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); } -void LANdiscovery_init(void) +void LANdiscovery_init(DHT *dht) { - networking_registerhandler(temp_net, 33, &handle_LANdiscovery, NULL); + networking_registerhandler(dht->c->lossless_udp->net, 33, &handle_LANdiscovery, dht); } diff --git a/core/LAN_discovery.h b/core/LAN_discovery.h index 6b5b8c75..5a790331 100644 --- a/core/LAN_discovery.h +++ b/core/LAN_discovery.h @@ -40,11 +40,11 @@ extern "C" { #endif /*Send a LAN discovery pcaket to the broadcast address with port port*/ -int send_LANdiscovery(uint16_t port); +int send_LANdiscovery(uint16_t port, Net_Crypto *c); /* sets up packet handlers */ -void LANdiscovery_init(void); +void LANdiscovery_init(DHT *dht); diff --git a/core/Messenger.c b/core/Messenger.c index cb3d2551..25a4ff98 100644 --- a/core/Messenger.c +++ b/core/Messenger.c @@ -108,9 +108,8 @@ static uint16_t address_checksum(uint8_t *address, uint32_t len) */ void getaddress(Messenger *m, uint8_t *address) { - //memcpy(address, m->public_key, crypto_box_PUBLICKEYBYTES); //TODO - memcpy(address, self_public_key, crypto_box_PUBLICKEYBYTES); - uint32_t nospam = get_nospam(); + memcpy(address, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); + uint32_t nospam = get_nospam(&(m->fr)); memcpy(address + crypto_box_PUBLICKEYBYTES, &nospam, sizeof(nospam)); uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum)); @@ -150,7 +149,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) if (length < 1) return FAERR_NOMESSAGE; - if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) + if (memcmp(client_id, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) return FAERR_OWNKEY; int friend_id = getfriend_id(m, client_id); @@ -176,7 +175,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { - DHT_addfriend(client_id); + DHT_addfriend(m->dht, client_id); m->friendlist[i].status = FRIEND_ADDED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; @@ -216,7 +215,7 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id) for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { - DHT_addfriend(client_id); + DHT_addfriend(m->dht, client_id); m->friendlist[i].status = FRIEND_CONFIRMED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; @@ -245,7 +244,7 @@ int m_delfriend(Messenger *m, int friendnumber) if (friendnumber >= m->numfriends || friendnumber < 0) return -1; - DHT_delfriend(m->friendlist[friendnumber].client_id); + DHT_delfriend(m->dht, m->friendlist[friendnumber].client_id); crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); free(m->friendlist[friendnumber].statusmessage); memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); @@ -522,7 +521,7 @@ void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno) /* set the function that will be executed when a friend request is received. */ void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata) { - callback_friendrequest(function, userdata); + callback_friendrequest(&(m->fr), function, userdata); } /* set the function that will be executed when a message from a friend is received. */ @@ -617,7 +616,7 @@ int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint /*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/ int LANdiscovery(timer *t, void *arg) { - send_LANdiscovery(htons(PORT)); + send_LANdiscovery(htons(PORT), temp_net_crypto); timer_start(t, LAN_DISCOVERY_INTERVAL); return 0; } @@ -637,19 +636,26 @@ Messenger *initMessenger(void) } m->net_crypto = new_net_crypto(m->net); if (m->net_crypto == NULL) { + kill_networking(m->net); + free(m); + return NULL; + } + m->dht = new_DHT(m->net_crypto); + if (m->dht == NULL) { + kill_net_crypto(m->net_crypto); + kill_networking(m->net); free(m); - free(m->net); return NULL; } new_keys(m->net_crypto); m_set_statusmessage(m, (uint8_t *)"Online", sizeof("Online")); - DHT_init(); - friendreq_init(); - LANdiscovery_init(); - set_nospam(random_int()); + friendreq_init(&(m->fr), m->net_crypto); + LANdiscovery_init(m->dht); + set_nospam(&(m->fr), random_int()); + init_cryptopackets(m->dht); - send_LANdiscovery(htons(PORT)); + send_LANdiscovery(htons(PORT), m->net_crypto); timer_single(&LANdiscovery, 0, LAN_DISCOVERY_INTERVAL); return m; @@ -661,7 +667,9 @@ void cleanupMessenger(Messenger *m) /* FIXME TODO ideally cleanupMessenger will mirror initMessenger * this requires the other modules to expose cleanup functions */ + kill_DHT(m->dht); kill_net_crypto(m->net_crypto); + kill_networking(m->net); free(m->friendlist); free(m); } @@ -677,7 +685,7 @@ void doFriends(Messenger *m) for (i = 0; i < m->numfriends; ++i) { if (m->friendlist[i].status == FRIEND_ADDED) { - int fr = send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, + int fr = send_friendrequest(m->dht, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, m->friendlist[i].info_size); if (fr >= 0) { @@ -699,7 +707,7 @@ void doFriends(Messenger *m) } } - IP_Port friendip = DHT_getfriendip(m->friendlist[i].client_id); + IP_Port friendip = DHT_getfriendip(m->dht, m->friendlist[i].client_id); switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { case 0: @@ -883,7 +891,7 @@ void doMessenger(Messenger *m) { networking_poll(m->net); - doDHT(); + do_DHT(m->dht); do_net_crypto(m->net_crypto); doInbound(m); doFriends(m); @@ -897,7 +905,7 @@ uint32_t Messenger_size(Messenger *m) return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) // nospam + sizeof(uint32_t) // DHT size - + DHT_size() // DHT itself + + DHT_size(m->dht) // DHT itself + sizeof(uint32_t) // Friendlist size + sizeof(Friend) * m->numfriends // Friendlist itself + sizeof(uint16_t) // Own nickname length @@ -910,13 +918,13 @@ void Messenger_save(Messenger *m, uint8_t *data) { save_keys(m->net_crypto, data); data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; - uint32_t nospam = get_nospam(); + uint32_t nospam = get_nospam(&(m->fr)); memcpy(data, &nospam, sizeof(nospam)); data += sizeof(nospam); - uint32_t size = DHT_size(); + uint32_t size = DHT_size(m->dht); memcpy(data, &size, sizeof(size)); data += sizeof(size); - DHT_save(data); + DHT_save(m->dht, data); data += size; size = sizeof(Friend) * m->numfriends; memcpy(data, &size, sizeof(size)); @@ -943,7 +951,7 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length) data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; uint32_t nospam; memcpy(&nospam, data, sizeof(nospam)); - set_nospam(nospam); + set_nospam(&(m->fr), nospam); data += sizeof(nospam); uint32_t size; memcpy(&size, data, sizeof(size)); @@ -954,7 +962,7 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length) length -= size; - if (DHT_load(data, size) == -1) + if (DHT_load(m->dht, data, size) == -1) return -1; data += size; diff --git a/core/Messenger.h b/core/Messenger.h index a2e8f16e..c4e7cc1e 100644 --- a/core/Messenger.h +++ b/core/Messenger.h @@ -115,6 +115,8 @@ typedef struct Messenger { Networking_Core *net; Net_Crypto * net_crypto; + DHT * dht; + Friend_Requests fr; uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; diff --git a/core/friend_requests.c b/core/friend_requests.c index 7be7a4bd..b723de36 100644 --- a/core/friend_requests.c +++ b/core/friend_requests.c @@ -23,15 +23,12 @@ #include "friend_requests.h" -uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; -uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; - /* Try to send a friendrequest to peer with public_key data is the data in the request and length is the length. return -1 if failure. 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.*/ -int send_friendrequest(uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) +int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) { if (length + sizeof(nospam_num) > MAX_DATA_SIZE) return -1; @@ -40,25 +37,25 @@ int send_friendrequest(uint8_t *public_key, uint32_t nospam_num, uint8_t *data, memcpy(temp, &nospam_num, sizeof(nospam_num)); memcpy(temp + sizeof(nospam_num), data, length); uint8_t packet[MAX_DATA_SIZE]; - int len = create_request(self_public_key, self_secret_key, packet, public_key, temp, length + sizeof(nospam_num), + int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, temp, length + sizeof(nospam_num), 32); /* 32 is friend request packet id */ if (len == -1) return -1; - IP_Port ip_port = DHT_getfriendip(public_key); + IP_Port ip_port = DHT_getfriendip(dht, public_key); if (ip_port.ip.i == 1) return -1; if (ip_port.ip.i != 0) { - if (sendpacket(temp_net->sock, ip_port, packet, len) != -1) + if (sendpacket(dht->c->lossless_udp->net->sock, ip_port, packet, len) != -1) return 0; return -1; } - int num = route_tofriend(public_key, packet, len); + int num = route_tofriend(dht, public_key, packet, len); if (num == 0) return -1; @@ -66,58 +63,47 @@ int send_friendrequest(uint8_t *public_key, uint32_t nospam_num, uint8_t *data, return num; } -static uint32_t nospam; + /* * Set and get the nospam variable used to prevent one type of friend request spam */ -void set_nospam(uint32_t num) +void set_nospam(Friend_Requests *fr, uint32_t num) { - nospam = num; + fr->nospam = num; } -uint32_t get_nospam() +uint32_t get_nospam(Friend_Requests *fr) { - return nospam; + return fr->nospam; } -static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t, void *); -static uint8_t handle_friendrequest_isset = 0; -static void *handle_friendrequest_userdata; + /* 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 *), void *userdata) +void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata) { - handle_friendrequest = function; - handle_friendrequest_isset = 1; - handle_friendrequest_userdata = userdata; + fr->handle_friendrequest = function; + fr->handle_friendrequest_isset = 1; + fr->handle_friendrequest_userdata = userdata; } - -/*NOTE: the following is just a temporary fix for the multiple friend requests received at the same time problem - TODO: Make this better (This will most likely tie in with the way we will handle spam.)*/ - -#define MAX_RECEIVED_STORED 32 - -static uint8_t received_requests[MAX_RECEIVED_STORED][crypto_box_PUBLICKEYBYTES]; -static uint16_t received_requests_index; - /*Add to list of received friend requests*/ -static void addto_receivedlist(uint8_t *client_id) +static void addto_receivedlist(Friend_Requests *fr, uint8_t *client_id) { - if (received_requests_index >= MAX_RECEIVED_STORED) - received_requests_index = 0; + if (fr->received_requests_index >= MAX_RECEIVED_STORED) + fr->received_requests_index = 0; - memcpy(received_requests[received_requests_index], client_id, crypto_box_PUBLICKEYBYTES); - ++received_requests_index; + memcpy(fr->received_requests[fr->received_requests_index], client_id, crypto_box_PUBLICKEYBYTES); + ++fr->received_requests_index; } /* Check if a friend request was already received return 0 if not, 1 if we did */ -static int request_received(uint8_t *client_id) +static int request_received(Friend_Requests *fr, uint8_t *client_id) { uint32_t i; for (i = 0; i < MAX_RECEIVED_STORED; ++i) { - if (memcmp(received_requests[i], client_id, crypto_box_PUBLICKEYBYTES) == 0) + if (memcmp(fr->received_requests[i], client_id, crypto_box_PUBLICKEYBYTES) == 0) return 1; } @@ -125,26 +111,27 @@ static int request_received(uint8_t *client_id) } -static int friendreq_handlepacket(IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) +static int friendreq_handlepacket(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) { - if (handle_friendrequest_isset == 0) + Friend_Requests *fr = object; + if (fr->handle_friendrequest_isset == 0) return 1; - if (length <= sizeof(nospam)) + if (length <= sizeof(fr->nospam)) return 1; - if (request_received(source_pubkey)) + if (request_received(fr, source_pubkey)) return 1; - if (memcmp(packet, &nospam, sizeof(nospam)) != 0) + if (memcmp(packet, &fr->nospam, sizeof(fr->nospam)) != 0) return 1; - addto_receivedlist(source_pubkey); - (*handle_friendrequest)(source_pubkey, packet + 4, length - 4, handle_friendrequest_userdata); + addto_receivedlist(fr, source_pubkey); + (*fr->handle_friendrequest)(source_pubkey, packet + 4, length - 4, fr->handle_friendrequest_userdata); return 0; } -void friendreq_init(void) +void friendreq_init(Friend_Requests *fr, Net_Crypto *c) { - cryptopacket_registerhandler(temp_net_crypto, 32, &friendreq_handlepacket); + cryptopacket_registerhandler(c, 32, &friendreq_handlepacket, fr); } diff --git a/core/friend_requests.h b/core/friend_requests.h index 3ce0df8c..cc31155e 100644 --- a/core/friend_requests.h +++ b/core/friend_requests.h @@ -31,21 +31,36 @@ extern "C" { #endif +typedef struct { + uint32_t nospam; + void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t, void *); + uint8_t handle_friendrequest_isset; + void *handle_friendrequest_userdata; + + /*NOTE: the following is just a temporary fix for the multiple friend requests received at the same time problem + TODO: Make this better (This will most likely tie in with the way we will handle spam.)*/ + + #define MAX_RECEIVED_STORED 32 + + uint8_t received_requests[MAX_RECEIVED_STORED][crypto_box_PUBLICKEYBYTES]; + uint16_t received_requests_index; +} Friend_Requests; + /* Try to send a friendrequest to peer with public_key data is the data in the request and length is the length. */ -int send_friendrequest(uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); +int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); /* * Set and get the nospam variable used to prevent one type of friend request spam */ -void set_nospam(uint32_t num); -uint32_t get_nospam(); +void set_nospam(Friend_Requests *fr, uint32_t num); +uint32_t get_nospam(Friend_Requests *fr); /* set the function that will be executed when a friend request for us is received. function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ -void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata); +void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata); /* sets up friendreq packet handlers */ -void friendreq_init(void); +void friendreq_init(Friend_Requests *fr, Net_Crypto *c); #ifdef __cplusplus } diff --git a/core/net_crypto.c b/core/net_crypto.c index dcf36a12..2e63d2f1 100644 --- a/core/net_crypto.c +++ b/core/net_crypto.c @@ -265,34 +265,35 @@ static int handle_request(Net_Crypto *c, uint8_t *public_key, uint8_t *data, uin return -1; } -void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb) +void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object) { - c->cryptopackethandlers[byte] = cb; + c->cryptopackethandlers[byte].function = cb; + c->cryptopackethandlers[byte].object = object; } static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length) { - Net_Crypto *c = object; + DHT *dht = object; if (packet[0] == 32) { if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; - if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. + if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; - int len = handle_request(c, public_key, data, &number, packet, length); + int len = handle_request(dht->c, public_key, data, &number, packet, length); if (len == -1 || len == 0) return 1; - if (!c->cryptopackethandlers[number]) return 1; + if (!dht->c->cryptopackethandlers[number].function) return 1; - c->cryptopackethandlers[number](source, public_key, data, len); + dht->c->cryptopackethandlers[number].function(dht->c->cryptopackethandlers[number].object, source, public_key, data, len); } else { /* if request is not for us, try routing it. */ - if (route_packet(packet + 1, packet, length) == length) //NOTE + if (route_packet(dht, packet + 1, packet, length) == length) //NOTE return 0; } } @@ -572,17 +573,9 @@ int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id) return CONN_NO_CONNECTION; } -/* Generate our public and private keys - Only call this function the first time the program starts. */ - -extern uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];//TODO: Remove this -extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; - void new_keys(Net_Crypto *c) { crypto_box_keypair(c->self_public_key, c->self_secret_key); - memcpy(self_public_key, c->self_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(self_secret_key, c->self_secret_key, crypto_box_PUBLICKEYBYTES); } /* save the public and private keys to the keys array @@ -713,12 +706,16 @@ Net_Crypto * new_net_crypto(Networking_Core * net) if (temp->lossless_udp == NULL) return NULL; memset(temp->incoming_connections, -1 , sizeof(int) * MAX_INCOMING); - //networking_registerhandler(temp, 32, &cryptopacket_handle); - networking_registerhandler(net, 32, &cryptopacket_handle, temp); temp_net_crypto = temp; //TODO remove return temp; } +void init_cryptopackets(void *dht) +{ + DHT *s_dht = dht; + networking_registerhandler(s_dht->c->lossless_udp->net, 32, &cryptopacket_handle, s_dht); +} + static void kill_timedout(Net_Crypto *c) { uint32_t i; diff --git a/core/net_crypto.h b/core/net_crypto.h index 745f1f14..887b432b 100644 --- a/core/net_crypto.h +++ b/core/net_crypto.h @@ -25,7 +25,6 @@ #define NET_CRYPTO_H #include "Lossless_UDP.h" -#include "DHT.h" #ifdef __cplusplus extern "C" { @@ -33,9 +32,6 @@ extern "C" { #define MAX_INCOMING 64 -extern uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];//TODO: Remove this -extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; - typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* nonce of received packets */ @@ -51,25 +47,32 @@ typedef struct { } Crypto_Connection; -typedef int (*cryptopacket_handler_callback)(IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, uint32_t len); +typedef int (*cryptopacket_handler_callback)(void * object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, uint32_t len); typedef struct { -Lossless_UDP * lossless_udp; + cryptopacket_handler_callback function; + void * object; +}Cryptopacket_Handles; -Crypto_Connection *crypto_connections; +typedef struct { + Lossless_UDP * lossless_udp; -uint32_t crypto_connections_length; /* Length of connections array */ + Crypto_Connection *crypto_connections; -/* Our public and secret keys. */ -uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; -uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; + uint32_t crypto_connections_length; /* Length of connections array */ -/* keeps track of the connection numbers for friends request so we can check later if they were sent */ -int incoming_connections[MAX_INCOMING]; + /* Our public and secret keys. */ + uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; -cryptopacket_handler_callback cryptopackethandlers[256]; + /* keeps track of the connection numbers for friends request so we can check later if they were sent */ + int incoming_connections[MAX_INCOMING]; + + Cryptopacket_Handles cryptopackethandlers[256]; } Net_Crypto; +#include "DHT.h" + Net_Crypto * temp_net_crypto; //TODO: remove this #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) @@ -130,7 +133,7 @@ int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t * /* Function to call when request beginning with byte is received */ -void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb); +void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void * object); /* Start a secure connection with other peer who has public_key and ip_port returns -1 if failure @@ -183,6 +186,9 @@ void do_net_crypto(Net_Crypto *c); void kill_net_crypto(Net_Crypto *c); +/* Init the cryptopacket handling */ +void init_cryptopackets(void *dht); + #ifdef __cplusplus } #endif diff --git a/core/network.c b/core/network.c index 684a4227..9ec390fb 100644 --- a/core/network.c +++ b/core/network.c @@ -196,7 +196,6 @@ Networking_Core * new_networking(IP ip, uint16_t port) /* Bind our socket to port PORT and address 0.0.0.0 */ ADDR addr = {AF_INET, htons(port), ip}; bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr)); - temp_net = temp; return temp; } diff --git a/core/network.h b/core/network.h index 5ed25620..47d9fff2 100644 --- a/core/network.h +++ b/core/network.h @@ -112,7 +112,6 @@ typedef struct { int sock; }Networking_Core; -Networking_Core * temp_net; /* returns current time in milleseconds since the epoch. */ uint64_t current_time(void); diff --git a/core/ping.c b/core/ping.c index d2b290a0..10b9b19f 100644 --- a/core/ping.c +++ b/core/ping.c @@ -26,7 +26,6 @@ typedef struct { static pinged_t pings[PING_NUM_MAX]; static size_t num_pings; static size_t pos_pings; -static clientid_t *self_id = (clientid_t *) &self_public_key; extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; // DHT.c @@ -115,19 +114,19 @@ int send_ping_request(IP_Port ipp, clientid_t *client_id) int rc; uint64_t ping_id; - if (is_pinging(ipp, 0) || id_eq(client_id, self_id)) + if (is_pinging(ipp, 0) || id_eq(client_id, (clientid_t *)temp_net_crypto->self_public_key)) return 1; // Generate random ping_id ping_id = add_ping(ipp); pk.magic = PACKET_PING_REQ; - id_cpy(&pk.client_id, self_id); // Our pubkey + id_cpy(&pk.client_id, (clientid_t *)temp_net_crypto->self_public_key); // Our pubkey random_nonce((uint8_t *) &pk.nonce); // Generate random nonce // Encrypt ping_id using recipient privkey rc = encrypt_data((uint8_t *) client_id, - self_secret_key, + temp_net_crypto->self_secret_key, (uint8_t *) &pk.nonce, (uint8_t *) &ping_id, sizeof(ping_id), (uint8_t *) &pk.ping_id); @@ -135,7 +134,7 @@ int send_ping_request(IP_Port ipp, clientid_t *client_id) if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) return 1; - return sendpacket(temp_net->sock, ipp, (uint8_t *) &pk, sizeof(pk)); + return sendpacket(temp_net_crypto->lossless_udp->net->sock, ipp, (uint8_t *) &pk, sizeof(pk)); } int send_ping_response(IP_Port ipp, clientid_t *client_id, uint64_t ping_id) @@ -143,16 +142,16 @@ int send_ping_response(IP_Port ipp, clientid_t *client_id, uint64_t ping_id) pingres_t pk; int rc; - if (id_eq(client_id, self_id)) + if (id_eq(client_id, (clientid_t *)temp_net_crypto->self_public_key)) return 1; pk.magic = PACKET_PING_RES; - id_cpy(&pk.client_id, self_id); // Our pubkey + id_cpy(&pk.client_id, (clientid_t *)temp_net_crypto->self_public_key); // Our pubkey random_nonce((uint8_t *) &pk.nonce); // Generate random nonce // Encrypt ping_id using recipient privkey rc = encrypt_data((uint8_t *) client_id, - self_secret_key, + temp_net_crypto->self_secret_key, (uint8_t *) &pk.nonce, (uint8_t *) &ping_id, sizeof(ping_id), (uint8_t *) &pk.ping_id); @@ -160,21 +159,22 @@ int send_ping_response(IP_Port ipp, clientid_t *client_id, uint64_t ping_id) if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) return 1; - return sendpacket(temp_net->sock, ipp, (uint8_t *) &pk, sizeof(pk)); + return sendpacket(temp_net_crypto->lossless_udp->net->sock, ipp, (uint8_t *) &pk, sizeof(pk)); } int handle_ping_request(void * object, IP_Port source, uint8_t *packet, uint32_t length) { + DHT * dht = object; pingreq_t *p = (pingreq_t *) packet; int rc; uint64_t ping_id; - if (length != sizeof(pingreq_t) || id_eq(&p->client_id, self_id)) + if (length != sizeof(pingreq_t) || id_eq(&p->client_id, (clientid_t *)dht->c->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data((uint8_t *) &p->client_id, - self_secret_key, + dht->c->self_secret_key, (uint8_t *) &p->nonce, (uint8_t *) &p->ping_id, sizeof(ping_id) + ENCRYPTION_PADDING, @@ -185,23 +185,24 @@ int handle_ping_request(void * object, IP_Port source, uint8_t *packet, uint32_t // Send response send_ping_response(source, &p->client_id, ping_id); - add_toping((uint8_t *) &p->client_id, source); + add_toping(dht, (uint8_t *) &p->client_id, source); return 0; } int handle_ping_response(void * object, IP_Port source, uint8_t *packet, uint32_t length) { + DHT * dht = object; pingres_t *p = (pingres_t *) packet; int rc; uint64_t ping_id; - if (length != sizeof(pingres_t) || id_eq(&p->client_id, self_id)) + if (length != sizeof(pingres_t) || id_eq(&p->client_id, (clientid_t *)dht->c->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data((uint8_t *) &p->client_id, - self_secret_key, + dht->c->self_secret_key, (uint8_t *) &p->nonce, (uint8_t *) &p->ping_id, sizeof(ping_id) + ENCRYPTION_PADDING, @@ -215,6 +216,6 @@ int handle_ping_response(void * object, IP_Port source, uint8_t *packet, uint32_ return 1; // Associate source ip with client_id - addto_lists(source, (uint8_t *) &p->client_id); + addto_lists(dht, source, (uint8_t *) &p->client_id); return 0; } diff --git a/testing/toxic/dhtstatus.c b/testing/toxic/dhtstatus.c index a11dc616..c7a57c7d 100644 --- a/testing/toxic/dhtstatus.c +++ b/testing/toxic/dhtstatus.c @@ -36,7 +36,7 @@ static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) static void dhtstatus_onDraw(ToxWindow *self) { - Client_data *close_clientlist = DHT_get_close_list(); + Client_data *close_clientlist = DHT_get_close_list(temp_DHT); curs_set(0); werase(self->window); diff --git a/testing/toxic/main.c b/testing/toxic/main.c index 9abe8de4..6f6c9db4 100644 --- a/testing/toxic/main.c +++ b/testing/toxic/main.c @@ -90,11 +90,11 @@ static Messenger *init_tox() #define MAXSERVERS 50 /* Connects to a random DHT server listed in the DHTservers file */ -int init_connection(void) +int init_connection(Messenger *m) { FILE *fp = NULL; - if (DHT_isconnected()) + if (DHT_isconnected(m->dht)) return 0; fp = fopen(SRVLIST_FILE, "r"); @@ -135,7 +135,7 @@ int init_connection(void) dht.ip.i = resolved_address; unsigned char *binary_string = hex_string_to_bin(key); - DHT_bootstrap(dht, binary_string); + DHT_bootstrap(m->dht, dht, binary_string); free(binary_string); return 0; } @@ -146,18 +146,18 @@ static void do_tox(Messenger *m, ToxWindow *prompt) static int conn_err = 0; static bool dht_on = false; - if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) { + if (!dht_on && !DHT_isconnected(m->dht) && !(conn_try++ % 100)) { if (!conn_err) { - conn_err = init_connection(); + conn_err = init_connection(m); wprintw(prompt->window, "\nEstablishing connection...\n"); if (conn_err) wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err); } - } else if (!dht_on && DHT_isconnected()) { + } else if (!dht_on && DHT_isconnected(m->dht)) { dht_on = true; wprintw(prompt->window, "\nDHT connected.\n"); - } else if (dht_on && !DHT_isconnected()) { + } else if (dht_on && !DHT_isconnected(m->dht)) { dht_on = false; wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n"); } diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c index 81f00bce..204cd7e6 100644 --- a/testing/toxic/prompt.c +++ b/testing/toxic/prompt.c @@ -204,7 +204,7 @@ void cmd_connect(ToxWindow *self, Messenger *m, char **args) dht.ip.i = resolved_address; unsigned char *binary_string = hex_string_to_bin(key); - DHT_bootstrap(dht, binary_string); + DHT_bootstrap(m->dht, dht, binary_string); free(binary_string); }