diff options
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r-- | src/microhttpd/connection.c | 215 |
1 files changed, 105 insertions, 110 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 4d2f49b5..d521c036 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -49,6 +49,10 @@ | |||
49 | #ifdef HTTPS_SUPPORT | 49 | #ifdef HTTPS_SUPPORT |
50 | #include "connection_https.h" | 50 | #include "connection_https.h" |
51 | #endif /* HTTPS_SUPPORT */ | 51 | #endif /* HTTPS_SUPPORT */ |
52 | #ifdef HAVE_SYS_PARAM_H | ||
53 | /* For FreeBSD version identification */ | ||
54 | #include <sys/param.h> | ||
55 | #endif /* HAVE_SYS_PARAM_H */ | ||
52 | 56 | ||
53 | 57 | ||
54 | /** | 58 | /** |
@@ -496,51 +500,46 @@ socket_flush_possible(struct MHD_Connection *connection) | |||
496 | _MHD_static_inline bool | 500 | _MHD_static_inline bool |
497 | socket_start_extra_buffering (struct MHD_Connection *connection) | 501 | socket_start_extra_buffering (struct MHD_Connection *connection) |
498 | { | 502 | { |
499 | bool res = false; | ||
500 | #if defined(TCP_CORK) || defined(TCP_NOPUSH) | ||
501 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
502 | #if defined(TCP_NODELAY) | ||
503 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
504 | #endif /* TCP_NODELAY */ | ||
505 | (void) connection; /* mute compiler warning, assertion below | ||
506 | may be compiled out! */ | ||
507 | mhd_assert(NULL != connection); | 503 | mhd_assert(NULL != connection); |
508 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) | ||
509 | /* Buffer data before sending */ | ||
510 | res = (0 == setsockopt (connection->socket_fd, | ||
511 | IPPROTO_TCP, | ||
512 | TCP_NOPUSH, | ||
513 | (const void *) &on_val, | ||
514 | sizeof (on_val))); | ||
515 | #if defined(TCP_NODELAY) | 504 | #if defined(TCP_NODELAY) |
516 | /* Enable Nagle's algorithm */ | 505 | if (connection->sk_tcp_nodelay_on) |
517 | /* TCP_NODELAY may interfere with TCP_NOPUSH */ | 506 | { |
518 | res = (0 == setsockopt (connection->socket_fd, | 507 | const MHD_SCKT_OPT_BOOL_ off_val = 0; |
508 | /* Enable Nagle's algorithm */ | ||
509 | /* TCP_NODELAY may interfere with TCP_NOPUSH */ | ||
510 | if (0 == setsockopt (connection->socket_fd, | ||
519 | IPPROTO_TCP, | 511 | IPPROTO_TCP, |
520 | TCP_NODELAY, | 512 | TCP_NODELAY, |
521 | (const void *) &off_val, | 513 | (const void *) &off_val, |
522 | sizeof (off_val))) && res; | 514 | sizeof (off_val))) |
515 | { | ||
516 | connection->sk_tcp_nodelay_on = false; | ||
517 | } | ||
518 | } | ||
523 | #endif /* TCP_NODELAY */ | 519 | #endif /* TCP_NODELAY */ |
524 | #else /* TCP_CORK */ | 520 | |
521 | #if defined(MHD_TCP_CORK_NOPUSH) | ||
522 | if (!connection->sk_tcp_cork_nopush_on) | ||
523 | { | ||
524 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
525 | /* Buffer data before sending (TCP_CORK) or | ||
526 | * Send only full frames (TCP_NOPUSH) */ | ||
527 | if (0 == setsockopt (connection->socket_fd, | ||
528 | IPPROTO_TCP, | ||
529 | MHD_TCP_CORK_NOPUSH, | ||
530 | (const void *) &on_val, | ||
531 | sizeof (on_val))) | ||
532 | { | ||
533 | connection->sk_tcp_cork_nopush_on = true; | ||
534 | } | ||
535 | } | ||
536 | #endif /* MHD_TCP_CORK_NOPUSH */ | ||
537 | |||
525 | #if defined(TCP_NODELAY) | 538 | #if defined(TCP_NODELAY) |
526 | /* Enable Nagle's algorithm */ | 539 | return connection->sk_tcp_cork_nopush_on && !connection->sk_tcp_nodelay_on; |
527 | /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends | 540 | #else /* ! TCP_NODELAY */ |
528 | solely on TCP_CORK result, so ignoring return code here. */ | 541 | return connection->sk_tcp_cork_nopush_on; |
529 | (void) setsockopt (connection->socket_fd, | 542 | #endif /* ! TCP_NODELAY */ |
530 | IPPROTO_TCP, | ||
531 | TCP_NODELAY, | ||
532 | (const void *) &off_val, | ||
533 | sizeof (off_val)); | ||
534 | #endif /* TCP_NODELAY */ | ||
535 | /* Send only full packets */ | ||
536 | res = (0 == setsockopt (connection->socket_fd, | ||
537 | IPPROTO_TCP, | ||
538 | TCP_CORK, | ||
539 | (const void *) &on_val, | ||
540 | sizeof (on_val))); | ||
541 | #endif /* TCP_CORK */ | ||
542 | #endif /* TCP_CORK || TCP_NOPUSH */ | ||
543 | return res; | ||
544 | } | 543 | } |
545 | 544 | ||
546 | 545 | ||
@@ -553,43 +552,38 @@ socket_start_extra_buffering (struct MHD_Connection *connection) | |||
553 | _MHD_static_inline bool | 552 | _MHD_static_inline bool |
554 | socket_start_no_buffering (struct MHD_Connection *connection) | 553 | socket_start_no_buffering (struct MHD_Connection *connection) |
555 | { | 554 | { |
556 | #if defined(TCP_NODELAY) | 555 | #if defined(MHD_TCP_CORK_NOPUSH) |
557 | bool res = true; | 556 | if (connection->sk_tcp_cork_nopush_on) |
558 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | 557 | { |
559 | #if defined(TCP_CORK) || defined(TCP_NOPUSH) | 558 | const MHD_SCKT_OPT_BOOL_ off_val = 0; |
560 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | 559 | /* Disable extra buffering */ |
561 | #endif /* TCP_CORK || TCP_NOPUSH */ | 560 | if (0 == setsockopt (connection->socket_fd, |
562 | |||
563 | (void)connection; /* Mute compiler warning. */ | ||
564 | mhd_assert(NULL != connection); | ||
565 | #if defined(TCP_CORK) | ||
566 | /* Allow partial packets */ | ||
567 | res = (0 == setsockopt (connection->socket_fd, | ||
568 | IPPROTO_TCP, | 561 | IPPROTO_TCP, |
569 | TCP_CORK, | 562 | MHD_TCP_CORK_NOPUSH, |
570 | (const void *) &off_val, | 563 | (const void *) &off_val, |
571 | sizeof (off_val))) && res; | 564 | sizeof (off_val))) |
572 | #endif /* TCP_CORK */ | 565 | { |
566 | connection->sk_tcp_cork_nopush_on = false; | ||
567 | } | ||
568 | } | ||
569 | #endif /* MHD_TCP_CORK_NOPUSH */ | ||
570 | |||
573 | #if defined(TCP_NODELAY) | 571 | #if defined(TCP_NODELAY) |
574 | /* Disable Nagle's algorithm for sending packets without delay */ | 572 | if (!connection->sk_tcp_nodelay_on) |
575 | res = (0 == setsockopt (connection->socket_fd, | 573 | { |
574 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
575 | /* Enable sending without delay */ | ||
576 | if (0 == setsockopt (connection->socket_fd, | ||
576 | IPPROTO_TCP, | 577 | IPPROTO_TCP, |
577 | TCP_NODELAY, | 578 | TCP_NODELAY, |
578 | (const void *) &on_val, | 579 | (const void *) &on_val, |
579 | sizeof (on_val))) && res; | 580 | sizeof (on_val))) |
581 | { | ||
582 | connection->sk_tcp_nodelay_on = true; | ||
583 | } | ||
584 | } | ||
580 | #endif /* TCP_NODELAY */ | 585 | #endif /* TCP_NODELAY */ |
581 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) | 586 | return connection->sk_tcp_nodelay_on && !connection->sk_tcp_cork_nopush_on; |
582 | /* Disable extra buffering */ | ||
583 | res = (0 == setsockopt (connection->socket_fd, | ||
584 | IPPROTO_TCP, | ||
585 | TCP_NOPUSH, | ||
586 | (const void *) &off_val, | ||
587 | sizeof (off_val))) && res; | ||
588 | #endif /* TCP_NOPUSH && !TCP_CORK */ | ||
589 | return res; | ||
590 | #else /* !TCP_NODELAY */ | ||
591 | return false; | ||
592 | #endif /* !TCP_NODELAY */ | ||
593 | } | 587 | } |
594 | 588 | ||
595 | 589 | ||
@@ -607,12 +601,24 @@ socket_start_no_buffering_flush (struct MHD_Connection *connection) | |||
607 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) | 601 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) |
608 | const int dummy = 0; | 602 | const int dummy = 0; |
609 | #endif /* !TCP_CORK */ | 603 | #endif /* !TCP_CORK */ |
610 | 604 | #if defined(TCP_CORK) || (defined(__FreeBSD__) && __FreeBSD__+0 >= 9) | |
611 | (void)connection; /* Mute compiler warning. */ | 605 | const MHD_SCKT_OPT_BOOL_ off_val = 0; |
612 | mhd_assert(NULL != connection); | 606 | /* Switching off TCP_CORK flush buffer even |
607 | * if TCP_CORK was not enabled */ | ||
608 | if (0 == setsockopt (connection->socket_fd, | ||
609 | IPPROTO_TCP, | ||
610 | MHD_TCP_CORK_NOPUSH, | ||
611 | (const void *) &off_val, | ||
612 | sizeof (off_val))) | ||
613 | { | ||
614 | connection->sk_tcp_cork_nopush_on = false; | ||
615 | } | ||
616 | #endif /* MHD_TCP_CORK_NOPUSH */ | ||
613 | 617 | ||
614 | res = socket_start_no_buffering (connection); | 618 | res = socket_start_no_buffering (connection); |
615 | #if defined(TCP_NOPUSH) && !defined(TCP_CORK) | 619 | #if defined(__FreeBSD__) && __FreeBSD__+0 >= 9 |
620 | /* FreeBSD do not need zero-send for flushing starting from version 9 */ | ||
621 | #elif defined(TCP_NOPUSH) && !defined(TCP_CORK) | ||
616 | /* Force flush data with zero send otherwise Darwin and some BSD systems | 622 | /* Force flush data with zero send otherwise Darwin and some BSD systems |
617 | will add 5 seconds delay. Not required with TCP_CORK as switching off | 623 | will add 5 seconds delay. Not required with TCP_CORK as switching off |
618 | TCP_CORK always flushes socket buffer. */ | 624 | TCP_CORK always flushes socket buffer. */ |
@@ -633,50 +639,39 @@ socket_start_no_buffering_flush (struct MHD_Connection *connection) | |||
633 | _MHD_static_inline bool | 639 | _MHD_static_inline bool |
634 | socket_start_normal_buffering (struct MHD_Connection *connection) | 640 | socket_start_normal_buffering (struct MHD_Connection *connection) |
635 | { | 641 | { |
636 | #if defined(TCP_NODELAY) | ||
637 | bool res = true; | ||
638 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
639 | #if defined(TCP_CORK) | ||
640 | MHD_SCKT_OPT_BOOL_ cork_val = 0; | ||
641 | socklen_t param_size = sizeof (cork_val); | ||
642 | #endif /* TCP_CORK */ | ||
643 | mhd_assert(NULL != connection); | 642 | mhd_assert(NULL != connection); |
644 | #if defined(TCP_CORK) | 643 | #if defined(MHD_TCP_CORK_NOPUSH) |
645 | /* Allow partial packets */ | 644 | if (connection->sk_tcp_cork_nopush_on) |
646 | /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before | 645 | { |
647 | so try to check current value of TCP_CORK to prevent unrequested flushing */ | 646 | const MHD_SCKT_OPT_BOOL_ off_val = 0; |
648 | if ( (0 != getsockopt (connection->socket_fd, | 647 | /* Disable extra buffering */ |
649 | IPPROTO_TCP, | 648 | if (0 == setsockopt (connection->socket_fd, |
650 | TCP_CORK, | ||
651 | (void*)&cork_val, | ||
652 | ¶m_size)) || | ||
653 | (0 != cork_val)) | ||
654 | res = (0 == setsockopt (connection->socket_fd, | ||
655 | IPPROTO_TCP, | ||
656 | TCP_CORK, | ||
657 | (const void *) &off_val, | ||
658 | sizeof (off_val))) && res; | ||
659 | #elif defined(TCP_NOPUSH) | ||
660 | /* Disable extra buffering */ | ||
661 | /* No need to check current value as disabling TCP_NOPUSH will not flush partial | ||
662 | packet if TCP_NOPUSH wasn't enabled before */ | ||
663 | res = (0 == setsockopt (connection->socket_fd, | ||
664 | IPPROTO_TCP, | 649 | IPPROTO_TCP, |
665 | TCP_NOPUSH, | 650 | MHD_TCP_CORK_NOPUSH, |
666 | (const void *) &off_val, | 651 | (const void *) &off_val, |
667 | sizeof (off_val))) && res; | 652 | sizeof (off_val))) |
668 | #endif /* TCP_NOPUSH && !TCP_CORK */ | 653 | { |
669 | /* Enable Nagle's algorithm for normal buffering */ | 654 | connection->sk_tcp_cork_nopush_on = false; |
670 | res = (0 == setsockopt (connection->socket_fd, | 655 | } |
656 | } | ||
657 | #endif /* MHD_TCP_CORK_NOPUSH */ | ||
658 | |||
659 | #if defined(TCP_NODELAY) | ||
660 | if (connection->sk_tcp_nodelay_on) | ||
661 | { | ||
662 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
663 | /* Enable Nagle's algorithm */ | ||
664 | if (0 == setsockopt (connection->socket_fd, | ||
671 | IPPROTO_TCP, | 665 | IPPROTO_TCP, |
672 | TCP_NODELAY, | 666 | TCP_NODELAY, |
673 | (const void *) &off_val, | 667 | (const void *) &off_val, |
674 | sizeof (off_val))) && res; | 668 | sizeof (off_val))) |
675 | return res; | 669 | { |
676 | #else /* !TCP_NODELAY */ | 670 | connection->sk_tcp_nodelay_on = false; |
677 | (void) connection; | 671 | } |
678 | return false; | 672 | } |
679 | #endif /* !TCP_NODELAY */ | 673 | #endif /* TCP_NODELAY */ |
674 | return !connection->sk_tcp_nodelay_on && !connection->sk_tcp_cork_nopush_on; | ||
680 | } | 675 | } |
681 | 676 | ||
682 | 677 | ||