diff options
author | ng0 <ng0@n0.is> | 2019-07-24 10:03:37 +0000 |
---|---|---|
committer | ng0 <ng0@n0.is> | 2019-07-24 10:03:37 +0000 |
commit | aad43f23f0aa5cf997d9e880e2d78eefd9c6a221 (patch) | |
tree | df91bd1cd474f4f60017ac7bfc3a008c62db0e38 /src/microhttpd | |
parent | 1b013c78a695cee32135ec5ec93dff959bf8f8f6 (diff) | |
download | libmicrohttpd-aad43f23f0aa5cf997d9e880e2d78eefd9c6a221.tar.gz libmicrohttpd-aad43f23f0aa5cf997d9e880e2d78eefd9c6a221.zip |
incomplete commit, adding 2 new helper functions and more.
Diffstat (limited to 'src/microhttpd')
-rw-r--r-- | src/microhttpd/connection.c | 11 | ||||
-rw-r--r-- | src/microhttpd/mhd_send.c | 325 | ||||
-rw-r--r-- | src/microhttpd/mhd_send.h | 3 |
3 files changed, 333 insertions, 6 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 1893de15..626adb42 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -3350,12 +3350,20 @@ MHD_connection_handle_write (struct MHD_Connection *connection) | |||
3350 | return; | 3350 | return; |
3351 | case MHD_CONNECTION_HEADERS_SENDING: | 3351 | case MHD_CONNECTION_HEADERS_SENDING: |
3352 | /* TODO: Maybe use MHD_send_on_connection2_()? */ | 3352 | /* TODO: Maybe use MHD_send_on_connection2_()? */ |
3353 | /* | ||
3354 | ret = MHD_send_on_connection2_ (struct MHD_Connection *connection, | ||
3355 | const char *header, | ||
3356 | size_t header_size, | ||
3357 | const char *buffer, | ||
3358 | size_t buffer_size); | ||
3359 | */ | ||
3353 | ret = MHD_send_on_connection_ (connection, | 3360 | ret = MHD_send_on_connection_ (connection, |
3354 | &connection->write_buffer | 3361 | &connection->write_buffer |
3355 | [connection->write_buffer_send_offset], | 3362 | [connection->write_buffer_send_offset], |
3356 | connection->write_buffer_append_offset - | 3363 | connection->write_buffer_append_offset - |
3357 | connection->write_buffer_send_offset, | 3364 | connection->write_buffer_send_offset, |
3358 | MHD_SSO_MAY_CORK); | 3365 | MHD_SSO_MAY_CORK); |
3366 | |||
3359 | if (ret < 0) | 3367 | if (ret < 0) |
3360 | { | 3368 | { |
3361 | if (MHD_ERR_AGAIN_ == ret) | 3369 | if (MHD_ERR_AGAIN_ == ret) |
@@ -3392,7 +3400,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection) | |||
3392 | #if defined(_MHD_HAVE_SENDFILE) | 3400 | #if defined(_MHD_HAVE_SENDFILE) |
3393 | if (MHD_resp_sender_sendfile == connection->resp_sender) | 3401 | if (MHD_resp_sender_sendfile == connection->resp_sender) |
3394 | { | 3402 | { |
3395 | ret = sendfile_adapter (connection); | 3403 | // ret = sendfile_adapter (connection); |
3404 | ret = MHD_sendfile_on_connection_ (connection); | ||
3396 | } | 3405 | } |
3397 | else | 3406 | else |
3398 | #else /* ! _MHD_HAVE_SENDFILE */ | 3407 | #else /* ! _MHD_HAVE_SENDFILE */ |
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c index 7991830c..ee32a868 100644 --- a/src/microhttpd/mhd_send.c +++ b/src/microhttpd/mhd_send.c | |||
@@ -33,6 +33,52 @@ | |||
33 | #include "mhd_send.h" | 33 | #include "mhd_send.h" |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * Set socket to nodelay, on or off. | ||
37 | * | ||
38 | * @param connection the MHD_Connection structure | ||
39 | * @param value the state to set, boolean | ||
40 | */ | ||
41 | void | ||
42 | MHD_send_socket_state_nodelay_ (struct MHD_Connection *connection, | ||
43 | bool value) | ||
44 | { | ||
45 | #if TCP_NODELAY | ||
46 | const MHD_SCKT_OPT_BOOL_ state_val = value ? 1 : 0; | ||
47 | |||
48 | if (0 == setsockopt (connection->socket_fd, | ||
49 | IPPROTO_TCP, | ||
50 | TCP_NODELAY, | ||
51 | (const void *) &state_val, | ||
52 | sizeof (state_val))) | ||
53 | { | ||
54 | connection->sk_tcp_nodelay_on = value; | ||
55 | } | ||
56 | #endif | ||
57 | } | ||
58 | |||
59 | void | ||
60 | MHD_send_socket_state_nopush_ (struct MHD_Connection *connection, | ||
61 | bool value, | ||
62 | bool state_store) | ||
63 | { | ||
64 | #if TCP_NOPUSH | ||
65 | const MHD_SCKT_OPT_BOOL_ state_val = value ? 1 : 0; | ||
66 | |||
67 | if (0 == setsockopt (connection->socket_fd, | ||
68 | IPPROTO_TCP, | ||
69 | TCP_NOPUSH, | ||
70 | (const void *) &state_val, | ||
71 | sizeof (state_val))) | ||
72 | { | ||
73 | /* When TRUE above, this is usually FALSE, but | ||
74 | * not always. We can't use the negation of | ||
75 | * value for that reason. */ | ||
76 | connection->sk_tcp_nodelay_on = state_store; | ||
77 | } | ||
78 | #endif | ||
79 | } | ||
80 | |||
81 | /** | ||
36 | * Send buffer on connection, and remember the current state of | 82 | * Send buffer on connection, and remember the current state of |
37 | * the socket options; only call setsockopt when absolutely | 83 | * the socket options; only call setsockopt when absolutely |
38 | * necessary. | 84 | * necessary. |
@@ -145,6 +191,8 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
145 | * exist and we can disregard TCP_NODELAY unless requested. */ | 191 | * exist and we can disregard TCP_NODELAY unless requested. */ |
146 | if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork)) | 192 | if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork)) |
147 | { | 193 | { |
194 | MHD_send_socket_state_nopush_ (connection, true, false); | ||
195 | /* | ||
148 | if (0 == setsockopt (s, | 196 | if (0 == setsockopt (s, |
149 | IPPROTO_TCP, | 197 | IPPROTO_TCP, |
150 | TCP_NOPUSH, | 198 | TCP_NOPUSH, |
@@ -153,11 +201,13 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
153 | { | 201 | { |
154 | connection->sk_tcp_nodelay_on = false; | 202 | connection->sk_tcp_nodelay_on = false; |
155 | } | 203 | } |
204 | */ | ||
156 | } | 205 | } |
157 | #endif | 206 | #endif |
158 | #if TCP_NODELAY | 207 | #if TCP_NODELAY |
159 | if ((! using_tls) && (! use_corknopush) && (! have_cork && want_cork)) | 208 | if ((! using_tls) && (! use_corknopush) && (! have_cork && want_cork)) |
160 | { | 209 | { |
210 | /* | ||
161 | if (0 == setsockopt (s, | 211 | if (0 == setsockopt (s, |
162 | IPPROTO_TCP, | 212 | IPPROTO_TCP, |
163 | TCP_NODELAY, | 213 | TCP_NODELAY, |
@@ -166,6 +216,8 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
166 | { | 216 | { |
167 | connection->sk_tcp_nodelay_on = false; | 217 | connection->sk_tcp_nodelay_on = false; |
168 | } | 218 | } |
219 | */ | ||
220 | MHD_send_socket_state_nodelay_ (connection, false); | ||
169 | } | 221 | } |
170 | #endif | 222 | #endif |
171 | 223 | ||
@@ -274,6 +326,8 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
274 | * for the TCP_CORK case here. */ | 326 | * for the TCP_CORK case here. */ |
275 | if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork)) | 327 | if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork)) |
276 | { | 328 | { |
329 | MHD_send_socket_state_nopush_ (connection, true, false); | ||
330 | /* | ||
277 | if (0 == setsockopt (s, | 331 | if (0 == setsockopt (s, |
278 | IPPROTO_TCP, | 332 | IPPROTO_TCP, |
279 | TCP_NOPUSH, | 333 | TCP_NOPUSH, |
@@ -282,12 +336,15 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
282 | { | 336 | { |
283 | connection->sk_tcp_nodelay_on = false; | 337 | connection->sk_tcp_nodelay_on = false; |
284 | } | 338 | } |
339 | */ | ||
285 | } | 340 | } |
286 | #endif | 341 | #endif |
287 | 342 | ||
288 | #if TCP_NODELAY | 343 | #if TCP_NODELAY |
289 | if ((! using_tls) && (! use_corknopush) && (have_cork && ! want_cork)) | 344 | if ((! using_tls) && (! use_corknopush) && (have_cork && ! want_cork)) |
290 | { | 345 | { |
346 | MHD_send_socket_state_nodelay_ (connection, true); | ||
347 | /* | ||
291 | if (0 == setsockopt (s, | 348 | if (0 == setsockopt (s, |
292 | IPPROTO_TCP, | 349 | IPPROTO_TCP, |
293 | TCP_NODELAY, | 350 | TCP_NODELAY, |
@@ -296,6 +353,7 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
296 | { | 353 | { |
297 | connection->sk_tcp_nodelay_on = true; | 354 | connection->sk_tcp_nodelay_on = true; |
298 | } | 355 | } |
356 | */ | ||
299 | } | 357 | } |
300 | #endif | 358 | #endif |
301 | 359 | ||
@@ -348,6 +406,8 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
348 | #if TCP_NODELAY | 406 | #if TCP_NODELAY |
349 | if ((! use_corknopush) && (! have_cork && want_cork)) | 407 | if ((! use_corknopush) && (! have_cork && want_cork)) |
350 | { | 408 | { |
409 | MHD_send_socket_state_nodelay_ (connection, false); | ||
410 | /* | ||
351 | if (0 == setsockopt (s, | 411 | if (0 == setsockopt (s, |
352 | IPPROTO_TCP, | 412 | IPPROTO_TCP, |
353 | TCP_NODELAY, | 413 | TCP_NODELAY, |
@@ -356,6 +416,7 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
356 | { | 416 | { |
357 | connection->sk_tcp_nodelay_on = false; | 417 | connection->sk_tcp_nodelay_on = false; |
358 | } | 418 | } |
419 | */ | ||
359 | } | 420 | } |
360 | #endif | 421 | #endif |
361 | 422 | ||
@@ -404,6 +465,8 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
404 | if (ret == header_len + buffer_len) | 465 | if (ret == header_len + buffer_len) |
405 | { | 466 | { |
406 | /* Response complete, set NOPUSH to off */ | 467 | /* Response complete, set NOPUSH to off */ |
468 | MHD_send_socket_state_nopush_ (connection, false, false); | ||
469 | /* | ||
407 | if (0 == setsockopt (s, | 470 | if (0 == setsockopt (s, |
408 | IPPROTO_TCP, | 471 | IPPROTO_TCP, |
409 | TCP_NOPUSH, | 472 | TCP_NOPUSH, |
@@ -412,6 +475,7 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
412 | { | 475 | { |
413 | connection->sk_tcp_nodelay_on = false; | 476 | connection->sk_tcp_nodelay_on = false; |
414 | } | 477 | } |
478 | */ | ||
415 | } | 479 | } |
416 | errno = eno; | 480 | errno = eno; |
417 | } | 481 | } |
@@ -431,11 +495,262 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
431 | * with this seems to be to mmap the file and write(2) as | 495 | * with this seems to be to mmap the file and write(2) as |
432 | * large a chunk as possible to the socket. Alternatively, | 496 | * large a chunk as possible to the socket. Alternatively, |
433 | * use madvise(..., MADV_SEQUENTIAL). */ | 497 | * use madvise(..., MADV_SEQUENTIAL). */ |
498 | |||
499 | #if defined(_MHD_HAVE_SENDFILE) | ||
500 | /** | ||
501 | * Function for sending responses backed by file FD. | ||
502 | * A sendfile() wrapper which also performs cork/uncork | ||
503 | * operations. | ||
504 | * | ||
505 | * @param connection the #MHD_Connection structure | ||
506 | * @return actual number of bytes sent | ||
507 | */ | ||
434 | ssize_t | 508 | ssize_t |
435 | MHD_sendfile_on_connection_ (struct MHD_Connection *connection, | 509 | MHD_sendfile_on_connection_ (struct MHD_Connection *connection) |
436 | const char *buffer, | ||
437 | size_t buffer_size, | ||
438 | enum MHD_SendSocketOptions options) | ||
439 | { | 510 | { |
440 | // TODO | 511 | // I'm looking for a version of sendfile_adapter() that *also* performs |
512 | // cork/uncork operations. Specifically, we want to make sure that the | ||
513 | // buffer is flushed after sendfile() is done (so setsockopt() behavior | ||
514 | // equivalent to MHD_SSO_NO_CORK), and _also_ of course update the | ||
515 | // setsockopt state, i.e. connection->sk_tcp_nodelay_on = true; | ||
516 | |||
517 | bool want_cork = false; | ||
518 | bool have_cork; | ||
519 | bool have_more; | ||
520 | bool use_corknopush; | ||
521 | bool using_tls = false; | ||
522 | ssize_t ret; | ||
523 | const int file_fd = connection->response->fd; | ||
524 | uint64_t left; | ||
525 | uint64_t offsetu64; | ||
526 | #ifndef HAVE_SENDFILE64 | ||
527 | const uint64_t max_off_t = (uint64_t)OFF_T_MAX; | ||
528 | #else /* HAVE_SENDFILE64 */ | ||
529 | const uint64_t max_off_t = (uint64_t)OFF64_T_MAX; | ||
530 | #endif /* HAVE_SENDFILE64 */ | ||
531 | #ifdef MHD_LINUX_SOLARIS_SENDFILE | ||
532 | #ifndef HAVE_SENDFILE64 | ||
533 | off_t offset; | ||
534 | #else /* HAVE_SENDFILE64 */ | ||
535 | off64_t offset; | ||
536 | #endif /* HAVE_SENDFILE64 */ | ||
537 | #endif /* MHD_LINUX_SOLARIS_SENDFILE */ | ||
538 | #ifdef HAVE_FREEBSD_SENDFILE | ||
539 | off_t sent_bytes; | ||
540 | int flags = 0; | ||
541 | #endif | ||
542 | #ifdef HAVE_DARWIN_SENDFILE | ||
543 | off_t len; | ||
544 | #endif /* HAVE_DARWIN_SENDFILE */ | ||
545 | const bool used_thr_p_c = (0 != (connection->daemon->options & MHD_USE_THREAD_PER_CONNECTION)); | ||
546 | const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ : MHD_SENFILE_CHUNK_; | ||
547 | size_t send_size = 0; | ||
548 | mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender); | ||
549 | |||
550 | offsetu64 = connection->response_write_position + connection->response->fd_off; | ||
551 | left = connection->response->total_size - connection->response_write_position; | ||
552 | /* Do not allow system to stick sending on single fast connection: | ||
553 | * use 128KiB chunks (2MiB for thread-per-connection). */ | ||
554 | send_size = (left > chunk_size) ? chunk_size : (size_t) left; | ||
555 | if (max_off_t < offsetu64) | ||
556 | { /* Retry to send with standard 'send()'. */ | ||
557 | connection->resp_sender = MHD_resp_sender_std; | ||
558 | return MHD_ERR_AGAIN_; | ||
559 | } | ||
560 | #ifdef MHD_LINUX_SOLARIS_SENDFILE | ||
561 | #ifndef HAVE_SENDFILE64 | ||
562 | offset = (off_t) offsetu64; | ||
563 | ret = sendfile (connection->socket_fd, | ||
564 | file_fd, | ||
565 | &offset, | ||
566 | send_size); | ||
567 | #else /* HAVE_SENDFILE64 */ | ||
568 | offset = (off64_t) offsetu64; | ||
569 | ret = sendfile64 (connection->socket_fd, | ||
570 | file_fd, | ||
571 | &offset, | ||
572 | send_size); | ||
573 | #endif /* HAVE_SENDFILE64 */ | ||
574 | if (0 > ret) | ||
575 | { | ||
576 | const int err = MHD_socket_get_error_(); | ||
577 | if (MHD_SCKT_ERR_IS_EAGAIN_(err)) | ||
578 | { | ||
579 | #ifdef EPOLL_SUPPORT | ||
580 | /* EAGAIN --- no longer write-ready */ | ||
581 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
582 | #endif /* EPOLL_SUPPORT */ | ||
583 | return MHD_ERR_AGAIN_; | ||
584 | } | ||
585 | if (MHD_SCKT_ERR_IS_EINTR_ (err)) | ||
586 | return MHD_ERR_AGAIN_; | ||
587 | #ifdef HAVE_LINUX_SENDFILE | ||
588 | if (MHD_SCKT_ERR_IS_(err, | ||
589 | MHD_SCKT_EBADF_)) | ||
590 | return MHD_ERR_BADF_; | ||
591 | /* sendfile() failed with EINVAL if mmap()-like operations are not | ||
592 | supported for FD or other 'unusual' errors occurred, so we should try | ||
593 | to fall back to 'SEND'; see also this thread for info on | ||
594 | odd libc/Linux behavior with sendfile: | ||
595 | http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */ | ||
596 | connection->resp_sender = MHD_resp_sender_std; | ||
597 | return MHD_ERR_AGAIN_; | ||
598 | #else /* HAVE_SOLARIS_SENDFILE */ | ||
599 | if ( (EAFNOSUPPORT == err) || | ||
600 | (EINVAL == err) || | ||
601 | (EOPNOTSUPP == err) ) | ||
602 | { /* Retry with standard file reader. */ | ||
603 | connection->resp_sender = MHD_resp_sender_std; | ||
604 | return MHD_ERR_AGAIN_; | ||
605 | } | ||
606 | if ( (ENOTCONN == err) || | ||
607 | (EPIPE == err) ) | ||
608 | { | ||
609 | return MHD_ERR_CONNRESET_; | ||
610 | } | ||
611 | return MHD_ERR_BADF_; /* Fail hard */ | ||
612 | #endif /* HAVE_SOLARIS_SENDFILE */ | ||
613 | } | ||
614 | #ifdef EPOLL_SUPPORT | ||
615 | else if (send_size > (size_t)ret) | ||
616 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
617 | #endif /* EPOLL_SUPPORT */ | ||
618 | #elif defined(HAVE_FREEBSD_SENDFILE) | ||
619 | #ifdef SF_FLAGS | ||
620 | flags = used_thr_p_c ? | ||
621 | freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_; | ||
622 | #endif /* SF_FLAGS */ | ||
623 | if (0 != sendfile (file_fd, | ||
624 | connection->socket_fd, | ||
625 | (off_t) offsetu64, | ||
626 | send_size, | ||
627 | NULL, | ||
628 | &sent_bytes, | ||
629 | flags)) | ||
630 | { | ||
631 | const int err = MHD_socket_get_error_(); | ||
632 | if (MHD_SCKT_ERR_IS_EAGAIN_(err) || | ||
633 | MHD_SCKT_ERR_IS_EINTR_(err) || | ||
634 | EBUSY == err) | ||
635 | { | ||
636 | mhd_assert (SSIZE_MAX >= sent_bytes); | ||
637 | if (0 != sent_bytes) | ||
638 | return (ssize_t)sent_bytes; | ||
639 | |||
640 | return MHD_ERR_AGAIN_; | ||
641 | } | ||
642 | /* Some unrecoverable error. Possibly file FD is not suitable | ||
643 | * for sendfile(). Retry with standard send(). */ | ||
644 | connection->resp_sender = MHD_resp_sender_std; | ||
645 | return MHD_ERR_AGAIN_; | ||
646 | } | ||
647 | mhd_assert (0 < sent_bytes); | ||
648 | mhd_assert (SSIZE_MAX >= sent_bytes); | ||
649 | ret = (ssize_t)sent_bytes; | ||
650 | #elif defined(HAVE_DARWIN_SENDFILE) | ||
651 | len = (off_t)send_size; /* chunk always fit */ | ||
652 | if (0 != sendfile (file_fd, | ||
653 | connection->socket_fd, | ||
654 | (off_t) offsetu64, | ||
655 | &len, | ||
656 | NULL, | ||
657 | 0)) | ||
658 | { | ||
659 | const int err = MHD_socket_get_error_(); | ||
660 | if (MHD_SCKT_ERR_IS_EAGAIN_(err) || | ||
661 | MHD_SCKT_ERR_IS_EINTR_(err)) | ||
662 | { | ||
663 | mhd_assert (0 <= len); | ||
664 | mhd_assert (SSIZE_MAX >= len); | ||
665 | mhd_assert (send_size >= (size_t)len); | ||
666 | if (0 != len) | ||
667 | return (ssize_t)len; | ||
668 | |||
669 | return MHD_ERR_AGAIN_; | ||
670 | } | ||
671 | if (ENOTCONN == err || | ||
672 | EPIPE == err) | ||
673 | return MHD_ERR_CONNRESET_; | ||
674 | if (ENOTSUP == err || | ||
675 | EOPNOTSUPP == err) | ||
676 | { /* This file FD is not suitable for sendfile(). | ||
677 | * Retry with standard send(). */ | ||
678 | connection->resp_sender = MHD_resp_sender_std; | ||
679 | return MHD_ERR_AGAIN_; | ||
680 | } | ||
681 | return MHD_ERR_BADF_; /* Return hard error. */ | ||
682 | } | ||
683 | mhd_assert (0 <= len); | ||
684 | mhd_assert (SSIZE_MAX >= len); | ||
685 | mhd_assert (send_size >= (size_t)len); | ||
686 | ret = (ssize_t)len; | ||
687 | #endif /* HAVE_FREEBSD_SENDFILE */ | ||
688 | |||
689 | /* ! could be avoided by redefining the variable. */ | ||
690 | have_cork = ! connection->sk_tcp_nodelay_on; | ||
691 | |||
692 | #ifdef MSG_MORE | ||
693 | have_more = true; | ||
694 | #else | ||
695 | have_more = false; | ||
696 | #endif | ||
697 | |||
698 | #if TCP_NODELAY | ||
699 | use_corknopush = false; | ||
700 | #elif TCP_CORK | ||
701 | use_corknopush = true; | ||
702 | #elif TCP_NOPUSH | ||
703 | use_corknopush = true; | ||
704 | #endif | ||
705 | |||
706 | #ifdef HTTPS_SUPPORT | ||
707 | using_tls = (0 != (connection->daemon->options & MHD_USE_TLS)); | ||
708 | #endif | ||
709 | |||
710 | #if TCP_CORK | ||
711 | /* When we have CORK, we can have NODELAY on the same system, | ||
712 | * at least since Linux 2.2 and both can be combined since | ||
713 | * Linux 2.5.71. For more details refer to tcp(7) on Linux. | ||
714 | * No other system in 2019-06 has TCP_CORK. */ | ||
715 | if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork)) | ||
716 | { | ||
717 | if (0 == setsockopt (connection->socket_fd, | ||
718 | IPPROTO_TCP, | ||
719 | TCP_CORK, | ||
720 | (const void *) &off_val, | ||
721 | sizeof (off_val))) | ||
722 | { | ||
723 | connection->sk_tcp_nodelay_on = true; | ||
724 | } | ||
725 | else if (0 == setsockopt (connection->socket_fd, | ||
726 | IPPROTO_TCP, | ||
727 | TCP_NODELAY, | ||
728 | (const void *) &on_val, | ||
729 | sizeof (on_val))) | ||
730 | { | ||
731 | connection->sk_tcp_nodelay_on = true; | ||
732 | } | ||
733 | } | ||
734 | #elif TCP_NOPUSH | ||
735 | /* TCP_NOPUSH on FreeBSD is equal to cork on Linux, with the | ||
736 | * exception that we know that TCP_NOPUSH will definitely | ||
737 | * exist and we can disregard TCP_NODELAY unless requested. */ | ||
738 | if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork)) | ||
739 | { | ||
740 | MHD_send_socket_state_nopush_ (connection, true, false); | ||
741 | /* | ||
742 | if (0 == setsockopt (connection->socket_fd, | ||
743 | IPPROTO_TCP, | ||
744 | TCP_NOPUSH, | ||
745 | (const void *) &on_val, | ||
746 | sizeof (on_val))) | ||
747 | { | ||
748 | connection->sk_tcp_nodelay_on = false; | ||
749 | } | ||
750 | */ | ||
751 | } | ||
752 | #endif | ||
753 | |||
754 | return ret; | ||
441 | } | 755 | } |
756 | #endif /* _MHD_HAVE_SENDFILE */ | ||
diff --git a/src/microhttpd/mhd_send.h b/src/microhttpd/mhd_send.h index e6ed3268..a6049865 100644 --- a/src/microhttpd/mhd_send.h +++ b/src/microhttpd/mhd_send.h | |||
@@ -74,4 +74,7 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
74 | size_t header_size, | 74 | size_t header_size, |
75 | const char *buffer, | 75 | const char *buffer, |
76 | size_t buffer_size); | 76 | size_t buffer_size); |
77 | |||
78 | ssize_t | ||
79 | MHD_sendfile_on_connection_ (struct MHD_Connection *connection); | ||
77 | #endif /* MHD_SEND_H */ | 80 | #endif /* MHD_SEND_H */ |