[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 245/335: WIP-4
From: |
gnunet |
Subject: |
[libmicrohttpd] 245/335: WIP-4 |
Date: |
Sat, 27 Jul 2024 22:02:21 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to tag stf-m2
in repository libmicrohttpd.
commit 706092798a9fa6210048052de6171f0f5660e793
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Sat Jul 20 18:46:46 2024 +0200
WIP-4
---
src/include/microhttpd2.h | 73 +++++++++----
src/mhd2/events_process.c | 2 +-
src/mhd2/mhd_mempool.c | 2 +
src/mhd2/mhd_request.h | 9 +-
src/mhd2/mhd_response.h | 5 +
src/mhd2/mhd_sockets_funcs.c | 32 ++++++
src/mhd2/mhd_sockets_funcs.h | 17 +++
src/mhd2/stream_funcs.c | 224 ++++++++++++++++++++++++++++++++++++--
src/mhd2/stream_funcs.h | 146 ++++++++++++++++++-------
src/mhd2/stream_process_reply.c | 10 +-
src/mhd2/stream_process_request.c | 36 +++---
11 files changed, 462 insertions(+), 94 deletions(-)
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h
index 029a40b1..61c56e6a 100644
--- a/src/include/microhttpd2.h
+++ b/src/include/microhttpd2.h
@@ -492,6 +492,16 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
*/
MHD_SC_CONNECTION_POOL_NO_MEM_COOKIE = 30132
,
+ /**
+ * Detected jump back of system clock
+ */
+ MHD_SC_SYS_CLOCK_JUMP_BACK_LARGE = 30140
+ ,
+ /**
+ * Detected correctable jump back of system clock
+ */
+ MHD_SC_SYS_CLOCK_JUMP_BACK_CORRECTED = 30141
+ ,
/* 40000-level errors are caused by the HTTP client
(or the network) */
@@ -600,27 +610,32 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
*/
MHD_SC_REQ_FOOTER_LINE_NO_COLON = 40141
,
+ /**
+ * The request is malformed.
+ */
+ MHD_SC_REQ_MALFORMED = 40155
+ ,
/**
* The cookie string has been parsed, but it is not fully compliant with
* specifications
*/
- MHD_SC_REQ_COOKIE_PARSED_NOT_COMPLIANT = 40142
+ MHD_SC_REQ_COOKIE_PARSED_NOT_COMPLIANT = 40160
,
/**
* The cookie string has been parsed only partially
*/
- MHD_SC_REQ_COOKIE_PARSED_PARTIALLY = 40142
+ MHD_SC_REQ_COOKIE_PARSED_PARTIALLY = 40161
,
/**
* The cookie string is ignored, as it is not fully compliant with
* specifications
*/
- MHD_SC_REQ_COOKIE_IGNORED_NOT_COMPLIANT = 40143
+ MHD_SC_REQ_COOKIE_IGNORED_NOT_COMPLIANT = 40162
,
/**
* The cookie string has been ignored as it is invalid
*/
- MHD_SC_REQ_COOKIE_INVALID = 40143
+ MHD_SC_REQ_COOKIE_INVALID = 40163
,
/* 50000-level errors are because of an error internal
@@ -1050,7 +1065,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
/**
* MHD failed to build the response header.
*/
- MHD_SC_FAILED_RESPONSE_HEADER_GENERATION = 50230
+ MHD_SC_REPLY_FAILED_HEADER_GENERATION = 50230
+ ,
+ /**
+ * Failed to allocate memory in connection's pool for the reply.
+ */
+ MHD_SC_REPLY_POOL_ALLOCATION_FAILURE = 50231
,
/**
* The feature is not supported by this MHD build (either
@@ -1168,7 +1188,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
* MHD is closing a connection because the application
* callback told it to do so.
*/
- MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED = 60006
+ MHD_SC_APPLICATION_CALLBACK_ABORT_ACTION = 60006
,
/**
* Application only partially processed upload and did
@@ -3446,49 +3466,56 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_RequestTerminationCode
MHD_REQUEST_TERMINATED_COMPLETED_OK = 0
,
/**
- * The application terminated request without response.
+ * No activity on the connection for the number of seconds specified using
+ * #MHD_C_OPTION_TIMEOUT().
* @ingroup request
*/
- MHD_REQUEST_TERMINATED_BY_APP = 1
+ MHD_REQUEST_TERMINATED_TIMEOUT_REACHED = 10
,
/**
- * The request is not valid according to
- * HTTP specifications.
+ * The connection was broken or TLS protocol error.
* @ingroup request
*/
- MHD_REQUEST_TERMINATED_HTTP_PROTOCOL_ERROR = 2
+ MHD_REQUEST_TERMINATED_CONNECTION_ERROR = 20
,
/**
- * The client terminated the connection by closing the socket
- * for writing (TCP half-closed) before sending complete request;
+ * The client terminated the connection by closing the socket either
+ * completely or for writing (TCP half-closed) before sending complete
+ * request.
* @ingroup request
*/
- MHD_REQUEST_TERMINATED_CLIENT_ABORT = 3
+ MHD_REQUEST_TERMINATED_CLIENT_ABORT = 30
,
/**
- * Error handling the connection due to resources exhausted.
+ * The request is not valid according to
+ * HTTP specifications.
* @ingroup request
*/
- MHD_REQUEST_TERMINATED_NO_RESOURCES = 4
+ MHD_REQUEST_TERMINATED_HTTP_PROTOCOL_ERROR = 31
,
/**
- * Closing the session since MHD is being shut down.
+ * The application aborted request without response.
* @ingroup request
*/
- MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN = 5
+ MHD_REQUEST_TERMINATED_BY_APP_ABORT = 40
,
/**
- * No activity on the connection for the number of seconds specified using
- * #MHD_C_OPTION_TIMEOUT().
+ * The application aborted request without response.
* @ingroup request
*/
- MHD_REQUEST_TERMINATED_TIMEOUT_REACHED = 6
+ MHD_REQUEST_TERMINATED_BY_APP_ERROR = 41
,
/**
- * The connection was broken or TLS protocol error.
+ * Error handling the connection due to resources exhausted.
+ * @ingroup request
+ */
+ MHD_REQUEST_TERMINATED_NO_RESOURCES = 50
+ ,
+ /**
+ * Closing the session since MHD is being shut down.
* @ingroup request
*/
- MHD_REQUEST_TERMINATED_CONNECTION_ERROR = 7
+ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN = 60
};
/**
diff --git a/src/mhd2/events_process.c b/src/mhd2/events_process.c
index 43f36c18..b54cd0dc 100644
--- a/src/mhd2/events_process.c
+++ b/src/mhd2/events_process.c
@@ -416,7 +416,7 @@ get_all_net_updates_by_poll (struct MHD_Daemon *restrict d,
// TODO: handle empty list situation
- num_events = mhd_poll (d->events.data.poll.fds, num_fds, -1);
+ num_events = mhd_poll (d->events.data.poll.fds, num_fds, -1); // TODO: use
correct timeout value
if (0 > num_events)
{
int err;
diff --git a/src/mhd2/mhd_mempool.c b/src/mhd2/mhd_mempool.c
index 97d1f07d..a4bb9028 100644
--- a/src/mhd2/mhd_mempool.c
+++ b/src/mhd2/mhd_mempool.c
@@ -265,6 +265,8 @@ struct mhd_MemoryPool
* 'false' if pool was malloc'ed, 'true' if mmapped (VirtualAlloc'ed for
W32).
*/
bool is_mmap;
+
+ // TODO: implement *optional* zeroing on reset on reallocs
};
diff --git a/src/mhd2/mhd_request.h b/src/mhd2/mhd_request.h
index 445e32b2..cb608941 100644
--- a/src/mhd2/mhd_request.h
+++ b/src/mhd2/mhd_request.h
@@ -252,6 +252,11 @@ struct MHD_Request
*/
struct mhd_ReqContentData cntn;
+ /**
+ * Set to true if request is too large to be handled
+ */
+ bool too_large;
+
/**
* HTTP version string (i.e. http/1.1). Allocated
* in pool.
@@ -357,14 +362,14 @@ struct MHD_Request
* and some other API calls. Here is where we store it. (MHD does
* not know or care what it is).
*/
- void *client_context;
+ void *app_context;
/**
* Did we ever call the "default_handler" on this request?
* This flag determines if we have called the #MHD_OPTION_NOTIFY_COMPLETED
* handler when the request finishes.
*/
- bool client_aware;
+ bool app_aware;
/**
* Number of bare CR characters that were replaced with space characters
diff --git a/src/mhd2/mhd_response.h b/src/mhd2/mhd_response.h
index 4153af4c..78b27aca 100644
--- a/src/mhd2/mhd_response.h
+++ b/src/mhd2/mhd_response.h
@@ -259,6 +259,11 @@ struct mhd_ResponseConfiguration
* Response has "Connection:" header
*/
bool has_hdr_conn; // TODO: set the member
+
+ /**
+ * Response is internal-only error response
+ */
+ bool int_err_resp;
};
#ifndef NDEBUG
diff --git a/src/mhd2/mhd_sockets_funcs.c b/src/mhd2/mhd_sockets_funcs.c
index 477cabbc..a24e2633 100644
--- a/src/mhd2/mhd_sockets_funcs.c
+++ b/src/mhd2/mhd_sockets_funcs.c
@@ -126,6 +126,38 @@ 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)
+ struct linger par;
+
+ par.l_onoff = 1;
+ par.l_linger = 0;
+
+ return 0 == setsockopt (sckt, SOL_SOCKET, SO_LINGER,
+ (const void *) &par, sizeof (par));
+#else /* ! TCP_NODELAY */
+ (void) sock;
+ return false;
+#endif /* ! TCP_NODELAY */
+}
+
+
+MHD_INTERNAL bool
+mhd_socket_shut_wr (MHD_Socket sckt)
+{
+#if defined(SHUT_WR) // TODO: detect constants in configure
+ return 0 == shutdown (sckt, SHUT_WR);
+#elif defined(SD_SEND) // TODO: detect constants in configure
+ return 0 == shutdown (sckt, SD_SEND);
+#else
+ return false;
+#endif
+}
+
+
#ifndef HAVE_SOCKETPAIR
static bool
diff --git a/src/mhd2/mhd_sockets_funcs.h b/src/mhd2/mhd_sockets_funcs.h
index d8b52daa..64e78579 100644
--- a/src/mhd2/mhd_sockets_funcs.h
+++ b/src/mhd2/mhd_sockets_funcs.h
@@ -51,6 +51,23 @@ mhd_socket_nonblocking (MHD_Socket sckt);
MHD_INTERNAL bool
mhd_socket_noninheritable (MHD_Socket sckt);
+/**
+ * Change socket options to be closed "hard".
+ *
+ * @param sock the socket to manipulate
+ * @return true on success, false otherwise
+ */
+MHD_INTERNAL bool
+mhd_socket_set_hard_close (MHD_Socket sckt);
+
+/**
+ * Shutdown sending on socket
+ *
+ * @param sock the socket to manipulate
+ * @return true on success, false otherwise
+ */
+MHD_INTERNAL bool
+mhd_socket_shut_wr (MHD_Socket sckt);
/**
* Control Nagle's algorithm on @a sock.
diff --git a/src/mhd2/stream_funcs.c b/src/mhd2/stream_funcs.c
index 931be594..87a08111 100644
--- a/src/mhd2/stream_funcs.c
+++ b/src/mhd2/stream_funcs.c
@@ -37,9 +37,12 @@
#include "mhd_str.h"
#include "mhd_str_macros.h"
+#include "mhd_sockets_funcs.h"
+
#include "request_get_value.h"
#include "response_destroy.h"
#include "mhd_mono_clock.h"
+#include "daemon_logger.h"
#include "mhd_public_api.h"
@@ -501,13 +504,13 @@ mhd_stream_finish_req_serving (struct MHD_Connection
*restrict c,
#if 0 // TODO: notification callback
if ( (NULL != d->notify_completed) &&
- (c->rq.client_aware) )
+ (c->rq.app_aware) )
d->notify_completed (d->notify_completed_cls,
c,
- &c->rq.client_context,
+ &c->rq.app_context,
MHD_REQUEST_TERMINATED_COMPLETED_OK);
+ c->rq.app_aware = false;
#endif
- c->rq.client_aware = false;
if (NULL != c->rp.response)
mhd_response_dec_use_count (c->rp.response);
@@ -524,6 +527,8 @@ mhd_stream_finish_req_serving (struct MHD_Connection
*restrict c,
/* iov (if any) will be deallocated by mhd_pool_reset */
memset (&c->rp, 0, sizeof(c->rp));
+ // TODO: set all rq and tp pointers to NULL manually. Do the same in other
places.
+
c->write_buffer = NULL;
c->write_buffer_size = 0;
c->write_buffer_send_offset = 0;
@@ -543,15 +548,51 @@ mhd_stream_finish_req_serving (struct MHD_Connection
*restrict c,
new_read_buf_size);
c->read_buffer_size = new_read_buf_size;
}
- c->rq.client_context = NULL;
+ c->rq.app_context = NULL;
}
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
mhd_stream_check_timedout (struct MHD_Connection *restrict c)
{
- (void) c;
- // TODO: implement
+ 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;
}
@@ -574,7 +615,7 @@ mhd_stream_update_activity_mark (struct MHD_Connection
*restrict c)
return; /* Skip update of activity for connections
without timeout timer. */
- c->last_activity = MHD_monotonic_msec_counter ();
+ 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 */
@@ -585,3 +626,172 @@ mhd_stream_update_activity_mark (struct MHD_Connection
*restrict c)
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_ (1) MHD_FN_PAR_CSTR_ (3) void
+mhd_conn_pre_close (struct MHD_Connection *restrict c,
+ enum mhd_ConnCloseReason reason,
+ const char *log_msg)
+{
+ bool close_hard;
+ enum MHD_RequestTerminationCode term_code;
+ enum MHD_StatusCode sc;
+
+ sc = MHD_SC_INTERNAL_ERROR;
+ switch (reason)
+ {
+ case mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN:
+ close_hard = true;
+ term_code = MHD_REQUEST_TERMINATED_HTTP_PROTOCOL_ERROR;
+ sc = MHD_SC_REQ_MALFORMED;
+ break;
+ case mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REQUEST:
+ close_hard = true;
+ term_code = MHD_REQUEST_TERMINATED_NO_RESOURCES;
+ break;
+ case mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY:
+ close_hard = true;
+ term_code = MHD_REQUEST_TERMINATED_CLIENT_ABORT;
+ sc = MHD_SC_REPLY_POOL_ALLOCATION_FAILURE;
+ break;
+ case mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY:
+ close_hard = true;
+ term_code = MHD_REQUEST_TERMINATED_NO_RESOURCES;
+ break;
+ case mhd_CONN_CLOSE_APP_ERROR:
+ close_hard = true;
+ term_code = MHD_REQUEST_TERMINATED_BY_APP_ERROR;
+ sc = MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED;
+ break;
+ case mhd_CONN_CLOSE_APP_ABORTED:
+ close_hard = true;
+ term_code = MHD_REQUEST_TERMINATED_BY_APP_ABORT;
+ sc = MHD_SC_APPLICATION_CALLBACK_ABORT_ACTION;
+ break;
+ case mhd_CONN_CLOSE_INT_ERROR:
+ close_hard = true;
+ term_code = MHD_REQUEST_TERMINATED_NO_RESOURCES;
+ break;
+ case mhd_CONN_CLOSE_SOCKET_ERR:
+ close_hard = true;
+ switch (c->sk_discnt_err)
+ {
+ case mhd_SOCKET_ERR_NOMEM:
+ term_code = MHD_REQUEST_TERMINATED_NO_RESOURCES;
+ break;
+ case mhd_SOCKET_ERR_CONNRESET:
+ term_code = MHD_REQUEST_TERMINATED_CLIENT_ABORT;
+ break;
+ case mhd_SOCKET_ERR_CONN_BROKEN:
+ case mhd_SOCKET_ERR_NOTCONN:
+ case mhd_SOCKET_ERR_TLS:
+ case mhd_SOCKET_ERR_PIPE:
+ case mhd_SOCKET_ERR_NOT_CHECKED:
+ case mhd_SOCKET_ERR_BADF:
+ case mhd_SOCKET_ERR_INVAL:
+ case mhd_SOCKET_ERR_OPNOTSUPP:
+ case mhd_SOCKET_ERR_NOTSOCK:
+ case mhd_SOCKET_ERR_OTHER:
+ case mhd_SOCKET_ERR_INTERNAL:
+ term_code = MHD_REQUEST_TERMINATED_CONNECTION_ERROR;
+ break;
+ case mhd_SOCKET_ERR_NO_ERROR:
+ case mhd_SOCKET_ERR_AGAIN:
+ case mhd_SOCKET_ERR_INTR:
+ default:
+ mhd_assert (0 && "Impossible value");
+ MHD_UNREACHABLE_;
+ }
+ break;
+
+ case mhd_CONN_CLOSE_TIMEDOUT:
+ if (MHD_CONNECTION_INIT == c->state)
+ {
+ close_hard = false;
+ term_code = MHD_REQUEST_TERMINATED_COMPLETED_OK; /* Not used */
+ break;
+ }
+ close_hard = true;
+ term_code = MHD_REQUEST_TERMINATED_TIMEOUT_REACHED;
+ break;
+
+ case mhd_CONN_CLOSE_CLIENT_HTTP_ERR_SENT_ERR:
+ close_hard = false;
+ term_code = c->rq.too_large ?
+ MHD_REQUEST_TERMINATED_NO_RESOURCES :
+ MHD_REQUEST_TERMINATED_HTTP_PROTOCOL_ERROR;
+ break;
+ case mhd_CONN_CLOSE_HTTP_COMPLETED:
+ close_hard = false;
+ term_code = MHD_REQUEST_TERMINATED_COMPLETED_OK;
+ break;
+
+ default:
+ mhd_assert (0 && "Unreachable code");
+ MHD_UNREACHABLE_;
+ term_code = MHD_REQUEST_TERMINATED_COMPLETED_OK;
+ close_hard = false;
+ }
+
+ mhd_assert ((NULL == log_msg) || (MHD_SC_INTERNAL_ERROR != sc));
+
+ /* Make changes on the socket early to let the kernel and the remote
+ * to process the changes in parallel. */
+ if (close_hard)
+ {
+ /* Use abortive closing, send RST to remote to indicate a problem */
+ (void) mhd_socket_set_hard_close (c->socket_fd);
+ c->state = MHD_CONNECTION_CLOSED;
+ c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
+ }
+ else
+ {
+ if (mhd_socket_shut_wr (c->socket_fd) && (! c->sk_rmt_shut_wr))
+ {
+ (void) 0; // TODO: start local lingering phase
+ c->state = MHD_CONNECTION_CLOSED; // TODO: start local lingering phase
+ c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; // TODO: start local
lingering phase
+ }
+ else
+ { /* No need / not possible to linger */
+ c->state = MHD_CONNECTION_CLOSED;
+ c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
+ }
+ }
+
+#ifdef HAVE_LOG_FUNCTIONALITY
+ if (NULL != log_msg)
+ {
+ mhd_LOG_MSG (c->daemon, sc, log_msg);
+ }
+#else /* ! HAVE_LOG_FUNCTIONALITY */
+ (void) log_msg;
+#endif /* ! HAVE_LOG_FUNCTIONALITY */
+
+#if 0 // TODO: notification callback
+ if ( (NULL != d->notify_completed) &&
+ (c->rq.app_aware) )
+ d->notify_completed (d->notify_completed_cls,
+ c,
+ &c->rq.app_context,
+ MHD_REQUEST_TERMINATED_COMPLETED_OK);
+#else
+ (void) term_code;
+#endif
+
+ if (NULL != c->rp.response)
+ mhd_response_dec_use_count (c->rp.response);
+ c->rp.response = NULL;
+
+ mhd_assert (NULL != c->pool);
+ c->read_buffer_offset = 0;
+ c->read_buffer_size = 0;
+ c->read_buffer = NULL;
+ c->write_buffer_send_offset = 0;
+ c->write_buffer_append_offset = 0;
+ c->write_buffer_size = 0;
+ c->write_buffer = NULL;
+ mhd_pool_destroy (c->pool);
+ c->pool = NULL;
+}
diff --git a/src/mhd2/stream_funcs.h b/src/mhd2/stream_funcs.h
index 1c105c0c..cc36670b 100644
--- a/src/mhd2/stream_funcs.h
+++ b/src/mhd2/stream_funcs.h
@@ -134,80 +134,146 @@ MHD_INTERNAL void
mhd_stream_update_activity_mark (struct MHD_Connection *restrict c)
MHD_FN_PAR_NONNULL_ALL_;
+/**
+ * Update last activity mark to the current time..
+ * @param c the connection to update
+ * @return 'true' if connection has not been timed out,
+ * 'false' otherwise
+ */
+MHD_INTERNAL bool
+mhd_stream_check_timedout (struct MHD_Connection *restrict c)
+MHD_FN_PAR_NONNULL_ALL_;
-enum mhd_StreamAbortReason
+/**
+ * The reason to close the connection
+ */
+enum mhd_ConnCloseReason
{
- mhd_STREAM_ABORT_CLIENT_HTTP_ERR
+ /* Hard problem while receiving */
+ /**
+ * Client sent data that cannot be interpreted as HTTP data
+ */
+ mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN
+ ,
+ /**
+ * No space in the connection pool memory for receiving or processing
+ * the request
+ */
+ mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REQUEST
+ ,
+ /**
+ * The client shut down send before complete request sent
+ */
+ mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY
,
- mhd_STREAM_ABORT_NO_POOL_MEM_FOR_REPLY
+
+ /* Hard problem while sending */
+
+ /**
+ * No space in the connection pool memory for the reply
+ */
+ mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY
+ ,
+ /**
+ * Application behaves incorrectly
+ */
+ mhd_CONN_CLOSE_APP_ERROR
+ ,
+ /**
+ * Application requested about of the stream
+ */
+ mhd_CONN_CLOSE_APP_ABORTED
+ ,
+
+ /* Hard problem while receiving or sending */
+ /**
+ * MHD internal error.
+ * Should never appear.
+ */
+ mhd_CONN_CLOSE_INT_ERROR
+ ,
+ /**
+ * The TCP or TLS connection is broken or aborted due to error on socket
+ * or TLS
+ */
+ mhd_CONN_CLOSE_SOCKET_ERR
,
- mhd_STREAM_ABORT_APP_ERROR
+
+ /* Could be hard or soft error depending on connection state */
+ /**
+ * Timeout detected when receiving request
+ */
+ mhd_CONN_CLOSE_TIMEDOUT
+ ,
+
+ /* Soft problem */
+ /**
+ * The connection must be closed after error response as the client
+ * violates HTTP specification
+ */
+ mhd_CONN_CLOSE_CLIENT_HTTP_ERR_SENT_ERR
+ ,
+
+ /* Graceful closing */
+ /**
+ * Close connection after graceful completion of HTTP communication
+ */
+ mhd_CONN_CLOSE_HTTP_COMPLETED
+
};
+
/**
- * Close stream with error
- *
- * @param c the connection to close.
+ * Perform initial clean-up and mark for closing.
+ * Set the reason to "request finished"
+ * @param c the connection for pre-closing
*/
MHD_INTERNAL void
-mhd_stream_abort (struct MHD_Connection *c,
- enum mhd_StreamAbortReason reason,
- const char *log_msg)
+mhd_conn_pre_close (struct MHD_Connection *restrict c,
+ enum mhd_ConnCloseReason reason,
+ const char *log_msg)
MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3);
+/**
+ * Abort the stream and log message
+ */
#ifdef HAVE_LOG_FUNCTIONALITY
-# define mhd_STREAM_ABORT(c,r,m) (mhd_stream_abort ((c),(r),(m)))
+# define mhd_STREAM_ABORT(c,r,m) (mhd_conn_pre_close ((c),(r),(m)))
#else /* ! HAVE_LOG_FUNCTIONALITY */
-# define mhd_STREAM_ABORT(c,r,m) (mhd_stream_abort ((c),(r),NULL))
+# define mhd_STREAM_ABORT(c,r,m) (mhd_conn_pre_close ((c),(r),NULL))
#endif /* ! HAVE_LOG_FUNCTIONALITY */
-/**
- * Update last activity mark to the current time..
- * @param c the connection to update
- * @return 'true' if connection has not been timed out,
- * 'false' otherwise
- */
-MHD_INTERNAL bool
-mhd_stream_check_timedout (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
-
-
/**
* Perform initial clean-up and mark for closing.
* Set the reason to "aborted by application"
- * @param c to make
+ * @param c the connection for pre-closing
*/
-MHD_INTERNAL void
-mhd_conn_pre_close_app_abort (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
-
+#define mhd_conn_pre_close_app_abort(c) \
+ mhd_conn_pre_close (c, mhd_CONN_CLOSE_APP_ABORTED, NULL)
/**
* Perform initial clean-up and mark for closing.
* Set the reason to "socket error"
- * @param c to make
+ * @param c the connection for pre-closing
*/
-MHD_INTERNAL void
-mhd_conn_pre_close_skt_err (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
+#define mhd_conn_pre_close_skt_err(c) \
+ mhd_conn_pre_close (c, mhd_CONN_CLOSE_SOCKET_ERR, NULL)
/**
* Perform initial clean-up and mark for closing.
* Set the reason to "request finished"
- * @param c to make
+ * @param c the connection for pre-closing
*/
-MHD_INTERNAL void
-mhd_conn_pre_close_req_finished (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
+#define mhd_conn_pre_close_req_finished(c) \
+ mhd_conn_pre_close (c, mhd_CONN_CLOSE_HTTP_COMPLETED, NULL)
/**
* Perform initial clean-up and mark for closing.
* Set the reason to "timed out".
- * @param c to make
+ * @param c the connection for pre-closing
*/
-MHD_INTERNAL void
-mhd_conn_pre_close_timedout (struct MHD_Connection *restrict c)
-MHD_FN_PAR_NONNULL_ALL_;
+#define mhd_conn_pre_close_timedout(c) \
+ mhd_conn_pre_close (c, mhd_CONN_CLOSE_TIMEDOUT, NULL)
#endif /* ! MHD_STREAM_FUNCS_H */
diff --git a/src/mhd2/stream_process_reply.c b/src/mhd2/stream_process_reply.c
index 68b06d8d..3a0dacb1 100644
--- a/src/mhd2/stream_process_reply.c
+++ b/src/mhd2/stream_process_reply.c
@@ -853,7 +853,7 @@ mhd_stream_build_header_response (struct MHD_Connection
*restrict c)
if (! build_header_response_inn (c))
{
mhd_STREAM_ABORT (c,
- mhd_STREAM_ABORT_NO_POOL_MEM_FOR_REPLY,
+ mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY,
"No memory in the pool for the reply headers.");
return false;
}
@@ -928,7 +928,7 @@ mhd_stream_prep_unchunked_body (struct MHD_Connection
*restrict c)
{
/* not enough memory */
mhd_STREAM_ABORT (c,
- mhd_STREAM_ABORT_NO_POOL_MEM_FOR_REPLY,
+ mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY,
"No memory in the pool for the response data.");
return;
}
@@ -978,7 +978,7 @@ mhd_stream_prep_chunked_body (struct MHD_Connection
*restrict c)
if (32 > c->write_buffer_size)
{
mhd_STREAM_ABORT (c,
- mhd_STREAM_ABORT_NO_POOL_MEM_FOR_REPLY,
+ mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY,
"No memory in the pool for the reply chunked content.");
}
mhd_assert (max_chunk_overhead < \
@@ -1025,7 +1025,7 @@ mhd_stream_prep_chunked_body (struct MHD_Connection
*restrict c)
if (size_to_fill < filled)
{
mhd_STREAM_ABORT (c,
- mhd_STREAM_ABORT_APP_ERROR,
+ mhd_CONN_CLOSE_APP_ERROR,
"Closing connection (application returned more data "
"than requested).");
return;
@@ -1133,7 +1133,7 @@ mhd_stream_prep_chunked_footer (struct MHD_Connection
*restrict c)
if (! prep_chunked_footer_inn (c))
{
mhd_STREAM_ABORT (c,
- mhd_STREAM_ABORT_NO_POOL_MEM_FOR_REPLY,
+ mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY,
"No memory in the pool for the reply chunked footer.");
return;
}
diff --git a/src/mhd2/stream_process_request.c
b/src/mhd2/stream_process_request.c
index 1dc0672b..ee4d8734 100644
--- a/src/mhd2/stream_process_request.c
+++ b/src/mhd2/stream_process_request.c
@@ -630,7 +630,7 @@ get_request_line_inner (struct MHD_Connection *restrict c)
MHD_MAX_EMPTY_LINES_SKIP : 1)) <
c->rq.hdrs.rq_line.skipped_empty_lines))
{
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"Too many meaningless extra empty lines " \
"received before the request.");
return true; /* Process connection closure */
@@ -706,7 +706,7 @@ get_request_line_inner (struct MHD_Connection *restrict c)
ERR_RSP_BARE_CR_IN_HEADER);
}
else
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"Bare CR characters are not allowed " \
"in the request line.");
@@ -734,7 +734,7 @@ get_request_line_inner (struct MHD_Connection *restrict c)
ERR_RSP_BARE_LF_IN_HEADER);
}
else
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"Bare LF characters are not allowed " \
"in the request line.");
return true; /* Error in the request */
@@ -859,7 +859,7 @@ get_request_line_inner (struct MHD_Connection *restrict c)
ERR_RSP_REQUEST_MALFORMED);
}
else
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"The request line is malformed.");
return true;
@@ -922,7 +922,7 @@ get_request_line_inner (struct MHD_Connection *restrict c)
mhd_assert (NULL == c->rq.version);
if (0 == p)
{
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"The request line starts with a whitespace.");
return true; /* Error in the request */
}
@@ -959,7 +959,7 @@ get_request_line_inner (struct MHD_Connection *restrict c)
ERR_RSP_RQ_LINE_TOO_MANY_WSP);
}
else
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"The request line has more than "
"two whitespaces.");
return true; /* Error in the request */
@@ -1048,7 +1048,7 @@ get_request_line_inner (struct MHD_Connection *restrict c)
}
else
{
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"Invalid character is in the request line.");
return true; /* Error in the request */
}
@@ -1056,7 +1056,7 @@ get_request_line_inner (struct MHD_Connection *restrict c)
else if (0 == chr)
{
/* NUL character */
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"The NUL character is in the request line.");
return true; /* Error in the request */
}
@@ -1196,12 +1196,16 @@ process_request_target (struct MHD_Connection *c)
if (NULL != c->daemon->req_cfg.uri_cb.cb)
{
struct MHD_String full_uri;
+ struct MHD_EarlyUriCbData req_data;
full_uri.cstr = c->rq.hdrs.rq_line.rq_tgt;
full_uri.len = c->rq.req_target_len;
- c->rq.client_aware = true;
+ req_data.request = &(c->rq);
+ req_data.request_app_context = NULL;
+ c->rq.app_aware = true;
c->daemon->req_cfg.uri_cb.cb (c->daemon->req_cfg.uri_cb.cls,
- &(c->rq),
- &full_uri);
+ &full_uri,
+ &req_data);
+ c->rq.app_context = req_data.request_app_context;
}
if (NULL != c->rq.hdrs.rq_line.rq_tgt_qmark)
@@ -1286,7 +1290,7 @@ send_redirect_fixed_rq_target (struct MHD_Connection
*restrict c)
(fixed_uri_len > MHD_MAX_FIXED_URI_LEN) ||
(NULL == (b = malloc (fixed_uri_len + 1))) )
{
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR, \
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN, \
"The request has whitespace character is " \
"in the URI and the URI is too large to " \
"send automatic redirect to fixed URI.");
@@ -1350,7 +1354,7 @@ send_redirect_fixed_rq_target (struct MHD_Connection
*restrict c)
return;
}
free (b);
- mhd_STREAM_ABORT (c, mhd_STREAM_ABORT_CLIENT_HTTP_ERR,
+ mhd_STREAM_ABORT (c, mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN,
"The request has whitespace character is in the URI.");
return;
}
@@ -2867,7 +2871,7 @@ mhd_stream_call_app_request_cb (struct MHD_Connection
*restrict c)
path.cstr = c->rq.url;
path.len = c->rq.url_len;
- c->rq.client_aware = true;
+ c->rq.app_aware = true;
a = d->req_cfg.cb (d->req_cfg.cb_cls,
&(c->rq),
&path,
@@ -3181,7 +3185,7 @@ process_request_chunked_body (struct MHD_Connection
*restrict c)
ERR_RSP_REQUEST_CHUNK_TOO_LARGE);
return true;
}
- mhd_assert (c->rq.client_aware);
+ mhd_assert (c->rq.app_aware);
if (mhd_ACTION_POST_PROCESS == c->rq.app_act.head_act.act)
{
@@ -3288,7 +3292,7 @@ process_request_nonchunked_body (struct MHD_Connection
*restrict c)
mhd_assert (! c->rq.have_chunked_upload);
mhd_assert (MHD_SIZE_UNKNOWN != c->rq.cntn.cntn_size);
mhd_assert (c->rq.cntn.recv_size < c->rq.cntn.cntn_size);
- mhd_assert (c->rq.client_aware);
+ mhd_assert (c->rq.app_aware);
if ((c->rq.cntn.cntn_size - c->rq.cntn.recv_size) < c->read_buffer_offset)
cntn_data_ready = (size_t) (c->rq.cntn.cntn_size - c->rq.cntn.recv_size);
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libmicrohttpd] 227/335: -fix typo, (continued)
- [libmicrohttpd] 227/335: -fix typo, gnunet, 2024/07/27
- [libmicrohttpd] 228/335: -fix typo, gnunet, 2024/07/27
- [libmicrohttpd] 207/335: Renamed sys_socket_types.h -> sys_sockets_types.h, gnunet, 2024/07/27
- [libmicrohttpd] 234/335: Follow-up for 631d550d6ed81be0ebd5a06e107868e5153da430, gnunet, 2024/07/27
- [libmicrohttpd] 238/335: More portability, gnunet, 2024/07/27
- [libmicrohttpd] 212/335: configure: check for uintptr_t type, gnunet, 2024/07/27
- [libmicrohttpd] 214/335: configure: added check for various levels of compound literals support, gnunet, 2024/07/27
- [libmicrohttpd] 243/335: Copy-paste fixes, gnunet, 2024/07/27
- [libmicrohttpd] 225/335: Still WIP, gnunet, 2024/07/27
- [libmicrohttpd] 242/335: Fixes, gnunet, 2024/07/27
- [libmicrohttpd] 245/335: WIP-4,
gnunet <=
- [libmicrohttpd] 231/335: WIP more, gnunet, 2024/07/27
- [libmicrohttpd] 235/335: GNU/Linux fixes, gnunet, 2024/07/27
- [libmicrohttpd] 237/335: GNU/Linux fixes-3, gnunet, 2024/07/27
- [libmicrohttpd] 236/335: More GNU/Linux fixes, gnunet, 2024/07/27
- [libmicrohttpd] 251/335: Implemented MHD_daemon_get_info_fixed_sz(), gnunet, 2024/07/27
- [libmicrohttpd] 246/335: WIP-5, gnunet, 2024/07/27
- [libmicrohttpd] 224/335: Minor update, gnunet, 2024/07/27
- [libmicrohttpd] 253/335: fix issues in test logic, gnunet, 2024/07/27
- [libmicrohttpd] 240/335: more example test code, gnunet, 2024/07/27
- [libmicrohttpd] 254/335: Fixed GET parameters parsing, gnunet, 2024/07/27