summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-09-21 09:03:54 -0400
committerirungentoo <irungentoo@gmail.com>2013-09-21 09:03:54 -0400
commit3e4599e33a1e65a369bf62caec443b9699b2aab4 (patch)
tree3881db4a5595b6f97402be83759636eb352d4f2b
parent112c8dadf9b983d683f1fdd4e0ea3da4d9f9748f (diff)
Lossless UDP is now suitable for sending files.
Added some actual flow control and made send/recieve buffers grow when necessary.
-rw-r--r--testing/Lossless_UDP_testclient.c22
-rw-r--r--testing/Lossless_UDP_testserver.c28
-rw-r--r--toxcore/Lossless_UDP.c219
-rw-r--r--toxcore/Lossless_UDP.h27
-rw-r--r--toxcore/net_crypto.c4
5 files changed, 238 insertions, 62 deletions
diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c
index 3c52c6d6..52c48a97 100644
--- a/testing/Lossless_UDP_testclient.c
+++ b/testing/Lossless_UDP_testclient.c
@@ -164,7 +164,7 @@ int main(int argc, char *argv[])
164 exit(0); 164 exit(0);
165 } 165 }
166 166
167 uint8_t buffer[512]; 167 uint8_t buffer[MAX_DATA_SIZE];
168 int read; 168 int read;
169 169
170 FILE *file = fopen(argv[argvoffset + 3], "rb"); 170 FILE *file = fopen(argv[argvoffset + 3], "rb");
@@ -216,10 +216,10 @@ int main(int argc, char *argv[])
216 } 216 }
217 217
218 timer = current_time(); 218 timer = current_time();
219 219 unsigned long long bytes_sent = 0;
220 220
221 /*read first part of file */ 221 /*read first part of file */
222 read = fread(buffer, 1, 512, file); 222 read = fread(buffer, 1, MAX_DATA_SIZE, file);
223 223
224 while (1) { 224 while (1) {
225 /* printconnection(connection); */ 225 /* printconnection(connection); */
@@ -228,26 +228,32 @@ int main(int argc, char *argv[])
228 228
229 if (is_connected(ludp, connection) == 3) { 229 if (is_connected(ludp, connection) == 3) {
230 230
231 if (write_packet(ludp, connection, buffer, read)) { 231 while (write_packet(ludp, connection, buffer, read)) {
232 bytes_sent += read;
232 /* printf("Wrote data.\n"); */ 233 /* printf("Wrote data.\n"); */
233 read = fread(buffer, 1, 512, file); 234 read = fread(buffer, 1, MAX_DATA_SIZE, file);
234 235
235 } 236 }
236 237
237 /* printf("%u\n", sendqueue(connection)); */ 238 /* printf("%u\n", sendqueue(connection)); */
238 if (sendqueue(ludp, connection) == 0) { 239 if (sendqueue(ludp, connection) == 0) {
239 if (read == 0) { 240 if (read == 0) {
240 printf("Sent file successfully in: %llu us\n", (unsigned long long)(current_time() - timer)); 241 unsigned long long us = (unsigned long long)(current_time() - timer);
242 printf("Sent file successfully in: %llu us = %llu seconds. Average speed: %llu KB/s\n", us, us / 1000000UL,
243 bytes_sent / (us / 1024UL));
244 //printf("Total bytes sent: %llu B, Total data sent: %llu B, overhead: %llu B\n", total_bytes_sent, bytes_sent, total_bytes_sent-bytes_sent);
241 break; 245 break;
242 } 246 }
243 } 247 }
244 } else { 248 } else {
245 printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); 249 printf("%u Client Connecting Lost after: %llu us\n", is_connected(ludp, connection),
250 (unsigned long long)(current_time() - timer));
246 return 0; 251 return 0;
247 } 252 }
248 253
249 /* c_sleep(1); */
250 } 254 }
251 255
256 c_sleep(25);
257
252 return 0; 258 return 0;
253} 259}
diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c
index 9d061c0c..8deace82 100644
--- a/testing/Lossless_UDP_testserver.c
+++ b/testing/Lossless_UDP_testserver.c
@@ -160,7 +160,7 @@ int main(int argc, char *argv[])
160 exit(0); 160 exit(0);
161 } 161 }
162 162
163 uint8_t buffer[512]; 163 uint8_t buffer[MAX_DATA_SIZE];
164 int read; 164 int read;
165 165
166 FILE *file = fopen(argv[argvoffset + 1], "wb"); 166 FILE *file = fopen(argv[argvoffset + 1], "wb");
@@ -204,26 +204,32 @@ int main(int argc, char *argv[])
204 while (1) { 204 while (1) {
205 //printconnection(0); 205 //printconnection(0);
206 networking_poll(ludp->net); 206 networking_poll(ludp->net);
207 do_lossless_udp(ludp);
208 207
209 if (is_connected(ludp, connection) >= 2) { 208 if (is_connected(ludp, connection) >= 2) {
210 kill_connection_in(ludp, connection, 3000000); 209 confirm_connection(ludp, connection);
211 read = read_packet(ludp, connection, buffer); 210
212 211 while (1) {
213 if (read != 0) { 212 read = read_packet(ludp, connection, buffer);
214 // printf("Received data.\n"); 213
215 if (!fwrite(buffer, read, 1, file)) 214 if (read != 0) {
216 printf("file write error\n"); 215 // printf("Received data.\n");
216 if (!fwrite(buffer, read, 1, file))
217 printf("file write error\n");
218 } else {
219 break;
220 }
217 } 221 }
218 } 222 }
219 223
224 do_lossless_udp(ludp);
225
220 if (is_connected(ludp, connection) == 4) { 226 if (is_connected(ludp, connection) == 4) {
221 printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); 227 printf("Server Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer));
222 fclose(file); 228 fclose(file);
223 return 1; 229 return 1;
224 } 230 }
225 231
226 c_sleep(1); 232 c_sleep(25);
227 } 233 }
228 234
229 return 0; 235 return 0;
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c
index 81c2a2a5..6b2c83a5 100644
--- a/toxcore/Lossless_UDP.c
+++ b/toxcore/Lossless_UDP.c
@@ -52,6 +52,43 @@ int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
52 return -1; 52 return -1;
53} 53}
54 54
55/* Resize a queue
56 * return length of queue on success.
57 * return ~0 on failure.
58 */
59uint32_t resize_queue(Data **buffer, uint32_t length, uint32_t new_length, uint32_t min_packetnum,
60 uint32_t max_packetnum)
61{
62 if (MAX_QUEUE_NUM < new_length)
63 new_length = MAX_QUEUE_NUM;
64
65 if (max_packetnum - min_packetnum > new_length)
66 return ~0;
67
68 if (length == new_length)
69 return new_length;
70
71 Data *temp = calloc(1, sizeof(Data) * new_length);
72
73 if (temp == NULL)
74 return ~0;
75
76 if (*buffer == NULL) {
77 *buffer = temp;
78 return new_length;
79 }
80
81 uint32_t i;
82
83 for (i = min_packetnum; i != max_packetnum; ++i)
84 memcpy(temp + (i % new_length), *buffer + (i % length), sizeof(Data));
85
86 free(*buffer);
87 *buffer = temp;
88 return new_length;
89}
90
91
55 92
56/* 93/*
57 * Generate a handshake_id which depends on the ip_port. 94 * Generate a handshake_id which depends on the ip_port.
@@ -170,7 +207,8 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
170 memset(connection, 0, sizeof(Connection)); 207 memset(connection, 0, sizeof(Connection));
171 208
172 uint32_t handshake_id1 = handshake_id(ludp, ip_port); 209 uint32_t handshake_id1 = handshake_id(ludp, ip_port);
173 uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 210 /* add randomness to timeout to prevent connections getting stuck in a loop. */
211 uint8_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT;
174 212
175 *connection = (Connection) { 213 *connection = (Connection) {
176 .ip_port = ip_port, 214 .ip_port = ip_port,
@@ -186,9 +224,18 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
186 .last_sent = current_time(), 224 .last_sent = current_time(),
187 .killat = ~0, 225 .killat = ~0,
188 .send_counter = 0, 226 .send_counter = 0,
189 /* add randomness to timeout to prevent connections getting stuck in a loop. */ 227 .timeout = timeout,
190 .timeout = timeout 228 .confirmed = 1
191 }; 229 };
230 connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
231 connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
232
233 if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) {
234 free(connection->sendbuffer);
235 free(connection->recvbuffer);
236 memset(connection, 0, sizeof(Connection));
237 return -1;
238 }
192 239
193 return connection_id; 240 return connection_id;
194} 241}
@@ -221,8 +268,8 @@ static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
221 268
222 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 269 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
223 memset(connection, 0, sizeof(Connection)); 270 memset(connection, 0, sizeof(Connection));
224 271 /* Add randomness to timeout to prevent connections getting stuck in a loop. */
225 uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 272 uint8_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT;
226 273
227 *connection = (Connection) { 274 *connection = (Connection) {
228 .ip_port = ip_port, 275 .ip_port = ip_port,
@@ -234,12 +281,21 @@ static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
234 .last_sent = current_time(), 281 .last_sent = current_time(),
235 .send_counter = 127, 282 .send_counter = 127,
236 283
237 /* Add randomness to timeout to prevent connections getting stuck in a loop. */
238 .timeout = timeout, 284 .timeout = timeout,
239 285
240 /* If this connection isn't handled within the timeout kill it. */ 286 /* If this connection isn't handled within the timeout kill it. */
241 .killat = current_time() + 1000000UL * timeout 287 .killat = current_time() + 1000000UL * timeout,
288 .confirmed = 0
242 }; 289 };
290 connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
291 connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
292
293 if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) {
294 free(connection->sendbuffer);
295 free(connection->recvbuffer);
296 memset(connection, 0, sizeof(Connection));
297 return -1;
298 }
243 299
244 return connection_id; 300 return connection_id;
245} 301}
@@ -286,6 +342,8 @@ int kill_connection(Lossless_UDP *ludp, int connection_id)
286 if (connection->status > 0) { 342 if (connection->status > 0) {
287 connection->status = 0; 343 connection->status = 0;
288 change_handshake(ludp, connection->ip_port); 344 change_handshake(ludp, connection->ip_port);
345 free(connection->sendbuffer);
346 free(connection->recvbuffer);
289 memset(connection, 0, sizeof(Connection)); 347 memset(connection, 0, sizeof(Connection));
290 free_connections(ludp); 348 free_connections(ludp);
291 return 0; 349 return 0;
@@ -332,6 +390,27 @@ int is_connected(Lossless_UDP *ludp, int connection_id)
332 return 0; 390 return 0;
333} 391}
334 392
393/* Confirm an incoming connection.
394 * Also disables the auto kill timeout on incomming connections.
395 *
396 * return 0 on success
397 * return -1 on failure.
398 */
399int confirm_connection(Lossless_UDP *ludp, int connection_id)
400{
401 if ((unsigned int)connection_id >= ludp->connections.len)
402 return -1;
403
404 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
405
406 if (connection->status == 0)
407 return -1;
408
409 connection->killat = ~0;
410 connection->confirmed = 1;
411 return 0;
412}
413
335/* return the ip_port of the corresponding connection. */ 414/* return the ip_port of the corresponding connection. */
336IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) 415IP_Port connection_ip(Lossless_UDP *ludp, int connection_id)
337{ 416{
@@ -383,7 +462,7 @@ char id_packet(Lossless_UDP *ludp, int connection_id)
383 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 462 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
384 463
385 if (connection->status != 0) 464 if (connection->status != 0)
386 return connection->recvbuffer[connection->successful_read % MAX_QUEUE_NUM].data[0]; 465 return connection->recvbuffer[connection->successful_read % connection->recvbuffer_length].data[0];
387 466
388 return -1; 467 return -1;
389} 468}
@@ -401,7 +480,7 @@ int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data)
401 if (connection->status == 0) 480 if (connection->status == 0)
402 return 0; 481 return 0;
403 482
404 uint16_t index = connection->successful_read % MAX_QUEUE_NUM; 483 uint16_t index = connection->successful_read % connection->recvbuffer_length;
405 uint16_t size = connection->recvbuffer[index].size; 484 uint16_t size = connection->recvbuffer[index].size;
406 memcpy(data, connection->recvbuffer[index].data, size); 485 memcpy(data, connection->recvbuffer[index].data, size);
407 ++connection->successful_read; 486 ++connection->successful_read;
@@ -418,15 +497,27 @@ int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t
418 if ((unsigned int)connection_id >= ludp->connections.len) 497 if ((unsigned int)connection_id >= ludp->connections.len)
419 return 0; 498 return 0;
420 499
421 if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= BUFFER_PACKET_NUM) 500 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
501
502 if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= MAX_QUEUE_NUM)
422 return 0; 503 return 0;
423 504
424 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 505 if (sendqueue(ludp, connection_id) >= connection->sendbuffer_length) {
506 uint32_t newlen = connection->sendbuffer_length = resize_queue(&connection->sendbuffer, connection->sendbuffer_length,
507 connection->sendbuffer_length * 2, connection->successful_sent, connection->sendbuff_packetnum);
508
509 if (newlen == (uint32_t)~0)
510 return 0;
511
512 connection->sendbuffer_length = newlen;
513 return write_packet(ludp, connection_id, data, length);
514 }
515
425 516
426 if (connection->status == 0) 517 if (connection->status == 0)
427 return 0; 518 return 0;
428 519
429 uint32_t index = connection->sendbuff_packetnum % MAX_QUEUE_NUM; 520 uint32_t index = connection->sendbuff_packetnum % connection->sendbuffer_length;
430 memcpy(connection->sendbuffer[index].data, data, length); 521 memcpy(connection->sendbuffer[index].data, data, length);
431 connection->sendbuffer[index].size = length; 522 connection->sendbuffer[index].size = length;
432 connection->sendbuff_packetnum++; 523 connection->sendbuff_packetnum++;
@@ -434,26 +525,32 @@ int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t
434} 525}
435 526
436/* Put the packet numbers the we are missing in requested and return the number. */ 527/* Put the packet numbers the we are missing in requested and return the number. */
437uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested) 528static uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested)
438{ 529{
530 if ((unsigned int)connection_id >= ludp->connections.len)
531 return 0;
532
533 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
534
439 /* Don't request packets if the buffer is full. */ 535 /* Don't request packets if the buffer is full. */
440 if (recvqueue(ludp, connection_id) >= (BUFFER_PACKET_NUM - 1)) 536 if (recvqueue(ludp, connection_id) >= (connection->recvbuffer_length - 1))
441 return 0; 537 return 0;
442 538
443 uint32_t number = 0; 539 uint32_t number = 0;
444 uint32_t i; 540 uint32_t i;
445 uint32_t temp; 541 uint32_t temp;
446 542
447 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
448
449 for (i = connection->recv_packetnum; 543 for (i = connection->recv_packetnum;
450 i != connection->osent_packetnum; 544 i != connection->osent_packetnum;
451 i++) { 545 i++) {
452 if (connection->recvbuffer[i % MAX_QUEUE_NUM].size == 0) { 546 if (connection->recvbuffer[i % connection->recvbuffer_length].size == 0) {
453 temp = htonl(i); 547 temp = htonl(i);
454 memcpy(requested + number, &temp, 4); 548 memcpy(requested + number, &temp, 4);
455 ++number; 549 ++number;
456 } 550 }
551
552 if (number >= MAX_REQUESTED_PACKETS)
553 return number;
457 } 554 }
458 555
459 if (number == 0) 556 if (number == 0)
@@ -485,7 +582,7 @@ static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshak
485static int send_SYNC(Lossless_UDP *ludp, int connection_id) 582static int send_SYNC(Lossless_UDP *ludp, int connection_id)
486{ 583{
487 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 584 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
488 uint8_t packet[(BUFFER_PACKET_NUM * 4 + 4 + 4 + 2)]; 585 uint8_t packet[(MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2)];
489 uint16_t index = 0; 586 uint16_t index = 0;
490 587
491 IP_Port ip_port = connection->ip_port; 588 IP_Port ip_port = connection->ip_port;
@@ -493,7 +590,7 @@ static int send_SYNC(Lossless_UDP *ludp, int connection_id)
493 uint32_t recv_packetnum = htonl(connection->recv_packetnum); 590 uint32_t recv_packetnum = htonl(connection->recv_packetnum);
494 uint32_t sent_packetnum = htonl(connection->sent_packetnum); 591 uint32_t sent_packetnum = htonl(connection->sent_packetnum);
495 592
496 uint32_t requested[BUFFER_PACKET_NUM]; 593 uint32_t requested[MAX_REQUESTED_PACKETS];
497 uint32_t number = missing_packets(ludp, connection_id, requested); 594 uint32_t number = missing_packets(ludp, connection_id, requested);
498 595
499 packet[0] = NET_PACKET_SYNC; 596 packet[0] = NET_PACKET_SYNC;
@@ -514,7 +611,7 @@ static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t pack
514{ 611{
515 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 612 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
516 613
517 uint32_t index = packet_num % MAX_QUEUE_NUM; 614 uint32_t index = packet_num % connection->sendbuffer_length;
518 uint32_t temp; 615 uint32_t temp;
519 uint8_t packet[1 + 4 + MAX_DATA_SIZE]; 616 uint8_t packet[1 + 4 + MAX_DATA_SIZE];
520 packet[0] = NET_PACKET_DATA; 617 packet[0] = NET_PACKET_DATA;
@@ -529,7 +626,7 @@ static int send_DATA(Lossless_UDP *ludp, int connection_id)
529{ 626{
530 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 627 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
531 int ret; 628 int ret;
532 uint32_t buffer[BUFFER_PACKET_NUM]; 629 uint32_t buffer[MAX_REQUESTED_PACKETS];
533 630
534 if (connection->num_req_paquets > 0) { 631 if (connection->num_req_paquets > 0) {
535 ret = send_data_packet(ludp, connection_id, connection->req_packets[0]); 632 ret = send_data_packet(ludp, connection_id, connection->req_packets[0]);
@@ -609,7 +706,7 @@ static int SYNC_valid(uint32_t length)
609 if (length < 4 + 4 + 2) 706 if (length < 4 + 4 + 2)
610 return 0; 707 return 0;
611 708
612 if (length > (BUFFER_PACKET_NUM * 4 + 4 + 4 + 2) || 709 if (length > (MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2) ||
613 ((length - 4 - 4 - 2) % 4) != 0) 710 ((length - 4 - 4 - 2) % 4) != 0)
614 return 0; 711 return 0;
615 712
@@ -656,6 +753,35 @@ static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter,
656 753
657 return 1; 754 return 1;
658} 755}
756
757/*
758 * Automatically adjusts send rates of data packets for optimal transmission.
759 *
760 * TODO: Impove this.
761 */
762static void adjust_datasendspeed(Connection *connection, uint32_t req_packets)
763{
764 /* if there are no packets in send buffer */
765 if (connection->sendbuff_packetnum - connection->successful_sent == 0) {
766 connection->data_rate -= connection->data_rate / 8;
767
768 if (connection->data_rate < DATA_SYNC_RATE)
769 connection->data_rate = DATA_SYNC_RATE;
770
771 return;
772 }
773
774 if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 20 || req_packets <= 1) {
775 connection->data_rate += connection->data_rate / 8;
776
777 if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate)
778 connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate;
779 } else {
780 connection->data_rate -= connection->data_rate / 8;
781 }
782}
783
784
659/* case 3 in handle_SYNC: */ 785/* case 3 in handle_SYNC: */
660static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, 786static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum,
661 uint32_t sent_packetnum, 787 uint32_t sent_packetnum,
@@ -672,13 +798,14 @@ static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter,
672 uint32_t comp_2 = (sent_packetnum - connection->osent_packetnum); 798 uint32_t comp_2 = (sent_packetnum - connection->osent_packetnum);
673 799
674 /* Packet valid. */ 800 /* Packet valid. */
675 if (comp_1 <= BUFFER_PACKET_NUM && 801 if (comp_1 <= connection->sendbuffer_length &&
676 comp_2 <= BUFFER_PACKET_NUM && 802 comp_2 <= MAX_QUEUE_NUM &&
677 comp_counter == 1) { 803 comp_counter == 1) {
678 connection->orecv_packetnum = recv_packetnum; 804 connection->orecv_packetnum = recv_packetnum;
679 connection->osent_packetnum = sent_packetnum; 805 connection->osent_packetnum = sent_packetnum;
680 connection->successful_sent = recv_packetnum; 806 connection->successful_sent = recv_packetnum;
681 connection->last_recvSYNC = current_time(); 807 connection->last_recvSYNC = current_time();
808
682 connection->recv_counter = counter; 809 connection->recv_counter = counter;
683 810
684 ++connection->send_counter; 811 ++connection->send_counter;
@@ -689,6 +816,7 @@ static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter,
689 } 816 }
690 817
691 connection->num_req_paquets = number; 818 connection->num_req_paquets = number;
819 adjust_datasendspeed(connection, number);
692 return 0; 820 return 0;
693 } 821 }
694 822
@@ -705,8 +833,8 @@ static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t l
705 uint8_t counter; 833 uint8_t counter;
706 uint32_t temp; 834 uint32_t temp;
707 uint32_t recv_packetnum, sent_packetnum; 835 uint32_t recv_packetnum, sent_packetnum;
708 uint32_t req_packets[BUFFER_PACKET_NUM];
709 uint16_t number = (length - 4 - 4 - 2) / 4; 836 uint16_t number = (length - 4 - 4 - 2) / 4;
837 uint32_t req_packets[number];
710 838
711 memcpy(&counter, packet + 1, 1); 839 memcpy(&counter, packet + 1, 1);
712 memcpy(&temp, packet + 2, 4); 840 memcpy(&temp, packet + 2, 4);
@@ -749,17 +877,35 @@ static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, ui
749 877
750 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 878 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
751 uint32_t i; 879 uint32_t i;
752 uint32_t maxnum = connection->successful_read + BUFFER_PACKET_NUM; 880 uint32_t test = data_num - connection->recv_packetnum;
881
882 if (test > MAX_QUEUE_NUM)
883 return 0;
884
885 if (test > connection->recvbuffer_length) {
886 if (connection->confirmed == 0)
887 return 0;
888
889 uint32_t len = resize_queue(&connection->recvbuffer, connection->recvbuffer_length, test * 2,
890 connection->successful_read, connection->successful_read + connection->recvbuffer_length);
891
892 if (len == (uint32_t)~0)
893 return 0;
894
895 connection->recvbuffer_length = len;
896 }
897
898 uint32_t maxnum = connection->successful_read + connection->recvbuffer_length;
753 uint32_t sent_packet = data_num - connection->osent_packetnum; 899 uint32_t sent_packet = data_num - connection->osent_packetnum;
754 900
755 for (i = connection->recv_packetnum; i != maxnum; ++i) { 901 for (i = connection->recv_packetnum; i != maxnum; ++i) {
756 if (i == data_num) { 902 if (i == data_num) {
757 memcpy(connection->recvbuffer[i % MAX_QUEUE_NUM].data, data, size); 903 memcpy(connection->recvbuffer[data_num % connection->recvbuffer_length].data, data, size);
758 904
759 connection->recvbuffer[i % MAX_QUEUE_NUM].size = size; 905 connection->recvbuffer[data_num % connection->recvbuffer_length].size = size;
760 connection->last_recvdata = current_time(); 906 connection->last_recvdata = current_time();
761 907
762 if (sent_packet < BUFFER_PACKET_NUM) 908 if (sent_packet < connection->recvbuffer_length)
763 connection->osent_packetnum = data_num; 909 connection->osent_packetnum = data_num;
764 910
765 break; 911 break;
@@ -767,7 +913,7 @@ static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, ui
767 } 913 }
768 914
769 for (i = connection->recv_packetnum; i != maxnum; ++i) { 915 for (i = connection->recv_packetnum; i != maxnum; ++i) {
770 if (connection->recvbuffer[i % MAX_QUEUE_NUM].size != 0) 916 if (connection->recvbuffer[i % connection->recvbuffer_length].size != 0)
771 connection->recv_packetnum = i; 917 connection->recv_packetnum = i;
772 else 918 else
773 break; 919 break;
@@ -880,7 +1026,7 @@ static void do_data(Lossless_UDP *ludp)
880 } 1026 }
881} 1027}
882 1028
883#define MAX_SYNC_RATE 10 1029#define MAX_SYNC_RATE 20
884 1030
885/* 1031/*
886 * Automatically adjusts send rates of packets for optimal transmission. 1032 * Automatically adjusts send rates of packets for optimal transmission.
@@ -897,12 +1043,12 @@ static void adjust_rates(Lossless_UDP *ludp)
897 1043
898 if (tmp->status == 3) { 1044 if (tmp->status == 3) {
899 if (sendqueue(ludp, tmp_i) != 0) { 1045 if (sendqueue(ludp, tmp_i) != 0) {
900 tmp->data_rate = (BUFFER_PACKET_NUM - tmp->num_req_paquets) * MAX_SYNC_RATE;
901 tmp->SYNC_rate = MAX_SYNC_RATE; 1046 tmp->SYNC_rate = MAX_SYNC_RATE;
902 } else if (tmp->last_recvdata + 1000000UL > temp_time) 1047 } else if (tmp->last_recvdata + 200000UL > temp_time) { /* 200 ms */
903 tmp->SYNC_rate = MAX_SYNC_RATE; 1048 tmp->SYNC_rate = MAX_SYNC_RATE;
904 else 1049 } else {
905 tmp->SYNC_rate = SYNC_RATE; 1050 tmp->SYNC_rate = SYNC_RATE;
1051 }
906 } 1052 }
907 } 1053 }
908} 1054}
@@ -918,6 +1064,11 @@ void do_lossless_udp(Lossless_UDP *ludp)
918 1064
919void kill_lossless_udp(Lossless_UDP *ludp) 1065void kill_lossless_udp(Lossless_UDP *ludp)
920{ 1066{
1067 uint32_t i;
1068
1069 for (i = 0; i < ludp->connections.len; ++i)
1070 kill_connection(ludp, i);
1071
921 tox_array_delete(&ludp->connections); 1072 tox_array_delete(&ludp->connections);
922 free(ludp); 1073 free(ludp);
923} 1074}
diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h
index f0ce0e87..aa6e344f 100644
--- a/toxcore/Lossless_UDP.h
+++ b/toxcore/Lossless_UDP.h
@@ -32,10 +32,11 @@
32#define MAX_DATA_SIZE 1024 32#define MAX_DATA_SIZE 1024
33 33
34/* Maximum data packets in sent and receive queues. */ 34/* Maximum data packets in sent and receive queues. */
35#define MAX_QUEUE_NUM 16 35#define MAX_QUEUE_NUM 1024
36#define DEFAULT_QUEUE_NUM 4
36 37
37/* Maximum number of data packets in the buffer. */ 38/* Maximum number of data packets in the buffer. */
38#define BUFFER_PACKET_NUM (16-1) 39#define MAX_REQUESTED_PACKETS 256
39 40
40/* Timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT. */ 41/* Timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT. */
41#define CONNEXION_TIMEOUT 5 42#define CONNEXION_TIMEOUT 5
@@ -71,7 +72,7 @@ typedef struct {
71 uint8_t inbound; 72 uint8_t inbound;
72 73
73 uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */ 74 uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */
74 uint16_t data_rate; /* Current data packet send rate packets per second. */ 75 uint32_t data_rate; /* Current data packet send rate packets per second. */
75 76
76 uint64_t last_SYNC; /* Time our last SYNC packet was sent. */ 77 uint64_t last_SYNC; /* Time our last SYNC packet was sent. */
77 uint64_t last_sent; /* Time our last data or handshake packet was sent. */ 78 uint64_t last_sent; /* Time our last data or handshake packet was sent. */
@@ -79,9 +80,10 @@ typedef struct {
79 uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */ 80 uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */
80 uint64_t killat; /* Time to kill the connection. */ 81 uint64_t killat; /* Time to kill the connection. */
81 82
82 Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */ 83 Data *sendbuffer; /* packet send buffer. */
83 Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */ 84 uint32_t sendbuffer_length;
84 85 Data *recvbuffer; /* packet receive buffer. */
86 uint32_t recvbuffer_length;
85 uint32_t handshake_id1; 87 uint32_t handshake_id1;
86 uint32_t handshake_id2; 88 uint32_t handshake_id2;
87 89
@@ -107,7 +109,7 @@ typedef struct {
107 uint32_t successful_read; 109 uint32_t successful_read;
108 110
109 /* List of currently requested packet numbers(by the other person). */ 111 /* List of currently requested packet numbers(by the other person). */
110 uint32_t req_packets[BUFFER_PACKET_NUM]; 112 uint32_t req_packets[MAX_REQUESTED_PACKETS];
111 113
112 /* Total number of currently requested packets(by the other person). */ 114 /* Total number of currently requested packets(by the other person). */
113 uint16_t num_req_paquets; 115 uint16_t num_req_paquets;
@@ -115,6 +117,9 @@ typedef struct {
115 uint8_t recv_counter; 117 uint8_t recv_counter;
116 uint8_t send_counter; 118 uint8_t send_counter;
117 uint8_t timeout; /* connection timeout in seconds. */ 119 uint8_t timeout; /* connection timeout in seconds. */
120
121 /* is the connection confirmed or not 1 if yes, 0 if no */
122 uint8_t confirmed;
118} Connection; 123} Connection;
119 124
120typedef struct { 125typedef struct {
@@ -168,6 +173,14 @@ int kill_connection(Lossless_UDP *ludp, int connection_id);
168 */ 173 */
169int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds); 174int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds);
170 175
176/* Confirm an incoming connection.
177 * Also disables the auto kill timeout on incomming connections.
178 *
179 * return 0 on success
180 * return -1 on failure.
181 */
182int confirm_connection(Lossless_UDP *ludp, int connection_id);
183
171/* returns the ip_port of the corresponding connection. 184/* returns the ip_port of the corresponding connection.
172 * return 0 if there is no such connection. 185 * return 0 if there is no such connection.
173 */ 186 */
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index a2e42557..ca23957d 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -749,8 +749,8 @@ static void receive_crypto(Net_Crypto *c)
749 c->crypto_connections[i].shared_key); 749 c->crypto_connections[i].shared_key);
750 c->crypto_connections[i].status = CONN_ESTABLISHED; 750 c->crypto_connections[i].status = CONN_ESTABLISHED;
751 751
752 /* Connection is accepted so we disable the auto kill by setting it to about 1 month from now. */ 752 /* Connection is accepted. */
753 kill_connection_in(c->lossless_udp, c->crypto_connections[i].number, 3000000); 753 confirm_connection(c->lossless_udp, c->crypto_connections[i].number);
754 } else { 754 } else {
755 /* This should not happen, kill the connection if it does. */ 755 /* This should not happen, kill the connection if it does. */
756 crypto_kill(c, i); 756 crypto_kill(c, i);