diff options
-rw-r--r-- | core/Lossless_UDP.c | 251 | ||||
-rw-r--r-- | core/Lossless_UDP.h | 23 | ||||
-rw-r--r-- | testing/Lossless_UDP_testclient.c | 42 | ||||
-rw-r--r-- | testing/Lossless_UDP_testserver.c | 37 |
4 files changed, 260 insertions, 93 deletions
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c index 7ef818e8..82a0493f 100644 --- a/core/Lossless_UDP.c +++ b/core/Lossless_UDP.c | |||
@@ -2,18 +2,38 @@ | |||
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 | |||
6 | Copyright (C) 2013 Tox project All Rights Reserved. | ||
7 | |||
8 | This file is part of Tox. | ||
9 | |||
10 | Tox is free software: you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation, either version 3 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | Tox is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
22 | |||
5 | */ | 23 | */ |
6 | 24 | ||
7 | #include "Lossless_UDP.h" | 25 | #include "Lossless_UDP.h" |
8 | 26 | ||
27 | |||
28 | |||
9 | //maximum data packets in sent and recieve queues. | 29 | //maximum data packets in sent and recieve queues. |
10 | #define MAX_QUEUE_NUM 32 | 30 | #define MAX_QUEUE_NUM 32 |
11 | 31 | ||
12 | //maximum length of the data in the data packets | 32 | //maximum length of the data in the data packets |
13 | #define PDATA_SIZE 1024 | 33 | #define MAX_DATA_SIZE 1024 |
14 | 34 | ||
15 | //maximum number of data packets that can be sent/recieved at the same time | 35 | //maximum number of data packets in the buffer |
16 | #define MAX_PACKET_NUM (MAX_QUEUE_NUM/4) | 36 | #define BUFFER_PACKET_NUM MAX_QUEUE_NUM |
17 | 37 | ||
18 | //Lossless UDP connection timeout. | 38 | //Lossless UDP connection timeout. |
19 | #define CONNEXION_TIMEOUT 10 | 39 | #define CONNEXION_TIMEOUT 10 |
@@ -21,12 +41,12 @@ | |||
21 | //initial amount of sync/hanshake packets to send per second. | 41 | //initial amount of sync/hanshake packets to send per second. |
22 | #define SYNC_RATE 5 | 42 | #define SYNC_RATE 5 |
23 | 43 | ||
24 | //send rate of sync packets when data is being sent/recieved. | 44 | //initial send rate of sync packets when data is being sent/recieved. |
25 | #define DATA_SYNC_RATE 20 | 45 | #define DATA_SYNC_RATE 20 |
26 | 46 | ||
27 | typedef struct | 47 | typedef struct |
28 | { | 48 | { |
29 | char data[PDATA_SIZE]; | 49 | char data[MAX_DATA_SIZE]; |
30 | uint16_t size; | 50 | uint16_t size; |
31 | }Data; | 51 | }Data; |
32 | 52 | ||
@@ -56,7 +76,7 @@ typedef struct | |||
56 | uint32_t sendbuff_packetnum; //number of latest packet written onto the sendbuffer | 76 | uint32_t sendbuff_packetnum; //number of latest packet written onto the sendbuffer |
57 | uint32_t successful_sent;//we know all packets before that number were successfully sent | 77 | uint32_t successful_sent;//we know all packets before that number were successfully sent |
58 | uint32_t successful_read;//packet number of last packet read with the read_packet function | 78 | uint32_t successful_read;//packet number of last packet read with the read_packet function |
59 | uint32_t req_packets[MAX_PACKET_NUM]; //list of currently requested packet numbers(by the other person) | 79 | uint32_t req_packets[BUFFER_PACKET_NUM]; //list of currently requested packet numbers(by the other person) |
60 | uint16_t num_req_paquets; //total number of currently requested packets(by the other person) | 80 | uint16_t num_req_paquets; //total number of currently requested packets(by the other person) |
61 | uint8_t recv_counter; | 81 | uint8_t recv_counter; |
62 | uint8_t send_counter; | 82 | uint8_t send_counter; |
@@ -83,6 +103,9 @@ int new_connection(IP_Port ip_port) | |||
83 | connections[i].status = 1; | 103 | connections[i].status = 1; |
84 | connections[i].inbound = 0; | 104 | connections[i].inbound = 0; |
85 | connections[i].handshake_id1 = random_int(); | 105 | connections[i].handshake_id1 = random_int(); |
106 | connections[i].sent_packetnum = connections[i].handshake_id1; | ||
107 | connections[i].sendbuff_packetnum = connections[i].handshake_id1; | ||
108 | connections[i].successful_sent = connections[i].handshake_id1; | ||
86 | connections[i].SYNC_rate = SYNC_RATE; | 109 | connections[i].SYNC_rate = SYNC_RATE; |
87 | connections[i].data_rate = DATA_SYNC_RATE; | 110 | connections[i].data_rate = DATA_SYNC_RATE; |
88 | connections[i].last_recv = current_time(); | 111 | connections[i].last_recv = current_time(); |
@@ -144,11 +167,41 @@ int kill_connection(int connection_id) | |||
144 | return -1; | 167 | return -1; |
145 | } | 168 | } |
146 | 169 | ||
170 | //check if connection is connected | ||
171 | //return 0 no. | ||
172 | //return 1 if attempting handshake | ||
173 | //return 2 if handshake is done | ||
174 | //return 3 if fully connected | ||
175 | int is_connected(int connection_id) | ||
176 | { | ||
177 | return connections[connection_id].status; | ||
178 | } | ||
179 | |||
180 | //returns the number of packets in the queue waiting to be successfully sent. | ||
181 | uint32_t sendqueue(int connection_id) | ||
182 | { | ||
183 | return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent; | ||
184 | } | ||
185 | |||
186 | //returns the number of packets in the queue waiting to be successfully read with read_packet(...) | ||
187 | uint32_t recvqueue(int connection_id) | ||
188 | { | ||
189 | return connections[connection_id].recv_packetnum - connections[connection_id].successful_read; | ||
190 | } | ||
191 | |||
147 | //return 0 if there is no received data in the buffer. | 192 | //return 0 if there is no received data in the buffer. |
148 | //return length of received packet if successful | 193 | //return length of received packet if successful |
149 | int read_packet(int connection_id, char * data) | 194 | int read_packet(int connection_id, char * data) |
150 | { | 195 | { |
151 | 196 | if(recvqueue(connection_id) != 0) | |
197 | { | ||
198 | uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; | ||
199 | uint16_t size = connections[connection_id].recvbuffer[index].size; | ||
200 | memcpy(data, connections[connection_id].recvbuffer[index].data, size); | ||
201 | connections[connection_id].successful_read++; | ||
202 | connections[connection_id].recvbuffer[index].size = 0; | ||
203 | return size; | ||
204 | } | ||
152 | return 0; | 205 | return 0; |
153 | } | 206 | } |
154 | 207 | ||
@@ -156,34 +209,27 @@ int read_packet(int connection_id, char * data) | |||
156 | //return 1 if data was put into the queue | 209 | //return 1 if data was put into the queue |
157 | int write_packet(int connection_id, char * data, uint32_t length) | 210 | int write_packet(int connection_id, char * data, uint32_t length) |
158 | { | 211 | { |
159 | 212 | if(length > MAX_DATA_SIZE) | |
160 | 213 | { | |
214 | return 0; | ||
215 | } | ||
216 | if(length == 0) | ||
217 | { | ||
218 | return 0; | ||
219 | } | ||
220 | if(sendqueue(connection_id) < MAX_QUEUE_NUM) | ||
221 | { | ||
222 | uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; | ||
223 | memcpy(connections[connection_id].sendbuffer[index].data, data, length); | ||
224 | connections[connection_id].sendbuffer[index].size = length; | ||
225 | connections[connection_id].sendbuff_packetnum++; | ||
226 | return 1; | ||
227 | } | ||
161 | return 0; | 228 | return 0; |
162 | } | 229 | } |
163 | 230 | ||
164 | 231 | ||
165 | 232 | ||
166 | //returns the number of packets in the queue waiting to be successfully sent. | ||
167 | int sendqueue(int connection_id) | ||
168 | { | ||
169 | return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent; | ||
170 | } | ||
171 | |||
172 | //returns the number of packets in the queue waiting to be successfully read with read_packet(...) | ||
173 | int recvqueue(int connection_id) | ||
174 | { | ||
175 | return connections[connection_id].recv_packetnum - connections[connection_id].successful_read; | ||
176 | } | ||
177 | |||
178 | //check if connection is connected | ||
179 | //return 0 no. | ||
180 | //return 1 if attempting handshake | ||
181 | //return 2 if handshake is done | ||
182 | //return 3 if fully connected | ||
183 | int is_connected(int connection_id) | ||
184 | { | ||
185 | return connections[connection_id].status; | ||
186 | } | ||
187 | 233 | ||
188 | //put the packet numbers the we are missing in requested and return the number | 234 | //put the packet numbers the we are missing in requested and return the number |
189 | uint32_t missing_packets(int connection_id, uint32_t * requested) | 235 | uint32_t missing_packets(int connection_id, uint32_t * requested) |
@@ -194,10 +240,14 @@ uint32_t missing_packets(int connection_id, uint32_t * requested) | |||
194 | { | 240 | { |
195 | if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) | 241 | if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) |
196 | { | 242 | { |
197 | memcpy(requested, &i, number); | 243 | memcpy(requested + number, &i, 4); |
198 | number++; | 244 | number++; |
199 | } | 245 | } |
200 | } | 246 | } |
247 | if(number == 0) | ||
248 | { | ||
249 | connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; | ||
250 | } | ||
201 | return number; | 251 | return number; |
202 | 252 | ||
203 | } | 253 | } |
@@ -221,14 +271,14 @@ int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_i | |||
221 | int send_SYNC(uint32_t connection_id) | 271 | int send_SYNC(uint32_t connection_id) |
222 | { | 272 | { |
223 | 273 | ||
224 | char packet[(MAX_PACKET_NUM*4 + 4 + 4 + 2)]; | 274 | char packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; |
225 | uint16_t index = 0; | 275 | uint16_t index = 0; |
226 | 276 | ||
227 | IP_Port ip_port = connections[connection_id].ip_port; | 277 | IP_Port ip_port = connections[connection_id].ip_port; |
228 | uint8_t counter = connections[connection_id].send_counter; | 278 | uint8_t counter = connections[connection_id].send_counter; |
229 | uint32_t recv_packetnum = connections[connection_id].recv_packetnum; | 279 | uint32_t recv_packetnum = connections[connection_id].recv_packetnum; |
230 | uint32_t sent_packetnum = connections[connection_id].sent_packetnum; | 280 | uint32_t sent_packetnum = connections[connection_id].sent_packetnum; |
231 | uint32_t requested[MAX_PACKET_NUM]; | 281 | uint32_t requested[BUFFER_PACKET_NUM]; |
232 | uint32_t number = missing_packets(connection_id, requested); | 282 | uint32_t number = missing_packets(connection_id, requested); |
233 | 283 | ||
234 | packet[0] = 17; | 284 | packet[0] = 17; |
@@ -245,21 +295,39 @@ int send_SYNC(uint32_t connection_id) | |||
245 | 295 | ||
246 | } | 296 | } |
247 | 297 | ||
248 | 298 | int send_data_packet(uint32_t connection_id, uint32_t packet_num) | |
249 | int send_data(IP_Port ip_port, uint32_t packet_num, char * data, uint32_t length) | ||
250 | { | 299 | { |
251 | if(length > PDATA_SIZE) | 300 | uint32_t index = packet_num % MAX_QUEUE_NUM; |
252 | { | 301 | char packet[1 + 4 + MAX_DATA_SIZE]; |
253 | return -1; | ||
254 | } | ||
255 | char packet[1 + 4 + PDATA_SIZE]; | ||
256 | |||
257 | packet[0] = 18; | 302 | packet[0] = 18; |
258 | memcpy(packet + 1, &packet_num, 4); | 303 | memcpy(packet + 1, &packet_num, 4); |
259 | memcpy(packet + 5, data, length); | 304 | memcpy(packet + 5, connections[connection_id].sendbuffer[index].data, |
260 | return sendpacket(ip_port, packet, 1 + 4 + length); | 305 | connections[connection_id].sendbuffer[index].size); |
306 | return sendpacket(connections[connection_id].ip_port, packet, | ||
307 | 1 + 4 + connections[connection_id].sendbuffer[index].size); | ||
261 | } | 308 | } |
262 | 309 | ||
310 | //sends 1 data packet | ||
311 | int send_DATA(uint32_t connection_id) | ||
312 | { | ||
313 | int ret; | ||
314 | uint32_t buffer[BUFFER_PACKET_NUM]; | ||
315 | if(connections[connection_id].num_req_paquets > 0) | ||
316 | { | ||
317 | ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]); | ||
318 | connections[connection_id].num_req_paquets--; | ||
319 | memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4); | ||
320 | memcpy(connections[connection_id].req_packets, buffer, connections[connection_id].num_req_paquets * 4); | ||
321 | return ret; | ||
322 | } | ||
323 | if(connections[connection_id].sendbuff_packetnum != connections[connection_id].sent_packetnum) | ||
324 | { | ||
325 | ret = send_data_packet(connection_id, connections[connection_id].sent_packetnum); | ||
326 | connections[connection_id].sent_packetnum++; | ||
327 | return ret; | ||
328 | } | ||
329 | return 0; | ||
330 | } | ||
263 | 331 | ||
264 | //END of packet sending functions | 332 | //END of packet sending functions |
265 | 333 | ||
@@ -281,7 +349,7 @@ int getconnection_id(IP_Port ip_port) | |||
281 | } | 349 | } |
282 | 350 | ||
283 | //table of random numbers used below. | 351 | //table of random numbers used below. |
284 | uint32_t randtable[6][256]; | 352 | static uint32_t randtable[6][256]; |
285 | 353 | ||
286 | 354 | ||
287 | //generate a handshake_id which depends on the ip_port. | 355 | //generate a handshake_id which depends on the ip_port. |
@@ -333,9 +401,9 @@ int handle_handshake(char * packet, uint32_t length, IP_Port source) | |||
333 | //NOTE:is this necessary? | 401 | //NOTE:is this necessary? |
334 | //connections[connection].handshake_id2 = handshake_id2; | 402 | //connections[connection].handshake_id2 = handshake_id2; |
335 | connections[connection].orecv_packetnum = handshake_id1; | 403 | connections[connection].orecv_packetnum = handshake_id1; |
336 | connections[connection].sent_packetnum = handshake_id1; | ||
337 | connections[connection].osent_packetnum = handshake_id2; | 404 | connections[connection].osent_packetnum = handshake_id2; |
338 | connections[connection].recv_packetnum = handshake_id2; | 405 | connections[connection].recv_packetnum = handshake_id2; |
406 | connections[connection].successful_read = handshake_id2; | ||
339 | } | 407 | } |
340 | return 0; | 408 | return 0; |
341 | 409 | ||
@@ -349,7 +417,7 @@ int SYNC_valid(uint32_t length) | |||
349 | { | 417 | { |
350 | return 0; | 418 | return 0; |
351 | } | 419 | } |
352 | if(length > (MAX_PACKET_NUM*4 + 4 + 4 + 2) || | 420 | if(length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) || |
353 | ((length - 4 - 4 - 2) % 4) != 0) | 421 | ((length - 4 - 4 - 2) % 4) != 0) |
354 | { | 422 | { |
355 | return 0; | 423 | return 0; |
@@ -367,9 +435,12 @@ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnu | |||
367 | { | 435 | { |
368 | connections[x].orecv_packetnum = recv_packetnum; | 436 | connections[x].orecv_packetnum = recv_packetnum; |
369 | connections[x].sent_packetnum = recv_packetnum; | 437 | connections[x].sent_packetnum = recv_packetnum; |
438 | connections[x].sendbuff_packetnum = recv_packetnum; | ||
439 | connections[x].successful_sent = recv_packetnum; | ||
370 | connections[x].osent_packetnum = sent_packetnum; | 440 | connections[x].osent_packetnum = sent_packetnum; |
371 | connections[x].recv_packetnum = sent_packetnum; | 441 | connections[x].recv_packetnum = sent_packetnum; |
372 | 442 | connections[x].successful_read = sent_packetnum; | |
443 | |||
373 | return x; | 444 | return x; |
374 | } | 445 | } |
375 | } | 446 | } |
@@ -379,26 +450,28 @@ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnu | |||
379 | //case 2: | 450 | //case 2: |
380 | int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) | 451 | int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) |
381 | { | 452 | { |
382 | if(recv_packetnum == connections[connection_id].orecv_packetnum && | 453 | if(recv_packetnum == connections[connection_id].orecv_packetnum) |
383 | sent_packetnum == connections[connection_id].osent_packetnum) | 454 | //&& sent_packetnum == connections[connection_id].osent_packetnum) |
384 | { | 455 | { |
385 | connections[connection_id].status = 3; | 456 | connections[connection_id].status = 3; |
386 | connections[connection_id].recv_counter = counter; | 457 | connections[connection_id].recv_counter = counter; |
387 | connections[connection_id].send_counter++; | 458 | connections[connection_id].send_counter++; |
388 | return 0; | 459 | return 0; |
389 | } | 460 | } |
461 | return 1; | ||
390 | } | 462 | } |
391 | //case 3: | 463 | //case 3: |
392 | int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets, | 464 | int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets, |
393 | uint16_t number) | 465 | uint16_t number) |
394 | { | 466 | { |
395 | uint8_t comp_counter = (connections[connection_id].recv_counter + 1); | 467 | uint8_t comp_counter = (counter - connections[connection_id].recv_counter ); |
396 | if((recv_packetnum - connections[connection_id].orecv_packetnum) < MAX_PACKET_NUM && | 468 | uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum); |
397 | (sent_packetnum - connections[connection_id].osent_packetnum) < MAX_PACKET_NUM && | 469 | uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum); |
398 | counter == comp_counter) //packet valid | 470 | if(comp_1 < BUFFER_PACKET_NUM && comp_2 < BUFFER_PACKET_NUM && comp_counter < 10) //packet valid |
399 | { | 471 | { |
400 | connections[connection_id].orecv_packetnum = recv_packetnum; | 472 | connections[connection_id].orecv_packetnum = recv_packetnum; |
401 | connections[connection_id].osent_packetnum = sent_packetnum; | 473 | connections[connection_id].osent_packetnum = sent_packetnum; |
474 | connections[connection_id].successful_sent = recv_packetnum; | ||
402 | connections[connection_id].last_recv = current_time(); | 475 | connections[connection_id].last_recv = current_time(); |
403 | connections[connection_id].recv_counter = counter; | 476 | connections[connection_id].recv_counter = counter; |
404 | connections[connection_id].send_counter++; | 477 | connections[connection_id].send_counter++; |
@@ -419,7 +492,7 @@ int handle_SYNC(char * packet, uint32_t length, IP_Port source) | |||
419 | int connection = getconnection_id(source); | 492 | int connection = getconnection_id(source); |
420 | uint8_t counter; | 493 | uint8_t counter; |
421 | uint32_t recv_packetnum, sent_packetnum; | 494 | uint32_t recv_packetnum, sent_packetnum; |
422 | uint32_t req_packets[MAX_PACKET_NUM]; | 495 | uint32_t req_packets[BUFFER_PACKET_NUM]; |
423 | uint16_t number = (length - 4 - 4 - 2)/ 4; | 496 | uint16_t number = (length - 4 - 4 - 2)/ 4; |
424 | 497 | ||
425 | memcpy(&counter, packet + 1, 1); | 498 | memcpy(&counter, packet + 1, 1); |
@@ -446,8 +519,63 @@ int handle_SYNC(char * packet, uint32_t length, IP_Port source) | |||
446 | return 0; | 519 | return 0; |
447 | } | 520 | } |
448 | 521 | ||
522 | //add a packet to the recieved buffer and set the recv_packetnum of the connection to its proper value. | ||
523 | //return 1 if data was too big, 0 if not. | ||
524 | int add_recv(int connection_id, uint32_t data_num, char * data, uint16_t size) | ||
525 | { | ||
526 | if(size > MAX_DATA_SIZE) | ||
527 | { | ||
528 | return 1; | ||
529 | } | ||
530 | |||
531 | uint32_t i; | ||
532 | uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; | ||
533 | uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; | ||
534 | for(i = connections[connection_id].recv_packetnum; i != maxnum; i++) | ||
535 | { | ||
536 | if(i == data_num) | ||
537 | { | ||
538 | memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); | ||
539 | connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; | ||
540 | if(sent_packet < BUFFER_PACKET_NUM) | ||
541 | { | ||
542 | connections[connection_id].osent_packetnum = data_num; | ||
543 | } | ||
544 | break; | ||
545 | } | ||
546 | } | ||
547 | for(i = connections[connection_id].recv_packetnum; i != maxnum; i++) | ||
548 | { | ||
549 | if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) | ||
550 | { | ||
551 | connections[connection_id].recv_packetnum = i; | ||
552 | } | ||
553 | else | ||
554 | { | ||
555 | break; | ||
556 | } | ||
557 | } | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
449 | int handle_data(char * packet, uint32_t length, IP_Port source) | 562 | int handle_data(char * packet, uint32_t length, IP_Port source) |
450 | { | 563 | { |
564 | int connection = getconnection_id(source); | ||
565 | |||
566 | if(connection == -1) | ||
567 | { | ||
568 | return 1; | ||
569 | } | ||
570 | if(length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) | ||
571 | { | ||
572 | return 1; | ||
573 | } | ||
574 | uint32_t number; | ||
575 | uint16_t size = length - 1 - 4; | ||
576 | |||
577 | memcpy(&number, packet + 1, 4); | ||
578 | return add_recv(connection, number, packet + 5, size); | ||
451 | 579 | ||
452 | } | 580 | } |
453 | 581 | ||
@@ -477,7 +605,6 @@ int LosslessUDP_handlepacket(char * packet, uint32_t length, IP_Port source) | |||
477 | } | 605 | } |
478 | 606 | ||
479 | //Send handshake requests | 607 | //Send handshake requests |
480 | //TODO: optimize this. | ||
481 | //handshake packets are sent at the same rate as SYNC packets | 608 | //handshake packets are sent at the same rate as SYNC packets |
482 | void doNew() | 609 | void doNew() |
483 | { | 610 | { |
@@ -521,7 +648,19 @@ void doSYNC() | |||
521 | 648 | ||
522 | void doData() | 649 | void doData() |
523 | { | 650 | { |
524 | 651 | uint32_t i; | |
652 | uint64_t temp_time = current_time(); | ||
653 | for(i = 0; i < MAX_CONNECTIONS; i++) | ||
654 | { | ||
655 | if(connections[i].status == 3) | ||
656 | { | ||
657 | if((connections[i].last_sent + (1000000UL/connections[i].data_rate)) <= temp_time) | ||
658 | { | ||
659 | send_DATA(i); | ||
660 | connections[i].last_sent = temp_time; | ||
661 | } | ||
662 | } | ||
663 | } | ||
525 | } | 664 | } |
526 | 665 | ||
527 | //TODO: flow control. | 666 | //TODO: flow control. |
diff --git a/core/Lossless_UDP.h b/core/Lossless_UDP.h index f8021f5a..8f5503ea 100644 --- a/core/Lossless_UDP.h +++ b/core/Lossless_UDP.h | |||
@@ -2,7 +2,26 @@ | |||
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 | |||
6 | Copyright (C) 2013 Tox project All Rights Reserved. | ||
7 | |||
8 | This file is part of Tox. | ||
9 | |||
10 | Tox is free software: you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation, either version 3 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | Tox is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
22 | |||
5 | */ | 23 | */ |
24 | |||
6 | #ifndef LOSSLESS_UDP_H | 25 | #ifndef LOSSLESS_UDP_H |
7 | #define LOSSLESS_UDP_H | 26 | #define LOSSLESS_UDP_H |
8 | 27 | ||
@@ -33,10 +52,10 @@ int read_packet(int connection_id, char * data); | |||
33 | int write_packet(int connection_id, char * data, uint32_t length); | 52 | int write_packet(int connection_id, char * data, uint32_t length); |
34 | 53 | ||
35 | //returns the number of packets in the queue waiting to be successfully sent. | 54 | //returns the number of packets in the queue waiting to be successfully sent. |
36 | int sendqueue(int connection_id); | 55 | uint32_t sendqueue(int connection_id); |
37 | 56 | ||
38 | //returns the number of packets in the queue waiting to be successfully read with read_packet(...) | 57 | //returns the number of packets in the queue waiting to be successfully read with read_packet(...) |
39 | int recvqueue(int connection_id); | 58 | uint32_t recvqueue(int connection_id); |
40 | 59 | ||
41 | //check if connection is connected | 60 | //check if connection is connected |
42 | //return 0 no. | 61 | //return 0 no. |
diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c index 20fae86f..5790ad3b 100644 --- a/testing/Lossless_UDP_testclient.c +++ b/testing/Lossless_UDP_testclient.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* Lossless_UDP testclient | 1 | /* Lossless_UDP testclient |
2 | * A program that connects and sends a file using our lossless UDP algorithm. | 2 | * A program that connects and sends a file using our lossless UDP algorithm. |
3 | * NOTE: this program simulates a 33% packet loss. | ||
3 | * | 4 | * |
4 | * Best used in combination with Lossless_UDP_testserver | 5 | * Best used in combination with Lossless_UDP_testserver |
5 | * | 6 | * |
@@ -44,7 +45,7 @@ void printip(IP_Port ip_port) | |||
44 | { | 45 | { |
45 | printf("\nIP: %u.%u.%u.%u Port: %u",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); | 46 | printf("\nIP: %u.%u.%u.%u Port: %u",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); |
46 | } | 47 | } |
47 | 48 | /* | |
48 | void printpackets(Data test) | 49 | void printpackets(Data test) |
49 | { | 50 | { |
50 | int i; | 51 | int i; |
@@ -80,14 +81,14 @@ void printconnection(int connection_id) | |||
80 | } | 81 | } |
81 | Data sendbuffer[MAX_QUEUE_NUM]; | 82 | Data sendbuffer[MAX_QUEUE_NUM]; |
82 | Data recvbuffer[MAX_QUEUE_NUM]; | 83 | Data recvbuffer[MAX_QUEUE_NUM]; |
83 | printf("recv_num: %u, recv_sync: %u, sent_packetnum %u, send_packetnum: %u, successful_sent: %u, successful_read: %u\n", | 84 | printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n", |
84 | connections[connection_id].recv_packetnum, | 85 | connections[connection_id].recv_packetnum, |
85 | connections[connection_id].recv_packetnum_sync, connections[connection_id].sent_packetnum, connections[connection_id].send_packetnum, | 86 | connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum, |
86 | connections[connection_id].successful_sent, | 87 | connections[connection_id].successful_sent, |
87 | connections[connection_id].successful_read); | 88 | connections[connection_id].successful_read); |
88 | 89 | ||
89 | printf("req packets: \n"); | 90 | printf("req packets: \n"); |
90 | for(i = 0; i < MAX_PACKET_NUM; i++) | 91 | for(i = 0; i < BUFFER_PACKET_NUM; i++) |
91 | { | 92 | { |
92 | printf(" %u ", connections[connection_id].req_packets[i]); | 93 | printf(" %u ", connections[connection_id].req_packets[i]); |
93 | } | 94 | } |
@@ -97,7 +98,7 @@ void printconnection(int connection_id) | |||
97 | printf("--------------------END---------------------\n"); | 98 | printf("--------------------END---------------------\n"); |
98 | 99 | ||
99 | } | 100 | } |
100 | 101 | */ | |
101 | //recieve packets and send them to the packethandler | 102 | //recieve packets and send them to the packethandler |
102 | //run doLossless_UDP(); | 103 | //run doLossless_UDP(); |
103 | void Lossless_UDP() | 104 | void Lossless_UDP() |
@@ -107,18 +108,19 @@ void Lossless_UDP() | |||
107 | uint32_t length; | 108 | uint32_t length; |
108 | while(recievepacket(&ip_port, data, &length) != -1) | 109 | while(recievepacket(&ip_port, data, &length) != -1) |
109 | { | 110 | { |
111 | printf("packet with length: %u\n", length); | ||
110 | if(rand() % 3 != 1)//add packet loss | 112 | if(rand() % 3 != 1)//add packet loss |
111 | 113 | { | |
112 | if(LosslessUDP_handlepacket(data, length, ip_port)) | 114 | if(LosslessUDP_handlepacket(data, length, ip_port)) |
113 | { | 115 | { |
114 | printpacket(data, length, ip_port); | 116 | printpacket(data, length, ip_port); |
115 | } | 117 | } |
116 | else | 118 | else |
117 | { | 119 | { |
118 | //printconnection(0); | 120 | //printconnection(0); |
119 | printf("Received handled packet with length: %u\n", length); | 121 | printf("Received handled packet with length: %u\n", length); |
122 | } | ||
120 | } | 123 | } |
121 | |||
122 | } | 124 | } |
123 | 125 | ||
124 | doLossless_UDP(); | 126 | doLossless_UDP(); |
@@ -155,6 +157,7 @@ int main(int argc, char *argv[]) | |||
155 | uint64_t timer = current_time(); | 157 | uint64_t timer = current_time(); |
156 | while(1) | 158 | while(1) |
157 | { | 159 | { |
160 | // printconnection(connection); | ||
158 | Lossless_UDP(); | 161 | Lossless_UDP(); |
159 | if(is_connected(connection) == 3) | 162 | if(is_connected(connection) == 3) |
160 | { | 163 | { |
@@ -166,27 +169,28 @@ int main(int argc, char *argv[]) | |||
166 | printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); | 169 | printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); |
167 | return 1; | 170 | return 1; |
168 | } | 171 | } |
169 | c_sleep(100); | 172 | c_sleep(1); |
170 | } | 173 | } |
171 | timer = current_time(); | 174 | timer = current_time(); |
172 | 175 | ||
173 | 176 | ||
174 | //read first part of file | 177 | //read first part of file |
175 | read = fread(buffer, 1, 1, file); | 178 | read = fread(buffer, 1, 128, file); |
176 | 179 | ||
177 | while(1) | 180 | while(1) |
178 | { | 181 | { |
179 | //printconnection(connection); | 182 | //printconnection(connection); |
180 | Lossless_UDP(); | 183 | Lossless_UDP(); |
181 | |||
182 | if(is_connected(connection) == 3) | 184 | if(is_connected(connection) == 3) |
183 | { | 185 | { |
184 | 186 | ||
185 | if(write_packet(connection, buffer, read)) | 187 | if(write_packet(connection, buffer, read)) |
186 | { | 188 | { |
187 | //printf("Wrote data.\n"); | 189 | //printf("Wrote data.\n"); |
188 | read = fread(buffer, 1, 1, file); | 190 | read = fread(buffer, 1, 128, file); |
191 | |||
189 | } | 192 | } |
193 | //printf("%u\n", sendqueue(connection)); | ||
190 | if(sendqueue(connection) == 0) | 194 | if(sendqueue(connection) == 0) |
191 | { | 195 | { |
192 | if(read == 0) | 196 | if(read == 0) |
@@ -201,7 +205,7 @@ int main(int argc, char *argv[]) | |||
201 | printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); | 205 | printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); |
202 | return 0; | 206 | return 0; |
203 | } | 207 | } |
204 | c_sleep(50); | 208 | c_sleep(1); |
205 | } | 209 | } |
206 | 210 | ||
207 | return 0; | 211 | return 0; |
diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c index 9a180cbb..5370da9e 100644 --- a/testing/Lossless_UDP_testserver.c +++ b/testing/Lossless_UDP_testserver.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* Lossless_UDP testserver | 1 | /* Lossless_UDP testserver |
2 | * A program that waits for a lossless UDP connection and then saves all the data recieved to a file. | 2 | * A program that waits for a lossless UDP connection and then saves all the data recieved to a file. |
3 | * NOTE: this program simulates a 33% packet loss. | ||
3 | * | 4 | * |
4 | * Best used in combination with Lossless_UDP_testclient | 5 | * Best used in combination with Lossless_UDP_testclient |
5 | * | 6 | * |
@@ -40,6 +41,7 @@ void printpacket(char * data, uint32_t length, IP_Port ip_port) | |||
40 | } | 41 | } |
41 | printf("\n--------------------END-----------------------------\n\n\n"); | 42 | printf("\n--------------------END-----------------------------\n\n\n"); |
42 | } | 43 | } |
44 | /* | ||
43 | void printpackets(Data test) | 45 | void printpackets(Data test) |
44 | { | 46 | { |
45 | int i; | 47 | int i; |
@@ -75,14 +77,14 @@ void printconnection(int connection_id) | |||
75 | } | 77 | } |
76 | Data sendbuffer[MAX_QUEUE_NUM]; | 78 | Data sendbuffer[MAX_QUEUE_NUM]; |
77 | Data recvbuffer[MAX_QUEUE_NUM]; | 79 | Data recvbuffer[MAX_QUEUE_NUM]; |
78 | printf("recv_num: %u, recv_sync: %u, sent_packetnum %u, send_packetnum: %u, successful_sent: %u, successful_read: %u\n", | 80 | printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n", |
79 | connections[connection_id].recv_packetnum, | 81 | connections[connection_id].recv_packetnum, |
80 | connections[connection_id].recv_packetnum_sync, connections[connection_id].sent_packetnum, connections[connection_id].send_packetnum, | 82 | connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum, |
81 | connections[connection_id].successful_sent, | 83 | connections[connection_id].successful_sent, |
82 | connections[connection_id].successful_read); | 84 | connections[connection_id].successful_read); |
83 | 85 | ||
84 | printf("req packets: \n"); | 86 | printf("req packets: \n"); |
85 | for(i = 0; i < MAX_PACKET_NUM; i++) | 87 | for(i = 0; i < BUFFER_PACKET_NUM; i++) |
86 | { | 88 | { |
87 | printf(" %u ", connections[connection_id].req_packets[i]); | 89 | printf(" %u ", connections[connection_id].req_packets[i]); |
88 | } | 90 | } |
@@ -92,7 +94,7 @@ void printconnection(int connection_id) | |||
92 | printf("--------------------END---------------------\n"); | 94 | printf("--------------------END---------------------\n"); |
93 | 95 | ||
94 | } | 96 | } |
95 | 97 | */ | |
96 | //recieve packets and send them to the packethandler | 98 | //recieve packets and send them to the packethandler |
97 | //run doLossless_UDP(); | 99 | //run doLossless_UDP(); |
98 | void Lossless_UDP() | 100 | void Lossless_UDP() |
@@ -103,14 +105,16 @@ void Lossless_UDP() | |||
103 | while(recievepacket(&ip_port, data, &length) != -1) | 105 | while(recievepacket(&ip_port, data, &length) != -1) |
104 | { | 106 | { |
105 | if(rand() % 3 != 1)//add packet loss | 107 | if(rand() % 3 != 1)//add packet loss |
106 | if(LosslessUDP_handlepacket(data, length, ip_port)) | ||
107 | { | ||
108 | printpacket(data, length, ip_port); | ||
109 | } | ||
110 | else | ||
111 | { | 108 | { |
112 | // printconnection(0); | 109 | if(LosslessUDP_handlepacket(data, length, ip_port)) |
113 | printf("Received handled packet with length: %u\n", length); | 110 | { |
111 | printpacket(data, length, ip_port); | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | //printconnection(0); | ||
116 | // printf("Received handled packet with length: %u\n", length); | ||
117 | } | ||
114 | } | 118 | } |
115 | } | 119 | } |
116 | 120 | ||
@@ -151,13 +155,14 @@ int main(int argc, char *argv[]) | |||
151 | connection = incoming_connection(); | 155 | connection = incoming_connection(); |
152 | if(connection != -1) | 156 | if(connection != -1) |
153 | { | 157 | { |
154 | if(is_connected(connection) == 3) | 158 | if(is_connected(connection) == 2) |
155 | { | 159 | { |
156 | printf("Recieved the connection.\n"); | 160 | printf("Recieved the connection.\n"); |
161 | |||
157 | } | 162 | } |
158 | break; | 163 | break; |
159 | } | 164 | } |
160 | c_sleep(100); | 165 | c_sleep(1); |
161 | } | 166 | } |
162 | 167 | ||
163 | timer = current_time(); | 168 | timer = current_time(); |
@@ -166,13 +171,13 @@ int main(int argc, char *argv[]) | |||
166 | { | 171 | { |
167 | //printconnection(0); | 172 | //printconnection(0); |
168 | Lossless_UDP(); | 173 | Lossless_UDP(); |
169 | if(is_connected(connection) == 3) | 174 | if(is_connected(connection) >= 2) |
170 | { | 175 | { |
171 | read = read_packet(connection, buffer); | 176 | read = read_packet(connection, buffer); |
172 | 177 | ||
173 | if(read != 0) | 178 | if(read != 0) |
174 | { | 179 | { |
175 | printf("Recieved data.\n"); | 180 | // printf("Recieved data.\n"); |
176 | if(!fwrite(buffer, read, 1, file)) | 181 | if(!fwrite(buffer, read, 1, file)) |
177 | { | 182 | { |
178 | printf("file write error\n"); | 183 | printf("file write error\n"); |
@@ -185,7 +190,7 @@ int main(int argc, char *argv[]) | |||
185 | fclose(file); | 190 | fclose(file); |
186 | return 1; | 191 | return 1; |
187 | } | 192 | } |
188 | c_sleep(50); | 193 | c_sleep(1); |
189 | } | 194 | } |
190 | 195 | ||
191 | return 0; | 196 | return 0; |