From 88ff81d9def5efe69cbaf91aa41906177ba7dde9 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 16 Aug 2013 13:11:09 -0400 Subject: Passed everything through astyle. --- core/DHT.c | 461 +++++++++++++++++++++++++++---------------------- core/DHT.h | 8 +- core/LAN_discovery.c | 32 ++-- core/Lossless_UDP.c | 247 +++++++++++++++----------- core/Lossless_UDP.h | 30 ++-- core/Messenger.c | 320 ++++++++++++++++++++++------------ core/Messenger.h | 56 +++--- core/friend_requests.c | 23 ++- core/friend_requests.h | 4 +- core/net_crypto.c | 131 ++++++++++---- core/net_crypto.h | 22 +-- core/network.c | 44 +++-- core/ping.c | 68 ++++---- core/ping.h | 8 +- core/timer.c | 99 ++++++----- core/timer.h | 38 ++-- core/util.c | 4 +- core/util.h | 4 +- 18 files changed, 952 insertions(+), 647 deletions(-) (limited to 'core') diff --git a/core/DHT.c b/core/DHT.c index c3249846..226a38ca 100644 --- a/core/DHT.c +++ b/core/DHT.c @@ -77,7 +77,7 @@ typedef struct { /* Symetric NAT hole punching stuff */ /* 1 if currently hole punching, otherwise 0 */ - uint8_t hole_punching; + uint8_t hole_punching; uint32_t punching_index; uint64_t punching_timestamp; uint64_t recvNATping_timestamp; @@ -98,11 +98,11 @@ typedef struct { /*----------------------------------------------------------------------------------*/ - /* Our client id/public key */ +/* 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 Friend *friends_list; static uint16_t num_friends; static Pinged send_nodes[LSEND_NODES_ARRAY]; static Node_format toping[MAX_TOPING]; @@ -111,7 +111,7 @@ static uint64_t last_toping; /*----------------------------------------------------------------------------------*/ -Client_data * DHT_get_close_list(void) +Client_data *DHT_get_close_list(void) { return close_clientlist; } @@ -121,37 +121,39 @@ Client_data * DHT_get_close_list(void) * return 1 if client_id1 is closer * return 2 if client_id2 is closer */ -static int id_closest(uint8_t * id, uint8_t * id1, uint8_t * id2) +static int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2) { size_t i; uint8_t distance1, distance2; - for(i = 0; i < CLIENT_ID_SIZE; ++i) { + for (i = 0; i < CLIENT_ID_SIZE; ++i) { distance1 = abs(id[i] ^ id1[i]); distance2 = abs(id[i] ^ id2[i]); - - if(distance1 < distance2) + + if (distance1 < distance2) return 1; - if(distance1 > distance2) + + if (distance1 > distance2) return 2; } + return 0; } static int ipport_equal(IP_Port a, IP_Port b) { - return (a.ip.i == b.ip.i) && (a.port == b.port); + return (a.ip.i == b.ip.i) && (a.port == b.port); } -static int id_equal(uint8_t* a, uint8_t* b) +static int id_equal(uint8_t *a, uint8_t *b) { - return memcmp(a, b, CLIENT_ID_SIZE) == 0; + return memcmp(a, b, CLIENT_ID_SIZE) == 0; } static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout) { - return timestamp + timeout <= time_now; + return timestamp + timeout <= time_now; } /* check if client with client_id is already in list of length length. @@ -161,18 +163,18 @@ static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout) * * TODO: maybe optimize this. */ -static int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) +static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id, IP_Port ip_port) { uint32_t i; uint64_t temp_time = unix_time(); - for(i = 0; i < length; ++i) { + for (i = 0; i < length; ++i) { /*If ip_port is assigned to a different client_id replace it*/ - if(ipport_equal(list[i].ip_port, ip_port)) { + if (ipport_equal(list[i].ip_port, ip_port)) { memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); } - if(id_equal(list[i].client_id, client_id)) { + if (id_equal(list[i].client_id, client_id)) { /* Refresh the client timestamp. */ list[i].timestamp = temp_time; list[i].ip_port.ip.i = ip_port.ip.i; @@ -180,18 +182,19 @@ static int client_in_list(Client_data * list, uint32_t length, uint8_t * client_ return 1; } } + return 0; } /* check if client with client_id is already in node format list of length length. * return True(1) or False(0) */ -static int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id) +static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *client_id) { uint32_t i; - for(i = 0; i < length; ++i) { - if(id_equal(list[i].client_id, client_id)) + for (i = 0; i < length; ++i) { + if (id_equal(list[i].client_id, client_id)) return 1; } @@ -200,12 +203,12 @@ static int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * cli /* 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(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 < num_friends; ++i) { + if (id_equal(friends_list[i].client_id, client_id)) return i; } @@ -217,7 +220,7 @@ 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(uint8_t *client_id, Node_format *nodes_list) { uint32_t i, j, k; uint64_t temp_time = unix_time(); @@ -228,13 +231,13 @@ static int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, close_clientlist[i].client_id); /* if node isn't good or is already in list. */ - if(tout || inlist) + if (tout || inlist) continue; - if(num_nodes < MAX_SENT_NODES) { + if (num_nodes < MAX_SENT_NODES) { - memcpy( nodes_list[num_nodes].client_id, - close_clientlist[i].client_id, + memcpy( nodes_list[num_nodes].client_id, + close_clientlist[i].client_id, CLIENT_ID_SIZE ); nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port; @@ -242,13 +245,14 @@ static int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) } else { - for(j = 0; j < MAX_SENT_NODES; ++j) { - closest = id_closest( client_id, - nodes_list[j].client_id, + for (j = 0; j < MAX_SENT_NODES; ++j) { + closest = id_closest( client_id, + nodes_list[j].client_id, close_clientlist[i].client_id ); - if(closest == 2) { - memcpy( nodes_list[j].client_id, - close_clientlist[i].client_id, + + if (closest == 2) { + memcpy( nodes_list[j].client_id, + close_clientlist[i].client_id, CLIENT_ID_SIZE); nodes_list[j].ip_port = close_clientlist[i].ip_port; @@ -258,35 +262,36 @@ static int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) } } - for(i = 0; i < num_friends; ++i) { - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) { + for (i = 0; i < num_friends; ++i) { + for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { tout = is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT); inlist = client_in_nodelist( nodes_list, - MAX_SENT_NODES, + MAX_SENT_NODES, friends_list[i].client_list[j].client_id); /* if node isn't good or is already in list. */ - if(tout || inlist) + if (tout || inlist) continue; - if(num_nodes < MAX_SENT_NODES) { + if (num_nodes < MAX_SENT_NODES) { - memcpy( nodes_list[num_nodes].client_id, - friends_list[i].client_list[j].client_id, + memcpy( nodes_list[num_nodes].client_id, + friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE); nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port; num_nodes++; } else { - for(k = 0; k < MAX_SENT_NODES; ++k) { + for (k = 0; k < MAX_SENT_NODES; ++k) { - closest = id_closest( client_id, - nodes_list[k].client_id, + closest = id_closest( client_id, + nodes_list[k].client_id, 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, + + if (closest == 2) { + memcpy( nodes_list[k].client_id, + friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE ); nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port; @@ -296,6 +301,7 @@ static int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) } } } + return num_nodes; } @@ -303,16 +309,17 @@ static int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) * return 0 if successful * return 1 if not (list contains no bad nodes) */ -static int replace_bad( Client_data * list, - uint32_t length, - uint8_t * client_id, - IP_Port ip_port ) +static int replace_bad( Client_data *list, + uint32_t length, + uint8_t *client_id, + IP_Port ip_port ) { uint32_t i; uint64_t temp_time = unix_time(); - for(i = 0; i < length; ++i) { + + for (i = 0; i < length; ++i) { /* if node is bad */ - if(is_timeout(temp_time, list[i].timestamp, BAD_NODE_TIMEOUT)) { + if (is_timeout(temp_time, list[i].timestamp, BAD_NODE_TIMEOUT)) { memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); list[i].ip_port = ip_port; list[i].timestamp = temp_time; @@ -325,42 +332,46 @@ static int replace_bad( Client_data * list, return 1; } -/*Sort the list. It will be sorted from furthest to closest. +/*Sort the list. It will be sorted from furthest to closest. TODO: this is innefficient and needs to be optimized.*/ static void sort_list(Client_data *list, uint32_t length, uint8_t *comp_client_id) { - if(length == 0) + if (length == 0) return; + uint32_t i, count; - while(1) { + + while (1) { count = 0; - for(i = 0; i < (length - 1); ++i) { - if(id_closest(comp_client_id, list[i].client_id, list[i + 1].client_id) == 1) { + + for (i = 0; i < (length - 1); ++i) { + if (id_closest(comp_client_id, list[i].client_id, list[i + 1].client_id) == 1) { Client_data temp = list[i + 1]; list[i + 1] = list[i]; list[i] = temp; ++count; } } - if(count == 0) + + if (count == 0) return; } } /* replace the first good node that is further to the comp_client_id than that of the client_id in the list */ -static int replace_good( Client_data * list, - uint32_t length, - uint8_t * client_id, - IP_Port ip_port, - uint8_t * comp_client_id ) +static int replace_good( Client_data *list, + uint32_t length, + uint8_t *client_id, + IP_Port ip_port, + uint8_t *comp_client_id ) { uint32_t i; uint64_t temp_time = unix_time(); sort_list(list, length, comp_client_id); - for(i = 0; i < length; ++i) - if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) { + for (i = 0; i < length; ++i) + if (id_closest(comp_client_id, list[i].client_id, client_id) == 2) { memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); list[i].ip_port = ip_port; list[i].timestamp = temp_time; @@ -373,42 +384,42 @@ static int replace_good( Client_data * list, return 1; } -/* Attempt to add client with ip_port and client_id to the friends client list - * and close_clientlist +/* 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(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. + * 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 we can't replace bad nodes we try replacing good ones */ - replace_good( close_clientlist, - LCLIENT_LIST, - client_id, - ip_port, + replace_good( close_clientlist, + LCLIENT_LIST, + client_id, + ip_port, self_public_key ); } } for (i = 0; i < num_friends; ++i) { - if (!client_in_list( friends_list[i].client_list, - MAX_FRIEND_CLIENTS, - client_id, + if (!client_in_list( friends_list[i].client_list, + MAX_FRIEND_CLIENTS, + client_id, ip_port )) { - if (replace_bad( friends_list[i].client_list, + if (replace_bad( friends_list[i].client_list, MAX_FRIEND_CLIENTS, - client_id, + client_id, ip_port )) { /* if we can't replace bad nodes we try replacing good ones. */ - replace_good( friends_list[i].client_list, - MAX_FRIEND_CLIENTS, - client_id, - ip_port, + replace_good( friends_list[i].client_list, + MAX_FRIEND_CLIENTS, + client_id, + ip_port, friends_list[i].client_id ); } } @@ -418,7 +429,7 @@ 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(IP_Port ip_port, uint8_t *client_id, uint8_t *nodeclient_id) { uint32_t i, j; uint64_t temp_time = unix_time(); @@ -458,17 +469,17 @@ static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) 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)) { + for (i = 0; i < LSEND_NODES_ARRAY; ++i ) { + if (!is_timeout(temp_time, send_nodes[i].timestamp, PING_TIMEOUT)) { pinging = 0; - if(ip_port.ip.i != 0 && ipport_equal(send_nodes[i].ip_port, ip_port)) - ++pinging; + if (ip_port.ip.i != 0 && ipport_equal(send_nodes[i].ip_port, ip_port)) + ++pinging; - if(ping_id != 0 && send_nodes[i].ping_id == ping_id) - ++pinging; + if (ping_id != 0 && send_nodes[i].ping_id == ping_id) + ++pinging; - if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) + if (pinging == (ping_id != 0) + (ip_port.ip.i != 0)) return 1; } } @@ -483,9 +494,9 @@ static uint64_t add_gettingnodes(IP_Port ip_port) uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); uint64_t temp_time = unix_time(); - 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)) { + 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; @@ -498,15 +509,15 @@ 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(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, self_public_key) || is_gettingnodes(ip_port, 0)) return 1; uint64_t ping_id = add_gettingnodes(ip_port); - if(ping_id == 0) + if (ping_id == 0) return 1; uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING]; @@ -518,14 +529,14 @@ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) memcpy(plain, &ping_id, sizeof(ping_id)); memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); - int len = encrypt_data( public_key, - self_secret_key, - nonce, - plain, - sizeof(ping_id) + CLIENT_ID_SIZE, + int len = encrypt_data( public_key, + self_secret_key, + nonce, + plain, + sizeof(ping_id) + CLIENT_ID_SIZE, encrypt ); - if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) + if (len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) return -1; data[0] = 2; @@ -537,10 +548,10 @@ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) } /* send a send nodes response */ -static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id) +static int sendnodes(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, self_public_key)) return 1; uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) @@ -549,7 +560,7 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, Node_format nodes_list[MAX_SENT_NODES]; int num_nodes = get_close_nodes(client_id, nodes_list); - if(num_nodes == 0) + if (num_nodes == 0) return 0; uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; @@ -560,14 +571,14 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, memcpy(plain, &ping_id, sizeof(ping_id)); memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); - int len = encrypt_data( public_key, - self_secret_key, - nonce, + int len = encrypt_data( public_key, + self_secret_key, + nonce, plain, - sizeof(ping_id) + num_nodes * sizeof(Node_format), + sizeof(ping_id) + num_nodes * sizeof(Node_format), encrypt ); - if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) + if (len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) return -1; data[0] = 3; @@ -578,11 +589,11 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, return sendpacket(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(IP_Port source, uint8_t *packet, uint32_t length) { uint64_t ping_id; - if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING )) return 1; @@ -592,11 +603,11 @@ static int handle_getnodes(IP_Port source, uint8_t * packet, uint32_t length) uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; - int len = decrypt_data( packet + 1, - self_secret_key, + int len = decrypt_data( packet + 1, + self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, plain ); if (len != sizeof(ping_id) + CLIENT_ID_SIZE) @@ -610,32 +621,33 @@ static int handle_getnodes(IP_Port source, uint8_t * packet, uint32_t length) return 0; } -static int handle_sendnodes(IP_Port source, uint8_t * packet, uint32_t length) +static int handle_sendnodes(IP_Port source, uint8_t *packet, uint32_t length) { uint64_t ping_id; uint32_t cid_size = 1 + CLIENT_ID_SIZE; cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || - ((length - cid_size) % sizeof(Node_format)) != 0 || - (length < cid_size + sizeof(Node_format))) + ((length - cid_size) % sizeof(Node_format)) != 0 || + (length < cid_size + sizeof(Node_format))) return 1; uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; - int len = decrypt_data( - packet + 1, - self_secret_key, - packet + 1 + CLIENT_ID_SIZE, - packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); + int len = decrypt_data( + packet + 1, + self_secret_key, + packet + 1 + CLIENT_ID_SIZE, + packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, + sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); - if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) + if (len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) return 1; memcpy(&ping_id, plain, sizeof(ping_id)); - if(!is_gettingnodes(source, ping_id)) + + if (!is_gettingnodes(source, ping_id)) return 1; Node_format nodes_list[MAX_SENT_NODES]; @@ -644,8 +656,9 @@ static int handle_sendnodes(IP_Port source, uint8_t * packet, uint32_t length) addto_lists(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); + + 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); } @@ -655,12 +668,14 @@ 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(uint8_t *client_id) { - if(friend_number(client_id) != -1) /*Is friend already in DHT?*/ + if (friend_number(client_id) != -1) /*Is friend already in DHT?*/ return 1; - Friend * temp; + + Friend *temp; temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); + if (temp == NULL) return 1; @@ -673,22 +688,24 @@ int DHT_addfriend(uint8_t * client_id) return 0; } -int DHT_delfriend(uint8_t * client_id) +int DHT_delfriend(uint8_t *client_id) { uint32_t i; - Friend * temp; + Friend *temp; + for (i = 0; i < num_friends; ++i) { /* Equal */ if (id_equal(friends_list[i].client_id, client_id)) { --num_friends; if (num_friends != i) { - memcpy( friends_list[i].client_id, - friends_list[num_friends].client_id, + memcpy( friends_list[i].client_id, + friends_list[num_friends].client_id, CLIENT_ID_SIZE ); } temp = realloc(friends_list, sizeof(Friend) * (num_friends)); + if (temp == NULL) return 1; @@ -701,7 +718,7 @@ int DHT_delfriend(uint8_t * client_id) } /* TODO: Optimize this. */ -IP_Port DHT_getfriendip(uint8_t * client_id) +IP_Port DHT_getfriendip(uint8_t *client_id) { uint32_t i, j; uint64_t temp_time = unix_time(); @@ -711,18 +728,21 @@ IP_Port DHT_getfriendip(uint8_t * client_id) /* Equal */ if (id_equal(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)) + 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; } + return empty; } } + empty.ip.i = 1; return empty; } /* Ping each client in the "friends" list every 60 seconds. Send a get nodes request - * every 20 seconds to a random good node for each "friend" in our "friends" list. + * every 20 seconds to a random good node for each "friend" in our "friends" list. */ static void doDHTFriends(void) { @@ -733,22 +753,25 @@ static void doDHTFriends(void) for (i = 0; i < 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 (!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 ); + 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 node is good. */ - if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { + if (!is_timeout(temp_time, 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 (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, @@ -775,10 +798,11 @@ static void doClose(void) /* 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 ); + send_ping_request( close_clientlist[i].ip_port, + (clientid_t *) &close_clientlist[i].client_id ); close_clientlist[i].last_pinged = temp_time; } + /* if node is good. */ if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) { index[num_nodes] = i; @@ -796,15 +820,15 @@ static void doClose(void) } } -void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key) +void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key) { getnodes(ip_port, public_key, self_public_key); } /* send the given packet to node with client_id - * returns -1 if failure + * returns -1 if failure */ -int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length) +int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length) { uint32_t i; @@ -822,17 +846,17 @@ 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(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) return -1; - Friend * friend = &friends_list[friend_num]; - Client_data * client; + Friend *friend = &friends_list[friend_num]; + Client_data *client; for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { client = &friend->client_list[i]; @@ -847,22 +871,24 @@ static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num) ++num_ips; } } + return num_ips; } /* Send the following packet to everyone who tells us they are connected to friend_id * returns the number of nodes it sent the packet to */ -int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) +int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) { int num = friend_number(friend_id); + if (num == -1) return 0; uint32_t i, sent = 0; uint64_t temp_time = unix_time(); - Friend * friend = &friends_list[num]; - Client_data * client; + Friend *friend = &friends_list[num]; + Client_data *client; for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { client = &friend->client_list[i]; @@ -874,20 +900,22 @@ int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) ++sent; } } + return sent; } /* 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(uint8_t *friend_id, uint8_t *packet, uint32_t length) { int num = friend_number(friend_id); + if (num == -1) return 0; - Friend * friend = &friends_list[num]; - Client_data * client; + Friend *friend = &friends_list[num]; + Client_data *client; IP_Port ip_list[MAX_FRIEND_CLIENTS]; int n = 0; @@ -898,15 +926,18 @@ static int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t len client = &friend->client_list[i]; /*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 (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { ip_list[n] = client->ip_port; ++n; } } + if (n < 1) return 0; + if (sendpacket(ip_list[rand() % n], packet, length) == length) return 1; + return 0; } @@ -916,21 +947,23 @@ static int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t len * 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(IP_Port *ip_portlist, uint8_t *friend_id) { uint32_t i; + for (i = 0; i < num_friends; ++i) { /* Equal */ if (id_equal(friends_list[i].client_id, friend_id)) return friend_iplist(ip_portlist, i); } + return -1; } /*----------------------------------------------------------------------------------*/ /*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/ -static int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) +static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type) { uint8_t data[sizeof(uint64_t) + 1]; uint8_t packet[MAX_DATA_SIZE]; @@ -952,20 +985,22 @@ static int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) if (num == 0) return -1; + return num; } /* 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(IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) { uint64_t ping_id; memcpy(&ping_id, packet + 1, sizeof(uint64_t)); int friendnumber = friend_number(source_pubkey); + if (friendnumber == -1) return 1; - Friend * friend = &friends_list[friendnumber]; + Friend *friend = &friends_list[friendnumber]; if (packet[0] == 0) { /* 1 is reply */ @@ -979,31 +1014,35 @@ static int handle_NATping(IP_Port source, uint8_t * source_pubkey, uint8_t * pac return 0; } } + return 1; } /* Get the most common ip in the ip_portlist * Only return ip if it appears in list min_num or more * len must not be bigger than MAX_FRIEND_CLIENTS - * return ip of 0 if failure + * return ip of 0 if failure */ -static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) +static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) { IP zero = {{0}}; - if(len > MAX_FRIEND_CLIENTS) + + if (len > MAX_FRIEND_CLIENTS) return zero; uint32_t i, j; uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; - for(i = 0; i < len; ++i) { - for(j = 0; j < len; ++j) { - if(ip_portlist[i].ip.i == ip_portlist[j].ip.i) + for (i = 0; i < len; ++i) { + for (j = 0; j < len; ++j) { + if (ip_portlist[i].ip.i == ip_portlist[j].ip.i) ++numbers[i]; } - if(numbers[i] >= min_num) + + if (numbers[i] >= min_num) return ip_portlist[i].ip; } + return zero; } @@ -1012,34 +1051,36 @@ static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) * where len is the length of ip_portlist * returns the number of ports and puts the list of ports in portlist */ -static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) +static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip) { uint32_t i; uint16_t num = 0; - for(i = 0; i < len; ++i) { - if(ip_portlist[i].ip.i == ip.i) { + for (i = 0; i < len; ++i) { + if (ip_portlist[i].ip.i == ip.i) { portlist[num] = ntohs(ip_portlist[i].port); ++num; } } + return num; } -static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num) +static void punch_holes(IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) { - if(numports > MAX_FRIEND_CLIENTS || numports == 0) + if (numports > MAX_FRIEND_CLIENTS || numports == 0) return; uint32_t i; uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; - for(i = friends_list[friend_num].punching_index; i != top; i++) { + for (i = friends_list[friend_num].punching_index; i != top; i++) { /*TODO: improve port guessing algorithm*/ - uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); + 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(pinging, (clientid_t *) &friends_list[friend_num].client_id); } + friends_list[friend_num].punching_index = i; } @@ -1053,18 +1094,20 @@ static void doNAT(void) int num = friend_iplist(ip_list, i); /*If already connected or friend is not online don't try to hole punch*/ - if (num < MAX_FRIEND_CLIENTS/2) + 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 (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) { + friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && + friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { + + IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); - IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2); if (ip.i == 0) continue; @@ -1087,14 +1130,16 @@ static void doNAT(void) and are then removed from the list. if the list is full the nodes farthest from our client_id are replaced the purpose of this list is to enable quick integration of new nodes into the - network while preventing amplification attacks. + 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) { if (ip_port.ip.i == 0) return -1; + 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); @@ -1103,6 +1148,7 @@ int add_toping(uint8_t *client_id, IP_Port ip_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); @@ -1111,6 +1157,7 @@ int add_toping(uint8_t *client_id, IP_Port ip_port) return 0; } } + return -1; } @@ -1119,13 +1166,17 @@ int add_toping(uint8_t *client_id, IP_Port ip_port) static void do_toping() { uint64_t temp_time = unix_time(); + if (!is_timeout(temp_time, last_toping, TIME_TOPING)) return; + last_toping = temp_time; uint32_t i; + for (i = 0; i < MAX_TOPING; ++i) { if (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; } @@ -1156,7 +1207,7 @@ uint32_t DHT_size(void) } /* save the DHT in data where data is an array of size DHT_size() */ -void DHT_save(uint8_t * data) +void DHT_save(uint8_t *data) { memcpy(data, close_clientlist, sizeof(close_clientlist)); memcpy(data + sizeof(close_clientlist), friends_list, sizeof(Friend) * num_friends); @@ -1164,60 +1215,64 @@ void DHT_save(uint8_t * data) /* load the DHT from data of size size; * return -1 if failure - * return 0 if success + * return 0 if success */ -int DHT_load(uint8_t * data, uint32_t size) +int DHT_load(uint8_t *data, uint32_t size) { init_ping(); - if(size < sizeof(close_clientlist)) + if (size < sizeof(close_clientlist)) return -1; - if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) + if ((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) return -1; uint32_t i, j; uint16_t temp; /* uint64_t temp_time = unix_time(); */ - Client_data * client; + Client_data *client; - temp = (size - sizeof(close_clientlist))/sizeof(Friend); + temp = (size - sizeof(close_clientlist)) / sizeof(Friend); - if(temp != 0) { - Friend * tempfriends_list = (Friend *)(data + sizeof(close_clientlist)); + if (temp != 0) { + Friend *tempfriends_list = (Friend *)(data + sizeof(close_clientlist)); - for(i = 0; i < temp; ++i) { + for (i = 0; i < temp; ++i) { DHT_addfriend(tempfriends_list[i].client_id); - for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) { + for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { client = &tempfriends_list[i].client_list[j]; - if(client->timestamp != 0) + + if (client->timestamp != 0) getnodes(client->ip_port, client->client_id, tempfriends_list[i].client_id); } } } - Client_data * tempclose_clientlist = (Client_data *)data; - for(i = 0; i < LCLIENT_LIST; ++i) { - if(tempclose_clientlist[i].timestamp != 0) - DHT_bootstrap( tempclose_clientlist[i].ip_port, + Client_data *tempclose_clientlist = (Client_data *)data; + + 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 ); } + return 0; } /* returns 0 if we are not connected to the DHT - * returns 1 if we are + * returns 1 if we are */ int DHT_isconnected(void) { 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)) + for (i = 0; i < LCLIENT_LIST; ++i) { + if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) return 1; } + return 0; } diff --git a/core/DHT.h b/core/DHT.h index c6ca4ce1..8cb0436a 100644 --- a/core/DHT.h +++ b/core/DHT.h @@ -39,13 +39,13 @@ typedef struct { IP_Port ip_port; uint64_t timestamp; uint64_t last_pinged; - + /* Returned by this node. Either our friend or us */ IP_Port ret_ip_port; uint64_t ret_timestamp; } Client_data; -Client_data * DHT_get_close_list(void); +Client_data *DHT_get_close_list(void); /* Add a new friend to the friends list client_id must be CLIENT_ID_SIZE bytes long. @@ -80,7 +80,7 @@ void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key); and are then removed from the list. if the list is full the nodes farthest from our client_id are replaced the purpose of this list is to enable quick integration of new nodes into the - network while preventing amplification attacks. + 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); @@ -123,7 +123,7 @@ int DHT_load(uint8_t *data, uint32_t size); returns 1 if we are */ int DHT_isconnected(); -void addto_lists(IP_Port ip_port, uint8_t * client_id); +void addto_lists(IP_Port ip_port, uint8_t *client_id); #ifdef __cplusplus } diff --git a/core/LAN_discovery.c b/core/LAN_discovery.c index 67dc656b..ad1337ef 100644 --- a/core/LAN_discovery.c +++ b/core/LAN_discovery.c @@ -41,7 +41,7 @@ static uint32_t get_broadcast(void) int i = 0; /* configure ifconf for the ioctl call */ - if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("[!] get_broadcast: socket() error"); return 0; } @@ -51,15 +51,16 @@ static uint32_t get_broadcast(void) ifconf.ifc_buf = (char *)i_faces; ifconf.ifc_len = sizeof(i_faces); count = ifconf.ifc_len / sizeof(struct ifreq); - if(ioctl(sock, SIOCGIFCONF, &ifconf) < 0) { + + if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) { perror("get_broadcast: ioctl() error"); return 0; } - for(i = 0; i < count; i++) { + for (i = 0; i < count; i++) { /* skip the loopback interface, as it's useless */ - if(strcmp(i_faces[i].ifr_name, "lo") != 0) { - if(ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) { + if (strcmp(i_faces[i].ifr_name, "lo") != 0) { + if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) { perror("[!] get_broadcast: ioctl error"); return 0; } @@ -69,8 +70,10 @@ static uint32_t get_broadcast(void) break; } } + close(sock); - if(sock_holder == NULL) { + + if (sock_holder == NULL) { perror("[!] no broadcast device found"); return 0; } @@ -83,14 +86,16 @@ static uint32_t get_broadcast(void) static IP broadcast_ip(void) { IP ip; - #ifdef __linux +#ifdef __linux ip.i = get_broadcast(); - if(ip.i == 0) + + if (ip.i == 0) /* error errored, but try anyway? */ ip.i = ~0; - #else + +#else ip.i = ~0; - #endif +#endif return ip; } @@ -100,14 +105,19 @@ static int LAN_ip(IP ip) { if (ip.c[0] == 127)/* Loopback */ return 0; + if (ip.c[0] == 10)/* 10.0.0.0 to 10.255.255.255 range */ return 0; + if (ip.c[0] == 172 && ip.c[1] >= 16 && ip.c[1] <= 31)/* 172.16.0.0 to 172.31.255.255 range */ return 0; + if (ip.c[0] == 192 && ip.c[1] == 168) /* 192.168.0.0 to 192.168.255.255 range */ return 0; + if (ip.c[0] == 169 && ip.c[1] == 254 && ip.c[2] != 0 && ip.c[2] != 255)/* 169.254.1.0 to 169.254.254.255 range */ return 0; + return -1; } @@ -115,8 +125,10 @@ static int handle_LANdiscovery(IP_Port source, uint8_t *packet, uint32_t length) { if (LAN_ip(source.ip) == -1) return 1; + if (length != crypto_box_PUBLICKEYBYTES + 1) return 1; + DHT_bootstrap(source, packet + 1); return 0; } diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c index 002e2cf8..fa5f9144 100644 --- a/core/Lossless_UDP.c +++ b/core/Lossless_UDP.c @@ -21,7 +21,7 @@ * */ -/* +/* * TODO: clean this file a bit. * There are a couple of useless variables to get rid of. */ @@ -59,9 +59,9 @@ typedef struct { */ 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. + * 2 if incoming_connection() has not returned it yet, 1 if it has. */ uint8_t inbound; @@ -81,31 +81,31 @@ typedef struct { uint32_t handshake_id2; /* number of data packets received (also used as handshake_id1) */ - uint32_t recv_packetnum; + 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; + uint32_t sent_packetnum; /* number of packets sent by the other peer. */ - uint32_t osent_packetnum; + 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; + uint32_t successful_sent; /* packet number of last packet read with the read_packet function */ - uint32_t successful_read; + uint32_t successful_read; /* list of currently requested packet numbers(by the other person) */ - uint32_t req_packets[BUFFER_PACKET_NUM]; + uint32_t req_packets[BUFFER_PACKET_NUM]; /* total number of currently requested packets(by the other person) */ - uint16_t num_req_paquets; + uint16_t num_req_paquets; uint8_t recv_counter; uint8_t send_counter; @@ -113,7 +113,7 @@ typedef struct { } Connection; -static Connection * connections; +static Connection *connections; static uint32_t connections_length; /* Length of connections array */ static uint32_t connections_number; /* Number of connections in connections array */ @@ -122,7 +122,7 @@ static uint32_t connections_number; /* Number of connections in connections arra /* Functions */ -/* +/* * Get connection id from IP_Port * Return -1 if there are no connections like we are looking for * Return id if it found it @@ -130,10 +130,11 @@ static uint32_t connections_number; /* Number of connections in connections arra int getconnection_id(IP_Port ip_port) { uint32_t i; + for (i = 0; i < MAX_CONNECTIONS; ++i) { if (connections[i].ip_port.ip.i == ip_port.ip.i && - connections[i].ip_port.port == ip_port.port && - connections[i].status > 0) + connections[i].ip_port.port == ip_port.port && + connections[i].status > 0) return i; } @@ -143,7 +144,7 @@ int getconnection_id(IP_Port ip_port) /* table of random numbers used below. */ static uint32_t randtable[6][256]; -/* +/* * Generate a handshake_id which depends on the ip_port. * This function will always give one unique handshake_id per ip_port. * @@ -152,18 +153,21 @@ static uint32_t randtable[6][256]; static uint32_t handshake_id(IP_Port source) { uint32_t id = 0, i; + for (i = 0; i < 6; ++i) { - if(randtable[i][((uint8_t *)&source)[i]] == 0) + if (randtable[i][((uint8_t *)&source)[i]] == 0) randtable[i][((uint8_t *)&source)[i]] = random_int(); + id ^= randtable[i][((uint8_t *)&source)[i]]; } + if (id == 0) /* id can't be zero */ id = 1; return id; } -/* +/* * Change the hanshake id associated with that ip_port * * TODO: make this better @@ -174,7 +178,7 @@ static void change_handshake(IP_Port source) randtable[rand][((uint8_t *)&source)[rand]] = random_int(); } -/* +/* * Initialize a new connection to ip_port * Returns an integer corresponding to the connection idt * Return -1 if it could not initialize the connectiont @@ -183,53 +187,56 @@ static void change_handshake(IP_Port source) int new_connection(IP_Port ip_port) { int connect = getconnection_id(ip_port); + if (connect != -1) return connect; - - if(connections_number == connections_length) { - Connection * temp; + + if (connections_number == connections_length) { + Connection *temp; temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); - if(temp == NULL) + if (temp == NULL) return -1; memset(&temp[connections_length], 0, sizeof(Connection)); ++connections_length; connections = temp; } - + uint32_t i; + for (i = 0; i < MAX_CONNECTIONS; ++i) { - if(connections[i].status == 0) { + if (connections[i].status == 0) { memset(&connections[i], 0, sizeof(Connection)); uint32_t handshake_id1 = handshake_id(ip_port); connections[i] = (Connection) { - .ip_port = ip_port, - .status = 1, - .inbound = 0, - .handshake_id1 = handshake_id1, - .sent_packetnum = handshake_id1, - .sendbuff_packetnum = handshake_id1, - .successful_sent = handshake_id1, - .SYNC_rate = SYNC_RATE, - .data_rate = DATA_SYNC_RATE, - .last_recvSYNC = current_time(), - .last_sent = current_time(), - .killat = ~0, - .send_counter = 0, - /* add randomness to timeout to prevent connections getting stuck in a loop. */ - .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT + .ip_port = ip_port, + .status = 1, + .inbound = 0, + .handshake_id1 = handshake_id1, + .sent_packetnum = handshake_id1, + .sendbuff_packetnum = handshake_id1, + .successful_sent = handshake_id1, + .SYNC_rate = SYNC_RATE, + .data_rate = DATA_SYNC_RATE, + .last_recvSYNC = current_time(), + .last_sent = current_time(), + .killat = ~0, + .send_counter = 0, + /* add randomness to timeout to prevent connections getting stuck in a loop. */ + .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT }; ++connections_number; return i; } } + return -1; } -/* +/* * Initialize a new inbound connection from ip_port * Returns an integer corresponding to the connection id. * Return -1 if it could not initialize the connection. @@ -238,55 +245,58 @@ static int new_inconnection(IP_Port ip_port) { if (getconnection_id(ip_port) != -1) return -1; - - if(connections_number == connections_length) { - Connection * temp; + + if (connections_number == connections_length) { + Connection *temp; temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); - if(temp == NULL) + if (temp == NULL) return -1; memset(&temp[connections_length], 0, sizeof(Connection)); ++connections_length; connections = temp; } - + uint32_t i; + for (i = 0; i < MAX_CONNECTIONS; ++i) { if (connections[i].status == 0) { memset(&connections[i], 0, sizeof(Connection)); uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; - connections[i] = (Connection){ + connections[i] = (Connection) { .ip_port = ip_port, - .status = 2, - .inbound = 2, - .SYNC_rate = SYNC_RATE, - .data_rate = DATA_SYNC_RATE, - .last_recvSYNC = current_time(), - .last_sent = current_time(), - .send_counter = 127, - - /* add randomness to timeout to prevent connections getting stuck in a loop. */ - .timeout = timeout, - - /* if this connection isn't handled within the timeout kill it. */ - .killat = current_time() + 1000000UL*timeout + .status = 2, + .inbound = 2, + .SYNC_rate = SYNC_RATE, + .data_rate = DATA_SYNC_RATE, + .last_recvSYNC = current_time(), + .last_sent = current_time(), + .send_counter = 127, + + /* add randomness to timeout to prevent connections getting stuck in a loop. */ + .timeout = timeout, + + /* if this connection isn't handled within the timeout kill it. */ + .killat = current_time() + 1000000UL * timeout }; ++connections_number; return i; } } + return -1; } -/* +/* * 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) { uint32_t i; + for (i = 0; i < MAX_CONNECTIONS; ++i) { if (connections[i].inbound == 2) { connections[i].inbound = 1; @@ -301,23 +311,25 @@ int incoming_connection(void) static void free_connections(void) { uint32_t i; - for(i = connections_length; i != 0; --i) + + for (i = connections_length; i != 0; --i) if (connections[i - 1].status != 0) break; - if(connections_length == i) + if (connections_length == i) return; - Connection * temp; + Connection *temp; temp = realloc(connections, sizeof(Connection) * i); - if(temp == NULL && i != 0) + + if (temp == NULL && i != 0) return; connections = temp; connections_length = i; } -/* +/* * Return -1 if it could not kill the connection. * Return 0 if killed successfully */ @@ -332,10 +344,11 @@ int kill_connection(int connection_id) return 0; } } + return -1; } -/* +/* * Kill connection in seconds. * Return -1 if it can not kill the connection. * Return 0 if it will kill it. @@ -344,14 +357,15 @@ int kill_connection_in(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; + connections[connection_id].killat = current_time() + 1000000UL * seconds; return 0; } } + return -1; } -/* +/* * Check if connection is connected: * Return 0 no. * Return 1 if attempting handshake. @@ -363,6 +377,7 @@ int is_connected(int connection_id) { if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) return connections[connection_id].status; + return 0; } @@ -371,6 +386,7 @@ IP_Port connection_ip(int connection_id) { if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) return connections[connection_id].ip_port; + IP_Port zero = {{{0}}, 0}; return zero; } @@ -380,6 +396,7 @@ uint32_t sendqueue(int connection_id) { if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) return 0; + return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent; } @@ -388,6 +405,7 @@ uint32_t recvqueue(int connection_id) { if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) return 0; + return connections[connection_id].recv_packetnum - connections[connection_id].successful_read; } @@ -406,7 +424,7 @@ char id_packet(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(int connection_id, uint8_t *data) { if (recvqueue(connection_id) != 0) { uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; @@ -416,14 +434,15 @@ int read_packet(int connection_id, uint8_t * data) connections[connection_id].recvbuffer[index].size = 0; return size; } + return 0; } -/* +/* * 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(int connection_id, uint8_t *data, uint32_t length) { if (length > MAX_DATA_SIZE || length == 0) return 0; @@ -440,31 +459,31 @@ 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(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(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) { + if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) { temp = htonl(i); memcpy(requested + number, &temp, 4); ++number; } } - - if(number == 0) + + if (number == 0) connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; return number; } -/* +/* * BEGIN Packet sending functions * One per packet type. * see http://wiki.tox.im/index.php/Lossless_UDP for more information. @@ -486,7 +505,7 @@ static int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t hand static int send_SYNC(uint32_t connection_id) { - uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; + uint8_t packet[(BUFFER_PACKET_NUM * 4 + 4 + 4 + 2)]; uint16_t index = 0; IP_Port ip_port = connections[connection_id].ip_port; @@ -507,7 +526,7 @@ 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(ip_port, packet, (number * 4 + 4 + 4 + 2)); } @@ -530,6 +549,7 @@ static int send_DATA(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--; @@ -537,15 +557,17 @@ static int send_DATA(uint32_t connection_id) memcpy(connections[connection_id].req_packets, buffer, connections[connection_id].num_req_paquets * 4); return ret; } + if (connections[connection_id].sendbuff_packetnum != connections[connection_id].sent_packetnum) { ret = send_data_packet(connection_id, connections[connection_id].sent_packetnum); connections[connection_id].sent_packetnum++; return ret; } + return 0; } -/* +/* * END of packet sending functions * * @@ -555,7 +577,7 @@ 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(IP_Port source, uint8_t *packet, uint32_t length) { if (length != (1 + 4 + 4)) return 1; @@ -573,11 +595,12 @@ static int handle_handshake(IP_Port source, uint8_t * packet, uint32_t length) send_handshake(source, handshake_id(source), handshake_id1); return 0; } + if (is_connected(connection) != 1) return 1; /* if handshake_id2 is what we sent previously as handshake_id1 */ - if (handshake_id2 == connections[connection].handshake_id1) { + if (handshake_id2 == connections[connection].handshake_id1) { connections[connection].status = 2; /* NOTE: is this necessary? connections[connection].handshake_id2 = handshake_id1; */ @@ -595,9 +618,11 @@ static int SYNC_valid(uint32_t length) { if (length < 4 + 4 + 2) return 0; - if (length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) || - ((length - 4 - 4 - 2) % 4) != 0) + + if (length > (BUFFER_PACKET_NUM * 4 + 4 + 4 + 2) || + ((length - 4 - 4 - 2) % 4) != 0) return 0; + return 1; } @@ -606,6 +631,7 @@ static int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_p { if (handshake_id(source) == recv_packetnum) { int x = new_inconnection(source); + if (x != -1) { connections[x].orecv_packetnum = recv_packetnum; connections[x].sent_packetnum = recv_packetnum; @@ -618,6 +644,7 @@ static int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_p return x; } } + return -1; } @@ -632,11 +659,13 @@ static int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packet send_SYNC(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, uint32_t * req_packets, - uint16_t number) +static int handle_SYNC3(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 ); uint32_t i, temp; @@ -646,9 +675,9 @@ static int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packet uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum); /* packet valid */ - if (comp_1 <= BUFFER_PACKET_NUM && - comp_2 <= BUFFER_PACKET_NUM && - comp_counter < 10 && comp_counter != 0) { + 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; @@ -666,6 +695,7 @@ static int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packet connections[connection_id].num_req_paquets = number; return 0; } + return 1; } @@ -680,12 +710,12 @@ static int handle_SYNC(IP_Port source, uint8_t *packet, uint32_t length) uint32_t temp; uint32_t recv_packetnum, sent_packetnum; uint32_t req_packets[BUFFER_PACKET_NUM]; - uint16_t number = (length - 4 - 4 - 2)/ 4; + uint16_t number = (length - 4 - 4 - 2) / 4; memcpy(&counter, packet + 1, 1); memcpy(&temp, packet + 2, 4); recv_packetnum = ntohl(temp); - memcpy(&temp,packet + 6, 4); + memcpy(&temp, packet + 6, 4); sent_packetnum = ntohl(temp); if (number != 0) @@ -695,17 +725,18 @@ static int handle_SYNC(IP_Port source, uint8_t *packet, uint32_t length) return handle_SYNC1(source, recv_packetnum, sent_packetnum); if (connections[connection].status == 2) - return handle_SYNC2(connection, counter, + return handle_SYNC2(connection, counter, recv_packetnum, sent_packetnum); if (connections[connection].status == 3) - return handle_SYNC3(connection, counter, recv_packetnum, + return handle_SYNC3(connection, counter, recv_packetnum, sent_packetnum, req_packets, number); + return 0; } -/* - * Add a packet to the received buffer and set the recv_packetnum of the +/* + * 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) @@ -766,8 +797,8 @@ static int handle_data(IP_Port source, uint8_t *packet, uint32_t length) return add_recv(connection, number, packet + 5, size); } -/* - * END of packet handling functions +/* + * END of packet handling functions */ void LosslessUDP_init(void) @@ -785,17 +816,18 @@ static void doNew(void) { 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) { + if ((connections[i].last_sent + (1000000UL / connections[i].SYNC_rate)) <= temp_time) { send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0); connections[i].last_sent = temp_time; } /* kill all timed out connections */ - if (connections[i].status > 0 && - (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && - connections[i].status != 4) { + if (connections[i].status > 0 && + (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && + connections[i].status != 4) { connections[i].status = 4; /* kill_connection(i); */ } @@ -809,9 +841,10 @@ static void doSYNC(void) { 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) { + if ((connections[i].last_SYNC + (1000000UL / connections[i].SYNC_rate)) <= temp_time) { send_SYNC(i); connections[i].last_SYNC = temp_time; } @@ -823,18 +856,20 @@ static void doData(void) 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)) + if ((connections[i].last_sent + (1000000UL / connections[i].data_rate)) <= temp_time) { + for (j = connections[i].last_sent; j < temp_time; j += (1000000UL / connections[i].data_rate)) send_DATA(i); + connections[i].last_sent = temp_time; } } #define MAX_SYNC_RATE 10 -/* +/* * Automatically adjusts send rates of packets for optimal transmission. * * TODO: flow control. @@ -843,9 +878,11 @@ static void adjustRates(void) { 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; + if (connections[i].status == 3) { if (sendqueue(i) != 0) { connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE; diff --git a/core/Lossless_UDP.h b/core/Lossless_UDP.h index 53afe606..bd426ee0 100644 --- a/core/Lossless_UDP.h +++ b/core/Lossless_UDP.h @@ -33,7 +33,7 @@ extern "C" { /* maximum length of the data in the data packets */ #define MAX_DATA_SIZE 1024 -/* +/* * Initialize a new connection to ip_port * Returns an integer corresponding to the connection id. * Return -1 if it could not initialize the connection. @@ -41,51 +41,51 @@ extern "C" { */ int new_connection(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); -/* +/* * 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); -/* +/* * Return -1 if it could not kill the connection. * Return 0 if killed successfully */ int kill_connection(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); -/* +/* * Returns the ip_port of the corresponding connection. * Return 0 if there is no such connection. */ IP_Port connection_ip(int connection_id); -/* - * Returns the id of the next packet in the queue - * Return -1 if no packet in queue +/* + * Returns the id of the next packet in the queue + * Return -1 if no packet in queue */ char id_packet(int connection_id); -/* +/* * Return 0 if there is no received data in the buffer. - * Return length of received packet if successful + * Return length of received packet if successful */ int read_packet(int connection_id, uint8_t *data); -/* +/* * Return 0 if data could not be put in packet queue * Return 1 if data was put into the queue */ @@ -94,8 +94,8 @@ int write_packet(int connection_id, uint8_t *data, uint32_t length); /* Returns the number of packets in the queue waiting to be successfully sent. */ uint32_t sendqueue(int connection_id); -/* - * returns the number of packets in the queue waiting to be successfully +/* + * returns the number of packets in the queue waiting to be successfully * read with read_packet(...) */ uint32_t recvqueue(int connection_id); @@ -112,7 +112,7 @@ int is_connected(int connection_id); /* Call this function a couple times per second It's the main loop. */ void doLossless_UDP(void); -/* +/* * This function sets up LosslessUDP packet handling. */ void LosslessUDP_init(void); diff --git a/core/Messenger.c b/core/Messenger.c index 4ed8bc41..09032067 100644 --- a/core/Messenger.c +++ b/core/Messenger.c @@ -35,11 +35,14 @@ static int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_i /* set the size of the friend list to numfriends return -1 if realloc fails */ -int realloc_friendlist(Messenger *m, uint32_t num) { - Friend *newfriendlist = realloc(m->friendlist, num*sizeof(Friend)); +int realloc_friendlist(Messenger *m, uint32_t num) +{ + Friend *newfriendlist = realloc(m->friendlist, num * sizeof(Friend)); + if (newfriendlist == NULL) return -1; - memset(&newfriendlist[num-1], 0, sizeof(Friend)); + + memset(&newfriendlist[num - 1], 0, sizeof(Friend)); m->friendlist = newfriendlist; return 0; } @@ -85,8 +88,10 @@ static uint16_t address_checksum(uint8_t *address, uint32_t len) uint8_t checksum[2] = {0}; uint16_t check; uint32_t i; - for(i = 0; i < len; ++i) + + for (i = 0; i < len; ++i) checksum[i % 2] ^= address[i]; + memcpy(&check, checksum, sizeof(check)); return check; } @@ -125,25 +130,33 @@ void getaddress(Messenger *m, uint8_t *address) int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) { if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES - + crypto_box_ZEROBYTES)) + - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + + crypto_box_ZEROBYTES)) return FAERR_TOOLONG; + uint8_t client_id[crypto_box_PUBLICKEYBYTES]; memcpy(client_id, address, crypto_box_PUBLICKEYBYTES); uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); memcpy(&check, address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), sizeof(check)); + if (check != checksum) return FAERR_BADCHECKSUM; + if (length < 1) return FAERR_NOMESSAGE; + if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) return FAERR_OWNKEY; + int friend_id = getfriend_id(m, client_id); + if (friend_id != -1) { uint32_t nospam; memcpy(&nospam, address + crypto_box_PUBLICKEYBYTES, sizeof(nospam)); - if(m->friendlist[friend_id].friendrequest_nospam == nospam) + + if (m->friendlist[friend_id].friendrequest_nospam == nospam) return FAERR_ALREADYSENT; + m->friendlist[friend_id].friendrequest_nospam = nospam; return FAERR_SETNEWNOSPAM; } @@ -153,6 +166,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) return FAERR_NOMEM; uint32_t i; + for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { DHT_addfriend(client_id); @@ -173,10 +187,11 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) return i; } } + return FAERR_UNKNOWN; } -int m_addfriend_norequest(Messenger *m, uint8_t * client_id) +int m_addfriend_norequest(Messenger *m, uint8_t *client_id) { if (getfriend_id(m, client_id) != -1) return -1; @@ -186,8 +201,9 @@ int m_addfriend_norequest(Messenger *m, uint8_t * client_id) return FAERR_NOMEM; uint32_t i; + for (i = 0; i <= m->numfriends; ++i) { - if(m->friendlist[i].status == NOFRIEND) { + if (m->friendlist[i].status == NOFRIEND) { DHT_addfriend(client_id); m->friendlist[i].status = FRIEND_REQUESTED; m->friendlist[i].crypt_connection_id = -1; @@ -202,6 +218,7 @@ int m_addfriend_norequest(Messenger *m, uint8_t * client_id) return i; } } + return -1; } @@ -220,9 +237,10 @@ int m_delfriend(Messenger *m, int friendnumber) uint32_t i; for (i = m->numfriends; i != 0; --i) { - if (m->friendlist[i-1].status != NOFRIEND) + if (m->friendlist[i - 1].status != NOFRIEND) break; } + m->numfriends = i; if (realloc_friendlist(m, m->numfriends + 1) != 0) @@ -240,6 +258,7 @@ int m_friendstatus(Messenger *m, int friendnumber) { if (friendnumber < 0 || friendnumber >= m->numfriends) return NOFRIEND; + return m->friendlist[friendnumber].status; } @@ -250,10 +269,13 @@ uint32_t m_sendmessage(Messenger *m, int friendnumber, uint8_t *message, uint32_ { if (friendnumber < 0 || friendnumber >= m->numfriends) return 0; + uint32_t msgid = ++m->friendlist[friendnumber].message_id; + if (msgid == 0) msgid = 1; /* otherwise, false error */ - if(m_sendmessage_withid(m, friendnumber, msgid, message, length)) { + + if (m_sendmessage_withid(m, friendnumber, msgid, message, length)) { return msgid; } @@ -264,6 +286,7 @@ uint32_t m_sendmessage_withid(Messenger *m, int friendnumber, uint32_t theid, ui { if (length >= (MAX_DATA_SIZE - sizeof(theid))) return 0; + uint8_t temp[MAX_DATA_SIZE]; theid = htonl(theid); memcpy(temp, &theid, sizeof(theid)); @@ -281,20 +304,22 @@ int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t lengt /* send a name packet to friendnumber length is the length with the NULL terminator*/ -static int m_sendname(Messenger *m, int friendnumber, uint8_t * name, uint16_t length) +static int m_sendname(Messenger *m, int friendnumber, uint8_t *name, uint16_t length) { - if(length > MAX_NAME_LENGTH || length == 0) + if (length > MAX_NAME_LENGTH || length == 0) return 0; + return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length); } /* set the name of a friend return 0 if success return -1 if failure */ -static int setfriendname(Messenger *m, int friendnumber, uint8_t * name) +static int setfriendname(Messenger *m, int friendnumber, uint8_t *name) { if (friendnumber >= m->numfriends || friendnumber < 0) return -1; + memcpy(m->friendlist[friendnumber].name, name, MAX_NAME_LENGTH); return 0; } @@ -305,15 +330,18 @@ static int setfriendname(Messenger *m, int friendnumber, uint8_t * name) length is the length of name with the NULL terminator return 0 if success return -1 if failure */ -int setname(Messenger *m, uint8_t * name, uint16_t length) +int setname(Messenger *m, uint8_t *name, uint16_t length) { if (length > MAX_NAME_LENGTH || length == 0) return -1; + memcpy(m->name, name, length); m->name_length = length; uint32_t i; + for (i = 0; i < m->numfriends; ++i) m->friendlist[i].name_sent = 0; + return 0; } @@ -340,10 +368,11 @@ uint16_t getself_name(Messenger *m, uint8_t *name, uint16_t nlen) name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. return 0 if success return -1 if failure */ -int getname(Messenger *m, int friendnumber, uint8_t * name) +int getname(Messenger *m, int friendnumber, uint8_t *name) { if (friendnumber >= m->numfriends || friendnumber < 0) return -1; + memcpy(name, m->friendlist[friendnumber].name, MAX_NAME_LENGTH); return 0; } @@ -352,12 +381,15 @@ int m_set_statusmessage(Messenger *m, uint8_t *status, uint16_t length) { if (length > MAX_STATUSMESSAGE_LENGTH) return -1; + memcpy(m->statusmessage, status, length); m->statusmessage_length = length; uint32_t i; + for (i = 0; i < m->numfriends; ++i) m->friendlist[i].statusmessage_sent = 0; + return 0; } @@ -366,10 +398,13 @@ int m_set_userstatus(Messenger *m, USERSTATUS status) if (status >= USERSTATUS_INVALID) { return -1; } + m->userstatus = status; uint32_t i; + for (i = 0; i < m->numfriends; ++i) m->friendlist[i].userstatus_sent = 0; + return 0; } @@ -379,21 +414,23 @@ int m_get_statusmessage_size(Messenger *m, int friendnumber) { if (friendnumber >= m->numfriends || friendnumber < 0) return -1; + return m->friendlist[friendnumber].statusmessage_length; } /* copy the user status of friendnumber into buf, truncating if needed to maxlen bytes, use m_get_statusmessage_size to find out how much you need to allocate */ -int m_copy_statusmessage(Messenger *m, int friendnumber, uint8_t * buf, uint32_t maxlen) +int m_copy_statusmessage(Messenger *m, int friendnumber, uint8_t *buf, uint32_t maxlen) { if (friendnumber >= m->numfriends || friendnumber < 0) return -1; + memset(buf, 0, maxlen); memcpy(buf, m->friendlist[friendnumber].statusmessage, MIN(maxlen, MAX_STATUSMESSAGE_LENGTH) - 1); return 0; } -int m_copy_self_statusmessage(Messenger *m, uint8_t * buf, uint32_t maxlen) +int m_copy_self_statusmessage(Messenger *m, uint8_t *buf, uint32_t maxlen) { memset(buf, 0, maxlen); memcpy(buf, m->statusmessage, MIN(maxlen, MAX_STATUSMESSAGE_LENGTH) - 1); @@ -404,10 +441,13 @@ USERSTATUS m_get_userstatus(Messenger *m, int friendnumber) { if (friendnumber >= m->numfriends || friendnumber < 0) return USERSTATUS_INVALID; + USERSTATUS status = m->friendlist[friendnumber].userstatus; + if (status >= USERSTATUS_INVALID) { status = USERSTATUS_NONE; } + return status; } @@ -416,7 +456,7 @@ USERSTATUS m_get_self_userstatus(Messenger *m) return m->userstatus; } -static int send_statusmessage(Messenger *m, int friendnumber, uint8_t * status, uint16_t length) +static int send_statusmessage(Messenger *m, int friendnumber, uint8_t *status, uint16_t length) { return write_cryptpacket_id(m, friendnumber, PACKET_ID_STATUSMESSAGE, status, length); } @@ -427,10 +467,11 @@ static int send_userstatus(Messenger *m, int friendnumber, USERSTATUS status) return write_cryptpacket_id(m, friendnumber, PACKET_ID_USERSTATUS, &stat, sizeof(stat)); } -static int set_friend_statusmessage(Messenger *m, int friendnumber, uint8_t * status, uint16_t length) +static int set_friend_statusmessage(Messenger *m, int friendnumber, uint8_t *status, uint16_t length) { if (friendnumber >= m->numfriends || friendnumber < 0) return -1; + uint8_t *newstatus = calloc(length, 1); memcpy(newstatus, status, length); free(m->friendlist[friendnumber].statusmessage); @@ -449,56 +490,61 @@ void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno) { if (yesno != 0 || yesno != 1) return; + if (friendnumber >= m->numfriends || friendnumber < 0) return; + m->friendlist[friendnumber].receives_read_receipts = yesno; } /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); */ /* 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) +void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata) { callback_friendrequest(function, userdata); } /* set the function that will be executed when a message from a friend is received. */ -void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata) +void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), + void *userdata) { m->friend_message = function; m->friend_message_userdata = userdata; } -void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata) +void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), void *userdata) { m->friend_action = function; m->friend_action_userdata = userdata; } -void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata) +void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), + void *userdata) { m->friend_namechange = function; m->friend_namechange_userdata = userdata; } -void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata) +void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), + void *userdata) { m->friend_statusmessagechange = function; m->friend_statuschange_userdata = userdata; } -void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void*), void* userdata) +void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void *), void *userdata) { m->friend_userstatuschange = function; m->friend_userstatuschange_userdata = userdata; } -void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void*), void* userdata) +void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void *), void *userdata) { m->read_receipt = function; m->read_receipt_userdata = userdata; } -void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void*), void* userdata) +void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void *), void *userdata) { m->friend_connectionstatuschange = function; m->friend_connectionstatuschange_userdata = userdata; @@ -508,10 +554,13 @@ static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_ { if (!m->friend_connectionstatuschange) return; + if (status == NOFRIEND) return; + const uint8_t was_connected = m->friendlist[friendnumber].status == FRIEND_ONLINE; const uint8_t is_connected = status == FRIEND_ONLINE; + if (is_connected != was_connected) m->friend_connectionstatuschange(m, friendnumber, is_connected, m->friend_connectionstatuschange_userdata); } @@ -526,8 +575,10 @@ int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint { if (friendnumber < 0 || friendnumber >= m->numfriends) return 0; + if (length >= MAX_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) return 0; + uint8_t packet[length + 1]; packet[0] = packet_id; memcpy(packet + 1, data, length); @@ -541,7 +592,7 @@ int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint #define PORT 33445 /*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/ -int LANdiscovery(timer* t, void* arg) +int LANdiscovery(timer *t, void *arg) { send_LANdiscovery(htons(PORT)); timer_start(t, LAN_DISCOVERY_INTERVAL); @@ -549,19 +600,20 @@ int LANdiscovery(timer* t, void* arg) } /* run this at startup */ -Messenger * initMessenger(void) +Messenger *initMessenger(void) { Messenger *m = calloc(1, sizeof(Messenger)); - if( ! m ) + + if ( ! m ) return 0; new_keys(); - m_set_statusmessage(m, (uint8_t*)"Online", sizeof("Online")); + m_set_statusmessage(m, (uint8_t *)"Online", sizeof("Online")); initNetCrypto(); IP ip; ip.i = 0; - if(init_networking(ip,PORT) == -1) + if (init_networking(ip, PORT) == -1) return 0; DHT_init(); @@ -576,7 +628,8 @@ Messenger * initMessenger(void) } /* run this before closing shop */ -void cleanupMessenger(Messenger *m){ +void cleanupMessenger(Messenger *m) +{ /* FIXME TODO ideally cleanupMessenger will mirror initMessenger * this requires the other modules to expose cleanup functions */ @@ -591,117 +644,155 @@ void doFriends(Messenger *m) uint32_t i; int len; uint8_t temp[MAX_DATA_SIZE]; + 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, m->friendlist[i].info_size); + int fr = send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, + m->friendlist[i].info_size); + if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */ set_friend_status(m, i, FRIEND_REQUESTED); else if (fr > 0) set_friend_status(m, i, FRIEND_REQUESTED); } - if (m->friendlist[i].status == FRIEND_REQUESTED || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */ + + if (m->friendlist[i].status == FRIEND_REQUESTED + || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */ if (m->friendlist[i].status == FRIEND_REQUESTED) { if (m->friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/ - send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, m->friendlist[i].info_size); + send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, + m->friendlist[i].info_size); m->friendlist[i].friend_request_id = unix_time(); } } + IP_Port friendip = DHT_getfriendip(m->friendlist[i].client_id); + switch (is_cryptoconnected(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); - break; - case 3: /* Connection is established */ - set_friend_status(m, i, FRIEND_ONLINE); - m->friendlist[i].name_sent = 0; - m->friendlist[i].userstatus_sent = 0; - m->friendlist[i].statusmessage_sent = 0; - break; - case 4: - crypto_kill(m->friendlist[i].crypt_connection_id); - m->friendlist[i].crypt_connection_id = -1; - break; - default: - break; + case 0: + if (friendip.ip.i > 1) + m->friendlist[i].crypt_connection_id = crypto_connect(m->friendlist[i].client_id, friendip); + + break; + + case 3: /* Connection is established */ + set_friend_status(m, i, FRIEND_ONLINE); + m->friendlist[i].name_sent = 0; + m->friendlist[i].userstatus_sent = 0; + m->friendlist[i].statusmessage_sent = 0; + break; + + case 4: + crypto_kill(m->friendlist[i].crypt_connection_id); + m->friendlist[i].crypt_connection_id = -1; + break; + + default: + break; } } + while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online */ if (m->friendlist[i].name_sent == 0) { if (m_sendname(m, i, m->name, m->name_length)) m->friendlist[i].name_sent = 1; } + if (m->friendlist[i].statusmessage_sent == 0) { if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) m->friendlist[i].statusmessage_sent = 1; } + if (m->friendlist[i].userstatus_sent == 0) { if (send_userstatus(m, i, m->userstatus)) m->friendlist[i].userstatus_sent = 1; } + len = read_cryptpacket(m->friendlist[i].crypt_connection_id, temp); uint8_t packet_id = temp[0]; - uint8_t* data = temp + 1; + uint8_t *data = temp + 1; int data_length = len - 1; + if (len > 0) { switch (packet_id) { - case PACKET_ID_NICKNAME: { - if (data_length >= MAX_NAME_LENGTH || data_length == 0) + case PACKET_ID_NICKNAME: { + if (data_length >= MAX_NAME_LENGTH || data_length == 0) + break; + + if (m->friend_namechange) + m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata); + + memcpy(m->friendlist[i].name, data, data_length); + m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */ break; - if(m->friend_namechange) - m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata); - memcpy(m->friendlist[i].name, data, data_length); - m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */ - break; - } - case PACKET_ID_STATUSMESSAGE: { - if (data_length == 0) + } + + case PACKET_ID_STATUSMESSAGE: { + if (data_length == 0) + break; + + uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1); + memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); + + if (m->friend_statusmessagechange) + m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH), + m->friend_statuschange_userdata); + + set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); + free(status); break; - uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1); - memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); - if (m->friend_statusmessagechange) - m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH), - m->friend_statuschange_userdata); - set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); - free(status); - break; - } - case PACKET_ID_USERSTATUS: { - if (data_length != 1) + } + + case PACKET_ID_USERSTATUS: { + if (data_length != 1) + break; + + USERSTATUS status = data[0]; + + if (m->friend_userstatuschange) + m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); + + set_friend_userstatus(m, i, status); break; - USERSTATUS status = data[0]; - if (m->friend_userstatuschange) - m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); - set_friend_userstatus(m, i, status); - break; - } - case PACKET_ID_MESSAGE: { - uint8_t *message_id = data; - uint8_t message_id_length = 4; - uint8_t *message = data + message_id_length; - uint16_t message_length = data_length - message_id_length; - if (m->friendlist[i].receives_read_receipts) { - write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); } - if (m->friend_message) - (*m->friend_message)(m, i, message, message_length, m->friend_message_userdata); - break; - } - case PACKET_ID_ACTION: { - if (m->friend_action) - (*m->friend_action)(m, i, data, data_length, m->friend_action_userdata); - break; - } - case PACKET_ID_RECEIPT: { - uint32_t msgid; - if (data_length < sizeof(msgid)) + + case PACKET_ID_MESSAGE: { + uint8_t *message_id = data; + uint8_t message_id_length = 4; + uint8_t *message = data + message_id_length; + uint16_t message_length = data_length - message_id_length; + + if (m->friendlist[i].receives_read_receipts) { + write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); + } + + if (m->friend_message) + (*m->friend_message)(m, i, message, message_length, m->friend_message_userdata); + break; - memcpy(&msgid, data, sizeof(msgid)); - msgid = ntohl(msgid); - if (m->read_receipt) - (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); - break; - } + } + + case PACKET_ID_ACTION: { + if (m->friend_action) + (*m->friend_action)(m, i, data, data_length, m->friend_action_userdata); + + break; + } + + case PACKET_ID_RECEIPT: { + uint32_t msgid; + + if (data_length < sizeof(msgid)) + break; + + memcpy(&msgid, data, sizeof(msgid)); + msgid = ntohl(msgid); + + if (m->read_receipt) + (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); + + break; + } } } else { if (is_cryptoconnected(m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ @@ -709,6 +800,7 @@ void doFriends(Messenger *m) m->friendlist[i].crypt_connection_id = -1; set_friend_status(m, i, FRIEND_CONFIRMED); } + break; } } @@ -721,8 +813,10 @@ void doInbound(Messenger *m) uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t session_key[crypto_box_PUBLICKEYBYTES]; int inconnection = crypto_inbound(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); m->friendlist[friend_id].crypt_connection_id = @@ -775,12 +869,14 @@ void Messenger_save(Messenger *m, uint8_t *data) } /* load the messenger from data of size length. */ -int Messenger_load(Messenger *m, uint8_t * data, uint32_t length) +int Messenger_load(Messenger *m, uint8_t *data, uint32_t length) { if (length == ~0) return -1; + if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3) return -1; + length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3; load_keys(data); data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; @@ -794,23 +890,28 @@ int Messenger_load(Messenger *m, uint8_t * data, uint32_t length) if (length < size) return -1; + length -= size; + if (DHT_load(data, size) == -1) return -1; + data += size; memcpy(&size, data, sizeof(size)); data += sizeof(size); + if (length != size || length % sizeof(Friend) != 0) return -1; - Friend * temp = malloc(size); + Friend *temp = malloc(size); memcpy(temp, data, size); uint16_t num = size / sizeof(Friend); uint32_t i; + for (i = 0; i < num; ++i) { - if(temp[i].status >= 3) { + if (temp[i].status >= 3) { int fnum = m_addfriend_norequest(m, temp[i].client_id); setfriendname(m, fnum, temp[i].name); /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ @@ -824,6 +925,7 @@ int Messenger_load(Messenger *m, uint8_t * data, uint32_t length) m_addfriend(m, address, temp[i].info, temp[i].info_size); } } + free(temp); return 0; } diff --git a/core/Messenger.h b/core/Messenger.h index e12b3fc8..cd9e6e63 100644 --- a/core/Messenger.h +++ b/core/Messenger.h @@ -76,7 +76,8 @@ typedef enum { USERSTATUS_AWAY, USERSTATUS_BUSY, USERSTATUS_INVALID -} USERSTATUS; +} +USERSTATUS; typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; @@ -111,22 +112,22 @@ typedef struct Messenger { Friend *friendlist; uint32_t numfriends; - 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*); - void* friend_action_userdata; - void (*friend_namechange)(struct Messenger *m, int, uint8_t *, uint16_t, void*); - void* friend_namechange_userdata; - void (*friend_statusmessagechange)(struct Messenger *m, int, uint8_t *, uint16_t, void*); - void* friend_statusmessagechange_userdata; - void (*friend_userstatuschange)(struct Messenger *m, int, USERSTATUS, void*); - void* friend_userstatuschange_userdata; - void (*read_receipt)(struct Messenger *m, int, uint32_t, void*); - void* read_receipt_userdata; - void (*friend_statuschange)(struct Messenger *m, int, uint8_t, void*); - void* friend_statuschange_userdata; - void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void*); - void* friend_connectionstatuschange_userdata; + 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 *); + void *friend_action_userdata; + void (*friend_namechange)(struct Messenger *m, int, uint8_t *, uint16_t, void *); + void *friend_namechange_userdata; + void (*friend_statusmessagechange)(struct Messenger *m, int, uint8_t *, uint16_t, void *); + void *friend_statusmessagechange_userdata; + void (*friend_userstatuschange)(struct Messenger *m, int, USERSTATUS, void *); + void *friend_userstatuschange_userdata; + void (*read_receipt)(struct Messenger *m, int, uint32_t, void *); + void *read_receipt_userdata; + void (*friend_statuschange)(struct Messenger *m, int, uint8_t, void *); + void *friend_statuschange_userdata; + void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void *); + void *friend_connectionstatuschange_userdata; } Messenger; @@ -255,29 +256,32 @@ void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno); /* set the function that will be executed when a friend request is received. function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ -void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void*), void* userdata); +void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata); /* set the function that will be executed when a message from a friend is received. function format is: function(int friendnumber, uint8_t * message, uint32_t length) */ -void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata); +void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), + void *userdata); /* set the function that will be executed when an action from a friend is received. function format is: function(int friendnumber, uint8_t * action, uint32_t length) */ -void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata); +void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), void *userdata); /* set the callback for name changes function(int friendnumber, uint8_t *newname, uint16_t length) you are not responsible for freeing newname */ -void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata); +void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), + void *userdata); /* set the callback for status message changes function(int friendnumber, uint8_t *newstatus, uint16_t length) you are not responsible for freeing newstatus */ -void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata); +void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void *), + void *userdata); /* set the callback for status type changes function(int friendnumber, USERSTATUS kind) */ -void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void*), void* userdata); +void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void *), void *userdata); /* set the callback for read receipts function(int friendnumber, uint32_t receipt) @@ -286,7 +290,7 @@ void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USE has been received on the other side. since core doesn't track ids for you, receipt may not correspond to any message in that case, you should discard it. */ -void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void*), void* userdata); +void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void *), void *userdata); /* set the callback for connection status changes function(int friendnumber, uint8_t status) @@ -296,12 +300,12 @@ void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, u note that this callback is not called when adding friends, thus the "after being previously online" part. it's assumed that when adding friends, their connection status is offline. */ -void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void*), void* userdata); +void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void *), void *userdata); /* run this at startup * returns allocated instance of Messenger on success * returns 0 if there are problems */ -Messenger * initMessenger(void); +Messenger *initMessenger(void); /* run this before closing shop * free all datastructures */ diff --git a/core/friend_requests.c b/core/friend_requests.c index 00beaa14..3708f154 100644 --- a/core/friend_requests.c +++ b/core/friend_requests.c @@ -31,16 +31,17 @@ uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; 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(uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) { - if(length + sizeof(nospam_num) > MAX_DATA_SIZE) + if (length + sizeof(nospam_num) > MAX_DATA_SIZE) return -1; uint8_t temp[MAX_DATA_SIZE]; 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), 32); /* 32 is friend request packet id */ + int len = create_request(packet, public_key, temp, length + sizeof(nospam_num), + 32); /* 32 is friend request packet id */ if (len == -1) return -1; @@ -53,6 +54,7 @@ int send_friendrequest(uint8_t * public_key, uint32_t nospam_num, uint8_t * data if (ip_port.ip.i != 0) { if (sendpacket(ip_port, packet, len) != -1) return 0; + return -1; } @@ -78,11 +80,11 @@ uint32_t get_nospam() return nospam; } -static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t, void*); +static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t, void *); static uint8_t handle_friendrequest_isset = 0; -static void* handle_friendrequest_userdata; +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(void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata) { handle_friendrequest = function; handle_friendrequest_isset = 1; @@ -99,7 +101,7 @@ 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(uint8_t *client_id) { if (received_requests_index >= MAX_RECEIVED_STORED) received_requests_index = 0; @@ -110,7 +112,7 @@ static void addto_receivedlist(uint8_t * client_id) /* 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(uint8_t *client_id) { uint32_t i; @@ -123,14 +125,17 @@ 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(IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) { if (handle_friendrequest_isset == 0) return 1; + if (length <= sizeof(nospam)) return 1; + if (request_received(source_pubkey)) return 1; + if (memcmp(packet, &nospam, sizeof(nospam)) != 0) return 1; diff --git a/core/friend_requests.h b/core/friend_requests.h index 0b75fd60..3ce0df8c 100644 --- a/core/friend_requests.h +++ b/core/friend_requests.h @@ -33,7 +33,7 @@ extern "C" { /* 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(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 */ @@ -42,7 +42,7 @@ uint32_t get_nospam(); /* 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(void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata); /* sets up friendreq packet handlers */ void friendreq_init(void); diff --git a/core/net_crypto.c b/core/net_crypto.c index a05208ef..4b7fa043 100644 --- a/core/net_crypto.c +++ b/core/net_crypto.c @@ -65,14 +65,16 @@ uint8_t crypto_iszero(uint8_t *mem, uint32_t length) { uint8_t check = 0; uint32_t i; + for (i = 0; i < length; ++i) { check |= mem[i]; } + return check; // We return zero if mem is made out of zeroes. } /* Precomputes the shared key from their public_key and our secret_key. - This way we can avoid an expensive elliptic curve scalar multiply for each + This way we can avoid an expensive elliptic curve scalar multiply for each encrypt/decrypt operation. enc_key has to be crypto_box_BEFORENMBYTES bytes long. */ void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key) @@ -81,7 +83,7 @@ void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_k } /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ -int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, +int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted) { if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0) @@ -94,7 +96,7 @@ int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, enc_key); - if(crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) + if (crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) return -1; /* unpad the encrypted message */ @@ -118,9 +120,9 @@ int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, nonce, enc_key) == -1) return -1; - /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero + /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero apparently memcmp should not be used so we do this instead:*/ - if(crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) + if (crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) return -1; /* unpad the plain message */ @@ -148,9 +150,11 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, static void increment_nonce(uint8_t *nonce) { uint32_t i; + for (i = 0; i < crypto_box_NONCEBYTES; ++i) { ++nonce[i]; - if(nonce[i] != 0) + + if (nonce[i] != 0) break; } } @@ -159,6 +163,7 @@ static void increment_nonce(uint8_t *nonce) void random_nonce(uint8_t *nonce) { uint32_t i, temp; + for (i = 0; i < crypto_box_NONCEBYTES / 4; ++i) { temp = random_int(); memcpy(nonce + 4 * i, &temp, 4); @@ -172,21 +177,28 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data) { if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) return 0; + if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) return 0; + uint8_t temp_data[MAX_DATA_SIZE]; int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data); + if (length == 0) return 0; + if (temp_data[0] != 3) return -1; + int len = decrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, - crypto_connections[crypt_connection_id].recv_nonce, + 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); return len; } + return -1; } @@ -196,19 +208,26 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length) { if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) return 0; + if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) return 0; + if (crypto_connections[crypt_connection_id].status != 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, + crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); + if (len == -1) return 0; + temp_data[0] = 3; + if (write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) return 0; + increment_nonce(crypto_connections[crypt_connection_id].sent_nonce); return 1; } @@ -223,6 +242,7 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t { if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING) return -1; + uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t temp[MAX_DATA_SIZE]; memcpy(temp + 1, data, length); @@ -230,8 +250,10 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t random_nonce(nonce); int len = encrypt_data(public_key, self_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); @@ -248,16 +270,19 @@ static int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *request_i { 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) { + length <= MAX_DATA_SIZE + ENCRYPTION_PADDING && + memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t temp[MAX_DATA_SIZE]; memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); - int len1 = decrypt_data(public_key, self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, + int len1 = decrypt_data(public_key, self_secret_key, nonce, + packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); - if(len1 == -1 || len1 == 0) + + if (len1 == -1 || len1 == 0) return -1; + request_id[0] = temp[0]; --len1; memcpy(data, temp + 1, len1); @@ -273,27 +298,32 @@ void cryptopacket_registerhandler(uint8_t byte, cryptopacket_handler_callback cb cryptopackethandlers[byte] = cb; } -static int cryptopacket_handle(IP_Port source, uint8_t * packet, uint32_t length) +static int cryptopacket_handle(IP_Port source, uint8_t *packet, uint32_t length) { if (packet[0] == 32) { if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || - length > MAX_DATA_SIZE + ENCRYPTION_PADDING) + length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; + if (memcmp(packet + 1, 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); + if (len == -1 || len == 0) return 1; + if (!cryptopackethandlers[number]) return 1; + cryptopackethandlers[number](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(packet + 1, packet, length) == length) return 0; } } + return 1; } @@ -312,8 +342,10 @@ static int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t int len = encrypt_data(public_key, self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); + if (len == -1) return 0; + temp_data[0] = 2; memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); @@ -324,15 +356,18 @@ static int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t return 1 if successful return 0 if failure */ static int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key, uint8_t *data, uint16_t length) + uint8_t *session_key, uint8_t *data, uint16_t length) { int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); + if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES - + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) { + + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) { return 0; } + if (data[0] != 2) return 0; + uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); @@ -355,11 +390,13 @@ static int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce, static int getcryptconnection_id(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) return i; } + return -1; } @@ -370,16 +407,21 @@ int crypto_connect(uint8_t *public_key, IP_Port ip_port) { uint32_t i; int id = getcryptconnection_id(public_key); + if (id != -1) { IP_Port c_ip = connection_ip(crypto_connections[id].number); - if(c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port) + + if (c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port) return -1; } + for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { if (crypto_connections[i].status == CONN_NO_CONNECTION) { int id = new_connection(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); @@ -391,9 +433,11 @@ int crypto_connect(uint8_t *public_key, IP_Port ip_port) increment_nonce(crypto_connections[i].recv_nonce); return i; } + return -1; /* this should never happen. */ } } + return -1; } @@ -407,6 +451,7 @@ int crypto_connect(uint8_t *public_key, IP_Port ip_port) int crypto_inbound(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) { @@ -414,9 +459,11 @@ int crypto_inbound(uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_ incoming_connections[i] = -1; continue; } + if (id_packet(incoming_connections[i]) == 2) { uint8_t temp_data[MAX_DATA_SIZE]; uint16_t len = read_packet(incoming_connections[i], temp_data); + if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) { int connection_id = incoming_connections[i]; incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */ @@ -425,6 +472,7 @@ int crypto_inbound(uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_ } } } + return -1; } @@ -435,13 +483,15 @@ int crypto_kill(int crypt_connection_id) { if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) return 1; + if (crypto_connections[crypt_connection_id].status != 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)); + memset(&crypto_connections[crypt_connection_id], 0 , sizeof(Crypto_Connection)); crypto_connections[crypt_connection_id].number = ~0; return 0; } + return 1; } @@ -451,15 +501,17 @@ int crypto_kill(int crypt_connection_id) int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) { uint32_t i; + if (connection_id == -1) return -1; + /* if(getcryptconnection_id(public_key) != -1) { return -1; }*/ for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { - if(crypto_connections[i].status == CONN_NO_CONNECTION) { + 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); @@ -474,17 +526,19 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre crypto_connections[i].sessionpublic_key) == 1) { increment_nonce(crypto_connections[i].recv_nonce); uint32_t zero = 0; - encrypt_precompute(crypto_connections[i].peersessionpublic_key, - crypto_connections[i].sessionsecret_key, + 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. */ return i; } + return -1; /* this should never happen. */ } } + return -1; } @@ -495,6 +549,7 @@ int is_cryptoconnected(int crypt_connection_id) { if (crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS) return crypto_connections[crypt_connection_id].status; + return CONN_NO_CONNECTION; } @@ -502,7 +557,7 @@ int is_cryptoconnected(int crypt_connection_id) Only call this function the first time the program starts. */ void new_keys(void) { - crypto_box_keypair(self_public_key,self_secret_key); + crypto_box_keypair(self_public_key, self_secret_key); } /* save the public and private keys to the keys array @@ -528,12 +583,14 @@ void load_keys(uint8_t *keys) static int new_incoming(int id) { uint32_t i; + for (i = 0; i < MAX_INCOMING; ++i) { if (incoming_connections[i] == -1) { incoming_connections[i] = id; return 0; } } + return 1; } @@ -542,9 +599,11 @@ static int new_incoming(int id) static void handle_incomings(void) { int income; + while (1) { income = incoming_connection(); - if(income == -1 || new_incoming(income) ) + + if (income == -1 || new_incoming(income) ) break; } } @@ -553,6 +612,7 @@ static void handle_incomings(void) static void receive_crypto(void) { uint32_t i; + for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { if (crypto_connections[i].status == CONN_HANDSHAKE_SENT) { uint8_t temp_data[MAX_DATA_SIZE]; @@ -560,19 +620,22 @@ static void receive_crypto(void) uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t session_key[crypto_box_PUBLICKEYBYTES]; uint16_t len; + if (id_packet(crypto_connections[i].number) == 1) /* if the packet is a friend request drop it (because we are already friends) */ len = read_packet(crypto_connections[i].number, temp_data); + if (id_packet(crypto_connections[i].number) == 2) { /* handle handshake packet. */ len = read_packet(crypto_connections[i].number, temp_data); + if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) { if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { 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); uint32_t zero = 0; - encrypt_precompute(crypto_connections[i].peersessionpublic_key, - crypto_connections[i].sessionsecret_key, + 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)); @@ -583,6 +646,7 @@ static void receive_crypto(void) crypto_kill(crypto_connections[i].number); } + if (crypto_connections[i].status == CONN_NOT_CONFIRMED) { if (id_packet(crypto_connections[i].number) == 3) { uint8_t temp_data[MAX_DATA_SIZE]; @@ -592,10 +656,11 @@ static void receive_crypto(void) crypto_connections[i].sessionsecret_key, crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); uint32_t zero = 0; + if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { increment_nonce(crypto_connections[i].recv_nonce); - encrypt_precompute(crypto_connections[i].peersessionpublic_key, - crypto_connections[i].sessionsecret_key, + encrypt_precompute(crypto_connections[i].peersessionpublic_key, + crypto_connections[i].sessionsecret_key, crypto_connections[i].shared_key); crypto_connections[i].status = CONN_ESTABLISHED; @@ -603,7 +668,7 @@ static void receive_crypto(void) kill_connection_in(crypto_connections[i].number, 3000000); } else crypto_kill(crypto_connections[i].number); // This should not happen kill the connection if it does - } else if(id_packet(crypto_connections[i].number) != -1) + } else if (id_packet(crypto_connections[i].number) != -1) /* This should not happen kill the connection if it does */ crypto_kill(crypto_connections[i].number); @@ -615,10 +680,11 @@ static void receive_crypto(void) sets all the global connection variables to their default values. */ void initNetCrypto(void) { - memset(crypto_connections, 0 ,sizeof(crypto_connections)); - memset(incoming_connections, -1 ,sizeof(incoming_connections)); + memset(crypto_connections, 0 , sizeof(crypto_connections)); + memset(incoming_connections, -1 , sizeof(incoming_connections)); networking_registerhandler(32, &cryptopacket_handle); uint32_t i; + for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) crypto_connections[i].number = ~0; } @@ -626,6 +692,7 @@ void initNetCrypto(void) static void killTimedout(void) { 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; diff --git a/core/net_crypto.h b/core/net_crypto.h index 570b9373..742d9fdc 100644 --- a/core/net_crypto.h +++ b/core/net_crypto.h @@ -38,14 +38,14 @@ extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) /* returns zero if the buffer contains only zeros */ -uint8_t crypto_iszero(uint8_t* buffer, uint32_t blen); +uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); /* encrypts plain of length length to encrypted of length + 16 using the public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce return -1 if there was a problem. return length of encrypted data if everything was fine. */ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, - uint8_t *plain, uint32_t length, uint8_t *encrypted); + uint8_t *plain, uint32_t length, uint8_t *encrypted); /* decrypts encrypted of length length to plain of length length - 16 using the @@ -53,15 +53,15 @@ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, return -1 if there was a problem(decryption failed) return length of plain data if everything was fine. */ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, - uint8_t *encrypted, uint32_t length, uint8_t *plain); + uint8_t *encrypted, uint32_t length, uint8_t *plain); -/* Fast encrypt/decrypt operations. Use if this is not a one-time communication. +/* Fast encrypt/decrypt operations. Use if this is not a one-time communication. encrypt_precompute does the shared-key generation once so it does not have to be preformed on every encrypt/decrypt. */ void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key); /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ -int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, +int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted); /* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ @@ -87,10 +87,10 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length); 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 *packet, uint8_t *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); +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); @@ -111,12 +111,12 @@ 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(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(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. @@ -130,11 +130,11 @@ void new_keys(void); /* 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(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(uint8_t *keys); /* run this to (re)initialize net_crypto sets all the global connection variables to their default values. */ diff --git a/core/network.c b/core/network.c index 7e3b344a..1977ce38 100644 --- a/core/network.c +++ b/core/network.c @@ -32,14 +32,14 @@ uint64_t current_time(void) FILETIME ft; GetSystemTimeAsFileTime(&ft); time = ft.dwHighDateTime; - time <<=32; + time <<= 32; time |= ft.dwLowDateTime; time -= 116444736000000000UL; - return time/10; + return time / 10; #else struct timeval a; gettimeofday(&a, NULL); - time = 1000000UL*a.tv_sec + a.tv_usec; + time = 1000000UL * a.tv_sec + a.tv_usec; return time; #endif } @@ -61,17 +61,17 @@ 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(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)); + return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); } /* Function to receive data, ip and port of sender is put into ip_port 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(IP_Port *ip_port, uint8_t *data, uint32_t *length) { ADDR addr; #ifdef WIN32 @@ -79,8 +79,9 @@ static int receivepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length) #else uint32_t addrlen = sizeof(addr); #endif - (*(int32_t*)length) = recvfrom(sock,(char*) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr*)&addr, &addrlen); - if (*(int32_t*)length <= 0) + (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); + + if (*(int32_t *)length <= 0) return -1; /* nothing received or empty packet */ ip_port->ip = addr.ip; @@ -100,11 +101,12 @@ void networking_poll() IP_Port ip_port; uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; - - while (receivepacket(&ip_port, data, &length) != -1) - { + + while (receivepacket(&ip_port, data, &length) != -1) { if (length < 1) continue; + if (!packethandlers[data[0]]) continue; + packethandlers[data[0]](ip_port, data, length); } } @@ -119,8 +121,10 @@ int init_networking(IP ip, uint16_t port) { #ifdef WIN32 WSADATA wsaData; - if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) + + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) return -1; + #else srandom((uint32_t)current_time()); #endif @@ -131,11 +135,15 @@ int init_networking(IP ip, uint16_t port) /* Check for socket error */ #ifdef WIN32 + if (sock == INVALID_SOCKET) /* MSDN recommends this */ return -1; + #else + if (sock < 0) return -1; + #endif /* Functions to increase the size of the send and receive UDP buffers @@ -153,7 +161,7 @@ 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(sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); /* Set socket nonblocking */ #ifdef WIN32 @@ -167,7 +175,7 @@ int init_networking(IP ip, uint16_t port) /* Bind our socket to port PORT and address 0.0.0.0 */ ADDR addr = {AF_INET, htons(port), ip}; - bind(sock, (struct sockaddr*)&addr, sizeof(addr)); + bind(sock, (struct sockaddr *)&addr, sizeof(addr)); return 0; } @@ -207,18 +215,18 @@ uint32_t resolve_addr(const char *address) rc = getaddrinfo(address, "echo", &hints, &server); // Lookup failed. - if(rc != 0) { + if (rc != 0) { return 0; } // IPv4 records only.. - if(server->ai_family != AF_INET) { + if (server->ai_family != AF_INET) { freeaddrinfo(server); return 0; } - - addr = ((struct sockaddr_in*)server->ai_addr)->sin_addr.s_addr; + + addr = ((struct sockaddr_in *)server->ai_addr)->sin_addr.s_addr; freeaddrinfo(server); return addr; diff --git a/core/ping.c b/core/ping.c index ee05d9fa..47d6e163 100644 --- a/core/ping.c +++ b/core/ping.c @@ -26,7 +26,7 @@ typedef struct { static pinged_t pings[PING_NUM_MAX]; static size_t num_pings; static size_t pos_pings; -static clientid_t* self_id = (clientid_t*) &self_public_key; +static clientid_t *self_id = (clientid_t *) &self_public_key; extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; // DHT.c @@ -48,10 +48,10 @@ static void remove_timeouts() // O(n) size_t new_num = num_pings; // Loop through buffer, oldest first - for (i=0; iclient_id, + rc = decrypt_data((uint8_t *) &p->client_id, self_secret_key, - (uint8_t*) &p->nonce, - (uint8_t*) &p->ping_id, + (uint8_t *) &p->nonce, + (uint8_t *) &p->ping_id, sizeof(ping_id) + ENCRYPTION_PADDING, - (uint8_t*) &ping_id); + (uint8_t *) &ping_id); if (rc != sizeof(ping_id)) return 1; // Send response send_ping_response(source, &p->client_id, ping_id); - add_toping((uint8_t*) &p->client_id, source); + add_toping((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(IP_Port source, uint8_t *packet, uint32_t length) { - pingres_t* p = (pingres_t*) packet; + pingres_t *p = (pingres_t *) packet; int rc; uint64_t ping_id; @@ -200,21 +200,21 @@ int handle_ping_response(IP_Port source, uint8_t* packet, uint32_t length) return 1; // Decrypt ping_id - rc = decrypt_data((uint8_t*) &p->client_id, + rc = decrypt_data((uint8_t *) &p->client_id, self_secret_key, - (uint8_t*) &p->nonce, - (uint8_t*) &p->ping_id, + (uint8_t *) &p->nonce, + (uint8_t *) &p->ping_id, sizeof(ping_id) + ENCRYPTION_PADDING, - (uint8_t*) &ping_id); + (uint8_t *) &ping_id); if (rc != sizeof(ping_id)) return 1; // Make sure ping_id is correct - if(!is_pinging(source, ping_id)) + if (!is_pinging(source, ping_id)) return 1; // Associate source ip with client_id - addto_lists(source, (uint8_t*) &p->client_id); + addto_lists(source, (uint8_t *) &p->client_id); return 0; } diff --git a/core/ping.h b/core/ping.h index 1ccfabac..0c44874b 100644 --- a/core/ping.h +++ b/core/ping.h @@ -10,7 +10,7 @@ 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); +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); diff --git a/core/timer.c b/core/timer.c index 06e25693..29190921 100644 --- a/core/timer.c +++ b/core/timer.c @@ -4,7 +4,7 @@ #include "timer.h" #include "network.h" -/* +/* A nested linked list increases efficiency of insertions. Depending on the number of timers we have, we might need to have nested linked lists in order to improve insertion efficiency. @@ -46,35 +46,37 @@ enum timer_state { STATE_CALLBACK }; -struct timer -{ +struct timer { enum timer_state state; - timer* _prev; - timer* _next; + timer *_prev; + timer *_next; timer_callback cb; - void* userdata; + void *userdata; uint64_t deadline; }; -static timer* timer_main_queue; -static timer* timer_us_queue; /* hi-speed queue */ +static timer *timer_main_queue; +static timer *timer_us_queue; /* hi-speed queue */ -inline static void timer_dequeue(timer* t, timer** queue) +inline static void timer_dequeue(timer *t, timer **queue) { if (t->state == STATE_INACTIVE) return; /* not in a queue */ - + if (t->_prev) { t->_prev->_next = t->_next; } else { *queue = t->_next; } + if (t->_next) t->_next->_prev = t->_prev; + t->state = STATE_INACTIVE; } -static void timer_enqueue(timer* t, timer** queue, timer* prev) +static void timer_enqueue(timer *t, timer **queue, timer *prev) { t->state = STATE_ACTIVE; + while (true) { if (!*queue) { t->_next = 0; @@ -104,22 +106,24 @@ void timer_init() } /* Do not depend on fields being zeroed */ -static timer* timer_pool; /* timer_pool is SINGLY LINKED!! */ +static timer *timer_pool; /* timer_pool is SINGLY LINKED!! */ -timer* new_timer(void) +timer *new_timer(void) { - timer* ret; + timer *ret; + if (timer_pool) { ret = timer_pool; timer_pool = timer_pool->_next; } else { ret = calloc(1, sizeof(struct timer)); } + ret->state = STATE_INACTIVE; return ret; } -void delete_timer(timer* t) +void delete_timer(timer *t) { timer_dequeue(t, &timer_main_queue); t->_next = timer_pool; @@ -127,93 +131,99 @@ void delete_timer(timer* t) timer_pool = t; } -void timer_setup(timer* t, timer_callback cb, void* userarg) +void timer_setup(timer *t, timer_callback cb, void *userarg) { t->cb = cb; t->userdata = userarg; } -void* timer_get_userdata(timer* t) +void *timer_get_userdata(timer *t) { return t->userdata; } -static void timer_delay_us(timer* t, int us) +static void timer_delay_us(timer *t, int us) { t->deadline += us; - timer** queue = t->_prev ? &(t->_prev->_next) : &timer_main_queue; + timer **queue = t->_prev ? &(t->_prev->_next) : &timer_main_queue; timer_dequeue(t, &timer_main_queue); timer_enqueue(t, queue, t->_prev); } -/* Starts the timer so that it's called in sec seconds in the future. +/* Starts the timer so that it's called in sec seconds in the future. * A non-positive value of sec results in the callback being called immediately. - * This function may be called again after a timer has been started to adjust + * This function may be called again after a timer has been started to adjust * the expiry time. */ -void timer_start(timer* t, int sec) +void timer_start(timer *t, int sec) { uint64_t newdeadline = current_time() + sec * US_PER_SECOND; - if (timer_is_active(t)){ + + if (timer_is_active(t)) { if (t->deadline < newdeadline) { timer_delay_us(t, newdeadline - t->deadline); return; } + timer_dequeue(t, &timer_main_queue); } + t->deadline = newdeadline; timer_enqueue(t, &timer_main_queue, 0); } /* Stops the timer. Returns -1 if the timer was not active. */ -int timer_stop(timer* t) +int timer_stop(timer *t) { int ret = timer_is_active(t) ? -1 : 0; timer_dequeue(t, &timer_main_queue); return ret; } -/* Adds additionalsec seconds to the timer. +/* Adds additionalsec seconds to the timer. * Returns -1 and does nothing if the timer was not active. */ -int timer_delay(timer* t, int additonalsec) +int timer_delay(timer *t, int additonalsec) { if (!timer_is_active(t)) return -1; + timer_delay_us(t, additonalsec * US_PER_SECOND); return 0; } -static uint64_t timer_diff(timer* t, uint64_t time) +static uint64_t timer_diff(timer *t, uint64_t time) { if (t->deadline <= time) return 0; + return time - t->deadline; } /* Returns the time remaining on a timer in seconds. * Returns -1 if the timer is not active. * Returns 0 if the timer has expired and will be called upon the next call to timer_poll. */ -int timer_time_remaining(timer* t) +int timer_time_remaining(timer *t) { if (!timer_is_active(t)) return -1; + return timer_diff(t, current_time()) / US_PER_SECOND; } -bool timer_is_active(timer* t) +bool timer_is_active(timer *t) { return t->state != STATE_INACTIVE; } /* Single-use timer. * Creates a new timer, preforms setup and starts it. */ -void timer_single(timer_callback cb, void* userarg, int sec) +void timer_single(timer_callback cb, void *userarg, int sec) { - timer* t = new_timer(); + timer *t = new_timer(); timer_setup(t, cb, userarg); timer_start(t, sec); } /* Single-use microsecond timer. */ -void timer_us(timer_callback cb, void* userarg, int us) +void timer_us(timer_callback cb, void *userarg, int us) { - timer* t = new_timer(); + timer *t = new_timer(); timer_setup(t, cb, userarg); t->deadline = current_time() + us; t->state = STATE_ACTIVE; @@ -228,26 +238,30 @@ void timer_poll(void) /* Handle millisecond timers */ while (timer_us_queue) { if (timer_diff(timer_us_queue, time) != 0) break; - timer* t = timer_us_queue; + + timer *t = timer_us_queue; timer_dequeue(t, &timer_us_queue); t->cb(0, t->userdata); delete_timer(t); } - if (time - prevtime > US_PER_SECOND || prevtime == 0 || prevtime > time) { + if (time - prevtime > US_PER_SECOND || prevtime == 0 || prevtime > time) { /* time moving backwards is just a sanity check */ prevtime = time; - + while (timer_main_queue) { if (timer_diff(timer_main_queue, time) != 0) break; - timer* t = timer_main_queue; + + timer *t = timer_main_queue; t->state = STATE_CALLBACK; int rv = t->cb(t, t->userdata); + if (rv != 0) { timer_dequeue(t, &timer_main_queue); delete_timer(t); continue; } + if (t->state != STATE_ACTIVE) { timer_dequeue(t, &timer_main_queue); } @@ -257,19 +271,20 @@ void timer_poll(void) /*** Internal Testing ***/ -/* I do not want to expose internals to the public, +/* I do not want to expose internals to the public, * which is why internals testing is done this way. */ -void timer_internal_tests(bool (*assert)(bool, char*)) +void timer_internal_tests(bool (*assert)(bool, char *)) { - + } void timer_debug_print() { - timer* t = timer_main_queue; + timer *t = timer_main_queue; printf("Queue:\n"); + while (t) { - printf("%" PRIu64 " (%" PRIu64 ") : %s\n", t->deadline, t->deadline/US_PER_SECOND, (char*)t->userdata); + printf("%" PRIu64 " (%" PRIu64 ") : %s\n", t->deadline, t->deadline / US_PER_SECOND, (char *)t->userdata); t = t->_next; } } diff --git a/core/timer.h b/core/timer.h index 8844a1dd..15491326 100644 --- a/core/timer.h +++ b/core/timer.h @@ -44,7 +44,7 @@ typedef struct timer timer; * You may call any of the timer functions within the callback: * For example, you may call timer_start to restart the timer from * within a callback. */ -typedef int (*timer_callback)(timer* t, void* userarg); +typedef int (*timer_callback)(timer *t, void *userarg); /* Initisalise timer subsystem */ void timer_init(void); @@ -53,52 +53,52 @@ void timer_init(void); void timer_poll(void); /* Creates a new timer. Does not enqueue/start it. */ -timer* new_timer(void); +timer *new_timer(void); /* Destroys a timer instance. */ -void delete_timer(timer* t); +void delete_timer(timer *t); /* Sets up the timer callback. */ -void timer_setup(timer* t, timer_callback cb, void* userarg); +void timer_setup(timer *t, timer_callback cb, void *userarg); /* Accessor Function. */ -void* timer_get_userdata(timer* t); +void *timer_get_userdata(timer *t); -/* Starts the timer so that it's called in sec seconds in the future from now. +/* Starts the timer so that it's called in sec seconds in the future from now. * A non-positive value of sec results in the callback being called immediately. - * This function may be called again after a timer has been started to adjust + * This function may be called again after a timer has been started to adjust * the expiry time. */ -void timer_start(timer* t, int sec); +void timer_start(timer *t, int sec); /* Stops the timer. Returns -1 if the timer was not active. */ -int timer_stop(timer* t); +int timer_stop(timer *t); -/* Adds additionalsec seconds to the timer. +/* Adds additionalsec seconds to the timer. * Returns -1 and does nothing if the timer was not active. */ -int timer_delay(timer* t, int additonalsec); +int timer_delay(timer *t, int additonalsec); /* Returns the time remaining on a timer in seconds. * Returns -1 if the timer is not active. * Returns 0 if the timer has expired and the callback hasn't been called yet. */ -int timer_time_remaining(timer* t); +int timer_time_remaining(timer *t); /* Determines if timer is active. Returns TRUE if it is active */ -bool timer_is_active(timer* t); +bool timer_is_active(timer *t); /* Single-use timer. - * Creates a new timer, preforms setup and starts it. + * Creates a new timer, preforms setup and starts it. * Callback must return a non-zero value to prevent memory leak. */ -void timer_single(timer_callback cb, void* userarg, int sec); +void timer_single(timer_callback cb, void *userarg, int sec); /* Single-use microsecond timer. - * Creates a new timer, preforms setup and starts it. + * Creates a new timer, preforms setup and starts it. * Please do not use this when accuracy is not absolutely required. * Use when one needs to time a period < 1 s. - * Use the more coarse timers above for periods > 5 s. + * Use the more coarse timers above for periods > 5 s. * WARNING: the callback will be called with NULL as the first argument */ -void timer_us(timer_callback cb, void* userarg, int us); +void timer_us(timer_callback cb, void *userarg, int us); /* Internal Testing */ -void timer_internal_tests(bool(*)(bool, char*)); +void timer_internal_tests(bool( *)(bool, char *)); #endif diff --git a/core/util.c b/core/util.c index d201bcb4..6f346db1 100644 --- a/core/util.c +++ b/core/util.c @@ -34,12 +34,12 @@ bool ipp_eq(IP_Port a, IP_Port b) return (a.ip.i == b.ip.i) && (a.port == b.port); } -bool id_eq(clientid_t* dest, clientid_t* src) +bool id_eq(clientid_t *dest, clientid_t *src) { return memcmp(dest, src, sizeof(clientid_t)) == 0; } -void id_cpy(clientid_t* dest, clientid_t* src) +void id_cpy(clientid_t *dest, clientid_t *src) { memcpy(dest, src, sizeof(clientid_t)); } diff --git a/core/util.h b/core/util.h index b85fbd39..5209c2ca 100644 --- a/core/util.h +++ b/core/util.h @@ -8,5 +8,5 @@ uint64_t now(); uint64_t random_64b(); bool ipp_eq(IP_Port a, IP_Port b); -bool id_eq(clientid_t* dest, clientid_t* src); -void id_cpy(clientid_t* dest, clientid_t* src); +bool id_eq(clientid_t *dest, clientid_t *src); +void id_cpy(clientid_t *dest, clientid_t *src); -- cgit v1.2.3