Evgeny Grin (Karlson2k) 1 rok temu
rodzic
commit
cc8b6b99ef

+ 137 - 16
scripts/d_options.rec

@@ -3,16 +3,149 @@
 # MHD option registry
 #
 %rec: MHD_Option
+# recutils supports only signed 32 bit values
+%typedef: enum_value range 1 0x7FFFFFFF
 %key: Name
 %singular: Value
+%type: Value enum_value
+%auto: Value
 %mandatory: Value
 %mandatory: Comment
-%mandatory: Argument1
-%mandatory: Description1
-%constraint: ( Value > 0 )
+%allowed: Type Argument1 Description1 Member1 Argument2 Description2 Member2 Argument3 Description3 Member3
+%type: Name,Type,Argument1,Member1,Argument2,Member2,Argument3,Member3 line
+%unique: Type Value Argument1 Description1 Member1 Argument2 Description2 Member2 Argument3 Description3 Member3
+
+#Name: 
+#Value: 
+#Type: enum MHD_Bool
+#Comment:
+#Argument1:
+#Description1:
+#Argument2:
+#Description2:
+
+Name: logger
+Value: 100
+Type: struct MHD_DaemonOptionValueLogger
+Comment: Set logging method.  Specify NULL to disable logging entirely.  By
++ default (if this option is not given), MHD writes log messages to stderr.
++
++ In case of special builds for embedded projects:
++ Logging will not work if MHD was compiled with "--disable-logging".
++ (The function will still be exported, but the @a logger will never
++ be invoked.)
+Argument1: MHD_LoggingCallback cb
+Description1: the logger function to invoke, NULL to disable logging
+Argument2: void *logger_cls
+Description2: the closure for logger @a cb callback
+
+
+Name: bind_socket_address
+Value: 201
+Type: struct MHD_DaemonOptionValueSA
+Comment: Bind to the given socket address.
++ Ineffective in conjunction with #MHD_daemon_listen_socket().
+Argument1: size_t sa_len
+Description1: the size of the socket address pointed by @a sa.
+Argument2: const struct sockaddr *sa
+Description2: the address to bind to; can be IPv4 (AF_INET), IPv6 (AF_INET6) or even a UNIX domain socket (AF_UNIX)
+
+
+Name: option_tcp_fastopen
+Value: 200
+Type: struct MHD_DaemonOptionValueTFO
+Comment: Configure TCP_FASTOPEN option, including setting a
++ custom @a queue_length.
++
++ Note that having a larger queue size can cause resource exhaustion
++ attack as the TCP stack has to now allocate resources for the SYN
++ packet along with its DATA.
+Argument1: enum MHD_TCPFastOpenType option
+Description1: the type use of of TCP FastOpen
+Argument2: unsigned int queue_length
+Description2: the length of the queue, zero to use system or MHD default
+
+Name: bind_port
+Value: 202
+Type: struct MHD_DaemonOptionValueBind
+Comment: Bind to the given TCP port and address family.
++
++ Ineffective in conjunction with #MHD_daemon_listen_socket().
++ Ineffective in conjunction with #MHD_daemon_bind_sa().
++
++ If neither this option nor the other two mentioned above
++ is specified, MHD will simply not listen on any socket!
+Argument1: enum MHD_AddressFamily af
+Description1: the address family to use
+Argument2: uint_fast16_t port
+Description2: port to use, 0 to let system assign any free port
+
+Name: LISTEN_BACKLOG
+Value: 203
+Type: unsigned int
+Comment: Use the given backlog for the listen() call.
++ Ineffective in conjunction with #MHD_daemon_listen_socket()
+
+Name: GLOBAL_CONNECTION_LIMIT
+Value: 204
+Type: unsigned int
+Comment: Limit on the number of (concurrent) network connections
++ made to the server from the same IP address.
++ Can be used to prevent one IP from taking over all of
++ the allowed connections. If the same IP tries to establish
++ more than the specified number of connections, they will
++ be immediately rejected.
+Argument1: conn_lim
+
+Name: DEFAULT_TIMEOUT
+Value: 205
+Type: unsigned int
+Comment: After how many seconds of inactivity should a
++ connection automatically be timed out?
++ Use zero for no timeout, which is also the (unsafe!) default.
+Argument1: def_timeout
+
+Name: listen_socket
+Value: 206
+Comment: Accept connections from the given socket.  Socket
++ must be a TCP or UNIX domain (SOCK_STREAM) socket.
+Argument1: MHD_socket listen_fd
+Description1: the listen socket to use, ignored if set to #MHD_INVALID_SOCKET
+
+Name: event_loop
+Value: 207
+Comment: Select a particular event loop internal system call.
+Argument1: enum MHD_EventLoopSyscal els
+
+Name: protocol_strict_level
+Value: 210
+Type: struct MHD_DaemonOptionValueStrctLvl
+Comment: Set how strictly MHD will enforce the HTTP protocol.
+Argument1: enum MHD_ProtocolStrictLevel sl
+Description1: the level of strictness
+Argument2: enum MHD_UseStictLevel how
+Description2: the way how to set the requested level
+
+Name: tls_psk_callback
+Value: 211
+Type: struct MHD_DaemonOptionValueTlsPskCB
+Comment: Configure PSK to use for the TLS key exchange.
+Argument1: MHD_PskServerCredentialsCallback psk_cb
+Description1: the function to call to obtain pre-shared key
+Argument2: void *psk_cb_cls
+Description2: the closure for @a psk_cb
+
+#Name: 
+#Value: 
+#Type: enum MHD_Bool
+#Comment: 
+#Argument1: 
+#Description1: 
+#Argument2: 
+#Description2: 
 
 Name: SUPPRESS_DATE_HEADER
-Value: 1
+Value: 101
 Argument1: enum MHD_Bool bool_val
 Description1: the value of the parameter
 Comment: Suppresses use of "Date:" header.
@@ -37,15 +170,3 @@ Comment: Enable `turbo`.  Disables certain calls to `shutdown()`,
 + other potentially unsafe optimisations.
 + Most effects only happen with internal threads with epoll.
 + The 'turbo' mode is not enabled (mode is disabled) by default.
-
-Name: sock addr
-Value: 4
-Comment: Bind to the given socket address.
-+ Ineffective in conjunction with #MHD_daemon_listen_socket().
-Type: struct MHD_DaemonOptionValueSA
-Argument1: size_t sa_len_val
-Description1: the number of bytes in @a sa
-Member1: sa_len
-Argument2: const struct sockaddr *sa_val
-Description2: the address to bind to; can be IPv4 (AF_INET), IPv6 (AF_INET6) or even a UNIX domain socket (AF_UNIX)
-Member2: sa

+ 61 - 20
scripts/d_options.sh

@@ -79,7 +79,8 @@ unset test_var
 # parameters
 max_width=79
 input_rec="d_options.rec"
-tmp_rec="d_options_preproc.rec"
+tmp_rec_name="D_Options_preproc"
+tmp_rec_file="d_options_preproc.rec"
 
 # fixed strings
 flat_arg_descr='the value of the parameter'
@@ -173,31 +174,39 @@ def_name_for_type() {
     esac
 }
 
+capitalise_first() {
+    local first_char="${1:0:1}"
+    printf '%s' "${first_char^^}${1:1}"
+}
+
+recfix --check "$input_rec" || exit 3
 
-cat << _EOF_ > "$tmp_rec"
-%rec: MHD_Option_preproc
+cat << _EOF_ > "$tmp_rec_file"
+%rec: ${tmp_rec_name}
+%key: EName
 %mandatory: Value
 %mandatory: Name
 %type: Value int
 %sort: Value
+%singular: EName UName Value
 
 _EOF_
 
 echo "Processing input file..."
 for N in $(recsel -t MHD_Option -R Value "$input_rec")
 do
-    NAME=$(recsel -t MHD_Option -P Name -e "Value=$N" "$input_rec")
+    NAME=$(recsel -t MHD_Option -P Name -e "Value = $N" "$input_rec")
     if [[ -z $NAME ]]; then
       echo "The 'Name' field is empty for 'Value=$N'" >&2
       exit 2
     fi
     echo "$N: ${NAME^^}"
-    COMMENT=$(recsel -t MHD_Option -P Comment -e "Value=$N" "$input_rec")
+    COMMENT=$(recsel -t MHD_Option -P Comment -e "Value = $N" "$input_rec")
     if [[ -z $COMMENT ]]; then
       echo "The 'Comment' field is empty for '$NAME' ('Value=$N')" >&2
       exit 2
     fi
-    TYPE=$(recsel -t MHD_Option -P Type -e "Value=$N" "$input_rec")
+    TYPE=$(recsel -t MHD_Option -P Type -e "Value = $N" "$input_rec")
     EComment="" # The initial part of doxy comment for the enum value
     EName=""    # The final part of the name of the enum value
     UName=""    # The final part of the name of the union member
@@ -208,6 +217,7 @@ do
     CLBody=""   # The Compound Literal body (for the set macro)
     SFArguments=""  # The arguments for the static function
     SFBody=""   # The static function body
+    StBody=''   # The data struct body (if any)
     
     nested='maybe'  # The option has nested struct parameters ('yes'/'no'/'maybe')
 
@@ -233,12 +243,12 @@ do
     MEMBERS=( )
     M=1
     while
-        ARGM=$(recsel -t MHD_Option -P Argument${M} -e "Value=$N" "$input_rec")
+        ARGM=$(recsel -t MHD_Option -P Argument${M} -e "Value = $N" "$input_rec")
         [[ -n $ARGM ]]
     do
         ARGS[$M]="$ARGM"
-        DESCRS[$M]="$(recsel -t MHD_Option -P Description${M} -e "Value=$N" "$input_rec")"
-        MEMBERS[$M]="$(recsel -t MHD_Option -P Member${M} -e "Value=$N" "$input_rec")"
+        DESCRS[$M]="$(recsel -t MHD_Option -P Description${M} -e "Value = $N" "$input_rec")"
+        MEMBERS[$M]="$(recsel -t MHD_Option -P Member${M} -e "Value = $N" "$input_rec")"
         (( M++ ))
     done
     
@@ -265,6 +275,9 @@ do
         arg_type='' # The type of the data of the current argument
         arg_descr='' # The description of the current argument
         nest_member='' # The name of the member of the nested structure
+        [[ "${ARGS[$M]}" =~ (^' '|' '$) ]] && err_exit "'Argument${M}' value '${ARGS[$M]}' for '$NAME' ('Value=$N') is not trimmed"
+        [[ "${DESCRS[$M]}" =~ (^' '|' '$) ]] && err_exit "'Description${M}' value '${DESCRS[$M]}' for '$NAME' ('Value=$N') is not trimmed"
+        [[ "${MEMBERS[$M]}" =~ (^' '|' '$) ]] && err_exit "'Member${M}' value '${MEMBERS[$M]}' for '$NAME' ('Value=$N') is not trimmed"
         # Pre-process parameters data
         if [[ -n ${ARGS[$M]} ]]; then
             arg_name="${ARGS[$M]##* }"
@@ -290,9 +303,12 @@ do
             [[ $TYPE = $arg_type ]] && \
                 err_exit "The same 'Type' and type for in 'Argument${M}' ('$arg_type') used for non-flat (nested) '$NAME' ('Value=$N')"
             [[ -z $arg_descr ]] && \
-                err_exit "Empty or no 'Description${M}' for argument '${ARGS[$M]}' for '$NAME' ('Value=$N')"
-            [[ -z $nest_membr ]] && \
-                err_exit "Empty or no 'Member${M}' for argument '${ARGS[$M]}' for nested (non-flat) '$NAME' ('Value=$N')"
+                err_exit "Empty or no 'Description${M}' for argument '${ARGS[$M]}' for non-flat (nested) '$NAME' ('Value=$N')"
+            if [[ "$arg_name" = "$nest_membr" ]]; then
+                echo "The name for 'Argument${M}' ('${ARGS[$M]}') is the same as the 'Member${M}' ('$nest_membr') for non-flat (nested) '$NAME' ('Value=$N')" >&2
+                nest_membr="v_${nest_membr}"
+                echo "Auto-correcting the struct member name to '$nest_membr' to avoid wrong macro expansion" >&2
+            fi
         else
             # flat, non-nested
             if [[ -z $arg_type ]]; then
@@ -314,6 +330,11 @@ do
         fi
         
         [[ "$arg_type" =~ \*$ ]] || arg_type+=' ' # Position '*' correctly
+        [[ "$arg_name" = "v_${UName}" ]] && err_exit "The name ('$arg_name') of the argument 'Argument${M}' ('${ARGS[$M]}') for '$NAME' ('Value=$N') conflicts with the union member name ('v_${UName}'). Macro would not work."
+        [[ "$arg_name" = "opt" ]] && err_exit "The name ('$arg_name') of the argument 'Argument${M}' ('${ARGS[$M]}') for '$NAME' ('Value=$N') conflicts with the option struct member name ('opt'). Macro would not work."
+        [[ "$arg_name" = "val" ]] && err_exit "The name ('$arg_name') of the argument 'Argument${M}' ('${ARGS[$M]}') for '$NAME' ('Value=$N') conflicts with the option struct member name ('val'). Macro would not work."
+        [[ "${arg_name,,}" = "${arg_name}" ]] || err_exit "The name ('$arg_name') of the argument 'Argument${M}' ('${ARGS[$M]}') for '$NAME' ('Value=$N') has capital letter(s)"
+        [[ $nested = 'yes' ]] && [[ -z $nest_membr ]] && nest_membr="v_${arg_name}"
         
         [[ $M -gt 1 ]] && [[ $nested = 'no' ]] && err_exit
         
@@ -339,14 +360,27 @@ do
         CLBody+=" = ($arg_name)"
 
         [[ $M -gt 1 ]] && SFBody+=$'\n'"  "
-        SFBody+="opt.val.v_${UName}"
+        SFBody+="opt_val.val.v_${UName}"
         [[ $nested = 'yes' ]] && SFBody+=".${nest_membr}"
         SFBody+=" = ${arg_name};"
         
+        if [[ $nested = 'yes' ]] && [[ "$TYPE" =~ ^'struct ' ]]; then
+            StBody+=$'\n'
+            StBody+="  /**"$'\n'
+            format_doxy '   * ' "$(capitalise_first "$arg_descr")" || err_exit
+            StBody+="$format_doxy_res"$'\n'"   */"$'\n'
+            StBody+="    ${arg_type}$nest_membr;"
+        fi
     done
+    
     UType="$TYPE"
+    if [[ $nested = 'yes' ]] && [[ "$TYPE" =~ ^'struct ' ]]; then
+        need_struct_decl='yes'
+    else
+        need_struct_decl='no'
+    fi
     
-    recins -t MHD_Option_preproc \
+    recins -t "${tmp_rec_name}" \
         -f Name -v "$NAME" \
         -f Value -v "$N" \
         -f EComment -v "$EComment" \
@@ -359,14 +393,21 @@ do
         -f CLBody -v "$CLBody" \
         -f SFArguments -v "$SFArguments" \
         -f SFBody -v "$SFBody" \
-        "$tmp_rec"
+        -f StBody -v "$StBody" \
+        --verbose "$tmp_rec_file" || err_exit
 done
 echo "finished."
 
 echo "Generating output files..."
-recfmt -f d_options_enum.template <"$tmp_rec" > enum_insert.h
-recfmt -f d_options_union.template <"$tmp_rec" > union_insert.h
-recfmt -f d_options_macro.template <"$tmp_rec" | ${SED-sed} -e 's/##removeme##//g' - > macro_insert.h
-recfmt -f d_options_func.template <"$tmp_rec" > func_insert.h
-# rm "$tmp_rec"
+echo "enum..."
+recfmt -f d_options_enum.template < "$tmp_rec_file" > enum_insert.h
+echo "structs..."
+recsel -e "StBody != ''" "$tmp_rec_file" | recfmt -f d_options_struct.template > struct_insert.h
+echo "union..."
+recfmt -f d_options_union.template < "$tmp_rec_file" > union_insert.h
+echo "macros..."
+recfmt -f d_options_macro.template < "$tmp_rec_file" | ${SED-sed} -e 's/##removeme##//g' - > macro_insert.h
+echo "functions..."
+recfmt -f d_options_func.template < "$tmp_rec_file" > func_insert.h
+# rm "$tmp_rec_file"
 echo "finished."

+ 1 - 0
scripts/d_options_func.template

@@ -13,3 +13,4 @@ MHD_DAEMON_OPTION_{{SName}} ({{SFArguments}})
 
   return opt_val;
 }
+

+ 1 - 0
scripts/d_options_macro.template

@@ -11,3 +11,4 @@
     {{CLBody}} \
   } \
   MHD_RESTORE_WARN_COMPOUND_LITERALS_
+

+ 7 - 0
scripts/d_options_struct.template

@@ -0,0 +1,7 @@
+/**
+ * Data for #MHD_D_O_{{EName}}
+ */
+{{UType}} v_{{UName}}
+{{{StBody}}
+};
+

+ 3 - 88
src/include/microhttpd2.h

@@ -2637,30 +2637,7 @@ typedef void
                        const char *fm,
                        va_list ap);
 
-/**
- * Set logging method.  Specify NULL to disable logging entirely.  By
- * default (if this option is not given), MHD writes log messages to
- * stderr.
- *
- * In case of special builds for embedded projects:
- * Logging will not work if MHD was compiled with "--disable-logging".
- * (The function will still be exported, but the @a logger will never
- * be invoked.)
- *
- * @param[in,out] daemon which instance to setup logging for
- * @param logger function to invoke,
- *               NULL to disable logging,
- * @param logger_cls closure for @a logger
- * @return #MHD_SC_OK on success,
- *         #MHD_SC_FEATURE_DISABLED if logging is disabled for this MHD build
- */
-MHD_EXTERN_ enum MHD_StatusCode
-MHD_daemon_set_logger (struct MHD_Daemon *daemon,
-                       MHD_LoggingCallback logger,
-                       void *logger_cls)
-MHD_FN_PAR_NONNULL_ (1);
-
-
+// FIXME: convert
 /**
  * Convenience macro used to disable logging.
  *
@@ -2671,19 +2648,6 @@ MHD_FN_PAR_NONNULL_ (1);
                          MHD_STATIC_CAST_(MHD_LoggingCallback,NULL),   \
                          NULL)
 
-
-struct MHD_DaemonOptionValueSA
-{
-  /**
-   * The size of the socket address pointed by @a sa.
-   */
-  size_t sa_len;
-  /**
-   * The pointer to the socket address.
-   */
-  const struct sockaddr *sa;
-};
-
 /**
  * Parameter for listen socket binding type
  */
@@ -2801,7 +2765,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_DaemonOption
 /**
  * Possible levels of enforcement for TCP_FASTOPEN.
  */
-enum MHD_FIXED_ENUM_APP_SET_ MHD_FastOpenOption
+enum MHD_FIXED_ENUM_APP_SET_ MHD_TCPFastOpenType
 {
   /**
    * Disable use of TCP_FASTOPEN.
@@ -2824,30 +2788,6 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_FastOpenOption
 };
 
 
-/**
- * Configure TCP_FASTOPEN option, including setting a
- * custom @a queue_length.
- *
- * Note that having a larger queue size can cause resource exhaustion
- * attack as the TCP stack has to now allocate resources for the SYN
- * packet along with its DATA.
- *
- * @param daemon which instance to configure TCP_FASTOPEN for
- * @param fom under which conditions should we use TCP_FASTOPEN?
- * @param queue_length queue length to use, default is 50 if this
- *        option is never given.
- * @return #MHD_SC_OK on on success,
- *         #MHD_SC_TOO_LATE if this option was set after the daemon was started and it cannot be set anymore
- *         #MHD_SC_FEATURE_DISABLED,
- *         #MHD_SC_FEATURE_NOT_AVAILABLE,
- *         #MHD_SC_OPTIONS_CONFLICT
- */
-MHD_EXTERN_ enum MHD_StatusCode
-MHD_daemon_set_option_tcp_fastopen (struct MHD_Daemon *daemon,
-                                    enum MHD_FastOpenOption option,
-                                    unsigned int queue_length)
-MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_;
-
 
 /**
  * Address family to be used by MHD.
@@ -2883,31 +2823,6 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_AddressFamily
 };
 
 
-/**
- * Bind to the given TCP port and address family.
- *
- * Ineffective in conjunction with #MHD_daemon_listen_socket().
- * Ineffective in conjunction with #MHD_daemon_bind_sa().
- *
- * If neither this option nor the other two mentioned above
- * is specified, MHD will simply not listen on any socket!
- *
- * @param[in,out] daemon which instance to configure the TCP port for
- * @param af address family to use
- * @param port port to use, 0 to bind to a random (free) port
- * @return #MHD_SC_OK on on success,
- *         #MHD_SC_TOO_LATE if this option was set after the daemon was started and it cannot be set anymore
- *         #MHD_SC_FEATURE_DISABLED,
- *         #MHD_SC_FEATURE_NOT_AVAILABLE,
- *         #MHD_SC_OPTIONS_CONFLICT
- */
-MHD_EXTERN_ enum MHD_StatusCode
-MHD_daemon_bind_port (struct MHD_Daemon *daemon,
-                      enum MHD_AddressFamily af,
-                      uint_fast16_t port)
-MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_;
-
-
 /**
  * Bind to the given socket address.
  * Ineffective in conjunction with #MHD_daemon_listen_socket().
@@ -3068,7 +2983,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_EventLoopSyscall
   MHD_ELS_POLL = 2
   ,
   /**
-   * Use epoll().
+   * Use epoll.
    */
   MHD_ELS_EPOLL = 3
 };