Modified the way friend requests worked.

Added routing of friend requests.
This commit is contained in:
irungentoo 2013-07-22 14:52:42 -04:00
parent b368a6b4b8
commit 55361eac6f
9 changed files with 199 additions and 157 deletions

View File

@ -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})

View File

@ -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();
}

View File

@ -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

93
core/friend_requests.c Normal file
View File

@ -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;
}

34
core/friend_requests.h Normal file
View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -10,6 +10,7 @@
*/
//#include "../core/network.h"
#include "../core/DHT.c"
#include "../core/friend_requests.c"
#include <string.h>
@ -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);

View File

@ -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();