libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

commit 9cce831b3eb779f3b19e91e099d4fb3cebcd5b56
parent 9af1d7309fa45b0fd7f5746759852eb0becca37a
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date:   Sun, 26 Jan 2025 21:00:00 +0100

Complete implementation of MHD_*_get_info_*() functions + some internal changes and fixes

Diffstat:
Mconfigure.ac | 110++++++++++++++++++++++++++++++++++++-------------------------------------------
Mdoc/examples/Makefile.am | 4++--
Am4/mhd_check_decls.m4 | 46++++++++++++++++++++++++++++++++++++++++++++++
Msrc/incl_priv/mhd_sys_options.h | 92+++++++++++--------------------------------------------------------------------
Msrc/include/d_options.rec | 21++++++++++++++++++++-
Msrc/include/microhttpd2.h | 1013++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/include/microhttpd2_generated_daemon_options.h | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/include/microhttpd2_generated_response_options.h | 4++--
Msrc/include/microhttpd2_main.h.in | 990++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/include/microhttpd2_portability.h | 29++++++++++++++++++++++-------
Msrc/include/microhttpd2_preamble.h.in | 8++++----
Dsrc/include/options.tmpl | 8--------
Msrc/include/r_options.rec | 2+-
Msrc/mhd2/Makefile.am | 14++++++++------
Msrc/mhd2/action.c | 12++++++------
Msrc/mhd2/auth_digest.c | 2+-
Msrc/mhd2/conn_data_process.c | 8++++----
Msrc/mhd2/conn_data_send.c | 12++++++------
Asrc/mhd2/conn_get_info.c | 167+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/mhd2/daemon_add_conn.c | 58+++++++++++++++++++++++++++++-----------------------------
Msrc/mhd2/daemon_funcs.c | 8++++----
Msrc/mhd2/daemon_funcs.h | 6+++---
Msrc/mhd2/daemon_get_info.c | 167++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/mhd2/daemon_logger.c | 4++--
Msrc/mhd2/daemon_logger.h | 6+++---
Msrc/mhd2/daemon_logger_default.c | 4++--
Msrc/mhd2/daemon_logger_default.h | 4++--
Msrc/mhd2/daemon_options.h | 9++++++++-
Msrc/mhd2/daemon_set_options.c | 12++++++++++++
Msrc/mhd2/daemon_start.c | 331++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/mhd2/events_process.c | 121+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/mhd2/events_process.h | 14++++++++++++++
Msrc/mhd2/lib_get_info.c | 420+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/mhd2/md5_ext.c | 1+
Msrc/mhd2/md5_int.c | 7+------
Msrc/mhd2/mhd_action.h | 34+++++++++++++++++-----------------
Msrc/mhd2/mhd_atomic_counter.h | 6+++---
Msrc/mhd2/mhd_connection.h | 63+++++++++++++++++++++++++++++++++++----------------------------
Msrc/mhd2/mhd_daemon.h | 73++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/mhd2/mhd_lib_init.c | 18++++++++++++++++--
Msrc/mhd2/mhd_lib_init.h | 13+++++++++++++
Msrc/mhd2/mhd_locks.h | 6+++---
Msrc/mhd2/mhd_panic.c | 4++--
Msrc/mhd2/mhd_panic.h | 2+-
Msrc/mhd2/mhd_recv.c | 10+++++-----
Msrc/mhd2/mhd_reply.h | 4++--
Msrc/mhd2/mhd_request.h | 19++++++++++++-------
Msrc/mhd2/mhd_response.h | 8++++----
Msrc/mhd2/mhd_send.c | 40++++++++++++++++++++--------------------
Msrc/mhd2/mhd_send.h | 2+-
Msrc/mhd2/mhd_sockets_funcs.c | 18++++++++----------
Msrc/mhd2/mhd_sockets_macros.h | 30++----------------------------
Msrc/mhd2/mhd_str.c | 10++++++----
Msrc/mhd2/mhd_str.h | 10++++++----
Asrc/mhd2/mhd_stream.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Msrc/mhd2/mhd_threads.c | 33++++++++++++++++++++++++++-------
Msrc/mhd2/mhd_threads.h | 39+++++++++++++++++++++++++++++----------
Msrc/mhd2/mhd_tls_choice.h | 14+++++++-------
Msrc/mhd2/mhd_tls_enums.h | 2+-
Msrc/mhd2/mhd_tls_funcs.c | 8++++----
Msrc/mhd2/mhd_tls_funcs.h | 27++++++++++++++++++++++++---
Msrc/mhd2/request_get_info.c | 301++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/mhd2/request_get_value.c | 15+++++++++------
Msrc/mhd2/respond_with_error.h | 2+-
Msrc/mhd2/response_from.c | 4++--
Msrc/mhd2/response_options.h | 2+-
Msrc/mhd2/sha256_ext.c | 2++
Msrc/mhd2/sha256_int.c | 7+------
Msrc/mhd2/sha512_256_int.c | 7+------
Msrc/mhd2/stream_funcs.c | 32++++++++++++++++----------------
Msrc/mhd2/stream_funcs.h | 14+++++++-------
Asrc/mhd2/stream_get_info.c | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/mhd2/stream_process_reply.c | 28++++++++++++++--------------
Msrc/mhd2/stream_process_request.c | 49+++++++++++++++++++++++++++----------------------
Msrc/mhd2/stream_process_states.c | 36++++++++++++++++++------------------
Msrc/mhd2/sys_ip_headers.h | 10++++++++++
Msrc/mhd2/sys_poll.h | 19+++++++------------
Msrc/mhd2/sys_select.h | 4++--
Msrc/mhd2/sys_sendfile.h | 4++--
Msrc/mhd2/sys_sockets_headers.h | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/mhd2/tls_gnu_conn_data.h | 2+-
Msrc/mhd2/tls_gnu_daemon_data.h | 2+-
Msrc/mhd2/tls_gnu_funcs.c | 47+++++++++++++++++++++++++++++++++++++++++++++--
Msrc/mhd2/tls_gnu_funcs.h | 31++++++++++++++++++++++++++++++-
Msrc/mhd2/tls_gnu_tls_lib.h | 2+-
Msrc/mhd2/tls_multi_conn_data.h | 8++++----
Msrc/mhd2/tls_multi_daemon_data.h | 8++++----
Msrc/mhd2/tls_multi_funcs.c | 232+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/mhd2/tls_multi_funcs.h | 29+++++++++++++++++++++++++++++
Msrc/mhd2/tls_multi_tls_lib.h | 4++--
Msrc/mhd2/tls_open_conn_data.h | 4++--
Msrc/mhd2/tls_open_daemon_data.h | 2+-
Msrc/mhd2/tls_open_funcs.c | 52+++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/mhd2/tls_open_funcs.h | 31++++++++++++++++++++++++++++++-
Msrc/mhd2/tls_open_tls_lib.h | 2+-
Msrc/mhd2/upgraded_net.c | 41+++++++++++++++++++++--------------------
Msrc/tests/Makefile.am | 2+-
Msrc/tests/basic/Makefile.am | 14+++++++-------
Msrc/tests/client_server/Makefile.am | 2+-
Msrc/tests/client_server/test_cert_tls.c | 8++++----
Msrc/tests/client_server/test_client_server.c | 6+++---
Msrc/tests/client_server/test_tls.c | 16++++++++--------
102 files changed, 3891 insertions(+), 1717 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -1746,7 +1746,7 @@ AS_IF([test "x$USE_THREADS" = "xposix"], [AC_DEFINE([mhd_THREADS_KIND_W32],[1],[define to use W32 threads])])]) AM_CONDITIONAL([USE_POSIX_THREADS], [test "x$USE_THREADS" = "xposix"]) AM_CONDITIONAL([USE_W32_THREADS], [test "x$USE_THREADS" = "xw32"]) -AM_CONDITIONAL([MHD_USE_THREADS], [test "x$USE_THREADS" != "xnone"]) +AM_CONDITIONAL([MHD_SUPPORT_THREADS], [test "x$USE_THREADS" != "xnone"]) AM_CONDITIONAL([DISABLE_THREADS], [test "x$USE_THREADS" = "xnone"]) AC_MSG_RESULT([$USE_THREADS]) @@ -2809,7 +2809,7 @@ AS_VAR_IF([mhd_cv_func_select],["yes"], AS_IF([test "x$enable_select" != "xno"], [ enable_select="yes" - AC_DEFINE([[MHD_USE_SELECT]],[[1]],[Define to '1' to enable use of select() system call]) + AC_DEFINE([[MHD_SUPPORT_SELECT]],[[1]],[Define to '1' to enable use of select() system call]) ] ) ], @@ -2819,7 +2819,7 @@ AS_VAR_IF([mhd_cv_func_select],["yes"], ) ] ) -AM_CONDITIONAL([MHD_USE_SELECT],[test "x${enable_select}" = "xyes"]) +AM_CONDITIONAL([MHD_SUPPORT_SELECT],[test "x${enable_select}" = "xyes"]) AC_ARG_ENABLE([[poll]], [AS_HELP_STRING([[--enable-poll[=ARG]]], [enable 'poll()' support (yes, no, auto) [auto]]) @@ -2862,7 +2862,7 @@ AS_IF([test "$os_is_native_w32" != "yes"], AS_VAR_IF([have_poll],["yes"], [ AC_DEFINE([[HAVE_POLL]],[[1]],[Define to '1' if poll() is supported on your platform]) - AC_CHECK_DECLS([POLLRDNORM,POLLIN,POLLRDBAND,POLLWRNORM,POLLOUT,POLLWRBAND,POLLPRI],[],[],[[ + MHD_CHECK_DECLS([POLLRDNORM POLLIN POLLRDBAND POLLWRNORM POLLOUT POLLWRBAND POLLPRI],[[ #ifdef HAVE_POLL_H #include <poll.h> #endif @@ -2874,7 +2874,7 @@ AS_VAR_IF([have_poll],["yes"], AS_IF([test "x$enable_poll" != "xno"], [ enable_poll="yes" - AC_DEFINE([[MHD_USE_POLL]],[[1]],[Define to '1' to enable use of select() system call]) + AC_DEFINE([[MHD_SUPPORT_POLL]],[[1]],[Define to '1' to enable use of select() system call]) ] ) ], @@ -2884,7 +2884,7 @@ AS_VAR_IF([have_poll],["yes"], ) ] ) -AM_CONDITIONAL([MHD_USE_POLL],[test "x${enable_poll}" = "xyes"]) +AM_CONDITIONAL([MHD_SUPPORT_POLL],[test "x${enable_poll}" = "xyes"]) AC_ARG_ENABLE([[epoll]], [AS_HELP_STRING([[--enable-epoll[=ARG]]], [enable epoll support (yes, no, auto) [auto]]) @@ -2906,7 +2906,7 @@ AS_IF([test "$enable_epoll" != "no"], [cacheVar="assuming yes"], [ AC_DEFINE([[HAVE_EPOLL]],[[1]],[Define to '1' if epoll is supported on your platform]) - AC_DEFINE([[MHD_USE_EPOLL]],[[1]],[Define to '1' to enable 'epoll' functionality]) + AC_DEFINE([[MHD_SUPPORT_EPOLL]],[[1]],[Define to '1' to enable 'epoll' functionality]) enable_epoll='yes' ], [ @@ -2935,7 +2935,7 @@ WARNING: " ) ] ) -AM_CONDITIONAL([MHD_USE_EPOLL], [[test "x${enable_epoll}" = "xyes"]]) +AM_CONDITIONAL([MHD_SUPPORT_EPOLL], [[test "x${enable_epoll}" = "xyes"]]) AS_IF([test "x$enable_epoll" = "xyes"], [ @@ -3106,12 +3106,14 @@ MHD_CHECK_FUNC_RUN([getsockname], #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +#if defined(_WIN32) && !defined(__CYGWIN__) #ifdef HAVE_WINSOCK2_H #include <winsock2.h> #endif #ifdef HAVE_WS2TCPIP_H #include <ws2tcpip.h> #endif +#endif #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif @@ -3136,35 +3138,37 @@ MHD_CHECK_FUNC_RUN([getsockname], const SOCKET invld_sckt = INVALID_SOCKET; WSADATA wsa_data; - if (0 != WSAStartup(MAKEWORD(2, 2), &wsa_data) || MAKEWORD(2, 2) != wsa_data.wVersion) + i][f (0 != WSAStartup(MAKEWORD(2, 2), &wsa_data) || MAKEWORD(2, 2) != wsa_data.wVersion) return 20; #endif - sckt = socket (PF_INET, SOCK_STREAM, 0); - if (invld_sckt != sckt) + sckt = socket (AF_INET, SOCK_STREAM, 0); + i][f (invld_sckt != sckt) { memset(&sa, 0, c_addr_size); sa.sin_family = AF_INET; + i][f (0 != INADDR_ANY) + sa.sin_addr.s_addr = htonl (INADDR_ANY); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sa.sin_len = c_addr_size; #endif - if (0 == bind (sckt, (struct sockaddr *)&sa, c_addr_size)) + i][f (0 == bind (sckt, (struct sockaddr *)&sa, c_addr_size)) { - if (0 == listen (sckt, 1)) + i][f (0 == listen (sckt, 1)) { addr_size = c_addr_size; - if (0 == getsockname (sckt, (struct sockaddr *)&sa, &addr_size)) + i][f (0 == getsockname (sckt, (struct sockaddr *)&sa, &addr_size)) { - if (c_addr_size >= addr_size) + i][f (c_addr_size >= addr_size) { - if (0 != ntohs(sa.sin_port)) + i][f (0 != ntohs(sa.sin_port)) { ret = 0; - } else ret = 7; - } else ret = 6; - } else ret = 5; - } else ret = 4; - } else ret = 3; - } else ret = 2; + } el][se ret = 7; + } el][se ret = 6; + } el][se ret = 5; + } el][se ret = 4; + } el][se ret = 3; + } el][se ret = 2; #if !defined(_WIN32) || defined(__CYGWIN__) close (sckt); #else @@ -3206,8 +3210,10 @@ AS_VAR_IF([[os_is_native_w32]], [["yes"]],[], ] ) -AC_CHECK_DECLS([AF_UNIX,AF_LOCAL,SOMAXCONN,IPV6_V6ONLY,SO_REUSEADDR,SO_REUSEPORT,\ -TCP_NODELAY,TCP_FASTOPEN],[],[], +MHD_CHECK_DECLS([AF_UNIX AF_LOCAL SOMAXCONN IPV6_V6ONLY TCP_NODELAY TCP_FASTOPEN \ + SOCK_NONBLOCK SOCK_CLOEXEC SOCK_NOSIGPIPE MSG_NOSIGNAL MSG_MORE \ + SOL_SOCKET SO_REUSEADDR SO_REUSEPORT SO_LINGER SO_NOSIGPIPE \ + SHUT_WR SD_SEND], [[ #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> @@ -3704,21 +3710,6 @@ errno_t gmtime_s(struct tm* _tm, const time_t* time); #include <time.h>]]) -AC_CHECK_DECL([SOCK_NONBLOCK], [AC_DEFINE([HAVE_SOCK_NONBLOCK], [1], [SOCK_NONBLOCK is defined in a socket header])], [], - [[ -#if defined(HAVE_SYS_TYPES_H) -# include <sys/types.h> -#endif -#if defined(HAVE_SYS_SOCKET_H) -# include <sys/socket.h> -#elif defined(HAVE_WINSOCK2_H) -# include <winsock2.h> -#elif defined(HAVE_UNISTD_H) -# include <unistd.h> -#endif - ]] -) - MHD_FIND_LIB([clock_gettime],[[#include <time.h>]], [[ struct timespec tp; @@ -3877,7 +3868,7 @@ MHD_CHECK_FUNC([[sysctl]], [[ i][f (sysctl(mib, 2, NULL, NULL, NULL, 0)) return 1; ]], [ - AC_CHECK_DECLS([CTL_NET,PF_INET,IPPROTO_ICMP,ICMPCTL_ICMPLIM],[],[], + MHD_CHECK_DECLS([CTL_NET PF_INET IPPROTO_ICMP ICMPCTL_ICMPLIM], [[ #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> @@ -4850,11 +4841,11 @@ AC_ARG_ENABLE([log-messages], [],[enable_log_messages="$enable_messages"] ) AS_VAR_IF([enable_log_messages],["yes"], - [AC_DEFINE([HAVE_LOG_FUNCTIONALITY],[1],[Define to '1' to enable internal logging and log messages.])], + [AC_DEFINE([MHD_SUPPORT_LOG_FUNCTIONALITY],[1],[Define to '1' to enable internal logging and log messages.])], [enable_log_messages="no"] ) AC_MSG_RESULT([[$enable_log_messages]]) -AM_CONDITIONAL([HAVE_LOG_FUNCTIONALITY], [test "x$enable_log_messages" != "xno"]) +AM_CONDITIONAL([MHD_SUPPORT_LOG_FUNCTIONALITY], [test "x$enable_log_messages" != "xno"]) AC_MSG_CHECKING([[whether to build text bodies for automatic HTTP response messages]]) AC_ARG_ENABLE([http-messages], @@ -4865,11 +4856,11 @@ AC_ARG_ENABLE([http-messages], [],[enable_http_messages="$enable_messages"] ) AS_VAR_IF([enable_http_messages],["yes"], - [AC_DEFINE([HAVE_HTTP_AUTO_MESSAGES_BODIES],[1],[Define to '1' to enable verbose text bodies for automatic HTTP replies.])], + [AC_DEFINE([MHD_ENABLE_AUTO_MESSAGES_BODIES],[1],[Define to '1' to enable verbose text bodies for automatic HTTP replies.])], [enable_http_messages="no"] ) AC_MSG_RESULT([[$enable_http_messages]]) -AM_CONDITIONAL([HAVE_HTTP_AUTO_MESSAGES_BODIES], [test "x$enable_http_messages" != "xno"]) +AM_CONDITIONAL([MHD_ENABLE_AUTO_MESSAGES_BODIES], [test "x$enable_http_messages" != "xno"]) # optional: have postprocessor? @@ -4881,8 +4872,8 @@ AC_ARG_ENABLE([postparser], [enable_postparser=yes]) AS_IF([[test "x$enable_postparser" != "xno"]], [ enable_postparser=yes - AC_DEFINE([HAVE_POST_PARSER],[1],[Define to 1 if libmicrohttpd is compiled with POST parser support.]) ]) -AM_CONDITIONAL([HAVE_POST_PARSER], [test "x$enable_postparser" != "xno"]) + AC_DEFINE([MHD_SUPPORT_POST_PARSER],[1],[Define to 1 if libmicrohttpd is compiled with POST parser support.]) ]) +AM_CONDITIONAL([MHD_SUPPORT_POST_PARSER], [test "x$enable_postparser" != "xno"]) AC_MSG_RESULT([[$enable_postparser]]) have_gnutls=no @@ -5260,7 +5251,7 @@ choke me now multiple_tls="yes" ] ) - AC_DEFINE([MHD_USE_GNUTLS],[1],[Define to '1' i][f GnuTLS library should be used]) + AC_DEFINE([MHD_SUPPORT_GNUTLS],[1],[Define to '1' i][f GnuTLS library should be used]) MSG_TLS_BACKENDS="${MSG_TLS_BACKENDS}GnuTLS" MHD_APPEND_FLAG_TO_VAR([MHD_TLS_LIB_CPPFLAGS],[$GNUTLS_CPPFLAGS]) MHD_APPEND_FLAG_TO_VAR([MHD_TLS_LIB_LDFLAGS],[$GNUTLS_LDFLAGS]) @@ -5275,7 +5266,7 @@ choke me now multiple_tls="yes" ] ) - AC_DEFINE([MHD_USE_OPENSSL],[1],[Define to '1' i][f OpenSSL library should be used]) + AC_DEFINE([MHD_SUPPORT_OPENSSL],[1],[Define to '1' i][f OpenSSL library should be used]) MSG_TLS_BACKENDS="${MSG_TLS_BACKENDS}OpenSSL" MHD_APPEND_FLAG_TO_VAR([MHD_TLS_LIB_CPPFLAGS],[$OPENSSL_CPPFLAGS]) MHD_APPEND_FLAG_TO_VAR([MHD_TLS_LIB_LDFLAGS],[$OPENSSL_LDFLAGS]) @@ -5290,7 +5281,7 @@ choke me now [MSG_HTTPS="yes (single backend)"] ) AS_IF([test -z "$MSG_TLS_BACKENDS"],[AC_MSG_FAILURE([configure internal error: no TLS backends])]) - AC_DEFINE([MHD_ENABLE_HTTPS],[1],[Define to '1' i][f HTTPS protocol should be enabled]) + AC_DEFINE([MHD_SUPPORT_HTTPS],[1],[Define to '1' i][f HTTPS protocol should be supported]) ], [ AS_VAR_IF([enable_https],["yes"], @@ -5328,16 +5319,16 @@ AS_VAR_IF([enable_https],["yes"], ) AC_MSG_RESULT([$MSG_HTTPS]) -AM_CONDITIONAL([MHD_USE_GNUTLS], [[test "x$have_gnutls" = "xyes"]]) +AM_CONDITIONAL([MHD_SUPPORT_GNUTLS], [[test "x$have_gnutls" = "xyes"]]) AC_SUBST([GNUTLS_CPPFLAGS]) AC_SUBST([GNUTLS_LDFLAGS]) AC_SUBST([GNUTLS_LIBS]) -AM_CONDITIONAL([MHD_USE_OPENSSL], [[test "x$have_openssl" = "xyes"]]) +AM_CONDITIONAL([MHD_SUPPORT_OPENSSL], [[test "x$have_openssl" = "xyes"]]) AC_SUBST([OPENSSL_CPPFLAGS]) AC_SUBST([OPENSSL_LDFLAGS]) AC_SUBST([OPENSSL_LIBS]) AM_CONDITIONAL([MHD_ENABLE_MULTITLS], [test "x$multiple_tls" = "xyes"]) -AM_CONDITIONAL([MHD_ENABLE_HTTPS], [test "x$enable_https" = "xyes"]) +AM_CONDITIONAL([MHD_SUPPORT_HTTPS], [test "x$enable_https" = "xyes"]) AS_VAR_IF([have_gnutls], ["yes"], [ @@ -5514,8 +5505,8 @@ AC_ARG_ENABLE([[httpupgrade]], [[enable_httpupgrade='yes']]) AS_VAR_IF([[enable_httpupgrade]],[["yes"]], [ - AC_DEFINE([[MHD_UPGRADE_SUPPORT]],[[1]],[Define to 1 if libmicrohttpd is compiled with HTTP Upgrade support.]) ]) -AM_CONDITIONAL([MHD_UPGRADE_SUPPORT], [[test "x$enable_httpupgrade" = "xyes"]]) + AC_DEFINE([[MHD_SUPPORT_UPGRADE]],[[1]],[Define to 1 if libmicrohttpd is compiled with HTTP Upgrade support.]) ]) +AM_CONDITIONAL([MHD_SUPPORT_UPGRADE], [[test "x$enable_httpupgrade" = "xyes"]]) AC_MSG_RESULT([[$enable_httpupgrade]]) # optional: HTTP cookie parsing support. Enabled by default @@ -5526,8 +5517,8 @@ AC_ARG_ENABLE([[cookie]], [[enable_cookie='yes']]) AS_VAR_IF([[enable_cookie]],[["yes"]], [ - AC_DEFINE([[COOKIE_SUPPORT]],[[1]],[Define to 1 if libmicrohttpd is compiled with HTTP cookie parsing support.]) ]) -AM_CONDITIONAL([ENABLE_COOKIE], [[test "x$enable_cookie" = "xyes"]]) + AC_DEFINE([[MHD_SUPPORT_COOKIES]],[[1]],[Define to 1 if libmicrohttpd is compiled with HTTP cookie parsing support.]) ]) +AM_CONDITIONAL([MHD_SUPPORT_COOKIES], [[test "x$enable_cookie" = "xyes"]]) AC_MSG_RESULT([[$enable_cookie]]) # optional: MD5 support for Digest Auth. Enabled by default. @@ -5934,9 +5925,8 @@ AM_CONDITIONAL([USE_IPV6_TESTING], [[test "x$mhd_cv_ipv6_for_testing" = "xyes"]] AS_VAR_IF([enable_tools],["yes"], [ AC_CHECK_HEADERS([features.h sys/pstat.h vxCpuLib.h],[],[],[AC_INCLUDES_DEFAULT]) - AC_CHECK_DECLS( - [_SC_NPROCESSORS_ONLN,_SC_NPROC_ONLN,_SC_CRAY_NCPU,_SC_NPROCESSORS_CONF,CTL_HW,HW_NCPUONLINE,HW_NCPU,HW_AVAILCPU], - [],[], + MHD_CHECK_DECLS([_SC_NPROCESSORS_ONLN _SC_NPROC_ONLN _SC_CRAY_NCPU _SC_NPROCESSORS_CONF \ + CTL_HW HW_NCPUONLINE HW_NCPU HW_AVAILCPU], [[ #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> @@ -6030,7 +6020,7 @@ AS_VAR_IF([enable_tools],["yes"], } CPU_FREE(p_set); ]], - [AC_CHECK_DECLS([CPU_SETSIZE],[],[],[#include <sched.h>])] + [MHD_CHECK_DECLS([CPU_SETSIZE],[],[],[#include <sched.h>])] ) ] ) diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am @@ -24,11 +24,11 @@ noinst_PROGRAMS = if MHD_SUPPORT_AUTH_BASIC noinst_PROGRAMS += -if MHD_ENABLE_HTTPS +if MHD_SUPPORT_HTTPS noinst_PROGRAMS += endif endif -if HAVE_POST_PARSER +if MHD_SUPPORT_POST_PARSER noinst_PROGRAMS += endif diff --git a/m4/mhd_check_decls.m4 b/m4/mhd_check_decls.m4 @@ -0,0 +1,46 @@ +# SYNOPSIS +# +# MHD_CHECK_DECLS([SYMBOLS-TO-TEST], [INCLUDES]) +# +# DESCRIPTION +# +# This macro checks whether specific symbols is defined in the headers. +# SYMBOLS-TO-TEST is s space-separated list of symbols to check. +# The symbol could be a macro, a variable, a constant, a enum value, +# a function name or other kind of symbols recognisable by compiler (or +# preprocessor). +# For every found symbol a relevant preprocessor macro is defined. +# Unlike AC_CHECK_DECLS this m4 macro does not define preprocossor macro if +# symbol is NOT found. +# +# Example usage: +# +# MHD_CHECK_DECLS([SSIZE_MAX OFF_T_MAX], [[#include <limits.h>]]) +# +# +# LICENSE +# +# Copyright (c) 2025 Karlson2k (Evgeny Grin) <k2k@drgrin.dev> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([MHD_CHECK_DECLS],[dnl +m4_newline([[# Expansion of $0 macro starts here]]) +m4_if(m4_index([$1], [(]),[-1],[],[dnl +m4_fatal([SYMBOLS-TO-TEST parameter (first macro argument) contains '('])])dnl m4_if +m4_if(m4_index([$1], [)]),[-1],[],[dnl +m4_fatal([SYMBOLS-TO-TEST parameter (first macro argument) contains ')'])])dnl m4_if +m4_if(m4_index([$1], [,]),[-1],[],[dnl +m4_fatal([SYMBOLS-TO-TEST parameter (first macro argument) contains ','])])dnl m4_if +m4_foreach_w([check_Symbol],[$1], +[AC_CHECK_DECL(check_Symbol,[dnl +AC_DEFINE([HAVE_DCLR_]m4_toupper(check_Symbol),[1],[Define to '1' if you have the declaration of ']check_Symbol['])dnl +],[],[$2]) +])dnl +m4_newline([[# Expansion of $0 macro ends here]]) +]) diff --git a/src/incl_priv/mhd_sys_options.h b/src/incl_priv/mhd_sys_options.h @@ -322,13 +322,13 @@ #if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE) || \ defined(HAVE_DARWIN_SENDFILE) /* Have any supported sendfile() function. */ -# define MHD_USE_SENDFILE 1 +# define mhd_USE_SENDFILE 1 #endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE || HAVE_DARWIN_SENDFILE */ #if defined(mhd_THREADS_KIND_POSIX) || defined(mhd_THREADS_KIND_W32) -# ifndef MHD_USE_THREADS -# define MHD_USE_THREADS 1 +# ifndef MHD_SUPPORT_THREADS +# define MHD_SUPPORT_THREADS 1 # endif #endif /* mhd_THREADS_KIND_POSIX || mhd_THREADS_KIND_W32 */ @@ -496,6 +496,15 @@ __pragma(runtime_checks("c", restore)) #endif /* _MSC_FULL_VER */ + +#if ! defined(mhd_W32_NATIVE) +/** + * Indicate that suppression of SIGPIPE is required for some network + * system calls. + */ +# define mhd_SEND_SPIPE_SUPPRESS_NEEDED 1 +#endif + #ifdef _DEBUG # ifndef MHD_NO_TLS_DEBUG_MESSAGES # ifndef mhd_USE_TLS_DEBUG_MESSAGES @@ -507,83 +516,6 @@ # endif #endif -/* Un-define some HAVE_DECL_* macro if they equal zero. - This should allow safely use #ifdef in the code. - Define HAS_DECL_* macros only if matching HAVE_DECL_* macro - has non-zero value. Unlike HAVE_DECL_*, macros HAS_DECL_* - cannot have zero value. */ -#ifdef HAVE_DECL__SC_NPROCESSORS_ONLN -# if 0 == HAVE_DECL__SC_NPROCESSORS_ONLN -# undef HAVE_DECL__SC_NPROCESSORS_ONLN -# else /* 0 != HAVE_DECL__SC_NPROCESSORS_ONLN */ -# define HAS_DECL__SC_NPROCESSORS_ONLN 1 -# endif /* 0 != HAVE_DECL__SC_NPROCESSORS_ONLN */ -#endif /* HAVE_DECL__SC_NPROCESSORS_ONLN */ - -#ifdef HAVE_DECL__SC_NPROCESSORS_CONF -# if 0 == HAVE_DECL__SC_NPROCESSORS_CONF -# undef HAVE_DECL__SC_NPROCESSORS_CONF -# else /* 0 != HAVE_DECL__SC_NPROCESSORS_CONF */ -# define HAS_DECL__SC_NPROCESSORS_CONF 1 -# endif /* 0 != HAVE_DECL__SC_NPROCESSORS_CONF */ -#endif /* HAVE_DECL__SC_NPROCESSORS_CONF */ - -#ifdef HAVE_DECL__SC_NPROC_ONLN -# if 0 == HAVE_DECL__SC_NPROC_ONLN -# undef HAVE_DECL__SC_NPROC_ONLN -# else /* 0 != HAVE_DECL__SC_NPROC_ONLN */ -# define HAS_DECL__SC_NPROC_ONLN 1 -# endif /* 0 != HAVE_DECL__SC_NPROC_ONLN */ -#endif /* HAVE_DECL__SC_NPROC_ONLN */ - -#ifdef HAVE_DECL__SC_CRAY_NCPU -# if 0 == HAVE_DECL__SC_CRAY_NCPU -# undef HAVE_DECL__SC_CRAY_NCPU -# else /* 0 != HAVE_DECL__SC_CRAY_NCPU */ -# define HAS_DECL__SC_CRAY_NCPU 1 -# endif /* 0 != HAVE_DECL__SC_CRAY_NCPU */ -#endif /* HAVE_DECL__SC_CRAY_NCPU */ - -#ifdef HAVE_DECL_CTL_HW -# if 0 == HAVE_DECL_CTL_HW -# undef HAVE_DECL_CTL_HW -# else /* 0 != HAVE_DECL_CTL_HW */ -# define HAS_DECL_CTL_HW 1 -# endif /* 0 != HAVE_DECL_CTL_HW */ -#endif /* HAVE_DECL_CTL_HW */ - -#ifdef HAVE_DECL_HW_NCPUONLINE -# if 0 == HAVE_DECL_HW_NCPUONLINE -# undef HAVE_DECL_HW_NCPUONLINE -# else /* 0 != HAVE_DECL_HW_NCPUONLINE */ -# define HAS_DECL_HW_NCPUONLINE 1 -# endif /* 0 != HAVE_DECL_HW_NCPUONLINE */ -#endif /* HAVE_DECL_HW_NCPUONLINE */ - -#ifdef HAVE_DECL_HW_AVAILCPU -# if 0 == HAVE_DECL_HW_AVAILCPU -# undef HAVE_DECL_HW_AVAILCPU -# else /* 0 != HAVE_DECL_HW_AVAILCPU */ -# define HAS_DECL_HW_AVAILCPU 1 -# endif /* 0 != HAVE_DECL_HW_AVAILCPU */ -#endif /* HAVE_DECL_HW_AVAILCPU */ - -#ifdef HAVE_DECL_HW_NCPU -# if 0 == HAVE_DECL_HW_NCPU -# undef HAVE_DECL_HW_NCPU -# else /* 0 != HAVE_DECL_HW_NCPU */ -# define HAS_DECL_HW_NCPU 1 -# endif /* 0 != HAVE_DECL_HW_NCPU */ -#endif /* HAVE_DECL_HW_NCPU */ - -#ifdef HAVE_DECL_CPU_SETSIZE -# if 0 == HAVE_DECL_CPU_SETSIZE -# undef HAVE_DECL_CPU_SETSIZE -# else /* 0 != HAVE_DECL_CPU_SETSIZE */ -# define HAS_DECL_CPU_SETSIZE 1 -# endif /* 0 != HAVE_DECL_CPU_SETSIZE */ -#endif /* HAVE_DECL_CPU_SETSIZE */ - #ifndef MHD_AUTH_DIGEST_DEF_TIMEOUT # define MHD_AUTH_DIGEST_DEF_TIMEOUT 90 #endif /* ! MHD_AUTH_DIGEST_DEF_TIMEOUT */ diff --git a/src/include/d_options.rec b/src/include/d_options.rec @@ -36,7 +36,8 @@ Comment: Set a callback to use for logging Type: struct MHD_DaemonOptionValueLog Argument1: MHD_LoggingCallback log_cb Description1: the callback to use for logging, -+ NULL to disable logging ++ NULL to disable logging. ++ The logging to stderr is enabled by default. Argument2: void *log_cb_cls Description2: the closure for the logging callback # Note: CG does not exactly like this... @@ -385,6 +386,24 @@ Comment: Disable #MHD_action_suspend() functionality. + You should only use this function if you do not use suspend functionality and need a generally minor boost in performance. + The suspend is not disallowed (suspend is allowed) by default. +Name: DISABLE_COOKIES +Value: 324 +Type: enum MHD_Bool +Comment: Disable cookies parsing. ++ ++ Disable automatic cookies processing if cookies are not used. ++ Cookies are automatically parsed by default. +CustomSetter: /* custom setter */ ++ /* The is not an easy for automatic generations */ ++ // TODO: remove options generator, put preprocessor directives to ++ // the first column ++ #ifdef MHD_SUPPORT_COOKIES ++ settings->disable_cookies = option->val.disable_cookies; ++ #else ++ if (MHD_NO != option->val.disable_cookies) ++ return MHD_SC_FEATURE_DISABLED; ++ #endif + # Notification callbacks Name: daemon_ready_callback diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h @@ -1,6 +1,6 @@ /* This file is part of GNU libmicrohttpd - Copyright (C) 2006-2024 Christian Grothoff, Karlson2k (Evgeny Grin) + Copyright (C) 2006-2025 Christian Grothoff, Karlson2k (Evgeny Grin) (and other contributing authors) GNU libmicrohttpd is free software; you can redistribute it and/or @@ -1471,7 +1471,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode MHD_SC_CONFIGURATION_UNEXPECTED_WM = 60022 , /** - * Parameter specified unknown socket poll syscall. + * Parameter specified unknown Sockets Polling Syscall (SPS). */ MHD_SC_CONFIGURATION_UNEXPECTED_SPS = 60023 , @@ -1632,13 +1632,13 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode * The type of the information is not available due to configuration * or state of the object. */ - MHD_SC_INFO_GET_TYPE_UNSUPPORTED = 60203 + MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE = 60203 , /** * The type of the information should be available for the object, but * cannot be provided due to some error or other reasons. */ - MHD_SC_INFO_GET_TYPE_UNAVAILALBE = 60204 + MHD_SC_INFO_GET_TYPE_UNOBTAINABLE = 60204 , /** * The type of the Digest Auth algorithm is unknown or not supported. @@ -4013,7 +4013,8 @@ MHD_D_OPTION_POLL_SYSCALL ( /** * Set a callback to use for logging * @param log_cb the callback to use for logging, - * NULL to disable logging + * NULL to disable logging. + * The logging to stderr is enabled by default. * @param log_cb_cls the closure for the logging callback * @return structure with the requested setting */ @@ -4400,6 +4401,18 @@ MHD_D_OPTION_DISALLOW_SUSPEND_RESUME ( ); /** + * Disable cookies parsing. + * +Disable automatic cookies processing if cookies are not used. + * Cookies are automatically parsed by default. + * @param value the value of the parameter * @return structure with the requested setting + */ +struct MHD_DaemonOptionAndValue +MHD_D_OPTION_DISABLE_COOKIES ( + enum MHD_Bool value + ); + +/** * Set a callback to be called for pre-start finalisation. * The specified callback will be called one time, after network initialisation, TLS pre-initialisation, but before the start of the internal threads (if allowed) @@ -8537,46 +8550,57 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * Exceptions are marked explicitly in the description. */ /** - * Get whether messages are supported. If supported then in debug - * mode messages can be printed to stderr or to external logger. + * Get whether messages are supported. If supported then messages can be + * printed to stderr or to an external logger. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_MESSAGES = 11 + MHD_LIB_INFO_FIXED_HAS_LOG_MESSAGES = 11 , /** - * Get whether MHD supports threads. + * Get whether detailed automatic HTTP reply messages are supported. + * If supported then automatic responses have bodies with text expalining + * the error details. + * Automatic responses are sent by MHD automatically when client is violating + * HTTP specification, for example, the request header has whitespace in + * header name or request's "Content-Length" header has non-number value. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_THREADS = 12 + MHD_LIB_INFO_FIXED_HAS_AUTO_REPLIES_BODIES = 12 , /** - * Get whether MHD was built with asserts enabled. - * Enabled only on special debug builds. + * Get whether MHD was built with debug asserts disabled. + * These asserts enabled only on special debug builds. * For debug builds the error log is always enabled. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_DEBUG = 13 + MHD_LIB_INFO_FIXED_IS_NON_DEBUG = 13 + , + /** + * Get whether MHD supports threads. + * The result is placed in @a v_bool member. + */ + MHD_LIB_INFO_FIXED_HAS_THREADS = 14 , /** * Get whether automatic parsing of HTTP Cookie header is supported. * If disabled, no #MHD_VK_COOKIE will be generated by MHD. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_COOKIE_PARSER = 14 + MHD_LIB_INFO_FIXED_HAS_COOKIE_PARSER = 15 , /** * Get whether postprocessor is supported. If supported then * #MHD_action_post_processor() can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_POST_PARSER = 15 + MHD_LIB_INFO_FIXED_HAS_POST_PARSER = 16 , /** * Get whether HTTP "Upgrade" is supported. * If supported then #MHD_action_upgrade() can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_UPGRADE = 16 + MHD_LIB_INFO_FIXED_HAS_UPGRADE = 17 , /** * Get whether HTTP Basic authorization is supported. If supported @@ -8584,7 +8608,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * and #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_BASIC_AUTH = 20 + MHD_LIB_INFO_FIXED_HAS_AUTH_BASIC = 20 , /** * Get whether HTTP Digest authorization is supported. If @@ -8594,7 +8618,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * #MHD_digest_auth_check() can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH = 21 + MHD_LIB_INFO_FIXED_HAS_AUTH_DIGEST = 21 , /** * Get whether the early version the Digest Authorization (RFC 2069) is @@ -8660,66 +8684,80 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * the toolchain. * Some of the features can be disabled or selected at build-time. */ /** - * Get supported sockets polling function/techniques. + * Get sockets polling functions/techniques supported by this MHD build. + * Some functions can be disabled (like epoll) in kernel, this is not + * checked. * The result is placed in @a v_polling member. */ - MHD_LIB_INFO_FIXED_TYPE_SOCKETS_POLLING = 50 + MHD_LIB_INFO_FIXED_TYPE_SOCKETS_POLLING = 60 , /** * Get whether aggregate FD external polling is supported. - * The result is placed in @a v_polling member. + * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_AGGREGATE_FD = 51 + MHD_LIB_INFO_FIXED_HAS_AGGREGATE_FD = 61 , /** - * Get whether IPv6 is supported on the platform and whether IPv6 without IPv4 + * Get whether IPv6 is supported on the platform and IPv6-only listen socket * can be used. * The result is placed in @a v_ipv6 member. * @note The platform may have disabled IPv6 at run-time, it is not checked * by this information type. */ - MHD_LIB_INFO_FIXED_TYPE_IPv6 = 52 + MHD_LIB_INFO_FIXED_TYPE_IPV6 = 62 , /** * Get whether TCP Fast Open is supported by MHD build. * If supported then option #MHD_D_O_TCP_FASTOPEN can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_TCP_FASTOPEN = 53 + MHD_LIB_INFO_FIXED_HAS_TCP_FASTOPEN = 64 , /** * Get whether MHD support automatic detection of bind port number. * @sa #MHD_D_O_BIND_PORT * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_AUTODETECT_BIND_PORT = 54 + MHD_LIB_INFO_FIXED_HAS_AUTODETECT_BIND_PORT = 65 , /** * Get whether MHD use system's sendfile() function to send * file-FD based responses over non-TLS connections. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_SENDFILE = 55 + MHD_LIB_INFO_FIXED_HAS_SENDFILE = 66 + , + /** + * Get whether MHD supports automatic SIGPIPE suppression within internal + * events loop (MHD's managed threads). + * If SIGPIPE suppression is not supported, application must handle + * SIGPIPE signal by itself whem using MHD with internal events loop. + * If the platform does not have SIGPIPE the result is #MHD_YES. + * The result is placed in @a v_bool member. + */ + MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_INT = 80 , /** - * Get whether MHD supports automatic SIGPIPE suppression. + * Get whether MHD supports automatic SIGPIPE suppression when used with + * extenal events loop (in application thread). * If SIGPIPE suppression is not supported, application must handle - * SIGPIPE signal by itself. + * SIGPIPE signal by itself whem using MHD with external events loop. + * If the platform does not have SIGPIPE the result is #MHD_YES. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE = 60 + MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_EXT = 81 , /** * Get whether MHD sets names on generated threads. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_THREAD_NAMES = 61 + MHD_LIB_INFO_FIXED_HAS_THREAD_NAMES = 82 , /** * Get the type of supported inter-thread communication. * The result is placed in @a v_itc member. */ - MHD_LIB_INFO_FIXED_TYPE_ITC = 62 + MHD_LIB_INFO_FIXED_TYPE_ITC = 83 , /** * Get whether reading files beyond 2 GiB boundary is supported. @@ -8728,7 +8766,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * limited to 2 GiB. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_LARGE_FILE = 63 + MHD_LIB_INFO_FIXED_HAS_LARGE_FILE = 84 , /* * Platform-dependent features, some set on startup and some are @@ -8746,9 +8784,9 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed , /** * Get whether password encrypted private key for HTTPS daemon is - * supported. If supported then option - * #MHD_D_OPTION_TLS_KEY_CERT can be used with non-NULL @a mem_pass - * The result is placed in @a v_bool member. + * supported. If supported then option #MHD_D_OPTION_TLS_KEY_CERT + * can be used with non-NULL @a mem_pass. + * The result is placed in @a v_tls member. */ MHD_LIB_INFO_FIXED_HAS_TLS_KEY_PASSWORD = 102 , @@ -8774,6 +8812,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedDigestAlgoType , /** * The algorithm is implemented by MHD internal code. + * MHD implementation of hashing can never fail. */ MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_BUILT_IN = 1 , @@ -8824,9 +8863,10 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedIPv6Type MHD_LIB_INFO_FIXED_IPV6_TYPE_DUAL_ONLY = 1 , /** - * IPv6 is supported as IPv6-only or as "dual stack". + * IPv6 can be used as IPv6-only (without getting IPv4 incoming connections). + * The platform may support "dual stack" too. */ - MHD_LIB_INFO_FIXED_IPV6_TYPE_BOTH = 2 + MHD_LIB_INFO_FIXED_IPV6_TYPE_IPV6_PURE = 2 }; /** @@ -8836,21 +8876,27 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedIPv6Type enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedITCType { /** + * No ITC used. + * This value is returned if MHD is built without threads support + */ + MHD_LIB_INFO_FIXED_ITC_TYPE_NONE = 0 + , + /** * The pair of sockets are used as inter-thread communication. * The is the least efficient method of communication. */ - MHD_LIB_INFO_FIXED_ITC_TYPE_SOCKETPAIR = 0 + MHD_LIB_INFO_FIXED_ITC_TYPE_SOCKETPAIR = 1 , /** * The pipe is used as inter-thread communication. */ - MHD_LIB_INFO_FIXED_ITC_TYPE_PIPE = 1 + MHD_LIB_INFO_FIXED_ITC_TYPE_PIPE = 2 , /** * The EventFD is used as inter-thread communication. * This is the most efficient method of communication. */ - MHD_LIB_INFO_FIXED_ITC_TYPE_EVENTFD = 2 + MHD_LIB_INFO_FIXED_ITC_TYPE_EVENTFD = 3 }; @@ -8893,11 +8939,14 @@ union MHD_LibInfoFixedData */ enum MHD_Bool v_bool; /** - * The type of digest algorithm implemetation + * The type of digest algorithm implementation */ enum MHD_LibInfoFixedDigestAlgoType v_d_algo; /** - * The types of the sockets polling functions/techniques supported + * The types of the sockets polling functions/techniques supported by this MHD + * build. + * Some functions can be disabled (like epoll) in kernel, this is not + * checked. */ struct MHD_LibInfoFixedPollingFunc v_polling; /** @@ -8918,23 +8967,30 @@ union MHD_LibInfoFixedData * Get fixed information about MHD that is not changed at run-time. * The returned information can be cached by application as it will be not * changed at run-time. + * + * For any valid @a info_type the only possible returned error value is + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL. If the buffer is large enough and + * the requested type of information is valid, the function always succeeds + * and returns #MHD_SC_OK. + * * The wrapper macro #MHD_lib_get_info_fixed() could be more convenient. * * @param info_type the type of requested information - * @param[out] return_data the pointer to union to be set to the required - * information - * @param return_data_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_lib_get_info_fixed_sz (enum MHD_LibInfoFixed info_type, - union MHD_LibInfoFixedData *return_data, - size_t return_data_size) -MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2) -MHD_FN_PURE_; + union MHD_LibInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2); /** * Get fixed information about MHD that is not changed at run-time. @@ -8942,13 +8998,65 @@ MHD_FN_PURE_; * changed at run-time. * * @param info the type of requested information - * @param[out] data the pointer to union to set to the required information + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * or other error code * @ingroup specialized */ -#define MHD_lib_get_info_fixed(info,data) \ - MHD_lib_get_info_fixed_sz ((info),(data),sizeof(*(data))) +#define MHD_lib_get_info_fixed(info,output_buf) \ + MHD_lib_get_info_fixed_sz ((info),(output_buf),sizeof(*(output_buf))) + +#ifndef MHD_NO_STATIC_INLINE + +/* + * A helper below can be used in a simple check preventing use of downgraded + * library version. + * As new library version may introduce new functionality, and the application + * may detect some functionality available at application build-time, use of + * previous versions may lead to run-time failures. + * To prevent run-time failures, application may use a check like: + + if (MHD_lib_get_info_ver_num() < ((uint_fast32_t) MHD_VERSION)) + handle_init_failure(); + + */ +/** + * Get the library version number. + * @return the library version number. + */ +MHD_STATIC_INLINE_ MHD_FN_PURE_ uint_fast32_t +MHD_lib_get_info_ver_num (void) +{ + union MHD_LibInfoFixedData data; + data.v_uint32 = 0; /* Not really necessary */ + (void) MHD_lib_get_info_fixed (MHD_LIB_INFO_FIXED_VERSION_NUM, \ + &data); /* Never fail */ + return data.v_uint32; +} + + +MHD_STATIC_INLINE_END_ +/** + * Get the fixed boolean information about the library. + * @param info the type of requested information, must be the value with + * the boolean resulting data; behaviour is undefined if other + * types of requested information is used + * @return #MHD_YES or #MHD_NO + */ +MHD_STATIC_INLINE_ MHD_FN_PURE_ enum MHD_Bool +MHD_lib_get_fixed_info_bool (enum MHD_LibInfoFixed info_type) +{ + union MHD_LibInfoFixedData data; + (void) MHD_lib_get_info_fixed (info_type, \ + &data); /* Never fail */ + return data.v_bool; +} + + +MHD_STATIC_INLINE_END_ +#endif /* ! MHD_NO_STATIC_INLINE */ /** * Types of information about MHD, @@ -8960,22 +9068,37 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoDynamic /* * Basic MHD information * */ /** - * Get whether MHD was successfully initialised. - * The result is #MHD_NO when the library has not been yet initialised or - * when library has been de-initialised. - * Under normal conditions the result must be always #MHD_YES when requested - * by application. + * Get whether MHD has been successfully fully initialised. + * MHD uses lazy initialisation: a minimal initialisation is perfomed at + * startup, complete initialisation is perfomed when any daemon is created + * (or called other function which requires full initialisation). + * The result is #MHD_NO when the library has been not yet initialised + * completely since startup. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_DYNAMIC_INITED = 0 + MHD_LIB_INFO_DYNAMIC_INITED_FULLY_ONCE = 0 + , + /** + * Get whether MHD has been successfully fully initialised. + * MHD uses lazy initialisation: a minimal initialisation is perfomed at + * startup, complete initialisation is perfomed when any daemon is created + * (or called other function which requires full initialisation). + * The result is #MHD_YES if library is initialised state now (meaning + * that at least one deamon is created and not destroyed or some function + * required full initialisation is running). + * The result is placed in @a v_bool member. + */ + MHD_LIB_INFO_DYNAMIC_INITED_FULLY_NOW = 1 , /** * Get whether HTTPS and which types of TLS backend(s) currently available. - * If any MHD daemonis active (created and not destroyed, not nessesary + * If any MHD daemons active (created and not destroyed, not necessary * running) the result reflects the current backends availability. - * If no MHD daemon is active, then this function would try to temporarly + * If no MHD daemon is active, then this function would try to temporarily * enable backends to check for their availability. + * If global library initialisation failed, the function returns + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE error code. * The result is placed in @a v_tls member. */ MHD_LIB_INFO_DYNAMIC_TYPE_TLS = 100 @@ -9020,31 +9143,37 @@ union MHD_LibInfoDynamicData * The wrapper macro #MHD_lib_get_info_dynamic() could be more convenient. * * @param info_type the type of requested information - * @param[out] return_data the pointer to union to be set to the required - * information - * @param return_data_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * or other error code * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode -MHD_lib_get_info_dynamic_sz (enum MHD_LibInfoDynamic info_type, - union MHD_LibInfoDynamicData *return_data, - size_t return_data_size) -MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2); +MHD_lib_get_info_dynamic_sz ( + enum MHD_LibInfoDynamic info_type, + union MHD_LibInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2); /** * Get dynamic information about MHD that may be changed at run-time. * * @param info the type of requested information - * @param[out] data the pointer to union to set to the required information + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * or other error code * @ingroup specialized */ -#define MHD_lib_get_info_dynamic(info,data) \ - MHD_lib_get_info_fixed_sz ((info),(data),sizeof(*(data))) +#define MHD_lib_get_info_dynamic(info,output_buf) \ + MHD_lib_get_info_fixed_sz ((info),(output_buf),sizeof(*(output_buf))) /** @@ -9057,28 +9186,54 @@ enum MHD_DaemonInfoFixedType { /** - * Request the file descriptor for the listening socket. + * Get the port number of daemon's listen socket. + * Note: if port '0' (auto port) was specified for #MHD_D_OPTION_BIND_PORT(), + * returned value will be the real port number. + * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon + * does not have listening socket or if listening socket is non-IP. + * The function returns #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the port number + * detection failed or not supported by the platform. + * If the function succeed, the returned port number is never zero. + * The result is placed in @a v_port member. + */ + MHD_DAEMON_INFO_FIXED_BIND_PORT = 1 + , + /** + * Get the file descriptor for the listening socket. + * The provided socket must be used as 'read-only': only select() or similar + * functions should be used. Any modifications (changing socket attributes, + * calling accept(), closing it etc.) will lead to undefined behaviour. + * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon + * does not have listening socket. * The result is placed in @a v_socket member. */ - MHD_DAEMON_INFO_FIXED_LISTEN_SOCKET = 1 + MHD_DAEMON_INFO_FIXED_LISTEN_SOCKET = 2 , /** - * Request the file descriptor for the single FD that triggered when + * Get the file descriptor for the single FD that triggered when * any MHD event happens. * This FD can be watched as aggregate indicator for all MHD events. + * The provided socket must be used as 'read-only': only select() or similar + * functions should be used. Any modifications (changing socket attributes, + * calling accept() closing it etc.) will lead to undefined behaviour. + * The function returns #MHD_SC_INFO_GET_TYPE_NOT_SUPP_BY_BUILD if the library + * does not support mode with agregate FD. + * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon + * is not configured to use this mode. * The result is placed in @a v_fd member. */ - MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD + MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD = 3 , /** - * Request the port number of daemon's listen socket. - * No extra arguments should be passed. - * Note: if port '0' was specified for #MHD_D_OPTION_BIND_PORT(), returned - * value will be real port number. - * The result is placed in @a v_port member. + * Get the TLS backend used by the daemon. + * The value #MHD_TLS_BACKEND_ANY is never set in the returned data. + * The value #MHD_TLS_BACKEND_NONE is set if the daemon does not use TLS. + * If MHD built without TLS support then #MHD_TLS_BACKEND_NONE is always set. + * The result is placed in @a v_tls_backend member. */ - MHD_DAEMON_INFO_FIXED_BIND_PORT + MHD_DAEMON_INFO_FIXED_TLS_TYPE = 100 , + /* * Sentinel * */ /** * The sentinel value. @@ -9112,6 +9267,11 @@ union MHD_DaemonInfoFixedData uint_least16_t v_port; /** + * The TLS backend + */ + enum MHD_TlsBackend v_tls_backend; + + /** * Unused member. * Help enforcing future-proof alignment of the union. * Do not use. @@ -9128,22 +9288,36 @@ union MHD_DaemonInfoFixedData * * @param daemon the daemon to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf pointer to union where requested information will + * be stored + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_TOO_EARLY if the daemon has not been started yet, + * #MHD_SC_TOO_LATE if the daemon is being stopped or has failed, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * daemon due to the daemon + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the daemon, but cannot be provided + * due to some error or other + * reasons, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode -MHD_daemon_get_info_fixed_sz (struct MHD_Daemon *daemon, - enum MHD_DaemonInfoFixedType info_type, - union MHD_DaemonInfoFixedData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; +MHD_daemon_get_info_fixed_sz ( + struct MHD_Daemon *MHD_RESTRICT daemon, + enum MHD_DaemonInfoFixedType info_type, + union MHD_DaemonInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** * Obtain fixed information about the given daemon. @@ -9152,15 +9326,27 @@ MHD_FN_PURE_; * * @param daemon the daemon to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will + * @param[out] output_buf pointer to union where requested information will * be stored * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_TOO_EARLY if the daemon has not been started yet, + * #MHD_SC_TOO_LATE if the daemon is being stopped or has failed, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * daemon due to the daemon + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the daemon, but cannot be provided + * due to some error or other + * reasons, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_daemon_get_info_fixed(daemon,info_type,return_value) \ - MHD_daemon_get_info_fixed_sz ((daemon), (info_type), (return_value), \ - sizeof(*(return_value))) +#define MHD_daemon_get_info_fixed(daemon,info_type,output_buf) \ + MHD_daemon_get_info_fixed_sz ((daemon), (info_type), (output_buf), \ + sizeof(*(output_buf))) /** @@ -9171,7 +9357,7 @@ MHD_FN_PURE_; enum MHD_DaemonInfoDynamicType { /** - * The the maximum number of microseconds from the current moment until + * The the maximum number of millisecond from the current moment until * the mandatory call of the daemon data processing function (like * #MHD_deamon_process_reg_events(), #MHD_daemon_process_blocking()). * If resulting value is zero then daemon data processing function should be @@ -9180,19 +9366,17 @@ enum MHD_DaemonInfoDynamicType * Available only for daemons stated in #MHD_WM_EXTERNAL_PERIODIC, * #MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL, #MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE * or #MHD_WM_EXTERNAL_SINGLE_FD_WATCH modes. + * The function return #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if daemon has + * internal handling of events (internal threads). * The result is placed in @a v_uint64 member. */ MHD_DAEMON_INFO_DYNAMIC_MAX_TIME_TO_WAIT = 1 , /** - * Request the number of current connections handled by the daemon. - * No extra arguments should be passed. - * Note: when using MHD without internal threads, this type of request - * could be used only when MHD is is not processing the connection data - * in other thread at the same time. - * The result is placed in @a v_uint member. + * Check whether the daemon has any connected network clients. + * The result is placed in @a v_bool member. */ - MHD_DAEMON_INFO_DYNAMIC_CURRENT_CONNECTIONS = 20 + MHD_DAEMON_INFO_DYNAMIC_HAS_CONNECTIONS = 20 , /* * Sentinel * */ /** @@ -9210,14 +9394,14 @@ enum MHD_DaemonInfoDynamicType union MHD_DaemonInfoDynamicData { /** - * Unsigned 64 bits integer value. + * The boolean value */ - uint_fast64_t v_uint64; + enum MHD_Bool v_bool; /** - * Unsigned integer value. + * Unsigned 64 bits integer value. */ - unsigned int v_uint; + uint_fast64_t v_uint64; /** * Unused member. @@ -9235,20 +9419,35 @@ union MHD_DaemonInfoDynamicData * * @param daemon the daemon to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_TOO_EARLY if the daemon has not been started yet, + * #MHD_SC_TOO_LATE if the daemon is being stopped or has failed, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * daemon due to the daemon + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the daemon, but cannot be provided + * due to some error or other + * reasons, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode -MHD_daemon_get_info_dynamic_sz (struct MHD_Daemon *daemon, - enum MHD_DaemonInfoDynamicType info_type, - union MHD_DaemonInfoDynamicData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) +MHD_daemon_get_info_dynamic_sz ( + struct MHD_Daemon *MHD_RESTRICT daemon, + enum MHD_DaemonInfoDynamicType info_type, + union MHD_DaemonInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -9257,15 +9456,27 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); * * @param daemon the daemon to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_TOO_EARLY if the daemon has not been started yet, + * #MHD_SC_TOO_LATE if the daemon is being stopped or has failed, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * daemon due to the daemon + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the daemon, but cannot be provided + * due to some error or other + * reasons, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_daemon_get_info_dynamic(daemon,info_type,return_value) \ - MHD_daemon_get_info_dynamic_sz ((daemon), (info_type), (return_value), \ - sizeof(*(return_value))) +#define MHD_daemon_get_info_dynamic(daemon,info_type,output_buf) \ + MHD_daemon_get_info_dynamic_sz ((daemon), (info_type), (output_buf), \ + sizeof(*(output_buf))) /** @@ -9275,14 +9486,25 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); enum MHD_ConnectionInfoFixedType { /** - * Obtain IP address of the client. - * The result is placed in @a vs_sa member. + * Get the network address of the client. + * If the connection does not have known remote address (was not provided + * by the system or by the application in case of externally added + * connection) then error code #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE is + * returned if connection is IP type or unknown type or error code + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if connection type is non-IP. + * The @a sa pointer is never NULL if the function succeed (#MHD_SC_OK + * returned). + * The result is placed in @a v_sa_info member. * @ingroup request */ MHD_CONNECTION_INFO_FIXED_CLIENT_ADDRESS = 1 , /** - * Request the file descriptor for the connection socket. + * Get the file descriptor for the connection socket. + * The provided socket must be used as 'read-only': only select() or similar + * functions should be used. Any modifications (changing socket attributes, + * calling send() or recv(), closing it etc.) will lead to undefined + * behaviour. * The result is placed in @a v_fd member. * @ingroup request */ @@ -9295,6 +9517,19 @@ enum MHD_ConnectionInfoFixedType */ MHD_CONNECTION_INFO_FIXED_DAEMON = 20 , + /** + * Returns the pointer to a variable pointing to connection-specific + * application context data that was (possibly) set during + * a #MHD_NotifyConnectionCallback or provided via @a connection_cntx + * parameter of #MHD_daemon_add_connection(). + * By using provided pointer application may get or set the pointer to + * any data specific for the particular connection. + * The result is placed in @a v_ppvoid member. + * @ingroup request + */ + MHD_CONNECTION_INFO_FIXED_SOCKET_CONTEXT = 30 + , + /* * Sentinel * */ /** * The sentinel value. @@ -9304,6 +9539,18 @@ enum MHD_ConnectionInfoFixedType MHD_CONNECTION_INFO_FIXED_SENTINEL = 65535 }; +struct MHD_ConnInfoFixedSockAddr +{ + /** + * The size of the @a sa + */ + size_t sa_size; + + /** + * Socket Address type + */ + const struct sockaddr *sa; +}; /** * Information about a connection. @@ -9314,7 +9561,7 @@ union MHD_ConnectionInfoFixedData /** * Socket Address type */ - const struct sockaddr *vs_sa; + struct MHD_ConnInfoFixedSockAddr v_sa_info; /** * Socket type @@ -9325,6 +9572,11 @@ union MHD_ConnectionInfoFixedData * Daemon handler type */ struct MHD_Daemon *v_daemon; + + /** + * The pointer to pointer to the data + */ + void **v_ppvoid; }; @@ -9335,23 +9587,34 @@ union MHD_ConnectionInfoFixedData * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_connection_get_info_fixed_sz ( - struct MHD_Connection *connection, + struct MHD_Connection *MHD_RESTRICT connection, enum MHD_ConnectionInfoFixedType info_type, - union MHD_ConnectionInfoFixedData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; + union MHD_ConnectionInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -9360,16 +9623,25 @@ MHD_FN_PURE_; * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_connection_get_info_fixed(connection,info_type,return_value) \ - MHD_connection_get_info_fixed_sz ((connection),(info_type),(return_value \ - ), \ - sizeof(*(return_value))) +#define MHD_connection_get_info_fixed(connection,info_type,output_buf) \ + MHD_connection_get_info_fixed_sz ((connection),(info_type), \ + (output_buf), sizeof(*(output_buf))) /** @@ -9380,13 +9652,20 @@ enum MHD_ConnectionInfoDynamicType { /** * Get current version of HTTP protocol used for connection. + * If connection is handling HTTP/1.x requests the function may return + * error code #MHD_SC_TOO_EARLY if the full request line has not been received + * yet for the current request. * The result is placed in @a v_http_ver member. * @ingroup request */ MHD_CONNECTION_INFO_DYNAMIC_HTTP_VER = 1 , /** - * Get connection timeout. + * Get connection timeout value. + * This is the total number of seconds after which the idle connection is + * automatically disconnected. + * Note: the value set is NOT the number of seconds left before automatic + * disconnection. * The result is placed in @a v_uint member. * @ingroup request */ @@ -9400,26 +9679,27 @@ enum MHD_ConnectionInfoDynamicType MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_SUSPENDED = 11 , /** - * Returns the connection-specific application context data that was - * (possibly) set during a #MHD_NotifyConnectionCallback or provided via - * @a connection_cntx parameter of #MHD_daemon_add_connection(). - * The result is placed in @a v_pvoid member. - */ - MHD_CONNECTION_INFO_DYNAMIC_SOCKET_CONTEXT = 20 - , - /** * Get current version of TLS transport protocol used for connection + * If plain TCP connection is used then #MHD_TLS_VERSION_NO_TLS set in + * the data. + * It TLS handshake is not yet finished then error code #MHD_SC_TOO_EARLY is + * returned. If TLS has failed or being closed then #MHD_SC_TOO_LATE error + * code is returned. + * If TLS version cannot be detected for any reason then error code + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE is returned. * The result is placed in @a v_tls_ver member. * @ingroup request */ - MHD_CONNECTION_INFO_DYNAMIC_TLS_VER = 1 + MHD_CONNECTION_INFO_DYNAMIC_TLS_VER = 105 , /** - * Get the GnuTLS session handle. - * The result is placed in @a v_gnutls_session member. + * Get the TLS backend session handle. + * If plain TCP connection is used then the function returns error code + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE. + * The result is placed in @a v_tls_session member. * @ingroup request */ - MHD_CONNECTION_INFO_DYNAMIC_GNUTLS_SESSION = 40 + MHD_CONNECTION_INFO_DYNAMIC_TLS_SESSION = 140 , /* * Sentinel * */ @@ -9476,6 +9756,35 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_TlsVersion }; /** + * Connection TLS session information. + * Only one member is valid. Use #MHD_DAEMON_INFO_FIXED_TLS_TYPE to find out + * which member should be used. + */ +union MHD_ConnInfoDynamicTlsSess +{ + /* Include <gnutls/gnutls.h> before this header to get a better type safety */ + /** + * GnuTLS session handle, of type "gnutls_session_t". + */ +#if defined(GNUTLS_VERSION_MAJOR) && GNUTLS_VERSION_MAJOR >= 3 + gnutls_session_t v_gnutls_session; +#else + void * /* gnutls_session_t */ v_gnutls_session; +#endif + + /* Include <openssl/types.h> or <openssl/crypto.h> before this header to get + a better type safety */ + /** + * OpenSSL session handle, of type "SSL*". + */ +#if defined(OPENSSL_TYPES_H) && OPENSSL_VERSION_MAJOR >= 3 + SSL *v_openssl_session; +#else + void /* SSL */ *v_openssl_session; +#endif +}; + +/** * Information about a connection. */ union MHD_ConnectionInfoDynamicData @@ -9496,25 +9805,16 @@ union MHD_ConnectionInfoDynamicData enum MHD_Bool v_bool; /** - * The pointer to void type - */ - void *v_pvoid; - - /** * The TLS version */ enum MHD_TlsVersion v_tls_ver; - /* Include <gnutls/gnutls.h> before this header to get a better type safety */ /** - * GnuTLS session handle, of type "gnutls_session_t". + * Connection TLS session information. + * Only one member is valid. Use #MHD_DAEMON_INFO_FIXED_TLS_TYPE to find out + * which member should be used. */ -#if defined(GNUTLS_VERSION_MAJOR) && GNUTLS_VERSION_MAJOR >= 3 - gnutls_session_t -#else - void * /* gnutls_session_t */ -#endif - v_gnutls_session; + union MHD_ConnInfoDynamicTlsSess v_tls_session; }; /** @@ -9525,21 +9825,37 @@ union MHD_ConnectionInfoDynamicData * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the connection has not reached yet required + * state, + * #MHD_SC_TOO_LATE if the connection is already in state where + * the requested information is not available, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_connection_get_info_dynamic_sz ( - struct MHD_Connection *connection, + struct MHD_Connection *MHD_RESTRICT connection, enum MHD_ConnectionInfoDynamicType info_type, - union MHD_ConnectionInfoDynamicData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) + union MHD_ConnectionInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); @@ -9549,16 +9865,29 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the connection has not reached yet required + * state, + * #MHD_SC_TOO_LATE if the connection is already in state where + * the requested information is not available, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_connection_get_info_dynamic(connection,info_type,return_value) \ - MHD_connection_get_info_dynamic_sz ((connection),(info_type),( \ - return_value), \ - sizeof(*(return_value))) +#define MHD_connection_get_info_dynamic(connection,info_type,output_buf) \ + MHD_connection_get_info_dynamic_sz ((connection),(info_type), \ + (output_buf),sizeof(*(output_buf))) /** @@ -9568,20 +9897,21 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); enum MHD_FIXED_ENUM_APP_SET_ MHD_StreamInfoFixedType { /** - * Get the `struct MHD_Connection *` responsible for managing this stream. - * The result is placed in @a v_connection member. + * Get the `struct MHD_Daemon *` responsible for managing connection which + * is responsible for this stream. + * The result is placed in @a v_daemon member. * @ingroup request */ - MHD_STREAM_INFO_FIXED_CONNECTION = 1 + MHD_STREAM_INFO_FIXED_DAEMON = 20 , /** - * Get the `struct MHD_Daemon *` responsible for managing connection which - * is responsible for this stream. - * The result is placed in @a v_daemon member. + * Get the `struct MHD_Connection *` responsible for managing this stream. + * The result is placed in @a v_connection member. * @ingroup request */ - MHD_STREAM_INFO_FIXED_DAEMON = 2 + MHD_STREAM_INFO_FIXED_CONNECTION = 21 , + /* * Sentinel * */ /** * The sentinel value. @@ -9615,23 +9945,25 @@ union MHD_StreamInfoFixedData * * @param stream the stream to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_stream_get_info_fixed_sz ( - struct MHD_Stream *stream, + struct MHD_Stream *MHD_RESTRICT stream, enum MHD_StreamInfoFixedType info_type, - union MHD_StreamInfoFixedData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; + union MHD_StreamInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -9640,15 +9972,16 @@ MHD_FN_PURE_; * * @param stream the stream to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_stream_get_info_fixed(stream,info_type,return_value) \ - MHD_stream_get_info_fixed_sz ((stream),(info_type),(return_value), \ - sizeof(*(return_value))) +#define MHD_stream_get_info_fixed(stream,info_type,output_buf) \ + MHD_stream_get_info_fixed_sz ((stream),(info_type),(output_buf), \ + sizeof(*(output_buf))) /** @@ -9659,11 +9992,12 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_StreamInfoDynamicType { /** * Get the `struct MHD_Request *` for current request processed by the stream. - * If no request is being processed, the resulting pointer is NULL. + * If no request is being processed, the error code #MHD_SC_TOO_EARLY is + * returned. * The result is placed in @a v_request member. * @ingroup request */ - MHD_STREAM_INFO_DYNAMIC_REQUEST = 1 + MHD_STREAM_INFO_DYNAMIC_REQUEST = 20 , /* * Sentinel * */ @@ -9695,21 +10029,25 @@ union MHD_StreamInfoDynamicData * * @param stream the stream to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the stream has not reached yet required state, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_stream_get_info_dynamic_sz ( - struct MHD_Stream *stream, + struct MHD_Stream *MHD_RESTRICT stream, enum MHD_StreamInfoDynamicType info_type, - union MHD_StreamInfoDynamicData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) + union MHD_StreamInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); @@ -9719,15 +10057,17 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); * * @param stream the stream to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the stream has not reached yet required state, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_stream_get_info_dynamic(stream,info_type,return_value) \ - MHD_stream_get_info_dynamic_sz ((stream),(info_type),(return_value), \ - sizeof(*(return_value))) +#define MHD_stream_get_info_dynamic(stream,info_type,output_buf) \ + MHD_stream_get_info_dynamic_sz ((stream),(info_type),(output_buf), \ + sizeof(*(output_buf))) /** @@ -9737,38 +10077,51 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoFixedType { /** - * Return which stream the request is associated with. - * The result is placed in @a v_stream member. + * Get the version of HTTP protocol used for the request. + * If request line has not been fully received yet then #MHD_SC_TOO_EARLY + * error code is returned. + * The result is placed in @a v_http_ver member. + * @ingroup request */ - MHD_REQUEST_INFO_FIXED_STREAM = 1 + MHD_REQUEST_INFO_FIXED_HTTP_VER = 1 , /** - * Return which connection is associated with the stream which is associated - * with the request. - * The result is placed in @a v_connection member. + * Get the HTTP method used for the request (as a enum). + * The result is placed in @a v_http_method member. + * @sa #MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STR + * @ingroup request */ - MHD_REQUEST_INFO_FIXED_CONNECTION = 2 + MHD_REQUEST_INFO_FIXED_HTTP_METHOD = 2 , /** * Return MHD daemon to which the request belongs to. * The result is placed in @a v_daemon member. */ - MHD_REQUEST_INFO_FIXED_DAEMON = 3 + MHD_REQUEST_INFO_FIXED_DAEMON = 20 , /** - * Get the version of HTTP protocol used for the request. - * The result is placed in @a v_http_ver member. - * @ingroup request + * Return which connection is associated with the stream which is associated + * with the request. + * The result is placed in @a v_connection member. */ - MHD_REQUEST_INFO_FIXED_HTTP_VER = 4 + MHD_REQUEST_INFO_FIXED_CONNECTION = 21 , /** - * Get the HTTP method used for the request (as a enum). - * The result is placed in @a v_http_method member. - * @sa #MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STR + * Return which stream the request is associated with. + * The result is placed in @a v_stream member. + */ + MHD_REQUEST_INFO_FIXED_STREAM = 22 + , + /** + * Returns the pointer to a variable pointing to request-specific + * application context data. The same data is provided for + * #MHD_EarlyUriLogCallback and #MHD_RequestTerminationCallback. + * By using provided pointer application may get or set the pointer to + * any data specific for the particular request. + * The result is placed in @a v_ppvoid member. * @ingroup request */ - MHD_REQUEST_INFO_FIXED_HTTP_METHOD = 5 + MHD_REQUEST_INFO_FIXED_APP_CONTEXT = 30 , /* * Sentinel * */ @@ -9811,6 +10164,11 @@ union MHD_RequestInfoFixedData * The HTTP method type. */ enum MHD_HTTP_Method v_http_method; + + /** + * The pointer to pointer to the data. + */ + void **v_ppvoid; }; /** @@ -9820,23 +10178,27 @@ union MHD_RequestInfoFixedData * * @param request the request to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the request processing has not reached yet + * the required state, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_request_get_info_fixed_sz ( struct MHD_Request *MHD_RESTRICT request, enum MHD_RequestInfoFixedType info_type, - union MHD_RequestInfoFixedData *MHD_RESTRICT return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; + union MHD_RequestInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -9845,15 +10207,18 @@ MHD_FN_PURE_; * * @param request the request to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the request processing has not reached yet + * the required state, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_request_get_info_fixed(request,info_type,return_value) \ - MHD_request_get_info_fixed_sz ((request), (info_type), (return_value), \ - sizeof(*(return_value))) +#define MHD_request_get_info_fixed(request,info_type,output_buf) \ + MHD_request_get_info_fixed_sz ((request), (info_type), (output_buf), \ + sizeof(*(output_buf))) /** @@ -9897,11 +10262,19 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType MHD_REQUEST_INFO_DYNAMIC_NUMBER_COOKIES = 4 , /** + * Return length of the client's HTTP request header. + * This is a total raw size of the header (after TLS decipher if any) + * The result is placed in @a v_sizet member. + * @ingroup request + */ + MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE = 5 + , + /** * Get the number of decoded POST entries in the request. * The result is placed in @a v_sizet member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS = 5 + MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS = 6 , /** * Get whether the upload content is present in the request. @@ -9913,13 +10286,21 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType MHD_REQUEST_INFO_DYNAMIC_UPLOAD_PRESENT = 10 , /** + * Get whether the chunked upload content is present in the request. + * The result is #MHD_YES if chunked upload content is present. + * The result is placed in @a v_bool member. + * @ingroup request + */ + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_CHUNKED = 11 + , + /** * Get the total content upload size. * Resulted in zero if no content upload or upload content size is zero, * #MHD_SIZE_UNKNOWN if size is not known (chunked upload). * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL = 11 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL = 12 , /** * Get the total size of the content upload already received from the client. @@ -9928,7 +10309,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED = 12 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED = 13 , /** * Get the total size of the content upload left to be received from @@ -9937,7 +10318,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_RECIEVE = 13 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_RECIEVE = 14 , /** * Get the total size of the content upload already processed (upload callback @@ -9947,7 +10328,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_PROCESSED = 14 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_PROCESSED = 15 , /** * Get the total size of the content upload left to be processed. @@ -9959,26 +10340,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_PROCESS = 15 - , - /** - * Return length of the client's HTTP request header. - * This is a total raw size of the header (after TLS decipher if any) - * The result is placed in @a v_sizet member. - * @ingroup request - */ - MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE = 21 - , - /** - * Returns the request-specific pointer to a `void *`. The pointer obtainable - * by this pointer is the same as provided for #MHD_EarlyUriLogCallback and - * #MHD_RequestTerminationCallback. - * By using provided pointer application may get or set the pointer to - * any data specific for the particular request. - * The result is placed in @a v_ppvoid member. - * @ingroup request - */ - MHD_REQUEST_INFO_DYNAMIC_APP_CONTEXT = 31 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_PROCESS = 16 , /** * Returns pointer to information about username in client's digest auth @@ -10046,10 +10408,6 @@ union MHD_RequestInfoDynamicData * The unsigned 64 bits integer */ uint_fast64_t v_uint64; - /** - * The pointer to pointer to the data. - */ - void **v_ppvoid; /** * The information about client provided username for digest auth @@ -10073,6 +10431,9 @@ union MHD_RequestInfoDynamicData /** * Obtain dynamic information about the given request. * This information may be changed during the lifetime of the request. + * Most of the data provided is available only when the request line or complete + * request headers are processed and not available if responding has been + * started. * The wrapper macro #MHD_request_get_info_dynamic() could be more convenient. * * Any pointers in the returned data are valid until any MHD_Action or @@ -10081,55 +10442,77 @@ union MHD_RequestInfoDynamicData * * @param request the request to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a return_value_size is too small, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is + * not recognized by MHD, * #MHD_SC_TOO_LATE if request is already being closed or the response * is being sent * #MHD_SC_TOO_EARLY if requested data is not yet ready (for example, * headers are not yet received), - * #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is - * not recognized by MHD, * #MHD_SC_FEATURE_DISABLED if requested functionality is not supported * by this MHD build, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, * #MHD_SC_AUTH_ABSENT if request does not have particular Auth data, * #MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA if connection memory pool * has no space to put decoded * authentication data, * #MHD_SC_REQ_AUTH_DATA_BROKEN if the format of authentication data is * incorrect or broken, - * other error code otherwise + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_request_get_info_dynamic_sz ( struct MHD_Request *MHD_RESTRICT request, enum MHD_RequestInfoDynamicType info_type, - union MHD_RequestInfoDynamicData *MHD_RESTRICT return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) + union MHD_RequestInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** * Obtain dynamic information about the given request. * This information may be changed during the lifetime of the request. + * Most of the data provided is available only when the request line or complete + * request headers are processed and not available if responding has been + * started. + * + * Any pointers in the returned data are valid until any MHD_Action or + * MHD_UploadAction is provided. If the data is needed beyond this point, + * it should be copied. * * @param request the request to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is + * not recognized by MHD, + * #MHD_SC_TOO_LATE if request is already being closed or the response + * is being sent + * #MHD_SC_TOO_EARLY if requested data is not yet ready (for example, + * headers are not yet received), + * #MHD_SC_FEATURE_DISABLED if requested functionality is not supported + * by this MHD build, + * #MHD_SC_AUTH_ABSENT if request does not have particular Auth data, + * #MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA if connection memory pool + * has no space to put decoded + * authentication data, + * #MHD_SC_REQ_AUTH_DATA_BROKEN if the format of authentication data is + * incorrect or broken, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_request_get_info_dynamic(request,info_type,return_value) \ +#define MHD_request_get_info_dynamic(request,info_type,output_buf) \ MHD_request_get_info_dynamic_sz ((request), (info_type), \ - (return_value), \ - sizeof(*(return_value))) + (output_buf), \ + sizeof(*(output_buf))) /** * Callback for serious error condition. The default action is to print diff --git a/src/include/microhttpd2_generated_daemon_options.h b/src/include/microhttpd2_generated_daemon_options.h @@ -275,6 +275,15 @@ You should only use this function if you do not use suspend functionality and ne , /** + * Disable cookies parsing. + * +Disable automatic cookies processing if cookies are not used. + * Cookies are automatically parsed by default. + */ + MHD_D_O_DISABLE_COOKIES = 324 + , + + /** * Set a callback to be called for pre-start finalisation. * The specified callback will be called one time, after network initialisation, TLS pre-initialisation, but before the start of the internal threads (if allowed) @@ -345,7 +354,8 @@ struct MHD_DaemonOptionValueLog { /** * the callback to use for logging, - * NULL to disable logging + * NULL to disable logging. + * The logging to stderr is enabled by default. */ MHD_LoggingCallback v_log_cb; @@ -596,7 +606,8 @@ union MHD_DaemonOptionValue /** * Value for #MHD_D_O_LOG_CALLBACK. * the callback to use for logging, - * NULL to disable logging + * NULL to disable logging. + * The logging to stderr is enabled by default. */ struct MHD_DaemonOptionValueLog log_callback; @@ -767,6 +778,11 @@ union MHD_DaemonOptionValue enum MHD_Bool disallow_suspend_resume; /** + * Value for #MHD_D_O_DISABLE_COOKIES. + */ + enum MHD_Bool disable_cookies; + + /** * Value for #MHD_D_O_DAEMON_READY_CALLBACK. * the pre-start callback */ @@ -855,7 +871,8 @@ struct MHD_DaemonOptionAndValue /** * Set a callback to use for logging * @param log_cb the callback to use for logging, - * NULL to disable logging + * NULL to disable logging. + * The logging to stderr is enabled by default. * @param log_cb_cls the closure for the logging callback * @return structure with the requested setting */ @@ -1332,6 +1349,21 @@ You should only use this function if you do not use suspend functionality and ne } \ MHD_RESTORE_WARN_COMPOUND_LITERALS_ /** + * Disable cookies parsing. + * +Disable automatic cookies processing if cookies are not used. + * Cookies are automatically parsed by default. + * @param value the value of the parameter * @return structure with the requested setting + */ +# define MHD_D_OPTION_DISABLE_COOKIES(value) \ + MHD_NOWARN_COMPOUND_LITERALS_ \ + (const struct MHD_DaemonOptionAndValue) \ + { \ + .opt = MHD_D_O_DISABLE_COOKIES, \ + .val.disable_cookies = (value) \ + } \ + MHD_RESTORE_WARN_COMPOUND_LITERALS_ +/** * Set a callback to be called for pre-start finalisation. * The specified callback will be called one time, after network initialisation, TLS pre-initialisation, but before the start of the internal threads (if allowed) @@ -1500,7 +1532,8 @@ MHD_D_OPTION_POLL_SYSCALL ( /** * Set a callback to use for logging * @param log_cb the callback to use for logging, - * NULL to disable logging + * NULL to disable logging. + * The logging to stderr is enabled by default. * @param log_cb_cls the closure for the logging callback * @return structure with the requested setting */ @@ -2168,6 +2201,27 @@ MHD_D_OPTION_DISALLOW_SUSPEND_RESUME ( /** + * Disable cookies parsing. + * +Disable automatic cookies processing if cookies are not used. + * Cookies are automatically parsed by default. + * @param value the value of the parameter * @return structure with the requested setting + */ +static MHD_INLINE struct MHD_DaemonOptionAndValue +MHD_D_OPTION_DISABLE_COOKIES ( + enum MHD_Bool value + ) +{ + struct MHD_DaemonOptionAndValue opt_val; + + opt_val.opt = MHD_D_O_DISABLE_COOKIES; + opt_val.val.disable_cookies = (value); \ + + return opt_val; +} + + +/** * Set a callback to be called for pre-start finalisation. * The specified callback will be called one time, after network initialisation, TLS pre-initialisation, but before the start of the internal threads (if allowed) diff --git a/src/include/microhttpd2_generated_response_options.h b/src/include/microhttpd2_generated_response_options.h @@ -98,7 +98,7 @@ With this option HTTP/1.0 server is emulated (with support for 'keep-alive' conn /** * Data for #MHD_R_O_TERMINATION_CALLBACK */ -struct MHD_ResponeOptionValueEndedCB +struct MHD_ResponseOptionValueEndedCB { /** * the function to call, @@ -158,7 +158,7 @@ union MHD_ResponseOptionValue * the function to call, * NULL to not use the callback */ - struct MHD_ResponeOptionValueEndedCB termination_callback; + struct MHD_ResponseOptionValueEndedCB termination_callback; }; diff --git a/src/include/microhttpd2_main.h.in b/src/include/microhttpd2_main.h.in @@ -3928,46 +3928,57 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * Exceptions are marked explicitly in the description. */ /** - * Get whether messages are supported. If supported then in debug - * mode messages can be printed to stderr or to external logger. + * Get whether messages are supported. If supported then messages can be + * printed to stderr or to an external logger. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_MESSAGES = 11 + MHD_LIB_INFO_FIXED_HAS_LOG_MESSAGES = 11 , /** - * Get whether MHD supports threads. + * Get whether detailed automatic HTTP reply messages are supported. + * If supported then automatic responses have bodies with text expalining + * the error details. + * Automatic responses are sent by MHD automatically when client is violating + * HTTP specification, for example, the request header has whitespace in + * header name or request's "Content-Length" header has non-number value. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_THREADS = 12 + MHD_LIB_INFO_FIXED_HAS_AUTO_REPLIES_BODIES = 12 , /** - * Get whether MHD was built with asserts enabled. - * Enabled only on special debug builds. + * Get whether MHD was built with debug asserts disabled. + * These asserts enabled only on special debug builds. * For debug builds the error log is always enabled. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_DEBUG = 13 + MHD_LIB_INFO_FIXED_IS_NON_DEBUG = 13 + , + /** + * Get whether MHD supports threads. + * The result is placed in @a v_bool member. + */ + MHD_LIB_INFO_FIXED_HAS_THREADS = 14 , /** * Get whether automatic parsing of HTTP Cookie header is supported. * If disabled, no #MHD_VK_COOKIE will be generated by MHD. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_COOKIE_PARSER = 14 + MHD_LIB_INFO_FIXED_HAS_COOKIE_PARSER = 15 , /** * Get whether postprocessor is supported. If supported then * #MHD_action_post_processor() can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_POST_PARSER = 15 + MHD_LIB_INFO_FIXED_HAS_POST_PARSER = 16 , /** * Get whether HTTP "Upgrade" is supported. * If supported then #MHD_action_upgrade() can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_UPGRADE = 16 + MHD_LIB_INFO_FIXED_HAS_UPGRADE = 17 , /** * Get whether HTTP Basic authorization is supported. If supported @@ -3975,7 +3986,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * and #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_BASIC_AUTH = 20 + MHD_LIB_INFO_FIXED_HAS_AUTH_BASIC = 20 , /** * Get whether HTTP Digest authorization is supported. If @@ -3985,7 +3996,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * #MHD_digest_auth_check() can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH = 21 + MHD_LIB_INFO_FIXED_HAS_AUTH_DIGEST = 21 , /** * Get whether the early version the Digest Authorization (RFC 2069) is @@ -4051,66 +4062,80 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * the toolchain. * Some of the features can be disabled or selected at build-time. */ /** - * Get supported sockets polling function/techniques. + * Get sockets polling functions/techniques supported by this MHD build. + * Some functions can be disabled (like epoll) in kernel, this is not + * checked. * The result is placed in @a v_polling member. */ - MHD_LIB_INFO_FIXED_TYPE_SOCKETS_POLLING = 50 + MHD_LIB_INFO_FIXED_TYPE_SOCKETS_POLLING = 60 , /** * Get whether aggregate FD external polling is supported. - * The result is placed in @a v_polling member. + * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_AGGREGATE_FD = 51 + MHD_LIB_INFO_FIXED_HAS_AGGREGATE_FD = 61 , /** - * Get whether IPv6 is supported on the platform and whether IPv6 without IPv4 + * Get whether IPv6 is supported on the platform and IPv6-only listen socket * can be used. * The result is placed in @a v_ipv6 member. * @note The platform may have disabled IPv6 at run-time, it is not checked * by this information type. */ - MHD_LIB_INFO_FIXED_TYPE_IPv6 = 52 + MHD_LIB_INFO_FIXED_TYPE_IPV6 = 62 , /** * Get whether TCP Fast Open is supported by MHD build. * If supported then option #MHD_D_O_TCP_FASTOPEN can be used. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_TCP_FASTOPEN = 53 + MHD_LIB_INFO_FIXED_HAS_TCP_FASTOPEN = 64 , /** * Get whether MHD support automatic detection of bind port number. * @sa #MHD_D_O_BIND_PORT * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_AUTODETECT_BIND_PORT = 54 + MHD_LIB_INFO_FIXED_HAS_AUTODETECT_BIND_PORT = 65 , /** * Get whether MHD use system's sendfile() function to send * file-FD based responses over non-TLS connections. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_SENDFILE = 55 + MHD_LIB_INFO_FIXED_HAS_SENDFILE = 66 , /** - * Get whether MHD supports automatic SIGPIPE suppression. + * Get whether MHD supports automatic SIGPIPE suppression within internal + * events loop (MHD's managed threads). * If SIGPIPE suppression is not supported, application must handle - * SIGPIPE signal by itself. + * SIGPIPE signal by itself whem using MHD with internal events loop. + * If the platform does not have SIGPIPE the result is #MHD_YES. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE = 60 + MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_INT = 80 + , + /** + * Get whether MHD supports automatic SIGPIPE suppression when used with + * extenal events loop (in application thread). + * If SIGPIPE suppression is not supported, application must handle + * SIGPIPE signal by itself whem using MHD with external events loop. + * If the platform does not have SIGPIPE the result is #MHD_YES. + * The result is placed in @a v_bool member. + */ + MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_EXT = 81 , /** * Get whether MHD sets names on generated threads. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_THREAD_NAMES = 61 + MHD_LIB_INFO_FIXED_HAS_THREAD_NAMES = 82 , /** * Get the type of supported inter-thread communication. * The result is placed in @a v_itc member. */ - MHD_LIB_INFO_FIXED_TYPE_ITC = 62 + MHD_LIB_INFO_FIXED_TYPE_ITC = 83 , /** * Get whether reading files beyond 2 GiB boundary is supported. @@ -4119,7 +4144,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed * limited to 2 GiB. * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_FIXED_HAS_LARGE_FILE = 63 + MHD_LIB_INFO_FIXED_HAS_LARGE_FILE = 84 , /* * Platform-dependent features, some set on startup and some are @@ -4137,9 +4162,9 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed , /** * Get whether password encrypted private key for HTTPS daemon is - * supported. If supported then option - * #MHD_D_OPTION_TLS_KEY_CERT can be used with non-NULL @a mem_pass - * The result is placed in @a v_bool member. + * supported. If supported then option #MHD_D_OPTION_TLS_KEY_CERT + * can be used with non-NULL @a mem_pass. + * The result is placed in @a v_tls member. */ MHD_LIB_INFO_FIXED_HAS_TLS_KEY_PASSWORD = 102 , @@ -4165,6 +4190,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedDigestAlgoType , /** * The algorithm is implemented by MHD internal code. + * MHD implementation of hashing can never fail. */ MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_BUILT_IN = 1 , @@ -4215,9 +4241,10 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedIPv6Type MHD_LIB_INFO_FIXED_IPV6_TYPE_DUAL_ONLY = 1 , /** - * IPv6 is supported as IPv6-only or as "dual stack". + * IPv6 can be used as IPv6-only (without getting IPv4 incoming connections). + * The platform may support "dual stack" too. */ - MHD_LIB_INFO_FIXED_IPV6_TYPE_BOTH = 2 + MHD_LIB_INFO_FIXED_IPV6_TYPE_IPV6_PURE = 2 }; /** @@ -4227,21 +4254,27 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedIPv6Type enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedITCType { /** + * No ITC used. + * This value is returned if MHD is built without threads support + */ + MHD_LIB_INFO_FIXED_ITC_TYPE_NONE = 0 + , + /** * The pair of sockets are used as inter-thread communication. * The is the least efficient method of communication. */ - MHD_LIB_INFO_FIXED_ITC_TYPE_SOCKETPAIR = 0 + MHD_LIB_INFO_FIXED_ITC_TYPE_SOCKETPAIR = 1 , /** * The pipe is used as inter-thread communication. */ - MHD_LIB_INFO_FIXED_ITC_TYPE_PIPE = 1 + MHD_LIB_INFO_FIXED_ITC_TYPE_PIPE = 2 , /** * The EventFD is used as inter-thread communication. * This is the most efficient method of communication. */ - MHD_LIB_INFO_FIXED_ITC_TYPE_EVENTFD = 2 + MHD_LIB_INFO_FIXED_ITC_TYPE_EVENTFD = 3 }; @@ -4284,11 +4317,14 @@ union MHD_LibInfoFixedData */ enum MHD_Bool v_bool; /** - * The type of digest algorithm implemetation + * The type of digest algorithm implementation */ enum MHD_LibInfoFixedDigestAlgoType v_d_algo; /** - * The types of the sockets polling functions/techniques supported + * The types of the sockets polling functions/techniques supported by this MHD + * build. + * Some functions can be disabled (like epoll) in kernel, this is not + * checked. */ struct MHD_LibInfoFixedPollingFunc v_polling; /** @@ -4309,23 +4345,30 @@ union MHD_LibInfoFixedData * Get fixed information about MHD that is not changed at run-time. * The returned information can be cached by application as it will be not * changed at run-time. + * + * For any valid @a info_type the only possible returned error value is + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL. If the buffer is large enough and + * the requested type of information is valid, the function always succeeds + * and returns #MHD_SC_OK. + * * The wrapper macro #MHD_lib_get_info_fixed() could be more convenient. * * @param info_type the type of requested information - * @param[out] return_data the pointer to union to be set to the required - * information - * @param return_data_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_lib_get_info_fixed_sz (enum MHD_LibInfoFixed info_type, - union MHD_LibInfoFixedData *return_data, - size_t return_data_size) -MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2) -MHD_FN_PURE_; + union MHD_LibInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2); /** * Get fixed information about MHD that is not changed at run-time. @@ -4333,13 +4376,65 @@ MHD_FN_PURE_; * changed at run-time. * * @param info the type of requested information - * @param[out] data the pointer to union to set to the required information + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * or other error code * @ingroup specialized */ -#define MHD_lib_get_info_fixed(info,data) \ - MHD_lib_get_info_fixed_sz ((info),(data),sizeof(*(data))) +#define MHD_lib_get_info_fixed(info,output_buf) \ + MHD_lib_get_info_fixed_sz ((info),(output_buf),sizeof(*(output_buf))) + +#ifndef MHD_NO_STATIC_INLINE + +/* + * A helper below can be used in a simple check preventing use of downgraded + * library version. + * As new library version may introduce new functionality, and the application + * may detect some functionality available at application build-time, use of + * previous versions may lead to run-time failures. + * To prevent run-time failures, application may use a check like: + + if (MHD_lib_get_info_ver_num() < ((uint_fast32_t) MHD_VERSION)) + handle_init_failure(); + + */ +/** + * Get the library version number. + * @return the library version number. + */ +MHD_STATIC_INLINE_ MHD_FN_PURE_ uint_fast32_t +MHD_lib_get_info_ver_num (void) +{ + union MHD_LibInfoFixedData data; + data.v_uint32 = 0; /* Not really necessary */ + (void) MHD_lib_get_info_fixed (MHD_LIB_INFO_FIXED_VERSION_NUM, \ + &data); /* Never fail */ + return data.v_uint32; +} + + +MHD_STATIC_INLINE_END_ +/** + * Get the fixed boolean information about the library. + * @param info the type of requested information, must be the value with + * the boolean resulting data; behaviour is undefined if other + * types of requested information is used + * @return #MHD_YES or #MHD_NO + */ +MHD_STATIC_INLINE_ MHD_FN_PURE_ enum MHD_Bool +MHD_lib_get_fixed_info_bool (enum MHD_LibInfoFixed info_type) +{ + union MHD_LibInfoFixedData data; + (void) MHD_lib_get_info_fixed (info_type, \ + &data); /* Never fail */ + return data.v_bool; +} + + +MHD_STATIC_INLINE_END_ +#endif /* ! MHD_NO_STATIC_INLINE */ /** * Types of information about MHD, @@ -4351,22 +4446,37 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoDynamic /* * Basic MHD information * */ /** - * Get whether MHD was successfully initialised. - * The result is #MHD_NO when the library has not been yet initialised or - * when library has been de-initialised. - * Under normal conditions the result must be always #MHD_YES when requested - * by application. + * Get whether MHD has been successfully fully initialised. + * MHD uses lazy initialisation: a minimal initialisation is perfomed at + * startup, complete initialisation is perfomed when any daemon is created + * (or called other function which requires full initialisation). + * The result is #MHD_NO when the library has been not yet initialised + * completely since startup. + * The result is placed in @a v_bool member. + */ + MHD_LIB_INFO_DYNAMIC_INITED_FULLY_ONCE = 0 + , + /** + * Get whether MHD has been successfully fully initialised. + * MHD uses lazy initialisation: a minimal initialisation is perfomed at + * startup, complete initialisation is perfomed when any daemon is created + * (or called other function which requires full initialisation). + * The result is #MHD_YES if library is initialised state now (meaning + * that at least one deamon is created and not destroyed or some function + * required full initialisation is running). * The result is placed in @a v_bool member. */ - MHD_LIB_INFO_DYNAMIC_INITED = 0 + MHD_LIB_INFO_DYNAMIC_INITED_FULLY_NOW = 1 , /** * Get whether HTTPS and which types of TLS backend(s) currently available. - * If any MHD daemonis active (created and not destroyed, not nessesary + * If any MHD daemons active (created and not destroyed, not necessary * running) the result reflects the current backends availability. - * If no MHD daemon is active, then this function would try to temporarly + * If no MHD daemon is active, then this function would try to temporarily * enable backends to check for their availability. + * If global library initialisation failed, the function returns + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE error code. * The result is placed in @a v_tls member. */ MHD_LIB_INFO_DYNAMIC_TYPE_TLS = 100 @@ -4411,31 +4521,37 @@ union MHD_LibInfoDynamicData * The wrapper macro #MHD_lib_get_info_dynamic() could be more convenient. * * @param info_type the type of requested information - * @param[out] return_data the pointer to union to be set to the required - * information - * @param return_data_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * or other error code * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode -MHD_lib_get_info_dynamic_sz (enum MHD_LibInfoDynamic info_type, - union MHD_LibInfoDynamicData *return_data, - size_t return_data_size) -MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2); +MHD_lib_get_info_dynamic_sz ( + enum MHD_LibInfoDynamic info_type, + union MHD_LibInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2); /** * Get dynamic information about MHD that may be changed at run-time. * * @param info the type of requested information - * @param[out] data the pointer to union to set to the required information + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * or other error code * @ingroup specialized */ -#define MHD_lib_get_info_dynamic(info,data) \ - MHD_lib_get_info_fixed_sz ((info),(data),sizeof(*(data))) +#define MHD_lib_get_info_dynamic(info,output_buf) \ + MHD_lib_get_info_fixed_sz ((info),(output_buf),sizeof(*(output_buf))) /** @@ -4448,28 +4564,54 @@ enum MHD_DaemonInfoFixedType { /** - * Request the file descriptor for the listening socket. + * Get the port number of daemon's listen socket. + * Note: if port '0' (auto port) was specified for #MHD_D_OPTION_BIND_PORT(), + * returned value will be the real port number. + * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon + * does not have listening socket or if listening socket is non-IP. + * The function returns #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the port number + * detection failed or not supported by the platform. + * If the function succeed, the returned port number is never zero. + * The result is placed in @a v_port member. + */ + MHD_DAEMON_INFO_FIXED_BIND_PORT = 1 + , + /** + * Get the file descriptor for the listening socket. + * The provided socket must be used as 'read-only': only select() or similar + * functions should be used. Any modifications (changing socket attributes, + * calling accept(), closing it etc.) will lead to undefined behaviour. + * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon + * does not have listening socket. * The result is placed in @a v_socket member. */ - MHD_DAEMON_INFO_FIXED_LISTEN_SOCKET = 1 + MHD_DAEMON_INFO_FIXED_LISTEN_SOCKET = 2 , /** - * Request the file descriptor for the single FD that triggered when + * Get the file descriptor for the single FD that triggered when * any MHD event happens. * This FD can be watched as aggregate indicator for all MHD events. + * The provided socket must be used as 'read-only': only select() or similar + * functions should be used. Any modifications (changing socket attributes, + * calling accept() closing it etc.) will lead to undefined behaviour. + * The function returns #MHD_SC_INFO_GET_TYPE_NOT_SUPP_BY_BUILD if the library + * does not support mode with agregate FD. + * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon + * is not configured to use this mode. * The result is placed in @a v_fd member. */ - MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD + MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD = 3 , /** - * Request the port number of daemon's listen socket. - * No extra arguments should be passed. - * Note: if port '0' was specified for #MHD_D_OPTION_BIND_PORT(), returned - * value will be real port number. - * The result is placed in @a v_port member. + * Get the TLS backend used by the daemon. + * The value #MHD_TLS_BACKEND_ANY is never set in the returned data. + * The value #MHD_TLS_BACKEND_NONE is set if the daemon does not use TLS. + * If MHD built without TLS support then #MHD_TLS_BACKEND_NONE is always set. + * The result is placed in @a v_tls_backend member. */ - MHD_DAEMON_INFO_FIXED_BIND_PORT + MHD_DAEMON_INFO_FIXED_TLS_TYPE = 100 , + /* * Sentinel * */ /** * The sentinel value. @@ -4503,6 +4645,11 @@ union MHD_DaemonInfoFixedData uint_least16_t v_port; /** + * The TLS backend + */ + enum MHD_TlsBackend v_tls_backend; + + /** * Unused member. * Help enforcing future-proof alignment of the union. * Do not use. @@ -4519,22 +4666,36 @@ union MHD_DaemonInfoFixedData * * @param daemon the daemon to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf pointer to union where requested information will + * be stored + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_TOO_EARLY if the daemon has not been started yet, + * #MHD_SC_TOO_LATE if the daemon is being stopped or has failed, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * daemon due to the daemon + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the daemon, but cannot be provided + * due to some error or other + * reasons, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode -MHD_daemon_get_info_fixed_sz (struct MHD_Daemon *daemon, - enum MHD_DaemonInfoFixedType info_type, - union MHD_DaemonInfoFixedData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; +MHD_daemon_get_info_fixed_sz ( + struct MHD_Daemon *MHD_RESTRICT daemon, + enum MHD_DaemonInfoFixedType info_type, + union MHD_DaemonInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** * Obtain fixed information about the given daemon. @@ -4543,15 +4704,27 @@ MHD_FN_PURE_; * * @param daemon the daemon to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will + * @param[out] output_buf pointer to union where requested information will * be stored * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_TOO_EARLY if the daemon has not been started yet, + * #MHD_SC_TOO_LATE if the daemon is being stopped or has failed, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * daemon due to the daemon + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the daemon, but cannot be provided + * due to some error or other + * reasons, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_daemon_get_info_fixed(daemon,info_type,return_value) \ - MHD_daemon_get_info_fixed_sz ((daemon), (info_type), (return_value), \ - sizeof(*(return_value))) +#define MHD_daemon_get_info_fixed(daemon,info_type,output_buf) \ + MHD_daemon_get_info_fixed_sz ((daemon), (info_type), (output_buf), \ + sizeof(*(output_buf))) /** @@ -4562,7 +4735,7 @@ MHD_FN_PURE_; enum MHD_DaemonInfoDynamicType { /** - * The the maximum number of microseconds from the current moment until + * The the maximum number of millisecond from the current moment until * the mandatory call of the daemon data processing function (like * #MHD_deamon_process_reg_events(), #MHD_daemon_process_blocking()). * If resulting value is zero then daemon data processing function should be @@ -4571,19 +4744,17 @@ enum MHD_DaemonInfoDynamicType * Available only for daemons stated in #MHD_WM_EXTERNAL_PERIODIC, * #MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL, #MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE * or #MHD_WM_EXTERNAL_SINGLE_FD_WATCH modes. + * The function return #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if daemon has + * internal handling of events (internal threads). * The result is placed in @a v_uint64 member. */ MHD_DAEMON_INFO_DYNAMIC_MAX_TIME_TO_WAIT = 1 , /** - * Request the number of current connections handled by the daemon. - * No extra arguments should be passed. - * Note: when using MHD without internal threads, this type of request - * could be used only when MHD is is not processing the connection data - * in other thread at the same time. - * The result is placed in @a v_uint member. + * Check whether the daemon has any connected network clients. + * The result is placed in @a v_bool member. */ - MHD_DAEMON_INFO_DYNAMIC_CURRENT_CONNECTIONS = 20 + MHD_DAEMON_INFO_DYNAMIC_HAS_CONNECTIONS = 20 , /* * Sentinel * */ /** @@ -4601,14 +4772,14 @@ enum MHD_DaemonInfoDynamicType union MHD_DaemonInfoDynamicData { /** - * Unsigned 64 bits integer value. + * The boolean value */ - uint_fast64_t v_uint64; + enum MHD_Bool v_bool; /** - * Unsigned integer value. + * Unsigned 64 bits integer value. */ - unsigned int v_uint; + uint_fast64_t v_uint64; /** * Unused member. @@ -4626,20 +4797,35 @@ union MHD_DaemonInfoDynamicData * * @param daemon the daemon to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_TOO_EARLY if the daemon has not been started yet, + * #MHD_SC_TOO_LATE if the daemon is being stopped or has failed, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * daemon due to the daemon + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the daemon, but cannot be provided + * due to some error or other + * reasons, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode -MHD_daemon_get_info_dynamic_sz (struct MHD_Daemon *daemon, - enum MHD_DaemonInfoDynamicType info_type, - union MHD_DaemonInfoDynamicData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) +MHD_daemon_get_info_dynamic_sz ( + struct MHD_Daemon *MHD_RESTRICT daemon, + enum MHD_DaemonInfoDynamicType info_type, + union MHD_DaemonInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -4648,15 +4834,27 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); * * @param daemon the daemon to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_TOO_EARLY if the daemon has not been started yet, + * #MHD_SC_TOO_LATE if the daemon is being stopped or has failed, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * daemon due to the daemon + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the daemon, but cannot be provided + * due to some error or other + * reasons, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_daemon_get_info_dynamic(daemon,info_type,return_value) \ - MHD_daemon_get_info_dynamic_sz ((daemon), (info_type), (return_value), \ - sizeof(*(return_value))) +#define MHD_daemon_get_info_dynamic(daemon,info_type,output_buf) \ + MHD_daemon_get_info_dynamic_sz ((daemon), (info_type), (output_buf), \ + sizeof(*(output_buf))) /** @@ -4666,14 +4864,25 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); enum MHD_ConnectionInfoFixedType { /** - * Obtain IP address of the client. - * The result is placed in @a vs_sa member. + * Get the network address of the client. + * If the connection does not have known remote address (was not provided + * by the system or by the application in case of externally added + * connection) then error code #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE is + * returned if connection is IP type or unknown type or error code + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if connection type is non-IP. + * The @a sa pointer is never NULL if the function succeed (#MHD_SC_OK + * returned). + * The result is placed in @a v_sa_info member. * @ingroup request */ MHD_CONNECTION_INFO_FIXED_CLIENT_ADDRESS = 1 , /** - * Request the file descriptor for the connection socket. + * Get the file descriptor for the connection socket. + * The provided socket must be used as 'read-only': only select() or similar + * functions should be used. Any modifications (changing socket attributes, + * calling send() or recv(), closing it etc.) will lead to undefined + * behaviour. * The result is placed in @a v_fd member. * @ingroup request */ @@ -4686,6 +4895,19 @@ enum MHD_ConnectionInfoFixedType */ MHD_CONNECTION_INFO_FIXED_DAEMON = 20 , + /** + * Returns the pointer to a variable pointing to connection-specific + * application context data that was (possibly) set during + * a #MHD_NotifyConnectionCallback or provided via @a connection_cntx + * parameter of #MHD_daemon_add_connection(). + * By using provided pointer application may get or set the pointer to + * any data specific for the particular connection. + * The result is placed in @a v_ppvoid member. + * @ingroup request + */ + MHD_CONNECTION_INFO_FIXED_SOCKET_CONTEXT = 30 + , + /* * Sentinel * */ /** * The sentinel value. @@ -4695,6 +4917,18 @@ enum MHD_ConnectionInfoFixedType MHD_CONNECTION_INFO_FIXED_SENTINEL = 65535 }; +struct MHD_ConnInfoFixedSockAddr +{ + /** + * The size of the @a sa + */ + size_t sa_size; + + /** + * Socket Address type + */ + const struct sockaddr *sa; +}; /** * Information about a connection. @@ -4705,7 +4939,7 @@ union MHD_ConnectionInfoFixedData /** * Socket Address type */ - const struct sockaddr *vs_sa; + struct MHD_ConnInfoFixedSockAddr v_sa_info; /** * Socket type @@ -4716,6 +4950,11 @@ union MHD_ConnectionInfoFixedData * Daemon handler type */ struct MHD_Daemon *v_daemon; + + /** + * The pointer to pointer to the data + */ + void **v_ppvoid; }; @@ -4726,23 +4965,34 @@ union MHD_ConnectionInfoFixedData * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_connection_get_info_fixed_sz ( - struct MHD_Connection *connection, + struct MHD_Connection *MHD_RESTRICT connection, enum MHD_ConnectionInfoFixedType info_type, - union MHD_ConnectionInfoFixedData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; + union MHD_ConnectionInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -4751,16 +5001,25 @@ MHD_FN_PURE_; * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_connection_get_info_fixed(connection,info_type,return_value) \ - MHD_connection_get_info_fixed_sz ((connection),(info_type),(return_value \ - ), \ - sizeof(*(return_value))) +#define MHD_connection_get_info_fixed(connection,info_type,output_buf) \ + MHD_connection_get_info_fixed_sz ((connection),(info_type), \ + (output_buf), sizeof(*(output_buf))) /** @@ -4771,13 +5030,20 @@ enum MHD_ConnectionInfoDynamicType { /** * Get current version of HTTP protocol used for connection. + * If connection is handling HTTP/1.x requests the function may return + * error code #MHD_SC_TOO_EARLY if the full request line has not been received + * yet for the current request. * The result is placed in @a v_http_ver member. * @ingroup request */ MHD_CONNECTION_INFO_DYNAMIC_HTTP_VER = 1 , /** - * Get connection timeout. + * Get connection timeout value. + * This is the total number of seconds after which the idle connection is + * automatically disconnected. + * Note: the value set is NOT the number of seconds left before automatic + * disconnection. * The result is placed in @a v_uint member. * @ingroup request */ @@ -4791,26 +5057,27 @@ enum MHD_ConnectionInfoDynamicType MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_SUSPENDED = 11 , /** - * Returns the connection-specific application context data that was - * (possibly) set during a #MHD_NotifyConnectionCallback or provided via - * @a connection_cntx parameter of #MHD_daemon_add_connection(). - * The result is placed in @a v_pvoid member. - */ - MHD_CONNECTION_INFO_DYNAMIC_SOCKET_CONTEXT = 20 - , - /** * Get current version of TLS transport protocol used for connection + * If plain TCP connection is used then #MHD_TLS_VERSION_NO_TLS set in + * the data. + * It TLS handshake is not yet finished then error code #MHD_SC_TOO_EARLY is + * returned. If TLS has failed or being closed then #MHD_SC_TOO_LATE error + * code is returned. + * If TLS version cannot be detected for any reason then error code + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE is returned. * The result is placed in @a v_tls_ver member. * @ingroup request */ - MHD_CONNECTION_INFO_DYNAMIC_TLS_VER = 1 + MHD_CONNECTION_INFO_DYNAMIC_TLS_VER = 105 , /** - * Get the GnuTLS session handle. - * The result is placed in @a v_gnutls_session member. + * Get the TLS backend session handle. + * If plain TCP connection is used then the function returns error code + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE. + * The result is placed in @a v_tls_session member. * @ingroup request */ - MHD_CONNECTION_INFO_DYNAMIC_GNUTLS_SESSION = 40 + MHD_CONNECTION_INFO_DYNAMIC_TLS_SESSION = 140 , /* * Sentinel * */ @@ -4867,6 +5134,35 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_TlsVersion }; /** + * Connection TLS session information. + * Only one member is valid. Use #MHD_DAEMON_INFO_FIXED_TLS_TYPE to find out + * which member should be used. + */ +union MHD_ConnInfoDynamicTlsSess +{ + /* Include <gnutls/gnutls.h> before this header to get a better type safety */ + /** + * GnuTLS session handle, of type "gnutls_session_t". + */ +#if defined(GNUTLS_VERSION_MAJOR) && GNUTLS_VERSION_MAJOR >= 3 + gnutls_session_t v_gnutls_session; +#else + void * /* gnutls_session_t */ v_gnutls_session; +#endif + + /* Include <openssl/types.h> or <openssl/crypto.h> before this header to get + a better type safety */ + /** + * OpenSSL session handle, of type "SSL*". + */ +#if defined(OPENSSL_TYPES_H) && OPENSSL_VERSION_MAJOR >= 3 + SSL *v_openssl_session; +#else + void /* SSL */ *v_openssl_session; +#endif +}; + +/** * Information about a connection. */ union MHD_ConnectionInfoDynamicData @@ -4887,25 +5183,16 @@ union MHD_ConnectionInfoDynamicData enum MHD_Bool v_bool; /** - * The pointer to void type - */ - void *v_pvoid; - - /** * The TLS version */ enum MHD_TlsVersion v_tls_ver; - /* Include <gnutls/gnutls.h> before this header to get a better type safety */ /** - * GnuTLS session handle, of type "gnutls_session_t". + * Connection TLS session information. + * Only one member is valid. Use #MHD_DAEMON_INFO_FIXED_TLS_TYPE to find out + * which member should be used. */ -#if defined(GNUTLS_VERSION_MAJOR) && GNUTLS_VERSION_MAJOR >= 3 - gnutls_session_t -#else - void * /* gnutls_session_t */ -#endif - v_gnutls_session; + union MHD_ConnInfoDynamicTlsSess v_tls_session; }; /** @@ -4916,21 +5203,37 @@ union MHD_ConnectionInfoDynamicData * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the connection has not reached yet required + * state, + * #MHD_SC_TOO_LATE if the connection is already in state where + * the requested information is not available, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_connection_get_info_dynamic_sz ( - struct MHD_Connection *connection, + struct MHD_Connection *MHD_RESTRICT connection, enum MHD_ConnectionInfoDynamicType info_type, - union MHD_ConnectionInfoDynamicData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) + union MHD_ConnectionInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); @@ -4940,16 +5243,29 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the connection has not reached yet required + * state, + * #MHD_SC_TOO_LATE if the connection is already in state where + * the requested information is not available, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_connection_get_info_dynamic(connection,info_type,return_value) \ - MHD_connection_get_info_dynamic_sz ((connection),(info_type),( \ - return_value), \ - sizeof(*(return_value))) +#define MHD_connection_get_info_dynamic(connection,info_type,output_buf) \ + MHD_connection_get_info_dynamic_sz ((connection),(info_type), \ + (output_buf),sizeof(*(output_buf))) /** @@ -4959,20 +5275,21 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); enum MHD_FIXED_ENUM_APP_SET_ MHD_StreamInfoFixedType { /** - * Get the `struct MHD_Connection *` responsible for managing this stream. - * The result is placed in @a v_connection member. + * Get the `struct MHD_Daemon *` responsible for managing connection which + * is responsible for this stream. + * The result is placed in @a v_daemon member. * @ingroup request */ - MHD_STREAM_INFO_FIXED_CONNECTION = 1 + MHD_STREAM_INFO_FIXED_DAEMON = 20 , /** - * Get the `struct MHD_Daemon *` responsible for managing connection which - * is responsible for this stream. - * The result is placed in @a v_daemon member. + * Get the `struct MHD_Connection *` responsible for managing this stream. + * The result is placed in @a v_connection member. * @ingroup request */ - MHD_STREAM_INFO_FIXED_DAEMON = 2 + MHD_STREAM_INFO_FIXED_CONNECTION = 21 , + /* * Sentinel * */ /** * The sentinel value. @@ -5006,23 +5323,25 @@ union MHD_StreamInfoFixedData * * @param stream the stream to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_stream_get_info_fixed_sz ( - struct MHD_Stream *stream, + struct MHD_Stream *MHD_RESTRICT stream, enum MHD_StreamInfoFixedType info_type, - union MHD_StreamInfoFixedData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; + union MHD_StreamInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -5031,15 +5350,16 @@ MHD_FN_PURE_; * * @param stream the stream to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_stream_get_info_fixed(stream,info_type,return_value) \ - MHD_stream_get_info_fixed_sz ((stream),(info_type),(return_value), \ - sizeof(*(return_value))) +#define MHD_stream_get_info_fixed(stream,info_type,output_buf) \ + MHD_stream_get_info_fixed_sz ((stream),(info_type),(output_buf), \ + sizeof(*(output_buf))) /** @@ -5050,11 +5370,12 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_StreamInfoDynamicType { /** * Get the `struct MHD_Request *` for current request processed by the stream. - * If no request is being processed, the resulting pointer is NULL. + * If no request is being processed, the error code #MHD_SC_TOO_EARLY is + * returned. * The result is placed in @a v_request member. * @ingroup request */ - MHD_STREAM_INFO_DYNAMIC_REQUEST = 1 + MHD_STREAM_INFO_DYNAMIC_REQUEST = 20 , /* * Sentinel * */ @@ -5086,21 +5407,25 @@ union MHD_StreamInfoDynamicData * * @param stream the stream to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the stream has not reached yet required state, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_stream_get_info_dynamic_sz ( - struct MHD_Stream *stream, + struct MHD_Stream *MHD_RESTRICT stream, enum MHD_StreamInfoDynamicType info_type, - union MHD_StreamInfoDynamicData *return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) + union MHD_StreamInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); @@ -5110,15 +5435,17 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); * * @param stream the stream to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the stream has not reached yet required state, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_stream_get_info_dynamic(stream,info_type,return_value) \ - MHD_stream_get_info_dynamic_sz ((stream),(info_type),(return_value), \ - sizeof(*(return_value))) +#define MHD_stream_get_info_dynamic(stream,info_type,output_buf) \ + MHD_stream_get_info_dynamic_sz ((stream),(info_type),(output_buf), \ + sizeof(*(output_buf))) /** @@ -5128,38 +5455,51 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoFixedType { /** - * Return which stream the request is associated with. - * The result is placed in @a v_stream member. + * Get the version of HTTP protocol used for the request. + * If request line has not been fully received yet then #MHD_SC_TOO_EARLY + * error code is returned. + * The result is placed in @a v_http_ver member. + * @ingroup request */ - MHD_REQUEST_INFO_FIXED_STREAM = 1 + MHD_REQUEST_INFO_FIXED_HTTP_VER = 1 , /** - * Return which connection is associated with the stream which is associated - * with the request. - * The result is placed in @a v_connection member. + * Get the HTTP method used for the request (as a enum). + * The result is placed in @a v_http_method member. + * @sa #MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STR + * @ingroup request */ - MHD_REQUEST_INFO_FIXED_CONNECTION = 2 + MHD_REQUEST_INFO_FIXED_HTTP_METHOD = 2 , /** * Return MHD daemon to which the request belongs to. * The result is placed in @a v_daemon member. */ - MHD_REQUEST_INFO_FIXED_DAEMON = 3 + MHD_REQUEST_INFO_FIXED_DAEMON = 20 , /** - * Get the version of HTTP protocol used for the request. - * The result is placed in @a v_http_ver member. - * @ingroup request + * Return which connection is associated with the stream which is associated + * with the request. + * The result is placed in @a v_connection member. */ - MHD_REQUEST_INFO_FIXED_HTTP_VER = 4 + MHD_REQUEST_INFO_FIXED_CONNECTION = 21 , /** - * Get the HTTP method used for the request (as a enum). - * The result is placed in @a v_http_method member. - * @sa #MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STR + * Return which stream the request is associated with. + * The result is placed in @a v_stream member. + */ + MHD_REQUEST_INFO_FIXED_STREAM = 22 + , + /** + * Returns the pointer to a variable pointing to request-specific + * application context data. The same data is provided for + * #MHD_EarlyUriLogCallback and #MHD_RequestTerminationCallback. + * By using provided pointer application may get or set the pointer to + * any data specific for the particular request. + * The result is placed in @a v_ppvoid member. * @ingroup request */ - MHD_REQUEST_INFO_FIXED_HTTP_METHOD = 5 + MHD_REQUEST_INFO_FIXED_APP_CONTEXT = 30 , /* * Sentinel * */ @@ -5202,6 +5542,11 @@ union MHD_RequestInfoFixedData * The HTTP method type. */ enum MHD_HTTP_Method v_http_method; + + /** + * The pointer to pointer to the data. + */ + void **v_ppvoid; }; /** @@ -5211,23 +5556,27 @@ union MHD_RequestInfoFixedData * * @param request the request to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the request processing has not reached yet + * the required state, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_request_get_info_fixed_sz ( struct MHD_Request *MHD_RESTRICT request, enum MHD_RequestInfoFixedType info_type, - union MHD_RequestInfoFixedData *MHD_RESTRICT return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; + union MHD_RequestInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -5236,15 +5585,18 @@ MHD_FN_PURE_; * * @param request the request to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_TOO_EARLY if the request processing has not reached yet + * the required state, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_request_get_info_fixed(request,info_type,return_value) \ - MHD_request_get_info_fixed_sz ((request), (info_type), (return_value), \ - sizeof(*(return_value))) +#define MHD_request_get_info_fixed(request,info_type,output_buf) \ + MHD_request_get_info_fixed_sz ((request), (info_type), (output_buf), \ + sizeof(*(output_buf))) /** @@ -5288,11 +5640,19 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType MHD_REQUEST_INFO_DYNAMIC_NUMBER_COOKIES = 4 , /** + * Return length of the client's HTTP request header. + * This is a total raw size of the header (after TLS decipher if any) + * The result is placed in @a v_sizet member. + * @ingroup request + */ + MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE = 5 + , + /** * Get the number of decoded POST entries in the request. * The result is placed in @a v_sizet member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS = 5 + MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS = 6 , /** * Get whether the upload content is present in the request. @@ -5304,13 +5664,21 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType MHD_REQUEST_INFO_DYNAMIC_UPLOAD_PRESENT = 10 , /** + * Get whether the chunked upload content is present in the request. + * The result is #MHD_YES if chunked upload content is present. + * The result is placed in @a v_bool member. + * @ingroup request + */ + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_CHUNKED = 11 + , + /** * Get the total content upload size. * Resulted in zero if no content upload or upload content size is zero, * #MHD_SIZE_UNKNOWN if size is not known (chunked upload). * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL = 11 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL = 12 , /** * Get the total size of the content upload already received from the client. @@ -5319,7 +5687,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED = 12 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED = 13 , /** * Get the total size of the content upload left to be received from @@ -5328,7 +5696,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_RECIEVE = 13 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_RECIEVE = 14 , /** * Get the total size of the content upload already processed (upload callback @@ -5338,7 +5706,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_PROCESSED = 14 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_PROCESSED = 15 , /** * Get the total size of the content upload left to be processed. @@ -5350,26 +5718,7 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType * The result is placed in @a v_uint64 member. * @ingroup request */ - MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_PROCESS = 15 - , - /** - * Return length of the client's HTTP request header. - * This is a total raw size of the header (after TLS decipher if any) - * The result is placed in @a v_sizet member. - * @ingroup request - */ - MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE = 21 - , - /** - * Returns the request-specific pointer to a `void *`. The pointer obtainable - * by this pointer is the same as provided for #MHD_EarlyUriLogCallback and - * #MHD_RequestTerminationCallback. - * By using provided pointer application may get or set the pointer to - * any data specific for the particular request. - * The result is placed in @a v_ppvoid member. - * @ingroup request - */ - MHD_REQUEST_INFO_DYNAMIC_APP_CONTEXT = 31 + MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_PROCESS = 16 , /** * Returns pointer to information about username in client's digest auth @@ -5437,10 +5786,6 @@ union MHD_RequestInfoDynamicData * The unsigned 64 bits integer */ uint_fast64_t v_uint64; - /** - * The pointer to pointer to the data. - */ - void **v_ppvoid; /** * The information about client provided username for digest auth @@ -5464,6 +5809,9 @@ union MHD_RequestInfoDynamicData /** * Obtain dynamic information about the given request. * This information may be changed during the lifetime of the request. + * Most of the data provided is available only when the request line or complete + * request headers are processed and not available if responding has been + * started. * The wrapper macro #MHD_request_get_info_dynamic() could be more convenient. * * Any pointers in the returned data are valid until any MHD_Action or @@ -5472,55 +5820,77 @@ union MHD_RequestInfoDynamicData * * @param request the request to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - * by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a return_value_size is too small, + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is + * not recognized by MHD, * #MHD_SC_TOO_LATE if request is already being closed or the response * is being sent * #MHD_SC_TOO_EARLY if requested data is not yet ready (for example, * headers are not yet received), - * #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is - * not recognized by MHD, * #MHD_SC_FEATURE_DISABLED if requested functionality is not supported * by this MHD build, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, * #MHD_SC_AUTH_ABSENT if request does not have particular Auth data, * #MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA if connection memory pool * has no space to put decoded * authentication data, * #MHD_SC_REQ_AUTH_DATA_BROKEN if the format of authentication data is * incorrect or broken, - * other error code otherwise + * other error codes in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_request_get_info_dynamic_sz ( struct MHD_Request *MHD_RESTRICT request, enum MHD_RequestInfoDynamicType info_type, - union MHD_RequestInfoDynamicData *MHD_RESTRICT return_value, - size_t return_value_size) -MHD_FN_PAR_NONNULL_ (1) + union MHD_RequestInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** * Obtain dynamic information about the given request. * This information may be changed during the lifetime of the request. + * Most of the data provided is available only when the request line or complete + * request headers are processed and not available if responding has been + * started. + * + * Any pointers in the returned data are valid until any MHD_Action or + * MHD_UploadAction is provided. If the data is needed beyond this point, + * it should be copied. * * @param request the request to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is + * not recognized by MHD, + * #MHD_SC_TOO_LATE if request is already being closed or the response + * is being sent + * #MHD_SC_TOO_EARLY if requested data is not yet ready (for example, + * headers are not yet received), + * #MHD_SC_FEATURE_DISABLED if requested functionality is not supported + * by this MHD build, + * #MHD_SC_AUTH_ABSENT if request does not have particular Auth data, + * #MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA if connection memory pool + * has no space to put decoded + * authentication data, + * #MHD_SC_REQ_AUTH_DATA_BROKEN if the format of authentication data is + * incorrect or broken, + * other error codes in case of other errors * @ingroup specialized */ -#define MHD_request_get_info_dynamic(request,info_type,return_value) \ +#define MHD_request_get_info_dynamic(request,info_type,output_buf) \ MHD_request_get_info_dynamic_sz ((request), (info_type), \ - (return_value), \ - sizeof(*(return_value))) + (output_buf), \ + sizeof(*(output_buf))) /** * Callback for serious error condition. The default action is to print diff --git a/src/include/microhttpd2_portability.h b/src/include/microhttpd2_portability.h @@ -410,14 +410,29 @@ #endif #ifdef MHD_HAS_NOWARN_UNUSED_FUNC_ -# define MHD_STATIC_INLINE_ \ - MHD_NOWARN_UNUSED_FUNC_ static MHD_INLINE -# define MHD_STATIC_INLINE_END_ \ - MHD_RESTORE_WARN_UNUSED_FUNC_ +/** + * The header static inline function. + * Tries to prevent compiler warnings. + * @warning Must be always followed by #MHD_STATIC_INLINE_END_ after the end of + * function + */ +# define MHD_STATIC_INLINE_ MHD_NOWARN_UNUSED_FUNC_ static MHD_INLINE +/** + * Mark the end of header static inline function. + */ +# define MHD_STATIC_INLINE_END_ MHD_RESTORE_WARN_UNUSED_FUNC_ #else -# define MHD_STATIC_INLINE_ \ - MHD_NOWARN_EXPRESSION_ static MHD_INLINE -# define MHD_STATIC_INLINE_END_ /* empty */ +/** + * The header static inline function. + * Tries to prevent compiler warnings. + * @warning Must be always followed by #MHD_STATIC_INLINE_END_ after the end of + * function + */ +# define MHD_STATIC_INLINE_ MHD_NOWARN_EXPRESSION_ static MHD_INLINE +/** + * Mark the end of header static inline function. + */ +# define MHD_STATIC_INLINE_END_ /* empty */ #endif /** diff --git a/src/include/microhttpd2_preamble.h.in b/src/include/microhttpd2_preamble.h.in @@ -1,6 +1,6 @@ /* This file is part of GNU libmicrohttpd - Copyright (C) 2006-2024 Christian Grothoff, Karlson2k (Evgeny Grin) + Copyright (C) 2006-2025 Christian Grothoff, Karlson2k (Evgeny Grin) (and other contributing authors) GNU libmicrohttpd is free software; you can redistribute it and/or @@ -1471,7 +1471,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode MHD_SC_CONFIGURATION_UNEXPECTED_WM = 60022 , /** - * Parameter specified unknown socket poll syscall. + * Parameter specified unknown Sockets Polling Syscall (SPS). */ MHD_SC_CONFIGURATION_UNEXPECTED_SPS = 60023 , @@ -1632,13 +1632,13 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode * The type of the information is not available due to configuration * or state of the object. */ - MHD_SC_INFO_GET_TYPE_UNSUPPORTED = 60203 + MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE = 60203 , /** * The type of the information should be available for the object, but * cannot be provided due to some error or other reasons. */ - MHD_SC_INFO_GET_TYPE_UNAVAILALBE = 60204 + MHD_SC_INFO_GET_TYPE_UNOBTAINABLE = 60204 , /** * The type of the Digest Auth algorithm is unknown or not supported. diff --git a/src/include/options.tmpl b/src/include/options.tmpl @@ -1,8 +0,0 @@ - "{{Name}}" : { - "Value": {{Value}}, - "Type": "{{Type}}", - "Conditional": "{{Conditional}}", - "Comment": "{{Comment}}", - "Arguments": ["{{Argument1}}","{{Argument2}}","{{Argument3}}","{{Argument4}}","{{Argument5}}"], - "Descriptions": ["{{Description1}}","{{Description2}}","{{Description3}}","{{Description4}}","{{Description5}}"] - }, diff --git a/src/include/r_options.rec b/src/include/r_options.rec @@ -109,7 +109,7 @@ Comment: Disable sanity check preventing clients from manually setting the HTTP Name: termination_callback Value: 121 -Type: struct MHD_ResponeOptionValueEndedCB +Type: struct MHD_ResponseOptionValueEndedCB Comment: Set a function to be called once MHD is finished with the request. Argument1: MHD_RequestEndedCallback ended_cb Description1: the function to call, diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am @@ -80,6 +80,7 @@ libmicrohttpd2_la_SOURCES = \ conn_data_recv.c conn_data_recv.h \ conn_data_send.c conn_data_send.h \ conn_mark_ready.h \ + conn_get_info.c \ request_funcs.c request_funcs.h \ request_get_value.c request_get_value.h \ respond_with_error.c respond_with_error.h \ @@ -92,7 +93,8 @@ libmicrohttpd2_la_SOURCES = \ stream_funcs.c stream_funcs.h \ stream_process_states.c stream_process_states.h \ stream_process_request.c stream_process_request.h \ - stream_process_reply.c stream_process_reply.h + stream_process_reply.c stream_process_reply.h \ + stream_get_info.c if ! HAVE_SYS_CALLOC libmicrohttpd2_la_SOURCES += \ @@ -176,7 +178,7 @@ tls_open_OPTSOURCES = \ tls_open_tls_lib.h tls_open_daemon_data.h tls_open_conn_data.h \ tls_open_funcs.c tls_open_funcs.h -if HAVE_POST_PARSER +if MHD_SUPPORT_POST_PARSER libmicrohttpd2_la_SOURCES += $(post_parser_OPTSOURCES) endif @@ -192,22 +194,22 @@ if MHD_SUPPORT_AUTH_DIGEST libmicrohttpd2_la_SOURCES += $(auth_digest_OPTSOURCES) endif -if MHD_UPGRADE_SUPPORT +if MHD_SUPPORT_UPGRADE libmicrohttpd2_la_SOURCES += $(upgrade_OPTSOURCES) endif -if MHD_ENABLE_HTTPS +if MHD_SUPPORT_HTTPS libmicrohttpd2_la_SOURCES += $(tls_common_OPTSOURCES) if MHD_ENABLE_MULTITLS libmicrohttpd2_la_SOURCES += $(tls_multi_OPTSOURCES) endif -if MHD_USE_GNUTLS +if MHD_SUPPORT_GNUTLS libmicrohttpd2_la_SOURCES += $(tls_gnu_OPTSOURCES) endif -if MHD_USE_OPENSSL +if MHD_SUPPORT_OPENSSL libmicrohttpd2_la_SOURCES += $(tls_open_OPTSOURCES) endif endif diff --git a/src/mhd2/action.c b/src/mhd2/action.c @@ -38,7 +38,7 @@ #include "response_funcs.h" #include "response_destroy.h" -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE # include "upgrade_prep.h" #endif @@ -143,7 +143,7 @@ MHD_action_parse_post (struct MHD_Request *request, MHD_PostDataFinished done_cb, void *done_cb_cls) { -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER struct MHD_Action *const restrict head_act = &(request->app_act.head_act); if (mhd_ACTION_NO_ACTION != head_act->act) @@ -161,16 +161,16 @@ MHD_action_parse_post (struct MHD_Request *request, head_act->data.post_parse.done_cb_cls = done_cb_cls; return head_act; -#else /* ! HAVE_POST_PARSER */ +#else /* ! MHD_SUPPORT_POST_PARSER */ (void) request; (void) buffer_size; (void) max_nonstream_size; (void) enc; (void) stream_reader; (void) reader_cls; (void) done_cb; (void) done_cb_cls; return NULL; -#endif /* ! HAVE_POST_PARSER */ +#endif /* ! MHD_SUPPORT_POST_PARSER */ } -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE MHD_EXTERN_ MHD_FN_PAR_NONNULL_ (1) @@ -243,7 +243,7 @@ MHD_upload_action_upgrade ( } -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ MHD_EXTERN_ MHD_FN_PAR_NONNULL_ALL_ diff --git a/src/mhd2/auth_digest.c b/src/mhd2/auth_digest.c @@ -2187,7 +2187,7 @@ MHD_digest_auth_calc_userhash_hex ( size_t hex_buf_size, char userhash_hex[MHD_FN_PAR_DYN_ARR_SIZE_ (hex_buf_size)]) { - uint8_t userhash_bin[mhd_MAX_DIGEST]; + uint8_t userhash_bin[mhd_MAX_DIGEST] = { 0u /* mute compiler warning */ }; size_t digest_size; enum MHD_StatusCode res; diff --git a/src/mhd2/conn_data_process.c b/src/mhd2/conn_data_process.c @@ -47,9 +47,9 @@ #include "conn_data_send.h" #include "stream_process_states.h" -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "conn_tls_check.h" -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool mhd_conn_process_recv_send_data (struct MHD_Connection *restrict c) @@ -58,7 +58,7 @@ mhd_conn_process_recv_send_data (struct MHD_Connection *restrict c) bool has_sock_err; bool data_processed; -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (mhd_C_HAS_TLS (c)) { switch (mhd_conn_tls_check (c)) @@ -75,7 +75,7 @@ mhd_conn_process_recv_send_data (struct MHD_Connection *restrict c) break; } } -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ /* The "send-ready" state is known if system polling call is edge-triggered (it always checks for both send- and recv-ready) or if connection needs diff --git a/src/mhd2/conn_data_send.c b/src/mhd2/conn_data_send.c @@ -218,7 +218,7 @@ mhd_conn_data_send (struct MHD_Connection *restrict c) true, &sent); } - #if defined(MHD_USE_SENDFILE) + #if defined(mhd_USE_SENDFILE) else if (mhd_REPLY_CNTN_LOC_FILE == c->rp.cntn_loc) { mhd_assert (mhd_RESPONSE_CONTENT_DATA_FILE == resp->cntn_dtype); @@ -234,7 +234,7 @@ mhd_conn_data_send (struct MHD_Connection *restrict c) } } } - #endif /* MHD_USE_SENDFILE */ + #endif /* mhd_USE_SENDFILE */ else { mhd_assert (0 && "Should be unreachable"); @@ -286,7 +286,7 @@ mhd_conn_data_send (struct MHD_Connection *restrict c) mhd_HTTP_STAGE_FULL_REPLY_SENT); } break; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING: res = mhd_send_data (c, c->write_buffer_append_offset @@ -298,7 +298,7 @@ mhd_conn_data_send (struct MHD_Connection *restrict c) if (mhd_SOCKET_ERR_NO_ERROR == res) c->write_buffer_send_offset += sent; break; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ case mhd_HTTP_STAGE_INIT: case mhd_HTTP_STAGE_REQ_LINE_RECEIVING: case mhd_HTTP_STAGE_REQ_LINE_RECEIVED: @@ -319,11 +319,11 @@ mhd_conn_data_send (struct MHD_Connection *restrict c) case mhd_HTTP_STAGE_FULL_REPLY_SENT: case mhd_HTTP_STAGE_PRE_CLOSING: case mhd_HTTP_STAGE_CLOSED: -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_HTTP_STAGE_UPGRADING: case mhd_HTTP_STAGE_UPGRADED: case mhd_HTTP_STAGE_UPGRADED_CLEANING: -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ mhd_assert (0 && "Should be unreachable"); mhd_UNREACHABLE (); res = mhd_SOCKET_ERR_INTERNAL; diff --git a/src/mhd2/conn_get_info.c b/src/mhd2/conn_get_info.c @@ -0,0 +1,167 @@ +/* + This file is part of GNU libmicrohttpd + Copyright (C) 2025 Evgeny Grin (Karlson2k) + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +/** + * @file src/mhd2/conn_get_info.c + * @brief The implementation of MHD_connection_get_info_*() functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" + +#include "mhd_unreachable.h" + +#include "mhd_connection.h" + +#include "daemon_funcs.h" +#ifdef MHD_SUPPORT_HTTPS +# include "mhd_tls_funcs.h" +#endif + +#include "mhd_public_api.h" + +MHD_EXTERN_ MHD_FN_MUST_CHECK_RESULT_ +MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode +MHD_connection_get_info_fixed_sz ( + struct MHD_Connection *MHD_RESTRICT connection, + enum MHD_ConnectionInfoFixedType info_type, + union MHD_ConnectionInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +{ + switch (info_type) + { + case MHD_CONNECTION_INFO_FIXED_CLIENT_ADDRESS: + if (NULL == connection->sk.addr.data) + { + if (mhd_T_IS_NOT_YES (connection->sk.props.is_nonip)) + return MHD_SC_INFO_GET_TYPE_UNOBTAINABLE; + else + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + } + mhd_assert (0 != connection->sk.addr.size); + if (sizeof(output_buf->v_sa_info) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_sa_info.sa_size = connection->sk.addr.size; + output_buf->v_sa_info.sa = + (const struct sockaddr*) connection->sk.addr.data; + return MHD_SC_OK; + case MHD_CONNECTION_INFO_FIXED_CONNECTION_FD: + if (sizeof(output_buf->v_fd) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + mhd_assert (MHD_INVALID_SOCKET != connection->sk.fd); + output_buf->v_fd = connection->sk.fd; + return MHD_SC_OK; + case MHD_CONNECTION_INFO_FIXED_DAEMON: + if (sizeof(output_buf->v_daemon) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_daemon = mhd_daemon_get_master_daemon (connection->daemon); + return MHD_SC_OK; + case MHD_CONNECTION_INFO_FIXED_SOCKET_CONTEXT: + if (sizeof(output_buf->v_ppvoid) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_ppvoid = &(connection->socket_context); + return MHD_SC_OK; + + case MHD_CONNECTION_INFO_FIXED_SENTINEL: + default: + break; + } + return MHD_SC_INFO_GET_TYPE_UNKNOWN; +} + + +MHD_EXTERN_ MHD_FN_MUST_CHECK_RESULT_ +MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode +MHD_connection_get_info_dynamic_sz ( + struct MHD_Connection *MHD_RESTRICT connection, + enum MHD_ConnectionInfoDynamicType info_type, + union MHD_ConnectionInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +{ + switch (info_type) + { + case MHD_CONNECTION_INFO_DYNAMIC_HTTP_VER: + if (mhd_HTTP_STAGE_REQ_LINE_RECEIVED > connection->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_http_ver) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_http_ver = connection->rq.http_ver; + return MHD_SC_OK; + case MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_TIMEOUT: + if (sizeof(output_buf->v_uint) <= output_buf_size) + { + const uint_fast64_t tmout_ms = connection->connection_timeout_ms; + const unsigned int tmout = (unsigned int) (tmout_ms / 1000); + mhd_assert ((1000 * ((uint_fast64_t) tmout)) == tmout_ms); + output_buf->v_uint = tmout; + return MHD_SC_OK; + } + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + case MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_SUSPENDED: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_bool = connection->suspended ? MHD_YES : MHD_NO; + return MHD_SC_OK; + case MHD_CONNECTION_INFO_DYNAMIC_TLS_VER: +#ifdef MHD_SUPPORT_HTTPS + if ((mhd_CONN_STATE_TCP_CONNECTED != connection->conn_state) && + (mhd_CONN_STATE_TLS_CONNECTED != connection->conn_state)) + { + if (mhd_CONN_FLAG_CLOSING > connection->conn_state) + return MHD_SC_TOO_EARLY; + else + return MHD_SC_TOO_LATE; + } +#endif + if (sizeof(output_buf->v_tls_ver) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + if (! mhd_C_HAS_TLS (connection)) + output_buf->v_tls_ver = MHD_TLS_VERSION_NO_TLS; + else + { +#ifdef MHD_SUPPORT_HTTPS + if (! mhd_tls_conn_get_tls_ver (connection->tls, \ + &(output_buf->v_tls_ver))) + return MHD_SC_INFO_GET_TYPE_UNOBTAINABLE; +#else /* ! MHD_SUPPORT_HTTPS */ + mhd_UNREACHABLE (); +#endif /* ! MHD_SUPPORT_HTTPS */ + } + return MHD_SC_OK; + case MHD_CONNECTION_INFO_DYNAMIC_TLS_SESSION: + if (! mhd_C_HAS_TLS (connection)) + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + if (sizeof(output_buf->v_tls_session) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifndef MHD_SUPPORT_HTTPS + mhd_UNREACHABLE (); + return MHD_SC_INTERNAL_ERROR; +#else /* MHD_SUPPORT_HTTPS */ + mhd_tls_conn_get_tls_sess (connection->tls, &(output_buf->v_tls_session)); +#endif /* MHD_SUPPORT_HTTPS */ + break; + case MHD_CONNECTION_INFO_DYNAMIC_SENTINEL: + default: + break; + } + return MHD_SC_INFO_GET_TYPE_UNKNOWN; +} diff --git a/src/mhd2/daemon_add_conn.c b/src/mhd2/daemon_add_conn.c @@ -44,7 +44,7 @@ #include "sys_ip_headers.h" #include <string.h> -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL # include <sys/epoll.h> #endif @@ -67,7 +67,7 @@ #include "response_destroy.h" #include "conn_mark_ready.h" -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "mhd_tls_funcs.h" #endif @@ -169,7 +169,7 @@ new_connection_prepare_ (struct MHD_Daemon *restrict daemon, *conn_out = NULL; tls_data_size = 0; -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (mhd_D_HAS_TLS (daemon)) tls_data_size = mhd_tls_conn_get_tls_size (daemon->tls); #endif @@ -184,7 +184,7 @@ new_connection_prepare_ (struct MHD_Daemon *restrict daemon, } else { -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (0 != tls_data_size) c->tls = (struct mhd_TlsConnData *) (c + 1); # ifndef HAVE_NULL_PTR_ALL_ZEROS @@ -230,9 +230,9 @@ new_connection_prepare_ (struct MHD_Daemon *restrict daemon, c->sk.props.is_nonblck = non_blck; c->sk.props.is_nonip = sk_is_nonip; c->sk.props.has_spipe_supp = sk_spipe_supprs; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_thread_handle_ID_set_invalid (&c->tid); -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ c->daemon = daemon; c->connection_timeout_ms = daemon->conns.cfg.timeout; c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; @@ -333,7 +333,7 @@ new_connection_process_ (struct MHD_Daemon *restrict daemon, notify_app_conn (daemon, connection, false); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS if (mhd_DAEMON_TYPE_LISTEN_ONLY == daemon->threading.d_type) { mhd_assert ((mhd_POLL_TYPE_SELECT == daemon->events.poll_type) || \ @@ -366,14 +366,14 @@ new_connection_process_ (struct MHD_Daemon *restrict daemon, return MHD_SC_OK; /* *** Function success exit point *** */ } else -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ if (1) -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ { /* No 'thread-per-connection' */ -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS connection->tid = daemon->threading.tid; -#endif /* MHD_USE_THREADS */ -#ifdef MHD_USE_EPOLL +#endif /* MHD_SUPPORT_THREADS */ +#ifdef MHD_SUPPORT_EPOLL if (mhd_POLL_TYPE_EPOLL == daemon->events.poll_type) { struct epoll_event event; @@ -401,7 +401,7 @@ new_connection_process_ (struct MHD_Daemon *restrict daemon, } } else /* No 'epoll' */ -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ return MHD_SC_OK; /* *** Function success exit point *** */ } @@ -421,7 +421,7 @@ new_connection_process_ (struct MHD_Daemon *restrict daemon, } /* Free resources allocated before the call of this functions */ -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (mhd_C_HAS_TLS (connection)) mhd_tls_conn_deinit (connection->tls); #endif @@ -675,14 +675,14 @@ MHD_daemon_add_connection (struct MHD_Daemon *daemon, #else /* MHD_SOCKETS_KIND_WINSOCK */ sk_spipe_supprs = true; /* Nothing to suppress on W32 */ #endif /* MHD_SOCKETS_KIND_WINSOCK */ -#if defined(MHD_socket_nosignal_) +#if defined(mhd_socket_nosignal) if (! sk_spipe_supprs) - sk_spipe_supprs = MHD_socket_nosignal_ (client_socket); + sk_spipe_supprs = mhd_socket_nosignal (client_socket); if (! sk_spipe_supprs) { mhd_LOG_MSG (daemon, MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED, \ "Failed to suppress SIGPIPE on the new client socket."); -#ifndef MSG_NOSIGNAL +#ifndef HAVE_DCLR_MSG_NOSIGNAL /* Application expects that SIGPIPE will be suppressed, * but suppression failed and SIGPIPE cannot be suppressed with send(). */ if (! daemon->sigpipe_blocked) @@ -692,9 +692,9 @@ MHD_daemon_add_connection (struct MHD_Daemon *daemon, MHD_socket_fset_error_ (err); return MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED; } -#endif /* MSG_NOSIGNAL */ +#endif /* HAVE_DCLR_MSG_NOSIGNAL */ } -#endif /* MHD_socket_nosignal_ */ +#endif /* mhd_socket_nosignal */ if (1) // TODO: implement turbo { @@ -710,7 +710,7 @@ MHD_daemon_add_connection (struct MHD_Daemon *daemon, addrstorage.ss_len = addrlen; /* Force set the right length */ #endif /* HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ -#if defined(MHD_USE_THREADS) +#if defined(MHD_SUPPORT_THREADS) if (mhd_D_TYPE_HAS_WORKERS (daemon->threading.d_type)) { unsigned int i; @@ -753,7 +753,7 @@ MHD_daemon_add_connection (struct MHD_Daemon *daemon, (void) mhd_socket_close (client_socket); return MHD_SC_LIMIT_CONNECTIONS_REACHED; } -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ return internal_add_connection (daemon, client_socket, @@ -785,11 +785,11 @@ mhd_daemon_accept_connection (struct MHD_Daemon *restrict daemon) static const bool use_accept4 = false; #endif /* ! USE_ACCEPT4 && ! _DEBUG */ -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_assert ((! mhd_D_HAS_THREADS (daemon)) || \ mhd_thread_handle_ID_is_current_thread (daemon->threading.tid)); mhd_assert (! mhd_D_TYPE_HAS_WORKERS (daemon->threading.d_type)); -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ fd = daemon->net.listen.fd; mhd_assert (MHD_INVALID_SOCKET != fd); @@ -950,13 +950,13 @@ mhd_daemon_accept_connection (struct MHD_Daemon *restrict daemon) "socket."); } -#if defined(MHD_socket_nosignal_) - if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s)) +#if defined(mhd_socket_nosignal) + if (! sk_spipe_supprs && ! mhd_socket_nosignal (s)) { mhd_LOG_MSG (daemon, MHD_SC_ACCEPT_CONFIGURE_NOSIGPIPE_FAILED, "Failed to suppress SIGPIPE on incoming connection " \ "socket."); -#ifndef MSG_NOSIGNAL +#ifndef HAVE_DCLR_MSG_NOSIGNAL /* Application expects that SIGPIPE will be suppressed, * but suppression failed and SIGPIPE cannot be suppressed with send(). */ if (! daemon->sigpipe_blocked) @@ -964,11 +964,11 @@ mhd_daemon_accept_connection (struct MHD_Daemon *restrict daemon) (void) MHD_socket_close_ (s); return MHD_NO; } -#endif /* MSG_NOSIGNAL */ +#endif /* HAVE_DCLR_MSG_NOSIGNAL */ } else sk_spipe_supprs = true; -#endif /* MHD_socket_nosignal_ */ +#endif /* mhd_socket_nosignal */ return (MHD_SC_OK == internal_add_connection (daemon, s, &addrstorage, @@ -1041,7 +1041,7 @@ mhd_conn_close_final (struct MHD_Connection *restrict c) mhd_assert (c != mhd_DLINKEDL_GET_FIRST (&(c->daemon->conns), all_conn)); mhd_assert (c != mhd_DLINKEDL_GET_LAST (&(c->daemon->conns), all_conn)); -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (mhd_C_HAS_TLS (c)) { mhd_assert (mhd_D_HAS_TLS (c->daemon)); diff --git a/src/mhd2/daemon_funcs.c b/src/mhd2/daemon_funcs.c @@ -41,15 +41,15 @@ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ struct MHD_Daemon * mhd_daemon_get_master_daemon (struct MHD_Daemon *restrict d) { -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS if (mhd_D_HAS_MASTER (d)) return d->threading.hier.master; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ return d; } -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS MHD_INTERNAL bool mhd_daemon_trigger_itc (struct MHD_Daemon *restrict d) @@ -65,7 +65,7 @@ mhd_daemon_trigger_itc (struct MHD_Daemon *restrict d) } -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ MHD_NORETURN_ // TODO: implement diff --git a/src/mhd2/daemon_funcs.h b/src/mhd2/daemon_funcs.h @@ -45,7 +45,7 @@ MHD_INTERNAL struct MHD_Daemon * mhd_daemon_get_master_daemon (struct MHD_Daemon *restrict d) MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * Trigger daemon ITC. @@ -57,10 +57,10 @@ MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_; MHD_INTERNAL bool mhd_daemon_trigger_itc (struct MHD_Daemon *restrict d); -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ #define mhd_daemon_trigger_itc (d) ((void) d, ! 0) -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ /** diff --git a/src/mhd2/daemon_get_info.c b/src/mhd2/daemon_get_info.c @@ -1,6 +1,6 @@ /* This file is part of GNU libmicrohttpd - Copyright (C) 2024 Evgeny Grin (Karlson2k) + Copyright (C) 2024-2025 Evgeny Grin (Karlson2k) GNU libmicrohttpd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -26,62 +26,175 @@ #include "mhd_sys_options.h" +#include "mhd_unreachable.h" + #include "sys_base_types.h" #include "sys_sockets_types.h" #include "mhd_socket_type.h" #include "mhd_daemon.h" +#include "events_process.h" +#ifdef MHD_SUPPORT_HTTPS +# include "mhd_tls_choice.h" +# ifdef MHD_USE_MULTITLS +# include "tls_multi_daemon_data.h" +# endif +#endif #include "mhd_public_api.h" -MHD_EXTERN_ +MHD_EXTERN_ MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_ enum MHD_StatusCode -MHD_daemon_get_info_fixed_sz (struct MHD_Daemon *daemon, - enum MHD_DaemonInfoFixedType info_type, - union MHD_DaemonInfoFixedData *return_value, - size_t return_value_size) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode +MHD_daemon_get_info_fixed_sz ( + struct MHD_Daemon *MHD_RESTRICT daemon, + enum MHD_DaemonInfoFixedType info_type, + union MHD_DaemonInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) { + if (mhd_DAEMON_STATE_STARTED > daemon->state) + return MHD_SC_TOO_EARLY; + if (mhd_DAEMON_STATE_STARTED < daemon->state) + return MHD_SC_TOO_LATE; + switch (info_type) { + case MHD_DAEMON_INFO_FIXED_BIND_PORT: + if (MHD_INVALID_SOCKET == daemon->net.listen.fd) + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + if (mhd_SOCKET_TYPE_UNKNOWN > daemon->net.listen.type) + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + if (0 == daemon->net.listen.port) + { + if (mhd_SOCKET_TYPE_IP != daemon->net.listen.type) + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + return MHD_SC_INFO_GET_TYPE_UNOBTAINABLE; + } + if (sizeof(output_buf->v_port) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_port = daemon->net.listen.port; + return MHD_SC_OK; case MHD_DAEMON_INFO_FIXED_LISTEN_SOCKET: if (MHD_INVALID_SOCKET == daemon->net.listen.fd) - return MHD_SC_INFO_GET_TYPE_UNSUPPORTED; - if (sizeof(MHD_Socket) > return_value_size) + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + if (sizeof(MHD_Socket) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_socket = daemon->net.listen.fd; + output_buf->v_socket = daemon->net.listen.fd; return MHD_SC_OK; case MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD: -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL if (! mhd_D_IS_USING_EPOLL (daemon)) - return MHD_SC_INFO_GET_TYPE_UNSUPPORTED; - if (sizeof(int) > return_value_size) + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + if (sizeof(int) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_fd = daemon->events.data.epoll.e_fd; + output_buf->v_fd = daemon->events.data.epoll.e_fd; return MHD_SC_OK; #else return MHD_SC_INFO_GET_TYPE_NOT_SUPP_BY_BUILD; #endif break; - case MHD_DAEMON_INFO_FIXED_BIND_PORT: - if (MHD_INVALID_SOCKET == daemon->net.listen.fd) - return MHD_SC_INFO_GET_TYPE_UNSUPPORTED; - if (mhd_SOCKET_TYPE_UNKNOWN > daemon->net.listen.type) - return MHD_SC_INFO_GET_TYPE_UNSUPPORTED; - if (0 == daemon->net.listen.port) + case MHD_DAEMON_INFO_FIXED_TLS_TYPE: + if (sizeof(output_buf->v_tls_backend) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + if (! mhd_D_HAS_TLS (daemon)) + output_buf->v_tls_backend = MHD_TLS_BACKEND_NONE; + else { - if (mhd_SOCKET_TYPE_IP != daemon->net.listen.type) - return MHD_SC_INFO_GET_TYPE_UNSUPPORTED; - return MHD_SC_INFO_GET_TYPE_UNAVAILALBE; +#if ! defined(MHD_SUPPORT_HTTPS) + mhd_UNREACHABLE (); +#elif defined(MHD_USE_MULTITLS) + switch (daemon->tls->choice) + { +# ifdef MHD_SUPPORT_GNUTLS + case mhd_TLS_MULTI_ROUTE_GNU: + output_buf->v_tls_backend = MHD_TLS_BACKEND_GNUTLS; + break; +# endif +# ifdef MHD_SUPPORT_OPENSSL + case mhd_TLS_MULTI_ROUTE_OPEN: + output_buf->v_tls_backend = MHD_TLS_BACKEND_OPENSSL; + break; +# endif + case mhd_TLS_MULTI_ROUTE_NONE: + default: + mhd_UNREACHABLE (); + break; + } +#elif defined(MHD_SUPPORT_GNUTLS) + output_buf->v_tls_backend = MHD_TLS_BACKEND_GNUTLS; +#elif defined(MHD_SUPPORT_OPENSSL) + output_buf->v_tls_backend = MHD_TLS_BACKEND_OPENSSL; +#else +#error No TLS backends enabled, while TLS support is enabled +#endif } - if (sizeof(return_value->v_port) > return_value_size) - return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_port = daemon->net.listen.port; + break; return MHD_SC_OK; + case MHD_DAEMON_INFO_FIXED_SENTINEL: default: break; } return MHD_SC_INFO_GET_TYPE_UNKNOWN; } + + +MHD_EXTERN_ MHD_FN_MUST_CHECK_RESULT_ +MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode +MHD_daemon_get_info_dynamic_sz ( + struct MHD_Daemon *MHD_RESTRICT daemon, + enum MHD_DaemonInfoDynamicType info_type, + union MHD_DaemonInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +{ + if (mhd_DAEMON_STATE_STARTED > daemon->state) + return MHD_SC_TOO_EARLY; + if (mhd_DAEMON_STATE_STARTED < daemon->state) + return MHD_SC_TOO_LATE; + + switch (info_type) + { + case MHD_DAEMON_INFO_DYNAMIC_MAX_TIME_TO_WAIT: + if (mhd_WM_INT_HAS_THREADS (daemon->wmode_int)) + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + if (sizeof(output_buf->v_uint64) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_uint64 = mhd_daemon_get_wait_max (daemon); + return MHD_SC_OK; + case MHD_DAEMON_INFO_DYNAMIC_HAS_CONNECTIONS: + if (sizeof(output_buf->v_bool) <= output_buf_size) + { + enum MHD_Bool res; + /* + Reading number of connection from the daemon member could be non-atomic + and may give wrong result (if it is modified in other thread), however + test against zero/non-zero value is valid even if reading is + non-atomic. + */ + if (! mhd_D_HAS_WORKERS (daemon)) + res = (0 != daemon->conns.count) ? MHD_YES : MHD_NO; + else + { + unsigned int i; + res = MHD_NO; + mhd_assert (NULL != daemon->threading.hier.pool.workers); + for (i = 0; i < daemon->threading.hier.pool.num; ++i) + { + if (0 != daemon->threading.hier.pool.workers[i].conns.count) + { + res = MHD_YES; + break; + } + } + } + output_buf->v_bool = res; + return MHD_SC_OK; + } + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + case MHD_DAEMON_INFO_DYNAMIC_SENTINEL: + default: + break; + } + return MHD_SC_INFO_GET_TYPE_UNKNOWN; +} diff --git a/src/mhd2/daemon_logger.c b/src/mhd2/daemon_logger.c @@ -26,7 +26,7 @@ #include "mhd_sys_options.h" -#ifdef HAVE_LOG_FUNCTIONALITY +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY #include <stdarg.h> #include "sys_null_macro.h" #include "mhd_daemon.h" @@ -50,4 +50,4 @@ mhd_logger (struct MHD_Daemon *daemon, } -#endif /* ! HAVE_LOG_FUNCTIONALITY */ +#endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ diff --git a/src/mhd2/daemon_logger.h b/src/mhd2/daemon_logger.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifdef HAVE_LOG_FUNCTIONALITY +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY #include "mhd_public_api.h" /* For enum MHD_StatusCode */ @@ -76,7 +76,7 @@ mhd_logger (struct MHD_Daemon *daemon, */ #define mhd_LOG_FMT(format_string) format_string -#else /* ! HAVE_LOG_FUNCTIONALITY */ +#else /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ #ifdef HAVE_MACRO_VARIADIC @@ -138,6 +138,6 @@ mhd_LOG_PRINT (struct MHD_Daemon *daemon, */ #define mhd_LOG_FMT(format_string) NULL -#endif /* ! HAVE_LOG_FUNCTIONALITY */ +#endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ #endif /* ! MHD_DAEMON_LOGGER_H */ diff --git a/src/mhd2/daemon_logger_default.c b/src/mhd2/daemon_logger_default.c @@ -26,7 +26,7 @@ #include "mhd_sys_options.h" -#ifdef HAVE_LOG_FUNCTIONALITY +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY #include <stdio.h> @@ -54,4 +54,4 @@ mhd_logger_default (void *cls, } -#endif /* ! HAVE_LOG_FUNCTIONALITY */ +#endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ diff --git a/src/mhd2/daemon_logger_default.h b/src/mhd2/daemon_logger_default.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifdef HAVE_LOG_FUNCTIONALITY +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY #include "mhd_public_api.h" /* For enum MHD_StatusCode */ @@ -49,7 +49,7 @@ mhd_logger_default (void *cls, const char *fm, va_list ap); -#else /* ! HAVE_LOG_FUNCTIONALITY */ +#else /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ #include "sys_null_macro.h" diff --git a/src/mhd2/daemon_options.h b/src/mhd2/daemon_options.h @@ -31,7 +31,8 @@ struct DaemonOptions /** * Value for #MHD_D_O_LOG_CALLBACK. * the callback to use for logging, - * NULL to disable logging + * NULL to disable logging. + * The logging to stderr is enabled by default. */ struct MHD_DaemonOptionValueLog log_callback; @@ -232,6 +233,12 @@ struct DaemonOptions /** + * Value for #MHD_D_O_DISABLE_COOKIES. + */ + enum MHD_Bool disable_cookies; + + + /** * Value for #MHD_D_O_DAEMON_READY_CALLBACK. * the pre-start callback */ diff --git a/src/mhd2/daemon_set_options.c b/src/mhd2/daemon_set_options.c @@ -198,6 +198,18 @@ MHD_daemon_set_options ( case MHD_D_O_DISALLOW_SUSPEND_RESUME: settings->disallow_suspend_resume = option->val.disallow_suspend_resume; continue; + case MHD_D_O_DISABLE_COOKIES: + /* custom setter */ + /* The is not an easy for automatic generations */ + // TODO: remove options generator, put preprocessor directives to + // the first column + #ifdef MHD_SUPPORT_COOKIES + settings->disable_cookies = option->val.disable_cookies; + #else + if (MHD_NO != option->val.disable_cookies) + return MHD_SC_FEATURE_DISABLED; + #endif + continue; case MHD_D_O_DAEMON_READY_CALLBACK: settings->daemon_ready_callback.v_cb = option->val.daemon_ready_callback.v_cb; settings->daemon_ready_callback.v_cb_cls = option->val.daemon_ready_callback.v_cb_cls; diff --git a/src/mhd2/daemon_start.c b/src/mhd2/daemon_start.c @@ -39,13 +39,13 @@ #ifdef MHD_SOCKETS_KIND_POSIX # include "sys_errno.h" #endif -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL # include <sys/epoll.h> #endif #ifdef MHD_SOCKETS_KIND_POSIX # include <fcntl.h> -# ifdef MHD_USE_SELECT +# ifdef MHD_SUPPORT_SELECT # ifdef HAVE_SYS_SELECT_H # include <sys/select.h> /* For FD_SETSIZE */ # else @@ -75,11 +75,11 @@ #include "mhd_lib_init.h" #include "daemon_logger.h" -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "mhd_tls_funcs.h" #endif -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS # include "mhd_itc.h" # include "mhd_threads.h" # include "events_process.h" @@ -115,6 +115,31 @@ dsettings_release (struct DaemonOptions *s) /** + * Set basic daemon parameters that not require additional initialisation. + * Mostly copy such parameters from the settings object to the daemon object. + * @param d the daemon object + * @param s the user settings + * @return MHD_SC_OK on success, + * the error code otherwise + */ +static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) +MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode +daemon_set_basic_settings (struct MHD_Daemon *restrict d, + struct DaemonOptions *restrict s) +{ + d->req_cfg.strictness = s->protocol_strict_level.v_sl; + +#ifdef MHD_SUPPORT_COOKIES + d->req_cfg.disable_cookies = (MHD_NO != s->disable_cookies); +#endif + + d->req_cfg.suppress_date = (MHD_NO != s->suppress_date_header); + + return MHD_SC_OK; +} + + +/** * Set the daemon work mode and perform some related checks. * @param d the daemon object * @param s the user settings @@ -156,7 +181,7 @@ daemon_set_work_mode (struct MHD_Daemon *restrict d, "is not compatible with requested socket polling syscall."); return MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID; } -#ifndef MHD_USE_EPOLL +#ifndef MHD_SUPPORT_EPOLL mhd_LOG_MSG ( \ d, MHD_SC_FEATURE_DISABLED, \ "The epoll is required for the requested work mode " \ @@ -178,19 +203,19 @@ daemon_set_work_mode (struct MHD_Daemon *restrict d, } /* Intentional fallthrough */ case MHD_WM_WORKER_THREADS: -#ifndef MHD_USE_THREADS +#ifndef MHD_SUPPORT_THREADS mhd_LOG_MSG (d, MHD_SC_FEATURE_DISABLED, \ "The internal threads modes are not supported by this " \ "build of MHD."); return MHD_SC_FEATURE_DISABLED; -#else /* MHD_USE_THREADS */ +#else /* MHD_SUPPORT_THREADS */ if (MHD_WM_THREAD_PER_CONNECTION == s->work_mode.mode) d->wmode_int = mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION; else if (1 >= s->work_mode.params.num_worker_threads) /* && (MHD_WM_WORKER_THREADS == s->work_mode.mode) */ d->wmode_int = mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD; else d->wmode_int = mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ break; default: mhd_LOG_MSG (d, MHD_SC_CONFIGURATION_UNEXPECTED_WM, \ @@ -413,7 +438,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, #ifdef HAVE_INET6 else { -#ifdef IPV6_V6ONLY // TODO: detect constants declarations in configure +#ifdef HAVE_DCLR_IPV6_V6ONLY sk_type = mhd_SKT_IP_DUAL_REQUIRED; #else /* ! IPV6_V6ONLY */ mhd_LOG_MSG (d, \ @@ -454,7 +479,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, return MHD_SC_INTERNAL_ERROR; case MHD_AF_AUTO: #ifdef HAVE_INET6 -#ifdef IPV6_V6ONLY // TODO: detect constants declarations in configure +#ifdef HAVE_DCLR_IPV6_V6ONLY if (force_v6_any_dual) sk_type = mhd_SKT_IP_V6_WITH_V4_OPT; else if (v6_tried) @@ -493,7 +518,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, mhd_assert (! v6_tried); mhd_assert (! force_v6_any_dual); #ifdef HAVE_INET6 -#ifdef IPV6_V6ONLY // TODO: detect constants declarations in configure +#ifdef HAVE_DCLR_IPV6_V6ONLY sk_type = mhd_SKT_IP_DUAL_REQUIRED; #else /* ! IPV6_V6ONLY */ mhd_LOG_MSG (d, @@ -513,7 +538,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, mhd_assert (! v6_tried); mhd_assert (! force_v6_any_dual); #ifdef HAVE_INET6 -#ifdef IPV6_V6ONLY // TODO: detect constants declarations in configure +#ifdef HAVE_DCLR_IPV6_V6ONLY sk_type = mhd_SKT_IP_V6_WITH_V4_OPT; #else /* ! IPV6_V6ONLY */ sk_type = mhd_SKT_IP_V6_ONLY; @@ -528,7 +553,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, case MHD_AF_DUAL_v6_OPTIONAL: mhd_assert (! force_v6_any_dual); #ifdef HAVE_INET6 -#ifdef IPV6_V6ONLY // TODO: detect constants declarations in configure +#ifdef HAVE_DCLR_IPV6_V6ONLY sk_type = (! v6_tried) ? mhd_SKT_IP_V4_WITH_V6_OPT : mhd_SKT_IP_V4_ONLY; #else /* ! IPV6_V6ONLY */ @@ -689,7 +714,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, if (! sk_already_listening) { #ifdef HAVE_INET6 -#ifdef IPV6_V6ONLY // TODO: detect constants declarations in configure +#ifdef HAVE_DCLR_IPV6_V6ONLY if ((mhd_SKT_IP_V6_ONLY == sk_type) || (mhd_SKT_IP_DUAL_REQUIRED == sk_type) || (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type) || @@ -783,7 +808,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, if (MHD_FOM_AUTO <= d->settings->tcp_fastopen.v_option) { -#if defined(TCP_FASTOPEN) +#if defined(HAVE_DCLR_TCP_FASTOPEN) int fo_param; #ifdef __linux__ /* The parameter is the queue length */ @@ -820,7 +845,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, if (MHD_D_OPTION_BIND_TYPE_NOT_SHARED >= d->settings->listen_addr_reuse) { #ifndef MHD_SOCKETS_KIND_WINSOCK -#ifdef SO_REUSEADDR +#ifdef HAVE_DCLR_SO_REUSEADDR mhd_SCKT_OPT_BOOL on_val1 = 1; if (0 != setsockopt (sk, SOL_SOCKET, SO_REUSEADDR, (const void *) &on_val1, sizeof (on_val1))) @@ -836,7 +861,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, #endif /* ! MHD_SOCKETS_KIND_WINSOCK */ if (MHD_D_OPTION_BIND_TYPE_NOT_SHARED > d->settings->listen_addr_reuse) { -#if defined(SO_REUSEPORT) || defined(MHD_SOCKETS_KIND_WINSOCK) +#if defined(HAVE_DCLR_SO_REUSEPORT) || defined(MHD_SOCKETS_KIND_WINSOCK) mhd_SCKT_OPT_BOOL on_val2 = 1; if (0 != setsockopt (sk, SOL_SOCKET, #ifndef MHD_SOCKETS_KIND_WINSOCK @@ -912,7 +937,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, accept_queue_len = 0; if (0 == accept_queue_len) { -#ifdef SOMAXCONN +#if defined(SOMAXCONN) || defined(HAVE_DCLR_SOMAXCONN) accept_queue_len = SOMAXCONN; #else /* ! SOMAXCONN */ accept_queue_len = 127; /* Should be the safe value */ @@ -991,6 +1016,7 @@ create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, } +#ifdef MHD_USE_GETSOCKNAME /** * Detect and set the type and port of the listening socket * @param d the daemon to use @@ -1061,7 +1087,12 @@ detect_listen_type_and_port (struct MHD_Daemon *restrict d) } -#ifdef MHD_USE_EPOLL +#else +# define detect_listen_type_and_port(d) ((void) d) +#endif + + +#ifdef MHD_SUPPORT_EPOLL /** * Initialise daemon's epoll FD @@ -1132,7 +1163,7 @@ deinit_epoll (struct MHD_Daemon *restrict d) } -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ /** * Choose sockets monitoring syscall and pre-initialise it @@ -1169,36 +1200,36 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, break; case MHD_SPS_SELECT: mhd_assert (! mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); -#ifndef MHD_USE_SELECT +#ifndef MHD_SUPPORT_SELECT mhd_LOG_MSG (d, MHD_SC_SELECT_SYSCALL_NOT_AVAILABLE, \ "'select()' is not supported by the platform or " \ "this MHD build"); return MHD_SC_SELECT_SYSCALL_NOT_AVAILABLE; -#else /* MHD_USE_SELECT */ +#else /* MHD_SUPPORT_SELECT */ chosen_type = mhd_POLL_TYPE_SELECT; -#endif /* MHD_USE_SELECT */ +#endif /* MHD_SUPPORT_SELECT */ break; case MHD_SPS_POLL: mhd_assert (! mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); -#ifndef MHD_USE_POLL +#ifndef MHD_SUPPORT_POLL mhd_LOG_MSG (d, MHD_SC_POLL_SYSCALL_NOT_AVAILABLE, \ "'poll()' is not supported by the platform or " \ "this MHD build"); return MHD_SC_POLL_SYSCALL_NOT_AVAILABLE; -#else /* MHD_USE_POLL */ +#else /* MHD_SUPPORT_POLL */ chosen_type = mhd_POLL_TYPE_POLL; -#endif /* MHD_USE_POLL */ +#endif /* MHD_SUPPORT_POLL */ break; case MHD_SPS_EPOLL: mhd_assert (! mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); -#ifndef MHD_USE_EPOLL +#ifndef MHD_SUPPORT_EPOLL mhd_LOG_MSG (d, MHD_SC_EPOLL_SYSCALL_NOT_AVAILABLE, \ "'epoll' is not supported by the platform or " \ "this MHD build"); return MHD_SC_EPOLL_SYSCALL_NOT_AVAILABLE; -#else /* MHD_USE_EPOLL */ +#else /* MHD_SUPPORT_EPOLL */ chosen_type = mhd_POLL_TYPE_EPOLL; -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ break; default: mhd_LOG_MSG (d, MHD_SC_CONFIGURATION_UNEXPECTED_SPS, @@ -1210,22 +1241,22 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, if (mhd_POLL_TYPE_NOT_SET_YET == chosen_type) { -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL bool edge_trig_allowed; edge_trig_allowed = true; -# ifdef MHD_ENABLE_HTTPS +# ifdef MHD_SUPPORT_HTTPS if ((edge_trig_allowed) && (MHD_TLS_BACKEND_NONE != s->tls)) edge_trig_allowed = mhd_tls_is_edge_trigg_supported (s); -# endif /* MHD_ENABLE_HTTPS */ -#endif /* MHD_USE_EPOLL */ +# endif /* MHD_SUPPORT_HTTPS */ +#endif /* MHD_SUPPORT_EPOLL */ fallback_syscall_allowed = true; if (mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)) { chosen_type = mhd_POLL_TYPE_EXT; } -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL else if (MHD_WM_EXTERNAL_SINGLE_FD_WATCH == s->work_mode.mode) { fallback_syscall_allowed = false; @@ -1238,9 +1269,9 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, #endif else { -#if defined(MHD_USE_POLL) +#if defined(MHD_SUPPORT_POLL) chosen_type = mhd_POLL_TYPE_POLL; -#elif defined(MHD_USE_SELECT) +#elif defined(MHD_SUPPORT_SELECT) chosen_type = mhd_POLL_TYPE_SELECT; #else (void) 0; /* Do nothing. Mute compiler warning */ @@ -1251,7 +1282,7 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, fallback_syscall_allowed = false; /* Try 'epoll' if possible */ -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL if (mhd_POLL_TYPE_EPOLL == chosen_type) { enum MHD_StatusCode epoll_res; @@ -1269,15 +1300,15 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, } mhd_assert ((mhd_POLL_TYPE_EPOLL != d->events.poll_type) || \ (0 < d->events.data.epoll.e_fd)); -#else /* ! MHD_USE_EPOLL */ +#else /* ! MHD_SUPPORT_EPOLL */ (void) fallback_syscall_allowed; /* Mute compiler warning */ -#endif /* ! MHD_USE_EPOLL */ +#endif /* ! MHD_SUPPORT_EPOLL */ if (mhd_POLL_TYPE_NOT_SET_YET == chosen_type) { -#if defined(MHD_USE_POLL) +#if defined(MHD_SUPPORT_POLL) chosen_type = mhd_POLL_TYPE_POLL; -#elif defined(MHD_USE_SELECT) +#elif defined(MHD_SUPPORT_SELECT) chosen_type = mhd_POLL_TYPE_SELECT; #else mhd_LOG_MSG (d, MHD_SC_FEATURE_DISABLED, \ @@ -1300,7 +1331,7 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, d->events.data.ext.cls = s->work_mode.params.v_external_event_loop_cb.reg_cb_cls; break; -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT case mhd_POLL_TYPE_SELECT: mhd_assert (! mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); mhd_assert (MHD_WM_EXTERNAL_SINGLE_FD_WATCH != s->work_mode.mode); @@ -1309,8 +1340,8 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, d->events.data.select.wfds = NULL; /* Memory allocated during event and threads init */ d->events.data.select.efds = NULL; /* Memory allocated during event and threads init */ break; -#endif /* MHD_USE_SELECT */ -#ifdef MHD_USE_POLL +#endif /* MHD_SUPPORT_SELECT */ +#ifdef MHD_SUPPORT_POLL case mhd_POLL_TYPE_POLL: mhd_assert (! mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); mhd_assert (MHD_WM_EXTERNAL_SINGLE_FD_WATCH != s->work_mode.mode); @@ -1318,8 +1349,8 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, d->events.data.poll.fds = NULL; /* Memory allocated during event and threads init */ d->events.data.poll.rel = NULL; /* Memory allocated during event and threads init */ break; -#endif /* MHD_USE_POLL */ -#ifdef MHD_USE_EPOLL +#endif /* MHD_SUPPORT_POLL */ +#ifdef MHD_SUPPORT_EPOLL case mhd_POLL_TYPE_EPOLL: mhd_assert (! mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); /* Pre-initialised by init_epoll() */ @@ -1327,16 +1358,16 @@ daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, mhd_assert (0 <= d->events.data.epoll.e_fd); mhd_assert (NULL == d->events.data.epoll.events); break; -#endif /* MHD_USE_EPOLL */ -#ifndef MHD_USE_SELECT +#endif /* MHD_SUPPORT_EPOLL */ +#ifndef MHD_SUPPORT_SELECT case mhd_POLL_TYPE_SELECT: -#endif /* ! MHD_USE_SELECT */ -#ifndef MHD_USE_POLL +#endif /* ! MHD_SUPPORT_SELECT */ +#ifndef MHD_SUPPORT_POLL case mhd_POLL_TYPE_POLL: -#endif /* ! MHD_USE_POLL */ -#ifndef MHD_USE_EPOLL +#endif /* ! MHD_SUPPORT_POLL */ +#ifndef MHD_SUPPORT_EPOLL case mhd_POLL_TYPE_EPOLL: -#endif /* ! MHD_USE_EPOLL */ +#endif /* ! MHD_SUPPORT_EPOLL */ case mhd_POLL_TYPE_NOT_SET_YET: default: mhd_UNREACHABLE (); @@ -1376,14 +1407,14 @@ daemon_init_net (struct MHD_Daemon *restrict d, /* No direct return of error codes is allowed beyond this point. Deinit/cleanup must be performed before return of any error. */ -#if defined(MHD_SOCKETS_KIND_POSIX) && defined(MHD_USE_SELECT) +#if defined(MHD_SOCKETS_KIND_POSIX) && defined(MHD_SUPPORT_SELECT) if (mhd_POLL_TYPE_SELECT == d->events.poll_type) { if ((MHD_INVALID_SOCKET == d->net.cfg.max_fd_num) || (FD_SETSIZE < d->net.cfg.max_fd_num)) d->net.cfg.max_fd_num = FD_SETSIZE; } -#endif /* MHD_SOCKETS_KIND_POSIX && MHD_USE_SELECT */ +#endif /* MHD_SOCKETS_KIND_POSIX && MHD_SUPPORT_SELECT */ if (MHD_SC_OK == ret) { @@ -1421,10 +1452,10 @@ daemon_init_net (struct MHD_Daemon *restrict d, } } -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL if ((mhd_POLL_TYPE_EPOLL == d->events.poll_type)) close (d->events.data.epoll.e_fd); -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ mhd_assert (MHD_SC_OK != ret); @@ -1442,10 +1473,10 @@ daemon_deinit_net (struct MHD_Daemon *restrict d) mhd_assert (d->dbg.net_inited); mhd_assert (! d->dbg.net_deinited); mhd_assert (mhd_POLL_TYPE_NOT_SET_YET != d->events.poll_type); -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL if (mhd_POLL_TYPE_EPOLL == d->events.poll_type) deinit_epoll (d); -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ if (MHD_INVALID_SOCKET != d->net.listen.fd) mhd_socket_close (d->net.listen.fd); @@ -1590,7 +1621,7 @@ daemon_init_tls (struct MHD_Daemon *restrict d, mhd_StatusCodeInt ret; mhd_assert (! d->dbg.tls_inited); -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS d->tls = NULL; #endif @@ -1601,12 +1632,12 @@ daemon_init_tls (struct MHD_Daemon *restrict d, #endif return MHD_SC_OK; } -#ifndef MHD_ENABLE_HTTPS +#ifndef MHD_SUPPORT_HTTPS mhd_LOG_MSG (d, \ MHD_SC_TLS_DISABLED, \ "HTTPS is not supported by this MHD build"); return MHD_SC_TLS_DISABLED; -#else /* MHD_ENABLE_HTTPS */ +#else /* MHD_SUPPORT_HTTPS */ if (1) { enum mhd_TlsBackendAvailable tls_avail; @@ -1638,7 +1669,7 @@ daemon_init_tls (struct MHD_Daemon *restrict d, d->dbg.tls_inited = (MHD_SC_OK == ret); #endif return (enum MHD_StatusCode) ret; -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ } @@ -1650,7 +1681,7 @@ MHD_FN_PAR_NONNULL_ (1) static void daemon_deinit_tls (struct MHD_Daemon *restrict d) { mhd_assert (d->dbg.tls_inited); -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (NULL != d->tls) mhd_tls_daemon_deinit (d->tls); #endif @@ -1718,20 +1749,20 @@ static MHD_FN_PAR_NONNULL_ (1) MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode allocate_events (struct MHD_Daemon *restrict d) { -#if defined(MHD_USE_POLL) || defined(MHD_USE_EPOLL) +#if defined(MHD_SUPPORT_POLL) || defined(MHD_SUPPORT_EPOLL) /** * The number of elements to be monitored by sockets polling function */ unsigned int num_elements; num_elements = 0; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS ++num_elements; /* For the ITC */ #endif if (MHD_INVALID_SOCKET != d->net.listen.fd) ++num_elements; /* For the listening socket */ if (! mhd_D_HAS_THR_PER_CONN (d)) num_elements += d->conns.cfg.count_limit; -#endif /* MHD_USE_POLL || MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_POLL || MHD_SUPPORT_EPOLL */ mhd_assert (0 != d->conns.cfg.count_limit); mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); @@ -1747,7 +1778,7 @@ allocate_events (struct MHD_Daemon *restrict d) #endif return MHD_SC_OK; /* Success exit point */ break; -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT case mhd_POLL_TYPE_SELECT: /* The pointers have been set to NULL during pre-initialisations of the events */ mhd_assert (NULL == d->events.data.select.rfds); @@ -1777,8 +1808,8 @@ allocate_events (struct MHD_Daemon *restrict d) "Failed to allocate memory for fd_sets for the daemon"); return MHD_SC_FD_SET_MEMORY_ALLOCATE_FAILURE; break; -#endif /* MHD_USE_SELECT */ -#ifdef MHD_USE_POLL +#endif /* MHD_SUPPORT_SELECT */ +#ifdef MHD_SUPPORT_POLL case mhd_POLL_TYPE_POLL: /* The pointers have been set to NULL during pre-initialisations of the events */ mhd_assert (NULL == d->events.data.poll.fds); @@ -1808,8 +1839,8 @@ allocate_events (struct MHD_Daemon *restrict d) "Failed to allocate memory for poll fds for the daemon"); return MHD_SC_POLL_FDS_MEMORY_ALLOCATE_FAILURE; break; -#endif /* MHD_USE_POLL */ -#ifdef MHD_USE_EPOLL +#endif /* MHD_SUPPORT_POLL */ +#ifdef MHD_SUPPORT_EPOLL case mhd_POLL_TYPE_EPOLL: mhd_assert (! mhd_D_HAS_THR_PER_CONN (d)); /* The event FD has been created during pre-initialisations of the events */ @@ -1844,16 +1875,16 @@ allocate_events (struct MHD_Daemon *restrict d) "Failed to allocate memory for epoll events for the daemon"); return MHD_SC_EPOLL_EVENTS_MEMORY_ALLOCATE_FAILURE; break; -#endif /* MHD_USE_EPOLL */ -#ifndef MHD_USE_SELECT +#endif /* MHD_SUPPORT_EPOLL */ +#ifndef MHD_SUPPORT_SELECT case mhd_POLL_TYPE_SELECT: -#endif /* ! MHD_USE_SELECT */ -#ifndef MHD_USE_POLL +#endif /* ! MHD_SUPPORT_SELECT */ +#ifndef MHD_SUPPORT_POLL case mhd_POLL_TYPE_POLL: -#endif /* ! MHD_USE_POLL */ -#ifndef MHD_USE_EPOLL +#endif /* ! MHD_SUPPORT_POLL */ +#ifndef MHD_SUPPORT_EPOLL case mhd_POLL_TYPE_EPOLL: -#endif /* ! MHD_USE_EPOLL */ +#endif /* ! MHD_SUPPORT_EPOLL */ case mhd_POLL_TYPE_NOT_SET_YET: default: mhd_UNREACHABLE (); @@ -1881,7 +1912,7 @@ deallocate_events (struct MHD_Daemon *restrict d) mhd_UNREACHABLE (); return; } -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT else if (mhd_POLL_TYPE_SELECT == d->events.poll_type) { mhd_assert (NULL != d->events.data.select.efds); @@ -1891,8 +1922,8 @@ deallocate_events (struct MHD_Daemon *restrict d) free (d->events.data.select.wfds); free (d->events.data.select.rfds); } -#endif /* MHD_USE_SELECT */ -#ifdef MHD_USE_POLL +#endif /* MHD_SUPPORT_SELECT */ +#ifdef MHD_SUPPORT_POLL else if (mhd_POLL_TYPE_POLL == d->events.poll_type) { mhd_assert (NULL != d->events.data.poll.rel); @@ -1900,15 +1931,15 @@ deallocate_events (struct MHD_Daemon *restrict d) free (d->events.data.poll.rel); free (d->events.data.poll.fds); } -#endif /* MHD_USE_POLL */ -#ifdef MHD_USE_EPOLL +#endif /* MHD_SUPPORT_POLL */ +#ifdef MHD_SUPPORT_EPOLL else if (mhd_POLL_TYPE_EPOLL == d->events.poll_type) { mhd_assert (0 != d->events.data.epoll.num_elements); mhd_assert (NULL != d->events.data.epoll.events); free (d->events.data.epoll.events); } -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ #ifndef NDEBUG d->dbg.events_allocated = false; #endif @@ -1928,7 +1959,7 @@ init_itc (struct MHD_Daemon *restrict d) { mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS // TODO: add and process "thread unsafe" daemon's option if (! mhd_itc_init (&(d->threading.itc))) { @@ -1961,7 +1992,7 @@ init_itc (struct MHD_Daemon *restrict d) mhd_itc_set_invalid (&(d->threading.itc)); return MHD_SC_ITC_FD_OUTSIDE_OF_SET_RANGE; } -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ return MHD_SC_OK; } @@ -1977,11 +2008,11 @@ deinit_itc (struct MHD_Daemon *restrict d) { mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS // TODO: add and process "thread unsafe" daemon's option mhd_assert (! mhd_ITC_IS_INVALID (d->threading.itc)); (void) mhd_itc_destroy (d->threading.itc); -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ } @@ -2001,7 +2032,7 @@ add_itc_and_listen_to_monitoring (struct MHD_Daemon *restrict d) mhd_assert (d->dbg.events_allocated); mhd_assert (! d->dbg.events_fully_inited); mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); #endif @@ -2013,7 +2044,7 @@ add_itc_and_listen_to_monitoring (struct MHD_Daemon *restrict d) // FIXME: Register the ITC and the listening NOW? return MHD_SC_OK; break; -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT case mhd_POLL_TYPE_SELECT: mhd_assert (NULL != d->events.data.select.rfds); mhd_assert (NULL != d->events.data.select.wfds); @@ -2021,8 +2052,8 @@ add_itc_and_listen_to_monitoring (struct MHD_Daemon *restrict d) /* Nothing to do when using 'select()' */ return MHD_SC_OK; break; -#endif /* MHD_USE_SELECT */ -#ifdef MHD_USE_POLL +#endif /* MHD_SUPPORT_SELECT */ +#ifdef MHD_SUPPORT_POLL case mhd_POLL_TYPE_POLL: mhd_assert (NULL != d->events.data.poll.fds); mhd_assert (NULL != d->events.data.poll.rel); @@ -2030,7 +2061,7 @@ add_itc_and_listen_to_monitoring (struct MHD_Daemon *restrict d) { unsigned int i; i = 0; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS d->events.data.poll.fds[i].fd = mhd_itc_r_fd (d->threading.itc); d->events.data.poll.fds[i].events = POLLIN; d->events.data.poll.rel[i].fd_id = mhd_SOCKET_REL_MARKER_ITC; @@ -2045,8 +2076,8 @@ add_itc_and_listen_to_monitoring (struct MHD_Daemon *restrict d) } return MHD_SC_OK; break; -#endif /* MHD_USE_POLL */ -#ifdef MHD_USE_EPOLL +#endif /* MHD_SUPPORT_POLL */ +#ifdef MHD_SUPPORT_EPOLL case mhd_POLL_TYPE_EPOLL: mhd_assert (MHD_INVALID_SOCKET != d->events.data.epoll.e_fd); mhd_assert (NULL != d->events.data.epoll.events); @@ -2054,7 +2085,7 @@ add_itc_and_listen_to_monitoring (struct MHD_Daemon *restrict d) if (1) { struct epoll_event reg_event; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS reg_event.events = EPOLLIN; reg_event.data.u64 = (uint64_t) mhd_SOCKET_REL_MARKER_ITC; /* uint64_t is used in the epoll header */ if (0 != epoll_ctl (d->events.data.epoll.e_fd, EPOLL_CTL_ADD, @@ -2080,16 +2111,16 @@ add_itc_and_listen_to_monitoring (struct MHD_Daemon *restrict d) } return MHD_SC_OK; break; -#endif /* MHD_USE_EPOLL */ -#ifndef MHD_USE_SELECT +#endif /* MHD_SUPPORT_EPOLL */ +#ifndef MHD_SUPPORT_SELECT case mhd_POLL_TYPE_SELECT: -#endif /* ! MHD_USE_SELECT */ -#ifndef MHD_USE_POLL +#endif /* ! MHD_SUPPORT_SELECT */ +#ifndef MHD_SUPPORT_POLL case mhd_POLL_TYPE_POLL: -#endif /* ! MHD_USE_POLL */ -#ifndef MHD_USE_EPOLL +#endif /* ! MHD_SUPPORT_POLL */ +#ifndef MHD_SUPPORT_EPOLL case mhd_POLL_TYPE_EPOLL: -#endif /* ! MHD_USE_EPOLL */ +#endif /* ! MHD_SUPPORT_EPOLL */ case mhd_POLL_TYPE_NOT_SET_YET: default: mhd_UNREACHABLE (); @@ -2127,7 +2158,7 @@ init_individual_conns (struct MHD_Daemon *restrict d, else if (256 > d->conns.cfg.mem_pool_size) d->conns.cfg.mem_pool_size = 256; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE mhd_DLINKEDL_INIT_LIST (&(d->conns.upgr),upgr_cleanup); if (! mhd_mutex_init (&(d->conns.upgr.ucu_lock))) { @@ -2136,7 +2167,7 @@ init_individual_conns (struct MHD_Daemon *restrict d, "connection list."); return MHD_SC_MUTEX_INIT_FAILURE; } -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ #ifndef NDEBUG d->dbg.connections_inited = true; @@ -2152,12 +2183,12 @@ init_individual_conns (struct MHD_Daemon *restrict d, static MHD_FN_PAR_NONNULL_ (1) void deinit_individual_conns (struct MHD_Daemon *restrict d) { -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE mhd_assert (NULL == mhd_DLINKEDL_GET_FIRST (&(d->conns.upgr),upgr_cleanup)); mhd_assert (NULL == mhd_DLINKEDL_GET_LAST (&(d->conns.upgr),upgr_cleanup)); mhd_mutex_destroy_chk (&(d->conns.upgr.ucu_lock)); -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ mhd_assert (0 != d->conns.cfg.mem_pool_size); mhd_assert (0 == d->conns.count); @@ -2204,10 +2235,10 @@ init_individual_thread_data_events_conns (struct MHD_Daemon *restrict d, #ifndef NDEBUG d->dbg.events_fully_inited = true; #endif -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_thread_handle_ID_set_invalid (&(d->threading.tid)); d->threading.stop_requested = false; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ #ifndef NDEBUG d->dbg.threading_inited = true; #endif @@ -2285,10 +2316,10 @@ set_connections_total_limits (struct MHD_Daemon *restrict d, } } num_worker_daemons = 1; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS if (mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)) num_worker_daemons = s->work_mode.params.num_worker_threads; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ limit_by_conf = s->global_connection_limit; limit_by_num = UINT_MAX; @@ -2305,9 +2336,9 @@ set_connections_total_limits (struct MHD_Daemon *restrict d, The real limit is lower, as any other process FDs will use the slots in the allowed numbers range */ limit_by_num -= 3; /* The numbers zero, one and two are used typically */ -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS limit_by_num -= mhd_ITC_NUM_FDS * num_worker_daemons; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ if (MHD_INVALID_SOCKET != d->net.listen.fd) --limit_by_num; /* One FD is used for the listening socket */ if ((num_worker_daemons > limit_by_num) || @@ -2334,7 +2365,7 @@ set_connections_total_limits (struct MHD_Daemon *restrict d, #elif defined(MHD_SOCKETS_KIND_WINSOCK) if (1) { -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT if ((mhd_DAEMON_TYPE_SINGLE == d->threading.d_type) && (mhd_POLL_TYPE_SELECT == d->events.poll_type)) { @@ -2344,9 +2375,9 @@ set_connections_total_limits (struct MHD_Daemon *restrict d, limit_per_worker = FD_SETSIZE; if (MHD_INVALID_SOCKET != d->net.listen.fd) --limit_per_worker; /* The slot for the listening socket */ -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS --limit_per_worker; /* The slot for the ITC */ -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ if ((0 == limit_per_worker) || (limit_per_worker > FD_SETSIZE)) error_by_fd_setsize = true; else @@ -2356,7 +2387,7 @@ set_connections_total_limits (struct MHD_Daemon *restrict d, limit_by_select = UINT_MAX; } } -#endif /* MHD_USE_SELECT */ +#endif /* MHD_SUPPORT_SELECT */ (void) 0; /* Mute compiler warning */ } #endif /* MHD_SOCKETS_KIND_POSIX */ @@ -2382,9 +2413,9 @@ set_connections_total_limits (struct MHD_Daemon *restrict d, #define TYPICAL_NOFILES_LIMIT (1024) /* The usual limit for the number of open FDs */ suggested_limit = TYPICAL_NOFILES_LIMIT; suggested_limit -= 3; /* The numbers zero, one and two are used typically */ -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS suggested_limit -= mhd_ITC_NUM_FDS * num_worker_daemons; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ if (MHD_INVALID_SOCKET != d->net.listen.fd) --suggested_limit; /* One FD is used for the listening socket */ if (suggested_limit > TYPICAL_NOFILES_LIMIT) @@ -2437,18 +2468,18 @@ set_d_threading_type (struct MHD_Daemon *restrict d) mhd_assert (! mhd_WM_INT_HAS_THREADS (d->wmode_int)); mhd_assert (mhd_POLL_TYPE_EXT == d->events.poll_type); mhd_assert (NULL != d->events.data.ext.cb); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS d->threading.d_type = mhd_DAEMON_TYPE_SINGLE; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ return MHD_SC_OK; case mhd_WM_INT_INTERNAL_EVENTS_NO_THREADS: mhd_assert (! mhd_WM_INT_HAS_THREADS (d->wmode_int)); mhd_assert (mhd_POLL_TYPE_EXT != d->events.poll_type); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS d->threading.d_type = mhd_DAEMON_TYPE_SINGLE; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ return MHD_SC_OK; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS case mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD: mhd_assert (mhd_WM_INT_HAS_THREADS (d->wmode_int)); mhd_assert (mhd_POLL_TYPE_EXT != d->events.poll_type); @@ -2465,11 +2496,11 @@ set_d_threading_type (struct MHD_Daemon *restrict d) mhd_assert (mhd_POLL_TYPE_EXT != d->events.poll_type); d->threading.d_type = mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY; return MHD_SC_OK; -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ case mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD: case mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION: case mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL: -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ default: break; } @@ -2478,7 +2509,7 @@ set_d_threading_type (struct MHD_Daemon *restrict d) } -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * De-initialise workers pool, including workers daemons. @@ -2507,10 +2538,10 @@ deinit_workers_pool (struct MHD_Daemon *restrict d, { /* Note: loop exits after underflow of 'i' */ struct MHD_Daemon *const worker = d->threading.hier.pool.workers + i; deinit_individual_thread_data_events_conns (worker); -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL if (mhd_POLL_TYPE_EPOLL == worker->events.poll_type) deinit_epoll (worker); -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ } free (d->threading.hier.pool.workers); #ifndef NDEBUG @@ -2608,7 +2639,7 @@ init_workers_pool (struct MHD_Daemon *restrict d, worker->conns.cfg.count_limit = conn_per_daemon; if (conn_remainder > i) worker->conns.cfg.count_limit++; /* Distribute the reminder */ -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL if (mhd_POLL_TYPE_EPOLL == worker->events.poll_type) { if (0 == i) @@ -2621,7 +2652,7 @@ init_workers_pool (struct MHD_Daemon *restrict d, else res = init_epoll (worker); } -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ if (MHD_SC_OK == res) { res = init_individual_thread_data_events_conns (worker, s); @@ -2630,10 +2661,10 @@ init_workers_pool (struct MHD_Daemon *restrict d, /* Below is a clean-up of the current slot */ -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL if (mhd_POLL_TYPE_EPOLL == worker->events.poll_type) deinit_epoll (worker); -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ } break; } @@ -2656,7 +2687,7 @@ init_workers_pool (struct MHD_Daemon *restrict d, } -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ /** * Initialise threading and inter-thread communications. @@ -2691,7 +2722,7 @@ daemon_init_threading_and_conn (struct MHD_Daemon *restrict d, if (! mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)) res = init_individual_thread_data_events_conns (d, s); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS else { res = init_workers_pool (d, s); @@ -2702,7 +2733,7 @@ daemon_init_threading_and_conn (struct MHD_Daemon *restrict d, d->threading.hier.pool.workers[0].conns.cfg.mem_pool_size; } } -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ if (MHD_SC_OK == res) { mhd_assert (d->dbg.events_allocated || \ @@ -2747,22 +2778,22 @@ daemon_deinit_threading_and_conn (struct MHD_Daemon *restrict d) } else { -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_assert (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL == d->wmode_int); mhd_assert (! d->dbg.connections_inited); mhd_assert (! d->dbg.events_allocated); mhd_assert (d->dbg.thread_pool_inited); deinit_workers_pool (d, d->threading.hier.pool.num); -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ mhd_assert (0 && "Impossible value"); mhd_UNREACHABLE (); (void) 0; -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ } } -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * Start the daemon individual single thread. @@ -2952,7 +2983,7 @@ start_worker_pool_threads (struct MHD_Daemon *restrict d) } -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ /** * Start the daemon internal threads, if the daemon configured to use them. @@ -2970,7 +3001,7 @@ daemon_start_threads (struct MHD_Daemon *restrict d) mhd_assert (! mhd_D_TYPE_IS_INTERNAL_ONLY (d->threading.d_type)); if (mhd_WM_INT_HAS_THREADS (d->wmode_int)) { -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS if (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL != d->wmode_int) { mhd_assert (d->dbg.threading_inited); @@ -2983,11 +3014,11 @@ daemon_start_threads (struct MHD_Daemon *restrict d) mhd_assert (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY == d->threading.d_type); return start_worker_pool_threads (d); } -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ mhd_assert (0 && "Impossible value"); mhd_UNREACHABLE (); return MHD_SC_INTERNAL_ERROR; -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ } return MHD_SC_OK; } @@ -3007,7 +3038,7 @@ daemon_stop_threads (struct MHD_Daemon *restrict d) mhd_assert (d->dbg.threading_inited); if (mhd_WM_INT_HAS_THREADS (d->wmode_int)) { -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS if (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL != d->wmode_int) { mhd_assert (d->dbg.threading_inited); @@ -3022,11 +3053,11 @@ daemon_stop_threads (struct MHD_Daemon *restrict d) stop_worker_pool_threads (d, d->threading.hier.pool.num); return; } -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ mhd_assert (0 && "Impossible value"); mhd_UNREACHABLE (); return MHD_SC_INTERNAL_ERROR; -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ } } @@ -3046,6 +3077,10 @@ daemon_start_internal (struct MHD_Daemon *restrict d, { enum MHD_StatusCode res; + res = daemon_set_basic_settings (d, s); + if (MHD_SC_OK != res) + return res; + res = daemon_set_work_mode (d, s); if (MHD_SC_OK != res) return res; diff --git a/src/mhd2/events_process.c b/src/mhd2/events_process.c @@ -35,7 +35,7 @@ #include "mhd_socket_type.h" #include "sys_poll.h" #include "sys_select.h" -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL # include <sys/epoll.h> #endif #ifdef MHD_SOCKETS_KIND_POSIX @@ -58,20 +58,22 @@ #include "conn_data_process.h" #include "stream_funcs.h" -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE # include "upgrade_proc.h" -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ #include "mhd_public_api.h" -static int -get_max_wait (struct MHD_Daemon *restrict d) +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ uint_fast64_t +mhd_daemon_get_wait_max (struct MHD_Daemon *restrict d) { bool zero_wait = d->events.zero_wait; + + mhd_assert (! mhd_D_HAS_WORKERS (d)); + if (d->events.act_req.accept && d->conns.block_new) d->events.act_req.accept = false; - d->events.zero_wait = false; /* Reset as this pending data will be processed */ if (d->events.act_req.accept) return 0; if (zero_wait) @@ -79,10 +81,33 @@ get_max_wait (struct MHD_Daemon *restrict d) if (NULL != mhd_DLINKEDL_GET_FIRST (&(d->events), proc_ready)) return 0; - return INT_MAX; // TODO: calculate correct timeout value + return MHD_WAIT_INDEFINITELY; // TODO: calculate correct timeout value } +mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE + +static MHD_FN_PAR_NONNULL_ALL_ int +get_max_wait (struct MHD_Daemon *restrict d) +{ + uint_fast64_t ui64_wait = mhd_daemon_get_wait_max (d); + int i_wait = (int) ui64_wait; + + // TODO: move reset to the processing loop + d->events.zero_wait = false; /* Reset as this pending data will be processed */ + + if ((0 > i_wait) || + (ui64_wait != (uint_fast64_t) i_wait)) + return INT_MAX; + + return i_wait; +} + + +mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE +/* End of warning-less data truncation */ + + MHD_FN_PAR_NONNULL_ (1) static void update_conn_net_status (struct MHD_Daemon *restrict d, struct MHD_Connection *restrict c, @@ -140,7 +165,7 @@ daemon_accept_new_conns (struct MHD_Daemon *restrict d) if (slots_left < num_to_accept) num_to_accept = slots_left; } -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS else { /* Has workers thread pool. Care must be taken to evenly distribute @@ -221,7 +246,7 @@ daemon_accept_new_conns (struct MHD_Daemon *restrict d) else if (slots_left > num_to_accept) num_to_accept = slots_left; } -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ } while (0 != --num_to_accept) @@ -247,14 +272,14 @@ daemon_accept_new_conns (struct MHD_Daemon *restrict d) MHD_static_inline_ MHD_FN_PAR_NONNULL_ALL_ bool is_conn_excluded_from_http_comm (struct MHD_Connection *restrict c) { -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE if (NULL != c->upgr.c) { mhd_assert ((mhd_HTTP_STAGE_UPGRADED == c->stage) || \ (mhd_HTTP_STAGE_UPGRADED_CLEANING == c->stage)); return true; } -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ // TODO: Support suspended connection @@ -286,7 +311,7 @@ daemon_process_all_active_conns (struct MHD_Daemon *restrict d) } -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE /** * Clean-up all HTTP-Upgraded connections scheduled for clean-up * @param d the daemon to process @@ -318,9 +343,9 @@ daemon_cleanup_upgraded_conns (struct MHD_Daemon *restrict d) } -#else /* ! MHD_UPGRADE_SUPPORT */ +#else /* ! MHD_SUPPORT_UPGRADE */ #define daemon_cleanup_upgraded_conns(d) ((void) d) -#endif /* ! MHD_UPGRADE_SUPPORT */ +#endif /* ! MHD_SUPPORT_UPGRADE */ static void close_all_daemon_conns (struct MHD_Daemon *d) @@ -335,7 +360,7 @@ close_all_daemon_conns (struct MHD_Daemon *d) NULL != c; c = mhd_DLINKEDL_GET_LAST (&(d->conns),all_conn)) { -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE mhd_assert (mhd_HTTP_STAGE_UPGRADING != c->stage); mhd_assert (mhd_HTTP_STAGE_UPGRADED_CLEANING != c->stage); if (NULL != c->upgr.c) @@ -364,7 +389,7 @@ close_all_daemon_conns (struct MHD_Daemon *d) } -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT /** * Add socket to the fd_set @@ -434,7 +459,7 @@ select_update_fdsets (struct MHD_Daemon *restrict d, FD_ZERO (efds); ret = 0; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); fd_set_wrap (mhd_itc_r_fd (d->threading.itc), rfds, @@ -504,7 +529,7 @@ select_update_statuses_from_fdsets (struct MHD_Daemon *d, return true; #endif /* MHD_FAVOR_SMALL_CODE */ -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); if (FD_ISSET (mhd_itc_r_fd (d->threading.itc), efds)) { @@ -528,7 +553,7 @@ select_update_statuses_from_fdsets (struct MHD_Daemon *d, if (0 == num_events) return true; #endif /* MHD_FAVOR_SMALL_CODE */ -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ if (MHD_INVALID_SOCKET != d->net.listen.fd) { @@ -679,10 +704,10 @@ get_all_net_updates_by_select (struct MHD_Daemon *restrict d, } -#endif /* MHD_USE_SELECT */ +#endif /* MHD_SUPPORT_SELECT */ -#ifdef MHD_USE_POLL +#ifdef MHD_SUPPORT_POLL static MHD_FN_PAR_NONNULL_ (1) unsigned int poll_update_fds (struct MHD_Daemon *restrict d, @@ -698,7 +723,7 @@ poll_update_fds (struct MHD_Daemon *restrict d, mhd_assert (mhd_POLL_TYPE_POLL == d->events.poll_type); i_s = 0; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); mhd_assert (d->events.data.poll.fds[i_s].fd == \ mhd_itc_r_fd (d->threading.itc)); @@ -765,7 +790,7 @@ poll_update_statuses_from_fds (struct MHD_Daemon *restrict d, return true; i_s = 0; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); mhd_assert (d->events.data.poll.fds[i_s].fd == \ mhd_itc_r_fd (d->threading.itc)); @@ -792,7 +817,7 @@ poll_update_statuses_from_fds (struct MHD_Daemon *restrict d, if (0 == num_events) return true; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ if (MHD_INVALID_SOCKET != d->net.listen.fd) { @@ -932,9 +957,9 @@ get_all_net_updates_by_poll (struct MHD_Daemon *restrict d, } -#endif /* MHD_USE_POLL */ +#endif /* MHD_SUPPORT_POLL */ -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL /** * Map events provided by epoll to connection states, ITC and @@ -1059,7 +1084,7 @@ get_all_net_updates_by_epoll (struct MHD_Daemon *restrict d) } -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ static MHD_FN_PAR_NONNULL_ (1) bool @@ -1070,33 +1095,33 @@ process_all_events_and_data (struct MHD_Daemon *restrict d) case mhd_POLL_TYPE_EXT: return false; // TODO: implement break; -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT case mhd_POLL_TYPE_SELECT: if (! get_all_net_updates_by_select (d, false)) return false; break; -#endif /* MHD_USE_SELECT */ -#ifdef MHD_USE_POLL +#endif /* MHD_SUPPORT_SELECT */ +#ifdef MHD_SUPPORT_POLL case mhd_POLL_TYPE_POLL: if (! get_all_net_updates_by_poll (d, false)) return false; break; -#endif /* MHD_USE_POLL */ -#ifdef MHD_USE_EPOLL +#endif /* MHD_SUPPORT_POLL */ +#ifdef MHD_SUPPORT_EPOLL case mhd_POLL_TYPE_EPOLL: if (! get_all_net_updates_by_epoll (d)) return false; break; -#endif /* MHD_USE_EPOLL */ -#ifndef MHD_USE_SELECT +#endif /* MHD_SUPPORT_EPOLL */ +#ifndef MHD_SUPPORT_SELECT case mhd_POLL_TYPE_SELECT: -#endif /* ! MHD_USE_SELECT */ -#ifndef MHD_USE_POLL +#endif /* ! MHD_SUPPORT_SELECT */ +#ifndef MHD_SUPPORT_POLL case mhd_POLL_TYPE_POLL: -#endif /* ! MHD_USE_POLL */ -#ifndef MHD_USE_EPOLL +#endif /* ! MHD_SUPPORT_POLL */ +#ifndef MHD_SUPPORT_EPOLL case mhd_POLL_TYPE_EPOLL: -#endif /* ! MHD_USE_EPOLL */ +#endif /* ! MHD_SUPPORT_EPOLL */ case mhd_POLL_TYPE_NOT_SET_YET: default: mhd_UNREACHABLE (); @@ -1135,6 +1160,11 @@ mhd_worker_all_events (void *cls) mhd_assert (d->dbg.events_fully_inited); mhd_assert (d->dbg.connections_inited); +#ifdef mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE + // TODO: store and use the result + (void) mhd_thread_block_sigpipe (); +#endif + while (! d->threading.stop_requested) { if (d->threading.resume_requested) @@ -1160,19 +1190,19 @@ process_listening_and_itc_only (struct MHD_Daemon *restrict d) { if (false) (void) 0; -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT else if (mhd_POLL_TYPE_SELECT == d->events.poll_type) { return false; // TODO: implement } -#endif /* MHD_USE_SELECT */ -#ifdef MHD_USE_POLL +#endif /* MHD_SUPPORT_SELECT */ +#ifdef MHD_SUPPORT_POLL else if (mhd_POLL_TYPE_POLL == d->events.poll_type) { if (! get_all_net_updates_by_poll (d, true)) return false; } -#endif /* MHD_USE_POLL */ +#endif /* MHD_SUPPORT_POLL */ else { mhd_assert (0 && "Impossible value"); @@ -1201,6 +1231,11 @@ mhd_worker_listening_only (void *cls) mhd_assert (d->dbg.events_fully_inited); mhd_assert (d->dbg.connections_inited); +#ifdef mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE + // TODO: store and use the result + (void) mhd_thread_block_sigpipe (); +#endif + while (! d->threading.stop_requested) { if (! process_listening_and_itc_only (d)) diff --git a/src/mhd2/events_process.h b/src/mhd2/events_process.h @@ -29,8 +29,12 @@ #include "mhd_sys_options.h" +#include "sys_base_types.h" + #include "sys_thread_entry_type.h" +struct MHD_Daemon; /* forward declaration */ + /** * The entry point for the daemon worker thread * @param cls the closure @@ -52,4 +56,14 @@ mhd_worker_listening_only (void *cls); mhd_THRD_RTRN_TYPE mhd_THRD_CALL_SPEC mhd_worker_connection (void *cls); +/** + * Get maximum wait time for the daemon + * @param d the daemon to check + * @return the maximum wait time, + * #MHD_WAIT_INDEFINITELY if wait time is not limited + */ +MHD_INTERNAL uint_fast64_t +mhd_daemon_get_wait_max (struct MHD_Daemon *restrict d) +MHD_FN_PAR_NONNULL_ALL_; + #endif /* ! MHD_EVENTS_PROCESS_H */ diff --git a/src/mhd2/lib_get_info.c b/src/mhd2/lib_get_info.c @@ -1,6 +1,6 @@ /* This file is part of GNU libmicrohttpd - Copyright (C) 2024 Evgeny Grin (Karlson2k) + Copyright (C) 2024-2025 Evgeny Grin (Karlson2k) GNU libmicrohttpd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -34,152 +34,398 @@ #include "mhd_str_types.h" #include "mhd_str_macros.h" +#include "sys_sockets_headers.h" +#include "sys_ip_headers.h" + +#ifdef MHD_SUPPORT_THREADS +# include "mhd_threads.h" +#endif + +#include "mhd_itc.h" + #ifndef VERSION # include "mhd_str.h" #endif -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "mhd_tls_choice.h" /* Include all supported TLS backends headers */ -# if defined(MHD_USE_GNUTLS) +# if defined(MHD_SUPPORT_GNUTLS) # include "tls_gnu_funcs.h" # endif -# if defined(MHD_USE_OPENSSL) +# if defined(MHD_SUPPORT_OPENSSL) # include "tls_open_funcs.h" # endif #endif +#ifdef MHD_SUPPORT_MD5 +# include "mhd_md5.h" +#endif +#ifdef MHD_SUPPORT_SHA256 +# include "mhd_sha256.h" +#endif +#ifdef MHD_SUPPORT_SHA512_256 +# include "mhd_sha512_256.h" +#endif + #include "mhd_lib_init.h" +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + #include "mhd_public_api.h" MHD_EXTERN_ -MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2) -MHD_FN_PURE_ enum MHD_StatusCode +MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2) enum MHD_StatusCode MHD_lib_get_info_fixed_sz (enum MHD_LibInfoFixed info_type, - union MHD_LibInfoFixedData *return_data, - size_t return_data_size) + union MHD_LibInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) { switch (info_type) { + + /* * Basic MHD information * */ + case MHD_LIB_INFO_FIXED_VERSION_NUM: - if (sizeof(return_data->v_uint32) > return_data_size) + if (sizeof(output_buf->v_uint32) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; #if ! MHD_VERSION #error MHD_VERSION is not defined #endif - return_data->v_uint32 = MHD_VERSION; + output_buf->v_uint32 = (uint_fast32_t) MHD_VERSION; return MHD_SC_OK; case MHD_LIB_INFO_FIXED_VERSION_STR: - if (sizeof(return_data->v_string) <= return_data_size) + if (sizeof(output_buf->v_string) <= output_buf_size) { #ifdef VERSION static const struct MHD_String ver_str = mhd_MSTR_INIT (VERSION); - return_data->v_string.len = ver_str.len; - return_data->v_string.cstr = ver_str.cstr; + output_buf->v_string.len = ver_str.len; + output_buf->v_string.cstr = ver_str.cstr; return MHD_SC_OK; #else /* ! VERSION */ static char str_buf[10] = - {0, 0, 0, 0, 0, 0, 0, 0, 1, 1}; /* Larger than needed */ - if (0 != str_buf[9]) + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}; /* Larger than needed */ + if (0 != str_buf[8]) { uint_fast32_t ver_num = MHD_VERSION; uint8_t digit; digit = (uint8_t) (ver_num >> 24); - mhd_bin_to_hex (digit, - 1, - str_buf); - str_buf[3] = '.'; + (void) mhd_bin_to_hex (&digit, + 1, + str_buf); + str_buf[2] = '.'; digit = (uint8_t) (ver_num >> 16); - mhd_bin_to_hex (digit, - 1, - str_buf + 4); - str_buf[6] = '.'; + (void) mhd_bin_to_hex (&digit, + 1, + str_buf + 3); + str_buf[5] = '.'; digit = (uint8_t) (ver_num >> 8); - mhd_bin_to_hex (digit, - 1, - str_buf + 7); - str_buf[9] = 0; + (void) mhd_bin_to_hex (&digit, + 1, + str_buf + 6); + str_buf[8] = 0; } - return_data->v_string.len = 9; - return_data->v_string.cstr = str_buf; + output_buf->v_string.len = 8; + output_buf->v_string.cstr = str_buf; return MHD_SC_OK; #endif /* ! VERSION */ } return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - case MHD_LIB_INFO_FIXED_HAS_MESSAGES: + + /* * Basic MHD features, buid-time configurable * */ + + case MHD_LIB_INFO_FIXED_HAS_LOG_MESSAGES: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; + case MHD_LIB_INFO_FIXED_HAS_AUTO_REPLIES_BODIES: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_ENABLE_AUTO_MESSAGES_BODIES + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; + case MHD_LIB_INFO_FIXED_IS_NON_DEBUG: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef NDEBUG + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_THREADS: - case MHD_LIB_INFO_FIXED_HAS_DEBUG: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_THREADS + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_COOKIE_PARSER: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_COOKIES + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_POST_PARSER: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_POST_PARSER + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_UPGRADE: - mhd_assert (0 && "Not implemented yet"); - break; - case MHD_LIB_INFO_FIXED_HAS_BASIC_AUTH: - if (sizeof(return_data->v_bool) > return_data_size) + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_UPGRADE + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; + case MHD_LIB_INFO_FIXED_HAS_AUTH_BASIC: + if (sizeof(output_buf->v_bool) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; #ifdef MHD_SUPPORT_AUTH_BASIC - return_data->v_bool = MHD_YES; + output_buf->v_bool = MHD_YES; #else - return_data->v_bool = MHD_NO; + output_buf->v_bool = MHD_NO; #endif return MHD_SC_OK; - case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH: - if (sizeof(return_data->v_bool) > return_data_size) + case MHD_LIB_INFO_FIXED_HAS_AUTH_DIGEST: + case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH_RFC2069: + case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH_USERHASH: + if (sizeof(output_buf->v_bool) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; #ifdef MHD_SUPPORT_AUTH_DIGEST - return_data->v_bool = MHD_YES; + output_buf->v_bool = MHD_YES; #else - return_data->v_bool = MHD_NO; + output_buf->v_bool = MHD_NO; #endif return MHD_SC_OK; - case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH_RFC2069: case MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_MD5: + if (sizeof(output_buf->v_d_algo) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#if ! defined(MHD_SUPPORT_MD5) + output_buf->v_d_algo = MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_NOT_AVAILABLE; +#elif ! defined(MHD_MD5_EXTR) + output_buf->v_d_algo = MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_BUILT_IN; +#elif ! defined(mhd_MD5_HAS_EXT_ERROR) + output_buf->v_d_algo = + MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_EXTERNAL_NEVER_FAIL; +#else + output_buf->v_d_algo = + MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_EXTERNAL_MAY_FAIL; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_SHA256: + if (sizeof(output_buf->v_d_algo) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#if ! defined(MHD_SUPPORT_SHA256) + output_buf->v_d_algo = MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_NOT_AVAILABLE; +#elif ! defined(MHD_SHA256_EXTR) + output_buf->v_d_algo = MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_BUILT_IN; +#elif ! defined(mhd_SHA256_HAS_EXT_ERROR) + output_buf->v_d_algo = + MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_EXTERNAL_NEVER_FAIL; +#else + output_buf->v_d_algo = + MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_EXTERNAL_MAY_FAIL; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_SHA512_256: + if (sizeof(output_buf->v_d_algo) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#if ! defined(MHD_SUPPORT_SHA512_256) + output_buf->v_d_algo = MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_NOT_AVAILABLE; +#elif ! defined(MHD_SHA512_256_EXTR) + output_buf->v_d_algo = MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_BUILT_IN; +#elif ! defined(mhd_SHA512_256_HAS_EXT_ERROR) + output_buf->v_d_algo = + MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_EXTERNAL_NEVER_FAIL; +#else + output_buf->v_d_algo = + MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_EXTERNAL_MAY_FAIL; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH_AUTH_INT: case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH_ALGO_SESSION: - case MHD_LIB_INFO_FIXED_HAS_DIGEST_AUTH_USERHASH: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_bool = MHD_NO; + return MHD_SC_OK; + + /* * Platform-dependent features, some are configurable at build-time * */ + case MHD_LIB_INFO_FIXED_TYPE_SOCKETS_POLLING: + if (sizeof(output_buf->v_polling) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_SELECT + output_buf->v_polling.func_select = MHD_YES; +#else + output_buf->v_polling.func_select = MHD_NO; +#endif +#ifdef MHD_SUPPORT_POLL + output_buf->v_polling.func_poll = MHD_YES; +#else + output_buf->v_polling.func_poll = MHD_NO; +#endif +#ifdef MHD_SUPPORT_EPOLL + output_buf->v_polling.tech_epoll = MHD_YES; +#else + output_buf->v_polling.tech_epoll = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_AGGREGATE_FD: - case MHD_LIB_INFO_FIXED_TYPE_IPv6: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_EPOLL + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; + case MHD_LIB_INFO_FIXED_TYPE_IPV6: + if (sizeof(output_buf->v_ipv6) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#if ! defined(HAVE_INET6) + output_buf->v_ipv6 = MHD_LIB_INFO_FIXED_IPV6_TYPE_NONE; +#elif ! defined(HAVE_DCLR_IPV6_V6ONLY) + output_buf->v_ipv6 = MHD_LIB_INFO_FIXED_IPV6_TYPE_DUAL_ONLY; +#else + output_buf->v_ipv6 = MHD_LIB_INFO_FIXED_IPV6_TYPE_IPV6_PURE; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_TCP_FASTOPEN: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef HAVE_DCLR_TCP_FASTOPEN + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_AUTODETECT_BIND_PORT: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_USE_GETSOCKNAME + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_SENDFILE: - case MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef mhd_USE_SENDFILE + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; + case MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_INT: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#if ! defined (mhd_SEND_SPIPE_SUPPRESS_NEEDED) + output_buf->v_bool = MHD_YES; +#elif defined (mhd_SEND_SPIPE_SUPPRESS_POSSIBLE) \ + || defined(mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE) + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; + case MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_EXT: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#if ! defined (mhd_SEND_SPIPE_SUPPRESS_NEEDED) + output_buf->v_bool = MHD_YES; +#elif defined (mhd_SEND_SPIPE_SUPPRESS_POSSIBLE) + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_THREAD_NAMES: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef mhd_USE_THREAD_NAME + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_TYPE_ITC: + if (sizeof(output_buf->v_itc) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#if ! defined(MHD_SUPPORT_THREADS) + output_buf->v_itc = MHD_LIB_INFO_FIXED_ITC_TYPE_NONE; +#elif defined(MHD_ITC_SOCKETPAIR_) + output_buf->v_itc = MHD_LIB_INFO_FIXED_ITC_TYPE_SOCKETPAIR; +#elif defined(MHD_ITC_PIPE_) + output_buf->v_itc = MHD_LIB_INFO_FIXED_ITC_TYPE_PIPE; +#elif defined(MHD_ITC_EVENTFD_) + output_buf->v_itc = MHD_LIB_INFO_FIXED_ITC_TYPE_EVENTFD; +#else +#error The type of ITC is not defined +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_HAS_LARGE_FILE: - mhd_assert (0 && "Not implemented yet"); - break; + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#if ! defined(HAVE_PREAD) && defined(lseek64) + output_buf->v_bool = MHD_YES; +#elif defined(HAVE_PREAD64) + output_buf->v_bool = MHD_YES; +#elif defined(mhd_W32_NATIVE) + output_buf->v_bool = MHD_YES; +#else + output_buf->v_bool = + (0x7FFFFFFFFFFFFFFF == ((off_t) 0x7FFFFFFFFFFFFFFF)) ? MHD_YES : MHD_NO; +#endif + return MHD_SC_OK; case MHD_LIB_INFO_FIXED_TYPE_TLS: - if (sizeof(return_data->v_tls) <= return_data_size) + case MHD_LIB_INFO_FIXED_HAS_TLS_KEY_PASSWORD: /* Both backends have support */ + if (sizeof(output_buf->v_tls) <= output_buf_size) { -#ifndef MHD_ENABLE_HTTPS - return_data->v_tls.tls_supported = MHD_NO; - return_data->v_tls.backend_gnutls = MHD_NO; - return_data->v_tls.backend_openssl = MHD_NO; -#else - return_data->v_tls.tls_supported = MHD_YES; -# ifdef MHD_USE_GNUTLS - return_data->v_tls.backend_gnutls = MHD_YES; -# else /* ! MHD_USE_GNUTLS */ - return_data->v_tls.backend_gnutls = MHD_NO; -# endif /* ! MHD_USE_GNUTLS */ -# ifdef MHD_USE_OPENSSL - return_data->v_tls.backend_openssl = MHD_YES; -# else /* ! MHD_USE_OPENSSL */ - return_data->v_tls.backend_openssl = MHD_NO; -# endif /* ! MHD_USE_OPENSSL */ +#ifndef MHD_SUPPORT_HTTPS + output_buf->v_tls.tls_supported = MHD_NO; + output_buf->v_tls.backend_gnutls = MHD_NO; + output_buf->v_tls.backend_openssl = MHD_NO; +#else + output_buf->v_tls.tls_supported = MHD_YES; +# ifdef MHD_SUPPORT_GNUTLS + output_buf->v_tls.backend_gnutls = MHD_YES; +# else /* ! MHD_SUPPORT_GNUTLS */ + output_buf->v_tls.backend_gnutls = MHD_NO; +# endif /* ! MHD_SUPPORT_GNUTLS */ +# ifdef MHD_SUPPORT_OPENSSL + output_buf->v_tls.backend_openssl = MHD_YES; +# else /* ! MHD_SUPPORT_OPENSSL */ + output_buf->v_tls.backend_openssl = MHD_NO; +# endif /* ! MHD_SUPPORT_OPENSSL */ #endif return MHD_SC_OK; } return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - case MHD_LIB_INFO_FIXED_HAS_TLS_KEY_PASSWORD: - mhd_assert (0 && "Not implemented yet"); break; case MHD_LIB_INFO_FIXED_SENTINEL: default: @@ -189,40 +435,50 @@ MHD_lib_get_info_fixed_sz (enum MHD_LibInfoFixed info_type, } -MHD_EXTERN_ +MHD_EXTERN_ MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2) enum MHD_StatusCode -MHD_lib_get_info_dynamic_sz (enum MHD_LibInfoDynamic info_type, - union MHD_LibInfoDynamicData *return_data, - size_t return_data_size) +MHD_lib_get_info_dynamic_sz ( + enum MHD_LibInfoDynamic info_type, + union MHD_LibInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) { switch (info_type) { - case MHD_LIB_INFO_DYNAMIC_INITED: - mhd_assert (0 && "Not implemented yet"); - break; + case MHD_LIB_INFO_DYNAMIC_INITED_FULLY_ONCE: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_bool = + mhd_lib_is_fully_initialised_once () ? MHD_YES : MHD_NO; + return MHD_SC_OK; + case MHD_LIB_INFO_DYNAMIC_INITED_FULLY_NOW: + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_bool = + mhd_lib_is_fully_initialised_now () ? MHD_YES : MHD_NO; + return MHD_SC_OK; case MHD_LIB_INFO_DYNAMIC_TYPE_TLS: - if (sizeof(return_data->v_tls) <= return_data_size) + if (sizeof(output_buf->v_tls) <= output_buf_size) { -#ifndef MHD_ENABLE_HTTPS - return_data->v_tls.tls_supported = MHD_NO; - return_data->v_tls.backend_gnutls = MHD_NO; - return_data->v_tls.backend_openssl = MHD_NO; +#ifndef MHD_SUPPORT_HTTPS + output_buf->v_tls.tls_supported = MHD_NO; + output_buf->v_tls.backend_gnutls = MHD_NO; + output_buf->v_tls.backend_openssl = MHD_NO; #else bool gnutls_avail; bool openssl_avail; if (! mhd_lib_init_global_if_needed ()) - return MHD_SC_INFO_GET_TYPE_UNAVAILALBE; + return MHD_SC_INFO_GET_TYPE_UNOBTAINABLE; gnutls_avail = mhd_tls_gnu_is_inited_fine (); openssl_avail = mhd_tls_open_is_inited_fine (); - return_data->v_tls.tls_supported = + output_buf->v_tls.tls_supported = (gnutls_avail || openssl_avail) ? MHD_YES : MHD_NO; - return_data->v_tls.backend_gnutls = gnutls_avail ? MHD_YES : MHD_NO; - return_data->v_tls.backend_openssl = openssl_avail ? MHD_YES : MHD_NO; + output_buf->v_tls.backend_gnutls = gnutls_avail ? MHD_YES : MHD_NO; + output_buf->v_tls.backend_openssl = openssl_avail ? MHD_YES : MHD_NO; mhd_lib_deinit_global_if_needed (); #endif diff --git a/src/mhd2/md5_ext.c b/src/mhd2/md5_ext.c @@ -69,6 +69,7 @@ mhd_MD5_update (struct mhd_Md5CtxExt *ctx, size_t size, const uint8_t *data) { + mhd_assert (0 != size); if (0 == ctx->ext_error) ctx->ext_error = gnutls_hash (ctx->handle, data, size); } diff --git a/src/mhd2/md5_int.c b/src/mhd2/md5_int.c @@ -387,12 +387,7 @@ mhd_MD5_update (struct mhd_Md5CtxInt *restrict ctx, { unsigned int bytes_have; /**< Number of bytes in the context buffer */ - mhd_assert ((data != NULL) || (size == 0)); - -#ifndef MHD_FAVOR_SMALL_CODE - if (0 == size) - return; /* Shortcut, do nothing */ -#endif /* MHD_FAVOR_SMALL_CODE */ + mhd_assert (0 != size); /* Note: (count & (mhd_MD5_BLOCK_SIZE-1)) equals (count % mhd_MD5_BLOCK_SIZE) for this block size. */ diff --git a/src/mhd2/mhd_action.h b/src/mhd2/mhd_action.h @@ -33,7 +33,7 @@ #include "mhd_str_types.h" -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER # include "http_post_enc.h" # include "mhd_bool.h" # include "mhd_post_result.h" @@ -61,25 +61,25 @@ enum mhd_ActionType * Process clients upload by application callback */ mhd_ACTION_UPLOAD -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER , /** * Process POST data clients upload by POST parser */ mhd_ACTION_POST_PARSE -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ , /** * Suspend requests (connection) */ mhd_ACTION_SUSPEND -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE , /** * Perform HTTP "upgrade" */ mhd_ACTION_UPGRADE -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ , /** * Hard close request with no response @@ -143,7 +143,7 @@ struct mhd_UploadCallbacks struct mhd_UploadCallbackData inc; }; -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER #ifndef MHD_POST_DATA_READER_DEFINED typedef const struct MHD_UploadAction * @@ -208,10 +208,10 @@ struct mhd_PostParseActionData void *done_cb_cls; }; -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE struct MHD_UpgradedHandle; /* forward declaration */ @@ -242,7 +242,7 @@ struct mhd_UpgradeActionData void *cb_cls; }; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ /** @@ -260,18 +260,18 @@ union mhd_ActionData */ struct mhd_UploadCallbacks upload; -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER /** * The data for the action #mhd_ACTION_POST_PARSE */ struct mhd_PostParseActionData post_parse; -#endif /* HAVE_POST_PARSER */ -#ifdef MHD_UPGRADE_SUPPORT +#endif /* MHD_SUPPORT_POST_PARSER */ +#ifdef MHD_SUPPORT_UPGRADE /** * The data for "Upgrade" action */ struct mhd_UpgradeActionData upgrd; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ }; @@ -315,13 +315,13 @@ enum mhd_UploadActionType * Suspend requests (connection) */ mhd_UPLOAD_ACTION_SUSPEND -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE , /** * Perform HTTP "upgrade" */ mhd_UPLOAD_ACTION_UPGRADE -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ , /** * Hard close request with no response @@ -346,12 +346,12 @@ union mhd_UploadActionData * The data for the action #mhd_ACTION_RESPONSE */ struct MHD_Response *response; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE /** * The data for "Upgrade" action */ struct mhd_UpgradeActionData upgrd; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ }; /** diff --git a/src/mhd2/mhd_atomic_counter.h b/src/mhd2/mhd_atomic_counter.h @@ -46,20 +46,20 @@ #define mhd_ATOMIC_COUNTER_MAX \ ((mhd_ATOMIC_COUNTER_TYPE) (~((mhd_ATOMIC_COUNTER_TYPE) 0))) -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * Atomic operations are based on locks */ # define mhd_ATOMIC_BY_LOCKS 1 -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ /** * Atomic because single thread environment is used */ # define mhd_ATOMIC_SINGLE_THREAD 1 -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ #if defined(mhd_ATOMIC_BY_LOCKS) diff --git a/src/mhd2/mhd_connection.h b/src/mhd2/mhd_connection.h @@ -47,16 +47,17 @@ #include "mhd_request.h" #include "mhd_reply.h" +#include "mhd_stream.h" -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE # include "mhd_upgrade.h" -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ #include "mhd_socket_error.h" #include "mhd_public_api.h" -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "mhd_tls_choice.h" /* For the TLS struct forward declaration */ #endif @@ -160,7 +161,7 @@ enum MHD_FIXED_ENUM_ mhd_ConnState mhd_CONN_STATE_CLOSED = mhd_CONN_FLAG_CLOSED }; -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS /** * The status of TLS buffer for incoming (receive) data */ @@ -176,7 +177,7 @@ enum mhd_TlsBufDataIn */ mhd_TLS_BUF_HAS_DATA_IN = mhd_SOCKET_NET_STATE_RECV_READY }; -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ /** @@ -205,13 +206,13 @@ enum MHD_FIXED_FLAGS_ENUM_ MHD_ConnectionEventLoopInfo * We are finished and are awaiting cleanup. */ MHD_EVENT_LOOP_INFO_CLEANUP = 1 << 5 -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE , /** * We are finished and are awaiting cleanup. */ MHD_EVENT_LOOP_INFO_UPGRADED = 1 << 6 -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ }; #define MHD_EVENT_LOOP_INFO_PROCESS_READ \ @@ -378,13 +379,13 @@ enum MHD_FIXED_ENUM_ mhd_HttpStage * We have sent the response headers. Get ready to send the body. */ mhd_HTTP_STAGE_HEADERS_SENT -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE , /** * Sending special HTTP "Upgrade" headers */ mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ , /** * We are waiting for the client to provide more @@ -422,7 +423,7 @@ enum MHD_FIXED_ENUM_ mhd_HttpStage * Shutdown connection or restart processing to get a new request. */ mhd_HTTP_STAGE_FULL_REPLY_SENT -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE , /** * Transition to "Upgraded" state @@ -440,7 +441,7 @@ enum MHD_FIXED_ENUM_ mhd_HttpStage * Closing HTTP-Upgraded connection */ mhd_HTTP_STAGE_UPGRADED_CLEANING -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ , /** * Finished regular connection processing. @@ -505,7 +506,7 @@ struct MHD_Connection */ struct mhd_ConnSocket sk; -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS /** * Connection-specific TLS data. * NULL if TLS is not used (plain HTTP connection). @@ -523,7 +524,7 @@ struct MHD_Connection * Status of TLS buffer for the incoming data */ enum mhd_TlsBufDataIn tls_has_data_in; -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ /** * 'true' if connection is in 'process ready' list, @@ -541,7 +542,7 @@ struct MHD_Connection */ mhd_DLNKDL_LINKS (MHD_Connection,by_timeout); -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE /** * The data for handling HTTP-Upgraded connection */ @@ -551,7 +552,18 @@ struct MHD_Connection * Double-linke list of HTTP-Upgraded connections waiting for clean-up */ mhd_DLNKDL_LINKS (MHD_Connection,upgr_cleanup); -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ + + /** + * Reference to the MHD_Daemon struct. + */ + struct MHD_Daemon *daemon; + + /** + * HTTP/1.x stream data. + * Currently not used for the actual data. + */ + struct MHD_Stream h1_stream; /** * True if connection is suspended @@ -564,11 +576,6 @@ struct MHD_Connection bool resuming; /** - * Reference to the MHD_Daemon struct. - */ - struct MHD_Daemon *daemon; - - /** * Request-specific data */ struct MHD_Request rq; @@ -617,7 +624,7 @@ struct MHD_Connection */ char *write_buffer; -#if defined(MHD_USE_THREADS) +#if defined(MHD_SUPPORT_THREADS) /** * Thread handle for this connection (if we are using * one thread per connection). @@ -691,7 +698,7 @@ struct MHD_Connection */ bool discard_request; -#if defined(MHD_USE_THREADS) +#if defined(MHD_SUPPORT_THREADS) /** * Set to `true` if the thread has been joined. */ @@ -721,32 +728,32 @@ struct MHD_Connection #endif }; -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS /** * Returns non-zero if connection has TLS enabled or zero otherwise */ # define mhd_C_HAS_TLS(c) (((c)->tls) ? (! 0) : (0)) -#else /* ! MHD_ENABLE_HTTPS */ +#else /* ! MHD_SUPPORT_HTTPS */ /** * Returns non-zero if connection has TLS enabled or zero otherwise */ # define mhd_C_HAS_TLS(c) (0) -#endif /* ! MHD_ENABLE_HTTPS */ +#endif /* ! MHD_SUPPORT_HTTPS */ -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS /** * Returns #mhd_SOCKET_NET_STATE_RECV_READY if connection has incoming data * pending in TLS buffers */ # define mhd_C_HAS_TLS_DATA_IN(c) \ (((c)->tls) ? ((unsigned int) ((c)->tls_has_data_in)) : (0u)) -#else /* ! MHD_ENABLE_HTTPS */ +#else /* ! MHD_SUPPORT_HTTPS */ /** * Returns #mhd_SOCKET_NET_STATE_RECV_READY if connection has incoming data * pending in TLS buffers */ # define mhd_C_HAS_TLS_DATA_IN(c) (0) -#endif /* ! MHD_ENABLE_HTTPS */ +#endif /* ! MHD_SUPPORT_HTTPS */ #endif /* ! MHD_CONNECTION_H */ diff --git a/src/mhd2/mhd_daemon.h b/src/mhd2/mhd_daemon.h @@ -42,11 +42,11 @@ # include "mhd_digest_auth_data.h" #endif -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "mhd_tls_choice.h" #endif -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS # include "mhd_threads.h" # include "mhd_itc_types.h" # include "mhd_locks.h" @@ -54,7 +54,7 @@ #include "sys_select.h" #include "sys_poll.h" -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL # include <sys/epoll.h> #endif @@ -238,7 +238,7 @@ union mhd_SocketRelation struct MHD_Connection *connection; }; -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT /** * Daemon's pointers to the preallocated arrays for running sockets monitoring @@ -260,9 +260,9 @@ struct mhd_DaemonEventsSelectData fd_set *efds; }; -#endif /* MHD_USE_SELECT */ +#endif /* MHD_SUPPORT_SELECT */ -#ifdef MHD_USE_POLL +#ifdef MHD_SUPPORT_POLL /** * Daemon's pointers to the preallocated arrays for running sockets monitoring @@ -289,9 +289,9 @@ struct mhd_DaemonEventsPollData union mhd_SocketRelation *rel; }; -#endif /* MHD_USE_POLL */ +#endif /* MHD_SUPPORT_POLL */ -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL /** * Daemon's parameters and pointers to the preallocated memory for running * sockets monitoring by epoll. @@ -336,23 +336,23 @@ struct mhd_DaemonEventsExternal */ union mhd_DaemonEventMonitoringTypeSpecificData { -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT /** * Daemon's pointers to the preallocated arrays for running sockets monitoring * by poll(). */ struct mhd_DaemonEventsSelectData select; -#endif /* MHD_USE_SELECT */ +#endif /* MHD_SUPPORT_SELECT */ -#ifdef MHD_USE_POLL +#ifdef MHD_SUPPORT_POLL /** * Daemon's pointers to the preallocated arrays for running sockets monitoring * by poll(). */ struct mhd_DaemonEventsPollData poll; -#endif /* MHD_USE_POLL */ +#endif /* MHD_SUPPORT_POLL */ -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL /** * Daemon's parameters and pointers to the preallocated memory for running * sockets monitoring by epoll. @@ -493,7 +493,7 @@ struct mhd_DaemonNetwork */ struct mhd_ListenSocket listen; -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL /** * The epoll FD. * Set to '-1' when epoll is not used. @@ -581,7 +581,7 @@ struct mhd_DaemonAuthDigestData */ struct mhd_AtomicCounter num_gen_nonces; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * The mutex to change or access the @a nonces data */ @@ -596,7 +596,7 @@ struct mhd_DaemonAuthDigestData #endif /* MHD_SUPPORT_AUTH_DIGEST */ -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * The type of the daemon @@ -667,7 +667,7 @@ enum MHD_FIXED_ENUM_ mhd_DaemonType #define mhd_D_TYPE_HAS_MASTER_DAEMON(t) \ (mhd_DAEMON_TYPE_WORKER == (t)) -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ /** * Check whether the daemon type is allowed to have internal thread with @@ -695,9 +695,9 @@ enum MHD_FIXED_ENUM_ mhd_DaemonType */ #define mhd_D_TYPE_HAS_MASTER_DAEMON(t) (0) -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * Workers pool data @@ -791,7 +791,7 @@ struct mhd_DaemonThreadingData struct mhd_DaemonThreadingDataSettings cfg; }; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ /** * Configured settings for the daemon's connections @@ -814,7 +814,7 @@ struct mhd_DaemonConnectionsSettings size_t mem_pool_size; }; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE /** * The data for HTTP-Upgraded connections @@ -827,7 +827,7 @@ struct mhd_DaemonConnectionsUpgraded */ mhd_DLNKDL_LIST (MHD_Connection,upgr_cleanup); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * The mutex to change or check the @a upgr_cleanup list values */ @@ -835,7 +835,7 @@ struct mhd_DaemonConnectionsUpgraded #endif }; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ /** * Connections handling data @@ -878,12 +878,12 @@ struct mhd_DaemonConnections */ struct mhd_DaemonConnectionsSettings cfg; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE /** * The data for HTTP-Upgraded connections */ struct mhd_DaemonConnectionsUpgraded upgr; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ }; /** @@ -911,7 +911,7 @@ struct mhd_DeamonLargeBuffer */ size_t space_left; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * The mutex to change or check the @a space_left value */ @@ -940,6 +940,13 @@ struct mhd_DaemonRequestProcessingSettings */ enum MHD_ProtocolStrictLevel strictness; +#ifdef MHD_SUPPORT_COOKIES + /** + * Disable automatic cookies parsing + */ + bool disable_cookies; +#endif + /** * Early URI callback */ @@ -953,7 +960,7 @@ struct mhd_DaemonRequestProcessingSettings /** * Suppress "Date:" header in responses */ - bool suppress_date; // TODO: set from settings + bool suppress_date; }; @@ -1022,7 +1029,7 @@ struct MHD_Daemon struct mhd_DaemonAuthDigestData auth_dg; #endif /* MHD_SUPPORT_AUTH_DIGEST */ -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS /** * The pointer to the daemon TLS data. * If set to non-NULL then HTTPS protocol is used, if set to NULL then @@ -1031,7 +1038,7 @@ struct MHD_Daemon struct mhd_TlsDaemonData *tls; #endif -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /* Threading data */ /** @@ -1088,7 +1095,7 @@ struct MHD_Daemon # define mhd_FD_FITS_DAEMON(d_ptr,fd) (! 0) #endif -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL # define mhd_D_IS_USING_EPOLL(d) \ (mhd_POLL_TYPE_EPOLL == ((d)->events.poll_type)) #else @@ -1102,13 +1109,13 @@ struct MHD_Daemon ((mhd_WM_INT_EXTERNAL_EVENTS_EDGE == (d)->wmode_int) || \ mhd_D_IS_USING_EPOLL (d)) -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS # define mhd_D_HAS_THREADS(d) mhd_WM_INT_HAS_THREADS ((d)->wmode_int) #else # define mhd_D_HAS_THREADS(d) (0) #endif -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS # define mhd_D_HAS_THR_PER_CONN(d) \ (mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION == \ ((d)->wmode_int)) @@ -1127,7 +1134,7 @@ struct MHD_Daemon (mhd_D_IS_USING_EPOLL (d) || \ (mhd_WM_INT_EXTERNAL_EVENTS_EDGE ==((d)->wmode_int))) -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS /** * Returns non-zero if daemon has TLS enabled or zero otherwise */ diff --git a/src/mhd2/mhd_lib_init.c b/src/mhd2/mhd_lib_init.c @@ -129,13 +129,13 @@ static volatile size_t mhd_lib_use_counter; * global initialisation (after deinitialisation). */ static volatile bool mhd_lib_fully_inited_once; -# ifdef MHD_USE_THREADS +# ifdef MHD_SUPPORT_THREADS /** * The mutex to control access to full global initialisers and deinitialisers */ static mhd_mutex mhd_init_mutex; -# endif /* MHD_USE_THREADS */ +# endif /* MHD_SUPPORT_THREADS */ #else /* mhd_INIT_LAZY_BY_STATIC */ /* Markers of performed lazy initialisation */ /** @@ -447,3 +447,17 @@ mhd_lib_deinit_global_if_needed (void) mhd_lib_global_full_deinit (); mhd_mutex_unlock_chk (&mhd_init_mutex); } + + +MHD_INTERNAL bool +mhd_lib_is_fully_initialised_once (void) +{ + return mhd_LIB_INIT_LAZY_IS_PERFORMED () && mhd_lib_fully_inited_once; +} + + +MHD_INTERNAL bool +mhd_lib_is_fully_initialised_now (void) +{ + return mhd_lib_is_fully_initialised_once () && (0 != mhd_lib_use_counter); +} diff --git a/src/mhd2/mhd_lib_init.h b/src/mhd2/mhd_lib_init.h @@ -46,5 +46,18 @@ mhd_lib_init_global_if_needed (void); MHD_INTERNAL void mhd_lib_deinit_global_if_needed (void); +/** + * Check whether the library has been successfully completely initialised. + * @return + */ +MHD_INTERNAL bool +mhd_lib_is_fully_initialised_once (void); + +/** + * Check whether the library is in fully initialised state now. + * @return + */ +MHD_INTERNAL bool +mhd_lib_is_fully_initialised_now (void); #endif /* ! MHD_LIB_INIT_H */ diff --git a/src/mhd2/mhd_locks.h b/src/mhd2/mhd_locks.h @@ -39,7 +39,7 @@ #include "mhd_sys_options.h" -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS #if defined(mhd_THREADS_KIND_W32) # define mhd_MUTEX_KIND_W32_CS 1 @@ -235,7 +235,7 @@ typedef CRITICAL_SECTION mhd_mutex; MHD_PANIC ("Failed to unlock mutex.\n"); \ } while (0) -#else /* ! MHD_USE_THREADS */ +#else /* ! MHD_SUPPORT_THREADS */ # define mhd_mutex_init(ignored) (! 0) # define mhd_MUTEX_INITIALISER_STAT /* empty */ @@ -247,6 +247,6 @@ typedef CRITICAL_SECTION mhd_mutex; # define mhd_mutex_unlock(ignored) (! 0) # define mhd_mutex_unlock_chk(ignored) (void) 0 -#endif /* ! MHD_USE_THREADS */ +#endif /* ! MHD_SUPPORT_THREADS */ #endif /* ! MHD_LOCKS_H */ diff --git a/src/mhd2/mhd_panic.c b/src/mhd2/mhd_panic.c @@ -78,7 +78,7 @@ mhd_panic (const char *file, if (NULL != user_panic_handler) user_panic_handler (user_panic_handler_cls, file, func, line, message); -#ifdef HAVE_LOG_FUNCTIONALITY +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY if (0 == file[0]) fprintf (stderr, "Unrecoverable error detected in GNU libmicrohttpd%s%s\n", @@ -105,6 +105,6 @@ mhd_panic (const char *file, message); } } -#endif /* HAVE_LOG_FUNCTIONALITY */ +#endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */ abort (); } diff --git a/src/mhd2/mhd_panic.h b/src/mhd2/mhd_panic.h @@ -64,7 +64,7 @@ mhd_panic (const char *file, #error MHD_PANIC macro is already defined. Check other headers. #endif /* MHD_PANIC */ -#ifdef HAVE_LOG_FUNCTIONALITY +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY # ifdef MHD_HAVE_MHD_FUNC_ /** * Panic processing for unrecoverable errors. diff --git a/src/mhd2/mhd_recv.c b/src/mhd2/mhd_recv.c @@ -39,7 +39,7 @@ #include "mhd_assert.h" #include "mhd_socket_error_funcs.h" -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "mhd_tls_funcs.h" #endif @@ -81,7 +81,7 @@ mhd_recv_plain (struct MHD_Connection *restrict c, } -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_SIZE_ (3,2) MHD_FN_PAR_OUT_ (4) enum mhd_SocketError @@ -124,7 +124,7 @@ mhd_recv_tls (struct MHD_Connection *restrict c, } -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_SIZE_ (3,2) MHD_FN_PAR_OUT_ (4) enum mhd_SocketError @@ -136,13 +136,13 @@ mhd_recv (struct MHD_Connection *restrict c, mhd_assert (MHD_INVALID_SOCKET != c->sk.fd); mhd_assert (mhd_HTTP_STAGE_CLOSED != c->stage); -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (mhd_C_HAS_TLS (c)) return mhd_recv_tls (c, buf_size, buf, received); -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ return mhd_recv_plain (c, buf_size, buf, received); } diff --git a/src/mhd2/mhd_reply.h b/src/mhd2/mhd_reply.h @@ -109,12 +109,12 @@ struct MHD_Reply */ struct MHD_DynamicContentCreatorContext app_act_ctx; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE /** * Set to 'true' when "100 Continue" response has been sent */ bool sent_100_cntn; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ /** * Response to transmit (initially NULL). diff --git a/src/mhd2/mhd_request.h b/src/mhd2/mhd_request.h @@ -41,7 +41,7 @@ #include "mhd_action.h" #include "mhd_buffer.h" -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER # include "mhd_postfield_int.h" # include "mhd_post_parser.h" #endif @@ -205,7 +205,7 @@ struct mhd_RequestField mhd_DLINKEDL_LIST_DEF (mhd_RequestField); -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER struct mhd_RequestPostField; /* forward declarations */ @@ -238,7 +238,7 @@ struct mhd_RequestPostField mhd_DLINKEDL_LIST_DEF (mhd_RequestPostField); -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ /** @@ -253,6 +253,11 @@ struct mhd_ReqContentData struct mhd_Buffer lbuf; /** + * 'true' if request has any (even zero-sized) upload (content/body) + */ + bool cntn_present; + + /** * The total size of the request content. * #MHD_SIZE_UNKNOWN if the size is not yet known (chunked upload). */ @@ -274,12 +279,12 @@ struct mhd_ReqContentData union mhd_ReqContentParsingData { -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER /** * The POST parsing data */ struct mhd_PostParserData post; -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ // TODO: move "raw" upload processing data here }; @@ -394,12 +399,12 @@ struct MHD_Request */ mhd_DLNKDL_LIST (mhd_RequestField,fields); -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER /** * Linked list of parsed POST fields. */ mhd_DLNKDL_LIST (mhd_RequestPostField,post_fields); -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ /** * The action set by the application diff --git a/src/mhd2/mhd_response.h b/src/mhd2/mhd_response.h @@ -42,7 +42,7 @@ #include "mhd_iovec.h" -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS # include "mhd_locks.h" #endif @@ -129,7 +129,7 @@ struct mhd_ResponseFD */ bool is_pipe; -#ifdef MHD_USE_SENDFILE +#ifdef mhd_USE_SENDFILE /** * Use 'sendfile()' function for the @a FD * Initially 'true' (except for pipes) but can be flipped to 'false' if @@ -212,13 +212,13 @@ struct mhd_ResponseReuseData */ struct mhd_AtomicCounter counter; -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS /** * The mutex for @a settings access. * Used only when @a reusable is 'true'. */ mhd_mutex settings_lock; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ }; struct mhd_ResponseConfiguration diff --git a/src/mhd2/mhd_send.c b/src/mhd2/mhd_send.c @@ -71,7 +71,7 @@ #include "mhd_limits.h" -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "mhd_tls_funcs.h" #endif @@ -82,11 +82,11 @@ #ifdef mhd_USE_VECT_SEND -# if (! defined(HAVE_SENDMSG) || ! defined(MSG_NOSIGNAL)) && \ +# if (! defined(HAVE_SENDMSG) || ! defined(HAVE_DCLR_MSG_NOSIGNAL)) && \ defined(mhd_SEND_SPIPE_SUPPRESS_POSSIBLE) && \ defined(mhd_SEND_SPIPE_SUPPRESS_NEEDED) # define mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED 1 -# endif /* (!HAVE_SENDMSG || !MSG_NOSIGNAL) && +# endif /* (!HAVE_SENDMSG || !HAVE_DCLR_MSG_NOSIGNAL) && mhd_SEND_SPIPE_SUPPRESS_POSSIBLE && mhd_SEND_SPIPE_SUPPRESS_NEEDED */ #endif /* mhd_USE_VECT_SEND */ @@ -198,7 +198,7 @@ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool mhd_connection_set_nodelay_state (struct MHD_Connection *connection, bool nodelay_state) { -#ifdef TCP_NODELAY +#ifdef HAVE_DCLR_TCP_NODELAY static const mhd_SCKT_OPT_BOOL off_val = 0; static const mhd_SCKT_OPT_BOOL on_val = 1; int err_code; @@ -823,7 +823,7 @@ mhd_send_plain (struct MHD_Connection *restrict c, } -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3,2) @@ -867,7 +867,7 @@ mhd_send_tls (struct MHD_Connection *restrict c, } -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3,2) @@ -881,14 +881,14 @@ mhd_send_data (struct MHD_Connection *restrict connection, mhd_assert (MHD_INVALID_SOCKET != connection->sk.fd); mhd_assert (mhd_HTTP_STAGE_CLOSED != connection->stage); -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (mhd_C_HAS_TLS (connection)) return mhd_send_tls (connection, buf_size, buf, push_data, sent); -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ return mhd_send_plain (connection, buf_size, @@ -930,12 +930,12 @@ mhd_send_hdr_and_body (struct MHD_Connection *restrict connection, no_vec = false; no_vec = no_vec || (mhd_C_HAS_TLS (connection)); -#if (! defined(HAVE_SENDMSG) || ! defined(MSG_NOSIGNAL) ) && \ +#if (! defined(HAVE_SENDMSG) || ! defined(HAVE_DCLR_MSG_NOSIGNAL) ) && \ defined(mhd_SEND_SPIPE_SUPPRESS_POSSIBLE) && \ defined(mhd_SEND_SPIPE_SUPPRESS_NEEDED) no_vec = no_vec || (! connection->daemon->sigpipe_blocked && ! connection->sk.props.has_spipe_supp); -#endif /* (!HAVE_SENDMSG || ! MSG_NOSIGNAL) && +#endif /* (!HAVE_SENDMSG || ! HAVE_DCLR_MSG_NOSIGNAL) && mhd_SEND_SPIPE_SUPPRESS_POSSIBLE && mhd_SEND_SPIPE_SUPPRESS_NEEDED */ #endif /* mhd_USE_VECT_SEND */ @@ -1148,7 +1148,7 @@ mhd_send_hdr_and_body (struct MHD_Connection *restrict connection, } -#if defined(MHD_USE_SENDFILE) +#if defined(mhd_USE_SENDFILE) #if defined(HAVE_LINUX_SENDFILE) && defined(HAVE_SENDFILE64) # define mhd_off_t off64_t @@ -1377,7 +1377,7 @@ mhd_send_sendfile (struct MHD_Connection *restrict c, } -#endif /* MHD_USE_SENDFILE */ +#endif /* mhd_USE_SENDFILE */ #if defined(mhd_USE_VECT_SEND) @@ -1536,7 +1536,7 @@ send_iov_nontls (struct MHD_Connection *restrict connection, #endif /* mhd_USE_VECT_SEND */ -#if ! defined(mhd_USE_VECT_SEND) || defined(MHD_ENABLE_HTTPS) || \ +#if ! defined(mhd_USE_VECT_SEND) || defined(MHD_SUPPORT_HTTPS) || \ defined(mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED) @@ -1618,7 +1618,7 @@ send_iov_emu (struct MHD_Connection *restrict connection, } -#endif /* !mhd_USE_VECT_SEND || MHD_ENABLE_HTTPS +#endif /* !mhd_USE_VECT_SEND || MHD_SUPPORT_HTTPS || mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED */ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ @@ -1629,10 +1629,10 @@ mhd_send_iovec (struct MHD_Connection *restrict connection, size_t *restrict sent) { #ifdef mhd_USE_VECT_SEND -#if defined(MHD_ENABLE_HTTPS) || \ +#if defined(MHD_SUPPORT_HTTPS) || \ defined(mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED) bool use_iov_send = true; -#endif /* MHD_ENABLE_HTTPS || mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED */ +#endif /* MHD_SUPPORT_HTTPS || mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED */ #endif /* mhd_USE_VECT_SEND */ mhd_assert (NULL != connection->rp.resp_iov.iov); @@ -1640,7 +1640,7 @@ mhd_send_iovec (struct MHD_Connection *restrict connection, connection->rp.response->cntn_dtype); mhd_assert (connection->rp.resp_iov.cnt > connection->rp.resp_iov.sent); #ifdef mhd_USE_VECT_SEND -#if defined(MHD_ENABLE_HTTPS) || \ +#if defined(MHD_SUPPORT_HTTPS) || \ defined(mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED) use_iov_send = use_iov_send && (! mhd_C_HAS_TLS (connection)); @@ -1649,13 +1649,13 @@ mhd_send_iovec (struct MHD_Connection *restrict connection, connection->sk.props.has_spipe_supp); #endif /* mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED */ if (use_iov_send) -#endif /* MHD_ENABLE_HTTPS || mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED */ +#endif /* MHD_SUPPORT_HTTPS || mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED */ return send_iov_nontls (connection, r_iov, push_data, sent); #endif /* mhd_USE_VECT_SEND */ -#if ! defined(mhd_USE_VECT_SEND) || defined(MHD_ENABLE_HTTPS) || \ +#if ! defined(mhd_USE_VECT_SEND) || defined(MHD_SUPPORT_HTTPS) || \ defined(mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED) return send_iov_emu (connection, r_iov, push_data, sent); -#endif /* !mhd_USE_VECT_SEND || MHD_ENABLE_HTTPS +#endif /* !mhd_USE_VECT_SEND || MHD_SUPPORT_HTTPS || mhd_VECT_SEND_NEEDS_SPIPE_SUPPRESSED */ } diff --git a/src/mhd2/mhd_send.h b/src/mhd2/mhd_send.h @@ -102,7 +102,7 @@ mhd_send_hdr_and_body (struct MHD_Connection *restrict connection, MHD_FN_PAR_NONNULL_(1) MHD_FN_PAR_NONNULL_(3) MHD_FN_PAR_IN_SIZE_ (3,2) MHD_FN_PAR_IN_SIZE_ (6,5) MHD_FN_PAR_OUT_ (8); -#if defined(MHD_USE_SENDFILE) +#if defined(mhd_USE_SENDFILE) /** * Function for sending responses backed by file FD. * diff --git a/src/mhd2/mhd_sockets_funcs.c b/src/mhd2/mhd_sockets_funcs.c @@ -111,8 +111,7 @@ MHD_INTERNAL bool mhd_socket_set_nodelay (MHD_Socket sckt, bool on) { - // TODO: detect constants in configure -#ifdef TCP_NODELAY +#ifdef HAVE_DCLR_TCP_NODELAY mhd_SCKT_OPT_BOOL value; value = on ? 1 : 0; @@ -120,7 +119,7 @@ mhd_socket_set_nodelay (MHD_Socket sckt, return 0 == setsockopt (sckt, IPPROTO_TCP, TCP_NODELAY, (const void *) &value, sizeof (value)); #else /* ! TCP_NODELAY */ - (void) sock; (void) on; + (void) sckt; (void) on; return false; #endif /* ! TCP_NODELAY */ } @@ -129,8 +128,7 @@ mhd_socket_set_nodelay (MHD_Socket sckt, MHD_INTERNAL bool mhd_socket_set_hard_close (MHD_Socket sckt) { - // TODO: detect constants in configure -#if defined(SOL_SOCKET) && defined(SO_LINGER) +#if defined(HAVE_DCLR_SOL_SOCKET) && defined(HAVE_DCLR_SO_LINGER) struct linger par; par.l_onoff = 1; @@ -138,19 +136,19 @@ mhd_socket_set_hard_close (MHD_Socket sckt) return 0 == setsockopt (sckt, SOL_SOCKET, SO_LINGER, (const void *) &par, sizeof (par)); -#else /* ! TCP_NODELAY */ - (void) sock; +#else /* ! SOL_SOCKET || ! SO_LINGER */ + (void) sckt; return false; -#endif /* ! TCP_NODELAY */ +#endif /* ! SOL_SOCKET || ! SO_LINGER */ } MHD_INTERNAL bool mhd_socket_shut_wr (MHD_Socket sckt) { -#if defined(SHUT_WR) // TODO: detect constants in configure +#if defined(HAVE_DCLR_SHUT_WR) return 0 == shutdown (sckt, SHUT_WR); -#elif defined(SD_SEND) // TODO: detect constants in configure +#elif defined(HAVE_DCLR_SD_SEND) return 0 == shutdown (sckt, SD_SEND); #else return false; diff --git a/src/mhd2/mhd_sockets_macros.h b/src/mhd2/mhd_sockets_macros.h @@ -312,7 +312,7 @@ # define mhd_socket_pair(fdarr_ptr) \ (0 != socketpair (AF_INET, SOCK_STREAM, 0, (fdarr_ptr))) /* Fallback, could be broken on many platforms */ # endif -# if defined(HAVE_SOCK_NONBLOCK) +# if defined(HAVE_DCLR_SOCK_NONBLOCK) # ifdef MHD_AF_UNIX # define mhd_socket_pair_nblk(fdarr_ptr) \ (0 != socketpair (MHD_AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, \ @@ -321,7 +321,7 @@ # define mhd_socket_pair_nblk(fdarr_ptr) \ (0 != socketpair (AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0, (fdarr_ptr))) /* Fallback, could be broken on many platforms */ # endif -# endif /* HAVE_SOCK_NONBLOCK*/ +# endif /* HAVE_DCLR_SOCK_NONBLOCK*/ # endif /* HAVE_SOCKETPAIR */ #endif @@ -329,30 +329,4 @@ /* mhd_socket_pair() implemented in "mhd_sockets_funcs.h" based on local function */ #endif -#if defined(SOL_SOCKET) && defined(SO_NOSIGPIPE) -/** - * Helper for mhd_socket_nosignal() - */ -# ifdef HAVE_COMPOUND_LITERALS_LVALUES -# define mhd_socket_nosig_helper_int_one ((int){1}) -# else -/** - * Internal static const helper for mhd_socket_nosignal() - */ -static const int mhd_socket_nosig_helper_int_one = 1; -# endif - - -/** - * Change socket options to no signal on remote disconnect / broken connection. - * - * @param sock socket to manipulate - * @return non-zero if succeeded, zero otherwise - */ -# define mhd_socket_nosignal(sock) \ - (! setsockopt ((sock),SOL_SOCKET,SO_NOSIGPIPE, \ - &mhd_socket_nosig_helper_int_one, sizeof(int))) -#endif /* SOL_SOCKET && SO_NOSIGPIPE */ - - #endif /* ! MHD_SOCKETS_MACROS_H */ diff --git a/src/mhd2/mhd_str.c b/src/mhd2/mhd_str.c @@ -1549,7 +1549,8 @@ mhd_uint8_to_str_pad (uint8_t val, } -MHD_INTERNAL size_t +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_IN_SIZE_ (1, 2) MHD_FN_PAR_OUT_ (3) size_t mhd_bin_to_hex (const void *restrict bin, size_t size, char *restrict hex) @@ -1569,7 +1570,8 @@ mhd_bin_to_hex (const void *restrict bin, } -MHD_INTERNAL size_t +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_IN_SIZE_ (1, 2) MHD_FN_PAR_OUT_ (3) size_t mhd_bin_to_hex_z (const void *restrict bin, size_t size, char *restrict hex) @@ -2007,7 +2009,7 @@ mhd_str_equal_caseless_quoted_bin_n (const char *quoted, #endif /* MHD_SUPPORT_AUTH_DIGEST */ -#if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(HAVE_POST_PARSER) +#if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_POST_PARSER) MHD_INTERNAL size_t mhd_str_unquote (const char *quoted, @@ -2034,7 +2036,7 @@ mhd_str_unquote (const char *quoted, } -#endif /* MHD_SUPPORT_AUTH_DIGEST HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_AUTH_DIGEST || MHD_SUPPORT_POST_PARSER */ #if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_AUTH_BASIC) diff --git a/src/mhd2/mhd_str.h b/src/mhd2/mhd_str.h @@ -471,7 +471,8 @@ mhd_uint8_to_str_pad (uint8_t val, MHD_INTERNAL size_t mhd_bin_to_hex (const void *restrict bin, size_t size, - char *restrict hex); + char *restrict hex) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (1, 2) MHD_FN_PAR_OUT_ (3); /** * Convert @a size bytes from input binary data to lower case @@ -485,7 +486,8 @@ mhd_bin_to_hex (const void *restrict bin, MHD_INTERNAL size_t mhd_bin_to_hex_z (const void *restrict bin, size_t size, - char *restrict hex); + char *restrict hex) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (1, 2) MHD_FN_PAR_OUT_ (3); /** * Convert hexadecimal digits to binary data. @@ -691,7 +693,7 @@ mhd_str_equal_caseless_quoted_bin_n (const char *quoted, #endif /* MHD_SUPPORT_AUTH_DIGEST */ -#if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(HAVE_POST_PARSER) +#if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_POST_PARSER) /** * Convert string from quoted to unquoted form as specified by @@ -713,7 +715,7 @@ mhd_str_unquote (const char *quoted, size_t quoted_len, char *result); -#endif /* MHD_SUPPORT_AUTH_DIGEST HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_AUTH_DIGEST || MHD_SUPPORT_POST_PARSER */ #if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_AUTH_BASIC) diff --git a/src/mhd2/mhd_stream.h b/src/mhd2/mhd_stream.h @@ -0,0 +1,45 @@ +/* + This file is part of GNU libmicrohttpd + Copyright (C) 2025 Evgeny Grin (Karlson2k) + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +/** + * @file src/mhd2/mhd_stream.h + * @brief The definition of the MHD_Stream type and helper macros + * @author Karlson2k (Evgeny Grin) + */ + +#ifndef MHD_STREAM_H +#define MHD_STREAM_H 1 + +#include "mhd_sys_options.h" + +/** + * The HTTP stream data. + * For HTTP/1.x this information held in MHD_Connection structure + */ +struct MHD_Stream +{ + /** + * The dummy member. + * Do not use + */ + int place_holder; +}; + +#endif /* ! MHD_STREAM_H */ diff --git a/src/mhd2/mhd_threads.c b/src/mhd2/mhd_threads.c @@ -31,23 +31,28 @@ #ifdef mhd_THREADS_KIND_W32 # include <process.h> #endif -#if defined(MHD_USE_THREAD_NAME_) +#if defined(mhd_USE_THREAD_NAME) # if ! defined(MHD_USE_THREAD_ATTR_SETNAME) # include "sys_malloc.h" # endif # ifdef HAVE_PTHREAD_NP_H # include <pthread_np.h> # endif /* HAVE_PTHREAD_NP_H */ -#endif /* MHD_USE_THREAD_NAME_ */ +#endif /* mhd_USE_THREAD_NAME */ #include "sys_errno.h" #include "mhd_assert.h" +#ifdef mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE +# ifdef HAVE_SIGNAL_H +# include <signal.h> +# endif +#endif -#ifndef MHD_USE_THREAD_NAME_ +#ifndef mhd_USE_THREAD_NAME # define mhd_set_thread_name(t, n) (void) # define mhd_set_cur_thread_name(n) (void) -#else /* MHD_USE_THREAD_NAME_ */ +#else /* mhd_USE_THREAD_NAME */ # if defined(mhd_THREADS_KIND_POSIX) # if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \ @@ -171,7 +176,7 @@ mhd_set_thread_name (const mhd_thread_ID_native thread_id, # endif /* _MSC_FULL_VER */ # endif /* mhd_THREADS_KIND_W32 */ -#endif /* MHD_USE_THREAD_NAME_ */ +#endif /* mhd_USE_THREAD_NAME */ /** @@ -268,7 +273,7 @@ mhd_create_thread (mhd_thread_handle_ID *handle_id, } -#ifdef MHD_USE_THREAD_NAME_ +#ifdef mhd_USE_THREAD_NAME # ifndef MHD_USE_THREAD_ATTR_SETNAME struct mhd_named_helper_param @@ -419,4 +424,18 @@ mhd_create_named_thread (mhd_thread_handle_ID *handle_id, } -#endif /* MHD_USE_THREAD_NAME_ */ +#endif /* mhd_USE_THREAD_NAME */ + +#ifdef mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE +MHD_INTERNAL bool +mhd_thread_block_sigpipe (void) +{ + sigset_t s_mask; + + return ((0 == sigemptyset (&s_mask)) && + (0 == sigaddset (&s_mask, SIGPIPE)) && + (0 == pthread_sigmask (SIG_BLOCK, &s_mask, NULL))); +} + + +#endif /* mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE */ diff --git a/src/mhd2/mhd_threads.h b/src/mhd2/mhd_threads.h @@ -1,6 +1,6 @@ /* This file is part of GNU libmicrohttpd - Copyright (C) 2016-2024 Evgeny Grin (Karlson2k) + Copyright (C) 2016-2025 Evgeny Grin (Karlson2k) GNU libmicrohttpd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -40,13 +40,13 @@ #if defined(mhd_THREADS_KIND_POSIX) # include <pthread.h> -# ifndef MHD_USE_THREADS -# define MHD_USE_THREADS 1 +# ifndef MHD_SUPPORT_THREADS +# define MHD_SUPPORT_THREADS 1 # endif #elif defined(mhd_THREADS_KIND_W32) # include <windows.h> -# ifndef MHD_USE_THREADS -# define MHD_USE_THREADS 1 +# ifndef MHD_SUPPORT_THREADS +# define MHD_SUPPORT_THREADS 1 # endif #else # error No threading API is available. @@ -68,12 +68,12 @@ defined(HAVE_PTHREAD_SETNAME_NP_NETBSD) || \ defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \ defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI) -# define MHD_USE_THREAD_NAME_ +# define mhd_USE_THREAD_NAME # endif /* HAVE_PTHREAD_SETNAME_NP */ # elif defined(mhd_THREADS_KIND_W32) # ifdef _MSC_FULL_VER /* Thread names only available with VC compiler */ -# define MHD_USE_THREAD_NAME_ +# define mhd_USE_THREAD_NAME # endif /* _MSC_FULL_VER */ # endif #endif @@ -520,9 +520,9 @@ mhd_create_thread (mhd_thread_handle_ID *handle_id, mhd_THREAD_START_ROUTINE start_routine, void *arg); -#ifndef MHD_USE_THREAD_NAME_ +#ifndef mhd_USE_THREAD_NAME #define mhd_create_named_thread(t,n,s,r,a) mhd_create_thread ((t),(s),(r),(a)) -#else /* MHD_USE_THREAD_NAME_ */ +#else /* mhd_USE_THREAD_NAME */ /** * Create a named thread and set the attributes according to our options. * @@ -540,6 +540,25 @@ mhd_create_named_thread (mhd_thread_handle_ID *handle_id, mhd_THREAD_START_ROUTINE start_routine, void *arg); -#endif /* MHD_USE_THREAD_NAME_ */ +#endif /* mhd_USE_THREAD_NAME */ +#if ! defined(mhd_SEND_SPIPE_SUPPRESS_NEEDED) +# define mhd_thread_block_sigpipe() ((void) 0) +#else +# ifdef HAVE_PTHREAD_SIGMASK +/** + * Block a SIGPIPE signal in the current thread + * + * @return 'true' on success, + * 'false' otherwise + */ +MHD_INTERNAL bool +mhd_thread_block_sigpipe (void); + +/** + * Indicates that function #mhd_thread_block_sigpipe() is available + */ +# define mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE 1 +# endif +#endif #endif /* ! MHD_THREADS_H */ diff --git a/src/mhd2/mhd_tls_choice.h b/src/mhd2/mhd_tls_choice.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_ENABLE_HTTPS +#ifndef MHD_SUPPORT_HTTPS #error This header should be used only if HTTPS is enabled #endif @@ -49,7 +49,7 @@ /* * GnuTLS * */ -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS /** * Defined to one if GnuTLS is enabled at build time or to zero if not enabled */ @@ -68,7 +68,7 @@ /* * OpenSSL * */ -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL /** * Defined to one if OpenSSL is enabled at build time or to zero if not enabled */ @@ -142,7 +142,7 @@ * The TLS back-end identifier for macro names */ # define mhd_TLS_MACRO_NAME_ID MULTI -#elif defined(MHD_USE_GNUTLS) +#elif defined(MHD_SUPPORT_GNUTLS) /** * The TLS back-end identifier for function names */ @@ -155,7 +155,7 @@ * The TLS back-end identifier for macro names */ # define mhd_TLS_MACRO_NAME_ID GNU -#elif defined(MHD_USE_OPENSSL) +#elif defined(MHD_SUPPORT_OPENSSL) /** * The TLS back-end identifier for function names */ @@ -173,14 +173,14 @@ /* ** Functions replacement macros to simplify the code ** */ -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS /** * Check whether GnuTLS backend was successfully initialised globally */ # define mhd_tls_gnu_is_inited_fine() (! ! 0) #endif -#ifndef MHD_USE_OPENSSL +#ifndef MHD_SUPPORT_OPENSSL /** * Check whether OpenSSL backend was successfully initialised globally */ diff --git a/src/mhd2/mhd_tls_enums.h b/src/mhd2/mhd_tls_enums.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_ENABLE_HTTPS +#ifndef MHD_SUPPORT_HTTPS #error This header should be used only if HTTPS is enabled #endif diff --git a/src/mhd2/mhd_tls_funcs.c b/src/mhd2/mhd_tls_funcs.c @@ -29,10 +29,10 @@ #include "mhd_tls_funcs.h" /* Include all supported TLS backends headers */ -#if defined(MHD_USE_GNUTLS) +#if defined(MHD_SUPPORT_GNUTLS) # include "tls_gnu_funcs.h" #endif -#if defined(MHD_USE_OPENSSL) +#if defined(MHD_SUPPORT_OPENSSL) # include "tls_open_funcs.h" #endif @@ -51,13 +51,13 @@ mhd_tls_is_backend_available (struct DaemonOptions *s) || mhd_tls_open_is_inited_fine ()) ? mhd_TLS_BACKEND_AVAIL_OK : mhd_TLS_BACKEND_AVAIL_NOT_AVAILABLE; -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS if (MHD_TLS_BACKEND_GNUTLS == s->tls) return mhd_tls_gnu_is_inited_fine () ? mhd_TLS_BACKEND_AVAIL_OK : mhd_TLS_BACKEND_AVAIL_NOT_AVAILABLE; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL if (MHD_TLS_BACKEND_OPENSSL == s->tls) return mhd_tls_open_is_inited_fine () ? mhd_TLS_BACKEND_AVAIL_OK : diff --git a/src/mhd2/mhd_tls_funcs.h b/src/mhd2/mhd_tls_funcs.h @@ -33,15 +33,15 @@ #include "sys_bool_type.h" #include "mhd_tls_choice.h" -#ifndef MHD_ENABLE_HTTPS +#ifndef MHD_SUPPORT_HTTPS #error This header should be used only if HTTPS is enabled #endif #if defined(MHD_USE_MULTITLS) # include "tls_multi_funcs.h" -#elif defined(MHD_USE_GNUTLS) +#elif defined(MHD_SUPPORT_GNUTLS) # include "tls_gnu_funcs.h" -#elif defined(MHD_USE_OPENSSL) +#elif defined(MHD_SUPPORT_OPENSSL) # include "tls_open_funcs.h" #endif @@ -186,6 +186,27 @@ mhd_TLS_FUNC (_conn_send)((c_tls),(buf_size),(buf),(sent)) +/* ** TLS connection information ** */ + +/** + * Get the TLS session used in connection + * @param c_tls the connection TLS handle + * @param tls_ver_out the pointer to variable to be set to the TLS version + */ +#define mhd_tls_conn_get_tls_sess(c_tls,tls_sess_out) \ + mhd_TLS_FUNC (_conn_get_tls_sess)((c_tls),(tls_sess_out)) + +/** + * Get the TLS version used in connection + * @param c_tls the connection TLS handle + * @param tls_ver_out the pointer to variable to be set to the TLS version + * @return 'true' is TLS version information set successfully, + * 'false' if TLS version information cannot be obtained or mapped + */ +#define mhd_tls_conn_get_tls_ver(c_tls,tls_ver_out) \ + mhd_TLS_FUNC (_conn_get_tls_ver)((c_tls),(tls_ver_out)) + + /* ** General information function ** */ /** diff --git a/src/mhd2/request_get_info.c b/src/mhd2/request_get_info.c @@ -45,44 +45,64 @@ #include "mhd_public_api.h" -MHD_EXTERN_ +MHD_EXTERN_ MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_ enum MHD_StatusCode +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode MHD_request_get_info_fixed_sz ( struct MHD_Request *MHD_RESTRICT request, enum MHD_RequestInfoFixedType info_type, - union MHD_RequestInfoFixedData *MHD_RESTRICT return_value, - size_t return_value_size) + union MHD_RequestInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) { switch (info_type) { - case MHD_REQUEST_INFO_FIXED_STREAM: - mhd_assert (0 && "Not implemented yet"); - break; - case MHD_REQUEST_INFO_FIXED_CONNECTION: - if (sizeof(return_value->v_connection) > return_value_size) + case MHD_REQUEST_INFO_FIXED_HTTP_VER: + if (mhd_HTTP_STAGE_REQ_LINE_RECEIVED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_http_ver) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_connection = - mhd_CNTNR_PTR (request, struct MHD_Connection, rq); + output_buf->v_http_ver = request->http_ver; + return MHD_SC_OK; + case MHD_REQUEST_INFO_FIXED_HTTP_METHOD: + if (mhd_HTTP_METHOD_NO_METHOD == request->http_mthd) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_http_method) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_http_method = (enum MHD_HTTP_Method) request->http_mthd; return MHD_SC_OK; case MHD_REQUEST_INFO_FIXED_DAEMON: - if (sizeof(return_value->v_daemon) > return_value_size) + if (sizeof(output_buf->v_daemon) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_daemon = - mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->daemon; + output_buf->v_daemon = + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->daemon; return MHD_SC_OK; - case MHD_REQUEST_INFO_FIXED_HTTP_VER: - if (sizeof(return_value->v_http_ver) > return_value_size) + case MHD_REQUEST_INFO_FIXED_CONNECTION: + if (sizeof(output_buf->v_connection) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_http_ver = request->http_ver; + output_buf->v_connection = + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq); return MHD_SC_OK; - case MHD_REQUEST_INFO_FIXED_HTTP_METHOD: - if (sizeof(return_value->v_http_method) > return_value_size) + case MHD_REQUEST_INFO_FIXED_STREAM: + if (sizeof(output_buf->v_stream) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - mhd_assert (mhd_HTTP_METHOD_NO_METHOD != request->http_mthd); - return_value->v_http_method = (enum MHD_HTTP_Method) request->http_mthd; + output_buf->v_stream = + &(mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->h1_stream); return MHD_SC_OK; + case MHD_REQUEST_INFO_FIXED_APP_CONTEXT: + if (sizeof(output_buf->v_ppvoid) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_ppvoid = &(request->app_context); + return MHD_SC_OK; + case MHD_REQUEST_INFO_FIXED_SENTINEL: default: break; @@ -98,87 +118,258 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode MHD_request_get_info_dynamic_sz ( struct MHD_Request *MHD_RESTRICT request, enum MHD_RequestInfoDynamicType info_type, - union MHD_RequestInfoDynamicData *MHD_RESTRICT return_value, - size_t return_value_size) + union MHD_RequestInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) { - if (mhd_HTTP_STAGE_REQ_RECV_FINISHED < - mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage) - return MHD_SC_TOO_LATE; - if ((mhd_HTTP_STAGE_HEADERS_PROCESSED > - mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage) && - (MHD_REQUEST_INFO_DYNAMIC_NUMBER_GET_PARAMS < info_type)) - return MHD_SC_TOO_EARLY; switch (info_type) { case MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STR: - mhd_assert (mhd_HTTP_STAGE_REQ_LINE_RECEIVED <= \ - mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage); - if (sizeof(return_value->v_str) > return_value_size) + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; + if (0 == request->method.len) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_str) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_str = request->method; + output_buf->v_str = request->method; return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_URI: - if (mhd_HTTP_STAGE_REQ_LINE_RECEIVED < - mhd_CNTNR_PTR (request, struct MHD_Connection, rq)->stage) + if (mhd_HTTP_STAGE_REQ_LINE_RECEIVED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) return MHD_SC_TOO_EARLY; - if (sizeof(return_value->v_str) > return_value_size) + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED < + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; + if (sizeof(output_buf->v_str) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_str.cstr = request->url; - return_value->v_str.len = request->url_len; + output_buf->v_str.cstr = request->url; + output_buf->v_str.len = request->url_len; return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_NUMBER_GET_PARAMS: + if (mhd_HTTP_STAGE_REQ_LINE_RECEIVED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED < + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; + if (sizeof(output_buf->v_sizet) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_sizet = + MHD_request_get_values_cb (request, + MHD_VK_GET_ARGUMENT, + NULL, + NULL); + return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_NUMBER_COOKIES: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; + if (sizeof(output_buf->v_sizet) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_COOKIES + output_buf->v_sizet = + MHD_request_get_values_cb (request, + MHD_VK_COOKIE, + NULL, + NULL); +#else + output_buf->v_sizet = 0; +#endif + return MHD_SC_OK; + case MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED < + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; + if (sizeof(output_buf->v_sizet) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_sizet = request->header_size; + return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED < + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; + if (sizeof(output_buf->v_sizet) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; +#ifdef MHD_SUPPORT_POST_PARSER + output_buf->v_sizet = + MHD_request_get_values_cb (request, + MHD_VK_POSTDATA, + NULL, + NULL); +#else + output_buf->v_sizet = 0; +#endif + return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_UPLOAD_PRESENT: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_bool = request->cntn.cntn_present ? MHD_YES : MHD_NO; + return MHD_SC_OK; + case MHD_REQUEST_INFO_DYNAMIC_UPLOAD_CHUNKED: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_bool) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_bool = + (MHD_SIZE_UNKNOWN == request->cntn.cntn_size) ? MHD_YES : MHD_NO; + return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_uint64) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_uint64 = request->cntn.cntn_size; + return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_uint64) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_uint64 = request->cntn.recv_size; + return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_RECIEVE: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_uint64) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_uint64 = + (MHD_SIZE_UNKNOWN == request->cntn.cntn_size) ? + MHD_SIZE_UNKNOWN : (request->cntn.cntn_size - request->cntn.recv_size); + return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_PROCESSED: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_uint64) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_uint64 = request->cntn.proc_size; + return MHD_SC_OK; case MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_PROCESS: - mhd_assert (0 && "Not implemented yet"); - break; - case MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE: - if (sizeof(return_value->v_sizet) > return_value_size) + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_uint64) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; - return_value->v_sizet = request->header_size; + output_buf->v_uint64 = + (MHD_SIZE_UNKNOWN == request->cntn.cntn_size) ? + MHD_SIZE_UNKNOWN : (request->cntn.cntn_size - request->cntn.proc_size); return MHD_SC_OK; - case MHD_REQUEST_INFO_DYNAMIC_APP_CONTEXT: - mhd_assert (0 && "Not implemented yet"); - break; case MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_USERNAME: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED < + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; #ifdef MHD_SUPPORT_AUTH_DIGEST - if (sizeof(return_value->v_auth_basic_creds) > return_value_size) + if (sizeof(output_buf->v_auth_basic_creds) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; return mhd_request_get_auth_digest_username (request, - &(return_value-> + &(output_buf-> v_auth_digest_uname)); #else /* ! MHD_SUPPORT_AUTH_DIGEST */ return MHD_SC_FEATURE_DISABLED; #endif /* ! MHD_SUPPORT_AUTH_DIGEST */ break; case MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_INFO: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED < + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; #ifdef MHD_SUPPORT_AUTH_DIGEST - if (sizeof(return_value->v_auth_basic_creds) > return_value_size) + if (sizeof(output_buf->v_auth_basic_creds) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; return mhd_request_get_auth_digest_info (request, - &(return_value-> + &(output_buf-> v_auth_digest_info)); #else /* ! MHD_SUPPORT_AUTH_DIGEST */ return MHD_SC_FEATURE_DISABLED; #endif /* ! MHD_SUPPORT_AUTH_DIGEST */ break; case MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS: + if (mhd_HTTP_STAGE_HEADERS_PROCESSED > + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_EARLY; + if (mhd_HTTP_STAGE_REQ_RECV_FINISHED < + mhd_CNTNR_PTR (request, \ + struct MHD_Connection, \ + rq)->stage) + return MHD_SC_TOO_LATE; #ifdef MHD_SUPPORT_AUTH_BASIC - if (sizeof(return_value->v_auth_basic_creds) > return_value_size) + if (sizeof(output_buf->v_auth_basic_creds) > output_buf_size) return MHD_SC_INFO_GET_BUFF_TOO_SMALL; return mhd_request_get_auth_basic_creds (request, - &(return_value-> + &(output_buf-> v_auth_basic_creds)); #else /* MHD_SUPPORT_AUTH_BASIC */ return MHD_SC_FEATURE_DISABLED; #endif /* MHD_SUPPORT_AUTH_BASIC */ - mhd_assert (0 && "Not implemented yet"); break; + case MHD_REQUEST_INFO_DYNAMIC_SENTINEL: default: break; diff --git a/src/mhd2/request_get_value.c b/src/mhd2/request_get_value.c @@ -68,7 +68,7 @@ mhd_request_get_value_n (struct MHD_Request *restrict request, } } -#if HAVE_POST_PARSER +#if MHD_SUPPORT_POST_PARSER if (0 != (MHD_VK_POSTDATA & kind)) { struct mhd_RequestPostField *f; @@ -93,7 +93,7 @@ mhd_request_get_value_n (struct MHD_Request *restrict request, } } } -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ return NULL; } @@ -161,6 +161,9 @@ MHD_request_get_values_cb (struct MHD_Request *request, for (f = mhd_DLINKEDL_GET_FIRST (request, fields); NULL != f; f = mhd_DLINKEDL_GET_NEXT (f, fields)) { + if (0 == (kind & f->field.kind)) + continue; + ++count; if (NULL != iterator) { @@ -173,7 +176,7 @@ MHD_request_get_values_cb (struct MHD_Request *request, } } -#if HAVE_POST_PARSER +#if MHD_SUPPORT_POST_PARSER if (0 != (MHD_VK_POSTDATA & kind)) { struct mhd_RequestPostField *f; @@ -202,13 +205,13 @@ MHD_request_get_values_cb (struct MHD_Request *request, } } } -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ return count; } -#if HAVE_POST_PARSER +#if MHD_SUPPORT_POST_PARSER MHD_EXTERN_ MHD_FN_PAR_NONNULL_ (1) size_t @@ -278,4 +281,4 @@ MHD_request_get_post_data_cb (struct MHD_Request *request, } -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ diff --git a/src/mhd2/respond_with_error.h b/src/mhd2/respond_with_error.h @@ -57,7 +57,7 @@ respond_with_error_len (struct MHD_Connection *c, MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (4) MHD_FN_PAR_CSTR_ (6); -#ifdef HAVE_HTTP_AUTO_MESSAGES_BODIES +#ifdef MHD_ENABLE_AUTO_MESSAGES_BODIES /** * Transmit static string as error response */ diff --git a/src/mhd2/response_from.c b/src/mhd2/response_from.c @@ -335,7 +335,7 @@ MHD_response_from_fd (enum MHD_HTTP_StatusCode sc, res->cntn_dtype = mhd_RESPONSE_CONTENT_DATA_FILE; res->cntn.file.fd = fd; res->cntn.file.offset = offset; -#ifdef MHD_USE_SENDFILE +#ifdef mhd_USE_SENDFILE res->cntn.file.use_sf = (size < MHD_SIZE_UNKNOWN); #endif res->cntn.file.is_pipe = false; /* Not necessary */ @@ -356,7 +356,7 @@ MHD_response_from_pipe (enum MHD_HTTP_StatusCode sc, res->cntn_dtype = mhd_RESPONSE_CONTENT_DATA_FILE; res->cntn.file.fd = fd; res->cntn.file.offset = 0; /* Not necessary */ -#ifdef MHD_USE_SENDFILE +#ifdef mhd_USE_SENDFILE res->cntn.file.use_sf = false; /* Not necessary */ #endif res->cntn.file.is_pipe = true; diff --git a/src/mhd2/response_options.h b/src/mhd2/response_options.h @@ -61,7 +61,7 @@ struct ResponseOptions * the function to call, * NULL to not use the callback */ - struct MHD_ResponeOptionValueEndedCB termination_callback; + struct MHD_ResponseOptionValueEndedCB termination_callback; }; diff --git a/src/mhd2/sha256_ext.c b/src/mhd2/sha256_ext.c @@ -68,6 +68,8 @@ mhd_SHA256_update (struct mhd_Sha256CtxExt *ctx, size_t size, const uint8_t *data) { + mhd_assert (0 != size); + if (0 == ctx->ext_error) ctx->ext_error = gnutls_hash (ctx->handle, data, size); } diff --git a/src/mhd2/sha256_int.c b/src/mhd2/sha256_int.c @@ -399,12 +399,7 @@ mhd_SHA256_update (struct mhd_Sha256CtxInt *restrict ctx, { unsigned bytes_have; /**< Number of bytes in buffer */ - mhd_assert ((data != NULL) || (size == 0)); - -#ifndef MHD_FAVOR_SMALL_CODE - if (0 == size) - return; /* Shortcut, do nothing */ -#endif /* MHD_FAVOR_SMALL_CODE */ + mhd_assert (0 != size); /* Note: (count & (mhd_SHA256_BLOCK_SIZE-1)) equals (count % mhd_SHA256_BLOCK_SIZE) for this block size. */ diff --git a/src/mhd2/sha512_256_int.c b/src/mhd2/sha512_256_int.c @@ -458,12 +458,7 @@ mhd_SHA512_256_update (struct mhd_Sha512_256CtxInt *restrict ctx, unsigned int bytes_have; /**< Number of bytes in the context buffer */ uint64_t count_hi; /**< The high part to be moved to another variable */ - mhd_assert ((data != NULL) || (size == 0)); - -#ifndef MHD_FAVOR_SMALL_CODE - if (0 == size) - return; /* Shortcut, do nothing */ -#endif /* ! MHD_FAVOR_SMALL_CODE */ + mhd_assert (0 != size); /* Note: (count & (mhd_SHA512_256_BLOCK_SIZE-1)) equals (count % mhd_SHA512_256_BLOCK_SIZE) for this block size. */ diff --git a/src/mhd2/stream_funcs.c b/src/mhd2/stream_funcs.c @@ -32,7 +32,7 @@ #include "mhd_unreachable.h" #include <string.h> -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL # include <sys/epoll.h> #endif #include "sys_malloc.h" @@ -54,7 +54,7 @@ #include "conn_mark_ready.h" #include "stream_process_reply.h" -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS # include "mhd_tls_funcs.h" #endif @@ -649,9 +649,9 @@ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void mhd_stream_update_activity_mark (struct MHD_Connection *restrict c) { struct MHD_Daemon *const restrict d = c->daemon; -#if defined(MHD_USE_THREADS) +#if defined(MHD_SUPPORT_THREADS) mhd_assert (! mhd_D_HAS_WORKERS (d)); -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ mhd_assert (! c->suspended); @@ -813,12 +813,12 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c, MHD_REQUEST_ENDED_NO_RESOURCES : MHD_REQUEST_ENDED_HTTP_PROTOCOL_ERROR; break; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_CONN_CLOSE_UPGRADE: close_hard = false; end_code = MHD_REQUEST_ENDED_COMPLETED_OK_UPGRADE; break; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ case mhd_CONN_CLOSE_HTTP_COMPLETED: close_hard = false; end_code = MHD_REQUEST_ENDED_COMPLETED_OK; @@ -834,14 +834,14 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c, mhd_assert ((NULL == log_msg) || (MHD_SC_INTERNAL_ERROR != sc)); -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE if (mhd_CONN_CLOSE_UPGRADE == reason) { mhd_assert (mhd_HTTP_STAGE_UPGRADING == c->stage); c->event_loop_info = MHD_EVENT_LOOP_INFO_UPGRADED; } else -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ /* Make changes on the socket early to let the kernel and the remote * to process the changes in parallel. */ if (close_hard) @@ -861,7 +861,7 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c, use_graceful_closing = ! c->sk.state.rmt_shut_wr; if (use_graceful_closing) { -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS if (mhd_C_HAS_TLS (c)) { if ((0 != (((unsigned int) c->sk.ready) @@ -871,7 +871,7 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c, (mhd_TLS_PROCED_FAILED != mhd_tls_conn_shutdown (c->tls)); } else -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ if (1) { use_graceful_closing = mhd_socket_shut_wr (c->sk.fd); @@ -892,14 +892,14 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c, } } -#ifdef HAVE_LOG_FUNCTIONALITY +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY if (NULL != log_msg) { mhd_LOG_MSG (c->daemon, sc, log_msg); } -#else /* ! HAVE_LOG_FUNCTIONALITY */ +#else /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ (void) log_msg; -#endif /* ! HAVE_LOG_FUNCTIONALITY */ +#endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ #if 0 // TODO: notification callback mhd_assert ((mhd_HTTP_STAGE_INIT != c->stage) || (! c->rq.app_aware)); @@ -941,7 +941,7 @@ mhd_conn_pre_clean_part1 (struct MHD_Connection *restrict c) if (NULL != c->rq.cntn.lbuf.data) mhd_daemon_free_lbuf (c->daemon, &(c->rq.cntn.lbuf)); -#ifdef MHD_USE_EPOLL +#ifdef MHD_SUPPORT_EPOLL if (mhd_POLL_TYPE_EPOLL == c->daemon->events.poll_type) { struct epoll_event event; @@ -957,7 +957,7 @@ mhd_conn_pre_clean_part1 (struct MHD_Connection *restrict c) "Failed to remove connection socket from epoll."); } } -#endif /* MHD_USE_EPOLL */ +#endif /* MHD_SUPPORT_EPOLL */ } @@ -970,7 +970,7 @@ mhd_conn_pre_clean (struct MHD_Connection *restrict c) mhd_assert (c->dbg.closing_started); mhd_assert (! c->dbg.pre_cleaned); -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE if (NULL == c->upgr.c) #endif mhd_conn_pre_clean_part1 (c); diff --git a/src/mhd2/stream_funcs.h b/src/mhd2/stream_funcs.h @@ -260,7 +260,7 @@ enum mhd_ConnCloseReason mhd_CONN_CLOSE_ERR_REPLY_SENT , -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE /* Transition to another protocol */ /** @@ -270,7 +270,7 @@ enum mhd_ConnCloseReason */ mhd_CONN_CLOSE_UPGRADE , -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ /* Graceful closing */ /** @@ -307,11 +307,11 @@ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3); /** * Abort the stream and log message */ -#ifdef HAVE_LOG_FUNCTIONALITY +#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY # define mhd_STREAM_ABORT(c,r,m) (mhd_conn_start_closing ((c),(r),(m))) -#else /* ! HAVE_LOG_FUNCTIONALITY */ +#else /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ # define mhd_STREAM_ABORT(c,r,m) (mhd_conn_start_closing ((c),(r),NULL)) -#endif /* ! HAVE_LOG_FUNCTIONALITY */ +#endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ /** * Perform initial clean-up and mark for closing. @@ -361,7 +361,7 @@ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3); #define mhd_conn_start_closing_no_sys_res(c) \ mhd_conn_start_closing ((c), mhd_CONN_CLOSE_NO_SYS_RESOURCES, NULL) -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE /** * Perform initial clean-up and prepare for HTTP Upgrade. * Set the reason to "upgrading". @@ -369,7 +369,7 @@ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3); */ # define mhd_conn_pre_upgrade(c) \ mhd_conn_start_closing ((c), mhd_CONN_CLOSE_UPGRADE, NULL) -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ /** diff --git a/src/mhd2/stream_get_info.c b/src/mhd2/stream_get_info.c @@ -0,0 +1,105 @@ +/* + This file is part of GNU libmicrohttpd + Copyright (C) 2025 Evgeny Grin (Karlson2k) + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +/** + * @file src/mhd2/stream_get_info.c + * @brief The implementation of MHD_stream_get_info_*() functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" + +#include "mhd_unreachable.h" +#include "mhd_cntnr_ptr.h" + +#include "mhd_stream.h" +#include "mhd_connection.h" + +#include "daemon_funcs.h" + +#include "mhd_public_api.h" + + +MHD_EXTERN_ MHD_FN_MUST_CHECK_RESULT_ +MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode +MHD_stream_get_info_fixed_sz ( + struct MHD_Stream *MHD_RESTRICT stream, + enum MHD_StreamInfoFixedType info_type, + union MHD_StreamInfoFixedData *MHD_RESTRICT output_buf, + size_t output_buf_size) +{ + switch (info_type) + { + case MHD_STREAM_INFO_FIXED_DAEMON: + if (sizeof(output_buf->v_daemon) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_daemon = + mhd_daemon_get_master_daemon (mhd_CNTNR_PTR (stream, \ + struct MHD_Connection, \ + h1_stream)->daemon); + return MHD_SC_OK; + case MHD_STREAM_INFO_FIXED_CONNECTION: + if (sizeof(output_buf->v_connection) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_connection = mhd_CNTNR_PTR (stream, \ + struct MHD_Connection, \ + h1_stream); + return MHD_SC_OK; + + case MHD_STREAM_INFO_FIXED_SENTINEL: + default: + break; + } + return MHD_SC_INFO_GET_TYPE_UNKNOWN; +} + + +MHD_EXTERN_ MHD_FN_MUST_CHECK_RESULT_ +MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode +MHD_stream_get_info_dynamic_sz ( + struct MHD_Stream *MHD_RESTRICT stream, + enum MHD_StreamInfoDynamicType info_type, + union MHD_StreamInfoDynamicData *MHD_RESTRICT output_buf, + size_t output_buf_size) +{ + switch (info_type) + { + case MHD_STREAM_INFO_DYNAMIC_REQUEST: + if (mhd_HTTP_STAGE_REQ_LINE_RECEIVED > + mhd_CNTNR_PTR (stream, \ + struct MHD_Connection, \ + h1_stream)->stage) + return MHD_SC_TOO_EARLY; + if (sizeof(output_buf->v_request) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_request = + &(mhd_CNTNR_PTR (stream, \ + struct MHD_Connection, \ + h1_stream)->rq); + return MHD_SC_OK; + + case MHD_STREAM_INFO_DYNAMIC_SENTINEL: + default: + break; + } + return MHD_SC_INFO_GET_TYPE_UNKNOWN; +} diff --git a/src/mhd2/stream_process_reply.c b/src/mhd2/stream_process_reply.c @@ -162,7 +162,7 @@ get_conn_reuse (struct MHD_Connection *c) "keep-alive")) return mhd_CONN_MUST_CLOSE; -#if 0 // def MHD_UPGRADE_SUPPORT // TODO: Implement upgrade support +#if 0 // def MHD_SUPPORT_UPGRADE // TODO: Implement upgrade support /* TODO: Move below the next check when MHD stops closing connections * when response is queued in first callback */ if (NULL != r->upgrade_handler) @@ -174,7 +174,7 @@ get_conn_reuse (struct MHD_Connection *c) mhd_assert (! c->stop_with_error); return mhd_CONN_MUST_UPGRADE; } -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ return mhd_CONN_KEEPALIVE_POSSIBLE; } @@ -206,10 +206,10 @@ is_reply_body_needed (struct MHD_Connection *restrict c, #if 0 /* This check is not needed as upgrade handler is used only with code 101 */ -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE if (NULL != rp.response->upgrade_handler) return RP_BODY_NONE; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ #endif #if 0 @@ -262,10 +262,10 @@ setup_reply_properties (struct MHD_Connection *restrict c) 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); -#if 0 // def MHD_UPGRADE_SUPPORT // TODO: upgrade support +#if 0 // def MHD_SUPPORT_UPGRADE // TODO: upgrade support mhd_assert ( (NULL == r->upgrade_handler) || (RP_BODY_NONE == use_rp_body) ); -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ use_chunked = false; end_by_closing = false; @@ -315,7 +315,7 @@ setup_reply_properties (struct MHD_Connection *restrict c) c->rp.cntn_loc = mhd_REPLY_CNTN_LOC_CONN_BUF; break; } -#ifdef MHD_USE_SENDFILE +#ifdef mhd_USE_SENDFILE if (r->cntn.file.use_sf) { c->rp.cntn_loc = mhd_REPLY_CNTN_LOC_FILE; @@ -680,21 +680,21 @@ build_header_response_inn (struct MHD_Connection *restrict c) mhd_assert ((mhd_CONN_MUST_CLOSE == c->conn_reuse) || \ (mhd_CONN_KEEPALIVE_POSSIBLE == c->conn_reuse) || \ (mhd_CONN_MUST_UPGRADE == c->conn_reuse)); -#if 0 // def MHD_UPGRADE_SUPPORT // TODO: upgrade support +#if 0 // def MHD_SUPPORT_UPGRADE // TODO: upgrade support mhd_assert ((NULL == r->upgrade_handler) || \ (mhd_CONN_MUST_UPGRADE == c->keepalive)); -#else /* ! MHD_UPGRADE_SUPPORT */ +#else /* ! MHD_SUPPORT_UPGRADE */ mhd_assert (mhd_CONN_MUST_UPGRADE != c->conn_reuse); -#endif /* ! MHD_UPGRADE_SUPPORT */ +#endif /* ! MHD_SUPPORT_UPGRADE */ mhd_assert ((! c->rp.props.chunked) || c->rp.props.use_reply_body_headers); mhd_assert ((! c->rp.props.send_reply_body) || \ c->rp.props.use_reply_body_headers); mhd_assert ((! c->rp.props.end_by_closing) || \ (mhd_CONN_MUST_CLOSE == c->conn_reuse)); -#if 0 // def MHD_UPGRADE_SUPPORT // TODO: upgrade support +#if 0 // def MHD_SUPPORT_UPGRADE // TODO: upgrade support mhd_assert (NULL == r->upgrade_handler || \ ! c->rp.props.use_reply_body_headers); -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ check_connection_reply (c); @@ -1214,12 +1214,12 @@ mhd_stream_prep_unchunked_body (struct MHD_Connection *restrict c) c->rp.resp_iov.cnt = r->cntn.iovec.cnt; c->rp.resp_iov.sent = 0; } -#if defined(MHD_USE_SENDFILE) +#if defined(mhd_USE_SENDFILE) else if (mhd_REPLY_CNTN_LOC_FILE == c->rp.cntn_loc) { (void) 0; /* Nothing to do, file should be read directly */ } -#endif /* MHD_USE_SENDFILE */ +#endif /* mhd_USE_SENDFILE */ else { mhd_assert (0 && "Impossible value"); diff --git a/src/mhd2/stream_process_request.c b/src/mhd2/stream_process_request.c @@ -60,9 +60,9 @@ #include "stream_funcs.h" #include "daemon_funcs.h" -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER # include "post_parser_funcs.h" -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ #include "mhd_public_api.h" @@ -1186,7 +1186,10 @@ mhd_parse_get_args (size_t args_len, } if (i < args_len) /* Zero-terminate if not terminated */ args[i] = 0; - mhd_assert (0 == args[i]); + + /* assert below does not work correctly when compiler checks for + the provided buffer size */ + /* mhd_assert (0 == args[i]); */ /* Store found parameter */ @@ -2221,7 +2224,7 @@ mhd_stream_get_request_headers (struct MHD_Connection *restrict c, } -#ifdef COOKIE_SUPPORT +#ifdef MHD_SUPPORT_COOKIES /** * Cookie parsing result @@ -2568,7 +2571,7 @@ handle_req_cookie_no_space (struct MHD_Connection *restrict c) } -#endif /* COOKIE_SUPPORT */ +#endif /* MHD_SUPPORT_COOKIES */ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void @@ -2743,9 +2746,10 @@ mhd_stream_parse_request_headers (struct MHD_Connection *restrict c) continue; } -#ifdef COOKIE_SUPPORT +#ifdef MHD_SUPPORT_COOKIES /* "Cookie:" */ - if (mhd_str_equal_caseless_n_st (MHD_HTTP_HEADER_COOKIE, + if ((! c->daemon->req_cfg.disable_cookies) && + mhd_str_equal_caseless_n_st (MHD_HTTP_HEADER_COOKIE, f->field.nv.name.cstr, f->field.nv.name.len)) { @@ -2758,7 +2762,7 @@ mhd_stream_parse_request_headers (struct MHD_Connection *restrict c) } continue; } -#endif /* COOKIE_SUPPORT */ +#endif /* MHD_SUPPORT_COOKIES */ /* "Expect: 100-continue" */ if (mhd_str_equal_caseless_n_st (MHD_HTTP_HEADER_EXPECT, @@ -2786,6 +2790,7 @@ mhd_stream_parse_request_headers (struct MHD_Connection *restrict c) } } + c->rq.cntn.cntn_present = (has_trenc || has_cntnlen); if (has_trenc && has_cntnlen) { if (0 < c->daemon->req_cfg.strictness) @@ -2974,7 +2979,7 @@ mhd_stream_call_app_request_cb (struct MHD_Connection *restrict c) } c->stage = mhd_HTTP_STAGE_FULL_REQ_RECEIVED; return true; -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER case mhd_ACTION_POST_PARSE: if (0 == c->rq.cntn.cntn_size) { @@ -2994,16 +2999,16 @@ mhd_stream_call_app_request_cb (struct MHD_Connection *restrict c) } c->stage = mhd_HTTP_STAGE_BODY_RECEIVING; return true; -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ case mhd_ACTION_SUSPEND: c->suspended = true; return false; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_ACTION_UPGRADE: mhd_assert (0 == c->rq.cntn.cntn_size); c->stage = mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING; return false; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ case mhd_ACTION_ABORT: mhd_conn_start_closing_app_abort (c); return true; @@ -3059,14 +3064,14 @@ mhd_stream_process_upload_action (struct MHD_Connection *restrict c, case mhd_UPLOAD_ACTION_SUSPEND: c->suspended = true; return false; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_UPLOAD_ACTION_UPGRADE: mhd_assert (c->rq.cntn.recv_size == c->rq.cntn.cntn_size); mhd_assert (! c->rq.have_chunked_upload || \ mhd_HTTP_STAGE_FULL_REQ_RECEIVED == c->stage); c->stage = mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING; return false; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ case mhd_UPLOAD_ACTION_ABORT: mhd_conn_start_closing_app_abort (c); return true; @@ -3287,7 +3292,7 @@ process_request_chunked_body (struct MHD_Connection *restrict c) } mhd_assert (c->rq.app_aware); -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER if (mhd_ACTION_POST_PARSE == c->rq.app_act.head_act.act) { size_t size_provided; @@ -3307,7 +3312,7 @@ process_request_chunked_body (struct MHD_Connection *restrict c) c->rq.cntn.recv_size += size_provided; } else -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ if (1) { mhd_assert (mhd_ACTION_UPLOAD == c->rq.app_act.head_act.act); @@ -3421,7 +3426,7 @@ process_request_nonchunked_body (struct MHD_Connection *restrict c) read_buf_reuse = false; state_updated = false; -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER if (mhd_ACTION_POST_PARSE == c->rq.app_act.head_act.act) { size_t size_provided; @@ -3448,7 +3453,7 @@ process_request_nonchunked_body (struct MHD_Connection *restrict c) } } else -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ if (1) { mhd_assert (mhd_ACTION_UPLOAD == c->rq.app_act.head_act.act); @@ -3518,10 +3523,10 @@ mhd_stream_call_app_final_upload_cb (struct MHD_Connection *restrict c) mhd_assert (mhd_ACTION_POST_PARSE == c->rq.app_act.head_act.act || \ mhd_ACTION_UPLOAD == c->rq.app_act.head_act.act); -#ifdef HAVE_POST_PARSER +#ifdef MHD_SUPPORT_POST_PARSER if (mhd_ACTION_POST_PARSE == c->rq.app_act.head_act.act) return mhd_stream_process_post_finish (c); -#endif /* HAVE_POST_PARSER */ +#endif /* MHD_SUPPORT_POST_PARSER */ mhd_assert (mhd_ACTION_UPLOAD == c->rq.app_act.head_act.act); @@ -3934,12 +3939,12 @@ mhd_stream_check_and_grow_read_buffer_space (struct MHD_Connection *restrict c) case mhd_HTTP_STAGE_FULL_REPLY_SENT: case mhd_HTTP_STAGE_PRE_CLOSING: case mhd_HTTP_STAGE_CLOSED: -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING: case mhd_HTTP_STAGE_UPGRADING: case mhd_HTTP_STAGE_UPGRADED: case mhd_HTTP_STAGE_UPGRADED_CLEANING: -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ default: mhd_UNREACHABLE (); stage = MHD_PROC_RECV_BODY_NORMAL; diff --git a/src/mhd2/stream_process_states.c b/src/mhd2/stream_process_states.c @@ -51,19 +51,19 @@ #include "conn_mark_ready.h" -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE # include "upgrade_proc.h" -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void mhd_conn_event_loop_state_update (struct MHD_Connection *restrict c) { -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS mhd_assert (! mhd_C_HAS_TLS (c) || \ (mhd_CONN_STATE_TLS_CONNECTED == c->conn_state)); mhd_assert (mhd_C_HAS_TLS (c) || \ (mhd_CONN_STATE_TCP_CONNECTED == c->conn_state)); -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ switch (c->stage) { @@ -120,11 +120,11 @@ mhd_conn_event_loop_state_update (struct MHD_Connection *restrict c) mhd_assert (0 && "Impossible value"); mhd_UNREACHABLE (); break; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING: c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; break; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ case mhd_HTTP_STAGE_UNCHUNKED_BODY_UNREADY: mhd_assert (0 && "Should not be possible"); c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; @@ -150,7 +150,7 @@ mhd_conn_event_loop_state_update (struct MHD_Connection *restrict c) mhd_assert (0 && "Impossible value"); mhd_UNREACHABLE (); break; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_HTTP_STAGE_UPGRADING: mhd_assert (0 && "Impossible value"); mhd_UNREACHABLE (); @@ -163,7 +163,7 @@ mhd_conn_event_loop_state_update (struct MHD_Connection *restrict c) mhd_assert (0 && "Should be unreachable"); c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; break; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ case mhd_HTTP_STAGE_PRE_CLOSING: mhd_assert (0 && "Should be unreachable"); c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; @@ -269,9 +269,9 @@ mhd_conn_process_data (struct MHD_Connection *restrict c) } daemon_closing = (mhd_DAEMON_STATE_STOPPING == d->state); -#ifdef MHD_USE_THREADS +#ifdef MHD_SUPPORT_THREADS daemon_closing = daemon_closing || d->threading.stop_requested; -#endif /* MHD_USE_THREADS */ +#endif /* MHD_SUPPORT_THREADS */ if (daemon_closing) { mhd_conn_start_closing_d_shutdown (c); @@ -280,12 +280,12 @@ mhd_conn_process_data (struct MHD_Connection *restrict c) while (! c->suspended) { -#ifdef MHD_ENABLE_HTTPS +#ifdef MHD_SUPPORT_HTTPS mhd_assert (! mhd_C_HAS_TLS (c) || \ (mhd_CONN_STATE_TLS_CONNECTED == c->conn_state)); mhd_assert (mhd_C_HAS_TLS (c) || \ (mhd_CONN_STATE_TCP_CONNECTED == c->conn_state)); -#endif /* MHD_ENABLE_HTTPS */ +#endif /* MHD_SUPPORT_HTTPS */ switch (c->stage) { case mhd_HTTP_STAGE_INIT: @@ -329,9 +329,9 @@ mhd_conn_process_data (struct MHD_Connection *restrict c) if (c->continue_message_write_offset == mhd_SSTR_LEN (mdh_HTTP_1_1_100_CONTINUE_REPLY)) { -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE c->rp.sent_100_cntn = true; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ c->stage = mhd_HTTP_STAGE_BODY_RECEIVING; continue; } @@ -406,12 +406,12 @@ mhd_conn_process_data (struct MHD_Connection *restrict c) else c->stage = mhd_HTTP_STAGE_FULL_REPLY_SENT; continue; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING: if (! mhd_upgrade_try_start_upgrading (c)) break; continue; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ case mhd_HTTP_STAGE_UNCHUNKED_BODY_READY: mhd_assert (c->rp.props.send_reply_body); mhd_assert (! c->rp.props.chunked); @@ -469,7 +469,7 @@ mhd_conn_process_data (struct MHD_Connection *restrict c) && ! c->discard_request && ! c->sk.state.rmt_shut_wr); continue; -#ifdef MHD_UPGRADE_SUPPORT +#ifdef MHD_SUPPORT_UPGRADE case mhd_HTTP_STAGE_UPGRADING: if (mhd_upgrade_finish_switch_to_upgraded (c)) return true; /* Do not close connection */ @@ -483,7 +483,7 @@ mhd_conn_process_data (struct MHD_Connection *restrict c) mhd_assert (0 && "Should be unreachable"); mhd_UNREACHABLE (); break; -#endif /* MHD_UPGRADE_SUPPORT */ +#endif /* MHD_SUPPORT_UPGRADE */ case mhd_HTTP_STAGE_PRE_CLOSING: return false; case mhd_HTTP_STAGE_CLOSED: diff --git a/src/mhd2/sys_ip_headers.h b/src/mhd2/sys_ip_headers.h @@ -53,6 +53,16 @@ # include <ws2tcpip.h> #endif +#if ! defined(HAVE_DCLR_IPV6_V6ONLY) && defined(IPV6_V6ONLY) +/* Mis-deteted by configure */ +# define HAVE_DCLR_IPV6_V6ONLY 1 +#endif + +#if ! defined(HAVE_DCLR_TCP_NODELAY) && defined(TCP_NODELAY) +/* Mis-deteted by configure */ +# define HAVE_DCLR_TCP_NODELAY 1 +#endif + #ifdef IPPROTO_TCP # if defined(TCP_CORK) /** diff --git a/src/mhd2/sys_poll.h b/src/mhd2/sys_poll.h @@ -32,7 +32,7 @@ #include "mhd_sys_options.h" -#ifdef MHD_USE_POLL +#ifdef MHD_SUPPORT_POLL # include "mhd_socket_type.h" # if defined(MHD_SOCKETS_KIND_POSIX) # include <poll.h> @@ -44,36 +44,31 @@ #error Uknown sockets type # endif -# if (defined(HAVE_DECL_POLLRDNORM) && (0 != HAVE_DECL_POLLRDNORM + 0)) || \ - defined(POLLRDNORM) +# if defined(HAVE_DCLR_POLLRDNORM) || defined(POLLRDNORM) # define MHD_POLL_IN POLLRDNORM # else # define MHD_POLL_IN POLLIN # endif -# if (defined(HAVE_DECL_POLLWRNORM) && (0 != HAVE_DECL_POLLWRNORM + 0)) || \ - defined(POLLWRNORM) +# if defined(HAVE_DCLR_POLLWRNORM) || defined(POLLWRNORM) # define MHD_POLL_OUT POLLWRNORM # else # define MHD_POLL_OUT POLLOUT # endif -# if (defined(HAVE_DECL_POLLRDBAND) && (0 != HAVE_DECL_POLLRDBAND + 0)) || \ - defined(POLLRDBAND) +# if defined(HAVE_DCLR_POLLRDBAND) || defined(POLLRDBAND) # define MHD_POLLRDBAND POLLRDBAND # else # define MHD_POLLRDBAND (0) # endif -# if (defined(HAVE_DECL_POLLWRBAND) && (0 != HAVE_DECL_POLLWRBAND + 0)) || \ - defined(POLLWRBAND) +# if defined(HAVE_DCLR_POLLWRBAND) || defined(POLLWRBAND) # define MHD_POLLWRBAND POLLWRBAND # else # define MHD_POLLWRBAND (0) # endif -# if (defined(HAVE_DECL_POLLPRI) && (0 != HAVE_DECL_POLLPRI + 0)) || \ - defined(POLLWRBAND) +# if defined(HAVE_DCLR_POLLPRI) || defined(POLLWRBAND) # define MHD_POLLPRI POLLPRI # else # define MHD_POLLPRI (0) @@ -86,6 +81,6 @@ # define MHD_POLLHUP_ON_REM_SHUT_WR 1 # endif -#endif /* MHD_USE_POLL */ +#endif /* MHD_SUPPORT_POLL */ #endif /* ! MHD_SYS_POLL_H */ diff --git a/src/mhd2/sys_select.h b/src/mhd2/sys_select.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT # include "mhd_socket_type.h" # if defined(MHD_SOCKETS_KIND_POSIX) # ifdef HAVE_SYS_SELECT_H @@ -56,6 +56,6 @@ #error Uknown sockets type # endif -#endif /* MHD_USE_SELECT */ +#endif /* MHD_SUPPORT_SELECT */ #endif /* ! MHD_SYS_SELECT_H */ diff --git a/src/mhd2/sys_sendfile.h b/src/mhd2/sys_sendfile.h @@ -42,8 +42,8 @@ # include <sys/socket.h> # endif # include <sys/uio.h> -#elif defined(MHD_USE_SENDFILE) -#error MHD_USE_SENDFILE is defined, while no HAVE_xxx_SENDFILE defined +#elif defined(mhd_USE_SENDFILE) +#error mhd_USE_SENDFILE is defined, while no HAVE_xxx_SENDFILE defined #endif #endif /* ! MHD_SYS_SENDFILE_H */ diff --git a/src/mhd2/sys_sockets_headers.h b/src/mhd2/sys_sockets_headers.h @@ -48,31 +48,81 @@ # include <sys/un.h> #endif -#if defined(HAVE_SOCK_NONBLOCK) && ! defined(MHD_SOCKETS_KIND_WINSOCK) +#if defined(SOCK_NONBLOCK) && ! defined(HAVE_DCLR_SOCK_NONBLOCK) +/* Mis-detected by configure */ +# define HAVE_DCLR_SOCK_NONBLOCK 1 +#endif + +#if defined(SOCK_CLOEXEC) && ! defined(HAVE_DCLR_SOCK_CLOEXEC) +/* Mis-detected by configure */ +# define HAVE_DCLR_SOCK_CLOEXEC 1 +#endif + +#if defined(SOCK_NOSIGPIPE) && ! defined(HAVE_DCLR_SOCK_NOSIGPIPE) +/* Mis-detected by configure */ +# define HAVE_DCLR_SOCK_NOSIGPIPE 1 +#endif + +#if defined(MSG_NOSIGNAL) && ! defined(HAVE_DCLR_MSG_NOSIGNAL) +/* Mis-detected by configure */ +# define HAVE_DCLR_MSG_NOSIGNAL 1 +#endif + +#if defined(MSG_MORE) && ! defined(HAVE_DCLR_MSG_MORE) +/* Mis-detected by configure */ +# define HAVE_DCLR_MSG_MORE 1 +#endif + +#if defined(SOL_SOCKET) && ! defined(HAVE_DCLR_SOL_SOCKET) +/* Mis-detected by configure */ +# define HAVE_DCLR_SOL_SOCKET 1 +#endif + +#if defined(SO_REUSEADDR) && ! defined(HAVE_DCLR_SO_REUSEADDR) +/* Mis-detected by configure */ +# define HAVE_DCLR_SO_REUSEADDR 1 +#endif + +#if defined(SO_REUSEPORT) && ! defined(HAVE_DCLR_SO_REUSEPORT) +/* Mis-detected by configure */ +# define HAVE_DCLR_SO_REUSEPORT 1 +#endif + +#if defined(SO_LINGER) && ! defined(HAVE_DCLR_SO_LINGER) +/* Mis-detected by configure */ +# define HAVE_DCLR_SO_LINGER 1 +#endif + +#if defined(SO_NOSIGPIPE) && ! defined(HAVE_DCLR_SO_NOSIGPIPE) +/* Mis-detected by configure */ +# define HAVE_DCLR_SO_NOSIGPIPE 1 +#endif + +#if defined(HAVE_DCLR_SOCK_NONBLOCK) && ! defined(MHD_SOCKETS_KIND_WINSOCK) # define mhd_SOCK_NONBLOCK SOCK_NONBLOCK #else # define mhd_SOCK_NONBLOCK (0) #endif -#if defined(SOCK_CLOEXEC) && ! defined(MHD_SOCKETS_KIND_WINSOCK) +#if defined(HAVE_DCLR_SOCK_CLOEXEC) && ! defined(MHD_SOCKETS_KIND_WINSOCK) # define mhd_SOCK_CLOEXEC SOCK_CLOEXEC #else # define mhd_SOCK_CLOEXEC (0) #endif -#if defined(SOCK_NOSIGPIPE) && ! defined(MHD_SOCKETS_KIND_WINSOCK) +#if defined(HAVE_DCLR_SOCK_NOSIGPIPE) && ! defined(MHD_SOCKETS_KIND_WINSOCK) # define mhd_SOCK_NOSIGPIPE SOCK_NOSIGPIPE #else # define mhd_SOCK_NOSIGPIPE (0) #endif -#if defined(MSG_NOSIGNAL) && ! defined(MHD_SOCKETS_KIND_WINSOCK) +#if defined(HAVE_DCLR_MSG_NOSIGNAL) && ! defined(MHD_SOCKETS_KIND_WINSOCK) # define mhd_MSG_NOSIGNAL MSG_NOSIGNAL #else # define mhd_MSG_NOSIGNAL (0) #endif -#ifdef MSG_MORE +#ifdef HAVE_DCLR_MSG_MORE # ifdef __linux__ /* MSG_MORE signal kernel to buffer outbond data and works like * TCP_CORK per call without actually setting TCP_CORK value. @@ -121,11 +171,9 @@ typedef int mhd_SCKT_SEND_SIZE; #endif -#if defined(AF_UNIX) || \ - (defined(HAVE_DECL_AF_UNIX) && (HAVE_DECL_AF_UNIX + 0 != 0)) +#if defined(AF_UNIX) || defined(HAVE_DCLR_AF_UNIX) # define MHD_AF_UNIX AF_UNIX -#elif defined(AF_LOCAL) || \ - (defined(HAVE_DECL_AF_LOCAL) && (HAVE_DECL_AF_LOCAL + 0 != 0)) +#elif defined(AF_LOCAL) || defined(HAVE_DCLR_AF_LOCAL) # define MHD_AF_UNIX AF_LOCAL #endif /* AF_UNIX */ @@ -141,25 +189,41 @@ typedef int mhd_SCKT_SEND_SIZE; #endif -#if defined(MHD_socket_nosignal_) || \ - (defined(SOL_SOCKET) && defined(SO_NOSIGPIPE)) +#if defined(HAVE_DCLR_SOL_SOCKET) && defined(HAVE_DCLR_SO_NOSIGPIPE) /** - * Indicate that SIGPIPE can be suppressed by MHD for normal send() by flags - * or socket options. - * If this macro is undefined, MHD cannot suppress SIGPIPE for socket functions - * so sendfile() or writev() calls are avoided in application threads. + * Helper for mhd_socket_nosignal() */ -# define mhd_SEND_SPIPE_SUPPRESS_POSSIBLE 1 -#endif /* MHD_SOCKETS_KIND_WINSOCK || MHD_socket_nosignal_ || MSG_NOSIGNAL */ +# ifdef HAVE_COMPOUND_LITERALS_LVALUES +# define mhd_socket_nosig_helper_int_one ((mhd_SCKT_OPT_BOOL){1}) +# else +/** + * Internal static const helper for mhd_socket_nosignal() + */ +static const mhd_SCKT_OPT_BOOL mhd_socket_nosig_helper_int_one = 1; +# endif +/** + * Change socket options to no signal on remote disconnect / broken connection. + * + * @param sock socket to manipulate + * @return non-zero if succeeded, zero otherwise + */ +# define mhd_socket_nosignal(sock) \ + (! setsockopt ((sock),SOL_SOCKET,SO_NOSIGPIPE, \ + &mhd_socket_nosig_helper_int_one, \ + sizeof(mhd_SCKT_OPT_BOOL))) +#endif /* SOL_SOCKET && SO_NOSIGPIPE */ -#if ! defined(MHD_SOCKETS_KIND_WINSOCK) + +#if defined(mhd_socket_nosignal) || defined(HAVE_DCLR_MSG_NOSIGNAL) /** - * Indicate that suppression of SIGPIPE is required for some network - * system calls. + * Indicate that SIGPIPE can be suppressed by MHD for normal send() by flags + * or socket options. + * If this macro is undefined, MHD cannot suppress SIGPIPE for socket functions + * so application need to handle SIGPIPE. */ -# define mhd_SEND_SPIPE_SUPPRESS_NEEDED 1 -#endif +# define mhd_SEND_SPIPE_SUPPRESS_POSSIBLE 1 +#endif /* mhd_socket_nosignal || HAVE_DCLR_MSG_NOSIGNAL */ #endif /* ! MHD_SYS_SOCKETS_HEADERS_H */ diff --git a/src/mhd2/tls_gnu_conn_data.h b/src/mhd2/tls_gnu_conn_data.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS #error This header can be used only if GnuTLS is enabled #endif diff --git a/src/mhd2/tls_gnu_daemon_data.h b/src/mhd2/tls_gnu_daemon_data.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS #error This header can be used only if GnuTLS is enabled #endif diff --git a/src/mhd2/tls_gnu_funcs.c b/src/mhd2/tls_gnu_funcs.c @@ -50,8 +50,6 @@ #include "tls_gnu_funcs.h" #include "daemon_options.h" - -#include "mhd_public_api.h" #include "daemon_logger.h" #ifdef mhd_TLS_GNU_DH_PARAMS_NEEDS_PKCS3 @@ -62,6 +60,8 @@ # include <stdio.h> /* For TLS debug printing */ #endif +#include "mhd_public_api.h" + #ifdef mhd_USE_TLS_DEBUG_MESSAGES static void mhd_tls_gnu_debug_print (int level, const char *msg) @@ -783,3 +783,46 @@ mhd_tls_gnu_conn_send (struct mhd_TlsGnuConnData *restrict c_tls, *sent = (size_t) res; return mhd_SOCKET_ERR_NO_ERROR; } + + +/* ** TLS connection information ** */ + +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_OUT_ (2) void +mhd_tls_gnu_conn_get_tls_sess ( + struct mhd_TlsGnuConnData *restrict c_tls, + union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) +{ + tls_sess_out->v_gnutls_session = c_tls->sess; +} + + +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_OUT_ (2) bool +mhd_tls_gnu_conn_get_tls_ver (struct mhd_TlsGnuConnData *restrict c_tls, + enum MHD_TlsVersion *restrict tls_ver_out) +{ + gnutls_protocol_t gtls_tls_ver; + + mhd_assert (c_tls->dbg.is_tls_handshake_completed); + + gtls_tls_ver = gnutls_protocol_get_version (c_tls->sess); +#if GNUTLS_VERSION_NUMBER >= 0x030603 + if (GNUTLS_TLS1_3 == gtls_tls_ver) + *tls_ver_out = MHD_TLS_VERSION_1_3; + else +#endif + if (GNUTLS_TLS1_2 == gtls_tls_ver) + *tls_ver_out = MHD_TLS_VERSION_1_2; + else if (GNUTLS_TLS1_1 == gtls_tls_ver) + *tls_ver_out = MHD_TLS_VERSION_1_1; + else if (GNUTLS_TLS1_0 == gtls_tls_ver) + *tls_ver_out = MHD_TLS_VERSION_1_0; + else if (GNUTLS_VERSION_UNKNOWN == gtls_tls_ver) + return false; + else + /* The TLS version is know for GnuTLS, but cannot be mapped */ + *tls_ver_out = MHD_TLS_VERSION_UNKNOWN; + + return true; +} diff --git a/src/mhd2/tls_gnu_funcs.h b/src/mhd2/tls_gnu_funcs.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS #error This header can be used only if GnuTLS is enabled #endif @@ -51,6 +51,9 @@ struct mhd_TlsGnuDaemonData; /* Forward declaration */ */ struct mhd_TlsGnuConnData; /* Forward declaration */ +union MHD_ConnInfoDynamicTlsSess; /* Forward declaration */ + +enum MHD_TlsVersion; /* Forward declaration */ /* ** Global initialisation / de-initialisation ** */ @@ -249,4 +252,30 @@ mhd_tls_gnu_conn_send (struct mhd_TlsGnuConnData *restrict c_tls, size_t *restrict sent) MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3,2) MHD_FN_PAR_OUT_ (4); + +/* ** TLS connection information ** */ + +/** + * Get the TLS session used in connection + * @param c_tls the connection TLS handle + * @param tls_ver_out the pointer to variable to be set to the TLS version + */ +MHD_INTERNAL void +mhd_tls_gnu_conn_get_tls_sess ( + struct mhd_TlsGnuConnData *restrict c_tls, + union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2); + +/** + * Get the TLS version used in connection + * @param c_tls the connection TLS handle + * @param tls_ver_out the pointer to variable to be set to the TLS version + * @return 'true' is TLS version information set successfully, + * 'false' if TLS version information cannot be obtained or mapped + */ +MHD_INTERNAL bool +mhd_tls_gnu_conn_get_tls_ver (struct mhd_TlsGnuConnData *restrict c_tls, + enum MHD_TlsVersion *restrict tls_ver_out) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2); + #endif /* ! MHD_TLS_GNU_FUNCS_H */ diff --git a/src/mhd2/tls_gnu_tls_lib.h b/src/mhd2/tls_gnu_tls_lib.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS #error This header can be used only if GnuTLS is enabled #endif diff --git a/src/mhd2/tls_multi_conn_data.h b/src/mhd2/tls_multi_conn_data.h @@ -35,10 +35,10 @@ #error This header can be used only if MultiTLS is enabled #endif -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS struct mhd_TlsGnuConnData; /* forward declaration */ #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL struct mhd_TlsOpenConnData; /* forward declaration */ #endif @@ -47,13 +47,13 @@ struct mhd_TlsOpenConnData; /* forward declaration */ */ struct mhd_TlsMultiConnRoutePtr { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS /** * Pointer to GnuTLS connection-specific data */ struct mhd_TlsGnuConnData *gnutls; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL /** * Pointer to OpenSSL connection-specific data */ diff --git a/src/mhd2/tls_multi_daemon_data.h b/src/mhd2/tls_multi_daemon_data.h @@ -35,10 +35,10 @@ #error This header can be used only if MultiTLS is enabled #endif -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS struct mhd_TlsGnuDaemonData; /* forward declaration */ #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL struct mhd_TlsOpenDaemonData; /* forward declaration */ #endif @@ -47,13 +47,13 @@ struct mhd_TlsOpenDaemonData; /* forward declaration */ */ struct mhd_TlsMultiDaemonRoutePtr { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS /** * Pointer to GnuTLS daemon-specific data */ struct mhd_TlsGnuDaemonData *gnutls; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL /** * Pointer to OpenSSL daemon-specific data */ diff --git a/src/mhd2/tls_multi_funcs.c b/src/mhd2/tls_multi_funcs.c @@ -43,22 +43,22 @@ #include "tls_multi_funcs.h" /* Include all supported TLS backends headers */ -#if defined(MHD_USE_GNUTLS) +#if defined(MHD_SUPPORT_GNUTLS) # include "tls_gnu_funcs.h" #endif -#if defined(MHD_USE_OPENSSL) +#if defined(MHD_SUPPORT_OPENSSL) # include "tls_open_funcs.h" #endif #include "daemon_options.h" - -#include "mhd_public_api.h" #include "daemon_logger.h" #ifdef mhd_USE_TLS_DEBUG_MESSAGES # include <stdio.h> /* For TLS debug printing */ #endif +#include "mhd_public_api.h" + #ifdef mhd_USE_TLS_DEBUG_MESSAGES # define mhd_M_DEBUG_PRINT(msg) \ do { fprintf (stderr, "## MultiTLS: " msg "\n"); \ @@ -77,10 +77,10 @@ MHD_INTERNAL void mhd_tls_multi_global_init_once (void) { -#if defined(MHD_USE_GNUTLS) +#if defined(MHD_SUPPORT_GNUTLS) mhd_tls_gnu_global_init_once (); #endif -#if defined(MHD_USE_OPENSSL) +#if defined(MHD_SUPPORT_OPENSSL) mhd_tls_open_global_init_once (); #endif } @@ -90,10 +90,10 @@ MHD_INTERNAL void mhd_tls_multi_global_deinit (void) { /* Note: the order is reversed to match the initialisation */ -#if defined(MHD_USE_OPENSSL) +#if defined(MHD_SUPPORT_OPENSSL) mhd_tls_open_global_deinit (); #endif -#if defined(MHD_USE_GNUTLS) +#if defined(MHD_SUPPORT_GNUTLS) mhd_tls_gnu_global_deinit (); #endif } @@ -102,10 +102,10 @@ mhd_tls_multi_global_deinit (void) MHD_INTERNAL void mhd_tls_multi_global_re_init (void) { -#if defined(MHD_USE_GNUTLS) +#if defined(MHD_SUPPORT_GNUTLS) mhd_tls_gnu_global_re_init (); #endif -#if defined(MHD_USE_OPENSSL) +#if defined(MHD_SUPPORT_OPENSSL) mhd_tls_open_global_re_init (); #endif } @@ -122,26 +122,26 @@ mhd_tls_multi_is_edge_trigg_supported (struct DaemonOptions *s) mhd_UNREACHABLE (); return false; case MHD_TLS_BACKEND_ANY: -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS if (mhd_tls_gnu_is_edge_trigg_supported (s) && mhd_tls_gnu_is_inited_fine ()) return true; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL if (mhd_tls_open_is_edge_trigg_supported (s) && mhd_tls_open_is_inited_fine ()) return true; #endif return false; case MHD_TLS_BACKEND_GNUTLS: -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS /* Ignore "backend inited" status here, it will be checked on daemon TLS init */ return mhd_tls_gnu_is_edge_trigg_supported (s); #endif break; case MHD_TLS_BACKEND_OPENSSL: -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL /* Ignore "backend inited" status here, it will be checked on daemon TLS init */ return mhd_tls_open_is_edge_trigg_supported (s); @@ -175,13 +175,13 @@ tls_daemon_init_try (enum mhd_TlsMultiRoute route, { mhd_StatusCodeInt res; -#ifndef MHD_USE_OPENSSL +#ifndef MHD_SUPPORT_OPENSSL (void) sk_edge_trigg; /* Unused, mute compiler warning */ -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ switch (route) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: if (! mhd_tls_gnu_is_inited_fine ()) return MHD_SC_TLS_BACKEND_UNAVAILABLE; @@ -200,7 +200,7 @@ tls_daemon_init_try (enum mhd_TlsMultiRoute route, "the daemon, error code: %u", (unsigned) res); return res; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: if (! mhd_tls_open_is_inited_fine ()) return MHD_SC_TLS_BACKEND_UNAVAILABLE; @@ -252,10 +252,10 @@ mhd_tls_multi_daemon_init (struct MHD_Daemon *restrict d, { size_t i; enum mhd_TlsMultiRoute backends[] = { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS mhd_TLS_MULTI_ROUTE_GNU, #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL mhd_TLS_MULTI_ROUTE_OPEN, #endif mhd_TLS_MULTI_ROUTE_NONE /* Not used */ @@ -273,7 +273,7 @@ mhd_tls_multi_daemon_init (struct MHD_Daemon *restrict d, } } break; -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: mhd_assert (mhd_tls_gnu_is_inited_fine ()); /* Must be checked earlier */ res = tls_daemon_init_try (mhd_TLS_MULTI_ROUTE_GNU, @@ -282,8 +282,8 @@ mhd_tls_multi_daemon_init (struct MHD_Daemon *restrict d, s, d_tls); break; -#endif /* MHD_USE_GNUTLS */ -#ifdef MHD_USE_OPENSSL +#endif /* MHD_SUPPORT_GNUTLS */ +#ifdef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: mhd_assert (mhd_tls_open_is_inited_fine ()); /* Must be checked earlier */ res = tls_daemon_init_try (mhd_TLS_MULTI_ROUTE_OPEN, @@ -291,15 +291,15 @@ mhd_tls_multi_daemon_init (struct MHD_Daemon *restrict d, sk_edge_trigg, s, d_tls); -#endif /* MHD_USE_OPENSSL */ +#endif /* MHD_SUPPORT_OPENSSL */ break; -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case MHD_TLS_BACKEND_NONE: default: mhd_UNREACHABLE (); @@ -323,22 +323,22 @@ mhd_tls_multi_daemon_deinit (struct mhd_TlsMultiDaemonData *restrict d_tls) { switch (d_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: mhd_tls_gnu_daemon_deinit (d_tls->data.gnutls); break; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: mhd_tls_open_daemon_deinit (d_tls->data.openssl); break; #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -358,22 +358,22 @@ mhd_tls_multi_conn_get_tls_size (struct mhd_TlsMultiDaemonData *restrict d_tls) data_size = sizeof(struct mhd_TlsMultiConnData); switch (d_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: data_size += mhd_tls_gnu_conn_get_tls_size (d_tls->data.gnutls); break; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: data_size += mhd_tls_open_conn_get_tls_size (d_tls->data.openssl); break; #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -392,7 +392,7 @@ mhd_tls_multi_conn_init (const struct mhd_TlsMultiDaemonData *restrict d_tls, c_tls->choice = d_tls->choice; switch (c_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: /* Assume the same alignment requirements for both structures */ c_tls->data.gnutls = (struct mhd_TlsGnuConnData *) (c_tls + 1); @@ -400,7 +400,7 @@ mhd_tls_multi_conn_init (const struct mhd_TlsMultiDaemonData *restrict d_tls, sk, c_tls->data.gnutls); #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: /* Assume the same alignment requirements for both structures */ c_tls->data.openssl = (struct mhd_TlsOpenConnData *) (c_tls + 1); @@ -408,12 +408,12 @@ mhd_tls_multi_conn_init (const struct mhd_TlsMultiDaemonData *restrict d_tls, sk, c_tls->data.openssl); #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -434,22 +434,22 @@ mhd_tls_multi_conn_deinit (struct mhd_TlsMultiConnData *restrict c_tls) { switch (c_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: mhd_tls_gnu_conn_deinit (c_tls->data.gnutls); break; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: mhd_tls_open_conn_deinit (c_tls->data.openssl); break; #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -465,20 +465,20 @@ mhd_tls_multi_conn_handshake (struct mhd_TlsMultiConnData *restrict c_tls) { switch (c_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: return mhd_tls_gnu_conn_handshake (c_tls->data.gnutls); #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: return mhd_tls_open_conn_handshake (c_tls->data.openssl); #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -494,20 +494,20 @@ mhd_tls_multi_conn_shutdown (struct mhd_TlsMultiConnData *restrict c_tls) { switch (c_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: return mhd_tls_gnu_conn_shutdown (c_tls->data.gnutls); #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: return mhd_tls_open_conn_shutdown (c_tls->data.openssl); #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -529,26 +529,26 @@ mhd_tls_multi_conn_recv (struct mhd_TlsMultiConnData *restrict c_tls, { switch (c_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: return mhd_tls_gnu_conn_recv (c_tls->data.gnutls, buf_size, buf, received); #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: return mhd_tls_open_conn_recv (c_tls->data.openssl, buf_size, buf, received); #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -563,20 +563,20 @@ mhd_tls_multi_conn_has_data_in (struct mhd_TlsMultiConnData *restrict c_tls) { switch (c_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: return mhd_tls_gnu_conn_has_data_in (c_tls->data.gnutls); #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: return mhd_tls_open_conn_has_data_in (c_tls->data.openssl); #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -596,26 +596,26 @@ mhd_tls_multi_conn_send (struct mhd_TlsMultiConnData *restrict c_tls, { switch (c_tls->choice) { -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS case mhd_TLS_MULTI_ROUTE_GNU: return mhd_tls_gnu_conn_send (c_tls->data.gnutls, buf_size, buf, sent); #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL case mhd_TLS_MULTI_ROUTE_OPEN: return mhd_tls_open_conn_send (c_tls->data.openssl, buf_size, buf, sent); #endif -#ifndef MHD_USE_GNUTLS +#ifndef MHD_SUPPORT_GNUTLS case MHD_TLS_BACKEND_GNUTLS: -#endif /* ! MHD_USE_GNUTLS */ -#ifndef MHD_USE_OPENSSL +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL case MHD_TLS_BACKEND_OPENSSL: -#endif /* ! MHD_USE_OPENSSL */ +#endif /* ! MHD_SUPPORT_OPENSSL */ case mhd_TLS_MULTI_ROUTE_NONE: default: mhd_UNREACHABLE (); @@ -623,3 +623,71 @@ mhd_tls_multi_conn_send (struct mhd_TlsMultiConnData *restrict c_tls, } return mhd_SOCKET_ERR_INTERNAL; } + + +/* ** TLS connection information ** */ + +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_OUT_ (2) void +mhd_tls_multi_conn_get_tls_sess ( + struct mhd_TlsMultiConnData *restrict c_tls, + union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) +{ + switch (c_tls->choice) + { +#ifdef MHD_SUPPORT_GNUTLS + case mhd_TLS_MULTI_ROUTE_GNU: + mhd_tls_gnu_conn_get_tls_sess (c_tls->data.gnutls, + tls_sess_out); + break; +#endif +#ifdef MHD_SUPPORT_OPENSSL + case mhd_TLS_MULTI_ROUTE_OPEN: + mhd_tls_open_conn_get_tls_sess (c_tls->data.openssl, + tls_sess_out); + break; +#endif +#ifndef MHD_SUPPORT_GNUTLS + case MHD_TLS_BACKEND_GNUTLS: +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL + case MHD_TLS_BACKEND_OPENSSL: +#endif /* ! MHD_SUPPORT_OPENSSL */ + case mhd_TLS_MULTI_ROUTE_NONE: + default: + mhd_UNREACHABLE (); + break; + } +} + + +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_OUT_ (2) bool +mhd_tls_multi_conn_get_tls_ver (struct mhd_TlsMultiConnData *restrict c_tls, + enum MHD_TlsVersion *restrict tls_ver_out) +{ + switch (c_tls->choice) + { +#ifdef MHD_SUPPORT_GNUTLS + case mhd_TLS_MULTI_ROUTE_GNU: + return mhd_tls_gnu_conn_get_tls_ver (c_tls->data.gnutls, + tls_ver_out); +#endif +#ifdef MHD_SUPPORT_OPENSSL + case mhd_TLS_MULTI_ROUTE_OPEN: + return mhd_tls_open_conn_get_tls_ver (c_tls->data.openssl, + tls_ver_out); +#endif +#ifndef MHD_SUPPORT_GNUTLS + case MHD_TLS_BACKEND_GNUTLS: +#endif /* ! MHD_SUPPORT_GNUTLS */ +#ifndef MHD_SUPPORT_OPENSSL + case MHD_TLS_BACKEND_OPENSSL: +#endif /* ! MHD_SUPPORT_OPENSSL */ + case mhd_TLS_MULTI_ROUTE_NONE: + default: + mhd_UNREACHABLE (); + break; + } + return false; +} diff --git a/src/mhd2/tls_multi_funcs.h b/src/mhd2/tls_multi_funcs.h @@ -53,6 +53,9 @@ struct mhd_TlsMultiDaemonData; /* Forward declaration */ */ struct mhd_TlsMultiConnData; /* Forward declaration */ +union MHD_ConnInfoDynamicTlsSess; /* Forward declaration */ + +enum MHD_TlsVersion; /* Forward declaration */ /* ** Global initialisation / de-initialisation ** */ @@ -228,4 +231,30 @@ mhd_tls_multi_conn_send (struct mhd_TlsMultiConnData *restrict c_tls, size_t *restrict sent) MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3,2) MHD_FN_PAR_OUT_ (4); + +/* ** TLS connection information ** */ + +/** + * Get the TLS session used in connection + * @param c_tls the connection TLS handle + * @param tls_ver_out the pointer to variable to be set to the TLS version + */ +MHD_INTERNAL void +mhd_tls_multi_conn_get_tls_sess ( + struct mhd_TlsMultiConnData *restrict c_tls, + union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2); + +/** + * Get the TLS version used in connection + * @param c_tls the connection TLS handle + * @param tls_ver_out the pointer to variable to be set to the TLS version + * @return 'true' is TLS version information set successfully, + * 'false' if TLS version information cannot be obtained or mapped + */ +MHD_INTERNAL bool +mhd_tls_multi_conn_get_tls_ver (struct mhd_TlsMultiConnData *restrict c_tls, + enum MHD_TlsVersion *restrict tls_ver_out) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2); + #endif /* ! MHD_TLS_MULTI_FUNCS_H */ diff --git a/src/mhd2/tls_multi_tls_lib.h b/src/mhd2/tls_multi_tls_lib.h @@ -45,14 +45,14 @@ enum mhd_TlsMultiRoute * Invalid value if TLS is used. */ mhd_TLS_MULTI_ROUTE_NONE = 0 -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS , /** * Use GnuTLS backend */ mhd_TLS_MULTI_ROUTE_GNU #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL , /** * Use OpenSSL backend diff --git a/src/mhd2/tls_open_conn_data.h b/src/mhd2/tls_open_conn_data.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_USE_OPENSSL +#ifndef MHD_SUPPORT_OPENSSL #error This header can be used only if GnuTLS is enabled #endif @@ -47,7 +47,7 @@ struct mhd_TlsOpenConnDebug #endif /* ! NDEBUG */ /** - * The structure with connection-specific GnuTLS data + * The structure with connection-specific OpenSSL data */ struct mhd_TlsOpenConnData { diff --git a/src/mhd2/tls_open_daemon_data.h b/src/mhd2/tls_open_daemon_data.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_USE_OPENSSL +#ifndef MHD_SUPPORT_OPENSSL #error This header can be used only if GnuTLS is enabled #endif diff --git a/src/mhd2/tls_open_funcs.c b/src/mhd2/tls_open_funcs.c @@ -49,12 +49,12 @@ #include "daemon_logger.h" -#include "mhd_public_api.h" - #ifdef mhd_USE_TLS_DEBUG_MESSAGES # include <stdio.h> /* For TLS debug printing */ #endif +#include "mhd_public_api.h" + #ifdef mhd_USE_TLS_DEBUG_MESSAGES static MHD_FN_PAR_NONNULL_ (1) int @@ -417,7 +417,7 @@ daemon_init_ctx (struct MHD_Daemon *restrict d, { uint64_t ctx_opts; -#ifndef HAVE_LOG_FUNCTIONALITY +#ifndef MHD_SUPPORT_LOG_FUNCTIONALITY (void) d; /* Mute compiler warning */ #endif (void) s; // TODO: support configuration options @@ -1186,3 +1186,49 @@ mhd_tls_open_conn_send (struct mhd_TlsOpenConnData *restrict c_tls, #endif /* ! NDEBUG */ return mhd_SOCKET_ERR_TLS; } + + +/* ** TLS connection information ** */ + +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_OUT_ (2) void +mhd_tls_open_conn_get_tls_sess ( + struct mhd_TlsOpenConnData *restrict c_tls, + union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) +{ + tls_sess_out->v_openssl_session = c_tls->sess; +} + + +MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_OUT_ (2) bool +mhd_tls_open_conn_get_tls_ver (struct mhd_TlsOpenConnData *restrict c_tls, + enum MHD_TlsVersion *restrict tls_ver_out) +{ + int openssl_tls_ver; + + mhd_assert (c_tls->dbg.is_tls_handshake_completed); + + openssl_tls_ver = SSL_version (c_tls->sess); + switch (openssl_tls_ver) + { + case TLS1_VERSION: + *tls_ver_out = MHD_TLS_VERSION_1_0; + break; + case TLS1_1_VERSION: + *tls_ver_out = MHD_TLS_VERSION_1_1; + break; + case TLS1_2_VERSION: + *tls_ver_out = MHD_TLS_VERSION_1_2; + break; + case TLS1_3_VERSION: + *tls_ver_out = MHD_TLS_VERSION_1_3; + break; + case SSL3_VERSION: + default: + *tls_ver_out = MHD_TLS_VERSION_UNKNOWN; + break; + } + + return true; +} diff --git a/src/mhd2/tls_open_funcs.h b/src/mhd2/tls_open_funcs.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_USE_OPENSSL +#ifndef MHD_SUPPORT_OPENSSL #error This header can be used only if OpenSSL is enabled #endif @@ -51,6 +51,10 @@ struct mhd_TlsOpenDaemonData; /* Forward declaration */ */ struct mhd_TlsOpenConnData; /* Forward declaration */ +union MHD_ConnInfoDynamicTlsSess; /* Forward declaration */ + +enum MHD_TlsVersion; /* Forward declaration */ + /* ** Global initialisation / de-initialisation ** */ @@ -232,4 +236,29 @@ mhd_tls_open_conn_send (struct mhd_TlsOpenConnData *restrict c_tls, size_t *restrict sent) MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3,2) MHD_FN_PAR_OUT_ (4); + +/* ** TLS connection information ** */ + +/** + * Get the TLS session used in connection + * @param c_tls the connection TLS handle + * @param tls_ver_out the pointer to variable to be set to the TLS version + */ +MHD_INTERNAL void +mhd_tls_open_conn_get_tls_sess ( + struct mhd_TlsOpenConnData *restrict c_tls, + union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2); + +/** + * Get the TLS version used in connection + * @param c_tls the connection TLS handle + * @param tls_ver_out the pointer to variable to be set to the TLS version + * @return always 'true' + */ +MHD_INTERNAL bool +mhd_tls_open_conn_get_tls_ver (struct mhd_TlsOpenConnData *restrict c_tls, + enum MHD_TlsVersion *restrict tls_ver_out) +MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_ (2); + #endif /* ! MHD_TLS_OPEN_FUNCS_H */ diff --git a/src/mhd2/tls_open_tls_lib.h b/src/mhd2/tls_open_tls_lib.h @@ -29,7 +29,7 @@ #include "mhd_sys_options.h" -#ifndef MHD_USE_OPENSSL +#ifndef MHD_SUPPORT_OPENSSL #error This header can be used only if GnuTLS is enabled #endif diff --git a/src/mhd2/upgraded_net.c b/src/mhd2/upgraded_net.c @@ -32,7 +32,7 @@ #include "sys_base_types.h" #include "sys_poll.h" -#ifndef MHD_USE_POLL +#ifndef MHD_SUPPORT_POLL # include "sys_select.h" #endif #include "mhd_limits.h" @@ -50,8 +50,8 @@ #include "mhd_public_api.h" -#if ! defined (MHD_USE_POLL) && \ - (defined(MHD_SOCKETS_KIND_POSIX) || ! defined(MHD_USE_SELECT)) +#if ! defined (MHD_SUPPORT_POLL) && \ + (defined(MHD_SOCKETS_KIND_POSIX) || ! defined(MHD_SUPPORT_SELECT)) # if defined(_WIN32) || defined(HAVE_NANOSLEEP) || defined(HAVE_USLEEP) # define mhd_HAVE_MHD_SLEEP 1 @@ -95,7 +95,8 @@ mhd_sleep (uint_fast32_t millisec) #endif /* _WIN32 || HAVE_NANOSLEEP || HAVE_USLEEP */ -#endif /* ! MHD_USE_POLL) && (MHD_SOCKETS_KIND_POSIX || ! MHD_USE_SELECT) */ +#endif /* ! MHD_SUPPORT_POLL && + (MHD_SOCKETS_KIND_POSIX || ! MHD_SUPPORT_SELECT) */ MHD_EXTERN_ @@ -109,9 +110,9 @@ MHD_upgraded_recv (struct MHD_UpgradedHandle *MHD_RESTRICT urh, uint_fast64_t max_wait_millisec) { struct MHD_Connection *restrict c = urh->c; -#if defined(MHD_USE_POLL) || defined(MHD_USE_SELECT) +#if defined(MHD_SUPPORT_POLL) || defined(MHD_SUPPORT_SELECT) const MHD_Socket socket_fd = c->sk.fd; -#endif /* MHD_USE_POLL || MHD_USE_SELECT */ +#endif /* MHD_SUPPORT_POLL || MHD_SUPPORT_SELECT */ char *restrict buf_char = (char *) recv_buf; size_t last_block_size; enum mhd_SocketError res; @@ -178,7 +179,7 @@ MHD_upgraded_recv (struct MHD_UpgradedHandle *MHD_RESTRICT urh, { while (0 != max_wait_millisec) { -#if defined(MHD_USE_POLL) +#if defined(MHD_SUPPORT_POLL) if (1) { struct pollfd fds[1]; @@ -216,8 +217,8 @@ MHD_upgraded_recv (struct MHD_UpgradedHandle *MHD_RESTRICT urh, } max_wait_millisec = 0; /* Re-try only one time */ } -#else /* ! MHD_USE_POLL */ -# if defined(MHD_USE_SELECT) +#else /* ! MHD_SUPPORT_POLL */ +# if defined(MHD_SUPPORT_SELECT) bool use_select; # ifdef MHD_SOCKETS_KIND_POSIX use_select = (sk.fd < FD_SETSIZE); @@ -270,7 +271,7 @@ MHD_upgraded_recv (struct MHD_UpgradedHandle *MHD_RESTRICT urh, max_wait_millisec = 0; /* Re-try only one time */ } else /* combined with the next 'if()' */ -# endif /* MHD_USE_SELECT */ +# endif /* MHD_SUPPORT_SELECT */ if (1) { # ifndef mhd_HAVE_MHD_SLEEP @@ -286,7 +287,7 @@ MHD_upgraded_recv (struct MHD_UpgradedHandle *MHD_RESTRICT urh, max_wait_millisec -= wait_millisec; # endif /* mhd_HAVE_MHD_SLEEP */ } -#endif /* ! MHD_USE_POLL */ +#endif /* ! MHD_SUPPORT_POLL */ last_block_size = 0; res = mhd_recv (c, recv_buf_size - *received_size, @@ -326,9 +327,9 @@ MHD_upgraded_send (struct MHD_UpgradedHandle *MHD_RESTRICT urh, enum MHD_Bool more_data_to_come) { struct MHD_Connection *restrict c = urh->c; -#if defined(MHD_USE_POLL) || defined(MHD_USE_SELECT) +#if defined(MHD_SUPPORT_POLL) || defined(MHD_SUPPORT_SELECT) const MHD_Socket socket_fd = c->sk.fd; -#endif /* MHD_USE_POLL || MHD_USE_SELECT */ +#endif /* MHD_SUPPORT_POLL || MHD_SUPPORT_SELECT */ const char *restrict buf_char = (const char *) send_buf; const bool push_data = (MHD_NO == more_data_to_come); bool finish_time_set; @@ -350,9 +351,9 @@ MHD_upgraded_send (struct MHD_UpgradedHandle *MHD_RESTRICT urh, enum mhd_SocketError res; size_t last_block_size; uint_fast64_t wait_left; -#if ! defined(MHD_USE_POLL) && defined(MHD_USE_SELECT) +#if ! defined(MHD_SUPPORT_POLL) && defined(MHD_SUPPORT_SELECT) bool use_select; -#endif /* ! MHD_USE_POLL */ +#endif /* ! MHD_SUPPORT_POLL */ last_block_size = 0; res = mhd_send_data (c, @@ -407,7 +408,7 @@ MHD_upgraded_send (struct MHD_UpgradedHandle *MHD_RESTRICT urh, } } -#if defined(MHD_USE_POLL) +#if defined(MHD_SUPPORT_POLL) if (1) { struct pollfd fds[1]; @@ -449,8 +450,8 @@ MHD_upgraded_send (struct MHD_UpgradedHandle *MHD_RESTRICT urh, ! mhd_SCKT_ERR_IS_LOW_RESOURCES (wait_err)) return MHD_SC_UPGRADED_NET_HARD_ERROR; } -#else /* ! MHD_USE_POLL */ -# if defined(MHD_USE_SELECT) +#else /* ! MHD_SUPPORT_POLL */ +# if defined(MHD_SUPPORT_SELECT) # ifdef MHD_SOCKETS_KIND_POSIX use_select = (sk.fd < FD_SETSIZE); # else /* MHD_SOCKETS_KIND_WINSOCK */ @@ -516,7 +517,7 @@ MHD_upgraded_send (struct MHD_UpgradedHandle *MHD_RESTRICT urh, return MHD_SC_UPGRADED_NET_HARD_ERROR; } else /* combined with the next 'if()' */ -# endif /* MHD_USE_SELECT */ +# endif /* MHD_SUPPORT_SELECT */ if (1) { # ifndef mhd_HAVE_MHD_SLEEP @@ -530,7 +531,7 @@ MHD_upgraded_send (struct MHD_UpgradedHandle *MHD_RESTRICT urh, mhd_sleep (wait_millisec); # endif /* mhd_HAVE_MHD_SLEEP */ } -#endif /* ! MHD_USE_POLL */ +#endif /* ! MHD_SUPPORT_POLL */ } return MHD_SC_OK; diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am @@ -2,7 +2,7 @@ SUBDIRS = basic -if MHD_UPGRADE_SUPPORT +if MHD_SUPPORT_UPGRADE SUBDIRS += upgrade endif diff --git a/src/tests/basic/Makefile.am b/src/tests/basic/Makefile.am @@ -34,7 +34,7 @@ check_PROGRAMS = \ test_create_start_destroy_ipbest \ $(EMPTY_ITEM) -if MHD_USE_SELECT +if MHD_SUPPORT_SELECT check_PROGRAMS += \ test_create_destroy_select \ test_create_start_destroy_select \ @@ -43,7 +43,7 @@ check_PROGRAMS += \ $(EMPTY_ITEM) endif -if MHD_USE_POLL +if MHD_SUPPORT_POLL check_PROGRAMS += \ test_create_destroy_poll \ test_create_start_destroy_poll \ @@ -52,7 +52,7 @@ check_PROGRAMS += \ $(EMPTY_ITEM) endif -if MHD_USE_EPOLL +if MHD_SUPPORT_EPOLL check_PROGRAMS += \ test_create_destroy_epoll \ test_create_start_destroy_epoll \ @@ -61,7 +61,7 @@ check_PROGRAMS += \ $(EMPTY_ITEM) endif -if MHD_USE_THREADS +if MHD_SUPPORT_THREADS check_PROGRAMS += \ test_create_destroy_int_thread \ test_create_start_destroy_int_thread \ @@ -74,21 +74,21 @@ check_PROGRAMS += \ test_create_start_destroy_thread_pool_ipv4 \ $(EMPTY_ITEM) -if MHD_USE_SELECT +if MHD_SUPPORT_SELECT check_PROGRAMS += \ test_create_start_destroy_select_int_thread_ipv4 \ test_create_start_destroy_select_thread_per_conn_ipv4 \ $(EMPTY_ITEM) endif -if MHD_USE_POLL +if MHD_SUPPORT_POLL check_PROGRAMS += \ test_create_start_destroy_poll_int_thread_ipv4 \ test_create_start_destroy_poll_thread_per_conn_ipv4 \ $(EMPTY_ITEM) endif -if MHD_USE_EPOLL +if MHD_SUPPORT_EPOLL check_PROGRAMS += \ test_create_start_destroy_epoll_int_thread_ipv4 \ test_create_start_destroy_epoll_thread_pool_ipv4 \ diff --git a/src/tests/client_server/Makefile.am b/src/tests/client_server/Makefile.am @@ -29,7 +29,7 @@ check_PROGRAMS = \ test_authentication \ test_postprocessor -if MHD_ENABLE_HTTPS +if MHD_SUPPORT_HTTPS check_PROGRAMS += \ test_tls \ test_cert_tls diff --git a/src/tests/client_server/test_cert_tls.c b/src/tests/client_server/test_cert_tls.c @@ -42,7 +42,7 @@ main (int argc, char *argv[]) NULL), MHD_D_OPTION_TERMINATE () }; -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS struct MHD_DaemonOptionAndValue rca_options_gnu[] = { MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_AUTO), MHD_D_OPTION_WM_WORKER_THREADS (1), @@ -53,7 +53,7 @@ main (int argc, char *argv[]) MHD_D_OPTION_TERMINATE () }; #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL struct MHD_DaemonOptionAndValue rca_options_open[] = { MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_AUTO), MHD_D_OPTION_WM_WORKER_THREADS (1), @@ -91,7 +91,7 @@ main (int argc, char *argv[]) }, -#ifdef MHD_USE_GNUTLS +#ifdef MHD_SUPPORT_GNUTLS { .label = "certs_chain", .server_setup = &MHDT_server_setup_minimal, @@ -111,7 +111,7 @@ main (int argc, char *argv[]) }, #endif -#ifdef MHD_USE_OPENSSL +#ifdef MHD_SUPPORT_OPENSSL { .label = "certs_chain", .server_setup = &MHDT_server_setup_minimal, diff --git a/src/tests/client_server/test_client_server.c b/src/tests/client_server/test_client_server.c @@ -77,7 +77,7 @@ main (int argc, char *argv[]) MHDT_ServerRunner server_runner; void *server_runner_cls; } configs[] = { -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT { .label = "single threaded select", .server_setup = &MHDT_server_setup_minimal, @@ -91,7 +91,7 @@ main (int argc, char *argv[]) .server_runner = &MHDT_server_run_minimal, }, #endif -#ifdef MHD_USE_POLL +#ifdef MHD_SUPPORT_POLL { .label = "single threaded poll", .server_setup = &MHDT_server_setup_minimal, @@ -105,7 +105,7 @@ main (int argc, char *argv[]) .server_runner = &MHDT_server_run_minimal, }, #endif -#if MHD_USE_EPOLL +#if MHD_SUPPORT_EPOLL { .label = "single threaded epoll", .server_setup = &MHDT_server_setup_minimal, diff --git a/src/tests/client_server/test_tls.c b/src/tests/client_server/test_tls.c @@ -77,7 +77,7 @@ main (int argc, char *argv[]) MHDT_ServerRunner server_runner; void *server_runner_cls; } configs[] = { -#ifdef MHD_USE_SELECT +#ifdef MHD_SUPPORT_SELECT { .label = "single threaded select", .server_setup = &MHDT_server_setup_tls, @@ -90,7 +90,7 @@ main (int argc, char *argv[]) .server_setup_cls = thread2select, .server_runner = &MHDT_server_run_minimal, }, -#if MHD_USE_GNUTLS +#if MHD_SUPPORT_GNUTLS { .label = "multi-threaded select, forcing GnuTLS", .server_setup = &MHDT_server_setup_gnutls, @@ -99,7 +99,7 @@ main (int argc, char *argv[]) }, #endif #endif -#ifdef MHD_USE_POLL +#ifdef MHD_SUPPORT_POLL { .label = "single threaded poll", .server_setup = &MHDT_server_setup_tls, @@ -112,7 +112,7 @@ main (int argc, char *argv[]) .server_setup_cls = thread2poll, .server_runner = &MHDT_server_run_minimal, }, -#if MHD_USE_GNUTLS +#if MHD_SUPPORT_GNUTLS { .label = "multi-threaded poll, forcing GnuTLS", .server_setup = &MHDT_server_setup_gnutls, @@ -121,7 +121,7 @@ main (int argc, char *argv[]) }, #endif #endif -#if MHD_USE_EPOLL +#if MHD_SUPPORT_EPOLL { .label = "single threaded epoll", .server_setup = &MHDT_server_setup_tls, @@ -134,7 +134,7 @@ main (int argc, char *argv[]) .server_setup_cls = thread2epoll, .server_runner = &MHDT_server_run_minimal, }, -#if MHD_USE_GNUTLS +#if MHD_SUPPORT_GNUTLS { .label = "multi-threaded epoll, forcing GnuTLS", .server_setup = &MHDT_server_setup_gnutls, @@ -149,7 +149,7 @@ main (int argc, char *argv[]) .server_setup_cls = thread1auto, .server_runner = &MHDT_server_run_minimal, }, -#if MHD_USE_GNUTLS +#if MHD_SUPPORT_GNUTLS { .label = "auto-selected mode, single threaded, forcing GnuTLS", .server_setup = &MHDT_server_setup_gnutls, @@ -157,7 +157,7 @@ main (int argc, char *argv[]) .server_runner = &MHDT_server_run_minimal, }, #endif -#if MHD_USE_OPENSSL +#if MHD_SUPPORT_OPENSSL { .label = "auto-selected mode, single threaded, forcing OpenSSL", .server_setup = &MHDT_server_setup_openssl,