aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r--src/microhttpd/connection.c215
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
497socket_start_extra_buffering (struct MHD_Connection *connection) 501socket_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
554socket_start_no_buffering (struct MHD_Connection *connection) 553socket_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
634socket_start_normal_buffering (struct MHD_Connection *connection) 640socket_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 &param_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