Updated Lossless UDP.

This commit is contained in:
irungentoo 2013-06-30 11:34:35 -04:00
parent 6bd24212ee
commit 4ad22addf4
5 changed files with 115 additions and 61 deletions

View File

@ -21,7 +21,8 @@
along with Tox. If not, see <http://www.gnu.org/licenses/>. along with Tox. If not, see <http://www.gnu.org/licenses/>.
*/ */
//TODO: clean this file a bit.
//There are a couple of useless variables to get rid of.
#include "Lossless_UDP.h" #include "Lossless_UDP.h"
@ -89,11 +90,61 @@ Connection connections[MAX_CONNECTIONS];
//Functions //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
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)
{
return i;
}
}
return -1;
}
//table of random numbers used below.
static uint32_t randtable[6][256];
//generate a handshake_id which depends on the ip_port.
//this function will always give one unique handshake_id per ip_port.
//TODO: make this better
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)
{
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;
}
//initialize a new connection to ip_port //initialize a new connection to ip_port
//returns an integer corresponding to the connection id. //returns an integer corresponding to the connection id.
//return -1 if it could not initialize the connection. //return -1 if it could not initialize the connection.
//if there already was an existing connection to that ip_port return its number.
int new_connection(IP_Port ip_port) int new_connection(IP_Port ip_port)
{ {
int connect = getconnection_id(ip_port);
if(connect != -1)
{
return connect;
}
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CONNECTIONS; i++) for(i = 0; i < MAX_CONNECTIONS; i++)
{ {
@ -102,7 +153,7 @@ int new_connection(IP_Port ip_port)
connections[i].ip_port = ip_port; connections[i].ip_port = ip_port;
connections[i].status = 1; connections[i].status = 1;
connections[i].inbound = 0; connections[i].inbound = 0;
connections[i].handshake_id1 = random_int(); connections[i].handshake_id1 = handshake_id(ip_port);
connections[i].sent_packetnum = connections[i].handshake_id1; connections[i].sent_packetnum = connections[i].handshake_id1;
connections[i].sendbuff_packetnum = connections[i].handshake_id1; connections[i].sendbuff_packetnum = connections[i].handshake_id1;
connections[i].successful_sent = connections[i].handshake_id1; connections[i].successful_sent = connections[i].handshake_id1;
@ -121,6 +172,10 @@ int new_connection(IP_Port ip_port)
//return -1 if it could not initialize the connection. //return -1 if it could not initialize the connection.
int new_inconnection(IP_Port ip_port) int new_inconnection(IP_Port ip_port)
{ {
if(getconnection_id(ip_port) != -1)
{
return -1;
}
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CONNECTIONS; i++) for(i = 0; i < MAX_CONNECTIONS; i++)
{ {
@ -158,12 +213,15 @@ int incoming_connection()
//return -1 if it could not kill the connection. //return -1 if it could not kill the connection.
//return 0 if killed successfully //return 0 if killed successfully
int kill_connection(int connection_id) int kill_connection(int connection_id)
{
if(connection_id >= 0 && connection_id < MAX_CONNECTIONS)
{ {
if(connections[connection_id].status > 0) if(connections[connection_id].status > 0)
{ {
connections[connection_id].status = 0; connections[connection_id].status = 0;
return 0; return 0;
} }
}
return -1; return -1;
} }
@ -173,9 +231,24 @@ int kill_connection(int connection_id)
//return 2 if handshake is done //return 2 if handshake is done
//return 3 if fully connected //return 3 if fully connected
int is_connected(int connection_id) int is_connected(int connection_id)
{
if(connection_id >= 0 && connection_id < MAX_CONNECTIONS)
{ {
return connections[connection_id].status; return connections[connection_id].status;
} }
return 0;
}
//returns the ip_port of the corresponding connection.
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;
}
//returns the number of packets in the queue waiting to be successfully sent. //returns the number of packets in the queue waiting to be successfully sent.
uint32_t sendqueue(int connection_id) uint32_t sendqueue(int connection_id)
@ -331,47 +404,7 @@ int send_DATA(uint32_t connection_id)
//END of packet sending functions //END of packet sending 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
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)
{
return i;
}
}
return -1;
}
//table of random numbers used below.
static uint32_t randtable[6][256];
//generate a handshake_id which depends on the ip_port.
//this function will always give one unique handshake_id per ip_port.
//TODO: make this better
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)
{
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;
}
//Packet handling functions //Packet handling functions
//One to handle each type of packets we recieve //One to handle each type of packets we recieve
@ -383,27 +416,29 @@ int handle_handshake(char * packet, uint32_t length, IP_Port source)
return 1; return 1;
} }
uint32_t handshake_id1, handshake_id2; uint32_t handshake_id1, handshake_id2;
int connection = getconnection_id(source);
memcpy(&handshake_id1, packet + 1, 4); memcpy(&handshake_id1, packet + 1, 4);
memcpy(&handshake_id2, packet + 5, 4); memcpy(&handshake_id2, packet + 5, 4);
if(handshake_id2 == 0) if(handshake_id2 == 0)
{ {
send_handshake(source, handshake_id1, handshake_id(source)); send_handshake(source, handshake_id(source), handshake_id1);
return 0; return 0;
} }
int connection = getconnection_id(source);
if(is_connected(connection) != 1) if(is_connected(connection) != 1)
{ {
return 1; return 1;
} }
if(handshake_id1 == connections[connection].handshake_id1)//if handshake_id1 is what we sent previously. if(handshake_id2 == connections[connection].handshake_id1)//if handshake_id2 is what we sent previously as handshake_id1
{ {
connections[connection].status = 2; connections[connection].status = 2;
//NOTE:is this necessary? //NOTE:is this necessary?
//connections[connection].handshake_id2 = handshake_id2; //connections[connection].handshake_id2 = handshake_id1;
connections[connection].orecv_packetnum = handshake_id1; connections[connection].orecv_packetnum = handshake_id2;
connections[connection].osent_packetnum = handshake_id2; connections[connection].osent_packetnum = handshake_id1;
connections[connection].recv_packetnum = handshake_id2; connections[connection].recv_packetnum = handshake_id1;
connections[connection].successful_read = handshake_id2; connections[connection].successful_read = handshake_id1;
} }
return 0; return 0;

View File

@ -33,40 +33,56 @@
//initialize a new connection to ip_port //initialize a new connection to ip_port
//returns an integer corresponding to the connection id. //returns an integer corresponding to the connection id.
//return -1 if it could not initialize the connection. //return -1 if it could not initialize the connection.
//if there already was an existing connection to that ip_port return its number.
int new_connection(IP_Port ip_port); int new_connection(IP_Port ip_port);
//returns an integer corresponding to the next connection in our imcoming connection list //returns an integer corresponding to the next connection in our imcoming connection list
//return -1 if there are no new incoming connections in the list. //return -1 if there are no new incoming connections in the list.
int incoming_connection(); int incoming_connection();
//return -1 if it could not kill the connection. //return -1 if it could not kill the connection.
//return 0 if killed successfully //return 0 if killed successfully
int kill_connection(int connection_id); int kill_connection(int connection_id);
//returns the ip_port of the corresponding connection.
//return 0 if there is no such connection.
IP_Port connection_ip(int connection_id);
//return 0 if there is no received data in the buffer. //return 0 if there is no received data in the buffer.
//return length of recieved packet if successful //return length of recieved packet if successful
int read_packet(int connection_id, char * data); int read_packet(int connection_id, char * data);
//return 0 if data could not be put in packet queue //return 0 if data could not be put in packet queue
//return 1 if data was put into the queue //return 1 if data was put into the queue
int write_packet(int connection_id, char * data, uint32_t length); int write_packet(int connection_id, char * data, uint32_t length);
//returns the number of packets in the queue waiting to be successfully sent. //returns the number of packets in the queue waiting to be successfully sent.
uint32_t sendqueue(int connection_id); uint32_t sendqueue(int connection_id);
//returns the number of packets in the queue waiting to be successfully read with read_packet(...) //returns the number of packets in the queue waiting to be successfully read with read_packet(...)
uint32_t recvqueue(int connection_id); uint32_t recvqueue(int connection_id);
//check if connection is connected //check if connection is connected
//return 0 no. //return 0 no.
//return 1 if yes //return 1 if attempting handshake
//return 2 if the initial attempt isn't over yet. //return 2 if handshake is done
//return 3 if fully connected
int is_connected(int connection_id); int is_connected(int connection_id);
//Call this function a couple times per second //Call this function a couple times per second
//It's the main loop. //It's the main loop.
void doLossless_UDP(); void doLossless_UDP();
//if we receive a Lossless_UDP packet we call this function so it can be handled. //if we receive a Lossless_UDP packet we call this function so it can be handled.
//Return 0 if packet is handled correctly. //Return 0 if packet is handled correctly.
//return 1 if it didn't handle the packet or if the packet was shit. //return 1 if it didn't handle the packet or if the packet was shit.

View File

@ -63,7 +63,10 @@ Lossless UDP:
The client receives a Connection handshake packet(not initiating connection): The client receives a Connection handshake packet(not initiating connection):
If handshake_id2 is zero: If handshake_id2 is zero:
add our random handshake_id2 to it and send it back use the handshake_id1 in the packet as the handshake_id2 of the response.
use our random handshake_id1 as handshake_id1.
send the response packet.
The client receives a Connection handshake packet(initiating connection): The client receives a Connection handshake packet(initiating connection):

View File

@ -6,8 +6,8 @@
* *
* Compile with: gcc -O2 -Wall -o testclient ../core/network.c ../core/Lossless_UDP.c Lossless_UDP_testclient.c * Compile with: gcc -O2 -Wall -o testclient ../core/network.c ../core/Lossless_UDP.c Lossless_UDP_testclient.c
* *
* Command line arguments are the ip and port to cennect and send the file to. * Command line arguments are the ip and port to connect and send the file to.
* EX: ./test 127.0.0.1 33445 filename.txt * EX: ./testclient 127.0.0.1 33445 filename.txt
*/ */
#include "../core/network.h" #include "../core/network.h"

View File

@ -7,7 +7,7 @@
* Compile with: gcc -O2 -Wall -o testserver ../core/network.c ../core/Lossless_UDP.c Lossless_UDP_testserver.c * Compile with: gcc -O2 -Wall -o testserver ../core/network.c ../core/Lossless_UDP.c Lossless_UDP_testserver.c
* *
* Command line argument is the name of the file to save what we recieve to. * Command line argument is the name of the file to save what we recieve to.
* EX: ./test filename1.txt * EX: ./testserver filename1.txt
*/ */
#include "../core/network.h" #include "../core/network.h"