summaryrefslogtreecommitdiff
path: root/core/Lossless_UDP.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/Lossless_UDP.c')
-rw-r--r--core/Lossless_UDP.c78
1 files changed, 39 insertions, 39 deletions
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c
index f9d20b2f..0194375a 100644
--- a/core/Lossless_UDP.c
+++ b/core/Lossless_UDP.c
@@ -1,7 +1,7 @@
1/* Lossless_UDP.c 1/* Lossless_UDP.c
2 * 2 *
3 * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt 3 * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt
4 * 4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 * 6 *
7 * This file is part of Tox. 7 * This file is part of Tox.
@@ -18,7 +18,7 @@
18 * 18 *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 * 21 *
22 */ 22 */
23 23
24/* TODO: clean this file a bit. 24/* TODO: clean this file a bit.
@@ -47,18 +47,18 @@ timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION
47typedef struct { 47typedef struct {
48 uint8_t data[MAX_DATA_SIZE]; 48 uint8_t data[MAX_DATA_SIZE];
49 uint16_t size; 49 uint16_t size;
50}Data; 50} Data;
51 51
52typedef struct { 52typedef struct {
53 IP_Port ip_port; 53 IP_Port ip_port;
54 uint8_t status; /* 0 if connection is dead, 1 if attempting handshake, 54 uint8_t status; /* 0 if connection is dead, 1 if attempting handshake,
55 2 if handshake is done (we start sending SYNC packets) 55 2 if handshake is done (we start sending SYNC packets)
56 3 if we are sending SYNC packets and can send data 56 3 if we are sending SYNC packets and can send data
57 4 if the connection has timed out. */ 57 4 if the connection has timed out. */
58 58
59 uint8_t inbound; /* 1 or 2 if connection was initiated by someone else, 0 if not. 59 uint8_t inbound; /* 1 or 2 if connection was initiated by someone else, 0 if not.
60 2 if incoming_connection() has not returned it yet, 1 if it has. */ 60 2 if incoming_connection() has not returned it yet, 1 if it has. */
61 61
62 uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */ 62 uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */
63 uint16_t data_rate; /* current data packet send rate packets per second. */ 63 uint16_t data_rate; /* current data packet send rate packets per second. */
64 uint64_t last_SYNC; /* time at which our last SYNC packet was sent. */ 64 uint64_t last_SYNC; /* time at which our last SYNC packet was sent. */
@@ -82,7 +82,7 @@ typedef struct {
82 uint8_t recv_counter; 82 uint8_t recv_counter;
83 uint8_t send_counter; 83 uint8_t send_counter;
84 uint8_t timeout; /* connection timeout in seconds. */ 84 uint8_t timeout; /* connection timeout in seconds. */
85}Connection; 85} Connection;
86 86
87#define MAX_CONNECTIONS 256 87#define MAX_CONNECTIONS 256
88 88
@@ -95,10 +95,11 @@ static Connection connections[MAX_CONNECTIONS];
95/* get connection id from IP_Port 95/* get connection id from IP_Port
96 return -1 if there are no connections like we are looking for 96 return -1 if there are no connections like we are looking for
97 return id if it found it */ 97 return id if it found it */
98int getconnection_id(IP_Port ip_port) { 98int getconnection_id(IP_Port ip_port)
99{
99 uint32_t i; 100 uint32_t i;
100 for (i = 0; i < MAX_CONNECTIONS; ++i) { 101 for (i = 0; i < MAX_CONNECTIONS; ++i) {
101 if (connections[i].ip_port.ip.i == ip_port.ip.i && 102 if (connections[i].ip_port.ip.i == ip_port.ip.i &&
102 connections[i].ip_port.port == ip_port.port && connections[i].status > 0) 103 connections[i].ip_port.port == ip_port.port && connections[i].status > 0)
103 return i; 104 return i;
104 } 105 }
@@ -384,10 +385,10 @@ int send_data_packet(uint32_t connection_id, uint32_t packet_num)
384 packet[0] = 18; 385 packet[0] = 18;
385 temp = htonl(packet_num); 386 temp = htonl(packet_num);
386 memcpy(packet + 1, &temp, 4); 387 memcpy(packet + 1, &temp, 4);
387 memcpy(packet + 5, connections[connection_id].sendbuffer[index].data, 388 memcpy(packet + 5, connections[connection_id].sendbuffer[index].data,
388 connections[connection_id].sendbuffer[index].size); 389 connections[connection_id].sendbuffer[index].size);
389 return sendpacket(connections[connection_id].ip_port, packet, 390 return sendpacket(connections[connection_id].ip_port, packet,
390 1 + 4 + connections[connection_id].sendbuffer[index].size); 391 1 + 4 + connections[connection_id].sendbuffer[index].size);
391} 392}
392 393
393/* sends 1 data packet */ 394/* sends 1 data packet */
@@ -395,7 +396,7 @@ int send_DATA(uint32_t connection_id)
395{ 396{
396 int ret; 397 int ret;
397 uint32_t buffer[BUFFER_PACKET_NUM]; 398 uint32_t buffer[BUFFER_PACKET_NUM];
398 if (connections[connection_id].num_req_paquets > 0) { 399 if (connections[connection_id].num_req_paquets > 0) {
399 ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]); 400 ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]);
400 connections[connection_id].num_req_paquets--; 401 connections[connection_id].num_req_paquets--;
401 memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4); 402 memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4);
@@ -416,9 +417,9 @@ int send_DATA(uint32_t connection_id)
416 One to handle each type of packets we receive 417 One to handle each type of packets we receive
417 return 0 if handled correctly, 1 if packet is bad. */ 418 return 0 if handled correctly, 1 if packet is bad. */
418int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) 419int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
419{ 420{
420 if (length != (1 + 4 + 4)) 421 if (length != (1 + 4 + 4))
421 return 1; 422 return 1;
422 uint32_t temp; 423 uint32_t temp;
423 uint32_t handshake_id1, handshake_id2; 424 uint32_t handshake_id1, handshake_id2;
424 int connection = getconnection_id(source); 425 int connection = getconnection_id(source);
@@ -426,7 +427,7 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
426 handshake_id1 = ntohl(temp); 427 handshake_id1 = ntohl(temp);
427 memcpy(&temp, packet + 5, 4); 428 memcpy(&temp, packet + 5, 4);
428 handshake_id2 = ntohl(temp); 429 handshake_id2 = ntohl(temp);
429 430
430 if (handshake_id2 == 0) { 431 if (handshake_id2 == 0) {
431 send_handshake(source, handshake_id(source), handshake_id1); 432 send_handshake(source, handshake_id(source), handshake_id1);
432 return 0; 433 return 0;
@@ -452,7 +453,7 @@ int SYNC_valid(uint32_t length)
452{ 453{
453 if (length < 4 + 4 + 2) 454 if (length < 4 + 4 + 2)
454 return 0; 455 return 0;
455 if (length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) || 456 if (length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) ||
456 ((length - 4 - 4 - 2) % 4) != 0) 457 ((length - 4 - 4 - 2) % 4) != 0)
457 return 0; 458 return 0;
458 return 1; 459 return 1;
@@ -482,7 +483,7 @@ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnu
482int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) 483int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum)
483{ 484{
484 if (recv_packetnum == connections[connection_id].orecv_packetnum) { 485 if (recv_packetnum == connections[connection_id].orecv_packetnum) {
485 /* && sent_packetnum == connections[connection_id].osent_packetnum) */ 486 /* && sent_packetnum == connections[connection_id].osent_packetnum) */
486 connections[connection_id].status = 3; 487 connections[connection_id].status = 3;
487 connections[connection_id].recv_counter = counter; 488 connections[connection_id].recv_counter = counter;
488 ++connections[connection_id].send_counter; 489 ++connections[connection_id].send_counter;
@@ -522,14 +523,14 @@ int handle_SYNC(uint8_t *packet, uint32_t length, IP_Port source)
522{ 523{
523 524
524 if (!SYNC_valid(length)) 525 if (!SYNC_valid(length))
525 return 1; 526 return 1;
526 int connection = getconnection_id(source); 527 int connection = getconnection_id(source);
527 uint8_t counter; 528 uint8_t counter;
528 uint32_t temp; 529 uint32_t temp;
529 uint32_t recv_packetnum, sent_packetnum; 530 uint32_t recv_packetnum, sent_packetnum;
530 uint32_t req_packets[BUFFER_PACKET_NUM]; 531 uint32_t req_packets[BUFFER_PACKET_NUM];
531 uint16_t number = (length - 4 - 4 - 2)/ 4; 532 uint16_t number = (length - 4 - 4 - 2)/ 4;
532 533
533 memcpy(&counter, packet + 1, 1); 534 memcpy(&counter, packet + 1, 1);
534 memcpy(&temp, packet + 2, 4); 535 memcpy(&temp, packet + 2, 4);
535 recv_packetnum = ntohl(temp); 536 recv_packetnum = ntohl(temp);
@@ -556,7 +557,7 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
556 uint32_t i; 557 uint32_t i;
557 uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; 558 uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM;
558 uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; 559 uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum;
559 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 560 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
560 if (i == data_num) { 561 if (i == data_num) {
561 memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); 562 memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size);
562 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; 563 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size;
@@ -568,7 +569,7 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
568 } 569 }
569 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 570 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
570 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) 571 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0)
571 connections[connection_id].recv_packetnum = i; 572 connections[connection_id].recv_packetnum = i;
572 else 573 else
573 break; 574 break;
574 } 575 }
@@ -603,15 +604,15 @@ int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source)
603{ 604{
604 switch (packet[0]) { //TODO: check if no break statement is correct??? 605 switch (packet[0]) { //TODO: check if no break statement is correct???
605 case 16: 606 case 16:
606 return handle_handshake(packet, length, source); 607 return handle_handshake(packet, length, source);
607 608
608 case 17: 609 case 17:
609 return handle_SYNC(packet, length, source); 610 return handle_SYNC(packet, length, source);
610 611
611 case 18: 612 case 18:
612 return handle_data(packet, length, source); 613 return handle_data(packet, length, source);
613 614
614 default: 615 default:
615 return 1; 616 return 1;
616 } 617 }
617 618
@@ -627,13 +628,13 @@ void doNew()
627 for (i = 0; i < MAX_CONNECTIONS; ++i) { 628 for (i = 0; i < MAX_CONNECTIONS; ++i) {
628 if (connections[i].status == 1) 629 if (connections[i].status == 1)
629 if ((connections[i].last_sent + (1000000UL/connections[i].SYNC_rate)) <= temp_time) { 630 if ((connections[i].last_sent + (1000000UL/connections[i].SYNC_rate)) <= temp_time) {
630 send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0); 631 send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0);
631 connections[i].last_sent = temp_time; 632 connections[i].last_sent = temp_time;
632 } 633 }
633 634
634 /* kill all timed out connections */ 635 /* kill all timed out connections */
635 if ( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && 636 if ( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time &&
636 connections[i].status != 4) 637 connections[i].status != 4)
637 /* kill_connection(i); */ 638 /* kill_connection(i); */
638 connections[i].status = 4; 639 connections[i].status = 4;
639 if (connections[i].status > 0 && connections[i].killat < temp_time) 640 if (connections[i].status > 0 && connections[i].killat < temp_time)
@@ -648,8 +649,8 @@ void doSYNC()
648 for (i = 0; i < MAX_CONNECTIONS; ++i) { 649 for (i = 0; i < MAX_CONNECTIONS; ++i) {
649 if (connections[i].status == 2 || connections[i].status == 3) 650 if (connections[i].status == 2 || connections[i].status == 3)
650 if ((connections[i].last_SYNC + (1000000UL/connections[i].SYNC_rate)) <= temp_time) { 651 if ((connections[i].last_SYNC + (1000000UL/connections[i].SYNC_rate)) <= temp_time) {
651 send_SYNC(i); 652 send_SYNC(i);
652 connections[i].last_SYNC = temp_time; 653 connections[i].last_SYNC = temp_time;
653 } 654 }
654 } 655 }
655} 656}
@@ -682,10 +683,9 @@ void adjustRates()
682 connections[i].SYNC_rate = MAX_SYNC_RATE; 683 connections[i].SYNC_rate = MAX_SYNC_RATE;
683 if (connections[i].status == 3) { 684 if (connections[i].status == 3) {
684 if (sendqueue(i) != 0) { 685 if (sendqueue(i) != 0) {
685 connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE; 686 connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE;
686 connections[i].SYNC_rate = MAX_SYNC_RATE; 687 connections[i].SYNC_rate = MAX_SYNC_RATE;
687 } 688 } else if (connections[i].last_recvdata + 1000000UL > temp_time)
688 else if (connections[i].last_recvdata + 1000000UL > temp_time)
689 connections[i].SYNC_rate = MAX_SYNC_RATE; 689 connections[i].SYNC_rate = MAX_SYNC_RATE;
690 else 690 else
691 connections[i].SYNC_rate = SYNC_RATE; 691 connections[i].SYNC_rate = SYNC_RATE;