浏览代码

fix generator to special-case response options

Christian Grothoff 1 年之前
父节点
当前提交
59b558d928

+ 4 - 4
src/include/Makefile.am

@@ -5,10 +5,10 @@ microhttpd2_inline_daemon_documentation.h.in microhttpd2_generated_daemon_option
 	rm -f microhttpd2_inline_daemon_documentation.h.in microhttpd2_generated_daemon_options.h
 	./options-generator daemon > microhttpd2_generated_daemon_options.h
 	chmod -w $@
-#microhttpd2_inline_response_documentation.h.in microhttpd2_generated_response_options.h: r_options.rec options-generator
-#	rm -f microhttpd2_inline_response_documentation.h.in microhttpd2_generated_response_options.h
-#	./options-generator response > microhttpd2_generated_response_options.h
-#	chmod -w $@
+microhttpd2_inline_response_documentation.h.in microhttpd2_generated_response_options.h: r_options.rec options-generator
+	rm -f microhttpd2_inline_response_documentation.h.in microhttpd2_generated_response_options.h
+	./options-generator response > microhttpd2_generated_response_options.h
+	chmod -w $@
 
 microhttpd2.h: microhttpd2_preamble.h.in microhttpd2_inline_daemon_documentation.h.in microhttpd2_inline_response_documentation.h.in microhttpd2_main.h.in microhttpd2_postamble.h.in
 	rm -f $@

+ 27 - 31
src/include/d_options.rec

@@ -75,20 +75,18 @@ Description2: the address to bind to; can be IPv4 (AF_INET), IPv6 (AF_INET6) or
 Argument3: enum MHD_Bool dual
 Description3: When a previous version of the protocol exist (like IPv4 when @a v_sa is IPv6) bind to both protocols (IPv6 and IPv4).
 CustomSetter: /* custom setter */
-+  if (0 != option->val.bind_sa.v_sa_len)
-+  {
-+    if (NULL != settings->bind_sa.v_sa)
-+      free (settings->bind_sa.v_sa);
-+
-+    settings->bind_sa.v_sa = malloc (option->val.bind_sa.v_sa_len);
-+    if (NULL == settings->bind_sa.v_sa)
-+      return MHD_SC_DAEMON_MALLOC_FAILURE;
-+
-+    memcpy (settings->bind_sa.v_sa, option->val.bind_sa.v_sa,
-+            option->val.bind_sa.v_sa_len);
-+    settings->bind_sa.v_sa_len = option->val.bind_sa.v_sa_len;
-+    settings->bind_sa.v_dual = option->val.bind_sa.v_dual;
-+  }
++ if (0 != option->val.bind_sa.v_sa_len)
++ {
++   if (NULL != settings->bind_sa.v_sa)
++     free (settings->bind_sa.v_sa);
++   settings->bind_sa.v_sa = malloc (option->val.bind_sa.v_sa_len);
++   if (NULL == settings->bind_sa.v_sa)
++     return MHD_SC_DAEMON_MALLOC_FAILURE;
++   memcpy (settings->bind_sa.v_sa, option->val.bind_sa.v_sa,
++           option->val.bind_sa.v_sa_len);
++   settings->bind_sa.v_sa_len = option->val.bind_sa.v_sa_len;
++   settings->bind_sa.v_dual = option->val.bind_sa.v_dual;
++ }
 
 Name: listen_socket
 Value: 82
@@ -384,23 +382,21 @@ Argument2: /* const */ void *buf
 Description2: the buffer with strong random data, the content will be copied by MHD
 Type: struct MHD_DaemonOptionEntropySeed
 CustomSetter: /* custom setter */
-+  /* The is not an easy for automatic generations */
-+  if (0 != option->val.random_entropy.v_buf_size)
-+  {
-+    if (NULL != settings->random_entropy.v_buf)
-+      free (settings->random_entropy.v_buf);
-+
-+    settings->random_entropy.v_buf =
-+      malloc (option->val.random_entropy.v_buf_size);
-+    if (NULL == settings->random_entropy.v_buf)
-+      return MHD_SC_DAEMON_MALLOC_FAILURE;
-+
-+    memcpy (settings->random_entropy.v_buf,
-+            option->val.random_entropy.v_buf,
-+            option->val.random_entropy.v_buf_size);
-+    settings->random_entropy.v_buf_size =
-+      option->val.random_entropy.v_buf_size;
-+  }
++ /* The is not an easy for automatic generations */
++ if (0 != option->val.random_entropy.v_buf_size)
++ {
++   if (NULL != settings->random_entropy.v_buf)
++     free (settings->random_entropy.v_buf);
++   settings->random_entropy.v_buf =
++     malloc (option->val.random_entropy.v_buf_size);
++   if (NULL == settings->random_entropy.v_buf)
++     return MHD_SC_DAEMON_MALLOC_FAILURE;
++   memcpy (settings->random_entropy.v_buf,
++           option->val.random_entropy.v_buf,
++           option->val.random_entropy.v_buf_size);
++   settings->random_entropy.v_buf_size =
++     option->val.random_entropy.v_buf_size;
++ }
 
 
 Name: dauth_map_size

+ 1 - 1
src/include/microhttpd2.h

@@ -4171,7 +4171,7 @@ MHD_D_OPTION_DAUTH_DEF_MAX_NC (
 #if 0
 
 /**
- * Make the response object re-usable.
+ * Make the response object re-usable. (FIXME: not used in struct ResponseOptions; remove!?)
  * The response will not be consumed by MHD_action_from_response() and must be destroyed by MHD_response_destroy().
  * Useful if the same response is often used to reply.
  * @param val the value of the parameter * @return structure with the requested setting

+ 11 - 11
src/include/microhttpd2_generated_response_options.h

@@ -11,7 +11,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_ResponseOption
   ,
 
   /**
-   * Make the response object re-usable.
+   * Make the response object re-usable. (FIXME: not used in struct ResponseOptions; remove!?)
    * The response will not be consumed by MHD_action_from_response() and must be destroyed by MHD_response_destroy().
    * Useful if the same response is often used to reply.
    */
@@ -178,7 +178,7 @@ struct MHD_ResponseOptionAndValue
 
 #if defined(MHD_USE_COMPOUND_LITERALS) && defined(MHD_USE_DESIG_NEST_INIT)
 /**
- * Make the response object re-usable.
+ * Make the response object re-usable. (FIXME: not used in struct ResponseOptions; remove!?)
  * The response will not be consumed by MHD_action_from_response() and must be destroyed by MHD_response_destroy().
  * Useful if the same response is often used to reply.
  * @param val the value of the parameter * @return structure with the requested setting
@@ -321,12 +321,12 @@ With this option HTTP/1.0 server is emulated (with support for 'keep-alive' conn
 #else /* !MHD_USE_COMPOUND_LITERALS || !MHD_USE_DESIG_NEST_INIT */
 MHD_NOWARN_UNUSED_FUNC_
 /**
- * Make the response object re-usable.
+ * Make the response object re-usable. (FIXME: not used in struct ResponseOptions; remove!?)
  * The response will not be consumed by MHD_action_from_response() and must be destroyed by MHD_response_destroy().
  * Useful if the same response is often used to reply.
  * @param val the value of the parameter * @return structure with the requested setting
  */
-static MHD_INLINE struct MHD_responseOptionAndValue
+static MHD_INLINE struct MHD_ResponseOptionAndValue
 MHD_R_OPTION_REUSABLE (
   enum MHD_Bool val
   )
@@ -348,7 +348,7 @@ MHD_R_OPTION_REUSABLE (
  * This flag is primarily intended to be used when automatic 'Content-Length' header is undesirable in response to HEAD requests.
  * @param val the value of the parameter * @return structure with the requested setting
  */
-static MHD_INLINE struct MHD_responseOptionAndValue
+static MHD_INLINE struct MHD_ResponseOptionAndValue
 MHD_R_OPTION_HEAD_ONLY_RESPONSE (
   enum MHD_Bool val
   )
@@ -367,7 +367,7 @@ MHD_R_OPTION_HEAD_ONLY_RESPONSE (
  * Ignored when the reply cannot have body/content.
  * @param val the value of the parameter * @return structure with the requested setting
  */
-static MHD_INLINE struct MHD_responseOptionAndValue
+static MHD_INLINE struct MHD_ResponseOptionAndValue
 MHD_R_OPTION_CHUNKED_ENC (
   enum MHD_Bool val
   )
@@ -385,7 +385,7 @@ MHD_R_OPTION_CHUNKED_ENC (
  * Force close connection after sending the response, prevents keep-alive connections and adds 'Connection: close' header.
  * @param val the value of the parameter * @return structure with the requested setting
  */
-static MHD_INLINE struct MHD_responseOptionAndValue
+static MHD_INLINE struct MHD_ResponseOptionAndValue
 MHD_R_OPTION_CONN_CLOSE (
   enum MHD_Bool val
   )
@@ -412,7 +412,7 @@ MHD_R_OPTION_CONN_CLOSE (
 This option can be used to communicate with some broken client, which does not implement HTTP/1.1 features, but advertises HTTP/1.1 support.
  * @param val the value of the parameter * @return structure with the requested setting
  */
-static MHD_INLINE struct MHD_responseOptionAndValue
+static MHD_INLINE struct MHD_ResponseOptionAndValue
 MHD_R_OPTION_HTTP_1_0_COMPATIBLE_STRICT (
   enum MHD_Bool val
   )
@@ -441,7 +441,7 @@ MHD_R_OPTION_HTTP_1_0_COMPATIBLE_STRICT (
 With this option HTTP/1.0 server is emulated (with support for 'keep-alive' connections).
  * @param val the value of the parameter * @return structure with the requested setting
  */
-static MHD_INLINE struct MHD_responseOptionAndValue
+static MHD_INLINE struct MHD_ResponseOptionAndValue
 MHD_R_OPTION_HTTP_1_0_SERVER (
   enum MHD_Bool val
   )
@@ -460,7 +460,7 @@ MHD_R_OPTION_HTTP_1_0_SERVER (
  * Allow to set several 'Content-Length' headers. These headers will be used even with replies without body.
  * @param val the value of the parameter * @return structure with the requested setting
  */
-static MHD_INLINE struct MHD_responseOptionAndValue
+static MHD_INLINE struct MHD_ResponseOptionAndValue
 MHD_R_OPTION_INSANITY_HEADER_CONTENT_LENGTH (
   enum MHD_Bool val
   )
@@ -481,7 +481,7 @@ MHD_R_OPTION_INSANITY_HEADER_CONTENT_LENGTH (
  * @param term_cb_cls the closure for the callback
  * @return structure with the requested setting
  */
-static MHD_INLINE struct MHD_responseOptionAndValue
+static MHD_INLINE struct MHD_ResponseOptionAndValue
 MHD_R_OPTION_TERMINATION_CALLBACK (
   MHD_RequestTerminationCallback term_cb,
   void *term_cb_cls

+ 52 - 17
src/include/options-generator.c

@@ -1019,13 +1019,23 @@ TOP:
              " * @author %s-options-generator.c\n"
              " */\n"
              "\n"
-             "#include \"mhd_sys_options.h\"\n"
+             "#include \"sys_bool_type.h\"\n"
              "#include \"sys_base_types.h\"\n"
              "#include \"sys_malloc.h\"\n"
              "#include <string.h>\n"
              "#include \"mhd_%s.h\"\n"
              "#include \"%s_options.h\"\n"
-             "#include \"mhd_public_api.h\"\n"
+             "#include \"mhd_public_api.h\"\n",
+             category,
+             category,
+             category,
+             category);
+    if (0 == strcmp (category, "response"))
+      fprintf (f,
+               "#include \"mhd_locks.h\"\n"
+               "#include \"mhd_assert.h\"\n"
+               "#include \"response_funcs.h\"\n");
+    fprintf (f,
              "\n"
              "MHD_FN_PAR_NONNULL_ALL_ MHD_EXTERN_\n"
              "enum MHD_StatusCode\n"
@@ -1035,29 +1045,43 @@ TOP:
              "  size_t options_max_num)\n"
              "{\n",
              category,
-             category,
-             category,
-             category,
-             category,
              capitalize (category),
              category,
              capitalize (category));
     fprintf (f,
-             "  struct %sOptions *const settings = %s->settings;\n"
-             "  size_t i;\n"
-             "\n",
+             "  struct %sOptions *restrict settings = %s->settings;\n"
+             "  enum MHD_StatusCode res = MHD_SC_OK;\n"
+             "  size_t i;\n",
              capitalize (category),
              category);
     if (0 == strcmp (category, "daemon"))
     {
       fprintf (f,
+               "\n"
                "  if (mhd_DAEMON_STATE_NOT_STARTED != daemon->state)\n"
                "    return MHD_SC_TOO_LATE;\n"
                "\n");
     }
+    else if (0 == strcmp (category, "response"))
+    {
+      fprintf (f,
+               "  bool need_unlock = false;\n"
+               "\n"
+               "  if (response->frozen)\n"
+               "    return MHD_SC_TOO_LATE;\n"
+               "  if (response->reuse.reusable)\n"
+               "  {\n"
+               "    need_unlock = true;\n"
+               "    if (! mhd_mutex_lock(&response->reuse.settings_lock))\n"
+               "      return MHD_SC_RESPONSE_MUTEX_LOCK_FAILED;\n"
+               "    mhd_assert (1 == mhd_atomic_counter_get(&response->reuse.counter));\n"
+               "  }\n"
+               "\n");
+    }
     else
     {
       fprintf (f,
+               "\n"
                "  if (NULL == settings)\n"
                "    return MHD_SC_TOO_LATE;\n"
                "\n");
@@ -1065,29 +1089,39 @@ TOP:
     fprintf (f,
              "  for (i = 0; i < options_max_num; i++)\n"
              "  {\n"
-             "    const struct MHD_%sOptionAndValue *const option = options + i;\n"
+             "    const struct MHD_%sOptionAndValue *const option\n"
+             "      = options + i;\n"
              "    switch (option->opt)\n"
              "    {\n",
              capitalize (category));
     fprintf (f,
              "    case MHD_%c_O_END:\n"
-             "      return MHD_SC_OK;\n",
+             "      i = options_max_num - 1;\n"
+             "      break;\n",
              (char) toupper (*category));
     iterate (head,
              &dump_option_set_switch);
     fprintf (f,
              "    case MHD_%c_O_SENTINEL:\n"
              "    default: /* for -Wswitch-default -Wswitch-enum */ \n"
+             "      res = MHD_SC_OPTION_UNKNOWN;\n"
+             "      i = options_max_num - 1;\n"
              "      break;\n",
              (char) toupper (*category));
     fprintf (f,
              "    }\n"
-             "    return MHD_SC_OPTION_UNKNOWN;\n"
-             "  }\n"
-             "  return MHD_SC_OK;\n");
+             "  }\n");
+    if (0 == strcmp (category, "response"))
+    {
+      fprintf (f,
+               "\n"
+               "  if (need_unlock)\n"
+               "    mhd_mutex_lock_chk(&response->reuse.settings_lock);\n"
+               "\n");
+    }
     fprintf (f,
+             "  return res;\n"
              "}\n");
-
     fclose (f);
     chmod (so_c, S_IRUSR | S_IRGRP | S_IROTH);
     free (so_c);
@@ -1122,7 +1156,8 @@ TOP:
              "#include \"mhd_sys_options.h\"\n"
              "#include \"mhd_public_api.h\"\n"
              "\n"
-             "struct %sOptions {\n",
+             "struct %sOptions\n"
+             "{\n",
              category,
              category,
              uppercase (category),
@@ -1133,7 +1168,7 @@ TOP:
     fprintf (f,
              "};\n"
              "\n"
-             "#endif /* ! MHD_%s_OPTIONS_H */\n",
+             "#endif /* ! MHD_%s_OPTIONS_H 1 */\n",
              uppercase (category));
     fclose (f);
     chmod (do_h, S_IRUSR | S_IRGRP | S_IROTH);

+ 1 - 1
src/include/r_options.rec

@@ -20,7 +20,7 @@
 Name: REUSABLE
 Value: 20
 Type: enum MHD_Bool
-Comment: Make the response object re-usable.
+Comment: Make the response object re-usable. (FIXME: not used in struct ResponseOptions; remove!?)
 + The response will not be consumed by MHD_action_from_response() and must be destroyed by MHD_response_destroy().
 + Useful if the same response is often used to reply.
 

+ 3 - 2
src/mhd2/daemon_options.h

@@ -12,7 +12,8 @@
 #include "mhd_sys_options.h"
 #include "mhd_public_api.h"
 
-struct DaemonOptions {
+struct DaemonOptions
+{
   /**
    * Value for #MHD_D_O_WORK_MODE.
    * the object created by one of the next functions/macros: #MHD_WM_OPTION_EXTERNAL_PERIODIC(), #MHD_WM_OPTION_EXTERNAL_EVENT_LOOP_CB_LEVEL(), #MHD_WM_OPTION_EXTERNAL_EVENT_LOOP_CB_EDGE(), #MHD_WM_OPTION_EXTERNAL_SINGLE_FD_WATCH(), #MHD_WM_OPTION_WORKER_THREADS(), #MHD_WM_OPTION_THREAD_PER_CONNECTION()
@@ -286,4 +287,4 @@ struct DaemonOptions {
 
 };
 
-#endif /* ! MHD_DAEMON_OPTIONS_H */
+#endif /* ! MHD_DAEMON_OPTIONS_H 1 */

+ 37 - 37
src/mhd2/daemon_set_options.c

@@ -6,7 +6,7 @@
  * @author daemon-options-generator.c
  */
 
-#include "mhd_sys_options.h"
+#include "sys_bool_type.h"
 #include "sys_base_types.h"
 #include "sys_malloc.h"
 #include <string.h>
@@ -21,7 +21,8 @@ MHD_daemon_set_options (
   const struct MHD_DaemonOptionAndValue *options,
   size_t options_max_num)
 {
-  struct DaemonOptions *const settings = daemon->settings;
+  struct DaemonOptions *restrict settings = daemon->settings;
+  enum MHD_StatusCode res = MHD_SC_OK;
   size_t i;
 
   if (mhd_DAEMON_STATE_NOT_STARTED != daemon->state)
@@ -29,11 +30,13 @@ MHD_daemon_set_options (
 
   for (i = 0; i < options_max_num; i++)
   {
-    const struct MHD_DaemonOptionAndValue *const option = options + i;
+    const struct MHD_DaemonOptionAndValue *const option
+      = options + i;
     switch (option->opt)
     {
     case MHD_D_O_END:
-      return MHD_SC_OK;
+      i = options_max_num - 1;
+      break;
     case MHD_D_O_WORK_MODE:
       settings->work_mode = option->val.work_mode;
       continue;
@@ -50,20 +53,18 @@ MHD_daemon_set_options (
       continue;
     case MHD_D_O_BIND_SA:
       /* custom setter */
-       if (0 != option->val.bind_sa.v_sa_len)
-       {
-         if (NULL != settings->bind_sa.v_sa)
-           free (settings->bind_sa.v_sa);
-
-   settings->bind_sa.v_sa = malloc (option->val.bind_sa.v_sa_len);
-         if (NULL == settings->bind_sa.v_sa)
-           return MHD_SC_DAEMON_MALLOC_FAILURE;
-
-   memcpy (settings->bind_sa.v_sa, option->val.bind_sa.v_sa,
-                 option->val.bind_sa.v_sa_len);
-         settings->bind_sa.v_sa_len = option->val.bind_sa.v_sa_len;
-         settings->bind_sa.v_dual = option->val.bind_sa.v_dual;
-       }
+      if (0 != option->val.bind_sa.v_sa_len)
+      {
+        if (NULL != settings->bind_sa.v_sa)
+          free (settings->bind_sa.v_sa);
+        settings->bind_sa.v_sa = malloc (option->val.bind_sa.v_sa_len);
+        if (NULL == settings->bind_sa.v_sa)
+          return MHD_SC_DAEMON_MALLOC_FAILURE;
+        memcpy (settings->bind_sa.v_sa, option->val.bind_sa.v_sa,
+                option->val.bind_sa.v_sa_len);
+        settings->bind_sa.v_sa_len = option->val.bind_sa.v_sa_len;
+        settings->bind_sa.v_dual = option->val.bind_sa.v_dual;
+      }
       continue;
     case MHD_D_O_LISTEN_SOCKET:
       settings->listen_socket = option->val.listen_socket;
@@ -167,23 +168,21 @@ MHD_daemon_set_options (
       continue;
     case MHD_D_O_RANDOM_ENTROPY:
       /* custom setter */
-       /* The is not an easy for automatic generations */
-       if (0 != option->val.random_entropy.v_buf_size)
-       {
-         if (NULL != settings->random_entropy.v_buf)
-           free (settings->random_entropy.v_buf);
-
-   settings->random_entropy.v_buf =
-           malloc (option->val.random_entropy.v_buf_size);
-         if (NULL == settings->random_entropy.v_buf)
-           return MHD_SC_DAEMON_MALLOC_FAILURE;
-
-   memcpy (settings->random_entropy.v_buf,
-                 option->val.random_entropy.v_buf,
-                 option->val.random_entropy.v_buf_size);
-         settings->random_entropy.v_buf_size =
-           option->val.random_entropy.v_buf_size;
-       }
+      /* The is not an easy for automatic generations */
+      if (0 != option->val.random_entropy.v_buf_size)
+      {
+        if (NULL != settings->random_entropy.v_buf)
+          free (settings->random_entropy.v_buf);
+        settings->random_entropy.v_buf =
+          malloc (option->val.random_entropy.v_buf_size);
+        if (NULL == settings->random_entropy.v_buf)
+          return MHD_SC_DAEMON_MALLOC_FAILURE;
+        memcpy (settings->random_entropy.v_buf,
+                option->val.random_entropy.v_buf,
+                option->val.random_entropy.v_buf_size);
+        settings->random_entropy.v_buf_size =
+          option->val.random_entropy.v_buf_size;
+      }
       continue;
     case MHD_D_O_DAUTH_MAP_SIZE:
       settings->dauth_map_size = option->val.dauth_map_size;
@@ -199,9 +198,10 @@ MHD_daemon_set_options (
       continue;
     case MHD_D_O_SENTINEL:
     default: /* for -Wswitch-default -Wswitch-enum */ 
+      res = MHD_SC_OPTION_UNKNOWN;
+      i = options_max_num - 1;
       break;
     }
-    return MHD_SC_OPTION_UNKNOWN;
   }
-  return MHD_SC_OK;
+  return res;
 }

+ 1 - 5
src/mhd2/response_options.h

@@ -6,22 +6,18 @@
  * @author response-options-generator.c
  */
 
-/* EDITED MANUALLY */
-
 #ifndef MHD_RESPONSE_OPTIONS_H
 #define MHD_RESPONSE_OPTIONS_H 1
 
 #include "mhd_sys_options.h"
-
 #include "mhd_public_api.h"
 
-
 struct ResponseOptions
 {
   /**
    * Value for #MHD_R_O_REUSABLE.
    */
-  enum MHD_Bool reusable; /* Not used in this struct. FIXME: remove? */
+  enum MHD_Bool reusable;
 
 
   /**

+ 29 - 61
src/mhd2/response_set_options.c

@@ -6,59 +6,50 @@
  * @author response-options-generator.c
  */
 
-/* EDITED MANUALLY */
-
-
-#include "mhd_sys_options.h"
-#include "response_set_options.h"
-#include "sys_base_types.h"
 #include "sys_bool_type.h"
-#include "response_options.h"
+#include "sys_base_types.h"
+#include "sys_malloc.h"
+#include <string.h>
 #include "mhd_response.h"
+#include "response_options.h"
 #include "mhd_public_api.h"
 #include "mhd_locks.h"
 #include "mhd_assert.h"
 #include "response_funcs.h"
 
-/**
- * Internal version of the #MHD_response_set_options()
- * Assuming that settings lock is held by the MHD_response_set_options()
- * @param response the response to change
- * @param options the options to use
- * @param options_max_num the maximum number of @a options to use
- * @return #MHD_SC_OK on success, error code otherwise
- */
-static MHD_FN_PAR_NONNULL_ALL_ enum MHD_StatusCode
-response_set_options_int (
-  struct MHD_Response *restrict response,
-  const struct MHD_ResponseOptionAndValue *restrict options,
+MHD_FN_PAR_NONNULL_ALL_ MHD_EXTERN_
+enum MHD_StatusCode
+MHD_response_set_options (
+  struct MHD_Response *response,
+  const struct MHD_ResponseOptionAndValue *options,
   size_t options_max_num)
 {
-  struct ResponseOptions *restrict settings;
+  struct ResponseOptions *restrict settings = response->settings;
+  enum MHD_StatusCode res = MHD_SC_OK;
   size_t i;
+  bool need_unlock = false;
 
   if (response->frozen)
-    return MHD_SC_TOO_LATE; /* Re-check under the lock (if any) */
-
-  settings = response->settings;
+    return MHD_SC_TOO_LATE;
+  if (response->reuse.reusable)
+  {
+    need_unlock = true;
+    if (! mhd_mutex_lock(&response->reuse.settings_lock))
+      return MHD_SC_RESPONSE_MUTEX_LOCK_FAILED;
+    mhd_assert (1 == mhd_atomic_counter_get(&response->reuse.counter));
+  }
 
   for (i = 0; i < options_max_num; i++)
   {
-    const struct MHD_ResponseOptionAndValue *const volatile option =
-      options + i;
-
+    const struct MHD_ResponseOptionAndValue *const option
+      = options + i;
     switch (option->opt)
     {
     case MHD_R_O_END:
-      return MHD_SC_OK;
+      i = options_max_num - 1;
+      break;
     case MHD_R_O_REUSABLE:
-      if (response->reuse.reusable && !option->val.reusable)
-        return MHD_SC_RESPONSE_CANNOT_CLEAR_REUSE;
-      else if (response->reuse.reusable)
-        continue; /* This flag has been set before */
-      else
-        if (! response_make_reusable(response))
-          return MHD_SC_RESPONSE_MUTEX_INIT_FAILED;
+      settings->reusable = option->val.reusable;
       continue;
     case MHD_R_O_HEAD_ONLY_RESPONSE:
       settings->head_only_response = option->val.head_only_response;
@@ -83,38 +74,15 @@ response_set_options_int (
       settings->termination_callback.v_term_cb_cls = option->val.termination_callback.v_term_cb_cls;
       continue;
     case MHD_R_O_SENTINEL:
-    default:
+    default: /* for -Wswitch-default -Wswitch-enum */ 
+      res = MHD_SC_OPTION_UNKNOWN;
+      i = options_max_num - 1;
       break;
     }
-    return MHD_SC_OPTION_UNKNOWN;
   }
-  return MHD_SC_OK;
-}
-
-MHD_FN_PAR_NONNULL_ALL_ MHD_EXTERN_ enum MHD_StatusCode
-MHD_response_set_options (struct MHD_Response *response,
-                          const struct MHD_ResponseOptionAndValue *options,
-                          size_t options_max_num)
-{
-  bool need_unlock;
-  enum MHD_StatusCode res;
-
-  if (response->frozen)
-    return MHD_SC_TOO_LATE;
-
-  need_unlock = false;
-  if (response->reuse.reusable)
-  {
-    need_unlock = true;
-    if (! mhd_mutex_lock(&(response->reuse.settings_lock)))
-      return MHD_SC_RESPONSE_MUTEX_LOCK_FAILED;
-    mhd_assert (1 == mhd_atomic_counter_get(&(response->reuse.counter)));
-  }
-
-  res = response_set_options_int(response, options, options_max_num);
 
   if (need_unlock)
-    mhd_mutex_unlock_chk(&(response->reuse.settings_lock));
+    mhd_mutex_lock_chk(&response->reuse.settings_lock);
 
   return res;
 }