diff --git a/src/base.h b/src/base.h index 7258643b..efa152f8 100644 --- a/src/base.h +++ b/src/base.h @@ -25,7 +25,10 @@ typedef struct { off_t content_length; unsigned int htags; /* bitfield of flagged headers present in response */ array headers; - int send_chunked; + char send_chunked; + char resp_body_started; + char resp_body_finished; + uint32_t resp_header_len; } response; typedef struct { @@ -75,13 +78,8 @@ struct connection { time_t write_request_ts; time_t connection_start; - uint32_t request_count; /* number of requests handled in this connection */ - uint32_t loops_per_request; /* to catch endless loops in a single request - * - * used by mod_rewrite, mod_fastcgi, ... and others - * this is self-protection - */ + int keep_alive_idle; /* remember max_keep_alive_idle from config */ fdnode *fdn; /* fdevent (fdnode *) object */ int fd; /* the FD for this connection */ @@ -92,28 +90,20 @@ struct connection { int is_writable; int is_ssl_sock; - int keep_alive_idle; /* remember max_keep_alive_idle from config */ - - int file_started; - int file_finished; - chunkqueue *write_queue; /* a large queue for low-level write ( HTTP response ) [ file, mem ] */ chunkqueue *read_queue; /* a small queue for low-level read ( HTTP request ) [ mem ] */ - chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/ int traffic_limit_reached; off_t bytes_written; /* used by mod_accesslog, mod_rrd */ off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */ off_t bytes_read; /* used by mod_accesslog, mod_rrd */ - off_t bytes_header; sock_addr dst_addr; buffer *dst_addr_buf; /* request */ int http_status; - uint32_t header_len; request_st request; request_uri uri; @@ -123,7 +113,6 @@ struct connection { array environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */ int mode; /* DIRECT (0) or plugin id */ - int async_callback; server *srv; diff --git a/src/chunk.h b/src/chunk.h index ba35543b..ed62b4f6 100644 --- a/src/chunk.h +++ b/src/chunk.h @@ -38,7 +38,7 @@ typedef struct chunk { } file; } chunk; -typedef struct { +typedef struct chunkqueue { chunk *first; chunk *last; diff --git a/src/connections-glue.c b/src/connections-glue.c index b06e402a..d4b9b1e3 100644 --- a/src/connections-glue.c +++ b/src/connections-glue.c @@ -113,7 +113,7 @@ handler_t connection_handle_read_post_error(connection *con, int http_status) { con->request.keep_alive = 0; /*(do not change status if response headers already set and possibly sent)*/ - if (0 != con->bytes_header) return HANDLER_ERROR; + if (0 != con->response.resp_header_len) return HANDLER_ERROR; http_response_body_clear(con, 0); con->http_status = http_status; @@ -414,7 +414,7 @@ static int connection_write_100_continue(connection *con) { handler_t connection_handle_read_post_state(connection *con) { chunkqueue *cq = con->read_queue; - chunkqueue *dst_cq = con->request_content_queue; + chunkqueue *dst_cq = con->request.reqbody_queue; int is_closed = 0; @@ -491,8 +491,8 @@ void connection_response_reset(connection *con) { con->mode = DIRECT; con->http_status = 0; con->is_writable = 1; - con->file_finished = 0; - con->file_started = 0; + con->response.resp_body_finished = 0; + con->response.resp_body_started = 0; if (con->physical.path) { /*(skip for mod_fastcgi authorizer)*/ buffer_clear(con->physical.doc_root); buffer_reset(con->physical.path); diff --git a/src/connections.c b/src/connections.c index ffb7078f..f238b5b6 100644 --- a/src/connections.c +++ b/src/connections.c @@ -229,7 +229,7 @@ static void connection_handle_response_end_state(connection *con) { if (con->state != CON_STATE_ERROR) ++con->srv->con_written; - if (con->request.reqbody_length != con->request_content_queue->bytes_in + if (con->request.reqbody_length != con->request.reqbody_queue->bytes_in || con->state == CON_STATE_ERROR) { /* request body is present and has not been read completely */ con->request.keep_alive = 0; @@ -276,7 +276,7 @@ static void connection_handle_errdoc(connection *con) { return; connection_handle_errdoc_init(con); - con->file_finished = 1; + con->response.resp_body_finished = 1; /* try to send static errorfile */ if (!buffer_string_is_empty(con->conf.errorfile_prefix)) { @@ -343,7 +343,7 @@ static int connection_handle_write_prepare(connection *con) { http_response_body_clear(con, 0); http_header_response_append(con, HTTP_HEADER_OTHER, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST")); con->http_status = 200; - con->file_finished = 1; + con->response.resp_body_finished = 1; } break; @@ -365,7 +365,7 @@ static int connection_handle_write_prepare(connection *con) { case 304: /* disable chunked encoding again as we have no body */ http_response_body_clear(con, 1); - con->file_finished = 1; + con->response.resp_body_finished = 1; break; default: /* class: header + body */ /* only custom body for 4xx and 5xx */ @@ -384,7 +384,7 @@ static int connection_handle_write_prepare(connection *con) { return -1; } - if (con->file_finished) { + if (con->response.resp_body_finished) { /* we have all the content and chunked encoding is not used, set a content-length */ if (!(con->response.htags & (HTTP_HEADER_CONTENT_LENGTH|HTTP_HEADER_TRANSFER_ENCODING))) { @@ -452,7 +452,7 @@ static int connection_handle_write_prepare(connection *con) { * without the content */ http_response_body_clear(con, 1); - con->file_finished = 1; + con->response.resp_body_finished = 1; } http_response_write_header(con); @@ -463,7 +463,7 @@ static int connection_handle_write_prepare(connection *con) { static void connection_handle_write(connection *con) { switch(connection_write_chunkqueue(con, con->write_queue, MAX_WRITE_LIMIT)) { case 0: - if (con->file_finished) { + if (con->response.resp_body_finished) { connection_set_state(con, CON_STATE_RESPONSE_END); } break; @@ -492,12 +492,12 @@ static void connection_handle_write_state(connection *con) { connection_handle_write(con); if (con->state != CON_STATE_WRITE) break; } - } else if (con->file_finished) { + } else if (con->response.resp_body_finished) { connection_set_state(con, CON_STATE_RESPONSE_END); break; } - if (con->mode != DIRECT && !con->file_finished) { + if (con->mode != DIRECT && !con->response.resp_body_finished) { int rc = plugins_call_handle_subrequest(con); switch(rc) { case HANDLER_WAIT_FOR_EVENT: @@ -521,7 +521,7 @@ static void connection_handle_write_state(connection *con) { } while (con->state == CON_STATE_WRITE && (!chunkqueue_is_empty(con->write_queue) ? con->is_writable - : con->file_finished)); + : con->response.resp_body_finished)); } @@ -536,8 +536,8 @@ static connection *connection_init(server *srv) { con->ndx = -1; con->bytes_written = 0; con->bytes_read = 0; - con->bytes_header = 0; - con->loops_per_request = 0; + con->response.resp_header_len = 0; + con->request.loops_per_request = 0; con->request.conf = &con->conf; con->request.con = con; @@ -567,7 +567,7 @@ static connection *connection_init(server *srv) { #undef CLEAN con->write_queue = chunkqueue_init(); con->read_queue = chunkqueue_init(); - con->request_content_queue = chunkqueue_init(); + con->request.reqbody_queue = chunkqueue_init(); con->srv = srv; con->plugin_slots = srv->plugin_slots; @@ -600,7 +600,7 @@ void connections_free(server *srv) { chunkqueue_free(con->write_queue); chunkqueue_free(con->read_queue); - chunkqueue_free(con->request_content_queue); + chunkqueue_free(con->request.reqbody_queue); array_free_data(&con->request.headers); array_free_data(&con->response.headers); array_free_data(&con->environment); @@ -649,8 +649,8 @@ static int connection_reset(connection *con) { con->bytes_written = 0; con->bytes_written_cur_second = 0; con->bytes_read = 0; - con->bytes_header = 0; - con->loops_per_request = 0; + con->response.resp_header_len = 0; + con->request.loops_per_request = 0; con->request.http_method = HTTP_METHOD_UNSET; con->request.http_version = HTTP_VERSION_UNSET; @@ -678,20 +678,20 @@ static int connection_reset(connection *con) { con->request.te_chunked = 0; con->request.htags = 0; - if (con->header_len <= BUFFER_MAX_REUSE_SIZE) + if (con->request.rqst_header_len <= BUFFER_MAX_REUSE_SIZE) con->request.headers.used = 0; else array_reset_data_strings(&con->request.headers); - con->header_len = 0; + con->request.rqst_header_len = 0; if (0 != con->environment.used) array_reset_data_strings(&con->environment); - chunkqueue_reset(con->request_content_queue); + chunkqueue_reset(con->request.reqbody_queue); /* The cond_cache gets reset in response.c */ /* config_cond_cache_reset(con); */ - con->async_callback = 0; + con->request.async_callback = 0; con->error_handler_saved_status = 0; /*con->error_handler_saved_method = HTTP_METHOD_UNSET;*/ /*(error_handler_saved_method value is not valid unless error_handler_saved_status is set)*/ @@ -773,6 +773,7 @@ static int connection_handle_read_state(connection * const con) { chunkqueue * const cq = con->read_queue; chunk *c = cq->first; uint32_t clen = 0; + uint32_t header_len = 0; unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */ do { @@ -786,14 +787,14 @@ static int connection_handle_read_state(connection * const con) { hoff[1] = (unsigned short)c->offset; /* base offset for all lines */ /*hoff[2] = ...;*/ /* offset from base for 2nd line */ - con->header_len = + header_len = connection_read_header_hoff(c->mem->ptr + c->offset, clen, hoff); /* casting to (unsigned short) might truncate, and the hoff[] * addition might overflow, but max_request_field_size is USHRT_MAX, * so failure will be detected below */ const uint32_t max_request_field_size=con->conf.max_request_field_size; - if ((con->header_len ? con->header_len : clen) > max_request_field_size + if ((header_len ? header_len : clen) > max_request_field_size || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1) { log_error(con->conf.errh, __FILE__, __LINE__, "%s", "oversized request-header -> sending Status 431"); @@ -802,7 +803,7 @@ static int connection_handle_read_state(connection * const con) { return 1; } - if (0 != con->header_len) break; + if (0 != header_len) break; } while ((c = connection_read_header_more(con, cq, c, clen))); if (keepalive_request_start) { @@ -841,8 +842,8 @@ static int connection_handle_read_state(connection * const con) { if (con->conf.log_request_header) { log_error(con->conf.errh, __FILE__, __LINE__, - "fd: %d request-len: %d\n%.*s", con->fd, (int)con->header_len, - (int)con->header_len, hdrs); + "fd: %d request-len: %d\n%.*s", con->fd, (int)header_len, + (int)header_len, hdrs); } con->http_status = @@ -855,11 +856,12 @@ static int connection_handle_read_state(connection * const con) { /*(http_request_parse() modifies hdrs only to * undo line-wrapping in-place using spaces)*/ log_error(con->conf.errh, __FILE__, __LINE__, "request-header:\n%.*s", - (int)con->header_len, hdrs); + (int)header_len, hdrs); } } - chunkqueue_mark_written(cq, con->header_len); + con->request.rqst_header_len = header_len; + chunkqueue_mark_written(cq, header_len); connection_set_state(con, CON_STATE_REQUEST_END); return 1; } @@ -918,7 +920,7 @@ static handler_t connection_handle_fdevent(void *context, int revents) { con->is_readable = 1; /*(can read 0 for end-of-stream)*/ if (chunkqueue_is_empty(con->read_queue)) con->request.keep_alive = 0; if (con->request.reqbody_length < -1) { /*(transparent proxy mode; no more data to read)*/ - con->request.reqbody_length = con->request_content_queue->bytes_in; + con->request.reqbody_length = con->request.reqbody_queue->bytes_in; } if (sock_addr_get_family(&con->dst_addr) == AF_UNIX) { /* future: will getpeername() on AF_UNIX properly check if still connected? */ @@ -1136,7 +1138,7 @@ static int connection_handle_request(connection *con) { int rc = http_response_prepare(con); switch (rc) { case HANDLER_WAIT_FOR_EVENT: - if (!con->file_finished && (!con->file_started || 0 == con->conf.stream_response_body)) { + if (!con->response.resp_body_finished && (!con->response.resp_body_started || 0 == con->conf.stream_response_body)) { break; /* come back here */ } /* response headers received from backend; fall through to start response */ @@ -1186,16 +1188,16 @@ static int connection_handle_request(connection *con) { plugins_call_connection_reset(con); if (con->request.reqbody_length) { - if (con->request.reqbody_length != con->request_content_queue->bytes_in) { + if (con->request.reqbody_length != con->request.reqbody_queue->bytes_in) { con->request.keep_alive = 0; } con->request.reqbody_length = 0; - chunkqueue_reset(con->request_content_queue); + chunkqueue_reset(con->request.reqbody_queue); } con->is_writable = 1; - con->file_finished = 0; - con->file_started = 0; + con->response.resp_body_finished = 0; + con->response.resp_body_started = 0; con->error_handler_saved_status = con->http_status; con->error_handler_saved_method = con->request.http_method; @@ -1263,7 +1265,7 @@ int connection_state_machine(connection *con) { log_clock_gettime_realtime(&con->request.start_hp); con->request_count++; - con->loops_per_request = 0; + con->request.loops_per_request = 0; connection_set_state(con, CON_STATE_READ); /* fall through */ diff --git a/src/gw_backend.c b/src/gw_backend.c index 58e86c71..0e01e751 100644 --- a/src/gw_backend.c +++ b/src/gw_backend.c @@ -2012,7 +2012,7 @@ handler_t gw_handle_subrequest(connection *con, void *p_d) { if (con->mode != p->id) return HANDLER_GO_ON; /* not my job */ if ((con->conf.stream_response_body & FDEVENT_STREAM_RESPONSE_BUFMIN) - && con->file_started) { + && con->response.resp_body_started) { if (chunkqueue_length(con->write_queue) > 65536 - 4096) { fdevent_fdnode_event_clr(hctx->ev, hctx->fdn, FDEVENT_IN); } @@ -2033,7 +2033,7 @@ handler_t gw_handle_subrequest(connection *con, void *p_d) { && (0 == hctx->wb->bytes_in ? (con->state == CON_STATE_READ_POST || -1 == hctx->wb_reqlen) : (hctx->wb->bytes_in < hctx->wb_reqlen || hctx->wb_reqlen < 0))) { - /* leave excess data in con->request_content_queue, which is + /* leave excess data in con->request.reqbody_queue, which is * buffered to disk if too large and backend can not keep up */ /*(64k - 4k to attempt to avoid temporary files * in conjunction with FDEVENT_STREAM_REQUEST_BUFMIN)*/ @@ -2045,7 +2045,7 @@ handler_t gw_handle_subrequest(connection *con, void *p_d) { } else { handler_t rc = connection_handle_read_post_state(con); - chunkqueue *req_cq = con->request_content_queue; + chunkqueue *req_cq = con->request.reqbody_queue; #if 0 /*(not reached since we send 411 Length Required below)*/ if (hctx->wb_reqlen < -1 && con->request.reqbody_length >= 0) { /* (completed receiving Transfer-Encoding: chunked) */ @@ -2140,7 +2140,7 @@ static handler_t gw_recv_response(gw_handler_ctx *hctx, connection *con) { handler_ctx_clear(hctx); /* don't do more than 6 loops here; normally shouldn't happen */ - if (++con->loops_per_request > 5) { + if (++con->request.loops_per_request > 5) { log_error(con->conf.errh, __FILE__, __LINE__, "too many loops while processing request: %s", con->request.orig_uri->ptr); @@ -2191,7 +2191,7 @@ static handler_t gw_recv_response(gw_handler_ctx *hctx, connection *con) { } } - if (con->file_started == 0) { + if (con->response.resp_body_started == 0) { /* nothing has been sent out yet, try to use another child */ if (hctx->wb->bytes_out == 0 && @@ -2255,7 +2255,7 @@ static handler_t gw_handle_fdevent(void *ctx, int revents) { * */ gw_send_request(hctx, con); - } else if (con->file_started) { + } else if (con->response.resp_body_started) { /* drain any remaining data from kernel pipe buffers * even if (con->conf.stream_response_body * & FDEVENT_STREAM_RESPONSE_BUFMIN) diff --git a/src/http-header-glue.c b/src/http-header-glue.c index 73622a3e..0176b54c 100644 --- a/src/http-header-glue.c +++ b/src/http-header-glue.c @@ -108,7 +108,7 @@ int http_response_redirect_to_directory(connection *con, int status) { if (status >= 300) { http_header_response_set(con, HTTP_HEADER_LOCATION, CONST_STR_LEN("Location"), CONST_BUF_LEN(o)); con->http_status = status; - con->file_finished = 1; + con->response.resp_body_finished = 1; } else { http_header_response_set(con, HTTP_HEADER_CONTENT_LOCATION, CONST_STR_LEN("Content-Location"), CONST_BUF_LEN(o)); @@ -543,7 +543,7 @@ void http_response_send_file (connection *con, buffer *path) { if (fd < 0) { /* 0-length file */ con->http_status = 200; - con->file_finished = 1; + con->response.resp_body_finished = 1; return; } @@ -585,7 +585,7 @@ void http_response_send_file (connection *con, buffer *path) { && 0 == strncmp(range->ptr, "bytes=", 6)) { /* support only "bytes" byte-unit */ /* content prepared, I'm done */ - con->file_finished = 1; + con->response.resp_body_finished = 1; if (0 == http_response_parse_range(con, path, sce, range->ptr+6)) { con->http_status = 206; @@ -603,7 +603,7 @@ void http_response_send_file (connection *con, buffer *path) { if (0 == http_chunk_append_file_fd(con, path, fd, sce->st.st_size)) { con->http_status = 200; - con->file_finished = 1; + con->response.resp_body_finished = 1; } else { con->http_status = 500; @@ -813,12 +813,12 @@ range_success: ; void http_response_backend_error (connection *con) { - if (con->file_started) { + if (con->response.resp_body_started) { /*(response might have been already started, kill the connection)*/ /*(mode == DIRECT to avoid later call to http_response_backend_done())*/ con->mode = DIRECT; /*(avoid sending final chunked block)*/ con->request.keep_alive = 0; - con->file_finished = 1; + con->response.resp_body_finished = 1; } /*(else error status set later by http_response_backend_done())*/ } @@ -829,16 +829,16 @@ void http_response_backend_done (connection *con) { switch (con->state) { case CON_STATE_HANDLE_REQUEST: case CON_STATE_READ_POST: - if (!con->file_started) { + if (!con->response.resp_body_started) { /* Send an error if we haven't sent any data yet */ con->http_status = 500; con->mode = DIRECT; break; } /* else fall through */ case CON_STATE_WRITE: - if (!con->file_finished) { + if (!con->response.resp_body_finished) { http_chunk_close(con); - con->file_finished = 1; + con->response.resp_body_finished = 1; } default: break; @@ -896,7 +896,7 @@ static handler_t http_response_process_local_redir(connection *con, size_t blen) && 0 == blen && !(con->response.htags & HTTP_HEADER_STATUS) /*no "Status" or NPH response*/ && 1 == con->response.headers.used) { - if (++con->loops_per_request > 5) { + if (++con->request.loops_per_request > 5) { log_error(con->conf.errh, __FILE__, __LINE__, "too many internal loops while processing request: %s", con->request.orig_uri->ptr); @@ -909,11 +909,11 @@ static handler_t http_response_process_local_redir(connection *con, size_t blen) if (con->request.reqbody_length) { if (con->request.reqbody_length - != con->request_content_queue->bytes_in) { + != con->request.reqbody_queue->bytes_in) { con->request.keep_alive = 0; } con->request.reqbody_length = 0; - chunkqueue_reset(con->request_content_queue); + chunkqueue_reset(con->request.reqbody_queue); } if (con->http_status != 307 && con->http_status != 308) { @@ -1122,7 +1122,7 @@ handler_t http_response_parse_headers(connection *con, http_response_opts *opts, return HANDLER_ERROR; } con->http_status = 200; /* OK */ - con->file_started = 1; + con->response.resp_body_started = 1; return HANDLER_GO_ON; } else { /* invalid response headers */ @@ -1166,7 +1166,7 @@ handler_t http_response_parse_headers(connection *con, http_response_opts *opts, return HANDLER_ERROR; } - con->file_started = 1; + con->response.resp_body_started = 1; if (opts->authorizer && (con->http_status == 0 || con->http_status == 200)) { @@ -1180,7 +1180,7 @@ handler_t http_response_parse_headers(connection *con, http_response_opts *opts, if (opts->local_redir && con->http_status >= 300 && con->http_status < 400){ /*(con->response.htags & HTTP_HEADER_LOCATION)*/ handler_t rc = http_response_process_local_redir(con, blen); - if (con->mode == DIRECT) con->file_started = 0; + if (con->mode == DIRECT) con->response.resp_body_started = 0; if (rc != HANDLER_GO_ON) return rc; } @@ -1192,7 +1192,7 @@ handler_t http_response_parse_headers(connection *con, http_response_opts *opts, http_response_xsendfile2(con, vb, opts->xsendfile_docroot); /* http_header_response_unset() shortcut for HTTP_HEADER_OTHER */ buffer_clear(vb); /*(do not send to client)*/ - if (con->mode == DIRECT) con->file_started = 0; + if (con->mode == DIRECT) con->response.resp_body_started = 0; return HANDLER_FINISHED; } else if (NULL != (vb = http_header_response_get(con, HTTP_HEADER_OTHER, CONST_STR_LEN("X-Sendfile"))) || (opts->backend == BACKEND_FASTCGI /* X-LIGHTTPD-send-file is deprecated; historical for fastcgi */ @@ -1200,7 +1200,7 @@ handler_t http_response_parse_headers(connection *con, http_response_opts *opts, http_response_xsendfile(con, vb, opts->xsendfile_docroot); /* http_header_response_unset() shortcut for HTTP_HEADER_OTHER */ buffer_clear(vb); /*(do not send to client)*/ - if (con->mode == DIRECT) con->file_started = 0; + if (con->mode == DIRECT) con->response.resp_body_started = 0; return HANDLER_FINISHED; } } @@ -1308,12 +1308,12 @@ handler_t http_response_read(connection *con, http_response_opts *opts, buffer * * (backend should read all data desired prior to closing socket, * though might send app-level close data frame, if applicable) */ return HANDLER_FINISHED; /* read finished */ - } else if (0 == con->file_started) { + } else if (0 == con->response.resp_body_started) { /* split header from body */ handler_t rc = http_response_parse_headers(con, opts, b); if (rc != HANDLER_GO_ON) return rc; /* accumulate response in b until headers completed (or error) */ - if (con->file_started) buffer_clear(b); + if (con->response.resp_body_started) buffer_clear(b); } else { if (0 != http_chunk_append_buffer(con, b)) { /* error writing to tempfile; diff --git a/src/mod_accesslog.c b/src/mod_accesslog.c index ea49dac0..093c8224 100644 --- a/src/mod_accesslog.c +++ b/src/mod_accesslog.c @@ -958,8 +958,8 @@ static int log_access_record (const connection * const con, buffer * const b, fo case FORMAT_BYTES_OUT_NO_HEADER: if (con->bytes_written > 0) { - buffer_append_int(b, - con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header); + off_t bytes = con->bytes_written - (off_t)con->response.resp_header_len; + buffer_append_int(b, bytes > 0 ? bytes : 0); } else { buffer_append_string_len(b, CONST_STR_LEN("-")); } diff --git a/src/mod_cgi.c b/src/mod_cgi.c index ea6bb527..b1e4042a 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -333,7 +333,7 @@ static void cgi_connection_close(connection *con, handler_ctx *hctx) { cgi_handler_ctx_free(hctx); - /* finish response (if not already con->file_started, con->file_finished) */ + /* finish response (if not already con->response.resp_body_started, con->response.resp_body_finished) */ if (con->mode == p->id) { http_response_backend_done(con); } @@ -369,7 +369,7 @@ static handler_t cgi_handle_fdevent_send (void *ctx, int revents) { if (revents & FDEVENT_HUP) { /* skip sending remaining data to CGI */ if (con->request.reqbody_length) { - chunkqueue *cq = con->request_content_queue; + chunkqueue *cq = con->request.reqbody_queue; chunkqueue_mark_written(cq, chunkqueue_length(cq)); if (cq->bytes_in != (off_t)con->request.reqbody_length) { con->request.keep_alive = 0; @@ -412,7 +412,7 @@ static handler_t cgi_response_headers(connection *con, struct http_response_opts } if (hctx->conf.upgrade && !(con->response.htags & HTTP_HEADER_UPGRADE)) { - chunkqueue *cq = con->request_content_queue; + chunkqueue *cq = con->request.reqbody_queue; hctx->conf.upgrade = 0; if (cq->bytes_out == (off_t)con->request.reqbody_length) { cgi_connection_close_fdtocgi(con, hctx); /*(closes hctx->fdtocgi)*/ @@ -458,7 +458,7 @@ static handler_t cgi_handle_fdevent(void *ctx, int revents) { /* perhaps this issue is already handled */ if (revents & (FDEVENT_HUP|FDEVENT_RDHUP)) { - if (con->file_started) { + if (con->response.resp_body_started) { /* drain any remaining data from kernel pipe buffers * even if (con->conf.stream_response_body * & FDEVENT_STREAM_RESPONSE_BUFMIN) @@ -475,7 +475,7 @@ static handler_t cgi_handle_fdevent(void *ctx, int revents) { return rc; /* HANDLER_FINISHED or HANDLER_COMEBACK or HANDLER_ERROR */ } else if (!buffer_string_is_empty(hctx->response)) { /* unfinished header package which is a body in reality */ - con->file_started = 1; + con->response.resp_body_started = 1; if (0 != http_chunk_append_buffer(con, hctx->response)) { cgi_connection_close(con, hctx); return HANDLER_ERROR; @@ -639,7 +639,7 @@ static ssize_t cgi_write_file_chunk_mmap(connection *con, int fd, chunkqueue *cq static int cgi_write_request(handler_ctx *hctx, int fd) { connection *con = hctx->remote_conn; - chunkqueue *cq = con->request_content_queue; + chunkqueue *cq = con->request.reqbody_queue; chunk *c; /* old comment: windows doesn't support select() on pipes - wouldn't be easy to fix for all platforms. @@ -934,7 +934,7 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { if (NULL == hctx) return HANDLER_GO_ON; if ((con->conf.stream_response_body & FDEVENT_STREAM_RESPONSE_BUFMIN) - && con->file_started) { + && con->response.resp_body_started) { if (chunkqueue_length(con->write_queue) > 65536 - 4096) { fdevent_fdnode_event_clr(con->srv->ev,hctx->fdn,FDEVENT_IN); } else if (!(fdevent_fdnode_interest(hctx->fdn) & FDEVENT_IN)) { @@ -945,7 +945,7 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { } } - chunkqueue * const cq = con->request_content_queue; + chunkqueue * const cq = con->request.reqbody_queue; if (cq->bytes_in != (off_t)con->request.reqbody_length) { /*(64k - 4k to attempt to avoid temporary files @@ -980,7 +980,7 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { return HANDLER_FINISHED; } - } else if (!chunkqueue_is_empty(con->request_content_queue)) { + } else if (!chunkqueue_is_empty(cq)) { if (0 != cgi_write_request(hctx, hctx->fdtocgi)) { cgi_connection_close(con, hctx); return HANDLER_ERROR; diff --git a/src/mod_cml_lua.c b/src/mod_cml_lua.c index 4f3fc5b2..7e9ccf1f 100644 --- a/src/mod_cml_lua.c +++ b/src/mod_cml_lua.c @@ -286,7 +286,7 @@ int cache_parse_lua(connection *con, plugin_data *p, const buffer *fn) { force_assert(NULL != vb); } - con->file_finished = 1; + con->response.resp_body_finished = 1; if (HANDLER_FINISHED == http_response_handle_cachable(con, vb)) { /* ok, the client already has our content, diff --git a/src/mod_compress.c b/src/mod_compress.c index edb03399..b34798e0 100644 --- a/src/mod_compress.c +++ b/src/mod_compress.c @@ -750,8 +750,8 @@ static int deflate_file_to_buffer(connection *con, plugin_data *p, int ifd, buff buffer_reset(con->physical.path); - con->file_finished = 1; - con->file_started = 1; + con->response.resp_body_finished = 1; + con->response.resp_body_started = 1; return 0; } diff --git a/src/mod_deflate.c b/src/mod_deflate.c index f6576e4a..b5033e7b 100644 --- a/src/mod_deflate.c +++ b/src/mod_deflate.c @@ -15,7 +15,8 @@ * * Patch further modified in this incarnation. * - * Note: this patch only handles completed responses (con->file_finished); + * Note: this patch only handles completed responses + * (con->response.resp_body_finished) * this patch does not currently handle streaming dynamic responses, * and therefore also does not worry about Transfer-Encoding: chunked * (or having separate con->output_queue for chunked-encoded output) @@ -59,7 +60,8 @@ * block, e.g. $HTTP["url"] =~ "....." { deflate.mimetypes = ( ) } * - deflate.sync-flush removed; controlled by con->conf.stream_response_body * (though streaming compression not currently implemented in mod_deflate) - * - inactive directives in this patch (since con->file_finished required) + * - inactive directives in this patch + * (since con->response.resp_body_finished required) * deflate.work-block-size * deflate.output-buffer-size * - remove weak file size check; SIGBUS is trapped, file that shrink will error @@ -958,7 +960,8 @@ static handler_t deflate_compress_response(connection *con, handler_ctx *hctx) { /*(currently should always be true)*/ /*(current implementation requires response be complete)*/ - close_stream = (con->file_finished && chunkqueue_is_empty(hctx->in_queue)); + close_stream = (con->response.resp_body_finished + && chunkqueue_is_empty(hctx->in_queue)); if (mod_deflate_stream_flush(con, hctx, close_stream) < 0) { log_error(con->conf.errh, __FILE__, __LINE__, "flush error"); return HANDLER_ERROR; @@ -1071,7 +1074,7 @@ CONNECTION_FUNC(mod_deflate_handle_response_start) { handler_t rc; /*(current implementation requires response be complete)*/ - if (!con->file_finished) return HANDLER_GO_ON; + if (!con->response.resp_body_finished) return HANDLER_GO_ON; if (con->request.http_method == HTTP_METHOD_HEAD) return HANDLER_GO_ON; if (con->response.htags & HTTP_HEADER_TRANSFER_ENCODING) return HANDLER_GO_ON; @@ -1094,7 +1097,7 @@ CONNECTION_FUNC(mod_deflate_handle_response_start) { if (NULL == p->conf.mimetypes) return HANDLER_GO_ON; /* check if size of response is below min-compress-size or exceeds max*/ - /* (con->file_finished checked at top of routine) */ + /* (con->response.resp_body_finished checked at top of routine) */ len = chunkqueue_length(con->write_queue); if (len <= (off_t)p->conf.min_compress_size) return HANDLER_GO_ON; if (p->conf.max_compress_size /*(max_compress_size in KB)*/ @@ -1166,7 +1169,7 @@ CONNECTION_FUNC(mod_deflate_handle_response_start) { /* clear content length even if 304 since compressed length unknown */ http_response_body_clear(con, 0); - con->file_finished = 1; + con->response.resp_body_finished = 1; con->mode = DIRECT; return HANDLER_GO_ON; } diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c index 687dc360..418f4c7f 100644 --- a/src/mod_dirlisting.c +++ b/src/mod_dirlisting.c @@ -1015,7 +1015,7 @@ static int http_list_directory(connection *con, plugin_data *p, buffer *dir) { } chunkqueue_append_buffer_commit(con->write_queue); - con->file_finished = 1; + con->response.resp_body_finished = 1; return 0; } diff --git a/src/mod_evasive.c b/src/mod_evasive.c index 535c29fd..61fd8b9d 100644 --- a/src/mod_evasive.c +++ b/src/mod_evasive.c @@ -132,7 +132,7 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { if (!buffer_is_empty(p->conf.location)) { http_header_response_set(con, HTTP_HEADER_LOCATION, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.location)); con->http_status = 302; - con->file_finished = 1; + con->response.resp_body_finished = 1; } else { con->http_status = 403; } diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 4602837c..2e1a174a 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -220,7 +220,7 @@ static void fcgi_header(FCGI_Header * header, unsigned char type, int request_id static handler_t fcgi_stdin_append(handler_ctx *hctx) { FCGI_Header header; connection *con = hctx->remote_conn; - chunkqueue *req_cq = con->request_content_queue; + chunkqueue *req_cq = con->request.reqbody_queue; off_t offset, weWant; const off_t req_cqlen = req_cq->bytes_in - req_cq->bytes_out; int request_id = hctx->request_id; @@ -274,7 +274,7 @@ static handler_t fcgi_create_env(handler_ctx *hctx) { }; size_t rsz = (size_t)(con->read_queue->bytes_out - hctx->wb->bytes_in); - buffer * const b = chunkqueue_prepend_buffer_open_sz(hctx->wb, rsz < 65536 ? rsz : con->header_len); + buffer * const b = chunkqueue_prepend_buffer_open_sz(hctx->wb, rsz < 65536 ? rsz : con->request.rqst_header_len); /* send FCGI_BEGIN_REQUEST */ @@ -317,7 +317,7 @@ static handler_t fcgi_create_env(handler_ctx *hctx) { } if (con->request.reqbody_length) { - /*chunkqueue_append_chunkqueue(hctx->wb, con->request_content_queue);*/ + /*chunkqueue_append_chunkqueue(hctx->wb, con->request.reqbody_queue);*/ if (con->request.reqbody_length > 0) hctx->wb_reqlen += con->request.reqbody_length;/* (eventual) (minimal) total request size, not necessarily including all fcgi_headers around content length yet */ else /* as-yet-unknown total request size (Transfer-Encoding: chunked)*/ @@ -432,7 +432,7 @@ static handler_t fcgi_recv_parse(connection *con, struct http_response_opts_t *o if (packet.len == 0) break; /* is the header already finished */ - if (0 == con->file_started) { + if (0 == con->response.resp_body_started) { /* split header from body */ buffer *hdrs = hctx->response; if (NULL == hdrs) { @@ -445,7 +445,7 @@ static handler_t fcgi_recv_parse(connection *con, struct http_response_opts_t *o fin = 1; break; } - if (0 == con->file_started) { + if (0 == con->response.resp_body_started) { if (!hctx->response) { hctx->response = chunk_buffer_acquire(); buffer_copy_buffer(hctx->response, hdrs); diff --git a/src/mod_flv_streaming.c b/src/mod_flv_streaming.c index f8431e80..3fa60188 100644 --- a/src/mod_flv_streaming.c +++ b/src/mod_flv_streaming.c @@ -127,7 +127,7 @@ URIHANDLER_FUNC(mod_flv_streaming_path_handler) { } http_header_response_set(con, HTTP_HEADER_CONTENT_TYPE, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("video/x-flv")); - con->file_finished = 1; + con->response.resp_body_finished = 1; return HANDLER_FINISHED; } diff --git a/src/mod_magnet.c b/src/mod_magnet.c index bf7ac2cb..5fb66635 100644 --- a/src/mod_magnet.c +++ b/src/mod_magnet.c @@ -940,7 +940,7 @@ static handler_t magnet_attract(connection *con, plugin_data *p, buffer *name) { if (lua_return_value > 99) { con->http_status = lua_return_value; - con->file_finished = 1; + con->response.resp_body_finished = 1; /* try { ...*/ if (0 == setjmp(exceptionjmp)) { diff --git a/src/mod_proxy.c b/src/mod_proxy.c index c55620d9..03c99cdf 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -821,7 +821,7 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { const int upgrade = hctx->conf.header.upgrade && (NULL != http_header_request_get(con, HTTP_HEADER_UPGRADE, CONST_STR_LEN("Upgrade"))); size_t rsz = (size_t)(con->read_queue->bytes_out - hctx->gw.wb->bytes_in); - buffer * const b = chunkqueue_prepend_buffer_open_sz(hctx->gw.wb, rsz < 65536 ? rsz : con->header_len); + buffer * const b = chunkqueue_prepend_buffer_open_sz(hctx->gw.wb, rsz < 65536 ? rsz : con->request.rqst_header_len); /* build header */ @@ -949,7 +949,7 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { chunkqueue_prepend_buffer_commit(hctx->gw.wb); if (con->request.reqbody_length) { - chunkqueue_append_chunkqueue(hctx->gw.wb, con->request_content_queue); + chunkqueue_append_chunkqueue(hctx->gw.wb, con->request.reqbody_queue); if (con->request.reqbody_length > 0) hctx->gw.wb_reqlen += con->request.reqbody_length; /* total req size */ else /* as-yet-unknown total request size (Transfer-Encoding: chunked)*/ @@ -965,7 +965,7 @@ static handler_t proxy_create_env_connect(gw_handler_ctx *gwhctx) { handler_ctx *hctx = (handler_ctx *)gwhctx; connection *con = hctx->gw.remote_conn; con->http_status = 200; /* OK */ - con->file_started = 1; + con->response.resp_body_started = 1; gw_set_transparent(&hctx->gw); http_response_upgrade_read_body_unknown(con); diff --git a/src/mod_redirect.c b/src/mod_redirect.c index 459323c9..a72b78e2 100644 --- a/src/mod_redirect.c +++ b/src/mod_redirect.c @@ -180,7 +180,7 @@ URIHANDLER_FUNC(mod_redirect_uri_handler) { CONST_BUF_LEN(tb)); con->http_status = p->conf.redirect_code; con->mode = DIRECT; - con->file_finished = 1; + con->response.resp_body_finished = 1; } else if (HANDLER_ERROR == rc) { log_error(con->conf.errh, __FILE__, __LINE__, diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 915ddc8d..39bf460b 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -216,7 +216,7 @@ static handler_t scgi_create_env(handler_ctx *hctx) { : scgi_env_add_uwsgi; size_t offset; size_t rsz = (size_t)(con->read_queue->bytes_out - hctx->wb->bytes_in); - buffer * const b = chunkqueue_prepend_buffer_open_sz(hctx->wb, rsz < 65536 ? rsz : con->header_len); + buffer * const b = chunkqueue_prepend_buffer_open_sz(hctx->wb, rsz < 65536 ? rsz : con->request.rqst_header_len); /* save space for 9 digits (plus ':'), though incoming HTTP request * currently limited to 64k (65535, so 5 chars) */ @@ -267,7 +267,7 @@ static handler_t scgi_create_env(handler_ctx *hctx) { #endif if (con->request.reqbody_length) { - chunkqueue_append_chunkqueue(hctx->wb, con->request_content_queue); + chunkqueue_append_chunkqueue(hctx->wb, con->request.reqbody_queue); if (con->request.reqbody_length > 0) hctx->wb_reqlen += con->request.reqbody_length; /* total req size */ else /* as-yet-unknown total request size (Transfer-Encoding: chunked)*/ diff --git a/src/mod_sockproxy.c b/src/mod_sockproxy.c index 38f58bb4..949d1cd4 100644 --- a/src/mod_sockproxy.c +++ b/src/mod_sockproxy.c @@ -126,7 +126,7 @@ SETDEFAULTS_FUNC(mod_sockproxy_set_defaults) { static handler_t sockproxy_create_env_connect(handler_ctx *hctx) { connection *con = hctx->remote_conn; - con->file_started = 1; + con->response.resp_body_started = 1; gw_set_transparent(hctx); http_response_upgrade_read_body_unknown(con); diff --git a/src/mod_ssi.c b/src/mod_ssi.c index d29cd6ac..fe2179e9 100644 --- a/src/mod_ssi.c +++ b/src/mod_ssi.c @@ -1203,8 +1203,8 @@ static int mod_ssi_handle_request(connection *con, handler_ctx *p) { if (mod_ssi_process_file(con, p, &st)) return -1; - con->file_started = 1; - con->file_finished = 1; + con->response.resp_body_started = 1; + con->response.resp_body_finished = 1; if (buffer_string_is_empty(p->conf.content_type)) { http_header_response_set(con, HTTP_HEADER_CONTENT_TYPE, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html")); diff --git a/src/mod_status.c b/src/mod_status.c index 123d01fe..9d895882 100644 --- a/src/mod_status.c +++ b/src/mod_status.c @@ -494,7 +494,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c buffer_append_string_len(b, CONST_STR_LEN("