Re-designed connection closing

This commit is contained in:
Evgeny Grin (Karlson2k)
2024-08-21 13:21:26 +02:00
parent d867244c89
commit 2b78707ade
9 changed files with 225 additions and 201 deletions
+10 -6
View File
@@ -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 */
}
+3 -3
View File
@@ -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
View File
@@ -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 */
}
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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
View File
@@ -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;
}