commit 72e0245ba97efbadf7d7c3689df4b405e442df0e
parent d08a352c08e3b4e9bb2743587dd3a2631e578f87
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Mon, 22 Dec 2025 16:18:13 +0100
Renamed daemon timeout option and info type: use milliseconds instead of seconds,
moved timeout-related functions to special file
Diffstat:
23 files changed, 406 insertions(+), 239 deletions(-)
diff --git a/src/examples2/demo.c b/src/examples2/demo.c
@@ -1368,7 +1368,7 @@ main (int argc,
d,
MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_AUTO),
MHD_D_OPTION_WM_WORKER_THREADS (NUMBER_OF_THREADS),
- MHD_D_OPTION_DEFAULT_TIMEOUT (120 /* seconds */),
+ MHD_D_OPTION_DEFAULT_TIMEOUT_MILSEC (120000u),
MHD_D_OPTION_CONN_MEMORY_LIMIT (256 * 1024),
MHD_D_OPTION_BIND_PORT (MHD_AF_AUTO,
(uint_least16_t) port)))
diff --git a/src/examples2/json_echo.c b/src/examples2/json_echo.c
@@ -319,7 +319,7 @@ main (int argc,
&sock_reg_update_cb,
NULL),
MHD_D_OPTION_FD_NUMBER_LIMIT (FD_SETSIZE),
- MHD_D_OPTION_DEFAULT_TIMEOUT (120 /* seconds */),
+ MHD_D_OPTION_DEFAULT_TIMEOUT_MILSEC (120000u),
MHD_D_OPTION_CONN_MEMORY_LIMIT (256 * 1024),
MHD_D_OPTION_BIND_PORT (MHD_AF_AUTO,
(uint_least16_t) port)))
diff --git a/src/include/d_options.rec b/src/include/d_options.rec
@@ -325,15 +325,26 @@ CustomSetter: /* custom setter */
# Connection handling
-Name: DEFAULT_TIMEOUT
+Name: DEFAULT_TIMEOUT_MILSEC
Value: 160
-Comment: Specify inactivity timeout for connection.
-+ When no activity for specified time on connection, it is closed
-+ automatically.
-+ Use zero for no timeout, which is also the (unsafe!) default.
-+ Very large values (years) can be silently truncated to smaller values.
-Argument1: unsigned int timeout
-Description1: the in seconds, zero for no timeout
+Comment: Specify the inactivity timeout for a connection in milliseconds.
++ If a connection remains idle (no activity) for this many
++ milliseconds, it is closed automatically.
++ Use zero for no timeout; this is also the (unsafe!)
++ default.
++ Values larger than 1209600000 (two weeks) are silently
++ clamped to 1209600000.
++ Precise closing time is not guaranteed and depends on
++ system clock granularity and amount of time spent on
++ processing other connections. Typical precision is
++ within +/- 30 milliseconds, while the worst case could
++ be greater than +/- 1 second.
++ Values below 1500 milliseconds are risky as they
++ may cause valid connections to be aborted and may
++ increase load the server load due to clients' repetitive
++ automatic retries.
+Argument1: uint_fast32_t timeout
+Description1: the timeout in milliseconds, zero for no timeout
Name: GLOBAL_CONNECTION_LIMIT
Value: 161
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h
@@ -4425,17 +4425,28 @@ MHD_D_OPTION_TLS_OPENSSL_DEF_FILE (
);
/**
- * Specify inactivity timeout for connection.
- * When no activity for specified time on connection, it is closed
- * automatically.
- * Use zero for no timeout, which is also the (unsafe!) default.
- * Very large values (years) can be silently truncated to smaller values.
- * @param timeout the in seconds, zero for no timeout
+ * Specify the inactivity timeout for a connection in milliseconds.
+ * If a connection remains idle (no activity) for this many
+ * milliseconds, it is closed automatically.
+ * Use zero for no timeout; this is also the (unsafe!)
+ * default.
+ * Values larger than 1209600000 (two weeks) are silently
+ * clamped to 1209600000.
+ * Precise closing time is not guaranteed and depends on
+ * system clock granularity and amount of time spent on
+ * processing other connections. Typical precision is
+ * within +/- 30 milliseconds, while the worst case could
+ * be greater than +/- 1 second.
+ * Values below 1500 milliseconds are risky as they
+ * may cause valid connections to be aborted and may
+ * increase load the server load due to clients' repetitive
+ * automatic retries.
+ * @param timeout the timeout in milliseconds, zero for no timeout
* @return structure with the requested setting
*/
struct MHD_DaemonOptionAndValue
-MHD_D_OPTION_DEFAULT_TIMEOUT (
- unsigned int timeout
+MHD_D_OPTION_DEFAULT_TIMEOUT_MILSEC (
+ uint_fast32_t timeout
);
/**
@@ -9519,10 +9530,10 @@ enum MHD_DaemonInfoFixedType
MHD_DAEMON_INFO_FIXED_TLS_BACKEND = 120
,
/**
- * Get the default inactivity timeout for connections.
- * The result is placed in @a v_default_timeout_uint member.
+ * Get the default inactivity timeout for connections in milliseconds.
+ * The result is placed in @a v_default_timeout_milsec_uint32 member.
*/
- MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT = 160
+ MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT_MILSEC = 160
,
/**
* Get the limit of number of simutaneous network connections served by
@@ -9610,7 +9621,7 @@ union MHD_DaemonInfoFixedData
/**
* The data for the #MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT query
*/
- unsigned int v_default_timeout_uint;
+ uint_fast32_t v_default_timeout_milsec_uint32;
/**
* The data for the #MHD_DAEMON_INFO_FIXED_GLOBAL_CONNECTION_LIMIT query
diff --git a/src/include/microhttpd2_generated_daemon_options.h b/src/include/microhttpd2_generated_daemon_options.h
@@ -168,13 +168,24 @@ Works only when #MHD_D_OPTION_BIND_PORT() or #MHD_D_OPTION_BIND_SA() are used.
,
/**
- * Specify inactivity timeout for connection.
- * When no activity for specified time on connection, it is closed
- * automatically.
- * Use zero for no timeout, which is also the (unsafe!) default.
- * Very large values (years) can be silently truncated to smaller values.
- */
- MHD_D_O_DEFAULT_TIMEOUT = 160
+ * Specify the inactivity timeout for a connection in milliseconds.
+ * If a connection remains idle (no activity) for this many
+ * milliseconds, it is closed automatically.
+ * Use zero for no timeout; this is also the (unsafe!)
+ * default.
+ * Values larger than 1209600000 (two weeks) are silently
+ * clamped to 1209600000.
+ * Precise closing time is not guaranteed and depends on
+ * system clock granularity and amount of time spent on
+ * processing other connections. Typical precision is
+ * within +/- 30 milliseconds, while the worst case could
+ * be greater than +/- 1 second.
+ * Values below 1500 milliseconds are risky as they
+ * may cause valid connections to be aborted and may
+ * increase load the server load due to clients' repetitive
+ * automatic retries.
+ */
+ MHD_D_O_DEFAULT_TIMEOUT_MILSEC = 160
,
/**
@@ -797,10 +808,10 @@ union MHD_DaemonOptionValue
struct MHD_DaemonOptionValueTlsOsslDefFile tls_openssl_def_file;
/**
- * Value for #MHD_D_O_DEFAULT_TIMEOUT.
- * the in seconds, zero for no timeout
+ * Value for #MHD_D_O_DEFAULT_TIMEOUT_MILSEC.
+ * the timeout in milliseconds, zero for no timeout
*/
- unsigned int default_timeout;
+ uint_fast32_t default_timeout_milsec;
/**
* Value for #MHD_D_O_GLOBAL_CONNECTION_LIMIT.
@@ -1279,20 +1290,31 @@ Works only when #MHD_D_OPTION_BIND_PORT() or #MHD_D_OPTION_BIND_SA() are used.
} \
MHD_RESTORE_WARN_COMPOUND_LITERALS_ MHD_RESTORE_WARN_AGGR_DYN_INIT_
/**
- * Specify inactivity timeout for connection.
- * When no activity for specified time on connection, it is closed
- * automatically.
- * Use zero for no timeout, which is also the (unsafe!) default.
- * Very large values (years) can be silently truncated to smaller values.
- * @param timeout the in seconds, zero for no timeout
+ * Specify the inactivity timeout for a connection in milliseconds.
+ * If a connection remains idle (no activity) for this many
+ * milliseconds, it is closed automatically.
+ * Use zero for no timeout; this is also the (unsafe!)
+ * default.
+ * Values larger than 1209600000 (two weeks) are silently
+ * clamped to 1209600000.
+ * Precise closing time is not guaranteed and depends on
+ * system clock granularity and amount of time spent on
+ * processing other connections. Typical precision is
+ * within +/- 30 milliseconds, while the worst case could
+ * be greater than +/- 1 second.
+ * Values below 1500 milliseconds are risky as they
+ * may cause valid connections to be aborted and may
+ * increase load the server load due to clients' repetitive
+ * automatic retries.
+ * @param timeout the timeout in milliseconds, zero for no timeout
* @return structure with the requested setting
*/
-# define MHD_D_OPTION_DEFAULT_TIMEOUT(timeout) \
+# define MHD_D_OPTION_DEFAULT_TIMEOUT_MILSEC(timeout) \
MHD_NOWARN_COMPOUND_LITERALS_ MHD_NOWARN_AGGR_DYN_INIT_ \
(const struct MHD_DaemonOptionAndValue) \
{ \
- .opt = MHD_D_O_DEFAULT_TIMEOUT, \
- .val.default_timeout = (timeout) \
+ .opt = MHD_D_O_DEFAULT_TIMEOUT_MILSEC, \
+ .val.default_timeout_milsec = (timeout) \
} \
MHD_RESTORE_WARN_COMPOUND_LITERALS_ MHD_RESTORE_WARN_AGGR_DYN_INIT_
/**
@@ -2131,23 +2153,34 @@ MHD_D_OPTION_TLS_OPENSSL_DEF_FILE (
/**
- * Specify inactivity timeout for connection.
- * When no activity for specified time on connection, it is closed
- * automatically.
- * Use zero for no timeout, which is also the (unsafe!) default.
- * Very large values (years) can be silently truncated to smaller values.
- * @param timeout the in seconds, zero for no timeout
+ * Specify the inactivity timeout for a connection in milliseconds.
+ * If a connection remains idle (no activity) for this many
+ * milliseconds, it is closed automatically.
+ * Use zero for no timeout; this is also the (unsafe!)
+ * default.
+ * Values larger than 1209600000 (two weeks) are silently
+ * clamped to 1209600000.
+ * Precise closing time is not guaranteed and depends on
+ * system clock granularity and amount of time spent on
+ * processing other connections. Typical precision is
+ * within +/- 30 milliseconds, while the worst case could
+ * be greater than +/- 1 second.
+ * Values below 1500 milliseconds are risky as they
+ * may cause valid connections to be aborted and may
+ * increase load the server load due to clients' repetitive
+ * automatic retries.
+ * @param timeout the timeout in milliseconds, zero for no timeout
* @return structure with the requested setting
*/
static MHD_INLINE struct MHD_DaemonOptionAndValue
-MHD_D_OPTION_DEFAULT_TIMEOUT (
- unsigned int timeout
+MHD_D_OPTION_DEFAULT_TIMEOUT_MILSEC (
+ uint_fast32_t timeout
)
{
struct MHD_DaemonOptionAndValue opt_val;
- opt_val.opt = MHD_D_O_DEFAULT_TIMEOUT;
- opt_val.val.default_timeout = timeout;
+ opt_val.opt = MHD_D_O_DEFAULT_TIMEOUT_MILSEC;
+ opt_val.val.default_timeout_milsec = timeout;
return opt_val;
}
diff --git a/src/include/microhttpd2_main.h.in b/src/include/microhttpd2_main.h.in
@@ -4655,10 +4655,10 @@ enum MHD_DaemonInfoFixedType
MHD_DAEMON_INFO_FIXED_TLS_BACKEND = 120
,
/**
- * Get the default inactivity timeout for connections.
- * The result is placed in @a v_default_timeout_uint member.
+ * Get the default inactivity timeout for connections in milliseconds.
+ * The result is placed in @a v_default_timeout_milsec_uint32 member.
*/
- MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT = 160
+ MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT_MILSEC = 160
,
/**
* Get the limit of number of simutaneous network connections served by
@@ -4746,7 +4746,7 @@ union MHD_DaemonInfoFixedData
/**
* The data for the #MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT query
*/
- unsigned int v_default_timeout_uint;
+ uint_fast32_t v_default_timeout_milsec_uint32;
/**
* The data for the #MHD_DAEMON_INFO_FIXED_GLOBAL_CONNECTION_LIMIT query
diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am
@@ -85,6 +85,7 @@ libmicrohttpd2_la_SOURCES = \
daemon_add_conn.c daemon_add_conn.h \
daemon_funcs.c daemon_funcs.h \
daemon_event_update.c extr_events_funcs.c extr_events_funcs.h \
+ conn_timeout.c conn_timeout.h \
conn_data_process.c conn_data_process.h \
conn_data_recv.c conn_data_recv.h \
conn_data_send.c conn_data_send.h \
diff --git a/src/mhd2/conn_data_recv.c b/src/mhd2/conn_data_recv.c
@@ -55,6 +55,7 @@
#include "mhd_connection.h"
+#include "conn_timeout.h"
#include "stream_funcs.h"
#include "mhd_socket_error_funcs.h"
#include "sckt_recv.h"
diff --git a/src/mhd2/conn_data_send.c b/src/mhd2/conn_data_send.c
@@ -63,9 +63,11 @@
#include "mhd_socket_error_funcs.h"
-#include "mhd_send.h"
+#include "conn_timeout.h"
#include "stream_funcs.h"
+#include "mhd_send.h"
+
/**
* Check if we are done sending the write-buffer.
diff --git a/src/mhd2/conn_timeout.c b/src/mhd2/conn_timeout.c
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
+/*
+ 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.
+
+ Alternatively, you can redistribute GNU libmicrohttpd and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version, together
+ with the eCos exception, as follows:
+
+ As a special exception, if other files instantiate templates or
+ use macros or inline functions from this file, or you compile this
+ file and link it with other works to produce a work based on this
+ file, this file does not by itself cause the resulting work to be
+ covered by the GNU General Public License. However the source code
+ for this file must still be made available in accordance with
+ section (3) of the GNU General Public License v2.
+
+ This exception does not invalidate any other reasons why a work
+ based on this file might be covered by the GNU General Public
+ License.
+
+ You should have received copies of the GNU Lesser General Public
+ License and the GNU General Public License along with this library;
+ if not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/mhd2/conn_timeout.c
+ * @brief The definitions of connection timeout handling functions
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_sys_options.h"
+
+#include "sys_bool_type.h"
+
+#include "mhd_mono_clock.h"
+
+#include "mhd_daemon.h"
+#include "mhd_connection.h"
+
+#include "daemon_logger.h"
+
+#include "conn_timeout.h"
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
+mhd_stream_is_timeout_expired (struct MHD_Connection *restrict c)
+{
+ const uint_fast64_t timeout = c->connection_timeout_ms;
+ uint_fast64_t now;
+ uint_fast64_t since_actv;
+
+ mhd_assert (! c->suspended);
+
+ if (0 == timeout)
+ return false;
+
+ now = mhd_monotonic_msec_counter (); // TODO: Get and use timer value one time only per round
+ since_actv = now - c->last_activity;
+ /* Keep the next lines in sync with #connection_get_wait() to avoid
+ * undesired side-effects like busy-waiting. */
+ if (timeout < since_actv)
+ {
+ const uint_fast64_t jump_back = c->last_activity - now;
+ if (jump_back < since_actv)
+ {
+ /* Very unlikely that it is more than quarter-million years pause.
+ * More likely that system clock jumps back. */
+ if (4000 >= jump_back)
+ {
+ c->last_activity = now; /* Avoid repetitive messages.
+ Warn: the order of connections sorted
+ by timeout is not updated. */
+ mhd_LOG_PRINT (c->daemon, MHD_SC_SYS_CLOCK_JUMP_BACK_CORRECTED, \
+ mhd_LOG_FMT ("Detected system clock %u " \
+ "milliseconds jump back."),
+ (unsigned int) jump_back);
+ return false;
+ }
+ mhd_LOG_PRINT (c->daemon, MHD_SC_SYS_CLOCK_JUMP_BACK_LARGE, \
+ mhd_LOG_FMT ("Detected too large system clock %" \
+ PRIuFAST64 " milliseconds jump back"),
+ jump_back);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+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_SUPPORT_THREADS)
+ mhd_assert (! mhd_D_HAS_WORKERS (d));
+#endif /* MHD_SUPPORT_THREADS */
+
+ mhd_assert (! c->suspended);
+
+ if (0 == c->connection_timeout_ms)
+ return; /* Skip update of activity for connections
+ without timeout timer. */
+
+ c->last_activity = mhd_monotonic_msec_counter (); // TODO: Get and use time value one time per round
+ if (mhd_D_HAS_THR_PER_CONN (d))
+ return; /* each connection has personal timeout */
+
+ if (c->connection_timeout_ms != d->conns.cfg.timeout_milsec)
+ return; /* custom timeout, no need to move it in "normal" DLL */
+
+ /* move connection to head of timeout list (by remove + add operation) */
+ mhd_DLINKEDL_DEL_D (&(d->conns.def_timeout), c, by_timeout);
+ mhd_DLINKEDL_INS_FIRST_D (&(d->conns.def_timeout), c, by_timeout);
+}
+
+
+MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
+mhd_stream_resumed_activity_mark (struct MHD_Connection *restrict c)
+{
+ struct MHD_Daemon *const restrict d = c->daemon;
+#if defined(MHD_SUPPORT_THREADS)
+ mhd_assert (! mhd_D_HAS_WORKERS (d));
+#endif /* MHD_SUPPORT_THREADS */
+
+ mhd_assert (! c->suspended);
+ mhd_assert (c->resuming);
+
+ /* Update of activity for connections without timeout timer unless
+ * no timeout is set */
+ if (0 != c->connection_timeout_ms)
+ c->last_activity = mhd_monotonic_msec_counter (); // TODO: Get and use time value one time per round
+
+ if (mhd_D_HAS_THR_PER_CONN (d))
+ return; /* each connection has personal timeout */
+
+ if (c->connection_timeout_ms == d->conns.cfg.timeout_milsec)
+ mhd_DLINKEDL_INS_FIRST_D (&(d->conns.def_timeout), c, by_timeout);
+ else
+ mhd_DLINKEDL_INS_FIRST_D (&(d->conns.cust_timeout), c, by_timeout);
+}
+
+
+MHD_INTERNAL
+MHD_FN_PAR_NONNULL_ALL_ void
+mhd_conn_remove_from_timeout_lists (struct MHD_Connection *restrict c)
+{
+ if (mhd_D_HAS_THR_PER_CONN (c->daemon))
+ return;
+
+ if (c->connection_timeout_ms == c->daemon->conns.cfg.timeout_milsec)
+ mhd_DLINKEDL_DEL_D (&(c->daemon->conns.def_timeout), \
+ c, by_timeout);
+ else
+ mhd_DLINKEDL_DEL_D (&(c->daemon->conns.cust_timeout), \
+ c, by_timeout);
+}
diff --git a/src/mhd2/conn_timeout.h b/src/mhd2/conn_timeout.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
+/*
+ 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.
+
+ Alternatively, you can redistribute GNU libmicrohttpd and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version, together
+ with the eCos exception, as follows:
+
+ As a special exception, if other files instantiate templates or
+ use macros or inline functions from this file, or you compile this
+ file and link it with other works to produce a work based on this
+ file, this file does not by itself cause the resulting work to be
+ covered by the GNU General Public License. However the source code
+ for this file must still be made available in accordance with
+ section (3) of the GNU General Public License v2.
+
+ This exception does not invalidate any other reasons why a work
+ based on this file might be covered by the GNU General Public
+ License.
+
+ You should have received copies of the GNU Lesser General Public
+ License and the GNU General Public License along with this library;
+ if not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/mhd2/conn_timeout.h
+ * @brief The declarations of connection timeout handling functions
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_CONN_TIMEOUT_H
+#define MHD_CONN_TIMEOUT_H 1
+
+#include "mhd_sys_options.h"
+
+#include "sys_bool_type.h"
+
+struct MHD_Connection; /* Forward declaration */
+
+/**
+ * Check whether connection's timeout is expired.
+ * @param c the connection to update
+ * @return 'true' if connection timeout expired and the connection needs to be
+ * closed,
+ * 'false' otherwise
+ */
+MHD_INTERNAL bool
+mhd_stream_is_timeout_expired (struct MHD_Connection *restrict c)
+MHD_FN_PAR_NONNULL_ALL_;
+
+
+/**
+ * Update last activity mark to the current time.
+ * @param c the connection to update
+ */
+MHD_INTERNAL void
+mhd_stream_update_activity_mark (struct MHD_Connection *restrict c)
+MHD_FN_PAR_NONNULL_ALL_;
+
+
+/**
+ * Update last activity mark on the resumed connection
+ * @param c the connection to update
+ */
+MHD_INTERNAL void
+mhd_stream_resumed_activity_mark (struct MHD_Connection *restrict c)
+MHD_FN_PAR_NONNULL_ALL_;
+
+
+/**
+ * Remove connection from time-out lists
+ * @param c the connection to process
+ */
+MHD_INTERNAL void
+mhd_conn_remove_from_timeout_lists (struct MHD_Connection *restrict c)
+MHD_FN_PAR_NONNULL_ALL_;
+
+#endif /* ! MHD_CONN_TIMEOUT_H */
diff --git a/src/mhd2/daemon_add_conn.c b/src/mhd2/daemon_add_conn.c
@@ -316,7 +316,7 @@ new_connection_prepare_ (struct MHD_Daemon *restrict daemon,
mhd_thread_handle_ID_set_invalid (&c->tid);
#endif /* MHD_SUPPORT_THREADS */
c->daemon = daemon;
- c->connection_timeout_ms = daemon->conns.cfg.timeout_ms;
+ c->connection_timeout_ms = daemon->conns.cfg.timeout_milsec;
c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV;
#ifdef MHD_SUPPORT_HTTPS
diff --git a/src/mhd2/daemon_get_info.c b/src/mhd2/daemon_get_info.c
@@ -191,13 +191,11 @@ MHD_daemon_get_info_fixed_sz (
#endif
}
return MHD_SC_OK;
- case MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT:
- if (sizeof(output_buf->v_default_timeout_uint) > output_buf_size)
+ case MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT_MILSEC:
+ if (sizeof(output_buf->v_default_timeout_milsec_uint32) > output_buf_size)
return MHD_SC_INFO_GET_BUFF_TOO_SMALL;
- output_buf->v_default_timeout_uint =
- (unsigned int) (daemon->conns.cfg.timeout_ms / 1000u);
- mhd_assert (output_buf->v_default_timeout_uint * 1000u == \
- daemon->conns.cfg.timeout_ms);
+ output_buf->v_default_timeout_milsec_uint32 =
+ daemon->conns.cfg.timeout_milsec;
return MHD_SC_OK;
case MHD_DAEMON_INFO_FIXED_GLOBAL_CONNECTION_LIMIT:
if (sizeof(output_buf->v_global_connection_limit_uint) > output_buf_size)
diff --git a/src/mhd2/daemon_options.h b/src/mhd2/daemon_options.h
@@ -150,10 +150,10 @@ struct DaemonOptions
/**
- * Value for #MHD_D_O_DEFAULT_TIMEOUT.
- * the in seconds, zero for no timeout
+ * Value for #MHD_D_O_DEFAULT_TIMEOUT_MILSEC.
+ * the timeout in milliseconds, zero for no timeout
*/
- unsigned int default_timeout;
+ uint_fast32_t default_timeout_milsec;
/**
diff --git a/src/mhd2/daemon_set_options.c b/src/mhd2/daemon_set_options.c
@@ -188,8 +188,8 @@ MHD_daemon_set_options (
len + 1u);
}
continue;
- case MHD_D_O_DEFAULT_TIMEOUT:
- settings->default_timeout = option->val.default_timeout;
+ case MHD_D_O_DEFAULT_TIMEOUT_MILSEC:
+ settings->default_timeout_milsec = option->val.default_timeout_milsec;
continue;
case MHD_D_O_GLOBAL_CONNECTION_LIMIT:
settings->global_connection_limit = option->val.global_connection_limit;
diff --git a/src/mhd2/daemon_start.c b/src/mhd2/daemon_start.c
@@ -47,6 +47,8 @@
#include "mhd_assert.h"
#include "mhd_unreachable.h"
+#include "mhd_constexpr.h"
+
#include "sys_bool_type.h"
#include "sys_base_types.h"
#include "sys_malloc.h"
@@ -152,8 +154,7 @@ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
daemon_set_basic_settings (struct MHD_Daemon *restrict d,
struct DaemonOptions *restrict s)
{
- static const uint_fast64_t max_timeout_ms_value =
- ((uint_fast64_t) ~((uint_fast64_t) 0)) / 8;
+ mhd_constexpr uint_fast64_t max_timeout_ms_value = 1209600000u;
#ifdef MHD_SUPPORT_HTTP2
// TODO: make it configurable
@@ -169,11 +170,9 @@ daemon_set_basic_settings (struct MHD_Daemon *restrict d,
d->req_cfg.suppress_date = (MHD_NO != s->suppress_date_header);
- d->conns.cfg.timeout_ms = ((uint_fast64_t) s->default_timeout) * 1000u;
- if (d->conns.cfg.timeout_ms / 1000u != s->default_timeout)
- d->conns.cfg.timeout_ms = max_timeout_ms_value;
- else if (max_timeout_ms_value < d->conns.cfg.timeout_ms)
- d->conns.cfg.timeout_ms = max_timeout_ms_value;
+ d->conns.cfg.timeout_milsec = s->default_timeout_milsec;
+ if (max_timeout_ms_value < d->conns.cfg.timeout_milsec)
+ d->conns.cfg.timeout_milsec = max_timeout_ms_value;
d->conns.cfg.per_ip_limit = s->per_ip_limit;
diff --git a/src/mhd2/events_process.c b/src/mhd2/events_process.c
@@ -74,6 +74,7 @@
#include "mhd_daemon.h"
#include "mhd_connection.h"
+#include "conn_timeout.h"
#include "conn_mark_ready.h"
#include "daemon_logger.h"
#include "daemon_add_conn.h"
diff --git a/src/mhd2/mhd_daemon.h b/src/mhd2/mhd_daemon.h
@@ -953,7 +953,7 @@ struct mhd_DaemonConnectionsSettings
/**
* Connection's default timeout value (in milliseconds)
*/
- uint_fast64_t timeout_ms;
+ uint_fast32_t timeout_milsec;
/**
* Connection's memory pool size
diff --git a/src/mhd2/stream_funcs.c b/src/mhd2/stream_funcs.c
@@ -73,6 +73,7 @@
#include "mhd_mono_clock.h"
#include "daemon_logger.h"
#include "daemon_funcs.h"
+#include "conn_timeout.h"
#include "conn_mark_ready.h"
#include "stream_process_reply.h"
#include "extr_events_funcs.h"
@@ -637,124 +638,6 @@ mhd_stream_finish_req_serving (struct MHD_Connection *restrict c,
}
-MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
-mhd_stream_is_timeout_expired (struct MHD_Connection *restrict c)
-{
- const uint_fast64_t timeout = c->connection_timeout_ms;
- uint_fast64_t now;
- uint_fast64_t since_actv;
-
- mhd_assert (! c->suspended);
-
- if (0 == timeout)
- return false;
-
- now = mhd_monotonic_msec_counter (); // TODO: Get and use timer value one time only per round
- since_actv = now - c->last_activity;
- /* Keep the next lines in sync with #connection_get_wait() to avoid
- * undesired side-effects like busy-waiting. */
- if (timeout < since_actv)
- {
- const uint_fast64_t jump_back = c->last_activity - now;
- if (jump_back < since_actv)
- {
- /* Very unlikely that it is more than quarter-million years pause.
- * More likely that system clock jumps back. */
- if (4000 >= jump_back)
- {
- c->last_activity = now; /* Avoid repetitive messages.
- Warn: the order of connections sorted
- by timeout is not updated. */
- mhd_LOG_PRINT (c->daemon, MHD_SC_SYS_CLOCK_JUMP_BACK_CORRECTED, \
- mhd_LOG_FMT ("Detected system clock %u " \
- "milliseconds jump back."),
- (unsigned int) jump_back);
- return false;
- }
- mhd_LOG_PRINT (c->daemon, MHD_SC_SYS_CLOCK_JUMP_BACK_LARGE, \
- mhd_LOG_FMT ("Detected too large system clock %" \
- PRIuFAST64 " milliseconds jump back"),
- jump_back);
- }
- return true;
- }
- return false;
-}
-
-
-/**
- * Update last activity mark to the current time..
- * @param c the connection to update
- */
-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_SUPPORT_THREADS)
- mhd_assert (! mhd_D_HAS_WORKERS (d));
-#endif /* MHD_SUPPORT_THREADS */
-
- mhd_assert (! c->suspended);
-
- if (0 == c->connection_timeout_ms)
- return; /* Skip update of activity for connections
- without timeout timer. */
-
- c->last_activity = mhd_monotonic_msec_counter (); // TODO: Get and use time value one time per round
- if (mhd_D_HAS_THR_PER_CONN (d))
- return; /* each connection has personal timeout */
-
- if (c->connection_timeout_ms != d->conns.cfg.timeout_ms)
- return; /* custom timeout, no need to move it in "normal" DLL */
-
- /* move connection to head of timeout list (by remove + add operation) */
- mhd_DLINKEDL_DEL_D (&(d->conns.def_timeout), c, by_timeout);
- mhd_DLINKEDL_INS_FIRST_D (&(d->conns.def_timeout), c, by_timeout);
-}
-
-
-MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
-mhd_stream_resumed_activity_mark (struct MHD_Connection *restrict c)
-{
- struct MHD_Daemon *const restrict d = c->daemon;
-#if defined(MHD_SUPPORT_THREADS)
- mhd_assert (! mhd_D_HAS_WORKERS (d));
-#endif /* MHD_SUPPORT_THREADS */
-
- mhd_assert (! c->suspended);
- mhd_assert (c->resuming);
-
- /* Update of activity for connections without timeout timer unless
- * no timeout is set */
- if (0 != c->connection_timeout_ms)
- c->last_activity = mhd_monotonic_msec_counter (); // TODO: Get and use time value one time per round
-
- if (mhd_D_HAS_THR_PER_CONN (d))
- return; /* each connection has personal timeout */
-
- if (c->connection_timeout_ms == d->conns.cfg.timeout_ms)
- mhd_DLINKEDL_INS_FIRST_D (&(d->conns.def_timeout), c, by_timeout);
- else
- mhd_DLINKEDL_INS_FIRST_D (&(d->conns.cust_timeout), c, by_timeout);
-}
-
-
-MHD_INTERNAL
-MHD_FN_PAR_NONNULL_ALL_ void
-mhd_conn_remove_from_timeout_lists (struct MHD_Connection *restrict c)
-{
- if (mhd_D_HAS_THR_PER_CONN (c->daemon))
- return;
-
- if (c->connection_timeout_ms == c->daemon->conns.cfg.timeout_ms)
- mhd_DLINKEDL_DEL_D (&(c->daemon->conns.def_timeout), \
- c, by_timeout);
- else
- mhd_DLINKEDL_DEL_D (&(c->daemon->conns.cust_timeout), \
- c, by_timeout);
-}
-
-
/* return 'true' is lingering needed, 'false' is lingering is not needed */
static MHD_FN_PAR_NONNULL_ALL_ bool
conn_start_socket_closing (struct MHD_Connection *restrict c,
diff --git a/src/mhd2/stream_funcs.h b/src/mhd2/stream_funcs.h
@@ -153,43 +153,6 @@ mhd_stream_finish_req_serving (struct MHD_Connection *restrict c,
MHD_FN_PAR_NONNULL_ALL_;
/**
- * Update last activity mark to the current time.
- * @param c the connection to update
- */
-MHD_INTERNAL void
-mhd_stream_update_activity_mark (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
-
-
-/**
- * Update last activity mark on the resumed connection
- * @param c the connection to update
- */
-MHD_INTERNAL void
-mhd_stream_resumed_activity_mark (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
-
-
-/**
- * Remove connection from time-out lists
- * @param c the connection to process
- */
-MHD_INTERNAL void
-mhd_conn_remove_from_timeout_lists (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
-
-/**
- * Check whether connection's timeout is expired.
- * @param c the connection to update
- * @return 'true' if connection timeout expired and connection needs to be
- * closed,
- * 'false' otherwise
- */
-MHD_INTERNAL bool
-mhd_stream_is_timeout_expired (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
-
-/**
* The reason to close the connection
*/
enum mhd_ConnCloseReason
diff --git a/src/mhd2/stream_process_states.c b/src/mhd2/stream_process_states.c
@@ -73,6 +73,7 @@
#include "stream_process_reply.h"
#include "conn_mark_ready.h"
+#include "conn_timeout.h"
#ifdef MHD_SUPPORT_UPGRADE
# include "upgrade_proc.h"
diff --git a/src/tests/client_server/libtest.h b/src/tests/client_server/libtest.h
@@ -135,7 +135,7 @@ struct MHDT_Phase
* How long is the phase allowed to run at most before
* timing out. 0 for no timeout.
*/
- unsigned int timeout_ms;
+ uint_fast32_t timeout_ms;
/**
* How many clients should be run in parallel.
diff --git a/src/tools/perf_replies.c b/src/tools/perf_replies.c
@@ -1904,16 +1904,16 @@ get_mhd_conn_limit (struct MHD_Daemon *d)
}
-static unsigned int
+static unsigned long
get_mhd_def_timeout (struct MHD_Daemon *d)
{
union MHD_DaemonInfoFixedData d_info;
if (MHD_SC_OK !=
MHD_daemon_get_info_fixed (d,
- MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT,
+ MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT_MILSEC,
&d_info))
abort ();
- return d_info.v_default_timeout_uint;
+ return (unsigned long) d_info.v_default_timeout_milsec_uint32;
}
@@ -2020,7 +2020,9 @@ run_mhd (void)
opt_arr[opt_count++] =
MHD_D_OPTION_GLOBAL_CONNECTION_LIMIT (tool_params.connections);
- opt_arr[opt_count++] = MHD_D_OPTION_DEFAULT_TIMEOUT (tool_params.timeout);
+ opt_arr[opt_count++] =
+ MHD_D_OPTION_DEFAULT_TIMEOUT_MILSEC (tool_params.timeout
+ * (uint_fast32_t) 1000u);
if (opt_count > (sizeof(opt_arr) / sizeof(opt_arr[0])))
abort ();
@@ -2071,9 +2073,9 @@ run_mhd (void)
printf (" Connections limit: %u\n", get_mhd_conn_limit (d));
if (1)
{
- unsigned int def_timeout = get_mhd_def_timeout (d);
- printf (" Connection timeout: %u%s\n", def_timeout,
- 0 == def_timeout ? " (no timeout)" : "");
+ unsigned long def_timeout = get_mhd_def_timeout (d);
+ printf (" Connection timeout: %lu %s\n", def_timeout,
+ 0 == def_timeout ? "(no timeout)" : "milliseconds");
}
printf (" 'Date:' header: %s\n",
(! get_mhd_suppr_date (d)) ? "Yes" : "No");