diff --git a/auto_tests/friends_test.c b/auto_tests/friends_test.c index dd2db3e3..b6223489 100644 --- a/auto_tests/friends_test.c +++ b/auto_tests/friends_test.c @@ -44,6 +44,8 @@ #define c_sleep(x) usleep(1000*x) #endif +#define PORT 33445 + static Messenger *m; uint8_t *parent_id = NULL; @@ -52,13 +54,13 @@ uint8_t *child_id = NULL; pid_t child_pid = 0; int request_flags = 0; -void do_tox(void) +void do_tox(DHT *dht) { static int dht_on = 0; - if (!dht_on && DHT_isconnected()) { + if (!dht_on && DHT_isconnected(dht)) { dht_on = 1; - } else if (dht_on && !DHT_isconnected()) { + } else if (dht_on && !DHT_isconnected(dht)) { dht_on = 0; } @@ -77,7 +79,7 @@ void parent_confirm_status(Messenger *m, int num, uint8_t *data, uint16_t length request_flags |= FIRST_FLAG; } -int parent_friend_request(void) +int parent_friend_request(DHT *dht) { char *message = "Watson, come here, I need you."; int len = strlen(message); @@ -90,7 +92,7 @@ int parent_friend_request(void) /* wait on the status change */ for (i = 0; i < WAIT_COUNT; i++) { - do_tox(); + do_tox(dht); if (request_flags & FIRST_FLAG) break; @@ -123,7 +125,7 @@ void child_got_statuschange(Messenger *m, int friend_num, uint8_t *string, uint1 request_flags |= SECOND_FLAG; } -int parent_wait_for_message(void) +int parent_wait_for_message(DHT *dht) { int i = 0; @@ -131,7 +133,7 @@ int parent_wait_for_message(void) fflush(stdout); for (i = 0; i < WAIT_COUNT; i++) { - do_tox(); + do_tox(dht); if (request_flags & SECOND_FLAG) break; @@ -185,16 +187,16 @@ int main(int argc, char *argv[]) /* wait on the friend request */ while (!(request_flags & FIRST_FLAG)) - do_tox(); + do_tox(m->dht); /* wait for the status change */ while (!(request_flags & SECOND_FLAG)) - do_tox(); + do_tox(m->dht); for (i = 0; i < 6; i++) { /* send the message six times, just to be sure */ m_sendmessage(m, 0, (uint8_t *)message, strlen(message)); - do_tox(); + do_tox(m->dht); } cleanupMessenger(m); @@ -220,10 +222,10 @@ int main(int argc, char *argv[]) Messenger_save(m, parent_id); - if (parent_friend_request() == -1) + if (parent_friend_request(m->dht) == -1) return -1; - if (parent_wait_for_message() == -1) + if (parent_wait_for_message(m->dht) == -1) return -1; wait(NULL); diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index ad6eea01..55a41912 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -10,8 +10,7 @@ set(core_sources LAN_discovery.c Messenger.c util.c - ping.c - timer.c) + ping.c) if(SHARED_TOXCORE) add_library(toxcore SHARED ${core_sources}) diff --git a/core/DHT.c b/core/DHT.c index 924e3216..ab631604 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(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(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(IP_Port source, uint8_t *packet, uint32_t length) +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(IP_Port source, uint8_t *packet, uint32_t length) 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(IP_Port source, uint8_t *packet, uint32_t length) 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(IP_Port source, uint8_t *packet, uint32_t length) +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(IP_Port source, uint8_t *packet, uint32_t length) 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(IP_Port source, uint8_t *packet, uint32_t length) 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); + send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, (clientid_t *) &nodes_list[i].client_id); + 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(IP_Port source, uint8_t *packet, uint32_t length) /*----------------------------------------------------------------------------------*/ /*------------------------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->ping, dht->c, 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,46 @@ 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->ping, dht->c, 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); - send_ping_request(ip_port, (clientid_t *) public_key); + getnodes(dht, ip_port, public_key, dht->c->self_public_key); + send_ping_request(dht->ping, dht->c, 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(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 +796,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 +831,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 +841,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 +855,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(client->ip_port, packet, length) == length) + if (sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length) == length) ++sent; } } @@ -923,14 +866,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 +894,7 @@ static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t lengt if (n < 1) return 0; - if (sendpacket(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 +906,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 +922,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 +932,16 @@ 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(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,45 @@ 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->ping, dht->c, 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 +1074,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 +1094,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 +1102,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 +1124,89 @@ 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->ping, dht->c, 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(0, &handle_ping_request); - networking_registerhandler(1, &handle_ping_response); - networking_registerhandler(2, &handle_getnodes); - networking_registerhandler(3, &handle_sendnodes); - cryptopacket_registerhandler(254, &handle_NATping); + if (c == NULL) + return NULL; + + DHT *temp = calloc(1, sizeof(DHT)); + + if (temp == NULL) + return NULL; + + temp->ping = new_ping(); + + if (temp->ping == NULL) { + kill_DHT(temp); + 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); + 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) +{ + kill_ping(dht->ping); + 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 +1215,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,8 +1236,8 @@ 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, - tempclose_clientlist[i].client_id ); + DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, + tempclose_clientlist[i].client_id ); } return 0; @@ -1280,13 +1246,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..6295581b 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; + void *ping; +} DHT; +/*----------------------------------------------------------------------------------*/ + +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 ad1337ef..cbbb384b 100644 --- a/core/LAN_discovery.c +++ b/core/LAN_discovery.c @@ -121,30 +121,32 @@ static int LAN_ip(IP ip) return -1; } -static int handle_LANdiscovery(IP_Port source, uint8_t *packet, uint32_t length) +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(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(33, &handle_LANdiscovery); + 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/Lossless_UDP.c b/core/Lossless_UDP.c index 506a06eb..15e8dea3 100644 --- a/core/Lossless_UDP.c +++ b/core/Lossless_UDP.c @@ -28,97 +28,6 @@ #include "Lossless_UDP.h" -/* maximum data packets in sent and receive queues. */ -#define MAX_QUEUE_NUM 16 - -/* maximum number of data packets in the buffer */ -#define BUFFER_PACKET_NUM (16-1) - -/* timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */ -#define CONNEXION_TIMEOUT 5 - -/* initial amount of sync/hanshake packets to send per second. */ -#define SYNC_RATE 2 - -/* initial send rate of data. */ -#define DATA_SYNC_RATE 30 - -typedef struct { - uint8_t data[MAX_DATA_SIZE]; - uint16_t size; -} Data; - -typedef struct { - IP_Port ip_port; - - /* - * 0 if connection is dead, 1 if attempting handshake, - * 2 if handshake is done (we start sending SYNC packets) - * 3 if we are sending SYNC packets and can send data - * 4 if the connection has timed out. - */ - uint8_t status; - - /* - * 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. - */ - uint8_t inbound; - - uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */ - uint16_t data_rate; /* current data packet send rate packets per second. */ - - uint64_t last_SYNC; /* time our last SYNC packet was sent. */ - uint64_t last_sent; /* time our last data or handshake packet was sent. */ - uint64_t last_recvSYNC; /* time we last received a SYNC packet from the other */ - uint64_t last_recvdata; /* time we last received a DATA packet from the other */ - uint64_t killat; /* time to kill the connection */ - - Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */ - Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */ - - uint32_t handshake_id1; - uint32_t handshake_id2; - - /* number of data packets received (also used as handshake_id1) */ - uint32_t recv_packetnum; - - /* number of packets received by the other peer */ - uint32_t orecv_packetnum; - - /* number of data packets sent */ - uint32_t sent_packetnum; - - /* number of packets sent by the other peer. */ - uint32_t osent_packetnum; - - /* number of latest packet written onto the sendbuffer */ - uint32_t sendbuff_packetnum; - - /* we know all packets before that number were successfully sent */ - uint32_t successful_sent; - - /* packet number of last packet read with the read_packet function */ - uint32_t successful_read; - - /* list of currently requested packet numbers(by the other person) */ - uint32_t req_packets[BUFFER_PACKET_NUM]; - - /* total number of currently requested packets(by the other person) */ - uint16_t num_req_paquets; - - uint8_t recv_counter; - uint8_t send_counter; - uint8_t timeout; /* connection timeout in seconds. */ -} Connection; - - -static Connection *connections; - -static uint32_t connections_length; /* Length of connections array */ -static uint32_t connections_number; /* Number of connections in connections array */ - -#define MAX_CONNECTIONS connections_length /* Functions */ @@ -127,22 +36,20 @@ static uint32_t connections_number; /* Number of connections in connections arra * Return -1 if there are no connections like we are looking for * Return id if it found it */ -int getconnection_id(IP_Port ip_port) +int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) { uint32_t i; - for (i = 0; i < MAX_CONNECTIONS; ++i) { - if (connections[i].ip_port.ip.i == ip_port.ip.i && - connections[i].ip_port.port == ip_port.port && - connections[i].status > 0) + for (i = 0; i < ludp->connections_length; ++i) { + if (ludp->connections[i].ip_port.ip.i == ip_port.ip.i && + ludp->connections[i].ip_port.port == ip_port.port && + ludp->connections[i].status > 0) return i; } return -1; } -/* table of random numbers used below. */ -static uint32_t randtable[6][256]; /* * Generate a handshake_id which depends on the ip_port. @@ -150,15 +57,15 @@ static uint32_t randtable[6][256]; * * TODO: make this better */ -static uint32_t handshake_id(IP_Port source) +static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) { uint32_t id = 0, i; for (i = 0; i < 6; ++i) { - if (randtable[i][((uint8_t *)&source)[i]] == 0) - randtable[i][((uint8_t *)&source)[i]] = random_int(); + if (ludp->randtable[i][((uint8_t *)&source)[i]] == 0) + ludp->randtable[i][((uint8_t *)&source)[i]] = random_int(); - id ^= randtable[i][((uint8_t *)&source)[i]]; + id ^= ludp->randtable[i][((uint8_t *)&source)[i]]; } if (id == 0) /* id can't be zero */ @@ -172,10 +79,10 @@ static uint32_t handshake_id(IP_Port source) * * TODO: make this better */ -static void change_handshake(IP_Port source) +static void change_handshake(Lossless_UDP *ludp, IP_Port source) { uint8_t rand = random_int() % 4; - randtable[rand][((uint8_t *)&source)[rand]] = random_int(); + ludp->randtable[rand][((uint8_t *)&source)[rand]] = random_int(); } /* @@ -184,33 +91,33 @@ static void change_handshake(IP_Port source) * Return -1 if it could not initialize the connectiont * If there already was an existing connection to that ip_port return its number. */ -int new_connection(IP_Port ip_port) +int new_connection(Lossless_UDP *ludp, IP_Port ip_port) { - int connect = getconnection_id(ip_port); + int connect = getconnection_id(ludp, ip_port); if (connect != -1) return connect; - if (connections_number == connections_length) { + if (ludp->connections_number == ludp->connections_length) { Connection *temp; - temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); + temp = realloc(ludp->connections, sizeof(Connection) * (ludp->connections_length + 1)); if (temp == NULL) return -1; - memset(&temp[connections_length], 0, sizeof(Connection)); - ++connections_length; - connections = temp; + memset(&temp[ludp->connections_length], 0, sizeof(Connection)); + ++ludp->connections_length; + ludp->connections = temp; } uint32_t i; - for (i = 0; i < MAX_CONNECTIONS; ++i) { - if (connections[i].status == 0) { - memset(&connections[i], 0, sizeof(Connection)); - uint32_t handshake_id1 = handshake_id(ip_port); + for (i = 0; i < ludp->connections_length; ++i) { + if (ludp->connections[i].status == 0) { + memset(&ludp->connections[i], 0, sizeof(Connection)); + uint32_t handshake_id1 = handshake_id(ludp, ip_port); - connections[i] = (Connection) { + ludp->connections[i] = (Connection) { .ip_port = ip_port, .status = 1, .inbound = 0, @@ -227,7 +134,7 @@ int new_connection(IP_Port ip_port) /* add randomness to timeout to prevent connections getting stuck in a loop. */ .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT }; - ++connections_number; + ++ludp->connections_number; return i; } @@ -241,31 +148,31 @@ int new_connection(IP_Port ip_port) * Returns an integer corresponding to the connection id. * Return -1 if it could not initialize the connection. */ -static int new_inconnection(IP_Port ip_port) +static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port) { - if (getconnection_id(ip_port) != -1) + if (getconnection_id(ludp, ip_port) != -1) return -1; - if (connections_number == connections_length) { + if (ludp->connections_number == ludp->connections_length) { Connection *temp; - temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); + temp = realloc(ludp->connections, sizeof(Connection) * (ludp->connections_length + 1)); if (temp == NULL) return -1; - memset(&temp[connections_length], 0, sizeof(Connection)); - ++connections_length; - connections = temp; + memset(&temp[ludp->connections_length], 0, sizeof(Connection)); + ++ludp->connections_length; + ludp->connections = temp; } uint32_t i; - for (i = 0; i < MAX_CONNECTIONS; ++i) { - if (connections[i].status == 0) { - memset(&connections[i], 0, sizeof(Connection)); + for (i = 0; i < ludp->connections_length; ++i) { + if (ludp->connections[i].status == 0) { + memset(&ludp->connections[i], 0, sizeof(Connection)); uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; - connections[i] = (Connection) { + ludp->connections[i] = (Connection) { .ip_port = ip_port, .status = 2, .inbound = 2, @@ -281,7 +188,7 @@ static int new_inconnection(IP_Port ip_port) /* if this connection isn't handled within the timeout kill it. */ .killat = current_time() + 1000000UL * timeout }; - ++connections_number; + ++ludp->connections_number; return i; } } @@ -293,13 +200,13 @@ static int new_inconnection(IP_Port ip_port) * Returns an integer corresponding to the next connection in our incoming connection list. * Return -1 if there are no new incoming connections in the list. */ -int incoming_connection(void) +int incoming_connection(Lossless_UDP *ludp) { uint32_t i; - for (i = 0; i < MAX_CONNECTIONS; ++i) { - if (connections[i].inbound == 2) { - connections[i].inbound = 1; + for (i = 0; i < ludp->connections_length; ++i) { + if (ludp->connections[i].inbound == 2) { + ludp->connections[i].inbound = 1; return i; } } @@ -308,46 +215,46 @@ int incoming_connection(void) } /* Try to free some memory from the connections array. */ -static void free_connections(void) +static void free_connections(Lossless_UDP *ludp) { uint32_t i; - for (i = connections_length; i != 0; --i) - if (connections[i - 1].status != 0) + for (i = ludp->connections_length; i != 0; --i) + if (ludp->connections[i - 1].status != 0) break; - if (connections_length == i) + if (ludp->connections_length == i) return; if (i == 0) { - free(connections); - connections = NULL; - connections_length = i; + free(ludp->connections); + ludp->connections = NULL; + ludp->connections_length = i; return; } Connection *temp; - temp = realloc(connections, sizeof(Connection) * i); + temp = realloc(ludp->connections, sizeof(Connection) * i); if (temp == NULL && i != 0) return; - connections = temp; - connections_length = i; + ludp->connections = temp; + ludp->connections_length = i; } /* * Return -1 if it could not kill the connection. * Return 0 if killed successfully */ -int kill_connection(int connection_id) +int kill_connection(Lossless_UDP *ludp, int connection_id) { - if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { - if (connections[connection_id].status > 0) { - connections[connection_id].status = 0; - change_handshake(connections[connection_id].ip_port); - --connections_number; - free_connections(); + if (connection_id >= 0 && connection_id < ludp->connections_length) { + if (ludp->connections[connection_id].status > 0) { + ludp->connections[connection_id].status = 0; + change_handshake(ludp, ludp->connections[connection_id].ip_port); + --ludp->connections_number; + free_connections(ludp); return 0; } } @@ -360,11 +267,11 @@ int kill_connection(int connection_id) * Return -1 if it can not kill the connection. * Return 0 if it will kill it. */ -int kill_connection_in(int connection_id, uint32_t seconds) +int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds) { - if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { - if (connections[connection_id].status > 0) { - connections[connection_id].killat = current_time() + 1000000UL * seconds; + if (connection_id >= 0 && connection_id < ludp->connections_length) { + if (ludp->connections[connection_id].status > 0) { + ludp->connections[connection_id].killat = current_time() + 1000000UL * seconds; return 0; } } @@ -380,65 +287,66 @@ int kill_connection_in(int connection_id, uint32_t seconds) * Return 3 if fully connected. * Return 4 if timed out and waiting to be killed. */ -int is_connected(int connection_id) +int is_connected(Lossless_UDP *ludp, int connection_id) { - if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) - return connections[connection_id].status; + if (connection_id >= 0 && connection_id < ludp->connections_length) + return ludp->connections[connection_id].status; return 0; } /* returns the ip_port of the corresponding connection. */ -IP_Port connection_ip(int connection_id) +IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) { - if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) - return connections[connection_id].ip_port; + if (connection_id >= 0 && connection_id < ludp->connections_length) + return ludp->connections[connection_id].ip_port; IP_Port zero = {{{0}}, 0}; return zero; } /* returns the number of packets in the queue waiting to be successfully sent. */ -uint32_t sendqueue(int connection_id) +uint32_t sendqueue(Lossless_UDP *ludp, int connection_id) { - if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) + if (connection_id < 0 || connection_id >= ludp->connections_length) return 0; - return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent; + return ludp->connections[connection_id].sendbuff_packetnum - ludp->connections[connection_id].successful_sent; } /* 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(Lossless_UDP *ludp, int connection_id) { - if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) + if (connection_id < 0 || connection_id >= ludp->connections_length) return 0; - return connections[connection_id].recv_packetnum - connections[connection_id].successful_read; + return ludp->connections[connection_id].recv_packetnum - ludp->connections[connection_id].successful_read; } /* returns the id of the next packet in the queue return -1 if no packet in queue */ -char id_packet(int connection_id) +char id_packet(Lossless_UDP *ludp, int connection_id) { - if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) + if (connection_id < 0 || connection_id >= ludp->connections_length) return -1; - if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0) - return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; + if (recvqueue(ludp, connection_id) != 0 && ludp->connections[connection_id].status != 0) + return ludp->connections[connection_id].recvbuffer[ludp->connections[connection_id].successful_read % + MAX_QUEUE_NUM].data[0]; return -1; } /* return 0 if there is no received data in the buffer. return length of received packet if successful */ -int read_packet(int connection_id, uint8_t *data) +int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data) { - if (recvqueue(connection_id) != 0) { - uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; - uint16_t size = connections[connection_id].recvbuffer[index].size; - memcpy(data, connections[connection_id].recvbuffer[index].data, size); - ++connections[connection_id].successful_read; - connections[connection_id].recvbuffer[index].size = 0; + if (recvqueue(ludp, connection_id) != 0) { + uint16_t index = ludp->connections[connection_id].successful_read % MAX_QUEUE_NUM; + uint16_t size = ludp->connections[connection_id].recvbuffer[index].size; + memcpy(data, ludp->connections[connection_id].recvbuffer[index].data, size); + ++ludp->connections[connection_id].successful_read; + ludp->connections[connection_id].recvbuffer[index].size = 0; return size; } @@ -449,16 +357,16 @@ int read_packet(int connection_id, uint8_t *data) * Return 0 if data could not be put in packet queue * Return 1 if data was put into the queue */ -int write_packet(int connection_id, uint8_t *data, uint32_t length) +int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length) { if (length > MAX_DATA_SIZE || length == 0) return 0; - if (sendqueue(connection_id) < BUFFER_PACKET_NUM) { - uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; - memcpy(connections[connection_id].sendbuffer[index].data, data, length); - connections[connection_id].sendbuffer[index].size = length; - connections[connection_id].sendbuff_packetnum++; + if (sendqueue(ludp, connection_id) < BUFFER_PACKET_NUM) { + uint32_t index = ludp->connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; + memcpy(ludp->connections[connection_id].sendbuffer[index].data, data, length); + ludp->connections[connection_id].sendbuffer[index].size = length; + ludp->connections[connection_id].sendbuff_packetnum++; return 1; } @@ -466,18 +374,18 @@ int write_packet(int connection_id, uint8_t *data, uint32_t length) } /* put the packet numbers the we are missing in requested and return the number */ -uint32_t missing_packets(int connection_id, uint32_t *requested) +uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested) { uint32_t number = 0; uint32_t i; uint32_t temp; /* don't request packets if the buffer is full. */ - if (recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1)) + if (recvqueue(ludp, connection_id) >= (BUFFER_PACKET_NUM - 1)) return 0; - for (i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++) { - if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) { + for (i = ludp->connections[connection_id].recv_packetnum; i != ludp->connections[connection_id].osent_packetnum; i++) { + if (ludp->connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) { temp = htonl(i); memcpy(requested + number, &temp, 4); ++number; @@ -485,7 +393,7 @@ uint32_t missing_packets(int connection_id, uint32_t *requested) } if (number == 0) - connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; + ludp->connections[connection_id].recv_packetnum = ludp->connections[connection_id].osent_packetnum; return number; } @@ -496,7 +404,7 @@ uint32_t missing_packets(int connection_id, uint32_t *requested) * see http://wiki.tox.im/index.php/Lossless_UDP for more information. */ -static int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) +static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) { uint8_t packet[1 + 4 + 4]; uint32_t temp; @@ -507,21 +415,21 @@ static int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t hand temp = htonl(handshake_id2); memcpy(packet + 5, &temp, 4); - return sendpacket(ip_port, packet, sizeof(packet)); + return sendpacket(ludp->net->sock, ip_port, packet, sizeof(packet)); } -static int send_SYNC(uint32_t connection_id) +static int send_SYNC(Lossless_UDP *ludp, uint32_t connection_id) { uint8_t packet[(BUFFER_PACKET_NUM * 4 + 4 + 4 + 2)]; uint16_t index = 0; - IP_Port ip_port = connections[connection_id].ip_port; - uint8_t counter = connections[connection_id].send_counter; - uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum); - uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum); + IP_Port ip_port = ludp->connections[connection_id].ip_port; + uint8_t counter = ludp->connections[connection_id].send_counter; + uint32_t recv_packetnum = htonl(ludp->connections[connection_id].recv_packetnum); + uint32_t sent_packetnum = htonl(ludp->connections[connection_id].sent_packetnum); uint32_t requested[BUFFER_PACKET_NUM]; - uint32_t number = missing_packets(connection_id, requested); + uint32_t number = missing_packets(ludp, connection_id, requested); packet[0] = 17; index += 1; @@ -533,11 +441,11 @@ static int send_SYNC(uint32_t connection_id) index += 4; memcpy(packet + index, requested, 4 * number); - return sendpacket(ip_port, packet, (number * 4 + 4 + 4 + 2)); + return sendpacket(ludp->net->sock, ip_port, packet, (number * 4 + 4 + 4 + 2)); } -static int send_data_packet(uint32_t connection_id, uint32_t packet_num) +static int send_data_packet(Lossless_UDP *ludp, uint32_t connection_id, uint32_t packet_num) { uint32_t index = packet_num % MAX_QUEUE_NUM; uint32_t temp; @@ -545,29 +453,29 @@ static int send_data_packet(uint32_t connection_id, uint32_t packet_num) packet[0] = 18; temp = htonl(packet_num); memcpy(packet + 1, &temp, 4); - memcpy(packet + 5, connections[connection_id].sendbuffer[index].data, - connections[connection_id].sendbuffer[index].size); - return sendpacket(connections[connection_id].ip_port, packet, - 1 + 4 + connections[connection_id].sendbuffer[index].size); + memcpy(packet + 5, ludp->connections[connection_id].sendbuffer[index].data, + ludp->connections[connection_id].sendbuffer[index].size); + return sendpacket(ludp->net->sock, ludp->connections[connection_id].ip_port, packet, + 1 + 4 + ludp->connections[connection_id].sendbuffer[index].size); } /* sends 1 data packet */ -static int send_DATA(uint32_t connection_id) +static int send_DATA(Lossless_UDP *ludp, uint32_t connection_id) { int ret; uint32_t buffer[BUFFER_PACKET_NUM]; - if (connections[connection_id].num_req_paquets > 0) { - ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]); - connections[connection_id].num_req_paquets--; - memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4); - memcpy(connections[connection_id].req_packets, buffer, connections[connection_id].num_req_paquets * 4); + if (ludp->connections[connection_id].num_req_paquets > 0) { + ret = send_data_packet(ludp, connection_id, ludp->connections[connection_id].req_packets[0]); + ludp->connections[connection_id].num_req_paquets--; + memcpy(buffer, ludp->connections[connection_id].req_packets + 1, ludp->connections[connection_id].num_req_paquets * 4); + memcpy(ludp->connections[connection_id].req_packets, buffer, ludp->connections[connection_id].num_req_paquets * 4); return ret; } - if (connections[connection_id].sendbuff_packetnum != connections[connection_id].sent_packetnum) { - ret = send_data_packet(connection_id, connections[connection_id].sent_packetnum); - connections[connection_id].sent_packetnum++; + if (ludp->connections[connection_id].sendbuff_packetnum != ludp->connections[connection_id].sent_packetnum) { + ret = send_data_packet(ludp, connection_id, ludp->connections[connection_id].sent_packetnum); + ludp->connections[connection_id].sent_packetnum++; return ret; } @@ -584,37 +492,39 @@ static int send_DATA(uint32_t connection_id) /* Return 0 if handled correctly, 1 if packet is bad. */ -static int handle_handshake(IP_Port source, uint8_t *packet, uint32_t length) +static int handle_handshake(void *object, IP_Port source, uint8_t *packet, uint32_t length) { + Lossless_UDP *ludp = object; + if (length != (1 + 4 + 4)) return 1; uint32_t temp; uint32_t handshake_id1, handshake_id2; - int connection = getconnection_id(source); + int connection = getconnection_id(ludp, source); memcpy(&temp, packet + 1, 4); handshake_id1 = ntohl(temp); memcpy(&temp, packet + 5, 4); handshake_id2 = ntohl(temp); - if (handshake_id2 == 0 && is_connected(connection) < 3) { - send_handshake(source, handshake_id(source), handshake_id1); + if (handshake_id2 == 0 && is_connected(ludp, connection) < 3) { + send_handshake(ludp, source, handshake_id(ludp, source), handshake_id1); return 0; } - if (is_connected(connection) != 1) + if (is_connected(ludp, connection) != 1) return 1; /* if handshake_id2 is what we sent previously as handshake_id1 */ - if (handshake_id2 == connections[connection].handshake_id1) { - connections[connection].status = 2; + if (handshake_id2 == ludp->connections[connection].handshake_id1) { + ludp->connections[connection].status = 2; /* NOTE: is this necessary? - connections[connection].handshake_id2 = handshake_id1; */ - connections[connection].orecv_packetnum = handshake_id2; - connections[connection].osent_packetnum = handshake_id1; - connections[connection].recv_packetnum = handshake_id1; - connections[connection].successful_read = handshake_id1; + ludp->connections[connection].handshake_id2 = handshake_id1; */ + ludp->connections[connection].orecv_packetnum = handshake_id2; + ludp->connections[connection].osent_packetnum = handshake_id1; + ludp->connections[connection].recv_packetnum = handshake_id1; + ludp->connections[connection].successful_read = handshake_id1; } return 0; @@ -634,19 +544,19 @@ static int SYNC_valid(uint32_t length) } /* case 1 in handle_SYNC: */ -static int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) +static int handle_SYNC1(Lossless_UDP *ludp, IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) { - if (handshake_id(source) == recv_packetnum) { - int x = new_inconnection(source); + if (handshake_id(ludp, source) == recv_packetnum) { + int x = new_inconnection(ludp, source); if (x != -1) { - connections[x].orecv_packetnum = recv_packetnum; - connections[x].sent_packetnum = recv_packetnum; - connections[x].sendbuff_packetnum = recv_packetnum; - connections[x].successful_sent = recv_packetnum; - connections[x].osent_packetnum = sent_packetnum; - connections[x].recv_packetnum = sent_packetnum; - connections[x].successful_read = sent_packetnum; + ludp->connections[x].orecv_packetnum = recv_packetnum; + ludp->connections[x].sent_packetnum = recv_packetnum; + ludp->connections[x].sendbuff_packetnum = recv_packetnum; + ludp->connections[x].successful_sent = recv_packetnum; + ludp->connections[x].osent_packetnum = sent_packetnum; + ludp->connections[x].recv_packetnum = sent_packetnum; + ludp->connections[x].successful_read = sent_packetnum; return x; } @@ -656,63 +566,66 @@ static int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_p } /* case 2 in handle_SYNC: */ -static int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) +static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, + uint32_t sent_packetnum) { - if (recv_packetnum == connections[connection_id].orecv_packetnum) { - /* && sent_packetnum == connections[connection_id].osent_packetnum) */ - connections[connection_id].status = 3; - connections[connection_id].recv_counter = counter; - ++connections[connection_id].send_counter; - send_SYNC(connection_id); + if (recv_packetnum == ludp->connections[connection_id].orecv_packetnum) { + /* && sent_packetnum == ludp->connections[connection_id].osent_packetnum) */ + ludp->connections[connection_id].status = 3; + ludp->connections[connection_id].recv_counter = counter; + ++ludp->connections[connection_id].send_counter; + send_SYNC(ludp, connection_id); return 0; } return 1; } /* case 3 in handle_SYNC: */ -static int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, +static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, + uint32_t sent_packetnum, uint32_t *req_packets, uint16_t number) { - uint8_t comp_counter = (counter - connections[connection_id].recv_counter ); + uint8_t comp_counter = (counter - ludp->connections[connection_id].recv_counter ); uint32_t i, temp; - /* uint32_t comp_1 = (recv_packetnum - connections[connection_id].successful_sent); - uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */ - uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum); - uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum); + /* uint32_t comp_1 = (recv_packetnum - ludp->connections[connection_id].successful_sent); + uint32_t comp_2 = (sent_packetnum - ludp->connections[connection_id].successful_read); */ + uint32_t comp_1 = (recv_packetnum - ludp->connections[connection_id].orecv_packetnum); + uint32_t comp_2 = (sent_packetnum - ludp->connections[connection_id].osent_packetnum); /* packet valid */ if (comp_1 <= BUFFER_PACKET_NUM && comp_2 <= BUFFER_PACKET_NUM && comp_counter < 10 && comp_counter != 0) { - connections[connection_id].orecv_packetnum = recv_packetnum; - connections[connection_id].osent_packetnum = sent_packetnum; - connections[connection_id].successful_sent = recv_packetnum; - connections[connection_id].last_recvSYNC = current_time(); - connections[connection_id].recv_counter = counter; + ludp->connections[connection_id].orecv_packetnum = recv_packetnum; + ludp->connections[connection_id].osent_packetnum = sent_packetnum; + ludp->connections[connection_id].successful_sent = recv_packetnum; + ludp->connections[connection_id].last_recvSYNC = current_time(); + ludp->connections[connection_id].recv_counter = counter; - ++connections[connection_id].send_counter; + ++ludp->connections[connection_id].send_counter; for (i = 0; i < number; ++i) { temp = ntohl(req_packets[i]); - memcpy(connections[connection_id].req_packets + i, &temp, 4 * number); + memcpy(ludp->connections[connection_id].req_packets + i, &temp, 4 * number); } - connections[connection_id].num_req_paquets = number; + ludp->connections[connection_id].num_req_paquets = number; return 0; } return 1; } -static int handle_SYNC(IP_Port source, uint8_t *packet, uint32_t length) +static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t length) { + Lossless_UDP *ludp = object; if (!SYNC_valid(length)) return 1; - int connection = getconnection_id(source); + int connection = getconnection_id(ludp, source); uint8_t counter; uint32_t temp; uint32_t recv_packetnum, sent_packetnum; @@ -729,14 +642,14 @@ static int handle_SYNC(IP_Port source, uint8_t *packet, uint32_t length) memcpy(req_packets, packet + 10, 4 * number); if (connection == -1) - return handle_SYNC1(source, recv_packetnum, sent_packetnum); + return handle_SYNC1(ludp, source, recv_packetnum, sent_packetnum); - if (connections[connection].status == 2) - return handle_SYNC2(connection, counter, + if (ludp->connections[connection].status == 2) + return handle_SYNC2(ludp, connection, counter, recv_packetnum, sent_packetnum); - if (connections[connection].status == 3) - return handle_SYNC3(connection, counter, recv_packetnum, + if (ludp->connections[connection].status == 3) + return handle_SYNC3(ludp, connection, counter, recv_packetnum, sent_packetnum, req_packets, number); return 0; @@ -746,33 +659,33 @@ static int handle_SYNC(IP_Port source, uint8_t *packet, uint32_t length) * Add a packet to the received buffer and set the recv_packetnum of the * connection to its proper value. Return 1 if data was too big, 0 if not. */ -static int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) +static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) { if (size > MAX_DATA_SIZE) return 1; uint32_t i; - uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; - uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; + uint32_t maxnum = ludp->connections[connection_id].successful_read + BUFFER_PACKET_NUM; + uint32_t sent_packet = data_num - ludp->connections[connection_id].osent_packetnum; - for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { + for (i = ludp->connections[connection_id].recv_packetnum; i != maxnum; ++i) { if (i == data_num) { - memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); + memcpy(ludp->connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); - connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; - connections[connection_id].last_recvdata = current_time(); + ludp->connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; + ludp->connections[connection_id].last_recvdata = current_time(); if (sent_packet < BUFFER_PACKET_NUM) { - connections[connection_id].osent_packetnum = data_num; + ludp->connections[connection_id].osent_packetnum = data_num; } break; } } - for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { - if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) - connections[connection_id].recv_packetnum = i; + for (i = ludp->connections[connection_id].recv_packetnum; i != maxnum; ++i) { + if (ludp->connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) + ludp->connections[connection_id].recv_packetnum = i; else break; } @@ -780,15 +693,16 @@ static int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_ return 0; } -static int handle_data(IP_Port source, uint8_t *packet, uint32_t length) +static int handle_data(void *object, IP_Port source, uint8_t *packet, uint32_t length) { - int connection = getconnection_id(source); + Lossless_UDP *ludp = object; + int connection = getconnection_id(ludp, source); if (connection == -1) return 1; /* Drop the data packet if connection is not connected. */ - if (connections[connection].status != 3) + if (ludp->connections[connection].status != 3) return 1; if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) @@ -801,76 +715,86 @@ static int handle_data(IP_Port source, uint8_t *packet, uint32_t length) memcpy(&temp, packet + 1, 4); number = ntohl(temp); - return add_recv(connection, number, packet + 5, size); + return add_recv(ludp, connection, number, packet + 5, size); } /* * END of packet handling functions */ -void LosslessUDP_init(void) +Lossless_UDP *new_lossless_udp(Networking_Core *net) { - networking_registerhandler(16, &handle_handshake); - networking_registerhandler(17, &handle_SYNC); - networking_registerhandler(18, &handle_data); + if (net == NULL) + return NULL; + + Lossless_UDP *temp = calloc(1, sizeof(Lossless_UDP)); + + if (temp == NULL) + return NULL; + + temp->net = net; + networking_registerhandler(net, 16, &handle_handshake, temp); + networking_registerhandler(net, 17, &handle_SYNC, temp); + networking_registerhandler(net, 18, &handle_data, temp); + return temp; } /* * Send handshake requests * handshake packets are sent at the same rate as SYNC packets */ -static void doNew(void) +static void do_new(Lossless_UDP *ludp) { uint32_t i; uint64_t temp_time = current_time(); - for (i = 0; i < MAX_CONNECTIONS; ++i) { - if (connections[i].status == 1) - if ((connections[i].last_sent + (1000000UL / connections[i].SYNC_rate)) <= temp_time) { - send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0); - connections[i].last_sent = temp_time; + for (i = 0; i < ludp->connections_length; ++i) { + if (ludp->connections[i].status == 1) + if ((ludp->connections[i].last_sent + (1000000UL / ludp->connections[i].SYNC_rate)) <= temp_time) { + send_handshake(ludp, ludp->connections[i].ip_port, ludp->connections[i].handshake_id1, 0); + ludp->connections[i].last_sent = temp_time; } /* kill all timed out connections */ - if (connections[i].status > 0 && - (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && - connections[i].status != 4) { - connections[i].status = 4; + if (ludp->connections[i].status > 0 && + (ludp->connections[i].last_recvSYNC + ludp->connections[i].timeout * 1000000UL) < temp_time && + ludp->connections[i].status != 4) { + ludp->connections[i].status = 4; /* kill_connection(i); */ } - if (connections[i].status > 0 && connections[i].killat < temp_time) - kill_connection(i); + if (ludp->connections[i].status > 0 && ludp->connections[i].killat < temp_time) + kill_connection(ludp, i); } } -static void doSYNC(void) +static void do_SYNC(Lossless_UDP *ludp) { uint32_t i; uint64_t temp_time = current_time(); - for (i = 0; i < MAX_CONNECTIONS; ++i) { - if (connections[i].status == 2 || connections[i].status == 3) - if ((connections[i].last_SYNC + (1000000UL / connections[i].SYNC_rate)) <= temp_time) { - send_SYNC(i); - connections[i].last_SYNC = temp_time; + for (i = 0; i < ludp->connections_length; ++i) { + if (ludp->connections[i].status == 2 || ludp->connections[i].status == 3) + if ((ludp->connections[i].last_SYNC + (1000000UL / ludp->connections[i].SYNC_rate)) <= temp_time) { + send_SYNC(ludp, i); + ludp->connections[i].last_SYNC = temp_time; } } } -static void doData(void) +static void do_data(Lossless_UDP *ludp) { uint32_t i; uint64_t j; uint64_t temp_time = current_time(); - for (i = 0; i < MAX_CONNECTIONS; ++i) - if (connections[i].status == 3 && sendqueue(i) != 0) - if ((connections[i].last_sent + (1000000UL / connections[i].data_rate)) <= temp_time) { - for (j = connections[i].last_sent; j < temp_time; j += (1000000UL / connections[i].data_rate)) - send_DATA(i); + for (i = 0; i < ludp->connections_length; ++i) + if (ludp->connections[i].status == 3 && sendqueue(ludp, i) != 0) + if ((ludp->connections[i].last_sent + (1000000UL / ludp->connections[i].data_rate)) <= temp_time) { + for (j = ludp->connections[i].last_sent; j < temp_time; j += (1000000UL / ludp->connections[i].data_rate)) + send_DATA(ludp, i); - connections[i].last_sent = temp_time; + ludp->connections[i].last_sent = temp_time; } } @@ -881,32 +805,38 @@ static void doData(void) * * TODO: flow control. */ -static void adjustRates(void) +static void adjust_rates(Lossless_UDP *ludp) { uint32_t i; uint64_t temp_time = current_time(); - for (i = 0; i < MAX_CONNECTIONS; ++i) { - if (connections[i].status == 1 || connections[i].status == 2) - connections[i].SYNC_rate = MAX_SYNC_RATE; + for (i = 0; i < ludp->connections_length; ++i) { + if (ludp->connections[i].status == 1 || ludp->connections[i].status == 2) + ludp->connections[i].SYNC_rate = MAX_SYNC_RATE; - if (connections[i].status == 3) { - if (sendqueue(i) != 0) { - connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE; - connections[i].SYNC_rate = MAX_SYNC_RATE; - } else if (connections[i].last_recvdata + 1000000UL > temp_time) - connections[i].SYNC_rate = MAX_SYNC_RATE; + if (ludp->connections[i].status == 3) { + if (sendqueue(ludp, i) != 0) { + ludp->connections[i].data_rate = (BUFFER_PACKET_NUM - ludp->connections[i].num_req_paquets) * MAX_SYNC_RATE; + ludp->connections[i].SYNC_rate = MAX_SYNC_RATE; + } else if (ludp->connections[i].last_recvdata + 1000000UL > temp_time) + ludp->connections[i].SYNC_rate = MAX_SYNC_RATE; else - connections[i].SYNC_rate = SYNC_RATE; + ludp->connections[i].SYNC_rate = SYNC_RATE; } } } /* Call this function a couple times per second It's the main loop. */ -void doLossless_UDP(void) +void do_lossless_udp(Lossless_UDP *ludp) { - doNew(); - doSYNC(); - doData(); - adjustRates(); + do_new(ludp); + do_SYNC(ludp); + do_data(ludp); + adjust_rates(ludp); } + +void kill_lossless_udp(Lossless_UDP *ludp) +{ + free(ludp->connections); + free(ludp); +} \ No newline at end of file diff --git a/core/Lossless_UDP.h b/core/Lossless_UDP.h index bd426ee0..176e86ce 100644 --- a/core/Lossless_UDP.h +++ b/core/Lossless_UDP.h @@ -33,72 +33,168 @@ extern "C" { /* maximum length of the data in the data packets */ #define MAX_DATA_SIZE 1024 +/* maximum data packets in sent and receive queues. */ +#define MAX_QUEUE_NUM 16 + +/* maximum number of data packets in the buffer */ +#define BUFFER_PACKET_NUM (16-1) + +/* timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */ +#define CONNEXION_TIMEOUT 5 + +/* initial amount of sync/hanshake packets to send per second. */ +#define SYNC_RATE 2 + +/* initial send rate of data. */ +#define DATA_SYNC_RATE 30 + +typedef struct { + uint8_t data[MAX_DATA_SIZE]; + uint16_t size; +} Data; + +typedef struct { + IP_Port ip_port; + + /* + * 0 if connection is dead, 1 if attempting handshake, + * 2 if handshake is done (we start sending SYNC packets) + * 3 if we are sending SYNC packets and can send data + * 4 if the connection has timed out. + */ + uint8_t status; + + /* + * 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. + */ + uint8_t inbound; + + uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */ + uint16_t data_rate; /* current data packet send rate packets per second. */ + + uint64_t last_SYNC; /* time our last SYNC packet was sent. */ + uint64_t last_sent; /* time our last data or handshake packet was sent. */ + uint64_t last_recvSYNC; /* time we last received a SYNC packet from the other */ + uint64_t last_recvdata; /* time we last received a DATA packet from the other */ + uint64_t killat; /* time to kill the connection */ + + Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */ + Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */ + + uint32_t handshake_id1; + uint32_t handshake_id2; + + /* number of data packets received (also used as handshake_id1) */ + uint32_t recv_packetnum; + + /* number of packets received by the other peer */ + uint32_t orecv_packetnum; + + /* number of data packets sent */ + uint32_t sent_packetnum; + + /* number of packets sent by the other peer. */ + uint32_t osent_packetnum; + + /* number of latest packet written onto the sendbuffer */ + uint32_t sendbuff_packetnum; + + /* we know all packets before that number were successfully sent */ + uint32_t successful_sent; + + /* packet number of last packet read with the read_packet function */ + uint32_t successful_read; + + /* list of currently requested packet numbers(by the other person) */ + uint32_t req_packets[BUFFER_PACKET_NUM]; + + /* total number of currently requested packets(by the other person) */ + uint16_t num_req_paquets; + + uint8_t recv_counter; + uint8_t send_counter; + uint8_t timeout; /* connection timeout in seconds. */ +} Connection; + +typedef struct { + Networking_Core *net; + Connection *connections; + + uint32_t connections_length; /* Length of connections array */ + uint32_t connections_number; /* Number of connections in connections array */ + + /* table of random numbers used in handshake_id. */ + uint32_t randtable[6][256]; + +} Lossless_UDP; + /* * Initialize a new connection to ip_port * Returns an integer corresponding to the connection id. * Return -1 if it could not initialize the connection. * Return number if there already was an existing connection to that ip_port. */ -int new_connection(IP_Port ip_port); +int new_connection(Lossless_UDP *ludp, IP_Port ip_port); /* * Get connection id from IP_Port. * Return -1 if there are no connections like we are looking for. * Return id if it found it . */ -int getconnection_id(IP_Port ip_port); +int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port); /* * Returns an int corresponding to the next connection in our imcoming connection list * Return -1 if there are no new incoming connections in the list. */ -int incoming_connection(void); +int incoming_connection(Lossless_UDP *ludp); /* * Return -1 if it could not kill the connection. * Return 0 if killed successfully */ -int kill_connection(int connection_id); +int kill_connection(Lossless_UDP *ludp, int connection_id); /* * Kill connection in seconds seconds. * Return -1 if it can not kill the connection. * Return 0 if it will kill it */ -int kill_connection_in(int connection_id, uint32_t seconds); +int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds); /* * Returns the ip_port of the corresponding connection. * Return 0 if there is no such connection. */ -IP_Port connection_ip(int connection_id); +IP_Port connection_ip(Lossless_UDP *ludp, int connection_id); /* * Returns the id of the next packet in the queue * Return -1 if no packet in queue */ -char id_packet(int connection_id); +char id_packet(Lossless_UDP *ludp, int connection_id); /* * Return 0 if there is no received data in the buffer. * Return length of received packet if successful */ -int read_packet(int connection_id, uint8_t *data); +int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data); /* * Return 0 if data could not be put in packet queue * Return 1 if data was put into the queue */ -int write_packet(int connection_id, uint8_t *data, uint32_t length); +int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length); /* Returns the number of packets in the queue waiting to be successfully sent. */ -uint32_t sendqueue(int connection_id); +uint32_t sendqueue(Lossless_UDP *ludp, int connection_id); /* * returns the number of packets in the queue waiting to be successfully * read with read_packet(...) */ -uint32_t recvqueue(int connection_id); +uint32_t recvqueue(Lossless_UDP *ludp, int connection_id); /* Check if connection is connected: * Return 0 no. @@ -107,15 +203,17 @@ uint32_t recvqueue(int connection_id); * Return 3 if fully connected. * Return 4 if timed out and wating to be killed. */ -int is_connected(int connection_id); +int is_connected(Lossless_UDP *ludp, int connection_id); /* Call this function a couple times per second It's the main loop. */ -void doLossless_UDP(void); +void do_lossless_udp(Lossless_UDP *ludp); /* * This function sets up LosslessUDP packet handling. */ -void LosslessUDP_init(void); +Lossless_UDP *new_lossless_udp(Networking_Core *net); + +void kill_lossless_udp(Lossless_UDP *ludp); #ifdef __cplusplus } diff --git a/core/Messenger.c b/core/Messenger.c index 7fd6a569..dd24ab09 100644 --- a/core/Messenger.c +++ b/core/Messenger.c @@ -22,7 +22,6 @@ */ #include "Messenger.h" -#include "timer.h" #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -108,9 +107,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 +148,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 +174,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 +214,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,8 +243,8 @@ int m_delfriend(Messenger *m, int friendnumber) if (friendnumber >= m->numfriends || friendnumber < 0) return -1; - DHT_delfriend(m->friendlist[friendnumber].client_id); - crypto_kill(m->friendlist[friendnumber].crypt_connection_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)); uint32_t i; @@ -522,7 +520,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. */ @@ -606,20 +604,20 @@ int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint if (length != 0) memcpy(packet + 1, data, length); - return write_cryptpacket(m->friendlist[friendnumber].crypt_connection_id, packet, length + 1); + return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1); } - /*Interval in seconds between LAN discovery packet sending*/ #define LAN_DISCOVERY_INTERVAL 60 #define PORT 33445 /*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/ -int LANdiscovery(timer *t, void *arg) +static void LANdiscovery(Messenger *m) { - send_LANdiscovery(htons(PORT)); - timer_start(t, LAN_DISCOVERY_INTERVAL); - return 0; + if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) { + send_LANdiscovery(htons(PORT), m->net_crypto); + m->last_LANdiscovery = unix_time(); + } } /* run this at startup */ @@ -628,25 +626,41 @@ Messenger *initMessenger(void) Messenger *m = calloc(1, sizeof(Messenger)); if ( ! m ) - return 0; + return NULL; - new_keys(); - m_set_statusmessage(m, (uint8_t *)"Online", sizeof("Online")); - initNetCrypto(); IP ip; ip.i = 0; + m->net = new_networking(ip, PORT); - if (init_networking(ip, PORT) == -1) - return 0; + if (m->net == NULL) { + free(m); + return NULL; + } - DHT_init(); - LosslessUDP_init(); - friendreq_init(); - LANdiscovery_init(); - set_nospam(random_int()); + m->net_crypto = new_net_crypto(m->net); - send_LANdiscovery(htons(PORT)); - timer_single(&LANdiscovery, 0, LAN_DISCOVERY_INTERVAL); + 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); + return NULL; + } + + new_keys(m->net_crypto); + m_set_statusmessage(m, (uint8_t *)"Online", sizeof("Online")); + + friendreq_init(&(m->fr), m->net_crypto); + LANdiscovery_init(m->dht); + set_nospam(&(m->fr), random_int()); + init_cryptopackets(m->dht); return m; } @@ -657,6 +671,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); } @@ -672,7 +689,8 @@ 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) { @@ -694,12 +712,12 @@ 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->friendlist[i].crypt_connection_id)) { + switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { case 0: if (friendip.ip.i > 1) - m->friendlist[i].crypt_connection_id = crypto_connect(m->friendlist[i].client_id, friendip); + m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); break; @@ -712,7 +730,7 @@ void doFriends(Messenger *m) break; case 4: - crypto_kill(m->friendlist[i].crypt_connection_id); + crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); m->friendlist[i].crypt_connection_id = -1; break; @@ -741,7 +759,7 @@ void doFriends(Messenger *m) send_ping(m, i); } - len = read_cryptpacket(m->friendlist[i].crypt_connection_id, temp); + len = read_cryptpacket(m->net_crypto, m->friendlist[i].crypt_connection_id, temp); uint8_t packet_id = temp[0]; uint8_t *data = temp + 1; int data_length = len - 1; @@ -833,8 +851,9 @@ void doFriends(Messenger *m) } } } else { - if (is_cryptoconnected(m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ - crypto_kill(m->friendlist[i].crypt_connection_id); + if (is_cryptoconnected(m->net_crypto, + m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ + crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); m->friendlist[i].crypt_connection_id = -1; set_friend_status(m, i, FRIEND_CONFIRMED); } @@ -844,7 +863,7 @@ void doFriends(Messenger *m) if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { /* if we stopped recieving ping packets kill it */ - crypto_kill(m->friendlist[i].crypt_connection_id); + crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); m->friendlist[i].crypt_connection_id = -1; set_friend_status(m, i, FRIEND_CONFIRMED); } @@ -857,34 +876,31 @@ void doInbound(Messenger *m) uint8_t secret_nonce[crypto_box_NONCEBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t session_key[crypto_box_PUBLICKEYBYTES]; - int inconnection = crypto_inbound(public_key, secret_nonce, session_key); + int inconnection = crypto_inbound(m->net_crypto, public_key, secret_nonce, session_key); if (inconnection != -1) { int friend_id = getfriend_id(m, public_key); if (friend_id != -1) { - crypto_kill(m->friendlist[friend_id].crypt_connection_id); + crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id); m->friendlist[friend_id].crypt_connection_id = - accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key); + accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key); set_friend_status(m, friend_id, FRIEND_CONFIRMED); } } } - -/* the main loop that needs to be run at least 200 times per second. */ +/* the main loop that needs to be run at least 20 times per second. */ void doMessenger(Messenger *m) { - networking_poll(); + networking_poll(m->net); - doDHT(); - doLossless_UDP(); - doNetCrypto(); + do_DHT(m->dht); + do_net_crypto(m->net_crypto); doInbound(m); doFriends(m); - - timer_poll(); + LANdiscovery(m); } /* returns the size of the messenger data (for saving) */ @@ -893,7 +909,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 @@ -904,15 +920,15 @@ uint32_t Messenger_size(Messenger *m) /* save the messenger in data of size Messenger_size() */ void Messenger_save(Messenger *m, uint8_t *data) { - save_keys(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)); @@ -935,11 +951,11 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length) return -1; length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3; - load_keys(data); + load_keys(m->net_crypto, data); 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)); @@ -950,7 +966,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 9016be93..581c4ba9 100644 --- a/core/Messenger.h +++ b/core/Messenger.h @@ -112,8 +112,11 @@ typedef struct { } Friend; typedef struct Messenger { - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; + Networking_Core *net; + Net_Crypto *net_crypto; + DHT *dht; + Friend_Requests fr; uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; @@ -125,6 +128,8 @@ typedef struct Messenger { Friend *friendlist; uint32_t numfriends; + uint64_t last_LANdiscovery; + void (*friend_message)(struct Messenger *m, int, uint8_t *, uint16_t, void *); void *friend_message_userdata; void (*friend_action)(struct Messenger *m, int, uint8_t *, uint16_t, void *); @@ -219,17 +224,13 @@ int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t lengt return -1 if failure */ int setname(Messenger *m, uint8_t *name, uint16_t length); -/** - * @brief Get your nickname. - * - * @param[in] m The messanger context to use. - * - * @param[inout] name Pointer to a string for the name. - * - * @param[in] nlen The length of the string buffer. - * - * @return Return the length of the name, 0 on error. - */ +/* + Get your nickname. + m The messanger context to use. + name Pointer to a string for the name. + nlen The length of the string buffer. + returns Return the length of the name, 0 on error. +*/ uint16_t getself_name(Messenger *m, uint8_t *name, uint16_t nlen); /* get name of friendnumber diff --git a/core/friend_requests.c b/core/friend_requests.c index 3708f154..ee2da633 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]; - - /* 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,26 @@ 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(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(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 +64,48 @@ 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 +113,29 @@ 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(32, &friendreq_handlepacket); + cryptopacket_registerhandler(c, 32, &friendreq_handlepacket, fr); } diff --git a/core/friend_requests.h b/core/friend_requests.h index 3ce0df8c..2ebd557b 100644 --- a/core/friend_requests.h +++ b/core/friend_requests.h @@ -31,21 +31,37 @@ 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 8fcb62e1..e3757ffb 100644 --- a/core/net_crypto.c +++ b/core/net_crypto.c @@ -26,42 +26,12 @@ #include "net_crypto.h" -/* Our public and secret keys. */ -uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; -uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; - -typedef struct { - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */ - uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* nonce of received packets */ - uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* nonce of sent packets. */ - 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 peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ - uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* the precomputed shared key from encrypt_precompute */ - 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. - 4 if the connection is timed out. */ - uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ - -} Crypto_Connection; - -static Crypto_Connection *crypto_connections; - -static uint32_t crypto_connections_length; /* Length of connections array */ - -#define MAX_CRYPTO_CONNECTIONS crypto_connections_length - #define CONN_NO_CONNECTION 0 #define CONN_HANDSHAKE_SENT 1 #define CONN_NOT_CONFIRMED 2 #define CONN_ESTABLISHED 3 #define CONN_TIMED_OUT 4 -#define MAX_INCOMING 64 - -/* keeps track of the connection numbers for friends request so we can check later if they were sent */ -static int incoming_connections[MAX_INCOMING]; - /* Use this instead of memcmp; not vulnerable to timing attacks. */ uint8_t crypto_iszero(uint8_t *mem, uint32_t length) { @@ -175,16 +145,16 @@ void random_nonce(uint8_t *nonce) /* return 0 if there is no received data in the buffer return -1 if the packet was discarded. return length of received data if successful */ -int read_cryptpacket(int crypt_connection_id, uint8_t *data) +int read_cryptpacket(Net_Crypto *c, 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 >= c->crypto_connections_length) return 0; - if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) + if (c->crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) return 0; uint8_t temp_data[MAX_DATA_SIZE]; - int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data); + int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data); if (length == 0) return 0; @@ -192,12 +162,12 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data) if (temp_data[0] != 3) return -1; - int len = decrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, - crypto_connections[crypt_connection_id].recv_nonce, + int len = decrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, + c->crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data); if (len != -1) { - increment_nonce(crypto_connections[crypt_connection_id].recv_nonce); + increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce); return len; } @@ -206,20 +176,20 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data) /* return 0 if data could not be put in packet queue return 1 if data was put into the queue */ -int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length) +int write_cryptpacket(Net_Crypto *c, 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 >= c->crypto_connections_length) return 0; if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) return 0; - if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) + if (c->crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) return 0; uint8_t temp_data[MAX_DATA_SIZE]; - int len = encrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, - crypto_connections[crypt_connection_id].sent_nonce, + int len = encrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, + c->crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); if (len == -1) @@ -227,20 +197,23 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length) temp_data[0] = 3; - if (write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) + if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) return 0; - increment_nonce(crypto_connections[crypt_connection_id].sent_nonce); + increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce); return 1; } -/* create a request to peer with public_key. +/* create a request to peer. + send_public_key and send_secret_key are the pub/secret keys of the sender + recv_public_key is public key of reciever 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. request_id is the id of the request (32 = friend request, 254 = ping request) returns -1 on failure 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 *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, + uint8_t *data, uint32_t length, uint8_t request_id) { if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING) return -1; @@ -250,15 +223,15 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t memcpy(temp + 1, data, length); temp[0] = request_id; random_nonce(nonce); - int len = encrypt_data(public_key, self_secret_key, nonce, temp, length + 1, + int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1, 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); if (len == -1) return -1; packet[0] = 32; - memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); - memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; @@ -268,17 +241,18 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t in data if a friend or ping request was sent to us and returns the length of the data. packet is the request packet and length is its length return -1 if not valid request. */ -static int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet, uint16_t length) +static int handle_request(Net_Crypto *c, uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet, + uint16_t length) { if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && length <= MAX_DATA_SIZE + ENCRYPTION_PADDING && - memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { + memcmp(packet + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t temp[MAX_DATA_SIZE]; memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); - int len1 = decrypt_data(public_key, self_secret_key, nonce, + int len1 = decrypt_data(public_key, c->self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); @@ -293,35 +267,37 @@ static int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *request_i return -1; } -static cryptopacket_handler_callback cryptopackethandlers[256] = {0}; - -void cryptopacket_registerhandler(uint8_t byte, cryptopacket_handler_callback cb) +void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object) { - cryptopackethandlers[byte] = cb; + c->cryptopackethandlers[byte].function = cb; + c->cryptopackethandlers[byte].object = object; } -static int cryptopacket_handle(IP_Port source, uint8_t *packet, uint32_t length) +static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length) { + 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(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 (!cryptopackethandlers[number]) return 1; + if (!dht->c->cryptopackethandlers[number].function) return 1; - 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) + if (route_packet(dht, packet + 1, packet, length) == length) //NOTE return 0; } } @@ -332,7 +308,8 @@ static int cryptopacket_handle(IP_Port source, uint8_t *packet, uint32_t length) /* Send a crypto handshake packet containing an encrypted secret nonce and session public key to peer with connection_id and public_key the packet is encrypted with a random nonce which is sent in plain text with the packet */ -static int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) +static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, + uint8_t *session_key) { uint8_t temp_data[MAX_DATA_SIZE]; uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; @@ -342,22 +319,23 @@ static int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); 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, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); if (len == -1) return 0; temp_data[0] = 2; - memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); - return write_packet(connection_id, temp_data, len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); + return write_packet(c->lossless_udp, connection_id, temp_data, + len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); } /* Extract secret nonce, session public key and public_key from a packet(data) with length length return 1 if successful return 0 if failure */ -static int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce, +static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key, uint8_t *data, uint16_t length) { int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); @@ -374,7 +352,7 @@ static int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce, 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, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); @@ -389,13 +367,13 @@ static int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce, /* get crypto connection id from public key of peer return -1 if there are no connections like we are looking for return id if it found it */ -static int getcryptconnection_id(uint8_t *public_key) +static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) { uint32_t i; - for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { - if (crypto_connections[i].status != CONN_NO_CONNECTION) - if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) + for (i = 0; i < c->crypto_connections_length; ++i) { + if (c->crypto_connections[i].status != CONN_NO_CONNECTION) + if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) return i; } @@ -404,63 +382,63 @@ static int getcryptconnection_id(uint8_t *public_key) /* set the size of the friend list to numfriends return -1 if realloc fails */ -int realloc_cryptoconnection(uint32_t num) +int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) { if (num == 0) { - free(crypto_connections); - crypto_connections = NULL; + free(c->crypto_connections); + c->crypto_connections = NULL; return 0; } - Crypto_Connection *newcrypto_connections = realloc(crypto_connections, num * sizeof(Crypto_Connection)); + Crypto_Connection *newcrypto_connections = realloc(c->crypto_connections, num * sizeof(Crypto_Connection)); if (newcrypto_connections == NULL) return -1; - crypto_connections = newcrypto_connections; + c->crypto_connections = newcrypto_connections; return 0; } /* Start a secure connection with other peer who has public_key and ip_port returns -1 if failure returns crypt_connection_id of the initialized connection if everything went well. */ -int crypto_connect(uint8_t *public_key, IP_Port ip_port) +int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) { uint32_t i; - int id = getcryptconnection_id(public_key); + int id = getcryptconnection_id(c, public_key); if (id != -1) { - IP_Port c_ip = connection_ip(crypto_connections[id].number); + IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number); if (c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port) return -1; } - if (realloc_cryptoconnection(crypto_connections_length + 1) == -1) + if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1) return -1; - memset(&crypto_connections[crypto_connections_length], 0, sizeof(Crypto_Connection)); - crypto_connections[crypto_connections_length].number = ~0; + memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); + c->crypto_connections[c->crypto_connections_length].number = ~0; - for (i = 0; i <= MAX_CRYPTO_CONNECTIONS; ++i) { - if (crypto_connections[i].status == CONN_NO_CONNECTION) { - int id = new_connection(ip_port); + for (i = 0; i <= c->crypto_connections_length; ++i) { + if (c->crypto_connections[i].status == CONN_NO_CONNECTION) { + int id = new_connection(c->lossless_udp, ip_port); if (id == -1) return -1; - crypto_connections[i].number = id; - crypto_connections[i].status = CONN_HANDSHAKE_SENT; - random_nonce(crypto_connections[i].recv_nonce); - memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); - crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key); + c->crypto_connections[i].number = id; + c->crypto_connections[i].status = CONN_HANDSHAKE_SENT; + random_nonce(c->crypto_connections[i].recv_nonce); + memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); + crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); - if (crypto_connections_length == i) - ++crypto_connections_length; + if (c->crypto_connections_length == i) + ++c->crypto_connections_length; - if (send_cryptohandshake(id, public_key, crypto_connections[i].recv_nonce, - crypto_connections[i].sessionpublic_key) == 1) { - increment_nonce(crypto_connections[i].recv_nonce); + if (send_cryptohandshake(c, id, public_key, c->crypto_connections[i].recv_nonce, + c->crypto_connections[i].sessionpublic_key) == 1) { + increment_nonce(c->crypto_connections[i].recv_nonce); return i; } @@ -478,25 +456,26 @@ int crypto_connect(uint8_t *public_key, IP_Port ip_port) and the session public key for the connection in session_key to accept it see: accept_crypto_inbound(...) 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(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) { uint32_t i; for (i = 0; i < MAX_INCOMING; ++i) { - if (incoming_connections[i] != -1) { - if (is_connected(incoming_connections[i]) == 4 || is_connected(incoming_connections[i]) == 0) { - kill_connection(incoming_connections[i]); - incoming_connections[i] = -1; + if (c->incoming_connections[i] != -1) { + if (is_connected(c->lossless_udp, c->incoming_connections[i]) == 4 + || is_connected(c->lossless_udp, c->incoming_connections[i]) == 0) { + kill_connection(c->lossless_udp, c->incoming_connections[i]); + c->incoming_connections[i] = -1; continue; } - if (id_packet(incoming_connections[i]) == 2) { + if (id_packet(c->lossless_udp, c->incoming_connections[i]) == 2) { uint8_t temp_data[MAX_DATA_SIZE]; - uint16_t len = read_packet(incoming_connections[i], temp_data); + uint16_t len = read_packet(c->lossless_udp, c->incoming_connections[i], temp_data); - if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) { - int connection_id = incoming_connections[i]; - incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */ + if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { + int connection_id = c->incoming_connections[i]; + c->incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */ return connection_id; } } @@ -509,25 +488,25 @@ int crypto_inbound(uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_ /* kill a crypto connection return 0 if killed successfully return 1 if there was a problem. */ -int crypto_kill(int crypt_connection_id) +int crypto_kill(Net_Crypto *c, int crypt_connection_id) { - if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) + if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length) return 1; - if (crypto_connections[crypt_connection_id].status != CONN_NO_CONNECTION) { - crypto_connections[crypt_connection_id].status = CONN_NO_CONNECTION; - kill_connection(crypto_connections[crypt_connection_id].number); - memset(&crypto_connections[crypt_connection_id], 0 , sizeof(Crypto_Connection)); - crypto_connections[crypt_connection_id].number = ~0; + if (c->crypto_connections[crypt_connection_id].status != CONN_NO_CONNECTION) { + c->crypto_connections[crypt_connection_id].status = CONN_NO_CONNECTION; + kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); + memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); + c->crypto_connections[crypt_connection_id].number = ~0; uint32_t i; - for (i = crypto_connections_length; i != 0; --i) { - if (crypto_connections[i - 1].status != CONN_NO_CONNECTION) + for (i = c->crypto_connections_length; i != 0; --i) { + if (c->crypto_connections[i - 1].status != CONN_NO_CONNECTION) break; } - crypto_connections_length = i; - realloc_cryptoconnection(crypto_connections_length); + c->crypto_connections_length = i; + realloc_cryptoconnection(c, c->crypto_connections_length); return 0; } @@ -537,7 +516,8 @@ int crypto_kill(int crypt_connection_id) /* accept an incoming connection using the parameters provided by crypto_inbound return -1 if not 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(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, + uint8_t *session_key) { uint32_t i; @@ -549,37 +529,38 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre { return -1; }*/ - if (realloc_cryptoconnection(crypto_connections_length + 1) == -1) + if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1) return -1; - memset(&crypto_connections[crypto_connections_length], 0, sizeof(Crypto_Connection)); - crypto_connections[crypto_connections_length].number = ~0; + memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); + c->crypto_connections[c->crypto_connections_length].number = ~0; - for (i = 0; i <= MAX_CRYPTO_CONNECTIONS; ++i) { - if (crypto_connections[i].status == CONN_NO_CONNECTION) { - crypto_connections[i].number = connection_id; - crypto_connections[i].status = CONN_NOT_CONFIRMED; - random_nonce(crypto_connections[i].recv_nonce); - memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); - increment_nonce(crypto_connections[i].sent_nonce); - memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); + for (i = 0; i <= c->crypto_connections_length; ++i) { + if (c->crypto_connections[i].status == CONN_NO_CONNECTION) { + c->crypto_connections[i].number = connection_id; + c->crypto_connections[i].status = CONN_NOT_CONFIRMED; + random_nonce(c->crypto_connections[i].recv_nonce); + memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); + memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); + increment_nonce(c->crypto_connections[i].sent_nonce); + memcpy(c->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(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); - if (crypto_connections_length == i) - ++crypto_connections_length; + if (c->crypto_connections_length == i) + ++c->crypto_connections_length; - if (send_cryptohandshake(connection_id, public_key, crypto_connections[i].recv_nonce, - crypto_connections[i].sessionpublic_key) == 1) { - increment_nonce(crypto_connections[i].recv_nonce); + if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce, + c->crypto_connections[i].sessionpublic_key) == 1) { + increment_nonce(c->crypto_connections[i].recv_nonce); uint32_t zero = 0; - encrypt_precompute(crypto_connections[i].peersessionpublic_key, - crypto_connections[i].sessionsecret_key, - crypto_connections[i].shared_key); - crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ - write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); - crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ + encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, + c->crypto_connections[i].sessionsecret_key, + c->crypto_connections[i].shared_key); + c->crypto_connections[i].status = + CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ + write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); + c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ return i; } @@ -593,48 +574,46 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre /* return 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet (we have received a handshake but no empty data packet), 3 if the connection is established. 4 if the connection is timed out and waiting to be killed */ -int is_cryptoconnected(int crypt_connection_id) +int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id) { - if (crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS) - return crypto_connections[crypt_connection_id].status; + if (crypt_connection_id >= 0 && crypt_connection_id < c->crypto_connections_length) + return c->crypto_connections[crypt_connection_id].status; return CONN_NO_CONNECTION; } -/* Generate our public and private keys - Only call this function the first time the program starts. */ -void new_keys(void) +void new_keys(Net_Crypto *c) { - crypto_box_keypair(self_public_key, self_secret_key); + crypto_box_keypair(c->self_public_key, c->self_secret_key); } /* save the public and private keys to the keys array Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ -void save_keys(uint8_t *keys) +void save_keys(Net_Crypto *c, uint8_t *keys) { - memcpy(keys, self_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(keys + crypto_box_PUBLICKEYBYTES, self_secret_key, crypto_box_SECRETKEYBYTES); + memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES); } /* load the public and private keys from the keys array Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ -void load_keys(uint8_t *keys) +void load_keys(Net_Crypto *c, uint8_t *keys) { - memcpy(self_public_key, keys, crypto_box_PUBLICKEYBYTES); - memcpy(self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); + memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES); + memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); } /* TODO: optimize this adds an incoming connection to the incoming_connection list. returns 0 if successful returns 1 if failure */ -static int new_incoming(int id) +static int new_incoming(Net_Crypto *c, int id) { uint32_t i; for (i = 0; i < MAX_INCOMING; ++i) { - if (incoming_connections[i] == -1) { - incoming_connections[i] = id; + if (c->incoming_connections[i] == -1) { + c->incoming_connections[i] = id; return 0; } } @@ -644,81 +623,83 @@ static int new_incoming(int id) /* TODO: optimize this handle all new incoming connections. */ -static void handle_incomings(void) +static void handle_incomings(Net_Crypto *c) { int income; while (1) { - income = incoming_connection(); + income = incoming_connection(c->lossless_udp); - if (income == -1 || new_incoming(income) ) + if (income == -1 || new_incoming(c, income) ) break; } } /* handle received packets for not yet established crypto connections. */ -static void receive_crypto(void) +static void receive_crypto(Net_Crypto *c) { uint32_t i; - for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { - if (crypto_connections[i].status == CONN_HANDSHAKE_SENT) { + for (i = 0; i < c->crypto_connections_length; ++i) { + if (c->crypto_connections[i].status == CONN_HANDSHAKE_SENT) { uint8_t temp_data[MAX_DATA_SIZE]; uint8_t secret_nonce[crypto_box_NONCEBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t session_key[crypto_box_PUBLICKEYBYTES]; uint16_t len; - if (id_packet(crypto_connections[i].number) == 2) { /* handle handshake packet. */ - len = read_packet(crypto_connections[i].number, temp_data); + if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* handle handshake packet. */ + len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); - if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) { - if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { - memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); - increment_nonce(crypto_connections[i].sent_nonce); + if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { + if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { + memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); + memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); + increment_nonce(c->crypto_connections[i].sent_nonce); uint32_t zero = 0; - encrypt_precompute(crypto_connections[i].peersessionpublic_key, - crypto_connections[i].sessionsecret_key, - crypto_connections[i].shared_key); - crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ - write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); - crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ + encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, + c->crypto_connections[i].sessionsecret_key, + c->crypto_connections[i].shared_key); + c->crypto_connections[i].status = + CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ + write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); + c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* 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 - crypto_kill(crypto_connections[i].number); + } else if (id_packet(c->lossless_udp, + c->crypto_connections[i].number) != -1) { // This should not happen kill the connection if it does + crypto_kill(c, i); return; } } - if (crypto_connections[i].status == CONN_NOT_CONFIRMED) { - if (id_packet(crypto_connections[i].number) == 3) { + if (c->crypto_connections[i].status == CONN_NOT_CONFIRMED) { + if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) { uint8_t temp_data[MAX_DATA_SIZE]; uint8_t data[MAX_DATA_SIZE]; - int length = read_packet(crypto_connections[i].number, temp_data); - int len = decrypt_data(crypto_connections[i].peersessionpublic_key, - crypto_connections[i].sessionsecret_key, - crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); + int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); + int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key, + c->crypto_connections[i].sessionsecret_key, + c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); uint32_t zero = 0; if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { - increment_nonce(crypto_connections[i].recv_nonce); - encrypt_precompute(crypto_connections[i].peersessionpublic_key, - crypto_connections[i].sessionsecret_key, - crypto_connections[i].shared_key); - crypto_connections[i].status = CONN_ESTABLISHED; + increment_nonce(c->crypto_connections[i].recv_nonce); + encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, + c->crypto_connections[i].sessionsecret_key, + c->crypto_connections[i].shared_key); + c->crypto_connections[i].status = CONN_ESTABLISHED; /* 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(c->lossless_udp, c->crypto_connections[i].number, 3000000); } else { - crypto_kill(crypto_connections[i].number); // This should not happen kill the connection if it does + crypto_kill(c, i); // This should not happen kill the connection if it does return; } - } else if (id_packet(crypto_connections[i].number) != -1) + } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != -1) /* This should not happen kill the connection if it does */ - crypto_kill(crypto_connections[i].number); + crypto_kill(c, i); return; } @@ -727,33 +708,64 @@ static void receive_crypto(void) /* run this to (re)initialize net_crypto sets all the global connection variables to their default values. */ -void initNetCrypto(void) +Net_Crypto *new_net_crypto(Networking_Core *net) { - memset(incoming_connections, -1 , sizeof(incoming_connections)); - networking_registerhandler(32, &cryptopacket_handle); + if (net == NULL) + return NULL; + + Net_Crypto *temp = calloc(1, sizeof(Net_Crypto)); + + if (temp == NULL) + return NULL; + + temp->lossless_udp = new_lossless_udp(net); + + if (temp->lossless_udp == NULL) + return NULL; + + memset(temp->incoming_connections, -1 , sizeof(int) * MAX_INCOMING); + return temp; } -static void killTimedout(void) +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; - for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { - if (crypto_connections[i].status != CONN_NO_CONNECTION && is_connected(crypto_connections[i].number) == 4) - crypto_connections[i].status = CONN_TIMED_OUT; - else if (is_connected(crypto_connections[i].number) == 4) { - kill_connection(crypto_connections[i].number); - crypto_connections[i].number = ~0; + for (i = 0; i < c->crypto_connections_length; ++i) { + if (c->crypto_connections[i].status != CONN_NO_CONNECTION + && is_connected(c->lossless_udp, c->crypto_connections[i].number) == 4) + c->crypto_connections[i].status = CONN_TIMED_OUT; + else if (is_connected(c->lossless_udp, c->crypto_connections[i].number) == 4) { + kill_connection(c->lossless_udp, c->crypto_connections[i].number); + c->crypto_connections[i].number = ~0; } } } /* main loop */ -void doNetCrypto(void) +void do_net_crypto(Net_Crypto *c) { - /* TODO:check if friend requests were sent correctly - handle new incoming connections - handle friend requests */ - handle_incomings(); - receive_crypto(); - killTimedout(); + do_lossless_udp(c->lossless_udp); + handle_incomings(c); + receive_crypto(c); + kill_timedout(c); +} + +void kill_net_crypto(Net_Crypto *c) +{ + uint32_t i; + + for (i = 0; i < c->crypto_connections_length; ++i) { + crypto_kill(c, i); + } + + kill_lossless_udp(c->lossless_udp); + memset(c, 0, sizeof(Net_Crypto)); + free(c); } diff --git a/core/net_crypto.h b/core/net_crypto.h index 742d9fdc..46bcf250 100644 --- a/core/net_crypto.h +++ b/core/net_crypto.h @@ -25,15 +25,54 @@ #define NET_CRYPTO_H #include "Lossless_UDP.h" -#include "DHT.h" #ifdef __cplusplus extern "C" { #endif -/* Our public key. */ -extern uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; -extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; +#define MAX_INCOMING 64 + +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 */ + uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* nonce of sent packets. */ + 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 peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ + uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* the precomputed shared key from encrypt_precompute */ + 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. + 4 if the connection is timed out. */ + uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ + +} Crypto_Connection; + +typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, + uint32_t len); + +typedef struct { + cryptopacket_handler_callback function; + void *object; +} Cryptopacket_Handles; + +typedef struct { + Lossless_UDP *lossless_udp; + + Crypto_Connection *crypto_connections; + + uint32_t crypto_connections_length; /* Length of connections array */ + + /* Our public and secret keys. */ + uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; + + /* 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" #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) @@ -75,34 +114,36 @@ void random_nonce(uint8_t *nonce); /* return 0 if there is no received data in the buffer return -1 if the packet was discarded. return length of received data if successful */ -int read_cryptpacket(int crypt_connection_id, uint8_t *data); +int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data); /* return 0 if data could not be put in packet queue return 1 if data was put into the queue */ -int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length); +int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); -/* create a request to peer with public_key. - 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. - request_id is the id of the request (32 = friend request, 254 = ping request) - returns -1 on failure - 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); +/* create a request to peer. + send_public_key and send_secret_key are the pub/secret keys of the sender + recv_public_key is public key of reciever + 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. + request_id is the id of the request (32 = friend request, 254 = ping request) + returns -1 on failure + returns the length of the created packet on success */ +int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, + uint8_t *data, uint32_t length, uint8_t request_id); -typedef int (*cryptopacket_handler_callback)(IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, uint32_t len); /* Function to call when request beginning with byte is received */ -void cryptopacket_registerhandler(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 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(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port); /* kill a crypto connection return 0 if killed successfully return 1 if there was a problem. */ -int crypto_kill(int crypt_connection_id); +int crypto_kill(Net_Crypto *c, int crypt_connection_id); /* handle an incoming connection return -1 if no crypto inbound connection @@ -111,37 +152,43 @@ int crypto_kill(int crypt_connection_id); and the session public key for the connection in session_key to accept it see: accept_crypto_inbound(...) 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(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key); /* accept an incoming connection using the parameters provided by crypto_inbound return -1 if not successful returns the crypt_connection_id if successful */ -int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key); +int accept_crypto_inbound(Net_Crypto *c, 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 (we have received a handshake but no empty data packet), 3 if the connection is established. 4 if the connection is timed out and waiting to be killed */ -int is_cryptoconnected(int crypt_connection_id); +int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id); /* Generate our public and private keys Only call this function the first time the program starts. */ -void new_keys(void); +void new_keys(Net_Crypto *c); /* save the public and private keys to the keys array Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ -void save_keys(uint8_t *keys); +void save_keys(Net_Crypto *c, uint8_t *keys); /* load the public and private keys from the keys array Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ -void load_keys(uint8_t *keys); +void load_keys(Net_Crypto *c, uint8_t *keys); -/* run this to (re)initialize net_crypto +/* create new instance of Net_Crypto sets all the global connection variables to their default values. */ -void initNetCrypto(void); +Net_Crypto *new_net_crypto(Networking_Core *net); /* main loop */ -void doNetCrypto(void); +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 } diff --git a/core/network.c b/core/network.c index 1977ce38..849c7e2a 100644 --- a/core/network.c +++ b/core/network.c @@ -56,12 +56,9 @@ uint32_t random_int(void) #endif } -/* our UDP socket, a global variable. */ -static int sock; - /* Basic network functions: 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(int sock, IP_Port ip_port, uint8_t *data, uint32_t length) { ADDR addr = {AF_INET, ip_port.port, ip_port.ip}; return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); @@ -71,7 +68,7 @@ int sendpacket(IP_Port ip_port, uint8_t *data, uint32_t length) the packet data into data the packet length into length. dump all empty packets. */ -static int receivepacket(IP_Port *ip_port, uint8_t *data, uint32_t *length) +static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) { ADDR addr; #ifdef WIN32 @@ -89,36 +86,33 @@ static int receivepacket(IP_Port *ip_port, uint8_t *data, uint32_t *length) return 0; } -static packet_handler_callback packethandlers[256] = {0}; - -void networking_registerhandler(uint8_t byte, packet_handler_callback cb) +void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object) { - packethandlers[byte] = cb; + net->packethandlers[byte].function = cb; + net->packethandlers[byte].object = object; } -void networking_poll() +void networking_poll(Networking_Core *net) { IP_Port ip_port; uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; - while (receivepacket(&ip_port, data, &length) != -1) { + while (receivepacket(net->sock, &ip_port, data, &length) != -1) { if (length < 1) continue; - if (!packethandlers[data[0]]) continue; + if (!(net->packethandlers[data[0]].function)) continue; - packethandlers[data[0]](ip_port, data, length); + net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length); } } -/* initialize networking - bind to ip and port - 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) - returns 0 if no problems - returns -1 if there are problems */ -int init_networking(IP ip, uint16_t port) +uint8_t at_startup_ran; +static void at_startup(void) { + if (at_startup_ran != 0) + return; + #ifdef WIN32 WSADATA wsaData; @@ -129,20 +123,49 @@ int init_networking(IP ip, uint16_t port) srandom((uint32_t)current_time()); #endif srand((uint32_t)current_time()); + at_startup_ran = 1; +} +/* TODO: put this somewhere +static void at_shutdown(void) +{ +#ifdef WIN32 + WSACleanup(); +#endif +} +*/ + +/* initialize networking + bind to ip and port + 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) + returns Networking_Core object if no problems + returns NULL if there are problems */ +Networking_Core *new_networking(IP ip, uint16_t port) +{ + at_startup(); /* initialize our socket */ - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + Networking_Core *temp = calloc(1, sizeof(Networking_Core)); + + if (temp == NULL) + return NULL; + + temp->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Check for socket error */ #ifdef WIN32 - if (sock == INVALID_SOCKET) /* MSDN recommends this */ - return -1; + if (temp->sock == INVALID_SOCKET) { /* MSDN recommends this */ + free(temp); + return NULL; + } #else - if (sock < 0) - return -1; + if (temp->sock < 0) { + free(temp); + return NULL; + } #endif @@ -161,34 +184,33 @@ int init_networking(IP ip, uint16_t port) /* Enable broadcast on socket */ int broadcast = 1; - setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); + setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); /* Set socket nonblocking */ #ifdef WIN32 /* I think this works for windows */ u_long mode = 1; /* ioctl(sock, FIONBIO, &mode); */ - ioctlsocket(sock, FIONBIO, &mode); + ioctlsocket(temp->sock, FIONBIO, &mode); #else - fcntl(sock, F_SETFL, O_NONBLOCK, 1); + fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1); #endif /* Bind our socket to port PORT and address 0.0.0.0 */ ADDR addr = {AF_INET, htons(port), ip}; - bind(sock, (struct sockaddr *)&addr, sizeof(addr)); - - return 0; + bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr)); + return temp; } /* function to cleanup networking stuff */ -void shutdown_networking(void) +void kill_networking(Networking_Core *net) { #ifdef WIN32 - closesocket(sock); - WSACleanup(); + closesocket(net->sock); #else - close(sock); + close(net->sock); #endif + free(net); return; } diff --git a/core/network.h b/core/network.h index 127a55d1..87f45978 100644 --- a/core/network.h +++ b/core/network.h @@ -99,7 +99,18 @@ typedef struct { /* Function to receive data, ip and port of sender is put into ip_port the packet data into data the packet length into length. */ -typedef int (*packet_handler_callback)(IP_Port ip_port, uint8_t *data, uint32_t len); +typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, uint8_t *data, uint32_t len); + +typedef struct { + packet_handler_callback function; + void *object; +} Packet_Handles; + +typedef struct { + Packet_Handles packethandlers[256]; + /* our UDP socket */ + int sock; +} Networking_Core; /* returns current time in milleseconds since the epoch. */ uint64_t current_time(void); @@ -111,13 +122,13 @@ uint32_t random_int(void); /* Basic network functions: */ /* 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(int sock, IP_Port ip_port, uint8_t *data, uint32_t length); /* Function to call when packet beginning with byte is received */ -void networking_registerhandler(uint8_t byte, packet_handler_callback cb); +void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object); /* call this several times a second */ -void networking_poll(); +void networking_poll(Networking_Core *net); /* initialize networking bind to ip and port @@ -125,10 +136,10 @@ void networking_poll(); port is in host byte order (this means don't worry about it) returns 0 if no problems returns -1 if there were problems */ -int init_networking(IP ip, uint16_t port); +Networking_Core *new_networking(IP ip, uint16_t port); /* function to cleanup networking stuff(doesn't do much right now) */ -void shutdown_networking(void); +void kill_networking(Networking_Core *net); /* resolve_addr(): diff --git a/core/ping.c b/core/ping.c index 47d6e163..4bb9c38a 100644 --- a/core/ping.c +++ b/core/ping.c @@ -23,17 +23,20 @@ typedef struct { uint64_t timestamp; } pinged_t; -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; +typedef struct { + pinged_t pings[PING_NUM_MAX]; + size_t num_pings; + size_t pos_pings; +} PING; -extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; // DHT.c - -void init_ping() +void *new_ping(void) { - num_pings = 0; - pos_pings = 0; + return calloc(1, sizeof(PING)); +} + +void kill_ping(void *ping) +{ + free(ping); } static bool is_timeout(uint64_t time) @@ -41,17 +44,18 @@ static bool is_timeout(uint64_t time) return (time + PING_TIMEOUT) < now(); } -static void remove_timeouts() // O(n) +static void remove_timeouts(void *ping) // O(n) { + PING *png = ping; size_t i, id; - size_t new_pos = pos_pings; - size_t new_num = num_pings; + size_t new_pos = png->pos_pings; + size_t new_num = png->num_pings; // Loop through buffer, oldest first - for (i = 0; i < num_pings; i++) { - id = (pos_pings + i) % PING_NUM_MAX; + for (i = 0; i < png->num_pings; i++) { + id = (png->pos_pings + i) % PING_NUM_MAX; - if (is_timeout(pings[id].timestamp)) { + if (is_timeout(png->pings[id].timestamp)) { new_pos++; new_num--; } @@ -61,47 +65,50 @@ static void remove_timeouts() // O(n) } } - num_pings = new_num; - pos_pings = new_pos % PING_NUM_MAX; + png->num_pings = new_num; + png->pos_pings = new_pos % PING_NUM_MAX; } -uint64_t add_ping(IP_Port ipp) // O(n) +uint64_t add_ping(void *ping, IP_Port ipp) // O(n) { + PING *png = ping; size_t p; - remove_timeouts(); + remove_timeouts(ping); // Remove oldest ping if full buffer - if (num_pings == PING_NUM_MAX) { - num_pings--; - pos_pings = (pos_pings + 1) % PING_NUM_MAX; + if (png->num_pings == PING_NUM_MAX) { + png->num_pings--; + png->pos_pings = (png->pos_pings + 1) % PING_NUM_MAX; } // Insert new ping at end of list - p = (pos_pings + num_pings) % PING_NUM_MAX; + p = (png->pos_pings + png->num_pings) % PING_NUM_MAX; - pings[p].ipp = ipp; - pings[p].timestamp = now(); - pings[p].id = random_64b(); + png->pings[p].ipp = ipp; + png->pings[p].timestamp = now(); + png->pings[p].id = random_64b(); - num_pings++; - return pings[p].id; + png->num_pings++; + return png->pings[p].id; } -bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with something else. +bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with something else. { + PING *png = ping; + if (ipp.ip.i == 0 && ping_id == 0) return false; size_t i, id; - remove_timeouts(); + remove_timeouts(ping); - for (i = 0; i < num_pings; i++) { - id = (pos_pings + i) % PING_NUM_MAX; + for (i = 0; i < png->num_pings; i++) { + id = (png->pos_pings + i) % PING_NUM_MAX; // ping_id = 0 means match any id - if ((ipp_eq(pings[id].ipp, ipp) || ipp.ip.i == 0) && (pings[id].id == ping_id || ping_id == 0)) { + if ((ipp_eq(png->pings[id].ipp, ipp) || ipp.ip.i == 0) && (png->pings[id].id == ping_id || ping_id == 0)) { return true; } } @@ -109,25 +116,25 @@ bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with return false; } -int send_ping_request(IP_Port ipp, clientid_t *client_id) +int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, clientid_t *client_id) { pingreq_t pk; int rc; uint64_t ping_id; - if (is_pinging(ipp, 0) || id_eq(client_id, self_id)) + if (is_pinging(ping, ipp, 0) || id_eq(client_id, (clientid_t *)c->self_public_key)) return 1; // Generate random ping_id - ping_id = add_ping(ipp); + ping_id = add_ping(ping, ipp); pk.magic = PACKET_PING_REQ; - id_cpy(&pk.client_id, self_id); // Our pubkey + id_cpy(&pk.client_id, (clientid_t *)c->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, + c->self_secret_key, (uint8_t *) &pk.nonce, (uint8_t *) &ping_id, sizeof(ping_id), (uint8_t *) &pk.ping_id); @@ -135,24 +142,24 @@ int send_ping_request(IP_Port ipp, clientid_t *client_id) if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) return 1; - return sendpacket(ipp, (uint8_t *) &pk, sizeof(pk)); + return sendpacket(c->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) +int send_ping_response(Net_Crypto *c, 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 *)c->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 *)c->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, + c->self_secret_key, (uint8_t *) &pk.nonce, (uint8_t *) &ping_id, sizeof(ping_id), (uint8_t *) &pk.ping_id); @@ -160,21 +167,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(ipp, (uint8_t *) &pk, sizeof(pk)); + return sendpacket(c->lossless_udp->net->sock, ipp, (uint8_t *) &pk, sizeof(pk)); } -int handle_ping_request(IP_Port source, uint8_t *packet, uint32_t length) +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, @@ -184,24 +192,25 @@ int handle_ping_request(IP_Port source, uint8_t *packet, uint32_t length) return 1; // Send response - send_ping_response(source, &p->client_id, ping_id); - add_toping((uint8_t *) &p->client_id, source); + send_ping_response(dht->c, source, &p->client_id, ping_id); + add_toping(dht, (uint8_t *) &p->client_id, source); return 0; } -int handle_ping_response(IP_Port source, uint8_t *packet, uint32_t length) +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, @@ -211,10 +220,10 @@ int handle_ping_response(IP_Port source, uint8_t *packet, uint32_t length) return 1; // Make sure ping_id is correct - if (!is_pinging(source, ping_id)) + if (!is_pinging(dht->ping, source, ping_id)) 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/core/ping.h b/core/ping.h index 0c44874b..c04ec80e 100644 --- a/core/ping.h +++ b/core/ping.h @@ -7,10 +7,11 @@ #include -void init_ping(); -uint64_t add_ping(IP_Port ipp); -bool is_pinging(IP_Port ipp, uint64_t ping_id); -int send_ping_request(IP_Port ipp, clientid_t *client_id); -int send_ping_response(IP_Port ipp, clientid_t *client_id, uint64_t ping_id); -int handle_ping_request(IP_Port source, uint8_t *packet, uint32_t length); -int handle_ping_response(IP_Port source, uint8_t *packet, uint32_t length); +void *new_ping(void); +void kill_ping(void *ping); +uint64_t add_ping(void *ping, IP_Port ipp); +bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id); +int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, clientid_t *client_id); +int send_ping_response(Net_Crypto *c, IP_Port ipp, clientid_t *client_id, uint64_t ping_id); +int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length); +int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t length); diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 299e030c..5d97b37a 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -44,7 +44,7 @@ -void manage_keys() +void manage_keys(DHT *dht) { const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; uint8_t keys[KEYS_SIZE]; @@ -60,12 +60,12 @@ void manage_keys() exit(1); } - load_keys(keys); + load_keys(dht->c, keys); printf("Keys loaded successfully\n"); } else { //otherwise save new keys - new_keys(); - save_keys(keys); + new_keys(dht->c); + save_keys(dht->c, keys); keys_file = fopen("key", "w"); if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) { @@ -81,7 +81,13 @@ void manage_keys() int main(int argc, char *argv[]) { - manage_keys(); + //initialize networking + //bind to ip 0.0.0.0:PORT + IP ip; + ip.i = 0; + DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); + init_cryptopackets(dht); + manage_keys(dht); printf("Public key: "); uint32_t i; @@ -89,22 +95,17 @@ int main(int argc, char *argv[]) file = fopen("PUBLIC_ID.txt", "w"); for (i = 0; i < 32; i++) { - if (self_public_key[i] < 16) + if (dht->c->self_public_key[i] < 16) printf("0"); - printf("%hhX", self_public_key[i]); - fprintf(file, "%hhX", self_public_key[i]); + printf("%hhX", dht->c->self_public_key[i]); + fprintf(file, "%hhX", dht->c->self_public_key[i]); } fclose(file); printf("\n"); printf("Port: %u\n", PORT); - //initialize networking - //bind to ip 0.0.0.0:PORT - IP ip; - ip.i = 0; - init_networking(ip, PORT); perror("Initialization"); @@ -114,28 +115,24 @@ int main(int argc, char *argv[]) bootstrap_info.ip.i = inet_addr(argv[1]); bootstrap_info.port = htons(atoi(argv[2])); uint8_t *bootstrap_key = hex_string_to_bin(argv[3]); - DHT_bootstrap(bootstrap_info, bootstrap_key); + DHT_bootstrap(dht, bootstrap_info, bootstrap_key); free(bootstrap_key); } - DHT_init(); - friendreq_init(); - int is_waiting_for_dht_connection = 1; while (1) { - if (is_waiting_for_dht_connection && DHT_isconnected()) { + if (is_waiting_for_dht_connection && DHT_isconnected(dht)) { printf("Connected to other bootstrap server successfully.\n"); is_waiting_for_dht_connection = 0; } - doDHT(); + do_DHT(dht); - networking_poll(); + networking_poll(dht->c->lossless_udp->net); c_sleep(1); } - shutdown_networking(); return 0; } diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c index 896d6a69..81ac538b 100644 --- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c +++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c @@ -77,7 +77,7 @@ and connect to them. returns 1 if the connection to the DHT is up returns -1 if all attempts failed */ -int connect_to_servers(struct server_info_s *info) +int connect_to_servers(DHT *dht, struct server_info_s *info) { int i; int c; @@ -86,7 +86,7 @@ int connect_to_servers(struct server_info_s *info) if (info[i].valid) { /* Actual bootstrapping code goes here */ //puts("Calling DHT_bootstrap"); - DHT_bootstrap(info[i].conn, info[i].bs_pk); + DHT_bootstrap(dht, info[i].conn, info[i].bs_pk); } } @@ -94,28 +94,28 @@ int connect_to_servers(struct server_info_s *info) for (c = 0; c != 100; ++c) { usleep(10000); - if (DHT_isconnected()) { + if (DHT_isconnected(dht)) { //puts("Connected"); return 1; break; } - if (DHT_isconnected() == 0 && c == 99) { + if (DHT_isconnected(dht) == 0 && c == 99) { //puts("Not connected"); return -1; break; } - doDHT(); + do_DHT(dht); - networking_poll(); + networking_poll(dht->c->lossless_udp->net); } /* This probably never happens */ return 0; } -void manage_keys(char *keys_file) +void manage_keys(DHT *dht, char *keys_file) { const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; uint8_t keys[KEYS_SIZE]; @@ -134,13 +134,13 @@ void manage_keys(char *keys_file) printf("Keys loaded successfully\n"); } - load_keys(keys); + load_keys(dht->c, keys); } else { /* otherwise save new keys */ /* Silly work-around to ignore any errors coming from new_keys() */ - new_keys(); - save_keys(keys); + new_keys(dht->c); + save_keys(dht->c, keys); keysf = fopen(keys_file, "w"); if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) { @@ -294,9 +294,14 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - /* Read the config file */ server_conf = configure_server(argv[1]); + /* initialize networking + bind to ip 0.0.0.0:PORT */ + IP ip; + ip.i = 0; + DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port))); + /* Read the config file */ printf("PID file: %s\n", server_conf.pid_file); printf("Key file: %s\n", server_conf.keys_file); @@ -313,38 +318,32 @@ int main(int argc, char *argv[]) /* Manage the keys */ /* for now, just ignore any errors after this call. */ int tmperr = errno; - manage_keys(server_conf.keys_file); + manage_keys(dht, server_conf.keys_file); errno = tmperr; + init_cryptopackets(dht); /* Public key */ int i; printf("\nPublic Key: "); for (i = 0; i < 32; ++i) { uint8_t ln, hn; - ln = 0x0F & self_public_key[i]; - hn = 0xF0 & self_public_key[i]; + ln = 0x0F & dht->c->self_public_key[i]; + hn = 0xF0 & dht->c->self_public_key[i]; hn = hn >> 4; printf("%X%X", hn, ln); } printf("\n"); - /* initialize networking - bind to ip 0.0.0.0:PORT */ - IP ip; - ip.i = 0; - init_networking(ip, server_conf.port); - /* Bootstrap the DHT This one throws odd errors, too. Ignore. I assume they come from somewhere in the core. */ - DHT_init(); tmperr = errno; - connect_to_servers(server_conf.info); + connect_to_servers(dht, server_conf.info); errno = tmperr; - if (!DHT_isconnected()) { + if (!DHT_isconnected(dht)) { puts("Could not establish DHT connection. Check server settings.\n"); exit(EXIT_FAILURE); } else { @@ -404,13 +403,10 @@ int main(int argc, char *argv[]) close(STDIN_FILENO); close(STDERR_FILENO); - /* Main loop */ - friendreq_init(); - while (1) { - doDHT(); + do_DHT(dht); - networking_poll(); + networking_poll(dht->c->lossless_udp->net); usleep(10000); } diff --git a/core/timer.c b/other/unused/timer.c similarity index 100% rename from core/timer.c rename to other/unused/timer.c diff --git a/core/timer.h b/other/unused/timer.h similarity index 100% rename from core/timer.h rename to other/unused/timer.h diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index 9e07135c..e3cdc838 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -9,7 +9,6 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Lossless_UDP_testclient.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Lossless_UDP_testserver.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Messenger_test.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/crypto_speed_test.cmake) -include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/timer_test.cmake) if(WIN32) # include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox_win32.cmake) diff --git a/testing/DHT_test.c b/testing/DHT_test.c index 3883f3a7..8ab9157e 100644 --- a/testing/DHT_test.c +++ b/testing/DHT_test.c @@ -28,8 +28,8 @@ */ //#include "../core/network.h" -#include "../core/DHT.c" -#include "../core/friend_requests.c" +#include "../core/DHT.h" +#include "../core/friend_requests.h" #include "misc_tools.h" #include @@ -48,7 +48,7 @@ #define PORT 33445 -void print_clientlist() +void print_clientlist(DHT *dht) { uint32_t i, j; IP_Port p_ip; @@ -58,34 +58,34 @@ void print_clientlist() printf("ClientID: "); for (j = 0; j < 32; j++) { - printf("%02hhX", close_clientlist[i].client_id[j]); + printf("%02hhX", dht->close_clientlist[i].client_id[j]); } - p_ip = close_clientlist[i].ip_port; + p_ip = dht->close_clientlist[i].ip_port; printf("\nIP: %u.%u.%u.%u Port: %u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); - printf("\nTimestamp: %llu", (long long unsigned int) close_clientlist[i].timestamp); - printf("\nLast pinged: %llu\n", (long long unsigned int) close_clientlist[i].last_pinged); - p_ip = close_clientlist[i].ret_ip_port; + printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp); + printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged); + p_ip = dht->close_clientlist[i].ret_ip_port; printf("OUR IP: %u.%u.%u.%u Port: %u\n", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); - printf("Timestamp: %llu\n", (long long unsigned int) close_clientlist[i].ret_timestamp); + printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp); } } -void print_friendlist() +void print_friendlist(DHT *dht) { uint32_t i, j, k; IP_Port p_ip; printf("_________________FRIENDS__________________________________\n"); - for (k = 0; k < num_friends; k++) { + for (k = 0; k < dht->num_friends; k++) { printf("FRIEND %u\n", k); printf("ID: "); for (j = 0; j < 32; j++) { - printf("%c", friends_list[k].client_id[j]); + printf("%c", dht->friends_list[k].client_id[j]); } - p_ip = DHT_getfriendip(friends_list[k].client_id); + p_ip = DHT_getfriendip(dht, dht->friends_list[k].client_id); printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); printf("\nCLIENTS IN LIST:\n\n"); @@ -94,19 +94,19 @@ void print_friendlist() printf("ClientID: "); for (j = 0; j < 32; j++) { - if (friends_list[k].client_list[i].client_id[j] < 16) + if (dht->friends_list[k].client_list[i].client_id[j] < 16) printf("0"); - printf("%hhX", friends_list[k].client_list[i].client_id[j]); + printf("%hhX", dht->friends_list[k].client_list[i].client_id[j]); } - p_ip = friends_list[k].client_list[i].ip_port; + p_ip = dht->friends_list[k].client_list[i].ip_port; printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); - printf("\nTimestamp: %llu", (long long unsigned int) friends_list[k].client_list[i].timestamp); - printf("\nLast pinged: %llu\n", (long long unsigned int) friends_list[k].client_list[i].last_pinged); - p_ip = friends_list[k].client_list[i].ret_ip_port; + printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp); + printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged); + p_ip = dht->friends_list[k].client_list[i].ret_ip_port; printf("ret IP: %u.%u.%u.%u:%u\n", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); - printf("Timestamp: %llu\n", (long long unsigned int)friends_list[k].client_list[i].ret_timestamp); + printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp); } } } @@ -130,21 +130,28 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) int main(int argc, char *argv[]) { //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); + /* initialize networking */ + /* bind to ip 0.0.0.0:PORT */ + IP ip; + ip.i = 0; + + DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); + init_cryptopackets(dht); if (argc < 4) { printf("usage %s ip port public_key\n", argv[0]); exit(0); } - new_keys(); + new_keys(dht->c); printf("OUR ID: "); uint32_t i; for (i = 0; i < 32; i++) { - if (self_public_key[i] < 16) + if (dht->c->self_public_key[i] < 16) printf("0"); - printf("%hhX", self_public_key[i]); + printf("%hhX", dht->c->self_public_key[i]); } char temp_id[128]; @@ -153,13 +160,7 @@ int main(int argc, char *argv[]) if (scanf("%s", temp_id) != 1) exit(0); - DHT_addfriend(hex_string_to_bin(temp_id)); - - /* initialize networking */ - /* bind to ip 0.0.0.0:PORT */ - IP ip; - ip.i = 0; - init_networking(ip, PORT); + DHT_addfriend(dht, hex_string_to_bin(temp_id)); perror("Initialization"); @@ -170,7 +171,7 @@ int main(int argc, char *argv[]) * bootstrap_ip_port.ip.c[2] = 0; * bootstrap_ip_port.ip.c[3] = 1; */ bootstrap_ip_port.ip.i = inet_addr(argv[1]); - DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); + DHT_bootstrap(dht, bootstrap_ip_port, hex_string_to_bin(argv[3])); /* IP_Port ip_port; @@ -178,12 +179,9 @@ int main(int argc, char *argv[]) uint32_t length; */ - DHT_init(); - friendreq_init(); - while (1) { - doDHT(); + do_DHT(dht); /* slvrTODO: while(receivepacket(&ip_port, data, &length) != -1) { @@ -195,13 +193,12 @@ int main(int argc, char *argv[]) } } */ - networking_poll(); + networking_poll(dht->c->lossless_udp->net); - print_clientlist(); - print_friendlist(); + print_clientlist(dht); + print_friendlist(dht); c_sleep(300); } - shutdown_networking(); return 0; } diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c index 575be2bd..09e9e0a3 100644 --- a/testing/Lossless_UDP_testclient.c +++ b/testing/Lossless_UDP_testclient.c @@ -122,29 +122,29 @@ void printconnection(int connection_id) /*( receive packets and send them to the packethandler */ /*run doLossless_UDP(); */ -void Lossless_UDP() -{ - /* IP_Port ip_port; - uint8_t data[MAX_UDP_PACKET_SIZE]; - uint32_t length; - while (receivepacket(&ip_port, data, &length) != -1) { - printf("packet with length: %u\n", length); */ - /* if(rand() % 3 != 1)//add packet loss - { */ - /* - if (LosslessUDP_handlepacket(data, length, ip_port)) - printpacket(data, length, ip_port); - else - printf("Received handled packet with length: %u\n", length); //printconnection(0); */ +//void Lossless_UDP() +//{ +/* IP_Port ip_port; + uint8_t data[MAX_UDP_PACKET_SIZE]; + uint32_t length; + while (receivepacket(&ip_port, data, &length) != -1) { + printf("packet with length: %u\n", length); */ +/* if(rand() % 3 != 1)//add packet loss + { */ +/* + if (LosslessUDP_handlepacket(data, length, ip_port)) + printpacket(data, length, ip_port); + else + printf("Received handled packet with length: %u\n", length); //printconnection(0); */ - /* } */ - /* }*/ +/* } */ +/* }*/ - networking_poll(); +//networking_poll(); - doLossless_UDP(); +//doLossless_UDP(); -} +//} int main(int argc, char *argv[]) { @@ -166,25 +166,26 @@ int main(int argc, char *argv[]) /* bind to ip 0.0.0.0:PORT */ IP ip; ip.i = 0; - init_networking(ip, PORT); + Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); perror("Initialization"); IP_Port serverip; serverip.ip.i = inet_addr(argv[1]); serverip.port = htons(atoi(argv[2])); printip(serverip); - int connection = new_connection(serverip); + int connection = new_connection(ludp, serverip); uint64_t timer = current_time(); while (1) { /* printconnection(connection); */ - Lossless_UDP(); + networking_poll(ludp->net); + do_lossless_udp(ludp); - if (is_connected(connection) == 3) { + if (is_connected(ludp, connection) == 3) { printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer)); break; } - if (is_connected(connection) == 0) { + if (is_connected(ludp, connection) == 0) { printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); return 1; } @@ -194,25 +195,25 @@ int main(int argc, char *argv[]) timer = current_time(); - LosslessUDP_init(); /*read first part of file */ read = fread(buffer, 1, 512, file); while (1) { /* printconnection(connection); */ - Lossless_UDP(); + networking_poll(ludp->net); + do_lossless_udp(ludp); - if (is_connected(connection) == 3) { + if (is_connected(ludp, connection) == 3) { - if (write_packet(connection, buffer, read)) { + if (write_packet(ludp, connection, buffer, read)) { /* printf("Wrote data.\n"); */ read = fread(buffer, 1, 512, file); } /* printf("%u\n", sendqueue(connection)); */ - if (sendqueue(connection) == 0) { + if (sendqueue(ludp, connection) == 0) { if (read == 0) { printf("Sent file successfully in: %llu us\n", (unsigned long long)(current_time() - timer)); break; diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c index dec50d7f..a82b787a 100644 --- a/testing/Lossless_UDP_testserver.c +++ b/testing/Lossless_UDP_testserver.c @@ -118,27 +118,27 @@ void printconnection(int connection_id) /* receive packets and send them to the packethandler * run doLossless_UDP(); */ -void Lossless_UDP() -{ +//void Lossless_UDP() +//{ // IP_Port ip_port; // uint8_t data[MAX_UDP_PACKET_SIZE]; // uint32_t length; // while (receivepacket(&ip_port, data, &length) != -1) { - //if(rand() % 3 != 1)//add packet loss - //{ +//if(rand() % 3 != 1)//add packet loss +//{ // if (LosslessUDP_handlepacket(data, length, ip_port)) { // printpacket(data, length, ip_port); // } else { - //printconnection(0); +//printconnection(0); // printf("Received handled packet with length: %u\n", length); // } - //} +//} // } - networking_poll(); +// networking_poll(); - doLossless_UDP(); -} +//doLossless_UDP(); +//} int main(int argc, char *argv[]) @@ -161,20 +161,19 @@ int main(int argc, char *argv[]) //bind to ip 0.0.0.0:PORT IP ip; ip.i = 0; - init_networking(ip, PORT); + Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); perror("Initialization"); int connection; uint64_t timer = current_time(); - LosslessUDP_init(); - while (1) { - Lossless_UDP(); - connection = incoming_connection(); + networking_poll(ludp->net); + do_lossless_udp(ludp); + connection = incoming_connection(ludp); if (connection != -1) { - if (is_connected(connection) == 2) { + if (is_connected(ludp, connection) == 2) { printf("Received the connection.\n"); } @@ -189,11 +188,12 @@ int main(int argc, char *argv[]) while (1) { //printconnection(0); - Lossless_UDP(); + networking_poll(ludp->net); + do_lossless_udp(ludp); - if (is_connected(connection) >= 2) { - kill_connection_in(connection, 3000000); - read = read_packet(connection, buffer); + if (is_connected(ludp, connection) >= 2) { + kill_connection_in(ludp, connection, 3000000); + read = read_packet(ludp, connection, buffer); if (read != 0) { // printf("Received data.\n"); @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) } } - if (is_connected(connection) == 4) { + if (is_connected(ludp, connection) == 4) { printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); fclose(file); return 1; diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index f8685b39..c76584d7 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -48,6 +48,7 @@ #include #include #define c_sleep(x) usleep(1000*x) +#define PORT 33445 #endif @@ -106,7 +107,7 @@ int main(int argc, char *argv[]) IP_Port bootstrap_ip_port; bootstrap_ip_port.port = htons(atoi(argv[2])); bootstrap_ip_port.ip.i = inet_addr(argv[1]); - DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); + DHT_bootstrap(m->dht, bootstrap_ip_port, hex_string_to_bin(argv[3])); } else { FILE *file = fopen(argv[1], "rb"); diff --git a/testing/cmake/timer_test.cmake b/testing/cmake/timer_test.cmake deleted file mode 100644 index a5f8c5ec..00000000 --- a/testing/cmake/timer_test.cmake +++ /dev/null @@ -1,9 +0,0 @@ -cmake_minimum_required(VERSION 2.6.0) -project(timer_test C) - -set(exe_name timer_test) - -add_executable(${exe_name} - timer_test.c) - -linkCoreLibraries(${exe_name}) diff --git a/testing/nTox.c b/testing/nTox.c index 8813f305..a476cc19 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -521,12 +521,12 @@ int main(int argc, char *argv[]) exit(1); unsigned char *binary_string = hex_string_to_bin(argv[3]); - DHT_bootstrap(bootstrap_ip_port, binary_string); + DHT_bootstrap(m->dht, bootstrap_ip_port, binary_string); free(binary_string); nodelay(stdscr, TRUE); while (true) { - if (on == 0 && DHT_isconnected()) { + if (on == 0 && DHT_isconnected(m->dht)) { new_lines("[i] connected to DHT\n[i] define username with /n"); on = 1; } diff --git a/testing/timer_test.c b/testing/timer_test.c deleted file mode 100644 index f47d4878..00000000 --- a/testing/timer_test.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "../core/timer.h" -#include - -#ifdef WINDOWS -#include -#else -#include -#endif - -void mssleep(int ms) -{ -#ifdef WINDOWS - Sleep(ms); -#else - usleep(ms * 1000); -#endif -} - -int callback(timer *t, void *arg) -{ - printf("%s\n", (char *)arg); - return 1; -} - -int repeating(timer *t, void *arg) -{ - printf("%s\n", (char *)arg); - timer_start(t, 3); - return 0; -} - -extern void timer_debug_print(); - -int main(int argc, char **argv) -{ - timer_init(); - timer_debug_print(); - - timer *t = new_timer(); - timer_setup(t, &callback, "Long setup method, 4 seconds"); - timer_start(t, 4); - timer_debug_print(); - - timer_single(&repeating, (void *)"This repeats every 3 seconds", 3); - timer_debug_print(); - - timer_single(&callback, "Short method, 4 seconds", 4); - timer_debug_print(); - - timer_single(&callback, "1 second", 1); - timer_debug_print(); - - timer_single(&callback, "15 seconds", 15); - timer_debug_print(); - - timer_single(&callback, "10 seconds", 10); - timer_debug_print(); - - timer_us(&callback, "100000us", 100000); - timer_us(&callback, "13s", 13 * US_PER_SECOND); - - while (true) { - timer_poll(); - mssleep(10); - } - - return 0; -} diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c index 57404a59..c7979843 100644 --- a/testing/toxic/chat.c +++ b/testing/toxic/chat.c @@ -123,7 +123,7 @@ static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint1 status[len - 1] = '\0'; fix_name(status); - + wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); wattroff(ctx->history, COLOR_PAIR(3)); @@ -342,7 +342,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) wprintw(ctx->history, "Invalid command.\n"); } -static void chat_onDraw(ToxWindow *self) +static void chat_onDraw(ToxWindow *self, Messenger *m) { curs_set(1); int x, y; diff --git a/testing/toxic/dhtstatus.c b/testing/toxic/dhtstatus.c index a11dc616..6c9f2a80 100644 --- a/testing/toxic/dhtstatus.c +++ b/testing/toxic/dhtstatus.c @@ -34,9 +34,9 @@ static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) } } -static void dhtstatus_onDraw(ToxWindow *self) +static void dhtstatus_onDraw(ToxWindow *self, Messenger *m) { - Client_data *close_clientlist = DHT_get_close_list(); + Client_data *close_clientlist = DHT_get_close_list(m->dht); curs_set(0); werase(self->window); diff --git a/testing/toxic/friendlist.c b/testing/toxic/friendlist.c index 0a58bc54..2e46f124 100644 --- a/testing/toxic/friendlist.c +++ b/testing/toxic/friendlist.c @@ -102,7 +102,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) } } -static void friendlist_onDraw(ToxWindow *self) +static void friendlist_onDraw(ToxWindow *self, Messenger *m) { curs_set(0); werase(self->window); diff --git a/testing/toxic/main.c b/testing/toxic/main.c index 9abe8de4..e5525e94 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"); } @@ -297,7 +297,7 @@ int main(int argc, char *argv[]) strcpy(DATA_FILE, user_config_dir); strcat(DATA_FILE, CONFIGDIR); strcat(DATA_FILE, "data"); - + SRVLIST_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("DHTservers") + 1); strcpy(SRVLIST_FILE, user_config_dir); strcat(SRVLIST_FILE, CONFIGDIR); diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c index 81f00bce..e194a90e 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); } @@ -365,7 +365,9 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd) cmd[i] = '\0'; int j = i; + while (++j < MAX_STR_SIZE && isspace(cmd[j])); + i = j - 1; numargs++; @@ -460,7 +462,7 @@ static void prompt_onKey(ToxWindow *self, Messenger *m, int key) } } -static void prompt_onDraw(ToxWindow *self) +static void prompt_onDraw(ToxWindow *self, Messenger *m) { curs_set(1); int x, y; diff --git a/testing/toxic/windows.c b/testing/toxic/windows.c index c0ff3026..8fdf4e19 100644 --- a/testing/toxic/windows.c +++ b/testing/toxic/windows.c @@ -88,23 +88,25 @@ int add_window(Messenger *m, ToxWindow w) { if (LINES < 2) return -1; - + int i; - for(i = 0; i < MAX_WINDOWS_NUM; i++) { - if (windows[i].window) + + for (i = 0; i < MAX_WINDOWS_NUM; i++) { + if (windows[i].window) continue; - + w.window = newwin(LINES - 2, COLS, 0, 0); + if (w.window == NULL) return -1; windows[i] = w; w.onInit(&w, m); - - active_window = windows+i; + + active_window = windows + i; return i; } - + return -1; } @@ -113,8 +115,10 @@ void del_window(ToxWindow *w) { active_window = windows; // Go to prompt screen delwin(w->window); + if (w->x) free(w->x); + w->window = NULL; memset(w, 0, sizeof(ToxWindow)); clear(); @@ -124,19 +128,19 @@ void del_window(ToxWindow *w) /* Shows next window when tab or back-tab is pressed */ void set_next_window(int ch) { - ToxWindow *end = windows+MAX_WINDOWS_NUM-1; + ToxWindow *end = windows + MAX_WINDOWS_NUM - 1; ToxWindow *inf = active_window; - while(true) { + + while (true) { if (ch == '\t') { if (++active_window > end) active_window = windows; - } else - if (--active_window < windows) - active_window = end; - + } else if (--active_window < windows) + active_window = end; + if (active_window->window) return; - + if (active_window == inf) { // infinite loop check endwin(); exit(2); @@ -148,14 +152,14 @@ void set_active_window(int index) { if (index < 0 || index >= MAX_WINDOWS_NUM) return; - - active_window = windows+index; + + active_window = windows + index; } ToxWindow *init_windows() { int n_prompt = add_window(m, new_prompt()); - + if (n_prompt == -1 || add_window(m, new_friendlist()) == -1 || add_window(m, new_dhtstatus()) == -1) { @@ -166,7 +170,7 @@ ToxWindow *init_windows() prompt = &windows[n_prompt]; active_window = prompt; - + return prompt; } @@ -189,7 +193,7 @@ static void draw_bar() for (i = 0; i < (MAX_WINDOWS_NUM); ++i) { if (windows[i].window) { - if (windows+i == active_window) + if (windows + i == active_window) attron(A_BOLD); odd = (odd + 1) % blinkrate; @@ -197,13 +201,13 @@ static void draw_bar() if (windows[i].blink && (odd < (blinkrate / 2))) attron(COLOR_PAIR(3)); - clrtoeol(); + clrtoeol(); printw(" %s", windows[i].title); if (windows[i].blink && (odd < (blinkrate / 2))) attroff(COLOR_PAIR(3)); - if (windows+i == active_window) { + if (windows + i == active_window) { attroff(A_BOLD); } } @@ -225,7 +229,7 @@ void draw_active_window(Messenger *m) prepare_window(a->window); a->blink = false; draw_bar(); - a->onDraw(a); + a->onDraw(a, m); /* Handle input */ int ch = getch(); diff --git a/testing/toxic/windows.h b/testing/toxic/windows.h index be5557e9..86917dbe 100644 --- a/testing/toxic/windows.h +++ b/testing/toxic/windows.h @@ -24,7 +24,7 @@ typedef struct ToxWindow_ ToxWindow; struct ToxWindow_ { void(*onKey)(ToxWindow *, Messenger *, int); - void(*onDraw)(ToxWindow *); + void(*onDraw)(ToxWindow *, Messenger *); void(*onInit)(ToxWindow *, Messenger *); void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t); void(*onMessage)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t);