mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Updated Lossless UDP.
This commit is contained in:
parent
6bd24212ee
commit
4ad22addf4
|
@ -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++)
|
||||||
{
|
{
|
||||||
|
@ -159,11 +214,14 @@ int incoming_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +232,22 @@ int kill_connection(int connection_id)
|
||||||
//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.
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user