commit 47b46bec6d9e91f10e1032f99cee77a8994ee448
parent fb58efc21be3c64e6882d8c7c9182fe3ad68ef65
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Sun, 30 Aug 2026 17:36:27 +0200
Fixed processing early disconnects and shutdowns
Diffstat:
1 file changed, 56 insertions(+), 27 deletions(-)
diff --git a/src/mhd2/stream_process_states.c b/src/mhd2/stream_process_states.c
@@ -66,6 +66,9 @@
#ifdef MHD_SUPPORT_HTTP2
# include "h2/h2_comm.h"
#endif
+#ifdef MHD_SUPPORT_HTTPS
+# include "mhd_tls_funcs.h"
+#endif /* MHD_SUPPORT_HTTPS */
#include "stream_process_states.h"
#include "stream_funcs.h"
@@ -276,6 +279,20 @@ finish_resume (struct MHD_Connection *restrict c)
}
+/* always return 'false' */
+static MHD_FN_PAR_NONNULL_ALL_ bool
+handle_early_peer_shutdown (struct MHD_Connection *restrict c,
+ bool has_unfinished_process)
+{
+ mhd_conn_start_closing (c,
+ has_unfinished_process ?
+ mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY :
+ mhd_CONN_CLOSE_HTTP_COMPLETED,
+ NULL);
+ return false;
+}
+
+
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
mhd_conn_process_data (struct MHD_Connection *restrict c)
{
@@ -288,25 +305,39 @@ mhd_conn_process_data (struct MHD_Connection *restrict c)
return true;
}
- switch (process_http_comm_layer (c))
- {
- case mhd_COMM_LAYER_OK:
- break; /* Process HTTP data */
- case mhd_COMM_LAYER_PROCESSING:
- mhd_assert (!c->resuming);
- return true; /* Too early for HTTP */
- case mhd_COMM_LAYER_BROKEN:
- mhd_assert (c->dbg.closing_started);
- return false; /* Connection is broken */
- default:
- mhd_UNREACHABLE ();
- return false;
- }
+ mhd_assert ((!mhd_SCKT_NET_ST_HAS_FLAG (c->sk.ready,
+ mhd_SOCKET_NET_STATE_ERROR_READY))
+ || (mhd_SOCKET_ERR_NO_ERROR != c->sk.state.discnt_err));
- if (c->resuming)
+ if (mhd_SOCKET_ERR_NO_ERROR == c->sk.state.discnt_err)
{
- mhd_assert (!mhd_C_IS_HTTP2 (c));
- finish_resume (c);
+ switch (process_http_comm_layer (c))
+ {
+ case mhd_COMM_LAYER_OK:
+ break; /* Process HTTP data */
+ case mhd_COMM_LAYER_PROCESSING:
+ mhd_assert (!c->resuming);
+ if (c->sk.state.rmt_shut_wr)
+ {
+ bool unfinished;
+ unfinished = (0 != c->read_buffer_offset);
+#ifdef MHD_SUPPORT_HTTPS
+ if (!unfinished
+ && mhd_C_HAS_TLS (c))
+ unfinished =
+ (mhd_TLS_ALPN_PROT_HTTP2 == mhd_tls_conn_get_alpn_prot (c->tls));
+#endif /* MHD_SUPPORT_HTTPS */
+ return handle_early_peer_shutdown (c,
+ unfinished);
+ }
+ return true; /* Too early for HTTP */
+ case mhd_COMM_LAYER_BROKEN:
+ mhd_assert (c->dbg.closing_started);
+ return false; /* Connection is broken */
+ default:
+ mhd_UNREACHABLE ();
+ return false;
+ }
}
#ifdef MHD_SUPPORT_HTTP2
@@ -323,23 +354,21 @@ mhd_conn_process_data (struct MHD_Connection *restrict c)
mhd_assert (mhd_D_IS_HTTP1_ENABLED (d) || (!mhd_C_IS_HTTP2 (c)) \
|| c->stop_with_error);
+ if (c->resuming)
+ {
+ mhd_assert (!mhd_C_IS_HTTP2 (c));
+ finish_resume (c);
+ }
+
if ((c->sk.state.rmt_shut_wr) && (mhd_HTTP_STAGE_START_REPLY > c->stage))
{
if (0 == c->read_buffer_offset)
{ /* Read buffer is empty, connection state is actual */
- mhd_conn_start_closing (c,
- (mhd_HTTP_STAGE_INIT == c->stage) ?
- mhd_CONN_CLOSE_HTTP_COMPLETED :
- mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY,
- NULL);
- return false;
+ return handle_early_peer_shutdown (c,
+ (mhd_HTTP_STAGE_INIT != c->stage));
}
}
- mhd_assert ((!mhd_SCKT_NET_ST_HAS_FLAG (c->sk.ready,
- mhd_SOCKET_NET_STATE_ERROR_READY))
- || (mhd_SOCKET_ERR_NO_ERROR != c->sk.state.discnt_err));
-
if (mhd_SOCKET_ERR_NO_ERROR != c->sk.state.discnt_err)
{
mhd_assert (mhd_SOCKET_ERR_IS_HARD (c->sk.state.discnt_err));