diff options
Diffstat (limited to 'core/Lossless_UDP.c')
-rw-r--r-- | core/Lossless_UDP.c | 196 |
1 files changed, 123 insertions, 73 deletions
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c index 6be8328f..7a994724 100644 --- a/core/Lossless_UDP.c +++ b/core/Lossless_UDP.c | |||
@@ -45,43 +45,71 @@ timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION | |||
45 | #define DATA_SYNC_RATE 30 | 45 | #define DATA_SYNC_RATE 30 |
46 | 46 | ||
47 | typedef struct { | 47 | typedef 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 | ||
52 | typedef struct { | 52 | typedef 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 | /* |
55 | 2 if handshake is done (we start sending SYNC packets) | 55 | * 0 if connection is dead, 1 if attempting handshake, |
56 | 3 if we are sending SYNC packets and can send data | 56 | * 2 if handshake is done (we start sending SYNC packets) |
57 | 4 if the connection has timed out. */ | 57 | * 3 if we are sending SYNC packets and can send data |
58 | 58 | * 4 if the connection has timed out. | |
59 | uint8_t inbound; /* 1 or 2 if connection was initiated by someone else, 0 if not. | 59 | */ |
60 | 2 if incoming_connection() has not returned it yet, 1 if it has. */ | 60 | uint8_t status; |
61 | 61 | ||
62 | uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */ | 62 | /* |
63 | uint16_t data_rate; /* current data packet send rate packets per second. */ | 63 | * 1 or 2 if connection was initiated by someone else, 0 if not. |
64 | uint64_t last_SYNC; /* time at which our last SYNC packet was sent. */ | 64 | * 2 if incoming_connection() has not returned it yet, 1 if it has. |
65 | uint64_t last_sent; /* time at which our last data or handshake packet was sent. */ | 65 | */ |
66 | uint64_t last_recvSYNC; /* time at which we last received a SYNC packet from the other */ | 66 | uint8_t inbound; |
67 | uint64_t last_recvdata; /* time at which we last received a DATA packet from the other */ | 67 | |
68 | uint64_t killat; /* time at which to kill the connection */ | 68 | uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */ |
69 | Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */ | 69 | uint16_t data_rate; /* current data packet send rate packets per second. */ |
70 | Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */ | 70 | |
71 | uint32_t handshake_id1; | 71 | uint64_t last_SYNC; /* time our last SYNC packet was sent. */ |
72 | uint32_t handshake_id2; | 72 | uint64_t last_sent; /* time our last data or handshake packet was sent. */ |
73 | uint32_t recv_packetnum; /* number of data packets received (also used as handshake_id1) */ | 73 | uint64_t last_recvSYNC; /* time we last received a SYNC packet from the other */ |
74 | uint32_t orecv_packetnum; /* number of packets received by the other peer */ | 74 | uint64_t last_recvdata; /* time we last received a DATA packet from the other */ |
75 | uint32_t sent_packetnum; /* number of data packets sent */ | 75 | uint64_t killat; /* time to kill the connection */ |
76 | uint32_t osent_packetnum; /* number of packets sent by the other peer. */ | 76 | |
77 | uint32_t sendbuff_packetnum; /* number of latest packet written onto the sendbuffer */ | 77 | Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */ |
78 | uint32_t successful_sent; /* we know all packets before that number were successfully sent */ | 78 | Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */ |
79 | uint32_t successful_read; /* packet number of last packet read with the read_packet function */ | 79 | |
80 | uint32_t req_packets[BUFFER_PACKET_NUM]; /* list of currently requested packet numbers(by the other person) */ | 80 | uint32_t handshake_id1; |
81 | uint16_t num_req_paquets; /* total number of currently requested packets(by the other person) */ | 81 | uint32_t handshake_id2; |
82 | uint8_t recv_counter; | 82 | |
83 | uint8_t send_counter; | 83 | /* number of data packets received (also used as handshake_id1) */ |
84 | uint8_t timeout; /* connection timeout in seconds. */ | 84 | uint32_t recv_packetnum; |
85 | |||
86 | /* number of packets received by the other peer */ | ||
87 | uint32_t orecv_packetnum; | ||
88 | |||
89 | /* number of data packets sent */ | ||
90 | uint32_t sent_packetnum; | ||
91 | |||
92 | /* number of packets sent by the other peer. */ | ||
93 | uint32_t osent_packetnum; | ||
94 | |||
95 | /* number of latest packet written onto the sendbuffer */ | ||
96 | uint32_t sendbuff_packetnum; | ||
97 | |||
98 | /* we know all packets before that number were successfully sent */ | ||
99 | uint32_t successful_sent; | ||
100 | |||
101 | /* packet number of last packet read with the read_packet function */ | ||
102 | uint32_t successful_read; | ||
103 | |||
104 | /* list of currently requested packet numbers(by the other person) */ | ||
105 | uint32_t req_packets[BUFFER_PACKET_NUM]; | ||
106 | |||
107 | /* total number of currently requested packets(by the other person) */ | ||
108 | uint16_t num_req_paquets; | ||
109 | |||
110 | uint8_t recv_counter; | ||
111 | uint8_t send_counter; | ||
112 | uint8_t timeout; /* connection timeout in seconds. */ | ||
85 | } Connection; | 113 | } Connection; |
86 | 114 | ||
87 | 115 | ||
@@ -159,22 +187,26 @@ int new_connection(IP_Port ip_port) | |||
159 | for (i = 0; i < MAX_CONNECTIONS; ++i) { | 187 | for (i = 0; i < MAX_CONNECTIONS; ++i) { |
160 | if(connections[i].status == 0) { | 188 | if(connections[i].status == 0) { |
161 | memset(&connections[i], 0, sizeof(Connection)); | 189 | memset(&connections[i], 0, sizeof(Connection)); |
162 | connections[i].ip_port = ip_port; | 190 | |
163 | connections[i].status = 1; | 191 | connections[i] = (Connection) { |
164 | connections[i].inbound = 0; | 192 | .ip_port = ip_port, |
165 | connections[i].handshake_id1 = handshake_id(ip_port); | 193 | .status = 1, |
166 | connections[i].sent_packetnum = connections[i].handshake_id1; | 194 | .inbound = 0, |
167 | connections[i].sendbuff_packetnum = connections[i].handshake_id1; | 195 | .handshake_id1 = handshake_id(ip_port), |
168 | connections[i].successful_sent = connections[i].handshake_id1; | 196 | .sent_packetnum = connections[i].handshake_id1, |
169 | connections[i].SYNC_rate = SYNC_RATE; | 197 | .sendbuff_packetnum = connections[i].handshake_id1, |
170 | connections[i].data_rate = DATA_SYNC_RATE; | 198 | .successful_sent = connections[i].handshake_id1, |
171 | connections[i].last_recvSYNC = current_time(); | 199 | .SYNC_rate = SYNC_RATE, |
172 | connections[i].last_sent = current_time(); | 200 | .data_rate = DATA_SYNC_RATE, |
173 | connections[i].killat = ~0; | 201 | .last_recvSYNC = current_time(), |
174 | connections[i].send_counter = 0; | 202 | .last_sent = current_time(), |
175 | /* add randomness to timeout to prevent connections getting stuck in a loop. */ | 203 | .killat = ~0, |
176 | connections[i].timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; | 204 | .send_counter = 0, |
205 | /* add randomness to timeout to prevent connections getting stuck in a loop. */ | ||
206 | .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT | ||
207 | }; | ||
177 | ++connections_number; | 208 | ++connections_number; |
209 | |||
178 | return i; | 210 | return i; |
179 | } | 211 | } |
180 | } | 212 | } |
@@ -203,18 +235,23 @@ int new_inconnection(IP_Port ip_port) | |||
203 | for (i = 0; i < MAX_CONNECTIONS; ++i) { | 235 | for (i = 0; i < MAX_CONNECTIONS; ++i) { |
204 | if (connections[i].status == 0) { | 236 | if (connections[i].status == 0) { |
205 | memset(&connections[i], 0, sizeof(Connection)); | 237 | memset(&connections[i], 0, sizeof(Connection)); |
206 | connections[i].ip_port = ip_port; | 238 | |
207 | connections[i].status = 2; | 239 | connections[i] = (Connection){ |
208 | connections[i].inbound = 2; | 240 | .ip_port = ip_port, |
209 | connections[i].SYNC_rate = SYNC_RATE; | 241 | .status = 2, |
210 | connections[i].data_rate = DATA_SYNC_RATE; | 242 | .inbound = 2, |
211 | connections[i].last_recvSYNC = current_time(); | 243 | .SYNC_rate = SYNC_RATE, |
212 | connections[i].last_sent = current_time(); | 244 | .data_rate = DATA_SYNC_RATE, |
213 | /* add randomness to timeout to prevent connections getting stuck in a loop. */ | 245 | .last_recvSYNC = current_time(), |
214 | connections[i].timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; | 246 | .last_sent = current_time(), |
215 | /* if this connection isn't handled within the timeout kill it. */ | 247 | .send_counter = 127, |
216 | connections[i].killat = current_time() + 1000000UL*connections[i].timeout; | 248 | |
217 | connections[i].send_counter = 127; | 249 | /* add randomness to timeout to prevent connections getting stuck in a loop. */ |
250 | .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT, | ||
251 | |||
252 | /* if this connection isn't handled within the timeout kill it. */ | ||
253 | .killat = current_time() + 1000000UL*connections[i].timeout | ||
254 | }; | ||
218 | ++connections_number; | 255 | ++connections_number; |
219 | return i; | 256 | return i; |
220 | } | 257 | } |
@@ -245,10 +282,12 @@ static void free_connections() | |||
245 | 282 | ||
246 | if(connections_length == i) | 283 | if(connections_length == i) |
247 | return; | 284 | return; |
285 | |||
248 | Connection * temp; | 286 | Connection * temp; |
249 | temp = realloc(connections, sizeof(Connection) * i); | 287 | temp = realloc(connections, sizeof(Connection) * i); |
250 | if(temp == NULL && i != 0) | 288 | if(temp == NULL && i != 0) |
251 | return; | 289 | return; |
290 | |||
252 | connections = temp; | 291 | connections = temp; |
253 | connections_length = i; | 292 | connections_length = i; |
254 | } | 293 | } |
@@ -338,7 +377,7 @@ int read_packet(int connection_id, uint8_t * data) | |||
338 | { | 377 | { |
339 | if (recvqueue(connection_id) != 0) { | 378 | if (recvqueue(connection_id) != 0) { |
340 | uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; | 379 | uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; |
341 | uint16_t size = connections[connection_id].recvbuffer[index].size; | 380 | uint16_t size = connections[connection_id].recvbuffer[index].size; |
342 | memcpy(data, connections[connection_id].recvbuffer[index].data, size); | 381 | memcpy(data, connections[connection_id].recvbuffer[index].data, size); |
343 | ++connections[connection_id].successful_read; | 382 | ++connections[connection_id].successful_read; |
344 | connections[connection_id].recvbuffer[index].size = 0; | 383 | connections[connection_id].recvbuffer[index].size = 0; |
@@ -353,8 +392,10 @@ int write_packet(int connection_id, uint8_t * data, uint32_t length) | |||
353 | { | 392 | { |
354 | if (length > MAX_DATA_SIZE) | 393 | if (length > MAX_DATA_SIZE) |
355 | return 0; | 394 | return 0; |
395 | |||
356 | if (length == 0) | 396 | if (length == 0) |
357 | return 0; | 397 | return 0; |
398 | |||
358 | if (sendqueue(connection_id) < BUFFER_PACKET_NUM) { | 399 | if (sendqueue(connection_id) < BUFFER_PACKET_NUM) { |
359 | uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; | 400 | uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; |
360 | memcpy(connections[connection_id].sendbuffer[index].data, data, length); | 401 | memcpy(connections[connection_id].sendbuffer[index].data, data, length); |
@@ -398,6 +439,7 @@ int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_i | |||
398 | memcpy(packet + 1, &temp, 4); | 439 | memcpy(packet + 1, &temp, 4); |
399 | temp = htonl(handshake_id2); | 440 | temp = htonl(handshake_id2); |
400 | memcpy(packet + 5, &temp, 4); | 441 | memcpy(packet + 5, &temp, 4); |
442 | |||
401 | return sendpacket(ip_port, packet, sizeof(packet)); | 443 | return sendpacket(ip_port, packet, sizeof(packet)); |
402 | } | 444 | } |
403 | 445 | ||
@@ -407,12 +449,14 @@ int send_SYNC(uint32_t connection_id) | |||
407 | uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; | 449 | uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; |
408 | uint16_t index = 0; | 450 | uint16_t index = 0; |
409 | 451 | ||
410 | IP_Port ip_port = connections[connection_id].ip_port; | 452 | IP_Port ip_port = connections[connection_id].ip_port; |
411 | uint8_t counter = connections[connection_id].send_counter; | 453 | uint8_t counter = connections[connection_id].send_counter; |
412 | uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum); | 454 | uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum); |
413 | uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum); | 455 | uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum); |
456 | |||
414 | uint32_t requested[BUFFER_PACKET_NUM]; | 457 | uint32_t requested[BUFFER_PACKET_NUM]; |
415 | uint32_t number = missing_packets(connection_id, requested); | 458 | uint32_t number = missing_packets(connection_id, requested); |
459 | |||
416 | 460 | ||
417 | packet[0] = 17; | 461 | packet[0] = 17; |
418 | index += 1; | 462 | index += 1; |
@@ -598,8 +642,10 @@ int handle_SYNC(uint8_t *packet, uint32_t length, IP_Port source) | |||
598 | return 0; | 642 | return 0; |
599 | } | 643 | } |
600 | 644 | ||
601 | /* add a packet to the received buffer and set the recv_packetnum of the connection to its proper value. | 645 | /* |
602 | return 1 if data was too big, 0 if not. */ | 646 | * Add a packet to the received buffer and set the recv_packetnum of the |
647 | * connection to its proper value. Return 1 if data was too big, 0 if not. | ||
648 | */ | ||
603 | int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) | 649 | int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) |
604 | { | 650 | { |
605 | if (size > MAX_DATA_SIZE) | 651 | if (size > MAX_DATA_SIZE) |
@@ -635,7 +681,8 @@ int handle_data(uint8_t *packet, uint32_t length, IP_Port source) | |||
635 | if (connection == -1) | 681 | if (connection == -1) |
636 | return 1; | 682 | return 1; |
637 | 683 | ||
638 | if (connections[connection].status != 3) /* Drop the data packet if connection is not connected. */ | 684 | /* Drop the data packet if connection is not connected. */ |
685 | if (connections[connection].status != 3) | ||
639 | return 1; | 686 | return 1; |
640 | 687 | ||
641 | if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) | 688 | if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) |
@@ -650,10 +697,9 @@ int handle_data(uint8_t *packet, uint32_t length, IP_Port source) | |||
650 | } | 697 | } |
651 | 698 | ||
652 | /* END of packet handling functions */ | 699 | /* END of packet handling functions */ |
653 | |||
654 | int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source) | 700 | int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source) |
655 | { | 701 | { |
656 | switch (packet[0]) { //TODO: check if no break statement is correct??? | 702 | switch (packet[0]) { |
657 | case 16: | 703 | case 16: |
658 | return handle_handshake(packet, length, source); | 704 | return handle_handshake(packet, length, source); |
659 | 705 | ||
@@ -670,8 +716,10 @@ int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source) | |||
670 | return 0; | 716 | return 0; |
671 | } | 717 | } |
672 | 718 | ||
673 | /* Send handshake requests | 719 | /* |
674 | handshake packets are sent at the same rate as SYNC packets */ | 720 | * Send handshake requests |
721 | * handshake packets are sent at the same rate as SYNC packets | ||
722 | */ | ||
675 | void doNew() | 723 | void doNew() |
676 | { | 724 | { |
677 | uint32_t i; | 725 | uint32_t i; |
@@ -720,11 +768,13 @@ void doData() | |||
720 | } | 768 | } |
721 | } | 769 | } |
722 | 770 | ||
723 | /* TODO: flow control. | ||
724 | automatically adjusts send rates of packets for optimal transmission. */ | ||
725 | |||
726 | #define MAX_SYNC_RATE 10 | 771 | #define MAX_SYNC_RATE 10 |
727 | 772 | ||
773 | /* | ||
774 | * Automatically adjusts send rates of packets for optimal transmission. | ||
775 | * | ||
776 | * TODO: flow control. | ||
777 | */ | ||
728 | void adjustRates() | 778 | void adjustRates() |
729 | { | 779 | { |
730 | uint32_t i; | 780 | uint32_t i; |