[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [libmicrohttpd] 64/154: move sendfile function work to conn
From: |
gnunet |
Subject: |
[GNUnet-SVN] [libmicrohttpd] 64/154: move sendfile function work to connection.c |
Date: |
Mon, 19 Aug 2019 10:16:16 +0200 |
This is an automated email from the git hooks/post-receive script.
ng0 pushed a commit to branch master
in repository libmicrohttpd.
commit 0c40dc481b3ed4149c9bb82118d5c923fb34dcde
Author: ng0 <address@hidden>
AuthorDate: Wed Jul 24 10:17:45 2019 +0000
move sendfile function work to connection.c
---
src/microhttpd/connection.c | 72 ++++++++++++
src/microhttpd/mhd_send.c | 262 +-------------------------------------------
src/microhttpd/mhd_send.h | 9 ++
3 files changed, 82 insertions(+), 261 deletions(-)
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 626adb42..3315ad22 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -288,6 +288,12 @@ send_param_adapter (struct MHD_Connection *connection,
static ssize_t
sendfile_adapter (struct MHD_Connection *connection)
{
+ bool want_cork = false;
+ bool have_cork;
+ bool have_more;
+ bool use_corknopush;
+ bool using_tls = false;
+
ssize_t ret;
const int file_fd = connection->response->fd;
uint64_t left;
@@ -454,6 +460,72 @@ sendfile_adapter (struct MHD_Connection *connection)
mhd_assert (send_size >= (size_t)len);
ret = (ssize_t)len;
#endif /* HAVE_FREEBSD_SENDFILE */
+
+ /* ! could be avoided by redefining the variable. */
+ have_cork = ! connection->sk_tcp_nodelay_on;
+
+#ifdef MSG_MORE
+ have_more = true;
+#else
+ have_more = false;
+#endif
+
+#if TCP_NODELAY
+ use_corknopush = false;
+#elif TCP_CORK
+ use_corknopush = true;
+#elif TCP_NOPUSH
+ use_corknopush = true;
+#endif
+
+#ifdef HTTPS_SUPPORT
+ using_tls = (0 != (connection->daemon->options & MHD_USE_TLS));
+#endif
+
+#if TCP_CORK
+ /* When we have CORK, we can have NODELAY on the same system,
+ * at least since Linux 2.2 and both can be combined since
+ * Linux 2.5.71. For more details refer to tcp(7) on Linux.
+ * No other system in 2019-06 has TCP_CORK. */
+ if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork))
+ {
+ if (0 == setsockopt (connection->socket_fd,
+ IPPROTO_TCP,
+ TCP_CORK,
+ (const void *) &off_val,
+ sizeof (off_val)))
+ {
+ connection->sk_tcp_nodelay_on = true;
+ }
+ else if (0 == setsockopt (connection->socket_fd,
+ IPPROTO_TCP,
+ TCP_NODELAY,
+ (const void *) &on_val,
+ sizeof (on_val)))
+ {
+ connection->sk_tcp_nodelay_on = true;
+ }
+ }
+#elif TCP_NOPUSH
+ /* TCP_NOPUSH on FreeBSD is equal to cork on Linux, with the
+ * exception that we know that TCP_NOPUSH will definitely
+ * exist and we can disregard TCP_NODELAY unless requested. */
+ if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork))
+ {
+ MHD_send_socket_state_nopush_ (connection, true, false);
+ /*
+ if (0 == setsockopt (connection->socket_fd,
+ IPPROTO_TCP,
+ TCP_NOPUSH,
+ (const void *) &on_val,
+ sizeof (on_val)))
+ {
+ connection->sk_tcp_nodelay_on = false;
+ }
+ */
+ }
+#endif
+
return ret;
}
#endif /* _MHD_HAVE_SENDFILE */
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c
index 7e312b59..1d3b739a 100644
--- a/src/microhttpd/mhd_send.c
+++ b/src/microhttpd/mhd_send.c
@@ -24,14 +24,13 @@
* @author ng0 <address@hidden>
*/
-/* TODO: sendfile() wrappers. */
+/* TODO: sendfile() wrapper, in connection.c */
/* Functions to be used in: send_param_adapter, MHD_send_
* and every place where sendfile(), sendfile64(), setsockopt()
* are used. */
#include "mhd_send.h"
-#include "connection.h"
/**
* Set socket to nodelay, on or off.
@@ -496,262 +495,3 @@ MHD_send_on_connection2_ (struct MHD_Connection
*connection,
* with this seems to be to mmap the file and write(2) as
* large a chunk as possible to the socket. Alternatively,
* use madvise(..., MADV_SEQUENTIAL). */
-
-#if defined(_MHD_HAVE_SENDFILE)
-/**
- * Function for sending responses backed by file FD.
- * A sendfile() wrapper which also performs cork/uncork
- * operations.
- *
- * @param connection the #MHD_Connection structure
- * @return actual number of bytes sent
- */
-ssize_t
-MHD_sendfile_on_connection_ (struct MHD_Connection *connection)
-{
- // I'm looking for a version of sendfile_adapter() that *also* performs
- // cork/uncork operations. Specifically, we want to make sure that the
- // buffer is flushed after sendfile() is done (so setsockopt() behavior
- // equivalent to MHD_SSO_NO_CORK), and _also_ of course update the
- // setsockopt state, i.e. connection->sk_tcp_nodelay_on = true;
-
- bool want_cork = false;
- bool have_cork;
- bool have_more;
- bool use_corknopush;
- bool using_tls = false;
- ssize_t ret;
- const int file_fd = connection->response->fd;
- uint64_t left;
- uint64_t offsetu64;
-#ifndef HAVE_SENDFILE64
- const uint64_t max_off_t = (uint64_t)OFF_T_MAX;
-#else /* HAVE_SENDFILE64 */
- const uint64_t max_off_t = (uint64_t)OFF64_T_MAX;
-#endif /* HAVE_SENDFILE64 */
-#ifdef MHD_LINUX_SOLARIS_SENDFILE
-#ifndef HAVE_SENDFILE64
- off_t offset;
-#else /* HAVE_SENDFILE64 */
- off64_t offset;
-#endif /* HAVE_SENDFILE64 */
-#endif /* MHD_LINUX_SOLARIS_SENDFILE */
-#ifdef HAVE_FREEBSD_SENDFILE
- off_t sent_bytes;
- int flags = 0;
-#endif
-#ifdef HAVE_DARWIN_SENDFILE
- off_t len;
-#endif /* HAVE_DARWIN_SENDFILE */
- const bool used_thr_p_c = (0 != (connection->daemon->options &
MHD_USE_THREAD_PER_CONNECTION));
- const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ :
MHD_SENFILE_CHUNK_;
- size_t send_size = 0;
- mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender);
-
- offsetu64 = connection->response_write_position +
connection->response->fd_off;
- left = connection->response->total_size -
connection->response_write_position;
- /* Do not allow system to stick sending on single fast connection:
- * use 128KiB chunks (2MiB for thread-per-connection). */
- send_size = (left > chunk_size) ? chunk_size : (size_t) left;
- if (max_off_t < offsetu64)
- { /* Retry to send with standard 'send()'. */
- connection->resp_sender = MHD_resp_sender_std;
- return MHD_ERR_AGAIN_;
- }
-#ifdef MHD_LINUX_SOLARIS_SENDFILE
-#ifndef HAVE_SENDFILE64
- offset = (off_t) offsetu64;
- ret = sendfile (connection->socket_fd,
- file_fd,
- &offset,
- send_size);
-#else /* HAVE_SENDFILE64 */
- offset = (off64_t) offsetu64;
- ret = sendfile64 (connection->socket_fd,
- file_fd,
- &offset,
- send_size);
-#endif /* HAVE_SENDFILE64 */
- if (0 > ret)
- {
- const int err = MHD_socket_get_error_();
- if (MHD_SCKT_ERR_IS_EAGAIN_(err))
- {
-#ifdef EPOLL_SUPPORT
- /* EAGAIN --- no longer write-ready */
- connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
-#endif /* EPOLL_SUPPORT */
- return MHD_ERR_AGAIN_;
- }
- if (MHD_SCKT_ERR_IS_EINTR_ (err))
- return MHD_ERR_AGAIN_;
-#ifdef HAVE_LINUX_SENDFILE
- if (MHD_SCKT_ERR_IS_(err,
- MHD_SCKT_EBADF_))
- return MHD_ERR_BADF_;
- /* sendfile() failed with EINVAL if mmap()-like operations are not
- supported for FD or other 'unusual' errors occurred, so we should try
- to fall back to 'SEND'; see also this thread for info on
- odd libc/Linux behavior with sendfile:
- http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html
*/
- connection->resp_sender = MHD_resp_sender_std;
- return MHD_ERR_AGAIN_;
-#else /* HAVE_SOLARIS_SENDFILE */
- if ( (EAFNOSUPPORT == err) ||
- (EINVAL == err) ||
- (EOPNOTSUPP == err) )
- { /* Retry with standard file reader. */
- connection->resp_sender = MHD_resp_sender_std;
- return MHD_ERR_AGAIN_;
- }
- if ( (ENOTCONN == err) ||
- (EPIPE == err) )
- {
- return MHD_ERR_CONNRESET_;
- }
- return MHD_ERR_BADF_; /* Fail hard */
-#endif /* HAVE_SOLARIS_SENDFILE */
- }
-#ifdef EPOLL_SUPPORT
- else if (send_size > (size_t)ret)
- connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
-#endif /* EPOLL_SUPPORT */
-#elif defined(HAVE_FREEBSD_SENDFILE)
-#ifdef SF_FLAGS
- flags = used_thr_p_c ?
- freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
-#endif /* SF_FLAGS */
- if (0 != sendfile (file_fd,
- connection->socket_fd,
- (off_t) offsetu64,
- send_size,
- NULL,
- &sent_bytes,
- flags))
- {
- const int err = MHD_socket_get_error_();
- if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
- MHD_SCKT_ERR_IS_EINTR_(err) ||
- EBUSY == err)
- {
- mhd_assert (SSIZE_MAX >= sent_bytes);
- if (0 != sent_bytes)
- return (ssize_t)sent_bytes;
-
- return MHD_ERR_AGAIN_;
- }
- /* Some unrecoverable error. Possibly file FD is not suitable
- * for sendfile(). Retry with standard send(). */
- connection->resp_sender = MHD_resp_sender_std;
- return MHD_ERR_AGAIN_;
- }
- mhd_assert (0 < sent_bytes);
- mhd_assert (SSIZE_MAX >= sent_bytes);
- ret = (ssize_t)sent_bytes;
-#elif defined(HAVE_DARWIN_SENDFILE)
- len = (off_t)send_size; /* chunk always fit */
- if (0 != sendfile (file_fd,
- connection->socket_fd,
- (off_t) offsetu64,
- &len,
- NULL,
- 0))
- {
- const int err = MHD_socket_get_error_();
- if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
- MHD_SCKT_ERR_IS_EINTR_(err))
- {
- mhd_assert (0 <= len);
- mhd_assert (SSIZE_MAX >= len);
- mhd_assert (send_size >= (size_t)len);
- if (0 != len)
- return (ssize_t)len;
-
- return MHD_ERR_AGAIN_;
- }
- if (ENOTCONN == err ||
- EPIPE == err)
- return MHD_ERR_CONNRESET_;
- if (ENOTSUP == err ||
- EOPNOTSUPP == err)
- { /* This file FD is not suitable for sendfile().
- * Retry with standard send(). */
- connection->resp_sender = MHD_resp_sender_std;
- return MHD_ERR_AGAIN_;
- }
- return MHD_ERR_BADF_; /* Return hard error. */
- }
- mhd_assert (0 <= len);
- mhd_assert (SSIZE_MAX >= len);
- mhd_assert (send_size >= (size_t)len);
- ret = (ssize_t)len;
-#endif /* HAVE_FREEBSD_SENDFILE */
-
- /* ! could be avoided by redefining the variable. */
- have_cork = ! connection->sk_tcp_nodelay_on;
-
-#ifdef MSG_MORE
- have_more = true;
-#else
- have_more = false;
-#endif
-
-#if TCP_NODELAY
- use_corknopush = false;
-#elif TCP_CORK
- use_corknopush = true;
-#elif TCP_NOPUSH
- use_corknopush = true;
-#endif
-
-#ifdef HTTPS_SUPPORT
- using_tls = (0 != (connection->daemon->options & MHD_USE_TLS));
-#endif
-
-#if TCP_CORK
- /* When we have CORK, we can have NODELAY on the same system,
- * at least since Linux 2.2 and both can be combined since
- * Linux 2.5.71. For more details refer to tcp(7) on Linux.
- * No other system in 2019-06 has TCP_CORK. */
- if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork))
- {
- if (0 == setsockopt (connection->socket_fd,
- IPPROTO_TCP,
- TCP_CORK,
- (const void *) &off_val,
- sizeof (off_val)))
- {
- connection->sk_tcp_nodelay_on = true;
- }
- else if (0 == setsockopt (connection->socket_fd,
- IPPROTO_TCP,
- TCP_NODELAY,
- (const void *) &on_val,
- sizeof (on_val)))
- {
- connection->sk_tcp_nodelay_on = true;
- }
- }
-#elif TCP_NOPUSH
- /* TCP_NOPUSH on FreeBSD is equal to cork on Linux, with the
- * exception that we know that TCP_NOPUSH will definitely
- * exist and we can disregard TCP_NODELAY unless requested. */
- if ((! using_tls) && (use_corknopush) && (have_cork && ! want_cork))
- {
- MHD_send_socket_state_nopush_ (connection, true, false);
- /*
- if (0 == setsockopt (connection->socket_fd,
- IPPROTO_TCP,
- TCP_NOPUSH,
- (const void *) &on_val,
- sizeof (on_val)))
- {
- connection->sk_tcp_nodelay_on = false;
- }
- */
- }
-#endif
-
- return ret;
-}
-#endif /* _MHD_HAVE_SENDFILE */
diff --git a/src/microhttpd/mhd_send.h b/src/microhttpd/mhd_send.h
index a6049865..c4a6d705 100644
--- a/src/microhttpd/mhd_send.h
+++ b/src/microhttpd/mhd_send.h
@@ -77,4 +77,13 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection,
ssize_t
MHD_sendfile_on_connection_ (struct MHD_Connection *connection);
+
+void
+MHD_send_socket_state_nopush_ (struct MHD_Connection *connection,
+ bool value,
+ bool state_store);
+
+void
+MHD_send_socket_state_nodelay_ (struct MHD_Connection *connection,
+ bool value);
#endif /* MHD_SEND_H */
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [GNUnet-SVN] [libmicrohttpd] 55/154: doxygen: MHD_SSO, (continued)
- [GNUnet-SVN] [libmicrohttpd] 55/154: doxygen: MHD_SSO, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 30/154: comments, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 49/154: more OLDSOCK., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 59/154: sendfile and netbsd, comment., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 31/154: combine ifs, fix uninitialized var error, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 62/154: fix errors., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 35/154: use using_tls, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 36/154: implement TCP_NOPUSH branch content, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 34/154: Use s in setsockopt(), gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 38/154: check getsockopt's., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 64/154: move sendfile function work to connection.c,
gnunet <=
- [GNUnet-SVN] [libmicrohttpd] 58/154: start SENDMSG/WRITEV., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 60/154: doxygen fix., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 57/154: cover the case of TCP_NOPUSH and TCP_CORK coexisting on the same OS., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 56/154: doxygen, links, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 52/154: doxygen, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 40/154: doxygen for _send2, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 48/154: connection.c: preprocessor ifdef some setsockopts., gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 46/154: Merge remote-tracking branch 'origin/master' into dev/ng0/gsoc2019, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 53/154: reminder, gnunet, 2019/08/19
- [GNUnet-SVN] [libmicrohttpd] 41/154: doxygen for send_, gnunet, 2019/08/19