diff options
author | irungentoo <irungentoo@gmail.com> | 2013-09-21 09:03:54 -0400 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2013-09-21 09:03:54 -0400 |
commit | 3e4599e33a1e65a369bf62caec443b9699b2aab4 (patch) | |
tree | 3881db4a5595b6f97402be83759636eb352d4f2b | |
parent | 112c8dadf9b983d683f1fdd4e0ea3da4d9f9748f (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.c | 22 | ||||
-rw-r--r-- | testing/Lossless_UDP_testserver.c | 28 | ||||
-rw-r--r-- | toxcore/Lossless_UDP.c | 219 | ||||
-rw-r--r-- | toxcore/Lossless_UDP.h | 27 | ||||
-rw-r--r-- | toxcore/net_crypto.c | 4 |
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 | */ | ||
59 | uint32_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 | */ | ||
399 | int 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. */ |
336 | IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) | 415 | IP_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. */ |
437 | uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested) | 528 | static 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 | |||
485 | static int send_SYNC(Lossless_UDP *ludp, int connection_id) | 582 | static 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 | */ | ||
762 | static 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: */ |
660 | static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, | 786 | static 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 | ||
919 | void kill_lossless_udp(Lossless_UDP *ludp) | 1065 | void 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 | ||
120 | typedef struct { | 125 | typedef struct { |
@@ -168,6 +173,14 @@ int kill_connection(Lossless_UDP *ludp, int connection_id); | |||
168 | */ | 173 | */ |
169 | int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds); | 174 | int 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 | */ | ||
182 | int 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); |