[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 03/04: mhd_send.c: Fixed: body and header pushing logic
From: |
gnunet |
Subject: |
[libmicrohttpd] 03/04: mhd_send.c: Fixed: body and header pushing logic |
Date: |
Sun, 13 Dec 2020 15:37:52 +0100 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit 75e49713c671acc9d0df6167b23bbb0c1273b8df
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Sun Dec 13 17:24:36 2020 +0300
mhd_send.c: Fixed: body and header pushing logic
---
src/microhttpd/connection.c | 13 ++++++--
src/microhttpd/mhd_send.c | 81 ++++++++++++++++++++++++++++++++++++++-------
src/microhttpd/mhd_send.h | 15 +++++++--
3 files changed, 91 insertions(+), 18 deletions(-)
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 0ffaffff..51384788 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -2931,26 +2931,33 @@ MHD_connection_handle_write (struct MHD_Connection
*connection)
if ( (NULL == resp->crc) &&
(0 == connection->response_write_position) )
{
+ mhd_assert (resp->total_size >= resp->data_size);
/* Send response headers alongside the response body, if the body
* data is available. */
ret = MHD_send_hdr_and_body_ (connection,
&connection->write_buffer
[connection->write_buffer_send_offset],
wb_ready,
+ false,
resp->data,
- resp->data_size);
+ resp->data_size,
+ (resp->total_size == resp->data_size));
}
else
{
- /* This is response for HEAD request, reply body is not allowed
+ /* This is response for HEAD request or reply body is not allowed
* for any other reason or reply body is dynamically generated. */
/* Do not send the body data even if it's available. */
ret = MHD_send_hdr_and_body_ (connection,
&connection->write_buffer
[connection->write_buffer_send_offset],
wb_ready,
+ false,
NULL,
- 0);
+ 0,
+ ((0 == resp->total_size) ||
+ (resp->total_size ==
+ connection->response_write_position)));
}
if (ret < 0)
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c
index e54a251c..8abd30d6 100644
--- a/src/microhttpd/mhd_send.c
+++ b/src/microhttpd/mhd_send.c
@@ -811,10 +811,14 @@ ssize_t
MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
const char *header,
size_t header_size,
+ bool never_push_hdr,
const char *body,
- size_t body_size)
+ size_t body_size,
+ bool complete_response)
{
ssize_t ret;
+ bool push_hdr;
+ bool push_body;
#if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
MHD_socket s = connection->socket_fd;
struct iovec vector[2];
@@ -826,6 +830,32 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
#endif /* HAVE_SENDMSG || HAVE_WRITEV */
mhd_assert ( (NULL != body) || (0 == body_size) );
+ push_body = complete_response;
+
+ if (! never_push_hdr)
+ {
+ if (! complete_response)
+ push_hdr = true; /* Push the header as the client may react
+ * on header alone while the body data is
+ * being prepared. */
+ else
+ {
+ if (1400 > (header_size + body_size))
+ push_hdr = false; /* Do not push the header as complete
+ * reply is already ready and the whole
+ * reply most probably will fit into
+ * the single IP packet. */
+ else
+ push_hdr = true; /* Push header alone so client may react
+ * on it while reply body is being delivered. */
+ }
+ }
+ else
+ push_hdr = false;
+
+ if (complete_response && (0 == body_size))
+ push_hdr = true; /* The header alone is equal to the whole response. */
+
if (
#if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
(no_vec) ||
@@ -839,7 +869,8 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
ret = MHD_send_on_connection_ (connection,
header,
header_size,
- MHD_SSO_HDR_CORK);
+ push_hdr ?
+ MHD_SSO_PUSH_DATA: MHD_SSO_PREFER_BUFF);
if ( ((size_t) header_size == ret) &&
(((size_t) SSIZE_MAX > header_size)) &&
(0 != body_size) )
@@ -850,12 +881,17 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
* the next round. */
/* Make sure that sum of ret + ret2 will not exceed SSIZE_MAX. */
if ( (((size_t) SSIZE_MAX) - ((size_t) ret)) < body_size)
+ {
body_size = (((size_t) SSIZE_MAX) - ((size_t) ret));
+ complete_response = false;
+ push_body = complete_response;
+ }
ret2 = MHD_send_on_connection_ (connection,
body,
body_size,
- MHD_SSO_PUSH_DATA);
+ push_body ?
+ MHD_SSO_PUSH_DATA: MHD_SSO_PREFER_BUFF);
if (0 < ret2)
return ret + ret2; /* Total data sent */
if (MHD_ERR_AGAIN_ == ret2)
@@ -869,17 +905,19 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
if ( ((size_t) SSIZE_MAX <= body_size) ||
((size_t) SSIZE_MAX < (header_size + body_size)) )
+ {
body_size = SSIZE_MAX - header_size;
+ complete_response = false;
+ push_body = complete_response;
+ }
- /* Since we generally give the fully answer, we do not want
- corking to happen */
pre_send_setopt (connection,
#if HAVE_SENDMSG
true,
#elif HAVE_WRITEV
false,
#endif /* HAVE_WRITEV */
- true);
+ push_hdr || push_body);
vector[0].iov_base = (void *) header;
vector[0].iov_len = header_size;
@@ -913,12 +951,15 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
/* If there is a need to push the data from network buffers
* call post_send_setopt(). */
- /* If TLS connection is used then next final send() will be
- * without MSG_MORE support. If non-TLS connection is used
- * it's unknown whether sendfile() will be used or not so
- * assume that next final send() will be the same, like for
- * this response. */
- if ((header_size + body_size) == (size_t) ret)
+ if ( (push_body) &&
+ ((header_size + body_size) == (size_t) ret) )
+ {
+ /* Complete reply has been sent. */
+ /* If TLS connection is used then next final send() will be
+ * without MSG_MORE support. If non-TLS connection is used
+ * it's unknown whether next 'send' will be plain send() / sendmsg() or
+ * sendfile() will be used so assume that next final send() will be
+ * the same, like for this response. */
post_send_setopt (connection,
#if HAVE_SENDMSG
true,
@@ -926,6 +967,22 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
false,
#endif /* HAVE_WRITEV */
true);
+ }
+ else if ( (push_hdr) &&
+ (header_size <= (size_t) ret))
+ {
+ /* The header has been sent completely and there is a
+ * need to push the header data. */
+ /* Luckily it is know what type of send function will be used
+ * next. */
+ post_send_setopt (connection,
+#if defined(_MHD_HAVE_SENDFILE)
+ MHD_resp_sender_std == connection->resp_sender,
+#else /* ! _MHD_HAVE_SENDFILE */
+ true,
+#endif /* ! _MHD_HAVE_SENDFILE */
+ true);
+ }
return ret;
#else /* ! (HAVE_SENDMSG || HAVE_WRITEV) */
diff --git a/src/microhttpd/mhd_send.h b/src/microhttpd/mhd_send.h
index bc296588..69a06769 100644
--- a/src/microhttpd/mhd_send.h
+++ b/src/microhttpd/mhd_send.h
@@ -92,9 +92,16 @@ MHD_send_on_connection_ (struct MHD_Connection *connection,
*
* @param connection the MHD_Connection structure
* @param header content of header to send
- * @param header_size the size of the header (in bytes)
+ * @param header_size the size of the @a header (in bytes)
+ * @param never_push_hdr set to true to disable internal algorithm
+ * that can push automatically header data
+ * alone to the network
* @param body content of the body to send (optional, may be NULL)
- * @param body_size the size of the body (in bytes)
+ * @param body_size the size of the @a body (in bytes)
+ * @param complete_response set to true if complete response
+ * is provided by @a header and @a body,
+ * set to false if additional body data
+ * will be sent later
* @return sum of the number of bytes sent from both buffers or
* error code (negative)
*/
@@ -102,8 +109,10 @@ ssize_t
MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
const char *header,
size_t header_size,
+ bool never_push_hdr,
const char *body,
- size_t body_size);
+ size_t body_size,
+ bool complete_response);
#if defined(_MHD_HAVE_SENDFILE)
ssize_t
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.