gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] branch master updated (9c70bc55 -> 526de1a8)


From: gnunet
Subject: [libmicrohttpd] branch master updated (9c70bc55 -> 526de1a8)
Date: Sun, 13 Dec 2020 15:37:49 +0100

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from 9c70bc55 Do not send dynamic response body with header
     new 275990c3 Send reply: minor optimisation and readability
     new cd8294e5 MHD_send: renamed function for clarity, moved doxy
     new 75e49713 mhd_send.c: Fixed: body and header pushing logic
     new 526de1a8 MHD_send_hdr_and_body_: streamlined code

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/microhttpd/connection.c |  46 ++++++++-----
 src/microhttpd/mhd_send.c   | 164 ++++++++++++++++++++++++++------------------
 src/microhttpd/mhd_send.h   |  31 +++++++--
 3 files changed, 152 insertions(+), 89 deletions(-)

diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 100abbc0..51384788 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -2913,43 +2913,51 @@ MHD_connection_handle_write (struct MHD_Connection 
*connection)
     return;
   case MHD_CONNECTION_HEADERS_SENDING:
     {
+      struct MHD_Response *const resp = connection->response;
       const size_t wb_ready = connection->write_buffer_append_offset
                               - connection->write_buffer_send_offset;
       mhd_assert (connection->write_buffer_append_offset >= \
                   connection->write_buffer_send_offset);
-      mhd_assert (NULL != connection->response);
-      mhd_assert ( (0 == connection->response->data_size) || \
-                   (0 == connection->response->data_start) || \
-                   (NULL != connection->response->crc) );
+      mhd_assert (NULL != resp);
+      mhd_assert ( (0 == resp->data_size) || \
+                   (0 == resp->data_start) || \
+                   (NULL != resp->crc) );
       mhd_assert ( (0 == connection->response_write_position) || \
-                   (response->total_size ==
+                   (resp->total_size ==
                     connection->response_write_position) || \
                    (MHD_SIZE_UNKNOWN ==
                     connection->response_write_position) );
 
-      if ( (NULL == connection->response->crc) &&
+      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_on_connection2_ (connection,
-                                        &connection->write_buffer
-                                        [connection->write_buffer_send_offset],
-                                        wb_ready,
-                                        connection->response->data,
-                                        connection->response->data_size);
+        ret = MHD_send_hdr_and_body_ (connection,
+                                      &connection->write_buffer
+                                      [connection->write_buffer_send_offset],
+                                      wb_ready,
+                                      false,
+                                      resp->data,
+                                      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_on_connection2_ (connection,
-                                        &connection->write_buffer
-                                        [connection->write_buffer_send_offset],
-                                        wb_ready,
-                                        NULL,
-                                        0);
+        ret = MHD_send_hdr_and_body_ (connection,
+                                      &connection->write_buffer
+                                      [connection->write_buffer_send_offset],
+                                      wb_ready,
+                                      false,
+                                      NULL,
+                                      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 f0cdfb58..1f187902 100644
--- a/src/microhttpd/mhd_send.c
+++ b/src/microhttpd/mhd_send.c
@@ -807,46 +807,62 @@ MHD_send_on_connection_ (struct MHD_Connection 
*connection,
 }
 
 
-/**
- * Send header followed by buffer on connection.
- * Uses writev if possible to send both at once
- * and returns the sum of the number of bytes sent from
- * both buffers, or -1 on error;
- * if writev is unavailable, this call MUST only send from 'header'
- * (as we cannot handle the case that the first write
- * succeeds and the 2nd fails!).
- *
- * @param connection the MHD_Connection structure
- * @param header content of header to send
- * @param header_size the size of the header (in bytes)
- * @param buffer content of the buffer to send
- * @param buffer_size the size of the buffer (in bytes)
- * @return sum of the number of bytes sent from both buffers or
- *         -1 on error
- */
 ssize_t
-MHD_send_on_connection2_ (struct MHD_Connection *connection,
-                          const char *header,
-                          size_t header_size,
-                          const char *buffer,
-                          size_t buffer_size)
+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,
+                        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];
+#ifdef HAVE_SENDMSG
+  struct msghdr msg;
+#endif /* HAVE_SENDMSG */
 #ifdef HTTPS_SUPPORT
   const bool no_vec = (connection->daemon->options & MHD_USE_TLS);
 #else  /* ! HTTPS_SUPPORT */
   const bool no_vec = false;
 #endif /* ! HTTPS_SUPPORT */
 #endif /* HAVE_SENDMSG || HAVE_WRITEV */
-  mhd_assert ( (NULL != buffer) || (0 == buffer_size) );
+  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) ||
-    (0 == buffer_size) ||
+    (0 == body_size) ||
     ((size_t) SSIZE_MAX <= header_size)
 #else  /* ! (HAVE_SENDMSG || HAVE_WRITEV) */
     true
@@ -856,23 +872,29 @@ MHD_send_on_connection2_ (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 != buffer_size) )
+         (0 != body_size) )
     {
       int ret2;
       /* The header has been sent completely.
        * Try to send the reply body without waiting for
        * the next round. */
       /* Make sure that sum of ret + ret2 will not exceed SSIZE_MAX. */
-      if ( (((size_t) SSIZE_MAX) - ((size_t) ret)) <  buffer_size)
-        buffer_size = (((size_t) SSIZE_MAX) - ((size_t) ret));
+      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,
-                                      buffer,
-                                      buffer_size,
-                                      MHD_SSO_PUSH_DATA);
+                                      body,
+                                      body_size,
+                                      push_body ?
+                                      MHD_SSO_PUSH_DATA: MHD_SSO_PREFER_BUFF);
       if (0 < ret2)
         return ret + ret2; /* Total data sent */
       if (MHD_ERR_AGAIN_ == ret2)
@@ -884,58 +906,54 @@ MHD_send_on_connection2_ (struct MHD_Connection 
*connection,
   }
 #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
 
-  if ( ((size_t) SSIZE_MAX <= buffer_size) ||
-       ((size_t) SSIZE_MAX < (header_size + buffer_size)) )
-    buffer_size = SSIZE_MAX - header_size;
+  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;
-  vector[1].iov_base = (void *) buffer;
-  vector[1].iov_len = buffer_size;
+  vector[1].iov_base = (void *) body;
+  vector[1].iov_len = body_size;
 
 #if HAVE_SENDMSG
-  {
-    struct msghdr msg;
-
-    memset (&msg, 0, sizeof(struct msghdr));
-    msg.msg_iov = vector;
-    msg.msg_iovlen = 2;
+  memset (&msg, 0, sizeof(struct msghdr));
+  msg.msg_iov = vector;
+  msg.msg_iovlen = 2;
 
-    ret = sendmsg (s, &msg, MSG_NOSIGNAL_OR_ZERO);
-    if ( (-1 == ret) &&
-         (EAGAIN == errno) )
-      return MHD_ERR_AGAIN_;
-  }
+  ret = sendmsg (s, &msg, MSG_NOSIGNAL_OR_ZERO);
+  if ( (-1 == ret) &&
+       (EAGAIN == errno) )
+    return MHD_ERR_AGAIN_;
 #elif HAVE_WRITEV
-  {
-    int iovcnt;
-
-    iovcnt = sizeof (vector) / sizeof (struct iovec);
-    ret = writev (s, vector, iovcnt);
-    if ( (-1 == ret) &&
-         (EAGAIN == errno) )
-      return MHD_ERR_AGAIN_;
-  }
+  ret = writev (s, vector, 2);
+  if ( (-1 == ret) &&
+       (EAGAIN == errno) )
+    return MHD_ERR_AGAIN_;
 #endif
 
   /* 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 + buffer_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,
@@ -943,6 +961,22 @@ MHD_send_on_connection2_ (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 046e7936..69a06769 100644
--- a/src/microhttpd/mhd_send.h
+++ b/src/microhttpd/mhd_send.h
@@ -86,12 +86,33 @@ MHD_send_on_connection_ (struct MHD_Connection *connection,
                          size_t buffer_size,
                          enum MHD_SendSocketOptions options);
 
+
+/**
+ * Send reply header with optional reply body.
+ *
+ * @param connection the MHD_Connection structure
+ * @param header content of header to send
+ * @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 @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)
+ */
 ssize_t
-MHD_send_on_connection2_ (struct MHD_Connection *connection,
-                          const char *header,
-                          size_t header_size,
-                          const char *buffer,
-                          size_t buffer_size);
+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,
+                        bool complete_response);
 
 #if defined(_MHD_HAVE_SENDFILE)
 ssize_t

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]