From d9cc24b8e6aadda99ccfb26d3f8dfde0d3352716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Mon, 10 Jan 2011 20:00:44 +0100 Subject: [PATCH] [core]: fix connection/vrequest callbacks to return FALSE after they got reset, so handling stops --- include/lighttpd/virtualrequest.h | 2 +- src/main/connection.c | 52 +++++++++-------- src/main/subrequest_lua.c | 26 +++++---- src/main/virtualrequest.c | 95 ++++++++++--------------------- 4 files changed, 73 insertions(+), 102 deletions(-) diff --git a/include/lighttpd/virtualrequest.h b/include/lighttpd/virtualrequest.h index d488eaa..9154fe9 100644 --- a/include/lighttpd/virtualrequest.h +++ b/include/lighttpd/virtualrequest.h @@ -36,7 +36,7 @@ typedef enum { typedef liHandlerResult (*liFilterHandlerCB)(liVRequest *vr, liFilter *f); typedef void (*liFilterFreeCB)(liVRequest *vr, liFilter *f); -typedef liHandlerResult (*liVRequestHandlerCB)(liVRequest *vr); +typedef G_GNUC_WARN_UNUSED_RESULT gboolean (*liVRequestHandlerCB)(liVRequest *vr); typedef liHandlerResult (*liVRequestPluginHandlerCB)(liVRequest *vr, liPlugin *p); typedef gboolean (*liVRequestCheckIOCB)(liVRequest *vr); diff --git a/src/main/connection.c b/src/main/connection.c index 3033522..240a89c 100644 --- a/src/main/connection.c +++ b/src/main/connection.c @@ -3,7 +3,7 @@ #include static void li_connection_reset_keep_alive(liConnection *con); -static void li_connection_internal_error(liConnection *con); +static G_GNUC_WARN_UNUSED_RESULT gboolean li_connection_internal_error(liConnection *con); static void update_io_events(liConnection *con) { int events = 0; @@ -51,7 +51,7 @@ static void parse_request_body(liConnection *con) { } } -static void forward_response_body(liConnection *con) { +static G_GNUC_WARN_UNUSED_RESULT gboolean forward_response_body(liConnection *con) { liVRequest *vr = con->mainvr; if (con->state >= LI_CON_STATE_HANDLE_MAINVR) { if (!con->response_headers_sent) { @@ -61,8 +61,7 @@ static void forward_response_body(liConnection *con) { con->response_headers_sent = TRUE; if (!li_response_send_headers(con)) { con->response_headers_sent = FALSE; - li_connection_internal_error(con); - return; + return li_connection_internal_error(con); } li_vrequest_joblist_append(vr); } @@ -80,6 +79,8 @@ static void forward_response_body(liConnection *con) { con->info.out_queue_length = con->raw_out->length; } } + + return TRUE; } /* don't use con afterwards */ @@ -132,13 +133,14 @@ void li_connection_error(liConnection *con) { li_worker_con_put(con); } -static void li_connection_internal_error(liConnection *con) { +static G_GNUC_WARN_UNUSED_RESULT gboolean li_connection_internal_error(liConnection *con) { liVRequest *vr = con->mainvr; if (con->response_headers_sent) { if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { VR_DEBUG(vr, "%s", "Couldn't send '500 Internal Error': headers already sent"); } li_connection_error(con); + return FALSE; } else { if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { VR_DEBUG(vr, "%s", "internal error"); @@ -154,11 +156,11 @@ static void li_connection_internal_error(liConnection *con) { li_chunkqueue_reset(con->out); con->out->is_closed = TRUE; con->in->is_closed = TRUE; - forward_response_body(con); + return forward_response_body(con); } } -static gboolean connection_handle_read(liConnection *con) { +static G_GNUC_WARN_UNUSED_RESULT gboolean connection_handle_read(liConnection *con) { liVRequest *vr = con->mainvr; if (con->raw_in->length == 0) return TRUE; @@ -210,7 +212,7 @@ static gboolean connection_handle_read(liConnection *con) { li_vrequest_handle_direct(con->mainvr); con->state = LI_CON_STATE_WRITE; con->in->is_closed = TRUE; - forward_response_body(con); + if (!forward_response_body(con)) return FALSE; return TRUE; } @@ -234,7 +236,7 @@ static gboolean connection_handle_read(liConnection *con) { li_vrequest_handle_direct(con->mainvr); con->state = LI_CON_STATE_WRITE; con->in->is_closed = TRUE; - forward_response_body(con); + if (!forward_response_body(con)) return FALSE; return TRUE; } @@ -249,7 +251,7 @@ static gboolean connection_handle_read(liConnection *con) { con->state = LI_CON_STATE_WRITE; con->info.keep_alive = FALSE; con->in->is_closed = TRUE; - forward_response_body(con); + if (!forward_response_body(con)) return FALSE; } else { /* When does a client ask for 100 Continue? probably not while trying to ddos us * as post content probably goes to a dynamic backend anyway, we don't @@ -283,7 +285,7 @@ static void connection_update_io_timeout(liConnection *con) { } } -static gboolean connection_try_read(liConnection *con) { +static G_GNUC_WARN_UNUSED_RESULT gboolean connection_try_read(liConnection *con) { liNetworkStatus res; /* con->can_read = TRUE; */ @@ -329,7 +331,7 @@ static gboolean connection_try_read(liConnection *con) { return TRUE; } -static gboolean connection_try_write(liConnection *con) { +static G_GNUC_WARN_UNUSED_RESULT gboolean connection_try_write(liConnection *con) { liNetworkStatus res; con->can_write = TRUE; @@ -427,7 +429,7 @@ static void connection_keepalive_cb(struct ev_loop *loop, ev_timer *w, int reven li_worker_con_put(con); } -static liHandlerResult mainvr_handle_response_headers(liVRequest *vr) { +static G_GNUC_WARN_UNUSED_RESULT gboolean mainvr_handle_response_headers(liVRequest *vr) { liConnection *con = LI_CONTAINER_OF(vr->coninfo, liConnection, info); if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { VR_DEBUG(vr, "%s", "read request/handle response header"); @@ -443,12 +445,12 @@ static liHandlerResult mainvr_handle_response_headers(liVRequest *vr) { update_io_events(con); - return LI_HANDLER_GO_ON; + return TRUE; } -static liHandlerResult mainvr_handle_response_body(liVRequest *vr) { +static G_GNUC_WARN_UNUSED_RESULT gboolean mainvr_handle_response_body(liVRequest *vr) { liConnection *con = LI_CONTAINER_OF(vr->coninfo, liConnection, info); - if (!check_response_done(con)) return LI_HANDLER_GO_ON; + if (!check_response_done(con)) return TRUE; if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { VR_DEBUG(vr, "%s", "write response"); @@ -458,22 +460,22 @@ static liHandlerResult mainvr_handle_response_body(liVRequest *vr) { if (!connection_try_read(con)) return FALSE; parse_request_body(con); - forward_response_body(con); + if (!forward_response_body(con)) return FALSE; if (con->can_write) if (!connection_try_write(con)) return FALSE; - if (!check_response_done(con)) return LI_HANDLER_GO_ON; + if (!check_response_done(con)) return TRUE; update_io_events(con); - return LI_HANDLER_GO_ON; + return TRUE; } -static liHandlerResult mainvr_handle_response_error(liVRequest *vr) { +static G_GNUC_WARN_UNUSED_RESULT gboolean mainvr_handle_response_error(liVRequest *vr) { liConnection *con = LI_CONTAINER_OF(vr->coninfo, liConnection, info); - li_connection_internal_error(con); + if (!li_connection_internal_error(con)) return FALSE; if (con->can_read) if (!connection_try_read(con)) return FALSE; @@ -482,10 +484,10 @@ static liHandlerResult mainvr_handle_response_error(liVRequest *vr) { update_io_events(con); - return LI_HANDLER_GO_ON; + return FALSE; } -static liHandlerResult mainvr_handle_request_headers(liVRequest *vr) { +static G_GNUC_WARN_UNUSED_RESULT gboolean mainvr_handle_request_headers(liVRequest *vr) { liConnection *con = LI_CONTAINER_OF(vr->coninfo, liConnection, info); /* start reading input */ @@ -495,7 +497,7 @@ static liHandlerResult mainvr_handle_request_headers(liVRequest *vr) { parse_request_body(con); update_io_events(con); - return LI_HANDLER_GO_ON; + return TRUE; } static gboolean mainvr_handle_check_io(liVRequest *vr) { @@ -707,7 +709,7 @@ static void li_connection_reset_keep_alive(liConnection *con) { if (con->raw_in->length != 0) { /* start handling next request if data is already available */ - connection_handle_read(con); + if (!connection_handle_read(con)) return; } } diff --git a/src/main/subrequest_lua.c b/src/main/subrequest_lua.c index eedeaac..ea9ccf1 100644 --- a/src/main/subrequest_lua.c +++ b/src/main/subrequest_lua.c @@ -246,7 +246,7 @@ static void subvr_bind_lua(liSubrequest *sr, lua_State *L, int notify_ndx, int e sr->func_error_ref = luaL_ref(L, LUA_REGISTRYINDEX); /* -1 */ } -static liHandlerResult subvr_check(liVRequest *vr) { +static void subvr_check(liVRequest *vr) { liSubrequest *sr = LI_CONTAINER_OF(vr->coninfo, liSubrequest, coninfo); if (sr->notified_out_bytes < vr->vr_out->bytes_in @@ -262,22 +262,24 @@ static liHandlerResult subvr_check(liVRequest *vr) { if (sr->notified_out_closed) { /* reques done */ li_job_async(sr->parentvr_ref); } - - return LI_HANDLER_GO_ON; } -static liHandlerResult subvr_handle_response_headers(liVRequest *vr) { +static G_GNUC_WARN_UNUSED_RESULT gboolean subvr_handle_response_headers(liVRequest *vr) { liSubrequest *sr = LI_CONTAINER_OF(vr->coninfo, liSubrequest, coninfo); sr->have_response_headers = TRUE; - return subvr_check(vr); + subvr_check(vr); + + return TRUE; } -static liHandlerResult subvr_handle_response_body(liVRequest *vr) { - return subvr_check(vr); +static G_GNUC_WARN_UNUSED_RESULT gboolean subvr_handle_response_body(liVRequest *vr) { + subvr_check(vr); + + return TRUE; } -static liHandlerResult subvr_handle_response_error(liVRequest *vr) { +static G_GNUC_WARN_UNUSED_RESULT gboolean subvr_handle_response_error(liVRequest *vr) { liSubrequest *sr = LI_CONTAINER_OF(vr->coninfo, liSubrequest, coninfo); li_vrequest_free(sr->vr); @@ -286,11 +288,13 @@ static liHandlerResult subvr_handle_response_error(liVRequest *vr) { subvr_run_lua(sr, sr->func_error_ref); subvr_release_lua(sr); - return LI_HANDLER_GO_ON; + return FALSE; } -static liHandlerResult subvr_handle_request_headers(liVRequest *vr) { - return subvr_check(vr); +static G_GNUC_WARN_UNUSED_RESULT gboolean subvr_handle_request_headers(liVRequest *vr) { + subvr_check(vr); + + return TRUE; } static gboolean subvr_handle_check_io(liVRequest *vr) { diff --git a/src/main/virtualrequest.c b/src/main/virtualrequest.c index 82a1f64..49a70eb 100644 --- a/src/main/virtualrequest.c +++ b/src/main/virtualrequest.c @@ -409,23 +409,24 @@ static liHandlerResult vrequest_do_handle_actions(liVRequest *vr) { case LI_HANDLER_WAIT_FOR_EVENT: return LI_HANDLER_WAIT_FOR_EVENT; case LI_HANDLER_ERROR: - li_vrequest_error(vr); return LI_HANDLER_ERROR; } return LI_HANDLER_GO_ON; } -static gboolean vrequest_do_handle_read(liVRequest *vr) { +static G_GNUC_WARN_UNUSED_RESULT gboolean vrequest_do_handle_read(liVRequest *vr) { if (vr->backend && vr->backend->handle_request_body) { goffset lim_avail; if (vr->in->is_closed) vr->in_memory->is_closed = TRUE; if (!filters_handle_out_close(vr, &vr->filters_in)) { li_vrequest_error(vr); + return FALSE; } if (!filters_run(vr, &vr->filters_in)) { li_vrequest_error(vr); + return FALSE; } if (vr->in_buffer_state.tempfile || vr->request.content_length < 0 || vr->request.content_length > 64*1024 || @@ -440,7 +441,7 @@ static gboolean vrequest_do_handle_read(liVRequest *vr) { return FALSE; case LI_HANDLER_ERROR: li_vrequest_error(vr); - break; + return FALSE; } } else { li_chunkqueue_steal_all(vr->in, vr->in_memory); @@ -457,7 +458,7 @@ static gboolean vrequest_do_handle_read(liVRequest *vr) { return FALSE; case LI_HANDLER_ERROR: li_vrequest_error(vr); - break; + return FALSE; } } else { li_chunkqueue_skip_all(vr->vr_in); @@ -466,34 +467,23 @@ static gboolean vrequest_do_handle_read(liVRequest *vr) { return TRUE; } -static void vrequest_do_handle_write(liVRequest *vr) { +static G_GNUC_WARN_UNUSED_RESULT gboolean vrequest_do_handle_write(liVRequest *vr) { if (!filters_handle_out_close(vr, &vr->filters_out)) { li_vrequest_error(vr); - return; + return FALSE; } if (!filters_run(vr, &vr->filters_out)) { li_vrequest_error(vr); - return; + return FALSE; } - switch (vr->coninfo->callbacks->handle_response_body(vr)) { - case LI_HANDLER_GO_ON: - break; - case LI_HANDLER_COMEBACK: - li_vrequest_joblist_append(vr); /* come back later */ - return; - case LI_HANDLER_WAIT_FOR_EVENT: - return; - case LI_HANDLER_ERROR: - li_vrequest_error(vr); - break; - } - return; + if (!vr->coninfo->callbacks->handle_response_body(vr)) return FALSE; + + return TRUE; } void li_vrequest_state_machine(liVRequest *vr) { gboolean done = FALSE; - liHandlerResult res; do { switch (vr->state) { case LI_VRS_CLEAN: @@ -514,33 +504,22 @@ void li_vrequest_state_machine(liVRequest *vr) { if (vr->state == LI_VRS_HANDLE_REQUEST_HEADERS) return; break; /* go on to get post data/response headers if request is already handled */ case LI_HANDLER_ERROR: + li_vrequest_error(vr); return; } - res = vr->coninfo->callbacks->handle_request_headers(vr); - switch (res) { - case LI_HANDLER_GO_ON: - if (vr->state == LI_VRS_HANDLE_REQUEST_HEADERS) { - if (vr->request.http_method == LI_HTTP_METHOD_OPTIONS) { - vr->response.http_status = 200; - li_http_header_append(vr->response.headers, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST")); - } else { - /* unhandled request */ - vr->response.http_status = 404; - } - li_vrequest_handle_direct(vr); + + if (vr->state == LI_VRS_HANDLE_REQUEST_HEADERS) { + if (vr->request.http_method == LI_HTTP_METHOD_OPTIONS) { + vr->response.http_status = 200; + li_http_header_append(vr->response.headers, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST")); + } else { + /* unhandled request */ + vr->response.http_status = 404; } - break; - case LI_HANDLER_COMEBACK: - li_vrequest_joblist_append(vr); /* come back later */ - done = TRUE; - break; - case LI_HANDLER_WAIT_FOR_EVENT: - done = (vr->state == LI_VRS_HANDLE_REQUEST_HEADERS); - break; - case LI_HANDLER_ERROR: - li_vrequest_error(vr); - break; + li_vrequest_handle_direct(vr); } + + if (!vr->coninfo->callbacks->handle_request_headers(vr)) return; break; case LI_VRS_READ_CONTENT: @@ -562,33 +541,20 @@ void li_vrequest_state_machine(liVRequest *vr) { return; case LI_HANDLER_WAIT_FOR_EVENT: return; /* wait to handle response headers */ - case LI_HANDLER_ERROR: - return; - } - res = vr->coninfo->callbacks->handle_response_headers(vr); - switch (res) { - case LI_HANDLER_GO_ON: - vr->state = LI_VRS_WRITE_CONTENT; - break; - case LI_HANDLER_COMEBACK: - li_vrequest_joblist_append(vr); /* come back later */ - done = TRUE; - break; - case LI_HANDLER_WAIT_FOR_EVENT: - done = (vr->state == LI_VRS_HANDLE_REQUEST_HEADERS); - break; case LI_HANDLER_ERROR: li_vrequest_error(vr); - break; + return; } + if (!vr->coninfo->callbacks->handle_response_headers(vr)) return; + vr->state = LI_VRS_WRITE_CONTENT; break; case LI_VRS_WRITE_CONTENT: if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { VR_DEBUG(vr, "%s", "write content"); } - vrequest_do_handle_read(vr); - vrequest_do_handle_write(vr); + if (!vrequest_do_handle_read(vr)) return; + if (!vrequest_do_handle_write(vr)) return; done = TRUE; break; @@ -596,9 +562,8 @@ void li_vrequest_state_machine(liVRequest *vr) { if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { VR_DEBUG(vr, "%s", "error"); } - /* this will probably reset the vrequest, so stop handling after it */ - vr->coninfo->callbacks->handle_response_error(vr); - return; + if (!vr->coninfo->callbacks->handle_response_error(vr)) return; + return; /* stop anyway */ } } while (!done); }