diff options
-rw-r--r-- | src/microhttpd/test_upgrade.c | 358 |
1 files changed, 263 insertions, 95 deletions
diff --git a/src/microhttpd/test_upgrade.c b/src/microhttpd/test_upgrade.c index ddc47653..b30ad64b 100644 --- a/src/microhttpd/test_upgrade.c +++ b/src/microhttpd/test_upgrade.c | |||
@@ -62,6 +62,14 @@ | |||
62 | #endif /* HAVE_FORK && HAVE_WAITPID */ | 62 | #endif /* HAVE_FORK && HAVE_WAITPID */ |
63 | #endif /* HTTPS_SUPPORT */ | 63 | #endif /* HTTPS_SUPPORT */ |
64 | 64 | ||
65 | #if defined(MHD_POSIX_SOCKETS) | ||
66 | # ifdef MHD_WINSOCK_SOCKETS | ||
67 | # error Both MHD_POSIX_SOCKETS and MHD_WINSOCK_SOCKETS are defined | ||
68 | # endif /* MHD_WINSOCK_SOCKETS */ | ||
69 | #elif ! defined(MHD_WINSOCK_SOCKETS) | ||
70 | # error Neither MHD_POSIX_SOCKETS nor MHD_WINSOCK_SOCKETS are defined | ||
71 | #endif /* MHD_WINSOCK_SOCKETS */ | ||
72 | |||
65 | 73 | ||
66 | #ifndef MHD_STATICSTR_LEN_ | 74 | #ifndef MHD_STATICSTR_LEN_ |
67 | /** | 75 | /** |
@@ -262,6 +270,7 @@ gnutlscli_connect (int *sock, | |||
262 | #endif /* HTTPS_SUPPORT && HAVE_FORK && HAVE_WAITPID */ | 270 | #endif /* HTTPS_SUPPORT && HAVE_FORK && HAVE_WAITPID */ |
263 | 271 | ||
264 | 272 | ||
273 | #if 0 /* Unused code */ | ||
265 | /** | 274 | /** |
266 | * Change socket to blocking. | 275 | * Change socket to blocking. |
267 | * | 276 | * |
@@ -288,6 +297,35 @@ make_blocking (MHD_socket fd) | |||
288 | } | 297 | } |
289 | 298 | ||
290 | 299 | ||
300 | #endif /* Unused code */ | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Change socket to non-blocking. | ||
305 | * | ||
306 | * @param fd the socket to manipulate | ||
307 | */ | ||
308 | static void | ||
309 | make_nonblocking (MHD_socket fd) | ||
310 | { | ||
311 | #if defined(MHD_POSIX_SOCKETS) | ||
312 | int flags; | ||
313 | |||
314 | flags = fcntl (fd, F_GETFL); | ||
315 | if (-1 == flags) | ||
316 | externalErrorExitDesc ("fcntl() failed"); | ||
317 | if (O_NONBLOCK != (flags & O_NONBLOCK)) | ||
318 | if (-1 == fcntl (fd, F_SETFL, flags | O_NONBLOCK)) | ||
319 | externalErrorExitDesc ("fcntl() failed"); | ||
320 | #elif defined(MHD_WINSOCK_SOCKETS) | ||
321 | unsigned long flags = 1; | ||
322 | |||
323 | if (0 != ioctlsocket (fd, (int) FIONBIO, &flags)) | ||
324 | externalErrorExitDesc ("ioctlsocket() failed"); | ||
325 | #endif /* MHD_WINSOCK_SOCKETS */ | ||
326 | } | ||
327 | |||
328 | |||
291 | /** | 329 | /** |
292 | * Enable TCP_NODELAY on TCP/IP socket. | 330 | * Enable TCP_NODELAY on TCP/IP socket. |
293 | * | 331 | * |
@@ -337,6 +375,8 @@ struct wr_socket | |||
337 | wr_plain = 1, | 375 | wr_plain = 1, |
338 | wr_tls = 2 | 376 | wr_tls = 2 |
339 | } t; | 377 | } t; |
378 | |||
379 | bool is_nonblocking; | ||
340 | #ifdef HTTPS_SUPPORT | 380 | #ifdef HTTPS_SUPPORT |
341 | /** | 381 | /** |
342 | * TLS credentials | 382 | * TLS credentials |
@@ -363,6 +403,28 @@ struct wr_socket | |||
363 | #define wr_fd(s) ((s)->fd) | 403 | #define wr_fd(s) ((s)->fd) |
364 | 404 | ||
365 | 405 | ||
406 | #if 0 /* Unused code */ | ||
407 | static void | ||
408 | wr_make_blocking (struct wr_socket *s) | ||
409 | { | ||
410 | if (s->is_nonblocking) | ||
411 | make_blocking (s->fd); | ||
412 | s->is_nonblocking = false; | ||
413 | } | ||
414 | |||
415 | |||
416 | #endif /* Unused code */ | ||
417 | |||
418 | |||
419 | static void | ||
420 | wr_make_nonblocking (struct wr_socket *s) | ||
421 | { | ||
422 | if (! s->is_nonblocking) | ||
423 | make_nonblocking (s->fd); | ||
424 | s->is_nonblocking = true; | ||
425 | } | ||
426 | |||
427 | |||
366 | /** | 428 | /** |
367 | * Create wr_socket with plain TCP underlying socket | 429 | * Create wr_socket with plain TCP underlying socket |
368 | * @return created socket on success, NULL otherwise | 430 | * @return created socket on success, NULL otherwise |
@@ -378,6 +440,7 @@ wr_create_plain_sckt (void) | |||
378 | } | 440 | } |
379 | s->t = wr_plain; | 441 | s->t = wr_plain; |
380 | s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); | 442 | s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); |
443 | s->is_nonblocking = false; | ||
381 | if (MHD_INVALID_SOCKET != s->fd) | 444 | if (MHD_INVALID_SOCKET != s->fd) |
382 | { | 445 | { |
383 | make_nodelay (s->fd); | 446 | make_nodelay (s->fd); |
@@ -406,6 +469,7 @@ wr_create_tls_sckt (void) | |||
406 | s->t = wr_tls; | 469 | s->t = wr_tls; |
407 | s->tls_connected = 0; | 470 | s->tls_connected = 0; |
408 | s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); | 471 | s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); |
472 | s->is_nonblocking = false; | ||
409 | if (MHD_INVALID_SOCKET != s->fd) | 473 | if (MHD_INVALID_SOCKET != s->fd) |
410 | { | 474 | { |
411 | make_nodelay (s->fd); | 475 | make_nodelay (s->fd); |
@@ -469,65 +533,28 @@ wr_create_from_plain_sckt (MHD_socket plain_sk) | |||
469 | } | 533 | } |
470 | s->t = wr_plain; | 534 | s->t = wr_plain; |
471 | s->fd = plain_sk; | 535 | s->fd = plain_sk; |
536 | s->is_nonblocking = false; /* The actual mode is unknown */ | ||
537 | wr_make_nonblocking (s); /* Force set mode to have correct status */ | ||
472 | make_nodelay (s->fd); | 538 | make_nodelay (s->fd); |
473 | return s; | 539 | return s; |
474 | } | 540 | } |
475 | 541 | ||
476 | 542 | ||
477 | /** | ||
478 | * Connect socket to specified address. | ||
479 | * @param s socket to use | ||
480 | * @param addr address to connect | ||
481 | * @param length of structure pointed by @a addr | ||
482 | * @return zero on success, -1 otherwise. | ||
483 | */ | ||
484 | static int | ||
485 | wr_connect (struct wr_socket *s, | ||
486 | const struct sockaddr *addr, | ||
487 | unsigned int length) | ||
488 | { | ||
489 | if (0 != connect (s->fd, addr, (socklen_t) length)) | ||
490 | { | ||
491 | testErrorLogDesc ("connect() failed"); | ||
492 | return -1; | ||
493 | } | ||
494 | if (wr_plain == s->t) | ||
495 | return 0; | ||
496 | #ifdef HTTPS_SUPPORT | ||
497 | if (wr_tls == s->t) | ||
498 | { | ||
499 | /* Do not try handshake here as | ||
500 | * it require processing on MHD side and | ||
501 | * when testing with "external" polling, | ||
502 | * test will call MHD processing only | ||
503 | * after return from wr_connect(). */ | ||
504 | s->tls_connected = 0; | ||
505 | return 0; | ||
506 | } | ||
507 | #endif /* HTTPS_SUPPORT */ | ||
508 | testErrorLogDesc ("HTTPS socket connect called, but code does not support" \ | ||
509 | " HTTPS sockets"); | ||
510 | return -1; | ||
511 | } | ||
512 | |||
513 | |||
514 | enum wr_wait_for_type | 543 | enum wr_wait_for_type |
515 | { | 544 | { |
516 | WR_WAIT_FOR_RECV = 0, | 545 | WR_WAIT_FOR_RECV = 0, |
517 | WR_WAIT_FOR_SEND = 1 | 546 | WR_WAIT_FOR_SEND = 1 |
518 | }; | 547 | }; |
519 | 548 | ||
520 | static void | 549 | static bool |
521 | wr_wait_socket_ready_ (struct wr_socket *s, | 550 | wr_wait_socket_ready_noabort_ (struct wr_socket *s, |
522 | int timeout_ms, | 551 | int timeout_ms, |
523 | enum wr_wait_for_type wait_for) | 552 | enum wr_wait_for_type wait_for) |
524 | { | 553 | { |
525 | fd_set fds; | 554 | fd_set fds; |
526 | int sel_res; | 555 | int sel_res; |
527 | struct timeval tmo; | 556 | struct timeval tmo; |
528 | 557 | struct timeval *tmo_ptr; | |
529 | if (0 > timeout_ms) | ||
530 | return; | ||
531 | 558 | ||
532 | #ifndef MHD_WINSOCK_SOCKETS | 559 | #ifndef MHD_WINSOCK_SOCKETS |
533 | if (FD_SETSIZE <= s->fd) | 560 | if (FD_SETSIZE <= s->fd) |
@@ -535,20 +562,26 @@ wr_wait_socket_ready_ (struct wr_socket *s, | |||
535 | #endif /* ! MHD_WINSOCK_SOCKETS */ | 562 | #endif /* ! MHD_WINSOCK_SOCKETS */ |
536 | FD_ZERO (&fds); | 563 | FD_ZERO (&fds); |
537 | FD_SET (s->fd, &fds); | 564 | FD_SET (s->fd, &fds); |
565 | if (0 <= timeout_ms) | ||
566 | { | ||
538 | #if ! defined(_WIN32) || defined(__CYGWIN__) | 567 | #if ! defined(_WIN32) || defined(__CYGWIN__) |
539 | tmo.tv_sec = (time_t) (timeout_ms / 1000); | 568 | tmo.tv_sec = (time_t) (timeout_ms / 1000); |
540 | #else /* Native W32 */ | 569 | #else /* Native W32 */ |
541 | tmo.tv_sec = (long) (timeout_ms / 1000); | 570 | tmo.tv_sec = (long) (timeout_ms / 1000); |
542 | #endif /* Native W32 */ | 571 | #endif /* Native W32 */ |
543 | tmo.tv_usec = ((long) (timeout_ms % 1000)) * 1000; | 572 | tmo.tv_usec = ((long) (timeout_ms % 1000)) * 1000; |
573 | tmo_ptr = &tmo; | ||
574 | } | ||
575 | else | ||
576 | tmo_ptr = NULL; /* No timeout */ | ||
544 | 577 | ||
545 | if (WR_WAIT_FOR_RECV == wait_for) | 578 | if (WR_WAIT_FOR_RECV == wait_for) |
546 | sel_res = select (1 + (int) s->fd, &fds, NULL, NULL, &tmo); | 579 | sel_res = select (1 + (int) s->fd, &fds, NULL, NULL, tmo_ptr); |
547 | else | 580 | else |
548 | sel_res = select (1 + (int) s->fd, NULL, &fds, NULL, &tmo); | 581 | sel_res = select (1 + (int) s->fd, NULL, &fds, NULL, tmo_ptr); |
549 | 582 | ||
550 | if (1 == sel_res) | 583 | if (1 == sel_res) |
551 | return; | 584 | return true; |
552 | 585 | ||
553 | if (0 == sel_res) | 586 | if (0 == sel_res) |
554 | fprintf (stderr, "Timeout"); | 587 | fprintf (stderr, "Timeout"); |
@@ -563,6 +596,18 @@ wr_wait_socket_ready_ (struct wr_socket *s, | |||
563 | } | 596 | } |
564 | fprintf (stderr, " waiting for socket to be available for %s.\n", | 597 | fprintf (stderr, " waiting for socket to be available for %s.\n", |
565 | (WR_WAIT_FOR_RECV == wait_for) ? "receiving" : "sending"); | 598 | (WR_WAIT_FOR_RECV == wait_for) ? "receiving" : "sending"); |
599 | return false; | ||
600 | } | ||
601 | |||
602 | |||
603 | static void | ||
604 | wr_wait_socket_ready_ (struct wr_socket *s, | ||
605 | int timeout_ms, | ||
606 | enum wr_wait_for_type wait_for) | ||
607 | { | ||
608 | if (wr_wait_socket_ready_noabort_ (s, timeout_ms, wait_for)) | ||
609 | return; | ||
610 | |||
566 | if (WR_WAIT_FOR_RECV == wait_for) | 611 | if (WR_WAIT_FOR_RECV == wait_for) |
567 | mhdErrorExitDesc ("Client or application failed to receive the data"); | 612 | mhdErrorExitDesc ("Client or application failed to receive the data"); |
568 | else | 613 | else |
@@ -570,16 +615,105 @@ wr_wait_socket_ready_ (struct wr_socket *s, | |||
570 | } | 615 | } |
571 | 616 | ||
572 | 617 | ||
618 | /** | ||
619 | * Connect socket to specified address. | ||
620 | * @param s socket to use | ||
621 | * @param addr address to connect | ||
622 | * @param length of structure pointed by @a addr | ||
623 | * @param timeout_ms the maximum wait time in milliseconds to send the data, | ||
624 | * no limit if negative value is used | ||
625 | * @return zero on success, -1 otherwise. | ||
626 | */ | ||
627 | static int | ||
628 | wr_connect_tmo (struct wr_socket *s, | ||
629 | const struct sockaddr *addr, | ||
630 | unsigned int length, | ||
631 | int timeout_ms) | ||
632 | { | ||
633 | if (0 != connect (s->fd, addr, (socklen_t) length)) | ||
634 | { | ||
635 | int err; | ||
636 | bool connect_completed = false; | ||
637 | |||
638 | err = MHD_socket_get_error_ (); | ||
639 | #if defined(MHD_POSIX_SOCKETS) | ||
640 | while (! connect_completed && (EINTR == err)) | ||
641 | { | ||
642 | connect_completed = (0 == connect (s->fd, addr, (socklen_t) length)); | ||
643 | if (! connect_completed) | ||
644 | { | ||
645 | err = errno; | ||
646 | if (EALREADY == err) | ||
647 | err = EINPROGRESS; | ||
648 | else if (EISCONN == err) | ||
649 | connect_completed = true; | ||
650 | } | ||
651 | } | ||
652 | #endif /* MHD_POSIX_SOCKETS */ | ||
653 | if (! connect_completed && | ||
654 | (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_EINPROGRESS_) | ||
655 | || MHD_SCKT_ERR_IS_EAGAIN_ (err))) /* No modern system uses EAGAIN, except W32 */ | ||
656 | connect_completed = | ||
657 | wr_wait_socket_ready_noabort_ (s, timeout_ms, WR_WAIT_FOR_SEND); | ||
658 | if (! connect_completed) | ||
659 | { | ||
660 | testErrorLogDesc ("connect() failed"); | ||
661 | return -1; | ||
662 | } | ||
663 | } | ||
664 | if (wr_plain == s->t) | ||
665 | return 0; | ||
666 | #ifdef HTTPS_SUPPORT | ||
667 | if (wr_tls == s->t) | ||
668 | { | ||
669 | /* Do not try handshake here as | ||
670 | * it requires processing on MHD side and | ||
671 | * when testing with "external" polling, | ||
672 | * test will call MHD processing only | ||
673 | * after return from wr_connect(). */ | ||
674 | s->tls_connected = 0; | ||
675 | return 0; | ||
676 | } | ||
677 | #endif /* HTTPS_SUPPORT */ | ||
678 | testErrorLogDesc ("HTTPS socket connect called, but code does not support" \ | ||
679 | " HTTPS sockets"); | ||
680 | return -1; | ||
681 | } | ||
682 | |||
683 | |||
684 | /** | ||
685 | * Connect socket to specified address. | ||
686 | * @param s socket to use | ||
687 | * @param addr address to connect | ||
688 | * @param length of structure pointed by @a addr | ||
689 | * @return zero on success, -1 otherwise. | ||
690 | */ | ||
691 | static int | ||
692 | wr_connect (struct wr_socket *s, | ||
693 | const struct sockaddr *addr, | ||
694 | unsigned int length) | ||
695 | { | ||
696 | return wr_connect_tmo (s, addr, length, test_timeout * 1000); | ||
697 | } | ||
698 | |||
699 | |||
573 | #ifdef HTTPS_SUPPORT | 700 | #ifdef HTTPS_SUPPORT |
574 | /* Only to be called from wr_send() and wr_recv() ! */ | 701 | /* Only to be called from wr_send() and wr_recv() ! */ |
575 | static bool | 702 | static bool |
576 | wr_handshake_ (struct wr_socket *s) | 703 | wr_handshake_tmo_ (struct wr_socket *s, |
704 | int timeout_ms) | ||
577 | { | 705 | { |
578 | int res = gnutls_handshake (s->tls_s); | 706 | int res = gnutls_handshake (s->tls_s); |
707 | |||
708 | while ((GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res)) | ||
709 | { | ||
710 | wr_wait_socket_ready_ (s, timeout_ms, | ||
711 | gnutls_record_get_direction (s->tls_s) ? | ||
712 | WR_WAIT_FOR_SEND : WR_WAIT_FOR_RECV); | ||
713 | res = gnutls_handshake (s->tls_s); | ||
714 | } | ||
579 | if (GNUTLS_E_SUCCESS == res) | 715 | if (GNUTLS_E_SUCCESS == res) |
580 | s->tls_connected = true; | 716 | s->tls_connected = true; |
581 | else if (GNUTLS_E_AGAIN == res) | ||
582 | MHD_socket_set_error_ (MHD_SCKT_EAGAIN_); | ||
583 | else | 717 | else |
584 | { | 718 | { |
585 | fprintf (stderr, "The error returned by gnutls_handshake() is " | 719 | fprintf (stderr, "The error returned by gnutls_handshake() is " |
@@ -596,6 +730,17 @@ wr_handshake_ (struct wr_socket *s) | |||
596 | } | 730 | } |
597 | 731 | ||
598 | 732 | ||
733 | #if 0 /* Unused function */ | ||
734 | /* Only to be called from wr_send() and wr_recv() ! */ | ||
735 | static bool | ||
736 | wr_handshake_ (struct wr_socket *s) | ||
737 | { | ||
738 | return wr_handshake_tmo_ (s, test_timeout * 1000); | ||
739 | } | ||
740 | |||
741 | |||
742 | #endif /* Unused function */ | ||
743 | |||
599 | #endif /* HTTPS_SUPPORT */ | 744 | #endif /* HTTPS_SUPPORT */ |
600 | 745 | ||
601 | 746 | ||
@@ -618,35 +763,44 @@ wr_send_tmo (struct wr_socket *s, | |||
618 | { | 763 | { |
619 | if (wr_plain == s->t) | 764 | if (wr_plain == s->t) |
620 | { | 765 | { |
766 | int err; | ||
767 | ssize_t res = MHD_send_ (s->fd, buf, len); | ||
768 | if (0 <= res) | ||
769 | return res; | ||
770 | err = MHD_socket_get_error_ (); | ||
771 | if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) && ! MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
772 | return res; | ||
621 | wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_SEND); | 773 | wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_SEND); |
622 | return MHD_send_ (s->fd, buf, len); | 774 | return MHD_send_ (s->fd, buf, len); |
623 | } | 775 | } |
624 | #ifdef HTTPS_SUPPORT | 776 | #ifdef HTTPS_SUPPORT |
625 | if (wr_tls == s->t) | 777 | else if (wr_tls == s->t) |
626 | { | 778 | { |
627 | ssize_t ret; | 779 | ssize_t ret; |
628 | if (! s->tls_connected && ! wr_handshake_ (s)) | 780 | if (! s->tls_connected && ! wr_handshake_tmo_ (s, timeout_ms)) |
629 | return -1; | 781 | return -1; |
630 | 782 | ||
631 | wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_SEND); | 783 | while (1) |
632 | ret = gnutls_record_send (s->tls_s, buf, len); | ||
633 | if (ret > 0) | ||
634 | return ret; | ||
635 | if (GNUTLS_E_AGAIN == ret) | ||
636 | MHD_socket_set_error_ (MHD_SCKT_EAGAIN_); | ||
637 | else | ||
638 | { | 784 | { |
639 | fprintf (stderr, "The error returned by gnutls_record_send() is " | 785 | ret = gnutls_record_send (s->tls_s, buf, len); |
640 | "'%s' ", gnutls_strerror ((int) ret)); | 786 | if (ret >= 0) |
787 | return ret; | ||
788 | if ((GNUTLS_E_AGAIN != ret) && (GNUTLS_E_INTERRUPTED != ret)) | ||
789 | break; | ||
790 | wr_wait_socket_ready_ (s, timeout_ms, | ||
791 | gnutls_record_get_direction (s->tls_s) ? | ||
792 | WR_WAIT_FOR_SEND : WR_WAIT_FOR_RECV); | ||
793 | } | ||
794 | fprintf (stderr, "The error returned by gnutls_record_send() is " | ||
795 | "'%s' ", gnutls_strerror ((int) ret)); | ||
641 | #if GNUTLS_VERSION_NUMBER >= 0x020600 | 796 | #if GNUTLS_VERSION_NUMBER >= 0x020600 |
642 | fprintf (stderr, "(%s)\n", gnutls_strerror_name ((int) ret)); | 797 | fprintf (stderr, "(%s)\n", gnutls_strerror_name ((int) ret)); |
643 | #else /* GNUTLS_VERSION_NUMBER < 0x020600 */ | 798 | #else /* GNUTLS_VERSION_NUMBER < 0x020600 */ |
644 | fprintf (stderr, "(%d)\n", (int) ret); | 799 | fprintf (stderr, "(%d)\n", (int) ret); |
645 | #endif /* GNUTLS_VERSION_NUMBER < 0x020600 */ | 800 | #endif /* GNUTLS_VERSION_NUMBER < 0x020600 */ |
646 | testErrorLogDesc ("gnutls_record_send() failed with hard error"); | 801 | testErrorLogDesc ("gnutls_record_send() failed with hard error"); |
647 | MHD_socket_set_error_ (MHD_SCKT_ECONNABORTED_); /* hard error */ | 802 | MHD_socket_set_error_ (MHD_SCKT_ECONNABORTED_); /* hard error */ |
648 | return -1; | 803 | return -1; |
649 | } | ||
650 | } | 804 | } |
651 | #endif /* HTTPS_SUPPORT */ | 805 | #endif /* HTTPS_SUPPORT */ |
652 | testErrorLogDesc ("HTTPS socket send called, but code does not support" \ | 806 | testErrorLogDesc ("HTTPS socket send called, but code does not support" \ |
@@ -692,6 +846,13 @@ wr_recv_tmo (struct wr_socket *s, | |||
692 | { | 846 | { |
693 | if (wr_plain == s->t) | 847 | if (wr_plain == s->t) |
694 | { | 848 | { |
849 | int err; | ||
850 | ssize_t res = MHD_recv_ (s->fd, buf, len); | ||
851 | if (0 <= res) | ||
852 | return res; | ||
853 | err = MHD_socket_get_error_ (); | ||
854 | if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) && ! MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
855 | return res; | ||
695 | wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_RECV); | 856 | wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_RECV); |
696 | return MHD_recv_ (s->fd, buf, len); | 857 | return MHD_recv_ (s->fd, buf, len); |
697 | } | 858 | } |
@@ -699,28 +860,31 @@ wr_recv_tmo (struct wr_socket *s, | |||
699 | if (wr_tls == s->t) | 860 | if (wr_tls == s->t) |
700 | { | 861 | { |
701 | ssize_t ret; | 862 | ssize_t ret; |
702 | if (! s->tls_connected && ! wr_handshake_ (s)) | 863 | if (! s->tls_connected && ! wr_handshake_tmo_ (s, timeout_ms)) |
703 | return -1; | 864 | return -1; |
704 | 865 | ||
705 | wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_RECV); | 866 | while (1) |
706 | ret = gnutls_record_recv (s->tls_s, buf, len); | ||
707 | if (ret >= 0) | ||
708 | return ret; | ||
709 | if (GNUTLS_E_AGAIN == ret) | ||
710 | MHD_socket_set_error_ (MHD_SCKT_EAGAIN_); | ||
711 | else | ||
712 | { | 867 | { |
713 | fprintf (stderr, "The error returned by gnutls_record_recv() is " | 868 | ret = gnutls_record_recv (s->tls_s, buf, len); |
714 | "'%s' ", gnutls_strerror ((int) ret)); | 869 | if (ret >= 0) |
870 | return ret; | ||
871 | if ((GNUTLS_E_AGAIN != ret) && (GNUTLS_E_INTERRUPTED != ret)) | ||
872 | break; | ||
873 | wr_wait_socket_ready_ (s, timeout_ms, | ||
874 | gnutls_record_get_direction (s->tls_s) ? | ||
875 | WR_WAIT_FOR_SEND : WR_WAIT_FOR_RECV); | ||
876 | } | ||
877 | |||
878 | fprintf (stderr, "The error returned by gnutls_record_recv() is " | ||
879 | "'%s' ", gnutls_strerror ((int) ret)); | ||
715 | #if GNUTLS_VERSION_NUMBER >= 0x020600 | 880 | #if GNUTLS_VERSION_NUMBER >= 0x020600 |
716 | fprintf (stderr, "(%s)\n", gnutls_strerror_name ((int) ret)); | 881 | fprintf (stderr, "(%s)\n", gnutls_strerror_name ((int) ret)); |
717 | #else /* GNUTLS_VERSION_NUMBER < 0x020600 */ | 882 | #else /* GNUTLS_VERSION_NUMBER < 0x020600 */ |
718 | fprintf (stderr, "(%d)\n", (int) ret); | 883 | fprintf (stderr, "(%d)\n", (int) ret); |
719 | #endif /* GNUTLS_VERSION_NUMBER < 0x020600 */ | 884 | #endif /* GNUTLS_VERSION_NUMBER < 0x020600 */ |
720 | testErrorLogDesc ("gnutls_record_recv() failed with hard error"); | 885 | testErrorLogDesc ("gnutls_record_recv() failed with hard error"); |
721 | MHD_socket_set_error_ (MHD_SCKT_ECONNABORTED_); /* hard error */ | 886 | MHD_socket_set_error_ (MHD_SCKT_ECONNABORTED_); /* hard error */ |
722 | return -1; | 887 | return -1; |
723 | } | ||
724 | } | 888 | } |
725 | #endif /* HTTPS_SUPPORT */ | 889 | #endif /* HTTPS_SUPPORT */ |
726 | return -1; | 890 | return -1; |
@@ -945,7 +1109,7 @@ send_all (struct wr_socket *sock, | |||
945 | size_t sent; | 1109 | size_t sent; |
946 | const uint8_t *const buf = (const uint8_t *) data; | 1110 | const uint8_t *const buf = (const uint8_t *) data; |
947 | 1111 | ||
948 | make_blocking (wr_fd (sock)); | 1112 | wr_make_nonblocking (sock); |
949 | for (sent = 0; sent < data_size; sent += (size_t) ret) | 1113 | for (sent = 0; sent < data_size; sent += (size_t) ret) |
950 | { | 1114 | { |
951 | ret = wr_send (sock, | 1115 | ret = wr_send (sock, |
@@ -980,7 +1144,7 @@ recv_hdr (struct wr_socket *sock) | |||
980 | char c; | 1144 | char c; |
981 | ssize_t ret; | 1145 | ssize_t ret; |
982 | 1146 | ||
983 | make_blocking (wr_fd (sock)); | 1147 | wr_make_nonblocking (sock); |
984 | next = '\r'; | 1148 | next = '\r'; |
985 | i = 0; | 1149 | i = 0; |
986 | while (i < 4) | 1150 | while (i < 4) |
@@ -1032,7 +1196,7 @@ recv_all (struct wr_socket *sock, | |||
1032 | if (NULL == buf) | 1196 | if (NULL == buf) |
1033 | externalErrorExitDesc ("malloc() failed"); | 1197 | externalErrorExitDesc ("malloc() failed"); |
1034 | 1198 | ||
1035 | make_blocking (wr_fd (sock)); | 1199 | wr_make_nonblocking (sock); |
1036 | for (rcvd = 0; rcvd < data_size; rcvd += (size_t) ret) | 1200 | for (rcvd = 0; rcvd < data_size; rcvd += (size_t) ret) |
1037 | { | 1201 | { |
1038 | ret = wr_recv (sock, | 1202 | ret = wr_recv (sock, |
@@ -1193,6 +1357,7 @@ upgrade_cb (void *cls, | |||
1193 | (void) extra_in; /* Unused. Silent compiler warning. */ | 1357 | (void) extra_in; /* Unused. Silent compiler warning. */ |
1194 | 1358 | ||
1195 | usock = wr_create_from_plain_sckt (sock); | 1359 | usock = wr_create_from_plain_sckt (sock); |
1360 | wr_make_nonblocking (usock); | ||
1196 | if (0 != extra_in_size) | 1361 | if (0 != extra_in_size) |
1197 | mhdErrorExitDesc ("'extra_in_size' is not zero"); | 1362 | mhdErrorExitDesc ("'extra_in_size' is not zero"); |
1198 | if (0 != pthread_create (&pt, | 1363 | if (0 != pthread_create (&pt, |
@@ -1297,20 +1462,20 @@ run_mhd_select_loop (struct MHD_Daemon *daemon) | |||
1297 | const union MHD_DaemonInfo *pdinfo; | 1462 | const union MHD_DaemonInfo *pdinfo; |
1298 | bool connection_was_accepted; | 1463 | bool connection_was_accepted; |
1299 | bool connection_has_finished; | 1464 | bool connection_has_finished; |
1300 | bool use_epoll = false; | ||
1301 | #ifdef EPOLL_SUPPORT | 1465 | #ifdef EPOLL_SUPPORT |
1466 | bool use_epoll = false; | ||
1302 | int ep = -1; | 1467 | int ep = -1; |
1303 | 1468 | ||
1304 | pdinfo = MHD_get_daemeon_info (daemon, | 1469 | pdinfo = MHD_get_daemon_info (daemon, |
1305 | MHD_DAEMON_INFO_FLAGS); | 1470 | MHD_DAEMON_INFO_FLAGS); |
1306 | if (NULL == pdinfo) | 1471 | if (NULL == pdinfo) |
1307 | mhdErrorExitDesc ("MHD_get_daemon_info() failed"); | 1472 | mhdErrorExitDesc ("MHD_get_daemon_info() failed"); |
1308 | else | 1473 | else |
1309 | use_epoll = (0 != (pdinfo->flags & MHD_USE_EPOLL)); | 1474 | use_epoll = (0 != (pdinfo->flags & MHD_USE_EPOLL)); |
1310 | if (use_epoll) | 1475 | if (use_epoll) |
1311 | { | 1476 | { |
1312 | pdinfo = MHD_get_daemeon_info (daemon, | 1477 | pdinfo = MHD_get_daemon_info (daemon, |
1313 | MHD_DAEMON_INFO_EPOLL_FD); | 1478 | MHD_DAEMON_INFO_EPOLL_FD); |
1314 | if (NULL == pdinfo) | 1479 | if (NULL == pdinfo) |
1315 | mhdErrorExitDesc ("MHD_get_daemon_info() failed"); | 1480 | mhdErrorExitDesc ("MHD_get_daemon_info() failed"); |
1316 | ep = pdinfo->listen_fd; | 1481 | ep = pdinfo->listen_fd; |
@@ -1367,7 +1532,7 @@ run_mhd_select_loop (struct MHD_Daemon *daemon) | |||
1367 | { | 1532 | { |
1368 | if (ep != max_fd) | 1533 | if (ep != max_fd) |
1369 | mhdErrorExitDesc ("Wrong 'max_fd' value"); | 1534 | mhdErrorExitDesc ("Wrong 'max_fd' value"); |
1370 | if (! FD_ISSET (&rs, ep)) | 1535 | if (! FD_ISSET (ep, &rs)) |
1371 | mhdErrorExitDesc ("Epoll FD is NOT set in read fd_set"); | 1536 | mhdErrorExitDesc ("Epoll FD is NOT set in read fd_set"); |
1372 | } | 1537 | } |
1373 | #endif /* EPOLL_SUPPORT */ | 1538 | #endif /* EPOLL_SUPPORT */ |
@@ -1543,6 +1708,7 @@ test_upgrade (unsigned int flags, | |||
1543 | sock = test_tls ? wr_create_tls_sckt () : wr_create_plain_sckt (); | 1708 | sock = test_tls ? wr_create_tls_sckt () : wr_create_plain_sckt (); |
1544 | if (NULL == sock) | 1709 | if (NULL == sock) |
1545 | externalErrorExitDesc ("Create socket failed"); | 1710 | externalErrorExitDesc ("Create socket failed"); |
1711 | wr_make_nonblocking (sock); | ||
1546 | sa.sin_family = AF_INET; | 1712 | sa.sin_family = AF_INET; |
1547 | sa.sin_port = htons (dinfo->port); | 1713 | sa.sin_port = htons (dinfo->port); |
1548 | sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | 1714 | sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK); |
@@ -1565,6 +1731,8 @@ test_upgrade (unsigned int flags, | |||
1565 | sock = wr_create_from_plain_sckt (tls_fork_sock); | 1731 | sock = wr_create_from_plain_sckt (tls_fork_sock); |
1566 | if (NULL == sock) | 1732 | if (NULL == sock) |
1567 | externalErrorExitDesc ("wr_create_from_plain_sckt() failed"); | 1733 | externalErrorExitDesc ("wr_create_from_plain_sckt() failed"); |
1734 | |||
1735 | wr_make_nonblocking (sock); | ||
1568 | #else /* !HTTPS_SUPPORT || !HAVE_FORK || !HAVE_WAITPID */ | 1736 | #else /* !HTTPS_SUPPORT || !HAVE_FORK || !HAVE_WAITPID */ |
1569 | externalErrorExitDesc ("Unsupported 'use_tls_tool' value"); | 1737 | externalErrorExitDesc ("Unsupported 'use_tls_tool' value"); |
1570 | #endif /* !HTTPS_SUPPORT || !HAVE_FORK || !HAVE_WAITPID */ | 1738 | #endif /* !HTTPS_SUPPORT || !HAVE_FORK || !HAVE_WAITPID */ |