summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/Lossless_UDP.c251
-rw-r--r--core/Lossless_UDP.h23
2 files changed, 216 insertions, 58 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
27typedef struct 47typedef 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
175int 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.
181uint32_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(...)
187uint32_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
149int read_packet(int connection_id, char * data) 194int 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
157int write_packet(int connection_id, char * data, uint32_t length) 210int 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.
167int 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(...)
173int 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
183int 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
189uint32_t missing_packets(int connection_id, uint32_t * requested) 235uint32_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
221int send_SYNC(uint32_t connection_id) 271int 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 298int send_data_packet(uint32_t connection_id, uint32_t packet_num)
249int 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
311int 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.
284uint32_t randtable[6][256]; 352static 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:
380int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) 451int 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:
392int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets, 464int 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.
524int 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
449int handle_data(char * packet, uint32_t length, IP_Port source) 562int 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
482void doNew() 609void doNew()
483{ 610{
@@ -521,7 +648,19 @@ void doSYNC()
521 648
522void doData() 649void 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);
33int write_packet(int connection_id, char * data, uint32_t length); 52int 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.
36int sendqueue(int connection_id); 55uint32_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(...)
39int recvqueue(int connection_id); 58uint32_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.