diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2019-02-04 21:50:53 -0500 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2019-02-04 21:50:53 -0500 |
commit | 21afabb8f8f16eddf9e660513b072122ca0616e9 (patch) | |
tree | f6e2e40d5075742f2febcfaf6f08ffb4d3de5c8d | |
parent | 9e55fd72b5a41cfa3f0174ef7bfe3e37e345d239 (diff) | |
download | lighttpd-git-21afabb8f8f16eddf9e660513b072122ca0616e9.tar.gz |
[core] helper funcs for connection_state_machine()
carve connection_state_machine() into separate functions per state
-rw-r--r-- | src/connections.c | 254 |
1 files changed, 122 insertions, 132 deletions
diff --git a/src/connections.c b/src/connections.c index 0fde03ca..821f77c0 100644 --- a/src/connections.c +++ b/src/connections.c @@ -106,6 +106,9 @@ static int connection_close(server *srv, connection *con) { plugins_call_handle_connection_close(srv, con); + con->request_count = 0; + chunkqueue_reset(con->read_queue); + fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd); fdevent_unregister(srv->ev, con->fd); #ifdef __WIN32 @@ -477,6 +480,52 @@ static int connection_handle_write(server *srv, connection *con) { return 0; } +static void connection_handle_write_state(server *srv, connection *con) { + do { + /* only try to write if we have something in the queue */ + if (!chunkqueue_is_empty(con->write_queue)) { + if (con->is_writable) { + if (-1 == connection_handle_write(srv, con)) { + log_error_write(srv, __FILE__, __LINE__, "ds", + con->fd, "handle write failed."); + connection_set_state(srv, con, CON_STATE_ERROR); + break; + } + if (con->state != CON_STATE_WRITE) break; + } + } else if (con->file_finished) { + connection_set_state(srv, con, CON_STATE_RESPONSE_END); + break; + } + + if (con->mode != DIRECT && !con->file_finished) { + int r = plugins_call_handle_subrequest(srv, con); + switch(r) { + case HANDLER_WAIT_FOR_EVENT: + case HANDLER_FINISHED: + case HANDLER_GO_ON: + break; + case HANDLER_WAIT_FOR_FD: + srv->want_fds++; + fdwaitqueue_append(srv, con); + break; + case HANDLER_COMEBACK: + default: + log_error_write(srv, __FILE__, __LINE__, "sdd", + "unexpected subrequest handler ret-value:", + con->fd, r); + /* fall through */ + case HANDLER_ERROR: + connection_set_state(srv, con, CON_STATE_ERROR); + break; + } + } + } while (con->state == CON_STATE_WRITE + && (!chunkqueue_is_empty(con->write_queue) + ? con->is_writable + : con->file_finished)); +} + __attribute_cold__ @@ -1102,66 +1151,9 @@ connection *connection_accepted(server *srv, server_socket *srv_socket, sock_add } -int connection_state_machine(server *srv, connection *con) { - int done = 0, r; - - if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "state at start", - con->fd, - connection_get_state(con->state)); - } - - while (done == 0) { - size_t ostate = con->state; - - if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); - } - - switch (con->state) { - case CON_STATE_REQUEST_START: /* transient */ - con->request_start = srv->cur_ts; - con->read_idle_ts = srv->cur_ts; - if (con->conf.high_precision_timestamps) - log_clock_gettime_realtime(&con->request_start_hp); - - con->request_count++; - con->loops_per_request = 0; - - connection_set_state(srv, con, CON_STATE_READ); - - break; - case CON_STATE_REQUEST_END: /* transient */ - buffer_clear(con->uri.authority); - buffer_reset(con->uri.path); - buffer_reset(con->uri.query); - buffer_reset(con->request.orig_uri); - - if (http_request_parse(srv, con)) { - /* we have to read some data from the POST request */ - - connection_set_state(srv, con, CON_STATE_READ_POST); - - break; - } - - connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - - break; - case CON_STATE_READ_POST: - case CON_STATE_HANDLE_REQUEST: - /* - * the request is parsed - * - * decided what to do with the request - * - - * - * - */ - - switch (r = http_response_prepare(srv, con)) { +static int connection_handle_request(server *srv, connection *con) { + int r = http_response_prepare(srv, con); + switch (r) { case HANDLER_WAIT_FOR_EVENT: if (!con->file_finished && (!con->file_started || 0 == con->conf.stream_response_body)) { break; /* come back here */ @@ -1236,8 +1228,7 @@ int connection_state_machine(server *srv, connection *con) { connection_handle_errdoc_init(con); con->http_status = 0; /*(after connection_handle_errdoc_init())*/ - done = -1; - break; + return 1; } } } @@ -1252,8 +1243,7 @@ int connection_state_machine(server *srv, connection *con) { break; case HANDLER_COMEBACK: - done = -1; - break; + return 1; case HANDLER_ERROR: /* something went wrong */ connection_set_state(srv, con, CON_STATE_ERROR); @@ -1263,95 +1253,95 @@ int connection_state_machine(server *srv, connection *con) { break; } - if (con->state == CON_STATE_HANDLE_REQUEST && ostate == CON_STATE_READ_POST) { + return 0; +} + + +int connection_state_machine(server *srv, connection *con) { + connection_state_t ostate; + int r; + + if (srv->srvconf.log_state_handling) { + log_error_write(srv, __FILE__, __LINE__, "sds", + "state at enter", + con->fd, + connection_get_state(con->state)); + } + + do { + if (srv->srvconf.log_state_handling) { + log_error_write(srv, __FILE__, __LINE__, "sds", + "state for fd", con->fd, connection_get_state(con->state)); + } + + switch ((ostate = con->state)) { + case CON_STATE_REQUEST_START: /* transient */ + con->request_start = srv->cur_ts; + con->read_idle_ts = srv->cur_ts; + if (con->conf.high_precision_timestamps) + log_clock_gettime_realtime(&con->request_start_hp); + + con->request_count++; + con->loops_per_request = 0; + + connection_set_state(srv, con, CON_STATE_READ); + /* fall through */ + case CON_STATE_READ: + connection_handle_read_state(srv, con); + if (con->state != CON_STATE_REQUEST_END) break; + /* fall through */ + case CON_STATE_REQUEST_END: /* transient */ + buffer_clear(con->uri.authority); + buffer_reset(con->uri.path); + buffer_reset(con->uri.query); + buffer_reset(con->request.orig_uri); + + ostate = http_request_parse(srv, con) + ? CON_STATE_READ_POST + : CON_STATE_HANDLE_REQUEST; + connection_set_state(srv, con, ostate); + /* fall through */ + case CON_STATE_READ_POST: + case CON_STATE_HANDLE_REQUEST: + if (connection_handle_request(srv, con)) { + /* redo loop; will not match con->state */ + ostate = CON_STATE_CONNECT; + break; + } + + if (con->state == CON_STATE_HANDLE_REQUEST + && ostate == CON_STATE_READ_POST) { ostate = CON_STATE_HANDLE_REQUEST; } - break; - case CON_STATE_RESPONSE_START: - /* - * the decision is done - * - create the HTTP-Response-Header - * - */ + if (con->state != CON_STATE_RESPONSE_START) break; + /* fall through */ + case CON_STATE_RESPONSE_START: /* transient */ if (-1 == connection_handle_write_prepare(srv, con)) { connection_set_state(srv, con, CON_STATE_ERROR); - break; } - connection_set_state(srv, con, CON_STATE_WRITE); - break; + /* fall through */ + case CON_STATE_WRITE: + connection_handle_write_state(srv, con); + if (con->state != CON_STATE_RESPONSE_END) break; + /* fall through */ case CON_STATE_RESPONSE_END: /* transient */ case CON_STATE_ERROR: /* transient */ connection_handle_response_end_state(srv, con); break; - case CON_STATE_CONNECT: - chunkqueue_reset(con->read_queue); - - con->request_count = 0; - - break; case CON_STATE_CLOSE: connection_handle_close_state(srv, con); break; - case CON_STATE_READ: - connection_handle_read_state(srv, con); - break; - case CON_STATE_WRITE: - do { - /* only try to write if we have something in the queue */ - if (!chunkqueue_is_empty(con->write_queue)) { - if (con->is_writable) { - if (-1 == connection_handle_write(srv, con)) { - log_error_write(srv, __FILE__, __LINE__, "ds", - con->fd, - "handle write failed."); - connection_set_state(srv, con, CON_STATE_ERROR); - break; - } - if (con->state != CON_STATE_WRITE) break; - } - } else if (con->file_finished) { - connection_set_state(srv, con, CON_STATE_RESPONSE_END); - break; - } - - if (con->mode != DIRECT && !con->file_finished) { - switch(r = plugins_call_handle_subrequest(srv, con)) { - case HANDLER_WAIT_FOR_EVENT: - case HANDLER_FINISHED: - case HANDLER_GO_ON: - break; - case HANDLER_WAIT_FOR_FD: - srv->want_fds++; - fdwaitqueue_append(srv, con); - break; - case HANDLER_COMEBACK: - default: - log_error_write(srv, __FILE__, __LINE__, "sdd", "unexpected subrequest handler ret-value: ", con->fd, r); - /* fall through */ - case HANDLER_ERROR: - connection_set_state(srv, con, CON_STATE_ERROR); - break; - } - } - } while (con->state == CON_STATE_WRITE && (!chunkqueue_is_empty(con->write_queue) ? con->is_writable : con->file_finished)); - + case CON_STATE_CONNECT: break; default: log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown state:", con->fd, con->state); - break; } - - if (done == -1) { - done = 0; - } else if (ostate == con->state) { - done = 1; - } - } + } while (ostate != con->state); if (srv->srvconf.log_state_handling) { log_error_write(srv, __FILE__, __LINE__, "sds", |