summaryrefslogtreecommitdiff
path: root/toxcore/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/network.c')
-rw-r--r--toxcore/network.c71
1 files changed, 51 insertions, 20 deletions
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;