summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/Lossless_UDP.c164
1 files changed, 104 insertions, 60 deletions
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c
index 1073d134..014f0014 100644
--- a/core/Lossless_UDP.c
+++ b/core/Lossless_UDP.c
@@ -21,28 +21,27 @@
21 * 21 *
22 */ 22 */
23 23
24/* TODO: clean this file a bit. 24/*
25 There are a couple of useless variables to get rid of. */ 25 * TODO: clean this file a bit.
26 * There are a couple of useless variables to get rid of.
27 */
28
26#include "Lossless_UDP.h" 29#include "Lossless_UDP.h"
27 30
28/* maximum data packets in sent and receive queues. */ 31/* maximum data packets in sent and receive queues. */
29#define MAX_QUEUE_NUM 16 32#define MAX_QUEUE_NUM 16
30
31/* maximum length of the data in the data packets */
32/* #define MAX_DATA_SIZE 1024 */ /* defined in Lossless_UDP.h */
33 33
34/* maximum number of data packets in the buffer */ 34/* maximum number of data packets in the buffer */
35#define BUFFER_PACKET_NUM (16-1) 35#define BUFFER_PACKET_NUM (16-1)
36 36
37/* Lossless UDP connection timeout. 37/* timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
38timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
39#define CONNEXION_TIMEOUT 5 38#define CONNEXION_TIMEOUT 5
40 39
41/* initial amount of sync/hanshake packets to send per second. */ 40/* initial amount of sync/hanshake packets to send per second. */
42#define SYNC_RATE 2 41#define SYNC_RATE 2
43 42
44/* initial send rate of data. */ 43/* initial send rate of data. */
45#define DATA_SYNC_RATE 30 44#define DATA_SYNC_RATE 30
46 45
47typedef struct { 46typedef struct {
48 uint8_t data[MAX_DATA_SIZE]; 47 uint8_t data[MAX_DATA_SIZE];
@@ -51,6 +50,7 @@ typedef struct {
51 50
52typedef struct { 51typedef struct {
53 IP_Port ip_port; 52 IP_Port ip_port;
53
54 /* 54 /*
55 * 0 if connection is dead, 1 if attempting handshake, 55 * 0 if connection is dead, 1 if attempting handshake,
56 * 2 if handshake is done (we start sending SYNC packets) 56 * 2 if handshake is done (we start sending SYNC packets)
@@ -122,26 +122,33 @@ static uint32_t connections_number; /* Number of connections in connections arra
122 122
123/* Functions */ 123/* Functions */
124 124
125/* get connection id from IP_Port 125/*
126 return -1 if there are no connections like we are looking for 126 * Get connection id from IP_Port
127 return id if it found it */ 127 * Return -1 if there are no connections like we are looking for
128 * Return id if it found it
129 */
128int getconnection_id(IP_Port ip_port) 130int getconnection_id(IP_Port ip_port)
129{ 131{
130 uint32_t i; 132 uint32_t i;
131 for (i = 0; i < MAX_CONNECTIONS; ++i) { 133 for (i = 0; i < MAX_CONNECTIONS; ++i) {
132 if (connections[i].ip_port.ip.i == ip_port.ip.i && 134 if (connections[i].ip_port.ip.i == ip_port.ip.i &&
133 connections[i].ip_port.port == ip_port.port && connections[i].status > 0) 135 connections[i].ip_port.port == ip_port.port &&
136 connections[i].status > 0)
134 return i; 137 return i;
135 } 138 }
139
136 return -1; 140 return -1;
137} 141}
138 142
139/* table of random numbers used below. */ 143/* table of random numbers used below. */
140static uint32_t randtable[6][256]; 144static uint32_t randtable[6][256];
141 145
142/* generate a handshake_id which depends on the ip_port. 146/*
143 this function will always give one unique handshake_id per ip_port. 147 * Generate a handshake_id which depends on the ip_port.
144 TODO: make this better */ 148 * This function will always give one unique handshake_id per ip_port.
149 *
150 * TODO: make this better
151 */
145uint32_t handshake_id(IP_Port source) 152uint32_t handshake_id(IP_Port source)
146{ 153{
147 uint32_t id = 0, i; 154 uint32_t id = 0, i;
@@ -152,21 +159,27 @@ uint32_t handshake_id(IP_Port source)
152 } 159 }
153 if (id == 0) /* id can't be zero */ 160 if (id == 0) /* id can't be zero */
154 id = 1; 161 id = 1;
162
155 return id; 163 return id;
156} 164}
157 165
158/* change the hnshake id associated with that ip_port 166/*
159 TODO: make this better */ 167 * Change the hanshake id associated with that ip_port
168 *
169 * TODO: make this better
170 */
160void change_handshake(IP_Port source) 171void change_handshake(IP_Port source)
161{ 172{
162 uint8_t rand = random_int() % 4; 173 uint8_t rand = random_int() % 4;
163 randtable[rand][((uint8_t *)&source)[rand]] = random_int(); 174 randtable[rand][((uint8_t *)&source)[rand]] = random_int();
164} 175}
165 176
166/* initialize a new connection to ip_port 177/*
167 returns an integer corresponding to the connection id. 178 * Initialize a new connection to ip_port
168 return -1 if it could not initialize the connection. 179 * Returns an integer corresponding to the connection idt
169 if there already was an existing connection to that ip_port return its number. */ 180 * Return -1 if it could not initialize the connectiont
181 * If there already was an existing connection to that ip_port return its number.
182 */
170int new_connection(IP_Port ip_port) 183int new_connection(IP_Port ip_port)
171{ 184{
172 int connect = getconnection_id(ip_port); 185 int connect = getconnection_id(ip_port);
@@ -176,8 +189,10 @@ int new_connection(IP_Port ip_port)
176 if(connections_number == connections_length) { 189 if(connections_number == connections_length) {
177 Connection * temp; 190 Connection * temp;
178 temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); 191 temp = realloc(connections, sizeof(Connection) * (connections_length + 1));
192
179 if(temp == NULL) 193 if(temp == NULL)
180 return -1; 194 return -1;
195
181 memset(&temp[connections_length], 0, sizeof(Connection)); 196 memset(&temp[connections_length], 0, sizeof(Connection));
182 ++connections_length; 197 ++connections_length;
183 connections = temp; 198 connections = temp;
@@ -213,9 +228,11 @@ int new_connection(IP_Port ip_port)
213 return -1; 228 return -1;
214} 229}
215 230
216/* initialize a new inbound connection from ip_port 231/*
217 returns an integer corresponding to the connection id. 232 * Initialize a new inbound connection from ip_port
218 return -1 if it could not initialize the connection. */ 233 * Returns an integer corresponding to the connection id.
234 * Return -1 if it could not initialize the connection.
235 */
219int new_inconnection(IP_Port ip_port) 236int new_inconnection(IP_Port ip_port)
220{ 237{
221 if (getconnection_id(ip_port) != -1) 238 if (getconnection_id(ip_port) != -1)
@@ -224,8 +241,10 @@ int new_inconnection(IP_Port ip_port)
224 if(connections_number == connections_length) { 241 if(connections_number == connections_length) {
225 Connection * temp; 242 Connection * temp;
226 temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); 243 temp = realloc(connections, sizeof(Connection) * (connections_length + 1));
244
227 if(temp == NULL) 245 if(temp == NULL)
228 return -1; 246 return -1;
247
229 memset(&temp[connections_length], 0, sizeof(Connection)); 248 memset(&temp[connections_length], 0, sizeof(Connection));
230 ++connections_length; 249 ++connections_length;
231 connections = temp; 250 connections = temp;
@@ -259,8 +278,10 @@ int new_inconnection(IP_Port ip_port)
259 return -1; 278 return -1;
260} 279}
261 280
262/* returns an integer corresponding to the next connection in our incoming connection list 281/*
263 return -1 if there are no new incoming connections in the list. */ 282 * Returns an integer corresponding to the next connection in our incoming connection list.
283 * Return -1 if there are no new incoming connections in the list.
284 */
264int incoming_connection() 285int incoming_connection()
265{ 286{
266 uint32_t i; 287 uint32_t i;
@@ -270,9 +291,11 @@ int incoming_connection()
270 return i; 291 return i;
271 } 292 }
272 } 293 }
294
273 return -1; 295 return -1;
274} 296}
275/*Try to free some memory from the connections array.*/ 297
298/* Try to free some memory from the connections array. */
276static void free_connections() 299static void free_connections()
277{ 300{
278 uint32_t i; 301 uint32_t i;
@@ -292,8 +315,10 @@ static void free_connections()
292 connections_length = i; 315 connections_length = i;
293} 316}
294 317
295/* return -1 if it could not kill the connection. 318/*
296 return 0 if killed successfully */ 319 * Return -1 if it could not kill the connection.
320 * Return 0 if killed successfully
321 */
297int kill_connection(int connection_id) 322int kill_connection(int connection_id)
298{ 323{
299 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { 324 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) {
@@ -308,9 +333,11 @@ int kill_connection(int connection_id)
308 return -1; 333 return -1;
309} 334}
310 335
311/* kill connection in seconds seconds. 336/*
312 return -1 if it can not kill the connection. 337 * Kill connection in seconds.
313 return 0 if it will kill it */ 338 * Return -1 if it can not kill the connection.
339 * Return 0 if it will kill it.
340 */
314int kill_connection_in(int connection_id, uint32_t seconds) 341int kill_connection_in(int connection_id, uint32_t seconds)
315{ 342{
316 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { 343 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) {
@@ -322,12 +349,14 @@ int kill_connection_in(int connection_id, uint32_t seconds)
322 return -1; 349 return -1;
323} 350}
324 351
325/* check if connection is connected 352/*
326 return 0 no. 353 * Check if connection is connected:
327 return 1 if attempting handshake 354 * Return 0 no.
328 return 2 if handshake is done 355 * Return 1 if attempting handshake.
329 return 3 if fully connected 356 * Return 2 if handshake is done.
330 return 4 if timed out and waiting to be killed */ 357 * Return 3 if fully connected.
358 * Return 4 if timed out and waiting to be killed.
359 */
331int is_connected(int connection_id) 360int is_connected(int connection_id)
332{ 361{
333 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) 362 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS)
@@ -364,10 +393,9 @@ uint32_t recvqueue(int connection_id)
364 return -1 if no packet in queue */ 393 return -1 if no packet in queue */
365char id_packet(int connection_id) 394char id_packet(int connection_id)
366{ 395{
367 if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) 396 if (recvqueue(connection_id) > 0 && connections[connection_id].status != 0 && connection_id < MAX_CONNECTIONS)
368 return -1;
369 if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0)
370 return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; 397 return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0];
398
371 return -1; 399 return -1;
372} 400}
373 401
@@ -386,14 +414,13 @@ int read_packet(int connection_id, uint8_t * data)
386 return 0; 414 return 0;
387} 415}
388 416
389/* return 0 if data could not be put in packet queue 417/*
390 return 1 if data was put into the queue */ 418 * Return 0 if data could not be put in packet queue
419 * Return 1 if data was put into the queue
420 */
391int write_packet(int connection_id, uint8_t * data, uint32_t length) 421int write_packet(int connection_id, uint8_t * data, uint32_t length)
392{ 422{
393 if (length > MAX_DATA_SIZE) 423 if (length > MAX_DATA_SIZE || length == 0)
394 return 0;
395
396 if (length == 0)
397 return 0; 424 return 0;
398 425
399 if (sendqueue(connection_id) < BUFFER_PACKET_NUM) { 426 if (sendqueue(connection_id) < BUFFER_PACKET_NUM) {
@@ -403,6 +430,7 @@ int write_packet(int connection_id, uint8_t * data, uint32_t length)
403 connections[connection_id].sendbuff_packetnum++; 430 connections[connection_id].sendbuff_packetnum++;
404 return 1; 431 return 1;
405 } 432 }
433
406 return 0; 434 return 0;
407} 435}
408 436
@@ -412,8 +440,11 @@ uint32_t missing_packets(int connection_id, uint32_t * requested)
412 uint32_t number = 0; 440 uint32_t number = 0;
413 uint32_t i; 441 uint32_t i;
414 uint32_t temp; 442 uint32_t temp;
415 if (recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1)) /* don't request packets if the buffer is full. */ 443
444 /* don't request packets if the buffer is full. */
445 if (recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1))
416 return 0; 446 return 0;
447
417 for (i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++) { 448 for (i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++) {
418 if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) { 449 if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) {
419 temp = htonl(i); 450 temp = htonl(i);
@@ -421,14 +452,19 @@ uint32_t missing_packets(int connection_id, uint32_t * requested)
421 ++number; 452 ++number;
422 } 453 }
423 } 454 }
455
424 if(number == 0) 456 if(number == 0)
425 connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; 457 connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum;
458
426 return number; 459 return number;
427} 460}
428 461
429/* Packet sending functions 462/*
430 One per packet type. 463 * BEGIN Packet sending functions
431 see docs/Lossless_UDP.txt for more information. */ 464 * One per packet type.
465 * see docs/Lossless_UDP.txt for more information.
466 */
467
432int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) 468int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2)
433{ 469{
434 uint8_t packet[1 + 4 + 4]; 470 uint8_t packet[1 + 4 + 4];
@@ -445,7 +481,6 @@ int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_i
445 481
446int send_SYNC(uint32_t connection_id) 482int send_SYNC(uint32_t connection_id)
447{ 483{
448
449 uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; 484 uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)];
450 uint16_t index = 0; 485 uint16_t index = 0;
451 486
@@ -457,7 +492,6 @@ int send_SYNC(uint32_t connection_id)
457 uint32_t requested[BUFFER_PACKET_NUM]; 492 uint32_t requested[BUFFER_PACKET_NUM];
458 uint32_t number = missing_packets(connection_id, requested); 493 uint32_t number = missing_packets(connection_id, requested);
459 494
460
461 packet[0] = 17; 495 packet[0] = 17;
462 index += 1; 496 index += 1;
463 memcpy(packet + index, &counter, 1); 497 memcpy(packet + index, &counter, 1);
@@ -520,8 +554,10 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
520{ 554{
521 if (length != (1 + 4 + 4)) 555 if (length != (1 + 4 + 4))
522 return 1; 556 return 1;
557
523 uint32_t temp; 558 uint32_t temp;
524 uint32_t handshake_id1, handshake_id2; 559 uint32_t handshake_id1, handshake_id2;
560
525 int connection = getconnection_id(source); 561 int connection = getconnection_id(source);
526 memcpy(&temp, packet + 1, 4); 562 memcpy(&temp, packet + 1, 4);
527 handshake_id1 = ntohl(temp); 563 handshake_id1 = ntohl(temp);
@@ -534,17 +570,19 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
534 } 570 }
535 if (is_connected(connection) != 1) 571 if (is_connected(connection) != 1)
536 return 1; 572 return 1;
537 if (handshake_id2 == connections[connection].handshake_id1) { /* if handshake_id2 is what we sent previously as handshake_id1 */ 573
574 /* if handshake_id2 is what we sent previously as handshake_id1 */
575 if (handshake_id2 == connections[connection].handshake_id1) {
538 connections[connection].status = 2; 576 connections[connection].status = 2;
539 /* NOTE: is this necessary? 577 /* NOTE: is this necessary?
540 connections[connection].handshake_id2 = handshake_id1; */ 578 connections[connection].handshake_id2 = handshake_id1; */
541 connections[connection].orecv_packetnum = handshake_id2; 579 connections[connection].orecv_packetnum = handshake_id2;
542 connections[connection].osent_packetnum = handshake_id1; 580 connections[connection].osent_packetnum = handshake_id1;
543 connections[connection].recv_packetnum = handshake_id1; 581 connections[connection].recv_packetnum = handshake_id1;
544 connections[connection].successful_read = handshake_id1; 582 connections[connection].successful_read = handshake_id1;
545 } 583 }
546 return 0;
547 584
585 return 0;
548} 586}
549 587
550/* returns 1 if sync packet is valid 0 if not. */ 588/* returns 1 if sync packet is valid 0 if not. */
@@ -610,8 +648,9 @@ int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, ui
610 connections[connection_id].orecv_packetnum = recv_packetnum; 648 connections[connection_id].orecv_packetnum = recv_packetnum;
611 connections[connection_id].osent_packetnum = sent_packetnum; 649 connections[connection_id].osent_packetnum = sent_packetnum;
612 connections[connection_id].successful_sent = recv_packetnum; 650 connections[connection_id].successful_sent = recv_packetnum;
613 connections[connection_id].last_recvSYNC = current_time(); 651 connections[connection_id].last_recvSYNC = current_time();
614 connections[connection_id].recv_counter = counter; 652 connections[connection_id].recv_counter = counter;
653
615 ++connections[connection_id].send_counter; 654 ++connections[connection_id].send_counter;
616 655
617 for (i = 0; i < number; ++i) { 656 for (i = 0; i < number; ++i) {
@@ -630,6 +669,7 @@ int handle_SYNC(uint8_t *packet, uint32_t length, IP_Port source)
630 669
631 if (!SYNC_valid(length)) 670 if (!SYNC_valid(length))
632 return 1; 671 return 1;
672
633 int connection = getconnection_id(source); 673 int connection = getconnection_id(source);
634 uint8_t counter; 674 uint8_t counter;
635 uint32_t temp; 675 uint32_t temp;
@@ -679,12 +719,14 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
679 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; 719 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size;
680 connections[connection_id].last_recvdata = current_time(); 720 connections[connection_id].last_recvdata = current_time();
681 721
682 if (sent_packet < BUFFER_PACKET_NUM) 722 if (sent_packet < BUFFER_PACKET_NUM) {
683 connections[connection_id].osent_packetnum = data_num; 723 connections[connection_id].osent_packetnum = data_num;
724 }
684 725
685 break; 726 break;
686 } 727 }
687 } 728 }
729
688 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 730 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
689 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) 731 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0)
690 connections[connection_id].recv_packetnum = i; 732 connections[connection_id].recv_packetnum = i;
@@ -708,12 +750,14 @@ int handle_data(uint8_t *packet, uint32_t length, IP_Port source)
708 750
709 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) 751 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1)
710 return 1; 752 return 1;
753
711 uint32_t temp; 754 uint32_t temp;
712 uint32_t number; 755 uint32_t number;
713 uint16_t size = length - 1 - 4; 756 uint16_t size = length - 1 - 4;
714 757
715 memcpy(&temp, packet + 1, 4); 758 memcpy(&temp, packet + 1, 4);
716 number = ntohl(temp); 759 number = ntohl(temp);
760
717 return add_recv(connection, number, packet + 5, size); 761 return add_recv(connection, number, packet + 5, size);
718} 762}
719 763