summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2019-02-04 21:50:53 -0500
committerGlenn Strauss <gstrauss@gluelogic.com>2019-02-04 21:50:53 -0500
commit21afabb8f8f16eddf9e660513b072122ca0616e9 (patch)
treef6e2e40d5075742f2febcfaf6f08ffb4d3de5c8d
parent9e55fd72b5a41cfa3f0174ef7bfe3e37e345d239 (diff)
downloadlighttpd-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.c254
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",