diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 51f30e17..ab4ff4bc 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -10,6 +10,7 @@ set(core_sources network.c Lossless_UDP.c net_crypto.c + friend_requests.c Messenger.c) add_library(core ${core_sources}) diff --git a/core/Messenger.c b/core/Messenger.c index 25ce067d..3d874837 100644 --- a/core/Messenger.c +++ b/core/Messenger.c @@ -353,15 +353,14 @@ static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t le friendlist[friendnumber].userstatus_length = length; return 0; } - +/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); static uint8_t friend_request_isset = 0; - +*/ /* set the function that will be executed when a friend request is received. */ void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)) { - friend_request = function; - friend_request_isset = 1; + callback_friendrequest(function); } @@ -413,19 +412,20 @@ static void doFriends() { if(friendlist[i].status == 1) { - IP_Port friendip = DHT_getfriendip(friendlist[i].client_id); - int request = check_friendrequest(friendlist[i].friend_request_id); - /* printf("\n%u %u %u\n", friendip.ip.i, request, friendlist[i].friend_request_id); */ - if(friendip.ip.i > 1 && request == -1) - { - friendlist[i].friend_request_id = send_friendrequest(friendlist[i].client_id, - friendip, friendlist[i].info, friendlist[i].info_size); - friendlist[i].status = 2; - } + int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); + if(fr == 0)/*TODO: This needs to be fixed so that it sends the friend requests a couple of times in case + of packet loss*/ + { + friendlist[i].status = 2; + } + else + if(fr > 0) + { + friendlist[i].status = 2; + } } if(friendlist[i].status == 2 || friendlist[i].status == 3) /* friend is not online */ { - check_friendrequest(friendlist[i].friend_request_id); /* for now this is used to kill the friend request */ IP_Port friendip = DHT_getfriendip(friendlist[i].client_id); switch(is_cryptoconnected(friendlist[i].crypt_connection_id)) { @@ -508,21 +508,6 @@ static void doFriends() } } -static void doFriendRequest() -{ - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - uint8_t temp[MAX_DATA_SIZE]; - - int len = handle_friendrequest(public_key, temp); - if(len >= 0) - { - if(friend_request_isset) - { - (*friend_request)(public_key, temp, len); - } - } -} - static void doInbound() @@ -556,7 +541,7 @@ void doMessenger() #ifdef DEBUG /* if(rand() % 3 != 1) //simulate packet loss */ /* { */ - if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) + if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port)) { /* if packet is discarded */ printf("Received unhandled packet with length: %u\n", length); @@ -570,6 +555,7 @@ void doMessenger() #else DHT_handlepacket(data, length, ip_port); LosslessUDP_handlepacket(data, length, ip_port); + friendreq_handlepacket(data, length, ip_port); #endif } @@ -577,7 +563,6 @@ void doMessenger() doLossless_UDP(); doNetCrypto(); doInbound(); - doFriendRequest(); doFriends(); } diff --git a/core/Messenger.h b/core/Messenger.h index 6fd98972..a7f114cf 100644 --- a/core/Messenger.h +++ b/core/Messenger.h @@ -29,6 +29,7 @@ #include "net_crypto.h" #include "DHT.h" +#include "friend_requests.h" #define MAX_NAME_LENGTH 128 #define MAX_USERSTATUS_LENGTH 128 diff --git a/core/friend_requests.c b/core/friend_requests.c new file mode 100644 index 00000000..18f0866b --- /dev/null +++ b/core/friend_requests.c @@ -0,0 +1,93 @@ +/* friend_requests.c + * + * Handle friend requests. + * + */ + +#include "friend_requests.h" + +uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; + + +/* Try to send a friendrequest to peer with public_key + data is the data in the request and length is the length. + return -1 if failure. + return 0 if it sent the friend request directly to the friend. + return the number of peers it was routed through if it did not send it directly.*/ +int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length) +{ + uint8_t packet[MAX_DATA_SIZE]; + int len = create_request(packet, public_key, data, length, 32); /* 32 is friend request packet id */ + if(len == -1) + { + return -1; + } + IP_Port ip_port = DHT_getfriendip(public_key); + if(ip_port.ip.i == 1) + { + return -1; + } + if(ip_port.ip.i != 0) + { + if(sendpacket(ip_port, packet, len) != -1) + { + return 0; + } + return -1; + } + + int num = route_tofriend(public_key, packet, len); + if(num == 0) + { + return -1; + } + return num; +} + + +static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t); +static uint8_t handle_friendrequest_isset = 0; + +/* set the function that will be executed when a friend request is received. */ +void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)) +{ + handle_friendrequest = function; + handle_friendrequest_isset = 1; +} + + +int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) +{ + + if(packet[0] == 32) + { + if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && + length > MAX_DATA_SIZE + ENCRYPTION_PADDING) + { + return 1; + } + if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)//check if request is for us. + { + if(handle_friendrequest_isset == 0) + { + return 1; + } + uint8_t public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t data[MAX_DATA_SIZE]; + int len = handle_request(public_key, data, packet, length); + if(len == -1) + { + return 1; + } + (*handle_friendrequest)(public_key, data, len); + } + else//if request is not for us, try routing it. + { + if(route_packet(packet + 1, packet, length) == length) + { + return 0; + } + } + } + return 1; +} \ No newline at end of file diff --git a/core/friend_requests.h b/core/friend_requests.h new file mode 100644 index 00000000..a3de46c8 --- /dev/null +++ b/core/friend_requests.h @@ -0,0 +1,34 @@ +/* friend_requests.h + * + * Handle friend requests. + * + */ + + +#ifndef FRIEND_REQUESTS_H +#define FRIEND_REQUESTS_H + + +#include "DHT.h" +#include "net_crypto.h" + + +/* 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, uint8_t * data, uint32_t length); + + +/* set the function that will be executed when a friend request for us is received. + function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ +void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); + +/* if we receive a packet we call this function so it can be handled. + return 0 if packet is handled correctly. + return 1 if it didn't handle the packet or if the packet was shit. */ +int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source); + + + + + +#endif \ No newline at end of file diff --git a/core/net_crypto.c b/core/net_crypto.c index bdde7063..e01ed695 100644 --- a/core/net_crypto.c +++ b/core/net_crypto.c @@ -52,11 +52,6 @@ typedef struct static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS]; -#define MAX_FRIEND_REQUESTS 32 - -/* keeps track of the connection numbers for friends request so we can check later if they were sent */ -static int outbound_friendrequests[MAX_FRIEND_REQUESTS]; - #define MAX_INCOMING 64 /* keeps track of the connection numbers for friends request so we can check later if they were sent */ @@ -217,88 +212,63 @@ int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length) return 1; } -/* send a friend request to peer with public_key and ip_port. - Data represents the data we send with the friends request. +/* create a request to peer with public_key. + packet must be an array of MAX_DATA_SIZE big. + Data represents the data we send with the request with length being the length of the data. + request_id is the id of the request (32 = friend request, 254 = ping request) returns -1 on failure - returns a positive friend request id that can be used later to see if it was sent correctly on success. */ -int send_friendrequest(uint8_t * public_key, IP_Port ip_port, uint8_t * data, uint32_t length) + returns the length of the created packet on success */ +int create_request(uint8_t * packet, uint8_t * public_key, uint8_t * data, uint32_t length, uint8_t request_id) { - if(length > MAX_DATA_SIZE - 1 - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES) + if(MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING) { return -1; } - uint32_t i; - for(i = 0; i < MAX_FRIEND_REQUESTS; ++i) - { - if(outbound_friendrequests[i] == -1) - { - break; - } - } - if(i == MAX_FRIEND_REQUESTS) - { - return -1; - } - uint8_t temp_data[MAX_DATA_SIZE]; uint8_t nonce[crypto_box_NONCEBYTES]; random_nonce(nonce); int len = encrypt_data(public_key, self_secret_key, nonce, data, length, - 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); if(len == -1) { return -1; } - temp_data[0] = 1; - memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); - int id = new_connection(ip_port); - if(id == -1) - { - return -1; - } - if(write_packet(id, temp_data, len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES) == 1) - { - outbound_friendrequests[i] = id; - return i; - } - return -1; + packet[0] = request_id; + memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); + + return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; } -/* return -1 if failure - return 0 if connection is still trying to send the request. - return 1 if sent correctly - return 2 if connection timed out */ -int check_friendrequest(int friend_request) +/* puts the senders public key in the request in public_key, the data from the request + in data if a friend or ping request was sent to us and returns the length of the data. + packet is the request packet and length is its length + return -1 if not valid request. */ +int handle_request(uint8_t * public_key, uint8_t * data, uint8_t * packet, uint16_t length) { - if(friend_request < 0 || friend_request > MAX_FRIEND_REQUESTS) + + 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) + { + memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); + uint8_t nonce[crypto_box_NONCEBYTES]; + memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); + int len1 = decrypt_data(public_key, self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, + length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), data); + if(len1 == -1) + { + return -1; + } + return len1; + } + else { return -1; } - if(outbound_friendrequests[friend_request] == -1) - { - return -1; - } - if(sendqueue(outbound_friendrequests[friend_request]) == 0) - { - kill_connection(outbound_friendrequests[friend_request]); - outbound_friendrequests[friend_request] = -1; - return 1; - } - int status = is_connected(outbound_friendrequests[friend_request]); - if(status == 4) - { - kill_connection(outbound_friendrequests[friend_request]); - outbound_friendrequests[friend_request] = -1; - return 2; - } - if(status == 0) - { - outbound_friendrequests[friend_request] = -1; - return 2; - } - return 0; } + /* Send a crypto handshake packet containing an encrypted secret nonce and session public key to peer with connection_id and public_key the packet is encrypted with a random nonce which is sent in plain text with the packet */ @@ -359,43 +329,7 @@ int handle_cryptohandshake(uint8_t * public_key, uint8_t * secret_nonce, } -/* puts the public key of the friend if public_key, the data from the request - in data if a friend request was sent to us and returns the length of the data. - return -1 if no valid friend requests. */ -int handle_friendrequest(uint8_t * public_key, uint8_t * data) -{ - uint32_t i; - for(i = 0; i < MAX_INCOMING; ++i) - { - if(incoming_connections[i] != -1) - { - if(id_packet(incoming_connections[i]) == 1) - { - uint8_t temp_data[MAX_DATA_SIZE]; - uint16_t len = read_packet(incoming_connections[i], temp_data); - if(len > crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + 1 - - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES) - { - memcpy(public_key, temp_data + 1, crypto_box_PUBLICKEYBYTES); - uint8_t nonce[crypto_box_NONCEBYTES]; - memcpy(nonce, temp_data + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES); - int len1 = decrypt_data(public_key, self_secret_key, nonce, temp_data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, - len - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + 1), data); - if(len1 != -1) - { - kill_connection(incoming_connections[i]); - /* kill_connection_in(incoming_connections[i], 1); //conection is useless now, kill it in 1 seconds */ - incoming_connections[i] = -1; - return len1; - } - } - kill_connection(incoming_connections[i]); /* conection is useless now, kill it. */ - incoming_connections[i] = -1; - } - } - } - return -1; -} + /* get crypto connection id from public key of peer return -1 if there are no connections like we are looking for @@ -714,7 +648,6 @@ static void receive_crypto() void initNetCrypto() { memset(crypto_connections, 0 ,sizeof(crypto_connections)); - memset(outbound_friendrequests, -1 ,sizeof(outbound_friendrequests)); memset(incoming_connections, -1 ,sizeof(incoming_connections)); uint32_t i; for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) diff --git a/core/net_crypto.h b/core/net_crypto.h index 0bf21f60..5a282002 100644 --- a/core/net_crypto.h +++ b/core/net_crypto.h @@ -62,24 +62,20 @@ int read_cryptpacket(int crypt_connection_id, uint8_t * data); return 1 if data was put into the queue */ int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length); -/* send a friend request to peer with public_key and ip_port. - Data represents the data we send with the friends request. +/* create a request to peer with public_key. + packet must be an array of MAX_DATA_SIZE big. + Data represents the data we send with the request with length being the length of the data. + request_id is the id of the request (32 = friend request, 254 = ping request) returns -1 on failure - returns a positive friend request id that can be used later to see if it was sent correctly on success. */ -int send_friendrequest(uint8_t * public_key, IP_Port ip_port, uint8_t * data, uint32_t length); + returns the length of the created packet on success */ +int create_request(uint8_t * packet, uint8_t * public_key, uint8_t * data, uint32_t length, uint8_t request_id); -/* return -1 if failure - return 0 if connection is still trying to send the request. - return 1 if sent correctly - return 2 if connection timed out */ -int check_friendrequest(int friend_request); - - -/* puts the public key of the friend if public_key, the data from the request - in data if a friend request was sent to us and returns the length of the data. - return -1 if no valid friend requests. */ -int handle_friendrequest(uint8_t * public_key, uint8_t * data); +/* puts the senders public key in the request in public_key, the data from the request + in data if a friend or ping request was sent to us and returns the length of the data. + packet is the request packet and length is its length + return -1 if not valid request. */ +int handle_request(uint8_t * public_key, uint8_t * data, uint8_t * packet, uint16_t length); /* Start a secure connection with other peer who has public_key and ip_port diff --git a/testing/DHT_test.c b/testing/DHT_test.c index 368609d0..9d599370 100644 --- a/testing/DHT_test.c +++ b/testing/DHT_test.c @@ -10,6 +10,7 @@ */ //#include "../core/network.h" #include "../core/DHT.c" +#include "../core/friend_requests.c" #include @@ -45,7 +46,7 @@ void print_clientlist() printf("\nTimestamp: %u", close_clientlist[i].timestamp); printf("\nLast pinged: %u\n", close_clientlist[i].last_pinged); p_ip = close_clientlist[i].ret_ip_port; - printf("\nOUR IP: %u.%u.%u.%u Port: %u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); + printf("OUR IP: %u.%u.%u.%u Port: %u\n",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); } } @@ -81,7 +82,7 @@ void print_friendlist() printf("\nTimestamp: %u", friends_list[k].client_list[i].timestamp); printf("\nLast pinged: %u\n", friends_list[k].client_list[i].last_pinged); p_ip = friends_list[k].client_list[i].ret_ip_port; - printf("\nret IP: %u.%u.%u.%u:%u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); + printf("ret IP: %u.%u.%u.%u:%u\n",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); } } } @@ -146,8 +147,6 @@ int main(int argc, char *argv[]) init_networking(ip, PORT); - - perror("Initialization"); IP_Port bootstrap_ip_port; bootstrap_ip_port.port = htons(atoi(argv[2])); @@ -169,7 +168,7 @@ int main(int argc, char *argv[]) while(receivepacket(&ip_port, data, &length) != -1) { - if(DHT_handlepacket(data, length, ip_port)) + if(DHT_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port)) { //unhandled packet printpacket(data, length, ip_port); diff --git a/testing/nTox.c b/testing/nTox.c index 50ceb92e..f7948778 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -251,7 +251,7 @@ int main(int argc, char *argv[]) //if keyfiles exist if(argc > 4){ if(strncmp(argv[4], "nokey", 6) < 0){ - load_key(); + //load_key(); } } else { load_key();