mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
Re-designed connection closing
This commit is contained in:
@@ -49,16 +49,20 @@
|
||||
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
|
||||
mhd_conn_process_recv_send_data (struct MHD_Connection *restrict c)
|
||||
{
|
||||
/* 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
|
||||
sending (therefore "send-ready" was explicitly checked by sockets polling
|
||||
call). */
|
||||
const bool send_ready_state_known =
|
||||
((mhd_D_IS_USING_EDGE_TRIG (c->daemon)) ||
|
||||
(0 != (MHD_EVENT_LOOP_INFO_WRITE & c->event_loop_info)));
|
||||
(0 != (MHD_EVENT_LOOP_INFO_SEND & c->event_loop_info)));
|
||||
const bool has_sock_err =
|
||||
(0 != (mhd_SOCKET_NET_STATE_ERROR_READY & c->sk_ready));
|
||||
bool data_processed;
|
||||
|
||||
data_processed = false;
|
||||
|
||||
if (0 != (MHD_EVENT_LOOP_INFO_READ & c->event_loop_info))
|
||||
if (0 != (MHD_EVENT_LOOP_INFO_RECV & c->event_loop_info))
|
||||
{
|
||||
bool use_recv;
|
||||
use_recv = (0 != (mhd_SOCKET_NET_STATE_RECV_READY & c->sk_ready));
|
||||
@@ -74,7 +78,7 @@ mhd_conn_process_recv_send_data (struct MHD_Connection *restrict c)
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != (MHD_EVENT_LOOP_INFO_WRITE & c->event_loop_info))
|
||||
if (0 != (MHD_EVENT_LOOP_INFO_SEND & c->event_loop_info))
|
||||
{
|
||||
bool use_send;
|
||||
/* Perform sending if:
|
||||
@@ -107,8 +111,8 @@ mhd_conn_process_recv_send_data (struct MHD_Connection *restrict c)
|
||||
if (! force_close)
|
||||
{
|
||||
/* No need to check value of 'ret' here as closed connection
|
||||
* cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
|
||||
if ( (MHD_EVENT_LOOP_INFO_WRITE == c->event_loop_info) &&
|
||||
* cannot be in MHD_EVENT_LOOP_INFO_SEND state. */
|
||||
if ( (MHD_EVENT_LOOP_INFO_SEND == c->event_loop_info) &&
|
||||
write_ready)
|
||||
{
|
||||
MHD_connection_handle_write (c);
|
||||
@@ -172,7 +176,7 @@ mhd_conn_process_recv_send_data (struct MHD_Connection *restrict c)
|
||||
c->daemon->data_already_pending = true;
|
||||
#ifdef HTTPS_SUPPORT
|
||||
else if ( (c->tls_read_ready) &&
|
||||
(0 != (MHD_EVENT_LOOP_INFO_READ & c->event_loop_info)) )
|
||||
(0 != (MHD_EVENT_LOOP_INFO_RECV & c->event_loop_info)) )
|
||||
c->daemon->data_already_pending = true;
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ connection_set_initial_state (struct MHD_Connection *restrict c)
|
||||
mhd_assert (MHD_CONNECTION_INIT == c->state);
|
||||
|
||||
c->conn_reuse = mhd_CONN_KEEPALIVE_POSSIBLE;
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV;
|
||||
|
||||
memset (&c->rq, 0, sizeof(c->rq));
|
||||
memset (&c->rp, 0, sizeof(c->rp));
|
||||
@@ -203,7 +203,7 @@ new_connection_prepare_ (struct MHD_Daemon *restrict daemon,
|
||||
#endif /* MHD_USE_THREADS */
|
||||
connection->daemon = daemon;
|
||||
connection->connection_timeout_ms = daemon->conns.cfg.timeout;
|
||||
connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
connection->event_loop_info = MHD_EVENT_LOOP_INFO_RECV;
|
||||
if (0 != connection->connection_timeout_ms)
|
||||
connection->last_activity = MHD_monotonic_msec_counter ();
|
||||
|
||||
@@ -918,7 +918,7 @@ mhd_daemon_accept_connection (struct MHD_Daemon *restrict daemon)
|
||||
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
|
||||
mhd_conn_close_final (struct MHD_Connection *restrict c)
|
||||
{
|
||||
mhd_assert (c->dbg.pre_closed);
|
||||
mhd_assert (c->dbg.closing_started);
|
||||
mhd_assert (c->dbg.pre_cleaned);
|
||||
mhd_assert (NULL == c->rp.response);
|
||||
mhd_assert (! c->rq.app_aware);
|
||||
|
||||
+22
-14
@@ -99,7 +99,7 @@ update_conn_net_status (struct MHD_Daemon *restrict d,
|
||||
|
||||
if ((0 !=
|
||||
(((unsigned int) c->sk_ready) & ((unsigned int) c->event_loop_info)
|
||||
& (MHD_EVENT_LOOP_INFO_READ | MHD_EVENT_LOOP_INFO_WRITE)))
|
||||
& (MHD_EVENT_LOOP_INFO_RECV | MHD_EVENT_LOOP_INFO_SEND)))
|
||||
|| err_state)
|
||||
mhd_conn_mark_ready (c, d);
|
||||
else
|
||||
@@ -246,7 +246,10 @@ daemon_process_all_active_conns (struct MHD_Daemon *restrict d)
|
||||
struct MHD_Connection *next;
|
||||
next = mhd_DLINKEDL_GET_NEXT (c, proc_ready); /* The current connection can be closed */
|
||||
if (! mhd_conn_process_recv_send_data (c))
|
||||
{
|
||||
mhd_conn_pre_clean (c);
|
||||
mhd_conn_close_final (c);
|
||||
}
|
||||
|
||||
c = next;
|
||||
}
|
||||
@@ -259,14 +262,19 @@ close_all_daemon_conns (struct MHD_Daemon *d)
|
||||
{
|
||||
struct MHD_Connection *c;
|
||||
|
||||
for (c = mhd_DLINKEDL_GET_LAST (&(d->conns),all_conn);
|
||||
NULL != c;
|
||||
c = mhd_DLINKEDL_GET_LAST (&(d->conns),all_conn))
|
||||
if (! mhd_D_HAS_THR_PER_CONN (d))
|
||||
{
|
||||
mhd_conn_pre_close_d_shutdown (c);
|
||||
mhd_conn_pre_clean (c);
|
||||
mhd_conn_close_final (c);
|
||||
for (c = mhd_DLINKEDL_GET_LAST (&(d->conns),all_conn);
|
||||
NULL != c;
|
||||
c = mhd_DLINKEDL_GET_LAST (&(d->conns),all_conn))
|
||||
{
|
||||
mhd_conn_pre_close_d_shutdown (c);
|
||||
mhd_conn_pre_clean (c);
|
||||
mhd_conn_close_final (c);
|
||||
}
|
||||
}
|
||||
else
|
||||
mhd_assert (0 && "Not implemented yet");
|
||||
}
|
||||
|
||||
|
||||
@@ -370,12 +378,12 @@ select_update_fdsets (struct MHD_Daemon *restrict d,
|
||||
{
|
||||
mhd_assert (MHD_CONNECTION_CLOSED != c->state);
|
||||
|
||||
if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_READ))
|
||||
if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_RECV))
|
||||
fd_set_wrap (c->socket_fd,
|
||||
rfds,
|
||||
&ret,
|
||||
d);
|
||||
if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_WRITE))
|
||||
if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_SEND))
|
||||
fd_set_wrap (c->socket_fd,
|
||||
wfds,
|
||||
&ret,
|
||||
@@ -620,9 +628,9 @@ poll_update_fds (struct MHD_Daemon *restrict d,
|
||||
d->events.data.poll.fds[i_c].fd = c->socket_fd;
|
||||
d->events.data.poll.rel[i_c].connection = c;
|
||||
events = 0;
|
||||
if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_READ))
|
||||
if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_RECV))
|
||||
events |= MHD_POLL_IN;
|
||||
if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_WRITE))
|
||||
if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_SEND))
|
||||
events |= MHD_POLL_OUT;
|
||||
|
||||
d->events.data.poll.fds[i_c].events = (short) events;
|
||||
@@ -736,20 +744,20 @@ poll_update_statuses_from_fds (struct MHD_Daemon *restrict d,
|
||||
if (0 != (revents & POLLHUP))
|
||||
{ /* This can be a disconnect OR remote side set SHUT_WR */
|
||||
recv_ready = true; /* Check the socket by reading */
|
||||
if (0 == (c->event_loop_info & MHD_EVENT_LOOP_INFO_READ))
|
||||
if (0 == (c->event_loop_info & MHD_EVENT_LOOP_INFO_RECV))
|
||||
err_state = true; /* The socket will not be checked by reading, the only way to avoid spinning */
|
||||
}
|
||||
#endif
|
||||
if (0 != (revents & (MHD_POLLPRI | MHD_POLLRDBAND)))
|
||||
{ /* Statuses were not requested, but returned */
|
||||
if (! recv_ready ||
|
||||
(0 == (c->event_loop_info & MHD_EVENT_LOOP_INFO_READ)))
|
||||
(0 == (c->event_loop_info & MHD_EVENT_LOOP_INFO_RECV)))
|
||||
err_state = true; /* The socket will not be read, the only way to avoid spinning */
|
||||
}
|
||||
if (0 != (revents & MHD_POLLWRBAND))
|
||||
{ /* Status was not requested, but returned */
|
||||
if (! send_ready ||
|
||||
(0 == (c->event_loop_info & MHD_EVENT_LOOP_INFO_WRITE)))
|
||||
(0 == (c->event_loop_info & MHD_EVENT_LOOP_INFO_SEND)))
|
||||
err_state = true; /* The socket will not be written, the only way to avoid spinning */
|
||||
}
|
||||
|
||||
|
||||
@@ -79,13 +79,13 @@ enum MHD_FIXED_FLAGS_ENUM_ MHD_ConnectionEventLoopInfo
|
||||
* We are waiting to be able to read.
|
||||
* The same value as #mhd_SOCKET_NET_STATE_RECV_READY
|
||||
*/
|
||||
MHD_EVENT_LOOP_INFO_READ = 1 << 0
|
||||
MHD_EVENT_LOOP_INFO_RECV = 1 << 0
|
||||
,
|
||||
/**
|
||||
* We are waiting to be able to write.
|
||||
* The same value as #mhd_SOCKET_NET_STATE_SEND_READY
|
||||
*/
|
||||
MHD_EVENT_LOOP_INFO_WRITE = 1 << 1
|
||||
MHD_EVENT_LOOP_INFO_SEND = 1 << 1
|
||||
,
|
||||
/**
|
||||
* We are waiting for the application to provide data.
|
||||
@@ -99,7 +99,7 @@ enum MHD_FIXED_FLAGS_ENUM_ MHD_ConnectionEventLoopInfo
|
||||
};
|
||||
|
||||
#define MHD_EVENT_LOOP_INFO_PROCESS_READ \
|
||||
(MHD_EVENT_LOOP_INFO_READ | MHD_EVENT_LOOP_INFO_PROCESS)
|
||||
(MHD_EVENT_LOOP_INFO_RECV | MHD_EVENT_LOOP_INFO_PROCESS)
|
||||
|
||||
|
||||
/**
|
||||
@@ -343,7 +343,7 @@ enum MHD_FIXED_ENUM_ MHD_CONNECTION_STATE
|
||||
|
||||
struct mhd_ConnDebugData
|
||||
{
|
||||
bool pre_closed;
|
||||
bool closing_started;
|
||||
bool pre_cleaned;
|
||||
};
|
||||
|
||||
|
||||
+13
-14
@@ -500,11 +500,11 @@ mhd_stream_finish_req_serving (struct MHD_Connection *restrict c,
|
||||
/* Next function will notify client and set connection
|
||||
* state to "PRE-CLOSING" */
|
||||
/* Later response and memory pool will be destroyed */
|
||||
mhd_conn_pre_close (c,
|
||||
c->stop_with_error ?
|
||||
mhd_CONN_CLOSE_ERR_REPLY_SENT :
|
||||
mhd_CONN_CLOSE_HTTP_COMPLETED,
|
||||
NULL);
|
||||
mhd_conn_start_closing (c,
|
||||
c->stop_with_error ?
|
||||
mhd_CONN_CLOSE_ERR_REPLY_SENT :
|
||||
mhd_CONN_CLOSE_HTTP_COMPLETED,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -539,7 +539,7 @@ mhd_stream_finish_req_serving (struct MHD_Connection *restrict c,
|
||||
c->state = MHD_CONNECTION_INIT;
|
||||
c->event_loop_info =
|
||||
(0 == c->read_buffer_offset) ?
|
||||
MHD_EVENT_LOOP_INFO_READ : MHD_EVENT_LOOP_INFO_PROCESS;
|
||||
MHD_EVENT_LOOP_INFO_RECV : MHD_EVENT_LOOP_INFO_PROCESS;
|
||||
|
||||
memset (&c->rq, 0, sizeof(c->rq));
|
||||
|
||||
@@ -572,7 +572,7 @@ mhd_stream_finish_req_serving (struct MHD_Connection *restrict c,
|
||||
|
||||
|
||||
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
|
||||
mhd_stream_check_timedout (struct MHD_Connection *restrict c)
|
||||
mhd_stream_is_timeout_expired (struct MHD_Connection *restrict c)
|
||||
{
|
||||
const uint_fast64_t timeout = c->connection_timeout_ms;
|
||||
uint_fast64_t now;
|
||||
@@ -649,9 +649,9 @@ mhd_stream_update_activity_mark (struct MHD_Connection *restrict c)
|
||||
|
||||
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)
|
||||
mhd_conn_start_closing (struct MHD_Connection *restrict c,
|
||||
enum mhd_ConnCloseReason reason,
|
||||
const char *log_msg)
|
||||
{
|
||||
bool close_hard;
|
||||
enum MHD_RequestEndedCode end_code;
|
||||
@@ -781,7 +781,7 @@ mhd_conn_pre_close (struct MHD_Connection *restrict c,
|
||||
{
|
||||
/* 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->state = MHD_CONNECTION_PRE_CLOSING;
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
|
||||
}
|
||||
else
|
||||
@@ -832,7 +832,7 @@ mhd_conn_pre_close (struct MHD_Connection *restrict c,
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
c->dbg.pre_closed = true;
|
||||
c->dbg.closing_started = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -843,7 +843,7 @@ mhd_conn_pre_clean (struct MHD_Connection *restrict c)
|
||||
{
|
||||
// TODO: support suspended connections
|
||||
|
||||
mhd_assert (c->dbg.pre_closed);
|
||||
mhd_assert (c->dbg.closing_started);
|
||||
mhd_assert (! c->dbg.pre_cleaned);
|
||||
|
||||
mhd_conn_mark_unready (c, c->daemon);
|
||||
@@ -857,7 +857,6 @@ mhd_conn_pre_clean (struct MHD_Connection *restrict c)
|
||||
|
||||
if (NULL != c->rq.cntn.lbuf.data)
|
||||
mhd_daemon_free_lbuf (c->daemon, &(c->rq.cntn.lbuf));
|
||||
c->rq.cntn.lbuf.data = NULL;
|
||||
if (NULL != c->rp.response)
|
||||
mhd_response_dec_use_count (c->rp.response);
|
||||
c->rp.response = NULL;
|
||||
|
||||
+30
-16
@@ -135,13 +135,14 @@ mhd_stream_update_activity_mark (struct MHD_Connection *restrict c)
|
||||
MHD_FN_PAR_NONNULL_ALL_;
|
||||
|
||||
/**
|
||||
* Update last activity mark to the current time..
|
||||
* Check whether connection's timeout is expired.
|
||||
* @param c the connection to update
|
||||
* @return 'true' if connection has not been timed out,
|
||||
* @return 'true' if connection timeout expired and connection needs to be
|
||||
* closed,
|
||||
* 'false' otherwise
|
||||
*/
|
||||
MHD_INTERNAL bool
|
||||
mhd_stream_check_timedout (struct MHD_Connection *restrict c)
|
||||
mhd_stream_is_timeout_expired (struct MHD_Connection *restrict c)
|
||||
MHD_FN_PAR_NONNULL_ALL_;
|
||||
|
||||
/**
|
||||
@@ -234,24 +235,35 @@ enum mhd_ConnCloseReason
|
||||
|
||||
|
||||
/**
|
||||
* Prepare connection for closing.
|
||||
* Start closing of the connection.
|
||||
*
|
||||
* Application is notified about connection closing (if callback is set),
|
||||
* the socket is shut downed for sending and the connection is marked for
|
||||
* closing. The real resource deallocation and socket closing are performed
|
||||
* later.
|
||||
*
|
||||
* As no resources are deallocated by this function, it is safe to call it
|
||||
* "deep" in the code. Upon return all connection resources still could be used,
|
||||
* pointers can be dereferenced etc. The real cleanup is performed when
|
||||
* connection state is processed by #mhd_conn_process_data().
|
||||
*
|
||||
* @param c the connection for pre-closing
|
||||
* @param reason the reason for closing
|
||||
* @param log_msg the message for the log
|
||||
*/
|
||||
MHD_INTERNAL void
|
||||
mhd_conn_pre_close (struct MHD_Connection *restrict c,
|
||||
enum mhd_ConnCloseReason reason,
|
||||
const char *log_msg)
|
||||
mhd_conn_start_closing (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_conn_pre_close ((c),(r),(m)))
|
||||
# define mhd_STREAM_ABORT(c,r,m) (mhd_conn_start_closing ((c),(r),(m)))
|
||||
#else /* ! HAVE_LOG_FUNCTIONALITY */
|
||||
# define mhd_STREAM_ABORT(c,r,m) (mhd_conn_pre_close ((c),(r),NULL))
|
||||
# define mhd_STREAM_ABORT(c,r,m) (mhd_conn_start_closing ((c),(r),NULL))
|
||||
#endif /* ! HAVE_LOG_FUNCTIONALITY */
|
||||
|
||||
/**
|
||||
@@ -260,7 +272,7 @@ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3);
|
||||
* @param c the connection for pre-closing
|
||||
*/
|
||||
#define mhd_conn_pre_close_app_abort(c) \
|
||||
mhd_conn_pre_close ((c), mhd_CONN_CLOSE_APP_ABORTED, NULL)
|
||||
mhd_conn_start_closing ((c), mhd_CONN_CLOSE_APP_ABORTED, NULL)
|
||||
|
||||
/**
|
||||
* Perform initial clean-up and mark for closing.
|
||||
@@ -268,7 +280,7 @@ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3);
|
||||
* @param c the connection for pre-closing
|
||||
*/
|
||||
#define mhd_conn_pre_close_skt_err(c) \
|
||||
mhd_conn_pre_close ((c), mhd_CONN_CLOSE_SOCKET_ERR, NULL)
|
||||
mhd_conn_start_closing ((c), mhd_CONN_CLOSE_SOCKET_ERR, NULL)
|
||||
|
||||
/**
|
||||
* Perform initial clean-up and mark for closing.
|
||||
@@ -276,7 +288,7 @@ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3);
|
||||
* @param c the connection for pre-closing
|
||||
*/
|
||||
#define mhd_conn_pre_close_req_finished(c) \
|
||||
mhd_conn_pre_close ((c), mhd_CONN_CLOSE_HTTP_COMPLETED, NULL)
|
||||
mhd_conn_start_closing ((c), mhd_CONN_CLOSE_HTTP_COMPLETED, NULL)
|
||||
|
||||
/**
|
||||
* Perform initial clean-up and mark for closing.
|
||||
@@ -284,7 +296,7 @@ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3);
|
||||
* @param c the connection for pre-closing
|
||||
*/
|
||||
#define mhd_conn_pre_close_timedout(c) \
|
||||
mhd_conn_pre_close ((c), mhd_CONN_CLOSE_TIMEDOUT, NULL)
|
||||
mhd_conn_start_closing ((c), mhd_CONN_CLOSE_TIMEDOUT, NULL)
|
||||
|
||||
/**
|
||||
* Perform initial clean-up and mark for closing.
|
||||
@@ -292,11 +304,13 @@ MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3);
|
||||
* @param c the connection for pre-closing
|
||||
*/
|
||||
#define mhd_conn_pre_close_d_shutdown(c) \
|
||||
mhd_conn_pre_close ((c), mhd_CONN_CLOSE_DAEMON_SHUTDOWN, NULL)
|
||||
mhd_conn_start_closing ((c), mhd_CONN_CLOSE_DAEMON_SHUTDOWN, NULL)
|
||||
|
||||
/**
|
||||
* Perform initial connection cleanup.
|
||||
* The connection must be prepared for closing.
|
||||
* Perform initial connection cleanup after start of the connection closing
|
||||
* procedure.
|
||||
* This cleanup should be performed in the same thread that processes
|
||||
* the connection recv/send/data.
|
||||
* @param c the connection for pre-closing
|
||||
*/
|
||||
MHD_INTERNAL void
|
||||
|
||||
@@ -3760,7 +3760,7 @@ mhd_stream_check_and_grow_read_buffer_space (struct MHD_Connection *restrict c)
|
||||
*/
|
||||
bool rbuff_grow_required;
|
||||
|
||||
mhd_assert (0 != (MHD_EVENT_LOOP_INFO_READ & c->event_loop_info));
|
||||
mhd_assert (0 != (MHD_EVENT_LOOP_INFO_RECV & c->event_loop_info));
|
||||
mhd_assert (! c->discard_request);
|
||||
|
||||
rbuff_grow_required = (c->read_buffer_offset == c->read_buffer_size);
|
||||
|
||||
@@ -168,7 +168,7 @@ MHD_FN_PAR_NONNULL_ (1);
|
||||
*
|
||||
* @param c the connection to process
|
||||
* @return true if advanced to the next state,
|
||||
* false if more data needed or connection is suspended or aborted
|
||||
* false if more data needed or connection is suspended
|
||||
*/
|
||||
MHD_INTERNAL bool
|
||||
mhd_stream_process_request_body (struct MHD_Connection *restrict c)
|
||||
@@ -179,7 +179,7 @@ MHD_FN_PAR_NONNULL_ALL_;
|
||||
* Advance to the next state, handle errors.
|
||||
* @param c the connection to process
|
||||
* @return true if advanced to the next state,
|
||||
* false if connection is suspended or aborted
|
||||
* false if connection is suspended
|
||||
*/
|
||||
MHD_INTERNAL bool
|
||||
mhd_stream_call_app_final_upload_cb (struct MHD_Connection *restrict c)
|
||||
@@ -190,7 +190,7 @@ MHD_FN_PAR_NONNULL_ALL_;
|
||||
* Advance to the next state, handle errors.
|
||||
* @param c the connection to process
|
||||
* @return true if advanced to the next state,
|
||||
* false if connection is suspended or aborted
|
||||
* false if connection is suspended
|
||||
*/
|
||||
MHD_INTERNAL bool
|
||||
mhd_stream_process_req_recv_finished (struct MHD_Connection *restrict c)
|
||||
|
||||
+139
-140
@@ -76,127 +76,128 @@ update_active_state (struct MHD_Connection *restrict c)
|
||||
}
|
||||
}
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
while (1)
|
||||
switch (c->state)
|
||||
{
|
||||
switch (c->state)
|
||||
{
|
||||
case MHD_CONNECTION_INIT:
|
||||
case MHD_CONNECTION_REQ_LINE_RECEIVING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
break;
|
||||
case MHD_CONNECTION_REQ_LINE_RECEIVED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_REQ_HEADERS_RECEIVING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
break;
|
||||
case MHD_CONNECTION_HEADERS_RECEIVED:
|
||||
case MHD_CONNECTION_HEADERS_PROCESSED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_CONTINUE_SENDING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_CONNECTION_BODY_RECEIVING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
break;
|
||||
case MHD_CONNECTION_BODY_RECEIVED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_FOOTERS_RECEIVING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
break;
|
||||
case MHD_CONNECTION_FOOTERS_RECEIVED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_FULL_REQ_RECEIVED:
|
||||
mhd_assert (0 && "Should not be possible");
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS;
|
||||
break;
|
||||
case MHD_CONNECTION_REQ_RECV_FINISHED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_START_REPLY:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_HEADERS_SENDING:
|
||||
/* headers in buffer, keep writing */
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_CONNECTION_HEADERS_SENT:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_UNCHUNKED_BODY_UNREADY:
|
||||
mhd_assert (0 && "Should not be possible");
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS;
|
||||
break;
|
||||
case MHD_CONNECTION_UNCHUNKED_BODY_READY:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
|
||||
mhd_assert (0 && "Should not be possible");
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS;
|
||||
break;
|
||||
case MHD_CONNECTION_CHUNKED_BODY_READY:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_CONNECTION_CHUNKED_BODY_SENT:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_FOOTERS_SENDING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
|
||||
break;
|
||||
case MHD_CONNECTION_FULL_REPLY_SENT:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_CLOSED:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
|
||||
return false; /* do nothing, not even reading */
|
||||
case MHD_CONNECTION_INIT:
|
||||
case MHD_CONNECTION_REQ_LINE_RECEIVING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV;
|
||||
break;
|
||||
case MHD_CONNECTION_REQ_LINE_RECEIVED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_REQ_HEADERS_RECEIVING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV;
|
||||
break;
|
||||
case MHD_CONNECTION_HEADERS_RECEIVED:
|
||||
case MHD_CONNECTION_HEADERS_PROCESSED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_CONTINUE_SENDING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND;
|
||||
break;
|
||||
case MHD_CONNECTION_BODY_RECEIVING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV;
|
||||
break;
|
||||
case MHD_CONNECTION_BODY_RECEIVED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_FOOTERS_RECEIVING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV;
|
||||
break;
|
||||
case MHD_CONNECTION_FOOTERS_RECEIVED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_FULL_REQ_RECEIVED:
|
||||
mhd_assert (0 && "Should not be possible");
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS;
|
||||
break;
|
||||
case MHD_CONNECTION_REQ_RECV_FINISHED:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_START_REPLY:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_HEADERS_SENDING:
|
||||
/* headers in buffer, keep writing */
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND;
|
||||
break;
|
||||
case MHD_CONNECTION_HEADERS_SENT:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_UNCHUNKED_BODY_UNREADY:
|
||||
mhd_assert (0 && "Should not be possible");
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS;
|
||||
break;
|
||||
case MHD_CONNECTION_UNCHUNKED_BODY_READY:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND;
|
||||
break;
|
||||
case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
|
||||
mhd_assert (0 && "Should not be possible");
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS;
|
||||
break;
|
||||
case MHD_CONNECTION_CHUNKED_BODY_READY:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND;
|
||||
break;
|
||||
case MHD_CONNECTION_CHUNKED_BODY_SENT:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_FOOTERS_SENDING:
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND;
|
||||
break;
|
||||
case MHD_CONNECTION_FULL_REPLY_SENT:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
case MHD_CONNECTION_PRE_CLOSING:
|
||||
mhd_assert (0 && "Should be unreachable");
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
|
||||
break;
|
||||
case MHD_CONNECTION_CLOSED:
|
||||
mhd_assert (0 && "Should be unreachable");
|
||||
c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
|
||||
return false; /* do nothing, not even reading */
|
||||
#if 0 // def UPGRADE_SUPPORT // TODO: Upgrade support
|
||||
case MHD_CONNECTION_UPGRADE:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
case MHD_CONNECTION_UPGRADE:
|
||||
mhd_assert (0);
|
||||
break;
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
default:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
}
|
||||
|
||||
if (0 != (MHD_EVENT_LOOP_INFO_READ & c->event_loop_info))
|
||||
{
|
||||
/* Check whether the space is available to receive data */
|
||||
if (! mhd_stream_check_and_grow_read_buffer_space (c))
|
||||
{
|
||||
mhd_assert (c->discard_request);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Current MHD design assumes that data must be always processes when
|
||||
* available. If it is not possible, connection must be suspended. */
|
||||
mhd_assert (MHD_EVENT_LOOP_INFO_PROCESS != c->event_loop_info);
|
||||
|
||||
/* Sockets errors must be already handled */
|
||||
mhd_assert (0 == (c->sk_ready & mhd_SOCKET_NET_STATE_ERROR_READY));
|
||||
|
||||
if (0 !=
|
||||
(((unsigned int) c->sk_ready) & ((unsigned int) c->event_loop_info)
|
||||
& (MHD_EVENT_LOOP_INFO_READ | MHD_EVENT_LOOP_INFO_WRITE)))
|
||||
mhd_conn_mark_ready (c, c->daemon);
|
||||
else
|
||||
mhd_conn_mark_unready (c, c->daemon);
|
||||
|
||||
break; /* Everything was processed. */
|
||||
default:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
}
|
||||
|
||||
if (0 != (MHD_EVENT_LOOP_INFO_RECV & c->event_loop_info))
|
||||
{
|
||||
/* Check whether the space is available to receive data */
|
||||
if (! mhd_stream_check_and_grow_read_buffer_space (c))
|
||||
{
|
||||
mhd_assert (c->discard_request);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Current MHD design assumes that data must be always processes when
|
||||
* available. If it is not possible, connection must be suspended. */
|
||||
mhd_assert (MHD_EVENT_LOOP_INFO_PROCESS != c->event_loop_info);
|
||||
|
||||
/* Sockets errors must be already handled */
|
||||
mhd_assert (0 == (c->sk_ready & mhd_SOCKET_NET_STATE_ERROR_READY));
|
||||
|
||||
if (0 !=
|
||||
(((unsigned int) c->sk_ready) & ((unsigned int) c->event_loop_info)
|
||||
& (MHD_EVENT_LOOP_INFO_RECV | MHD_EVENT_LOOP_INFO_SEND)))
|
||||
mhd_conn_mark_ready (c, c->daemon);
|
||||
else
|
||||
mhd_conn_mark_unready (c, c->daemon);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -214,11 +215,11 @@ mhd_conn_process_data (struct MHD_Connection *restrict c)
|
||||
{
|
||||
if (0 == c->read_buffer_offset)
|
||||
{ /* Read buffer is empty, connection state is actual */
|
||||
mhd_conn_pre_close (c,
|
||||
(MHD_CONNECTION_INIT == c->state) ?
|
||||
mhd_CONN_CLOSE_HTTP_COMPLETED :
|
||||
mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY,
|
||||
NULL);
|
||||
mhd_conn_start_closing (c,
|
||||
(MHD_CONNECTION_INIT == c->state) ?
|
||||
mhd_CONN_CLOSE_HTTP_COMPLETED :
|
||||
mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY,
|
||||
NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -459,14 +460,15 @@ mhd_conn_process_data (struct MHD_Connection *restrict c)
|
||||
&& ! c->sk_rmt_shut_wr);
|
||||
continue;
|
||||
case MHD_CONNECTION_PRE_CLOSING:
|
||||
mhd_conn_pre_clean (c);
|
||||
break;
|
||||
case MHD_CONNECTION_CLOSED:
|
||||
break;
|
||||
return false;
|
||||
#if 0 // def UPGRADE_SUPPORT
|
||||
case MHD_CONNECTION_UPGRADE:
|
||||
return MHD_YES; /* keep open */
|
||||
#endif /* UPGRADE_SUPPORT */
|
||||
case MHD_CONNECTION_CLOSED:
|
||||
mhd_assert (0 && "Should be unreachable");
|
||||
MHD_UNREACHABLE_;
|
||||
break;
|
||||
default:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
@@ -475,10 +477,13 @@ mhd_conn_process_data (struct MHD_Connection *restrict c)
|
||||
break;
|
||||
}
|
||||
|
||||
mhd_assert (MHD_CONNECTION_PRE_CLOSING != c->state);
|
||||
mhd_assert (MHD_CONNECTION_CLOSED != c->state);
|
||||
|
||||
if (MHD_CONNECTION_CLOSED == c->state)
|
||||
if (MHD_CONNECTION_PRE_CLOSING == c->state)
|
||||
{
|
||||
mhd_assert (0 && "Pre-closing should be already caught in the loop");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c->suspended)
|
||||
{
|
||||
@@ -489,28 +494,22 @@ mhd_conn_process_data (struct MHD_Connection *restrict c)
|
||||
|
||||
if ((c->sk_rmt_shut_wr) && (MHD_CONNECTION_START_REPLY > c->state))
|
||||
{
|
||||
mhd_conn_pre_close (c,
|
||||
(MHD_CONNECTION_INIT == c->state) ?
|
||||
mhd_CONN_CLOSE_HTTP_COMPLETED :
|
||||
mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY,
|
||||
NULL);
|
||||
mhd_conn_pre_clean (c);
|
||||
mhd_conn_start_closing (c,
|
||||
(MHD_CONNECTION_INIT == c->state) ?
|
||||
mhd_CONN_CLOSE_HTTP_COMPLETED :
|
||||
mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY,
|
||||
NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mhd_stream_check_timedout (c)) // TODO: centralise timeout checks
|
||||
if (mhd_stream_is_timeout_expired (c)) // TODO: centralise timeout checks
|
||||
{
|
||||
mhd_conn_pre_close_timedout (c);
|
||||
mhd_conn_pre_clean (c);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! update_active_state (c))
|
||||
{
|
||||
mhd_conn_pre_clean (c);
|
||||
return false;
|
||||
}
|
||||
/* MHD_connection_update_event_loop_info (c);*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user