summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@tox.im>2014-03-08 14:35:03 -0500
committerirungentoo <irungentoo@tox.im>2014-03-08 14:35:03 -0500
commit95c8e9c2fb6c01a872871366e11aef18d49dc967 (patch)
tree0d19cd9b3376ad0c4dfd180a8d5b078ccc648a69
parent199f083e0ae27288e9aba1f70e6690a821f35a78 (diff)
parente1183194678bfd94bf15dfaaf1e153076a07937a (diff)
Merge pull request #790 from nurupo/tox-wait-fix
Some tox_wait_* improvements
-rw-r--r--toxcore/Messenger.c19
-rw-r--r--toxcore/Messenger.h7
-rw-r--r--toxcore/network.c71
-rw-r--r--toxcore/network.h7
-rw-r--r--toxcore/tox.c19
-rw-r--r--toxcore/tox.h40
6 files changed, 106 insertions, 57 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 81a347be..e48fa5fc 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -2342,19 +2342,24 @@ void do_messenger(Messenger *m)
2342/* 2342/*
2343 * functions to avoid excessive polling 2343 * functions to avoid excessive polling
2344 */ 2344 */
2345int wait_prepare_messenger(Messenger *m, uint8_t *data, uint16_t *lenptr) 2345size_t wait_data_size()
2346{ 2346{
2347 return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data, lenptr); 2347 return networking_wait_data_size();
2348} 2348}
2349 2349
2350int wait_execute_messenger(Messenger *m, uint8_t *data, uint16_t len, uint16_t milliseconds) 2350int wait_prepare_messenger(Messenger *m, uint8_t *data)
2351{ 2351{
2352 return networking_wait_execute(data, len, milliseconds); 2352 return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data);
2353}; 2353}
2354
2355int wait_execute_messenger(uint8_t *data, long seconds, long microseconds)
2356{
2357 return networking_wait_execute(data, seconds, microseconds);
2358}
2354 2359
2355void wait_cleanup_messenger(Messenger *m, uint8_t *data, uint16_t len) 2360int wait_cleanup_messenger(Messenger *m, uint8_t *data)
2356{ 2361{
2357 networking_wait_cleanup(m->net, data, len); 2362 return networking_wait_cleanup(m->net, data);
2358} 2363}
2359 2364
2360/* new messenger format for load/save, more robust and forward compatible */ 2365/* new messenger format for load/save, more robust and forward compatible */
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 213f8586..32b1f1b3 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -715,9 +715,10 @@ void do_messenger(Messenger *m);
715/* 715/*
716 * functions to avoid excessive polling 716 * functions to avoid excessive polling
717 */ 717 */
718int wait_prepare_messenger(Messenger *m, uint8_t *data, uint16_t *lenptr); 718size_t wait_data_size();
719int wait_execute_messenger(Messenger *m, uint8_t *data, uint16_t len, uint16_t milliseconds); 719int wait_prepare_messenger(Messenger *m, uint8_t *data);
720void wait_cleanup_messenger(Messenger *m, uint8_t *data, uint16_t len); 720int wait_execute_messenger(uint8_t *data, long seconds, long microseconds);
721int wait_cleanup_messenger(Messenger *m, uint8_t *data);
721 722
722/* SAVING AND LOADING FUNCTIONS: */ 723/* SAVING AND LOADING FUNCTIONS: */
723 724
diff --git a/toxcore/network.c b/toxcore/network.c
index 839618bf..35b55bf1 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -315,17 +315,17 @@ typedef struct {
315 uint64_t send_fail_eagain; 315 uint64_t send_fail_eagain;
316} select_info; 316} select_info;
317 317
318int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data, uint16_t *lenptr) 318size_t networking_wait_data_size()
319{ 319{
320 if ((data == NULL) || !lenptr || (*lenptr < sizeof(select_info))) { 320 return sizeof(select_info);
321 if (lenptr) { 321}
322 *lenptr = sizeof(select_info); 322
323 return 0; 323int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data)
324 } else 324{
325 return -1; 325 if (data == NULL) {
326 return 0;
326 } 327 }
327 328
328 *lenptr = sizeof(select_info);
329 select_info *s = (select_info *)data; 329 select_info *s = (select_info *)data;
330 s->sock = net->sock; 330 s->sock = net->sock;
331 s->sendqueue_length = sendqueue_length; 331 s->sendqueue_length = sendqueue_length;
@@ -335,25 +335,41 @@ int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uin
335 return 1; 335 return 1;
336} 336}
337 337
338int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds) 338/* *** Function MUSTN'T poll. ***
339* The function mustn't modify anything at all, so it can be called completely
340* asynchronously without any worry.
341*/
342int networking_wait_execute(uint8_t *data, long seconds, long microseconds)
339{ 343{
340 /* WIN32: supported since Win2K, but might need some adjustements */ 344 /* WIN32: supported since Win2K, but might need some adjustements */
341 /* UNIX: this should work for any remotely Unix'ish system */ 345 /* UNIX: this should work for any remotely Unix'ish system */
342 346
347 if (data == NULL) {
348 return 0;
349 }
350
343 select_info *s = (select_info *)data; 351 select_info *s = (select_info *)data;
344 352
345 /* add only if we had a failed write */ 353 /* add only if we had a failed write */
346 int writefds_add = 0; 354 int writefds_add = 0;
347 355
356 /* if send_fail_eagain is set, that means that socket's buffer was full and couldn't fit data we tried to send,
357 * so this is the only case when we need to know when the socket becomes write-ready, i.e. socket's buffer gets
358 * some free space for us to put data to be sent in, but select will tell us that the socket is writable even
359 * if we can fit a small part of our data (say 1 byte), so we wait some time, in hope that large enough chunk
360 * of socket's buffer will be available (at least that's how I understand intentions of the previous author of
361 * that code)
362 */
348 if (s->send_fail_eagain != 0) { 363 if (s->send_fail_eagain != 0) {
349 // current_time(): microseconds 364 // current_time(): microseconds
350 uint64_t now = current_time(); 365 uint64_t now = current_time();
351 366
352 /* s->sendqueue_length: might be used to guess how long we keep checking */ 367 /* s->sendqueue_length: might be used to guess how long we keep checking */
353 /* for now, threshold is hardcoded to 500ms, too long for a really really 368 /* for now, threshold is hardcoded to 250ms, too long for a really really
354 * fast link, but too short for a sloooooow link... */ 369 * fast link, but too short for a sloooooow link... */
355 if (now - s->send_fail_eagain < 500000) 370 if (now - s->send_fail_eagain < 250000) {
356 writefds_add = 1; 371 writefds_add = 1;
372 }
357 } 373 }
358 374
359 int nfds = 1 + s->sock; 375 int nfds = 1 + s->sock;
@@ -366,27 +382,34 @@ int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
366 fd_set writefds; 382 fd_set writefds;
367 FD_ZERO(&writefds); 383 FD_ZERO(&writefds);
368 384
369 if (writefds_add) 385 if (writefds_add) {
370 FD_SET(s->sock, &writefds); 386 FD_SET(s->sock, &writefds);
387 }
371 388
372 fd_set exceptfds; 389 fd_set exceptfds;
373 FD_ZERO(&exceptfds); 390 FD_ZERO(&exceptfds);
374 FD_SET(s->sock, &exceptfds); 391 FD_SET(s->sock, &exceptfds);
375 392
376 struct timeval timeout; 393 struct timeval timeout;
377 timeout.tv_sec = 0; 394 struct timeval *timeout_ptr = &timeout;
378 timeout.tv_usec = milliseconds * 1000; 395
396 if (seconds < 0 || microseconds < 0) {
397 timeout_ptr = NULL;
398 } else {
399 timeout.tv_sec = seconds;
400 timeout.tv_usec = microseconds;
401 }
379 402
380#ifdef LOGGING 403#ifdef LOGGING
381 errno = 0; 404 errno = 0;
382#endif 405#endif
383 /* returns -1 on error, 0 on timeout, the socket on activity */ 406 /* returns -1 on error, 0 on timeout, the socket on activity */
384 int res = select(nfds, &readfds, &writefds, &exceptfds, &timeout); 407 int res = select(nfds, &readfds, &writefds, &exceptfds, timeout_ptr);
385#ifdef LOGGING 408#ifdef LOGGING
386 409
387 /* only dump if not timeout */ 410 /* only dump if not timeout */
388 if (res) { 411 if (res) {
389 sprintf(logbuffer, "select(%d): %d (%d, %s) - %d %d %d\n", milliseconds, res, errno, 412 sprintf(logbuffer, "select(%d, %d): %d (%d, %s) - %d %d %d\n", microseconds, seconds, res, errno,
390 strerror(errno), FD_ISSET(s->sock, &readfds), FD_ISSET(s->sock, &writefds), 413 strerror(errno), FD_ISSET(s->sock, &readfds), FD_ISSET(s->sock, &writefds),
391 FD_ISSET(s->sock, &exceptfds)); 414 FD_ISSET(s->sock, &exceptfds));
392 loglog(logbuffer); 415 loglog(logbuffer);
@@ -394,18 +417,26 @@ int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
394 417
395#endif 418#endif
396 419
397 if (FD_ISSET(s->sock, &writefds)) 420 if (FD_ISSET(s->sock, &writefds)) {
398 s->send_fail_reset = 1; 421 s->send_fail_reset = 1;
422 }
399 423
400 return res > 0 ? 1 : 0; 424 return res > 0 ? 2 : 1;
401} 425}
402 426
403void networking_wait_cleanup(Networking_Core *net, uint8_t *data, uint16_t len) 427int networking_wait_cleanup(Networking_Core *net, uint8_t *data)
404{ 428{
429 if (data == NULL) {
430 return 0;
431 }
432
405 select_info *s = (select_info *)data; 433 select_info *s = (select_info *)data;
406 434
407 if (s->send_fail_reset) 435 if (s->send_fail_reset) {
408 net->send_fail_eagain = 0; 436 net->send_fail_eagain = 0;
437 }
438
439 return 1;
409} 440}
410 441
411uint8_t at_startup_ran = 0; 442uint8_t at_startup_ran = 0;
diff --git a/toxcore/network.h b/toxcore/network.h
index aaf89f19..97a73014 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -312,9 +312,10 @@ void networking_poll(Networking_Core *net);
312/* 312/*
313 * functions to avoid excessive polling 313 * functions to avoid excessive polling
314 */ 314 */
315int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data, uint16_t *lenptr); 315size_t networking_wait_data_size();
316int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds); 316int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data);
317void networking_wait_cleanup(Networking_Core *net, uint8_t *data, uint16_t len); 317int networking_wait_execute(uint8_t *data, long seconds, long microseconds);
318int networking_wait_cleanup(Networking_Core *net, uint8_t *data);
318 319
319/* Initialize networking. 320/* Initialize networking.
320 * bind to ip and port. 321 * bind to ip and port.
diff --git a/toxcore/tox.c b/toxcore/tox.c
index d3e596ba..aec0d902 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -767,22 +767,27 @@ void tox_do(Tox *tox)
767/* 767/*
768 * functions to avoid excessive polling 768 * functions to avoid excessive polling
769 */ 769 */
770int tox_wait_prepare(Tox *tox, uint8_t *data, uint16_t *lenptr) 770
771size_t tox_wait_data_size()
771{ 772{
772 Messenger *m = tox; 773 return wait_data_size();
773 return wait_prepare_messenger(m, data, lenptr);
774} 774}
775 775
776int tox_wait_execute(Tox *tox, uint8_t *data, uint16_t len, uint16_t milliseconds) 776int tox_wait_prepare(Tox *tox, uint8_t *data)
777{ 777{
778 Messenger *m = tox; 778 Messenger *m = tox;
779 return wait_execute_messenger(m, data, len, milliseconds); 779 return wait_prepare_messenger(m, data);
780}
781
782int tox_wait_execute(uint8_t *data, long seconds, long microseconds)
783{
784 return wait_execute_messenger(data, seconds, microseconds);
780} 785}
781 786
782void tox_wait_cleanup(Tox *tox, uint8_t *data, uint16_t len) 787int tox_wait_cleanup(Tox *tox, uint8_t *data)
783{ 788{
784 Messenger *m = tox; 789 Messenger *m = tox;
785 wait_cleanup_messenger(m, data, len); 790 return wait_cleanup_messenger(m, data);
786} 791}
787 792
788/* SAVING AND LOADING FUNCTIONS: */ 793/* SAVING AND LOADING FUNCTIONS: */
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 5b619cd0..1c84c1cb 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -662,37 +662,43 @@ void tox_kill(Tox *tox);
662void tox_do(Tox *tox); 662void tox_do(Tox *tox);
663 663
664/* 664/*
665 * tox_wait_prepare(): function should be called under lock 665 * tox_wait_data_size():
666 *
667 * returns a size of data buffer to allocate. the size is constant.
668 *
669 * tox_wait_prepare(): function should be called under lock every time we want to call tox_wait_execute()
666 * Prepares the data required to call tox_wait_execute() asynchronously 670 * Prepares the data required to call tox_wait_execute() asynchronously
667 * 671 *
668 * data[] is reserved and kept by the caller 672 * data[] should be of at least tox_wait_data_size() size and it's reserved and kept by the caller
669 * *lenptr is in/out: in = reserved data[], out = required data[] 673 * Use that data[] to call tox_wait_execute()
670 * 674 *
671 * returns 1 on success 675 * returns 1 on success
672 * returns 0 if *lenptr is insufficient 676 * returns 0 if data was NULL
673 * returns -1 if lenptr is NULL
674 * 677 *
675 * 678 *
676 * tox_wait_execute(): function can be called asynchronously 679 * tox_wait_execute(): function can be called asynchronously
677 * Waits for something to happen on the socket for up to milliseconds milliseconds. 680 * Waits for something to happen on the socket for up to seconds seconds and mircoseconds microseconds.
678 * *** Function MUSTN'T poll. *** 681 * mircoseconds should be between 0 and 999999.
679 * The function mustn't modify anything at all, so it can be called completely 682 * If you set either or both seconds and microseconds to negatives, it will block indefinetly until there
680 * asynchronously without any worry. 683 * is an activity.
681 * 684 *
682 * returns 1 if there is socket activity (i.e. tox_do() should be called) 685 * returns 2 if there is socket activity (i.e. tox_do() should be called)
683 * returns 0 if the timeout was reached 686 * returns 1 if the timeout was reached (tox_do() should be called anyway. it's advised to call it at least
684 * returns -1 if data was NULL or len too short 687 * once per second)
688 * returns 0 if data was NULL
685 * 689 *
686 * 690 *
687 * tox_wait_cleanup(): function should be called under lock 691 * tox_wait_cleanup(): function should be called under lock, every time tox_wait_execute() finishes
688 * Stores results from tox_wait_execute(). 692 * Stores results from tox_wait_execute().
689 * 693 *
690 * data[]/len shall be the exact same as given to tox_wait_execute() 694 * returns 1 on success
695 * returns 0 if data was NULL
691 * 696 *
692 */ 697 */
693int tox_wait_prepare(Tox *tox, uint8_t *data, uint16_t *lenptr); 698size_t tox_wait_data_size();
694int tox_wait_execute(Tox *tox, uint8_t *data, uint16_t len, uint16_t milliseconds); 699int tox_wait_prepare(Tox *tox, uint8_t *data);
695void tox_wait_cleanup(Tox *tox, uint8_t *data, uint16_t len); 700int tox_wait_execute(uint8_t *data, long seconds, long microseconds);
701int tox_wait_cleanup(Tox *tox, uint8_t *data);
696 702
697 703
698/* SAVING AND LOADING FUNCTIONS: */ 704/* SAVING AND LOADING FUNCTIONS: */