Mercurial > hg > nginx-quic
changeset 153:c71aeb75c071
nginx-0.0.1-2003-10-21-20:49:56 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 21 Oct 2003 16:49:56 +0000 |
parents | fb48bf4fea1c |
children | eac26585476e |
files | src/core/ngx_hunk.c src/event/ngx_event_pipe.c src/event/ngx_event_pipe.h src/event/ngx_event_proxy.c src/event/ngx_event_proxy.h src/http/modules/ngx_http_chunked_filter.c src/http/modules/ngx_http_gzip_filter.c src/http/modules/ngx_http_not_modified_filter.c src/http/modules/ngx_http_range_filter.c src/http/modules/ngx_http_static_handler.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_filter.h src/http/ngx_http_header_filter.c src/http/ngx_http_output_filter.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_special_response.c src/http/ngx_http_write_filter.c src/os/unix/ngx_freebsd_sendfile_chain.c |
diffstat | 20 files changed, 353 insertions(+), 301 deletions(-) [+] |
line wrap: on
line diff
--- a/src/core/ngx_hunk.c +++ b/src/core/ngx_hunk.c @@ -147,18 +147,6 @@ void ngx_chain_update_chains(ngx_chain_t if (ngx_hunk_size((*busy)->hunk) > 0) { break; } -#if 0 - if ((*busy)->hunk->type & NGX_HUNK_IN_MEMORY) { - if ((*busy)->hunk->pos != (*busy)->hunk->last) { - break; - } - - } else { - if ((*busy)->hunk->file_pos != (*busy)->hunk->file_last) { - break; - } - } -#endif #if (HAVE_WRITE_ZEROCOPY) if ((*busy)->hunk->type & NGX_HUNK_ZEROCOPY_BUSY) {
rename from src/event/ngx_event_proxy.c rename to src/event/ngx_event_pipe.c --- a/src/event/ngx_event_proxy.c +++ b/src/event/ngx_event_pipe.c @@ -2,29 +2,33 @@ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> -#include <ngx_event_proxy.h> +#include <ngx_event_pipe.h> + -static int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p); +static int ngx_event_pipe_read_upstream(ngx_event_pipe_t *p); +static int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p); + +static int ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p); ngx_inline static void ngx_remove_shadow_links(ngx_hunk_t *hunk); ngx_inline static void ngx_remove_shadow_free_raw_hunk(ngx_chain_t **free, ngx_hunk_t *h); ngx_inline static void ngx_add_after_partially_filled_hunk(ngx_chain_t **chain, ngx_chain_t *ce); -static int ngx_drain_chains(ngx_event_proxy_t *p); +static int ngx_drain_chains(ngx_event_pipe_t *p); -int ngx_event_proxy(ngx_event_proxy_t *p, int do_write) +int ngx_event_pipe(ngx_event_pipe_t *p, int do_write) { for ( ;; ) { if (do_write) { - if (ngx_event_proxy_write_to_downstream(p) == NGX_ABORT) { + if (ngx_event_pipe_write_to_downstream(p) == NGX_ABORT) { return NGX_ABORT; } } p->read = 0; - if (ngx_event_proxy_read_upstream(p) == NGX_ABORT) { + if (ngx_event_pipe_read_upstream(p) == NGX_ABORT) { return NGX_ABORT; } @@ -48,7 +52,7 @@ int ngx_event_proxy(ngx_event_proxy_t *p } -int ngx_event_proxy_read_upstream(ngx_event_proxy_t *p) +int ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) { int n, rc, size; ngx_hunk_t *h; @@ -116,7 +120,6 @@ int ngx_event_proxy_read_upstream(ngx_ev chain = p->free_raw_hunks; p->free_raw_hunks = NULL; -ngx_log_debug(p->log, "FREE: %08X:%d" _ chain->hunk->pos _ chain->hunk->end - chain->hunk->last); } else if (p->hunks < p->bufs.num) { @@ -133,22 +136,22 @@ ngx_log_debug(p->log, "FREE: %08X:%d" _ } else if (!p->cachable && p->downstream->write->ready) { /* - * If the hunks are not needed to be saved in a cache and - * a downstream is ready then write the hunks to a downstream. + * if the hunks are not needed to be saved in a cache and + * a downstream is ready then write the hunks to a downstream */ ngx_log_debug(p->log, "downstream ready"); break; - } else if (p->temp_offset < p->max_temp_file_size) { + } else if (p->cachable || p->temp_offset < p->max_temp_file_size) { /* - * If it's allowed then save some hunks from r->in - * to a temporary file, and add them to a r->out chain. + * if it's allowed then save some hunks from r->in + * to a temporary file, and add them to a r->out chain */ - rc = ngx_event_proxy_write_chain_to_temp_file(p); + rc = ngx_event_pipe_write_chain_to_temp_file(p); ngx_log_debug(p->log, "temp offset: %d" _ p->temp_offset); @@ -223,9 +226,7 @@ ngx_log_debug(p->log, "FREE: %08X:%d" _ ce = ce->next; } else { -ngx_log_debug(p->log, "PART: %08X:%d:%d" _ ce->hunk->pos _ ce->hunk->last - ce->hunk->pos _ n); ce->hunk->last += n; -ngx_log_debug(p->log, "PART: %08X:%d" _ ce->hunk->pos _ ce->hunk->end - ce->hunk->last); n = 0; } } @@ -243,7 +244,7 @@ ngx_log_debug(p->log, "PART: %08X:%d" _ } if (p->cachable && p->in) { - if (ngx_event_proxy_write_chain_to_temp_file(p) == NGX_ABORT) { + if (ngx_event_pipe_write_chain_to_temp_file(p) == NGX_ABORT) { return NGX_ABORT; } } @@ -252,11 +253,11 @@ ngx_log_debug(p->log, "PART: %08X:%d" _ } -int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p) +int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) { size_t busy_len; ngx_hunk_t *h; - ngx_chain_t *out, *ce, *te; + ngx_chain_t *out, **le, *ce, *te; ngx_log_debug(p->log, "write downstream: %d" _ p->downstream->write->ready); @@ -285,38 +286,47 @@ int ngx_event_proxy_write_to_downstream( } } + out = NULL; + le = NULL; - if (p->out) { - out = p->out; + for ( ;; ) { + if (p->out) { + ce = p->out; + + if (!(p->upstream_eof || p->upstream_error || p->upstream_done) + && (busy_len + ngx_hunk_size(ce->hunk) > p->max_busy_len)) + { + break; + } - if (!(p->upstream_eof || p->upstream_error || p->upstream_done) - && (busy_len + ngx_hunk_size(out->hunk) > p->max_busy_len)) - { + p->out = p->out->next; + ngx_remove_shadow_free_raw_hunk(&p->free_raw_hunks, ce->hunk); + + } else if (!p->cachable && p->in) { + ce = p->in; + + if (!(p->upstream_eof || p->upstream_error || p->upstream_done) + && (busy_len + ngx_hunk_size(ce->hunk) > p->max_busy_len)) + { + break; + } + + p->in = p->in->next; + + } else { break; } - p->out = p->out->next; - ngx_remove_shadow_free_raw_hunk(&p->free_raw_hunks, out->hunk); - - } else if (!p->cachable && p->in) { - out = p->in; + busy_len += ngx_hunk_size(ce->hunk); + ce->next = NULL; + ngx_chain_add_ce(out, le, ce); + } - if (!(p->upstream_eof || p->upstream_error || p->upstream_done) - && (busy_len + ngx_hunk_size(out->hunk) > p->max_busy_len)) - { - break; - } - - p->in = p->in->next; - - } else { + if (out == NULL) { break; } - out->next = NULL; - - - if (p->output_filter(p->output_ctx, out->hunk) == NGX_ERROR) { + if (p->output_filter(p->output_ctx, out) == NGX_ERROR) { p->downstream_error = 1; continue; } @@ -326,7 +336,6 @@ int ngx_event_proxy_write_to_downstream( /* add the free shadow raw hunks to p->free_raw_hunks */ for (ce = p->free; ce; ce = ce->next) { -ngx_log_debug(p->log, "SHADOW %08X" _ ce->hunk->shadow); if (ce->hunk->type & NGX_HUNK_LAST_SHADOW) { h = ce->hunk->shadow; /* THINK NEEDED ??? */ h->pos = h->last = h->start; @@ -334,31 +343,21 @@ ngx_log_debug(p->log, "SHADOW %08X" _ ce ngx_alloc_ce_and_set_hunk(te, h, p->pool, NGX_ABORT); ngx_add_after_partially_filled_hunk(&p->free_raw_hunks, te); -ngx_log_debug(p->log, "RAW %08X" _ h->pos); - ce->hunk->type &= ~NGX_HUNK_LAST_SHADOW; } ce->hunk->shadow = NULL; } } - ngx_log_debug(p->log, "STATE %d:%d:%d:%X:%X" _ - p->upstream_eof _ - p->upstream_error _ - p->upstream_done _ - p->in _ - p->out - ); - return NGX_OK; } -static int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p) +static int ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p) { int rc, size, hunk_size; ngx_hunk_t *h; - ngx_chain_t *ce, *te, *next, *in, **le, **last_free; + ngx_chain_t *ce, *te, *next, *out, **le, **last_free; ngx_log_debug(p->log, "write to file"); @@ -379,6 +378,8 @@ static int ngx_event_proxy_write_chain_t } } + out = p->in; + if (!p->cachable) { size = 0; @@ -407,21 +408,21 @@ ngx_log_debug(p->log, "hunk size: %d" _ ngx_log_debug(p->log, "size: %d" _ size); if (ce) { - in = ce; + p->in = ce; *le = NULL; } else { - in = NULL; + p->in = NULL; p->last_in = &p->in; } } else { - in = NULL; + p->in = NULL; p->last_in = &p->in; } - if (ngx_write_chain_to_file(p->temp_file, p->in, p->temp_offset, - p->pool) == NGX_ERROR) { + if (ngx_write_chain_to_file(p->temp_file, out, p->temp_offset, + p->pool) == NGX_ERROR) { return NGX_ABORT; } @@ -432,7 +433,7 @@ ngx_log_debug(p->log, "size: %d" _ size) /* void */ } - for (ce = p->in; ce; ce = next) { + for (ce = out; ce; ce = next) { next = ce->next; ce->next = NULL; @@ -453,15 +454,13 @@ ngx_log_debug(p->log, "size: %d" _ size) } } - p->in = in; - return NGX_OK; } /* the copy input filter */ -int ngx_event_proxy_copy_input_filter(ngx_event_proxy_t *p, ngx_hunk_t *hunk) +int ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_hunk_t *hunk) { ngx_hunk_t *h; ngx_chain_t *ce; @@ -567,7 +566,7 @@ ngx_inline static void ngx_add_after_par } -static int ngx_drain_chains(ngx_event_proxy_t *p) +static int ngx_drain_chains(ngx_event_pipe_t *p) { ngx_hunk_t *h; ngx_chain_t *ce, *te;
rename from src/event/ngx_event_proxy.h rename to src/event/ngx_event_pipe.h --- a/src/event/ngx_event_proxy.h +++ b/src/event/ngx_event_pipe.h @@ -1,5 +1,5 @@ -#ifndef _NGX_EVENT_PROXY_H_INCLUDED_ -#define _NGX_EVENT_PROXY_H_INCLUDED_ +#ifndef _NGX_EVENT_PIPE_H_INCLUDED_ +#define _NGX_EVENT_PIPE_H_INCLUDED_ #include <ngx_config.h> @@ -7,14 +7,14 @@ #include <ngx_event.h> -typedef struct ngx_event_proxy_s ngx_event_proxy_t; +typedef struct ngx_event_pipe_s ngx_event_pipe_t; -typedef int (*ngx_event_proxy_input_filter_pt)(ngx_event_proxy_t *p, - ngx_hunk_t *hunk); -typedef int (*ngx_event_proxy_output_filter_pt)(void *data, ngx_hunk_t *hunk); +typedef int (*ngx_event_pipe_input_filter_pt)(ngx_event_pipe_t *p, + ngx_hunk_t *hunk); +typedef int (*ngx_event_pipe_output_filter_pt)(void *data, ngx_chain_t *chain); -struct ngx_event_proxy_s { +struct ngx_event_pipe_s { ngx_chain_t *free_raw_hunks; ngx_chain_t *in; ngx_chain_t **last_in; @@ -30,10 +30,10 @@ struct ngx_event_proxy_s { * from the raw hunks to an incoming chain */ - ngx_event_proxy_input_filter_pt input_filter; + ngx_event_pipe_input_filter_pt input_filter; void *input_ctx; - ngx_event_proxy_output_filter_pt output_filter; + ngx_event_pipe_output_filter_pt output_filter; void *output_ctx; unsigned read:1; @@ -68,12 +68,8 @@ struct ngx_event_proxy_s { }; -int ngx_event_proxy(ngx_event_proxy_t *p, int do_write); -int ngx_event_proxy_copy_input_filter(ngx_event_proxy_t *p, ngx_hunk_t *hunk); - -/* STUB */ -int ngx_event_proxy_read_upstream(ngx_event_proxy_t *p); -int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p); +int ngx_event_pipe(ngx_event_pipe_t *p, int do_write); +int ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_hunk_t *hunk); -#endif /* _NGX_EVENT_PROXY_H_INCLUDED_ */ +#endif /* _NGX_EVENT_PIPE_H_INCLUDED_ */
--- a/src/http/modules/ngx_http_chunked_filter.c +++ b/src/http/modules/ngx_http_chunked_filter.c @@ -39,7 +39,7 @@ static int ngx_http_chunked_header_filte return next_header_filter(r); } - if (r->headers_out.content_length == -1) { + if (r->headers_out.content_length_n == -1) { if (r->http_version < NGX_HTTP_VERSION_11) { r->keepalive = 0;
--- a/src/http/modules/ngx_http_gzip_filter.c +++ b/src/http/modules/ngx_http_gzip_filter.c @@ -157,8 +157,9 @@ static int ngx_http_gzip_header_filter(n r->headers_out.content_encoding->value.len = 4; r->headers_out.content_encoding->value.data = "gzip"; - ctx->length = r->headers_out.content_length; - r->headers_out.content_length = -1; + ctx->length = r->headers_out.content_length_n; + r->headers_out.content_length_n = -1; + r->headers_out.content_length = NULL; r->filter |= NGX_HTTP_FILTER_NEED_IN_MEMORY; return next_header_filter(r);
--- a/src/http/modules/ngx_http_not_modified_filter.c +++ b/src/http/modules/ngx_http_not_modified_filter.c @@ -54,7 +54,8 @@ static int ngx_http_not_modified_header_ if (ims != NGX_ERROR && ims == r->headers_out.last_modified_time) { r->headers_out.status = NGX_HTTP_NOT_MODIFIED; - r->headers_out.content_length = -1; + r->headers_out.content_length_n = -1; + r->headers_out.content_length = NULL; r->headers_out.content_type->key.len = 0; r->headers_out.content_type = NULL; r->headers_out.accept_ranges->key.len = 0;
--- a/src/http/modules/ngx_http_range_filter.c +++ b/src/http/modules/ngx_http_range_filter.c @@ -49,7 +49,7 @@ static int ngx_http_range_header_filter( if (r->main || r->http_version < NGX_HTTP_VERSION_10 || r->headers_out.status != NGX_HTTP_OK - || r->headers_out.content_length == -1 + || r->headers_out.content_length_n == -1 /* STUB: we currently support ranges for file hunks only */ || r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) { @@ -103,7 +103,7 @@ static int ngx_http_range_header_filter( break; } - if (start >= r->headers_out.content_length) { + if (start >= r->headers_out.content_length_n) { rc = NGX_HTTP_RANGE_NOT_SATISFIABLE; break; } @@ -114,7 +114,7 @@ static int ngx_http_range_header_filter( ngx_test_null(range, ngx_push_array(&r->headers_out.ranges), NGX_ERROR); range->start = start; - range->end = r->headers_out.content_length; + range->end = r->headers_out.content_length_n; if (*p++ == ',') { continue; @@ -139,7 +139,7 @@ static int ngx_http_range_header_filter( break; } - if (end >= r->headers_out.content_length || start >= end) { + if (end >= r->headers_out.content_length_n || start >= end) { rc = NGX_HTTP_RANGE_NOT_SATISFIABLE; break; } @@ -170,9 +170,10 @@ static int ngx_http_range_header_filter( r->headers_out.content_range->value.len = ngx_snprintf(r->headers_out.content_range->value.data, 8 + 20 + 1, "bytes */" OFF_FMT, - r->headers_out.content_length); + r->headers_out.content_length_n); - r->headers_out.content_length = -1; + r->headers_out.content_length_n = -1; + r->headers_out.content_length = NULL; return rc; @@ -193,9 +194,9 @@ static int ngx_http_range_header_filter( 6 + 20 + 1 + 20 + 1 + 20 + 1, "bytes " OFF_FMT "-" OFF_FMT "/" OFF_FMT, range->start, range->end - 1, - r->headers_out.content_length); + r->headers_out.content_length_n); - r->headers_out.content_length = range->end - range->start; + r->headers_out.content_length_n = range->end - range->start; } else { @@ -267,13 +268,14 @@ static int ngx_http_range_header_filter( 20 + 1 + 20 + 1 + 20 + 5, OFF_FMT "-" OFF_FMT "/" OFF_FMT CRLF CRLF, range[i].start, range[i].end - 1, - r->headers_out.content_length); + r->headers_out.content_length_n); len += ctx->boundary_header.len + range[i].content_range.len + (size_t) (range[i].end - range[i].start); } - r->headers_out.content_length = len; + r->headers_out.content_length_n = len; + r->headers_out.content_length = NULL; } }
--- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -191,6 +191,7 @@ static int ngx_http_static_handler(ngx_h ngx_log_e level; ngx_err_t err; ngx_hunk_t *h; + ngx_chain_t out; ngx_http_type_t *type; ngx_http_log_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; @@ -257,7 +258,7 @@ static int ngx_http_static_handler(ngx_h #endif r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length = ngx_file_size(r->file.info); + r->headers_out.content_length_n = ngx_file_size(r->file.info); r->headers_out.last_modified_time = ngx_file_mtime(r->file.info); ngx_test_null(r->headers_out.content_type, @@ -317,7 +318,10 @@ static int ngx_http_static_handler(ngx_h h->file->fd = r->file.fd; h->file->log = r->connection->log; - return ngx_http_output_filter(r, h); + out.hunk = h; + out.next = NULL; + + return ngx_http_output_filter(r, &out); }
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -2,8 +2,8 @@ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> -/* STUB */ #include <ngx_event_connect.h> -/* STUB */ #include <ngx_event_proxy.h> +#include <ngx_event_connect.h> +#include <ngx_event_pipe.h> #include <ngx_http.h> #include <ngx_http_proxy_handler.h> @@ -632,12 +632,13 @@ static void ngx_http_proxy_send_response { int rc, i; ngx_table_elt_t *ch, *ph; - ngx_event_proxy_t *ep; + ngx_event_pipe_t *ep; ngx_http_request_t *r; r = p->request; - r->headers_out.content_length = -1; + r->headers_out.content_length_n = -1; + r->headers_out.content_length = NULL; /* copy an upstream header to r->headers_out */ @@ -655,13 +656,6 @@ static void ngx_http_proxy_send_response } } - if (&ph[i] == p->headers_in.content_length) { - r->headers_out.content_length = - ngx_atoi(p->headers_in.content_length->value.data, - p->headers_in.content_length->value.len); - continue; - } - ch = ngx_push_table(r->headers_out.headers); if (ch == NULL) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -675,6 +669,14 @@ static void ngx_http_proxy_send_response r->headers_out.content_type->key.len = 0; continue; } + + if (&ph[i] == p->headers_in.content_length) { + r->headers_out.content_length_n = + ngx_atoi(p->headers_in.content_length->value.data, + p->headers_in.content_length->value.len); + r->headers_out.content_length = ch; + continue; + } } /* STUB */ @@ -700,14 +702,14 @@ static void ngx_http_proxy_send_response p->header_sent = 1; - ep = ngx_pcalloc(r->pool, sizeof(ngx_event_proxy_t)); + ep = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); if (ep == NULL) { ngx_http_proxy_finalize_request(p, 0); return; } - ep->input_filter = ngx_event_proxy_copy_input_filter; - ep->output_filter = (ngx_event_proxy_output_filter_pt) + ep->input_filter = ngx_event_pipe_copy_input_filter; + ep->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter; ep->output_ctx = r; ep->bufs = p->lcf->bufs; @@ -743,14 +745,17 @@ static void ngx_http_proxy_send_response ep->preread_size = p->header_in->last - p->header_in->pos; /* - * event_proxy would do p->header_in->last += ep->preread_size - * as these bytes were read. + * event_pipe would do p->header_in->last += ep->preread_size + * as though these bytes were read. */ p->header_in->last = p->header_in->pos; - /* STUB */ ep->cachable = 0; + /* STUB */ ep->cachable = 1; +#if 0 + ep->max_temp_file_size = 1000000000; +#endif - p->event_proxy = ep; + p->event_pipe = ep; #if 0 lcx = p->log->data; @@ -771,7 +776,7 @@ static void ngx_http_proxy_process_body( ngx_connection_t *c; ngx_http_request_t *r; ngx_http_proxy_ctx_t *p; - ngx_event_proxy_t *ep; + ngx_event_pipe_t *ep; c = ev->data; @@ -786,7 +791,7 @@ static void ngx_http_proxy_process_body( r = p->request; } - ep = p->event_proxy; + ep = p->event_pipe; if (ev->timedout) { if (ev->write) { @@ -797,7 +802,7 @@ static void ngx_http_proxy_process_body( } } else { - if (ngx_event_proxy(ep, ev->write) == NGX_ABORT) { + if (ngx_event_pipe(ep, ev->write) == NGX_ABORT) { ngx_http_proxy_finalize_request(p, 0); return; } @@ -1159,14 +1164,14 @@ static void *ngx_http_proxy_create_loc_c conf->bufs.num = 10; conf->bufs.size = 4096; - conf->max_busy_len = 8192 + 4096; + conf->max_busy_len = 8192; /* CHECK in _init conf->max_temp_size >= conf->bufs.size !!! */ conf->max_temp_file_size = 4096 * 6; - conf->temp_file_write_size = 4096 * 2; + conf->temp_file_write_size = 4096 * 1; ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)), NULL);
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -48,6 +48,8 @@ typedef struct { ngx_table_elt_t *last_modified; ngx_table_elt_t *accept_ranges; + off_t content_length_n; + ngx_table_t *headers; } ngx_http_proxy_headers_in_t; @@ -74,7 +76,7 @@ struct ngx_http_proxy_ctx_s { int location_len; ngx_str_t host_header; - ngx_event_proxy_t *event_proxy; + ngx_event_pipe_t *event_pipe; unsigned accel:1; unsigned cachable:1;
--- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -130,13 +130,6 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, doc_root), NULL}, - {ngx_string("sendfile"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, sendfile), - NULL}, - {ngx_string("send_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -207,15 +200,22 @@ void ngx_http_handler(ngx_http_request_t lcx = r->connection->log->data; lcx->action = NULL; - /* STUB */ - r->keepalive = 1; - if (r->headers_in.connection) { - if (r->headers_in.connection->value.len == 5 - && ngx_strcasecmp(r->headers_in.connection->value.data, "close") - == 0) - { + switch (r->headers_in.connection_type) { + case 0: + if (r->http_version > NGX_HTTP_VERSION_10) { + r->keepalive = 1; + } else { r->keepalive = 0; } + break; + + case NGX_HTTP_CONNECTION_CLOSE: + r->keepalive = 0; + break; + + case NGX_HTTP_CONNECTION_KEEP_ALIVE: + r->keepalive = 1; + break; } #if 0 @@ -331,9 +331,10 @@ static void ngx_http_run_phases(ngx_http int ngx_http_find_location_config(ngx_http_request_t *r) { - int i, rc; - ngx_http_core_loc_conf_t *clcf, **clcfp; - ngx_http_core_srv_conf_t *cscf; + int i, rc; + ngx_http_core_loc_conf_t *clcf, **clcfp; + ngx_http_core_srv_conf_t *cscf; + ngx_http_write_filter_conf_t *wcf; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); @@ -363,12 +364,14 @@ ngx_log_debug(r->connection->log, "rc: % } } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + wcf = ngx_http_get_module_loc_conf(r, ngx_http_write_filter_module); - if (!(ngx_io.flags & NGX_IO_SENDFILE) || !clcf->sendfile) { + if (!(ngx_io.flags & NGX_IO_SENDFILE) || !wcf->sendfile) { r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (clcf->handler) { /* * if the location already has content handler then skip @@ -825,8 +828,6 @@ static void *ngx_http_core_create_loc_co */ - lcf->sendfile = NGX_CONF_UNSET; - lcf->send_timeout = NGX_CONF_UNSET; lcf->discarded_buffer_size = NGX_CONF_UNSET; lcf->keepalive_timeout = NGX_CONF_UNSET; @@ -895,7 +896,6 @@ static char *ngx_http_core_merge_loc_con ngx_conf_merge_str_value(conf->default_type, prev->default_type, "text/plain"); - ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 10000); ngx_conf_merge_size_value(conf->discarded_buffer_size, prev->discarded_buffer_size, 1500);
--- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -110,7 +110,6 @@ typedef struct { ngx_array_t *types; ngx_str_t default_type; - int sendfile; /* sendfile */ ngx_msec_t send_timeout; /* send_timeout */ ssize_t send_lowat; /* send_lowat */ ssize_t discarded_buffer_size; /* discarded_buffer_size */
--- a/src/http/ngx_http_filter.h +++ b/src/http/ngx_http_filter.h @@ -7,12 +7,20 @@ #define NGX_HTTP_FILTER_NEED_TEMP 4 -int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk); +typedef struct { + ssize_t buffer_output; + int sendfile; +} ngx_http_write_filter_conf_t; + + +int ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in); int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in); extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r); extern int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch); +extern ngx_module_t ngx_http_write_filter_module; + #endif /* _NGX_HTTP_FILTER_H_INCLUDED_ */
--- a/src/http/ngx_http_header_filter.c +++ b/src/http/ngx_http_header_filter.c @@ -159,9 +159,11 @@ static int ngx_http_header_filter(ngx_ht len += 15 + r->headers_out.content_range->value.len + 2; } - if (r->headers_out.content_length >= 0) { - /* "Content-Length: ... \r\n", 2^64 is 20 characters */ - len += 48; + if (r->headers_out.content_length == NULL) { + if (r->headers_out.content_length_n >= 0) { + /* "Content-Length: ... \r\n", 2^64 is 20 characters */ + len += 48; + } } if (r->headers_out.content_type && r->headers_out.content_type->value.len) { @@ -260,11 +262,13 @@ static int ngx_http_header_filter(ngx_ht *(h->last++) = CR; *(h->last++) = LF; } - /* 2^64 is 20 characters */ - if (r->headers_out.content_length >= 0) { - h->last += ngx_snprintf(h->last, 49, - "Content-Length: " OFF_FMT CRLF, - r->headers_out.content_length); + if (r->headers_out.content_length == NULL) { + /* 2^64 is 20 characters */ + if (r->headers_out.content_length_n >= 0) { + h->last += ngx_snprintf(h->last, 49, + "Content-Length: " OFF_FMT CRLF, + r->headers_out.content_length_n); + } } if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
--- a/src/http/ngx_http_output_filter.c +++ b/src/http/ngx_http_output_filter.c @@ -84,11 +84,11 @@ ngx_module_t ngx_http_output_filter_mod -int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) +int ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in) { int rc, last; ssize_t size; - ngx_chain_t out, *ce, **le; + ngx_chain_t *ce; ngx_http_output_filter_ctx_t *ctx; ngx_http_output_filter_conf_t *conf; @@ -103,33 +103,27 @@ int ngx_http_output_filter(ngx_http_requ /* * the short path for the case when the chain ctx->in is empty - * and there's no hunk or the hunk does not require the copy + * and the incoming chain is empty too or it has the single hunk + * that does not require the copy */ if (ctx->in == NULL) { - if (hunk == NULL) { - return ngx_next_filter(r, NULL); + if (in == NULL) { + return ngx_next_filter(r, in); } - if (!need_to_copy(r, hunk)) { - out.hunk = hunk; - out.next = NULL; - return ngx_next_filter(r, &out); + if (in->next == NULL && (!need_to_copy(r, in->hunk))) { + return ngx_next_filter(r, in); } } /* add the incoming hunk to the chain ctx->in */ - if (hunk) { - le = &ctx->in; - - for (ce = ctx->in; ce; ce = ce->next) { - le = &ce->next; + if (in) { + if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) { + return NGX_ERROR; } - - ngx_add_hunk_to_chain(ce, hunk, r->pool, NGX_ERROR); - *le = ce; } conf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
--- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -9,6 +9,7 @@ static void ngx_http_init_request(ngx_ev static void ngx_http_process_request_line(ngx_event_t *rev); static void ngx_http_process_request_headers(ngx_event_t *rev); static ssize_t ngx_http_read_request_header(ngx_http_request_t *r); +static int ngx_http_process_request_header(ngx_http_request_t *r); static void ngx_http_set_write_handler(ngx_http_request_t *r); @@ -256,7 +257,8 @@ ngx_log_debug(rev->log, "IN: %08x" _ in_ r->file.fd = NGX_INVALID_FILE; r->headers_in.content_length_n = -1; - r->headers_out.content_length = -1; + r->headers_in.keep_alive_n = -1; + r->headers_out.content_length_n = -1; r->headers_out.last_modified_time = -1; rev->event_handler = ngx_http_process_request_line; @@ -503,14 +505,11 @@ static void ngx_http_process_request_lin static void ngx_http_process_request_headers(ngx_event_t *rev) { int rc, i, offset; - size_t len; ssize_t n; ngx_table_elt_t *h; ngx_connection_t *c; ngx_http_request_t *r; - ngx_http_server_name_t *name; ngx_http_core_srv_conf_t *cscf; - ngx_http_core_loc_conf_t *clcf; c = rev->data; r = c->data; @@ -604,59 +603,11 @@ static void ngx_http_process_request_hea ngx_log_debug(r->connection->log, "HTTP header done"); - if (r->headers_in.host) { - for (len = 0; len < r->headers_in.host->value.len; len++) { - if (r->headers_in.host->value.data[len] == ':') { - break; - } - } - r->headers_in.host_name_len = len; - - /* find the name based server configuration */ - - name = r->virtual_names->elts; - for (i = 0; i < r->virtual_names->nelts; i++) { - if (r->headers_in.host_name_len != name[i].name.len) { - continue; - } - - if (ngx_strncasecmp(r->headers_in.host->value.data, - name[i].name.data, - r->headers_in.host_name_len) == 0) - { - r->srv_conf = name[i].core_srv_conf->ctx->srv_conf; - r->loc_conf = name[i].core_srv_conf->ctx->loc_conf; + rc = ngx_http_process_request_header(r); - clcf = ngx_http_get_module_loc_conf(r, - ngx_http_core_module); - c->log->file = clcf->err_log->file; - c->log->log_level = clcf->err_log->log_level; - - break; - } - } - - } else { - if (r->http_version > NGX_HTTP_VERSION_10) { - ngx_http_header_parse_error(r, - NGX_HTTP_PARSE_NO_HOST_HEADER, - NGX_HTTP_BAD_REQUEST); - return; - } - r->headers_in.host_name_len = 0; - } - - if (r->headers_in.content_length) { - r->headers_in.content_length_n = - ngx_atoi(r->headers_in.content_length->value.data, - r->headers_in.content_length->value.len); - - if (r->headers_in.content_length_n == NGX_ERROR) { - ngx_http_header_parse_error(r, - NGX_HTTP_PARSE_INVALID_CL_HEADER, - NGX_HTTP_BAD_REQUEST); - return; - } + if (rc != NGX_OK) { + ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST); + return; } if (r->header_timeout_set) { @@ -766,6 +717,86 @@ static ssize_t ngx_http_read_request_hea } +static int ngx_http_process_request_header(ngx_http_request_t *r) +{ + int i; + size_t len; + ngx_http_server_name_t *name; + ngx_http_core_loc_conf_t *clcf; + + if (r->headers_in.host) { + for (len = 0; len < r->headers_in.host->value.len; len++) { + if (r->headers_in.host->value.data[len] == ':') { + break; + } + } + r->headers_in.host_name_len = len; + + /* find the name based server configuration */ + + name = r->virtual_names->elts; + for (i = 0; i < r->virtual_names->nelts; i++) { + if (r->headers_in.host_name_len != name[i].name.len) { + continue; + } + + if (ngx_strncasecmp(r->headers_in.host->value.data, + name[i].name.data, + r->headers_in.host_name_len) == 0) + { + r->srv_conf = name[i].core_srv_conf->ctx->srv_conf; + r->loc_conf = name[i].core_srv_conf->ctx->loc_conf; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + r->connection->log->file = clcf->err_log->file; + r->connection->log->log_level = clcf->err_log->log_level; + + break; + } + } + + } else { + if (r->http_version > NGX_HTTP_VERSION_10) { + return NGX_HTTP_PARSE_NO_HOST_HEADER; + } + r->headers_in.host_name_len = 0; + } + + if (r->headers_in.content_length) { + r->headers_in.content_length_n = + ngx_atoi(r->headers_in.content_length->value.data, + r->headers_in.content_length->value.len); + + if (r->headers_in.content_length_n == NGX_ERROR) { + return NGX_HTTP_PARSE_INVALID_CL_HEADER; + } + } + + if (r->headers_in.connection) { + if (r->headers_in.connection->value.len == 5 + && ngx_strcasecmp(r->headers_in.connection->value.data, "close") + == 0) + { + r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; + + } else if (r->headers_in.connection->value.len == 10 + && ngx_strcasecmp(r->headers_in.connection->value.data, + "keep-alive") == 0) + { + r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE; + + if (r->headers_in.keep_alive) { + r->headers_in.keep_alive_n = + ngx_atoi(r->headers_in.keep_alive->value.data, + r->headers_in.keep_alive->value.len); + } + } + } + + return NGX_OK; +} + + void ngx_http_finalize_request(ngx_http_request_t *r, int rc) { ngx_log_debug(r->connection->log, "finalize http request"); @@ -1283,12 +1314,15 @@ static void ngx_http_empty_handler(ngx_e int ngx_http_send_last(ngx_http_request_t *r) { - ngx_hunk_t *h; + ngx_hunk_t *h; + ngx_chain_t out; ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); h->type = NGX_HUNK_LAST; + out.hunk = h; + out.next = NULL; - return ngx_http_output_filter(r, h); + return ngx_http_output_filter(r, &out); }
--- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -10,11 +10,11 @@ #define NGX_HTTP_HEAD 2 #define NGX_HTTP_POST 3 -#define NGX_HTTP_CONN_CLOSE 0 -#define NGX_HTTP_CONN_KEEP_ALIVE 1 +#define NGX_HTTP_CONNECTION_CLOSE 1 +#define NGX_HTTP_CONNECTION_KEEP_ALIVE 2 -#define NGX_NONE 1 +#define NGX_NONE 1 #define NGX_HTTP_PARSE_HEADER_DONE 1 @@ -63,9 +63,6 @@ typedef struct { typedef struct { - size_t host_name_len; - ssize_t content_length_n; - ngx_table_elt_t *host; ngx_table_elt_t *connection; ngx_table_elt_t *if_modified_since; @@ -77,6 +74,11 @@ typedef struct { ngx_table_elt_t *user_agent; ngx_table_elt_t *keep_alive; + size_t host_name_len; + ssize_t content_length_n; + size_t connection_type; + ssize_t keep_alive_n; + ngx_table_t *headers; } ngx_http_headers_in_t; @@ -107,6 +109,7 @@ typedef struct { ngx_table_elt_t *server; ngx_table_elt_t *date; ngx_table_elt_t *content_type; + ngx_table_elt_t *content_length; ngx_table_elt_t *content_encoding; ngx_table_elt_t *location; ngx_table_elt_t *last_modified; @@ -118,7 +121,7 @@ typedef struct { ngx_table_t *headers; - off_t content_length; + off_t content_length_n; char *etag; time_t date_time; time_t last_modified_time;
--- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -152,8 +152,9 @@ static ngx_str_t error_pages[] = { int ngx_http_special_response_handler(ngx_http_request_t *r, int error) { - int err, rc; - ngx_hunk_t *h; + int err, rc; + ngx_hunk_t *h; + ngx_chain_t *out, **le, *ce; r->headers_out.status = error; @@ -189,9 +190,9 @@ int ngx_http_special_response_handler(ng } if (error_pages[err].len) { - r->headers_out.content_length = error_pages[err].len - + sizeof(error_tail) - 1 - + sizeof(msie_stub) - 1; + r->headers_out.content_length_n = error_pages[err].len + + sizeof(error_tail) - 1 + + sizeof(msie_stub) - 1; ngx_test_null(r->headers_out.content_type, ngx_push_table(r->headers_out.headers), @@ -203,7 +204,8 @@ int ngx_http_special_response_handler(ng r->headers_out.content_type->value.data = "text/html"; } else { - r->headers_out.content_length = -1; + r->headers_out.content_length_n = -1; + r->headers_out.content_length = NULL; } rc = ngx_http_send_header(r); @@ -216,41 +218,42 @@ int ngx_http_special_response_handler(ng return NGX_OK; } + out = NULL; + le = NULL; + ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); - h->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; h->pos = error_pages[err].data; h->last = error_pages[err].data + error_pages[err].len; - if (ngx_http_output_filter(r, h) == NGX_ERROR) { - return NGX_ERROR; - } + ngx_alloc_ce_and_set_hunk(ce, h, r->pool, NGX_ERROR); + ngx_chain_add_ce(out, le, ce); + ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); - h->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; h->pos = error_tail; h->last = error_tail + sizeof(error_tail) - 1; + ngx_alloc_ce_and_set_hunk(ce, h, r->pool, NGX_ERROR); + ngx_chain_add_ce(out, le, ce); + if (/* STUB: "msie_padding on/off" */ 1 && r->http_version >= NGX_HTTP_VERSION_10 && error >= NGX_HTTP_BAD_REQUEST && error != NGX_HTTP_REQUEST_URI_TOO_LARGE ) { - - if (ngx_http_output_filter(r, h) == NGX_ERROR) { - return NGX_ERROR; - } - ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR); - h->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; h->pos = msie_stub; h->last = msie_stub + sizeof(msie_stub) - 1; + + ngx_alloc_ce_and_set_hunk(ce, h, r->pool, NGX_ERROR); + ngx_chain_add_ce(out, le, ce); } h->type |= NGX_HUNK_LAST; - return ngx_http_output_filter(r, h); + return ngx_http_output_filter(r, out); }
--- a/src/http/ngx_http_write_filter.c +++ b/src/http/ngx_http_write_filter.c @@ -6,11 +6,6 @@ typedef struct { - ssize_t buffer_output; -} ngx_http_write_filter_conf_t; - - -typedef struct { ngx_chain_t *out; } ngx_http_write_filter_ctx_t; @@ -23,6 +18,13 @@ static int ngx_http_write_filter_init(ng static ngx_command_t ngx_http_write_filter_commands[] = { + {ngx_string("sendfile"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_write_filter_conf_t, sendfile), + NULL}, + {ngx_string("buffer_output"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -81,36 +83,7 @@ int ngx_http_write_filter(ngx_http_reque for (ce = ctx->out; ce; ce = ce->next) { le = &ce->next; - if (ce->hunk->type & NGX_HUNK_IN_MEMORY) { - size += ce->hunk->last - ce->hunk->pos; - } else { - size += ce->hunk->file_last - ce->hunk->file_pos; - } - - if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { - flush = size; - } - - if (ce->hunk->type & NGX_HUNK_LAST) { - last = 1; - } - } - - /* add the new chain to the existent one */ - - for (/* void */; in; in = in->next) { - ngx_test_null(ce, ngx_alloc_chain_entry(r->pool), NGX_ERROR); - - ce->hunk = in->hunk; - ce->next = NULL; - *le = ce; - le = &ce->next; - - if (ce->hunk->type & NGX_HUNK_IN_MEMORY) { - size += ce->hunk->last - ce->hunk->pos; - } else { - size += ce->hunk->file_last - ce->hunk->file_pos; - } + size += ngx_hunk_size(ce->hunk); if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { flush = size; @@ -124,6 +97,31 @@ int ngx_http_write_filter(ngx_http_reque conf = ngx_http_get_module_loc_conf(r->main ? r->main : r, ngx_http_write_filter_module); + /* add the new chain to the existent one */ + + for (/* void */; in; in = in->next) { + ngx_test_null(ce, ngx_alloc_chain_entry(r->pool), NGX_ERROR); + + ce->hunk = in->hunk; + ce->next = NULL; + *le = ce; + le = &ce->next; + + if (!(ngx_io.flags & NGX_IO_SENDFILE) || !conf->sendfile) { + ce->hunk->type &= ~NGX_HUNK_FILE; + } + + size += ngx_hunk_size(ce->hunk); + + if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { + flush = size; + } + + if (ce->hunk->type & NGX_HUNK_LAST) { + last = 1; + } + } + #if (NGX_DEBUG_WRITE_FILTER) ngx_log_debug(r->connection->log, "write filter: last:%d flush:%qd size:%qd" _ @@ -176,6 +174,7 @@ static void *ngx_http_write_filter_creat NULL); conf->buffer_output = NGX_CONF_UNSET; + conf->sendfile = NGX_CONF_UNSET; return conf; } @@ -188,6 +187,7 @@ static char *ngx_http_write_filter_merge ngx_http_write_filter_conf_t *conf = child; ngx_conf_merge_size_value(conf->buffer_output, prev->buffer_output, 1460); + ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); return NULL; }
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -154,6 +154,11 @@ ngx_log_debug(c->log, "NOPUSH"); hdtr.trailers = (struct iovec *) trailer.elts; hdtr.trl_cnt = trailer.nelts; + /* + * the old sendfile() "nbytes bug": + * http://www.freebsd.org/cgi/query-pr.cgi?pr=33771 + */ + if (ngx_freebsd_sendfile_nbytes_bug == 0) { hsize = 0; } @@ -194,7 +199,6 @@ ngx_log_debug(c->log, "NOPUSH"); if (rc == -1) { err = ngx_errno; if (err == NGX_EAGAIN) { - eagain = 1; ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN"); } else if (err == NGX_EINTR) { @@ -256,6 +260,11 @@ ngx_log_debug(c->log, "NOPUSH"); in = ce; if (eagain) { + /* + * sendfile() can return EAGAIN even if it has sent + * a whole file part and successive sendfile() would + * return EAGAIN right away and would not send anything. + */ c->write->ready = 0; break; }