gnunet-svn
[Top][All Lists]
Advanced

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

[libmicrohttpd] branch master updated (1a46bfd6 -> f2565a62)


From: gnunet
Subject: [libmicrohttpd] branch master updated (1a46bfd6 -> f2565a62)
Date: Sun, 13 Mar 2022 18:33:23 +0100

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

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from 1a46bfd6 memorypool: fixed: unpoison memory for ASAN before destroying 
pool
     new b26d68a7 upgrade response: set response size to zero
     new b9743114 Added separate internal "responseIcy" flag.
     new e74fad60 Added warning in log if application-defined Content-Length is 
used
     new 2ebe7a85 Disallowed successful responses for CONNECT requests
     new 45b90c7c MHD_queue_response(): clarified log message
     new 3a6b50c8 MHD_queue_response(): refuse 101 code when not supported
     new 8105f71c Simplified function for determining needs for reply body and 
headers
     new f2565a62 MHD_set_response_options(): check whether the new flags could 
be used

The 8 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 | 197 +++++++++++++++++++++++++++++---------------
 src/microhttpd/internal.h   |   6 ++
 src/microhttpd/response.c   |   9 +-
 3 files changed, 143 insertions(+), 69 deletions(-)

diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index def03b68..af2036a0 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1,7 +1,7 @@
 /*
      This file is part of libmicrohttpd
      Copyright (C) 2007-2020 Daniel Pittman and Christian Grothoff
-     Copyright (C) 2015-2021 Evgeny Grin (Karlson2k)
+     Copyright (C) 2015-2022 Evgeny Grin (Karlson2k)
 
      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
@@ -1674,79 +1674,90 @@ connection_switch_from_recv_to_send (struct 
MHD_Connection *connection)
 
 
 /**
- * Check whether reply body-specific headers (namely Content-Length,
- * Transfer-Encoding) are needed.
+ * This enum type describes requirements for reply body and reply bode-specific
+ * headers (namely Content-Length, Transfer-Encoding).
+ */
+enum replyBodyUse
+{
+  /**
+   * No reply body allowed.
+   * Reply body headers 'Content-Length:' or 'Transfer-Encoding: chunked' are
+   * not allowed as well.
+   */
+  RP_BODY_NONE = 0,
+
+  /**
+   * Do not send reply body.
+   * Reply body headers 'Content-Length:' or 'Transfer-Encoding: chunked' are
+   * allowed, but optional.
+   */
+  RP_BODY_HEADERS_ONLY = 1,
+
+  /**
+   * Send reply body and
+   * reply body headers 'Content-Length:' or 'Transfer-Encoding: chunked'.
+   * Reply body headers are required.
+   */
+  RP_BODY_SEND = 2
+};
+
+
+/**
+ * Check whether reply body must be used.
  *
- * If reply body-specific headers are not needed then body itself
- * is not allowed as well.
- * When reply body-specific headers are needed, the body itself
- * can be present or not, depending on other conditions.
+ * If reply body is needed, it could be zero-sized.
  *
  * @param connection the connection to check
- * @return true if reply body-specific headers are needed,
- *         false otherwise.
- * @sa is_reply_body_needed()
+ * @param rcode the response code
+ * @return enum value indicating whether response body can be used and
+ *         whether response body length headers are allowed or required.
+ * @sa is_reply_body_header_needed()
  */
-static bool
-is_reply_body_headers_needed (struct MHD_Connection *connection)
+static enum replyBodyUse
+is_reply_body_needed (struct MHD_Connection *connection,
+                      unsigned int rcode)
 {
   struct MHD_Connection *const c = connection; /**< a short alias */
-  unsigned rcode;  /**< the response code */
 
-  mhd_assert (100 <= (c->responseCode & (~MHD_ICY_FLAG)) && \
-              999 >= (c->responseCode & (~MHD_ICY_FLAG)));
-
-  rcode = (unsigned) (c->responseCode & (~MHD_ICY_FLAG));
+  mhd_assert (100 <= rcode);
+  mhd_assert (999 >= rcode);
 
   if (199 >= rcode)
-    return false;
+    return RP_BODY_NONE;
 
   if (MHD_HTTP_NO_CONTENT == rcode)
-    return false;
+    return RP_BODY_NONE;
 
+#if 0
+  /* This check is not needed as upgrade handler is used only with code 101 */
 #ifdef UPGRADE_SUPPORT
-  if (NULL != c->response->upgrade_handler)
-    return false;
+  if (NULL != response->upgrade_handler)
+    return RP_BODY_NONE;
 #endif /* UPGRADE_SUPPORT */
+#endif
 
+#if 0
+  /* CONNECT is not supported by MHD */
+  /* Successful responses for connect requests are filtered by
+   * MHD_queue_response() */
   if ( (MHD_HTTP_MTHD_CONNECT == c->http_mthd) &&
        (2 == rcode / 100) )
     return false; /* Actually pass-through CONNECT is not supported by MHD */
+#endif
 
-  return true;
-}
-
-
-/**
- * Check whether reply body must be used.
- *
- * If reply body is needed, it could be zero-sized.
- *
- * @param connection the connection to check
- * @return true if reply body must be used,
- *         false otherwise
- * @sa is_reply_body_header_needed()
- */
-static bool
-is_reply_body_needed (struct MHD_Connection *connection)
-{
-  struct MHD_Connection *const c = connection; /**< a short alias */
-  unsigned rcode;  /**< the response code */
-
-  mhd_assert (100 <= (c->responseCode & (~MHD_ICY_FLAG)) && \
-              999 >= (c->responseCode & (~MHD_ICY_FLAG)));
-
-  if (! is_reply_body_headers_needed (c))
-    return false;
+  /* Reply body headers could be used.
+   * Check whether reply body itself must be used. */
 
   if (MHD_HTTP_MTHD_HEAD == c->http_mthd)
-    return false;
+    return RP_BODY_HEADERS_ONLY;
 
-  rcode = (unsigned) (c->responseCode & (~MHD_ICY_FLAG));
   if (MHD_HTTP_NOT_MODIFIED == rcode)
-    return false;
+    return RP_BODY_HEADERS_ONLY;
 
-  return true;
+  /* Reply body must be sent. The body may have zero length, but body size
+   * must be indicated by headers ('Content-Length:' or
+   * 'Transfer-Encoding: chunked'). */
+  return RP_BODY_SEND;
 }
 
 
@@ -1763,6 +1774,7 @@ setup_reply_properties (struct MHD_Connection *connection)
 {
   struct MHD_Connection *const c = connection; /**< a short alias */
   struct MHD_Response *const r = c->response;  /**< a short alias */
+  enum replyBodyUse use_rp_body;
   bool use_chunked;
 
   mhd_assert (NULL != r);
@@ -1770,11 +1782,13 @@ setup_reply_properties (struct MHD_Connection 
*connection)
   /* ** Adjust reply properties ** */
 
   c->keepalive = keepalive_possible (c);
-  c->rp_props.use_reply_body_headers = is_reply_body_headers_needed (c);
-  if (c->rp_props.use_reply_body_headers)
-    c->rp_props.send_reply_body = is_reply_body_needed (c);
-  else
-    c->rp_props.send_reply_body = false;
+  use_rp_body = is_reply_body_needed (c, c->responseCode);
+  c->rp_props.send_reply_body = (use_rp_body > RP_BODY_HEADERS_ONLY);
+  c->rp_props.use_reply_body_headers = (use_rp_body >= RP_BODY_HEADERS_ONLY);
+
+#ifdef UPGRADE_SUPPORT
+  mhd_assert ((NULL == r->upgrade_handler) || (RP_BODY_NONE == use_rp_body));
+#endif /* UPGRADE_SUPPORT */
 
   if (c->rp_props.use_reply_body_headers)
   {
@@ -1831,7 +1845,7 @@ check_connection_reply (struct MHD_Connection *connection)
     MHD_DLOG (c->daemon,
               _ ("This reply with response code %u cannot use reply body. "
                  "Non-empty response body is ignored and not used.\n"),
-              (unsigned) (c->responseCode & (~MHD_ICY_FLAG)));
+              (unsigned) (c->responseCode));
   }
   if ( (! c->rp_props.use_reply_body_headers) &&
        (0 != (r->flags_auto & MHD_RAF_HAS_CONTENT_LENGTH)) )
@@ -1840,7 +1854,7 @@ check_connection_reply (struct MHD_Connection *connection)
               _ ("This reply with response code %u cannot use reply body. "
                  "Application defined \"Content-Length\" header violates"
                  "HTTP specification.\n"),
-              (unsigned) (c->responseCode & (~MHD_ICY_FLAG)));
+              (unsigned) (c->responseCode));
   }
 #else
   (void) c; /* Mute compiler warning */
@@ -2049,7 +2063,7 @@ build_header_response (struct MHD_Connection *connection)
 
   check_connection_reply (c);
 
-  rcode = (unsigned) (c->responseCode & (~MHD_ICY_FLAG));
+  rcode = (unsigned) c->responseCode;
   if (MHD_CONN_MUST_CLOSE == c->keepalive)
   {
     /* The closure of connection must be always indicated by header
@@ -2091,7 +2105,7 @@ build_header_response (struct MHD_Connection *connection)
   /* * The status line * */
 
   /* The HTTP version */
-  if (0 == (c->responseCode & MHD_ICY_FLAG))
+  if (! c->responseIcy)
   { /* HTTP reply */
     if (0 == (r->flags & MHD_RF_HTTP_1_0_SERVER))
     { /* HTTP/1.1 reply */
@@ -3968,8 +3982,6 @@ MHD_connection_handle_write (struct MHD_Connection 
*connection)
                    (NULL != resp->crc) );
       mhd_assert ( (0 == connection->response_write_position) || \
                    (resp->total_size ==
-                    connection->response_write_position) || \
-                   (MHD_SIZE_UNKNOWN ==
                     connection->response_write_position) );
       mhd_assert ((MHD_CONN_MUST_UPGRADE != connection->keepalive) || \
                   (! connection->rp_props.send_reply_body));
@@ -4414,6 +4426,7 @@ connection_reset (struct MHD_Connection *connection,
     c->current_chunk_size = 0;
     c->current_chunk_offset = 0;
     c->responseCode = 0;
+    c->responseIcy = false;
     c->response_write_position = 0;
     c->method = NULL;
     c->http_mthd = MHD_HTTP_MTHD_NO_METHOD;
@@ -5142,7 +5155,10 @@ MHD_queue_response (struct MHD_Connection *connection,
                     struct MHD_Response *response)
 {
   struct MHD_Daemon *daemon;
+  bool reply_icy;
 
+  reply_icy = (0 != (status_code & MHD_ICY_FLAG));
+  status_code &= ~MHD_ICY_FLAG;
   if ((NULL == connection) || (NULL == response))
     return MHD_NO;
 
@@ -5220,25 +5236,46 @@ MHD_queue_response (struct MHD_Connection *connection,
     {
 #ifdef HAVE_MESSAGES
       MHD_DLOG (daemon,
-                _ ("Connection \"Upgrade\" can be used " \
+                _ ("Connection \"Upgrade\" can be used only " \
                    "with HTTP/1.1 connections!\n"));
 #endif
       return MHD_NO;
     }
   }
 #endif /* UPGRADE_SUPPORT */
-  if ( (100 > (status_code & (~MHD_ICY_FLAG))) ||
-       (999 < (status_code & (~MHD_ICY_FLAG))) )
+  if (MHD_HTTP_SWITCHING_PROTOCOLS == status_code)
+  {
+#ifdef UPGRADE_SUPPORT
+    if (NULL == response->upgrade_handler)
+    {
+#ifdef HAVE_MESSAGES
+      MHD_DLOG (daemon,
+                _ ("Application used status code 101 \"Switching Protocols\" " 
\
+                   "with non-'upgrade' response!\n"));
+#endif /* HAVE_MESSAGES */
+      return MHD_NO;
+    }
+#else  /* ! UPGRADE_SUPPORT */
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (daemon,
+              _ ("Application used status code 101 \"Switching Protocols\", " \
+                 "but this MHD was built without \"Upgrade\" support!\n"));
+#endif /* HAVE_MESSAGES */
+    return MHD_NO;
+#endif /* ! UPGRADE_SUPPORT */
+  }
+  if ( (100 > status_code) ||
+       (999 < status_code) )
   {
 #ifdef HAVE_MESSAGES
     MHD_DLOG (daemon,
               _ ("Refused wrong status code (%u). " \
                  "HTTP requires three digits status code!\n"),
-              (status_code & (~MHD_ICY_FLAG)));
+              status_code);
 #endif
     return MHD_NO;
   }
-  if (200 > (status_code & (~MHD_ICY_FLAG)))
+  if (200 > status_code)
   {
     if (MHD_HTTP_VER_1_0 == connection->http_ver)
     {
@@ -5246,7 +5283,7 @@ MHD_queue_response (struct MHD_Connection *connection,
       MHD_DLOG (daemon,
                 _ ("Wrong status code (%u) refused. " \
                    "HTTP/1.0 clients do not support 1xx status codes!\n"),
-                (status_code & (~MHD_ICY_FLAG)));
+                (status_code));
 #endif
       return MHD_NO;
     }
@@ -5257,15 +5294,39 @@ MHD_queue_response (struct MHD_Connection *connection,
       MHD_DLOG (daemon,
                 _ ("Wrong status code (%u) refused. " \
                    "HTTP/1.0 reply mode does not support 1xx status codes!\n"),
-                (status_code & (~MHD_ICY_FLAG)));
+                (status_code));
 #endif
       return MHD_NO;
     }
   }
+  if ( (MHD_HTTP_MTHD_CONNECT == connection->http_mthd) &&
+       (2 == status_code / 100) )
+  {
+#ifdef HAVE_MESSAGES
+    MHD_DLOG (daemon,
+              _ ("Successful (%u) response code cannot be used to answer " \
+                 "\"CONNECT\" request!\n"),
+              (status_code));
+#endif
+    return MHD_NO;
+  }
+
+#ifdef HAVE_MESSAGES
+  if ( (0 != (MHD_RF_INSANITY_HEADER_CONTENT_LENGTH & response->flags)) &&
+       (0 != (MHD_RAF_HAS_CONTENT_LENGTH & response->flags_auto)) )
+  {
+    MHD_DLOG (daemon,
+              _ ("The response has application-defined \"Content-Length\" " \
+                 "header. The reply to the request will be not " \
+                 "HTTP-compliant and may result in hung connection or " \
+                 "other problems!\n"));
+  }
+#endif
 
   MHD_increment_response_rc (response);
   connection->response = response;
   connection->responseCode = status_code;
+  connection->responseIcy = reply_icy;
 #if defined(_MHD_HAVE_SENDFILE)
   if ( (response->fd == -1) ||
        (response->is_pipe) ||
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 2cfe6455..20a406e3 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -1233,6 +1233,12 @@ struct MHD_Connection
    */
   unsigned int responseCode;
 
+  /**
+   * The "ICY" response.
+   * Reply begins with the SHOUTcast "ICY" line instead of "HTTP".
+   */
+  bool responseIcy;
+
   /**
    * Reply-specific properties
    */
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 3fd98088..fbee6308 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -895,8 +895,15 @@ MHD_set_response_options (struct MHD_Response *response,
   enum MHD_Result ret;
   enum MHD_ResponseOptions ro;
 
+  if ( (0 != (response->flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH)) &&
+       (0 == (flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH)))
+  { /* Request to remove MHD_RF_INSANITY_HEADER_CONTENT_LENGTH flag */
+    if (0 != (response->flags_auto & MHD_RAF_HAS_CONTENT_LENGTH))
+      return MHD_NO;
+  }
   ret = MHD_YES;
   response->flags = flags;
+
   va_start (ap, flags);
   while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
   {
@@ -1942,7 +1949,7 @@ MHD_create_response_for_upgrade (MHD_UpgradeHandler 
upgrade_handler,
 #endif
   response->upgrade_handler = upgrade_handler;
   response->upgrade_handler_cls = upgrade_handler_cls;
-  response->total_size = MHD_SIZE_UNKNOWN;
+  response->total_size = 0;
   response->reference_count = 1;
   if (MHD_NO ==
       MHD_add_response_header (response,

-- 
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]