commit 86e0ab38d04baf3afd70db67a6529c7060bb712e
parent 7acad4742ce595aa370b90448b031f0bd6b25c0c
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Sun, 15 Jun 2025 15:49:31 +0200
Added reporting of response is aborted in the middle.
Do not report when responding hasn't been started yet.
Diffstat:
3 files changed, 155 insertions(+), 35 deletions(-)
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h
@@ -582,6 +582,11 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
*/
MHD_SC_UPGRADED_NET_TIMEOUT = 30161
,
+ /**
+ * Not enough system resources
+ */
+ MHD_SC_NO_SYS_RESOURCES = 30180
+ ,
/* 40000-level errors are caused by the HTTP client
(or the network) */
@@ -593,22 +598,6 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED = 40000
,
/**
- * MHD is closing a connection because it was reset.
- */
- MHD_SC_CONNECTION_RESET_CLOSED = 40001
- ,
- /**
- * MHD is closing a connection because receiving the
- * request failed.
- */
- MHD_SC_CONNECTION_RECV_FAIL_CLOSED = 40002
- ,
- /**
- * MHD is closing a connection because sending the response failed.
- */
- MHD_SC_CONNECTION_SEND_FAIL_CLOSED = 40003
- ,
- /**
* MHD is returning an error because the header provided
* by the client is too big.
*/
@@ -776,6 +765,50 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
*/
MHD_SC_REQ_PROCCESSING_ERR_REPLY = 41000
,
+ /**
+ * MHD is closing a connection because of timeout.
+ */
+ MHD_SC_CONNECTION_TIMEOUT = 42000
+ ,
+ /**
+ * MHD is closing a connection because receiving the
+ * request failed.
+ */
+ MHD_SC_CONNECTION_RECV_FAIL_CLOSED = 42020
+ ,
+ /**
+ * MHD is closing a connection because sending the response failed.
+ */
+ MHD_SC_CONNECTION_SEND_FAIL_CLOSED = 42021
+ ,
+ /**
+ * MHD is closing a connection because remote client shut down its sending
+ * side before full request was sent.
+ */
+ MHD_SC_CLIENT_SHUTDOWN_EARLY = 42040
+ ,
+ /**
+ * MHD is closing a connection because remote client closed connection
+ * early.
+ */
+ MHD_SC_CLIENT_CLOSED_CONN_EARLY = 42041
+ ,
+ /**
+ * MHD is closing a connection connection has been (remotely) aborted.
+ */
+ MHD_SC_CONNECTION_ABORTED = 42042
+ ,
+ /**
+ * MHD is closing a connection because it was reset.
+ */
+ MHD_SC_CONNECTION_RESET = 42060
+ ,
+ /**
+ * MHD is closing a connection connection (or connection socket) has
+ * been broken.
+ */
+ MHD_SC_CONNECTION_BROKEN = 42061
+ ,
/* 50000-level errors are because of an error internal
to the MHD logic, possibly including our interaction
diff --git a/src/include/microhttpd2_preamble.h.in b/src/include/microhttpd2_preamble.h.in
@@ -582,6 +582,11 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
*/
MHD_SC_UPGRADED_NET_TIMEOUT = 30161
,
+ /**
+ * Not enough system resources
+ */
+ MHD_SC_NO_SYS_RESOURCES = 30180
+ ,
/* 40000-level errors are caused by the HTTP client
(or the network) */
@@ -593,22 +598,6 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
MHD_SC_CONNECTION_PARSE_FAIL_CLOSED = 40000
,
/**
- * MHD is closing a connection because it was reset.
- */
- MHD_SC_CONNECTION_RESET_CLOSED = 40001
- ,
- /**
- * MHD is closing a connection because receiving the
- * request failed.
- */
- MHD_SC_CONNECTION_RECV_FAIL_CLOSED = 40002
- ,
- /**
- * MHD is closing a connection because sending the response failed.
- */
- MHD_SC_CONNECTION_SEND_FAIL_CLOSED = 40003
- ,
- /**
* MHD is returning an error because the header provided
* by the client is too big.
*/
@@ -776,6 +765,50 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
*/
MHD_SC_REQ_PROCCESSING_ERR_REPLY = 41000
,
+ /**
+ * MHD is closing a connection because of timeout.
+ */
+ MHD_SC_CONNECTION_TIMEOUT = 42000
+ ,
+ /**
+ * MHD is closing a connection because receiving the
+ * request failed.
+ */
+ MHD_SC_CONNECTION_RECV_FAIL_CLOSED = 42020
+ ,
+ /**
+ * MHD is closing a connection because sending the response failed.
+ */
+ MHD_SC_CONNECTION_SEND_FAIL_CLOSED = 42021
+ ,
+ /**
+ * MHD is closing a connection because remote client shut down its sending
+ * side before full request was sent.
+ */
+ MHD_SC_CLIENT_SHUTDOWN_EARLY = 42040
+ ,
+ /**
+ * MHD is closing a connection because remote client closed connection
+ * early.
+ */
+ MHD_SC_CLIENT_CLOSED_CONN_EARLY = 42041
+ ,
+ /**
+ * MHD is closing a connection connection has been (remotely) aborted.
+ */
+ MHD_SC_CONNECTION_ABORTED = 42042
+ ,
+ /**
+ * MHD is closing a connection because it was reset.
+ */
+ MHD_SC_CONNECTION_RESET = 42060
+ ,
+ /**
+ * MHD is closing a connection connection (or connection socket) has
+ * been broken.
+ */
+ MHD_SC_CONNECTION_BROKEN = 42061
+ ,
/* 50000-level errors are because of an error internal
to the MHD logic, possibly including our interaction
diff --git a/src/mhd2/stream_funcs.c b/src/mhd2/stream_funcs.c
@@ -745,6 +745,7 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
bool close_hard;
enum MHD_RequestEndedCode end_code;
enum MHD_StatusCode sc;
+ bool reply_sending_aborted;
#ifdef mhd_DEBUG_CONN_ADD_CLOSE
fprintf (stderr,
@@ -756,6 +757,9 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
log_msg ? "\"" : "");
#endif /* mhd_DEBUG_CONN_ADD_CLOSE */
+ reply_sending_aborted =
+ ((mhd_HTTP_STAGE_HEADERS_SENDING <= c->stage)
+ && (mhd_HTTP_STAGE_FULL_REPLY_SENT > c->stage));
sc = MHD_SC_INTERNAL_ERROR;
switch (reason)
{
@@ -763,15 +767,18 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
close_hard = true;
end_code = MHD_REQUEST_ENDED_HTTP_PROTOCOL_ERROR;
sc = MHD_SC_REQ_MALFORMED;
+ mhd_assert (! reply_sending_aborted);
break;
case mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REQUEST:
close_hard = true;
end_code = MHD_REQUEST_ENDED_NO_RESOURCES;
+ mhd_assert (! reply_sending_aborted);
break;
case mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY:
close_hard = true;
end_code = MHD_REQUEST_ENDED_CLIENT_ABORT;
- sc = MHD_SC_REPLY_POOL_ALLOCATION_FAILURE;
+ sc = MHD_SC_CLIENT_SHUTDOWN_EARLY;
+ mhd_assert (! reply_sending_aborted);
break;
case mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY:
close_hard = true;
@@ -779,6 +786,9 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
MHD_REQUEST_ENDED_NO_RESOURCES :
MHD_REQUEST_ENDED_HTTP_PROTOCOL_ERROR;
sc = MHD_SC_REPLY_POOL_ALLOCATION_FAILURE;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted due to insufficient memory " \
+ "in the connection pool");
break;
case mhd_CONN_CLOSE_NO_MEM_FOR_ERR_RESPONSE:
close_hard = true;
@@ -791,47 +801,71 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
close_hard = true;
end_code = MHD_REQUEST_ENDED_BY_APP_ERROR;
sc = MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted due to application reply " \
+ "generation failure");
break;
case mhd_CONN_CLOSE_APP_ABORTED:
close_hard = true;
end_code = MHD_REQUEST_ENDED_BY_APP_ABORT;
sc = MHD_SC_APPLICATION_CALLBACK_ABORT_ACTION;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Application aborted reply sending");
break;
case mhd_CONN_CLOSE_FILE_OFFSET_TOO_LARGE:
close_hard = true;
end_code = MHD_REQUEST_ENDED_FILE_ERROR;
sc = MHD_SC_REPLY_FILE_OFFSET_TOO_LARGE;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted because OS failed " \
+ "to read too large response file");
break;
case mhd_CONN_CLOSE_FILE_READ_ERROR:
close_hard = true;
end_code = MHD_REQUEST_ENDED_FILE_ERROR;
sc = MHD_SC_REPLY_FILE_READ_ERROR;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted because OS failed " \
+ "to read response file");
break;
case mhd_CONN_CLOSE_FILE_TOO_SHORT:
close_hard = true;
end_code = MHD_REQUEST_ENDED_BY_APP_ERROR;
sc = MHD_SC_REPLY_FILE_TOO_SHORT;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted because response file is "
+ "shorter that expected");
break;
#ifdef MHD_SUPPORT_AUTH_DIGEST
case mhd_CONN_CLOSE_NONCE_ERROR:
close_hard = true;
end_code = MHD_REQUEST_ENDED_NONCE_ERROR;
sc = MHD_SC_REPLY_NONCE_ERROR;
+ mhd_assert (! reply_sending_aborted);
break;
#endif /* MHD_SUPPORT_AUTH_DIGEST */
case mhd_CONN_CLOSE_INT_ERROR:
close_hard = true;
end_code = MHD_REQUEST_ENDED_NO_RESOURCES;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted due to MHD internal error");
break;
case mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED:
close_hard = true;
end_code = MHD_REQUEST_ENDED_BY_EXT_EVENT_ERROR;
sc = MHD_SC_EXTR_EVENT_REG_FAILED;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted due to external event " \
+ "registration failure");
break;
case mhd_CONN_CLOSE_NO_SYS_RESOURCES:
close_hard = true;
end_code = MHD_REQUEST_ENDED_NO_RESOURCES;
+ sc = MHD_SC_NO_SYS_RESOURCES;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted due to lack of " \
+ "system resources");
break;
case mhd_CONN_CLOSE_SOCKET_ERR:
close_hard = true;
@@ -839,15 +873,29 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
{
case mhd_SOCKET_ERR_NOMEM:
end_code = MHD_REQUEST_ENDED_NO_RESOURCES;
+ sc = MHD_SC_NO_SYS_RESOURCES;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted because system closed " \
+ "socket due to lack of system resources");
break;
case mhd_SOCKET_ERR_REMT_DISCONN:
close_hard = false;
end_code = (mhd_HTTP_STAGE_INIT == c->stage) ?
- MHD_REQUEST_ENDED_COMPLETED_OK /* Not used */ :
- MHD_REQUEST_ENDED_CLIENT_ABORT;
+ MHD_REQUEST_ENDED_COMPLETED_OK /* Not used */
+ : MHD_REQUEST_ENDED_CLIENT_ABORT;
+ if (reply_sending_aborted)
+ {
+ sc = MHD_SC_CLIENT_CLOSED_CONN_EARLY;
+ if (NULL == log_msg)
+ log_msg = mhd_MSG4LOG ("Response aborted because remote client " \
+ "closed connection early");
+ }
break;
case mhd_SOCKET_ERR_CONNRESET:
end_code = MHD_REQUEST_ENDED_CLIENT_ABORT;
+ sc = MHD_SC_CONNECTION_RESET;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted due to aborted connection");
break;
case mhd_SOCKET_ERR_CONN_BROKEN:
case mhd_SOCKET_ERR_NOTCONN:
@@ -862,6 +910,9 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
case mhd_SOCKET_ERR_INTERNAL:
case mhd_SOCKET_ERR_NO_ERROR:
end_code = MHD_REQUEST_ENDED_CONNECTION_ERROR;
+ sc = MHD_SC_CONNECTION_BROKEN;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted due to broken connection");
break;
case mhd_SOCKET_ERR_AGAIN:
case mhd_SOCKET_ERR_INTR:
@@ -884,6 +935,9 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
}
close_hard = true;
end_code = MHD_REQUEST_ENDED_TIMEOUT_REACHED;
+ sc = MHD_SC_CONNECTION_TIMEOUT;
+ if (reply_sending_aborted && (NULL == log_msg))
+ log_msg = mhd_MSG4LOG ("Response aborted due to sending timeout");
break;
case mhd_CONN_CLOSE_ERR_REPLY_SENT: