nginx-0.0.1-2003-10-21-20:49:56 import

This commit is contained in:
Igor Sysoev 2003-10-21 16:49:56 +00:00
parent 9760a1336f
commit 419f9aceb4
20 changed files with 353 additions and 301 deletions

View File

@ -147,18 +147,6 @@ void ngx_chain_update_chains(ngx_chain_t **free, ngx_chain_t **busy,
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) {

View File

@ -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 do_write)
}
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_event_proxy_t *p)
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" _ chain->hunk->pos _ chain->hunk->end - ch
} 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" _ chain->hunk->pos _ chain->hunk->end - ch
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" _ ce->hunk->pos _ ce->hunk->end - ce->hunk
}
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" _ ce->hunk->pos _ ce->hunk->end - ce->hunk
}
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(ngx_event_proxy_t *p)
}
}
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(out->hunk) > p->max_busy_len))
{
if (!(p->upstream_eof || p->upstream_error || p->upstream_done)
&& (busy_len + ngx_hunk_size(ce->hunk) > p->max_busy_len))
{
break;
}
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);
busy_len += ngx_hunk_size(ce->hunk);
ce->next = NULL;
ngx_chain_add_ce(out, le, ce);
}
} else if (!p->cachable && p->in) {
out = p->in;
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(ngx_event_proxy_t *p)
/* 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->hunk->shadow);
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_to_temp_file(ngx_event_proxy_t *p)
}
}
out = p->in;
if (!p->cachable) {
size = 0;
@ -407,21 +408,21 @@ ngx_log_debug(p->log, "hunk size: %d" _ hunk_size);
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_partially_filled_hunk(ngx_chain_t **chain,
}
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;

View File

@ -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_ */

View File

@ -39,7 +39,7 @@ static int ngx_http_chunked_header_filter(ngx_http_request_t *r)
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;

View File

@ -157,8 +157,9 @@ static int ngx_http_gzip_header_filter(ngx_http_request_t *r)
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);

View File

@ -54,7 +54,8 @@ static int ngx_http_not_modified_header_filter(ngx_http_request_t *r)
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;

View File

@ -49,7 +49,7 @@ static int ngx_http_range_header_filter(ngx_http_request_t *r)
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(ngx_http_request_t *r)
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_http_request_t *r)
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(ngx_http_request_t *r)
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(ngx_http_request_t *r)
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(ngx_http_request_t *r)
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(ngx_http_request_t *r)
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;
}
}

View File

@ -191,6 +191,7 @@ static int ngx_http_static_handler(ngx_http_request_t *r)
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_http_request_t *r)
#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_http_request_t *r)
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);
}

View File

@ -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(ngx_http_proxy_ctx_t *p)
{
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(ngx_http_proxy_ctx_t *p)
}
}
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(ngx_http_proxy_ctx_t *p)
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(ngx_http_proxy_ctx_t *p)
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(ngx_http_proxy_ctx_t *p)
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_event_t *ev)
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(ngx_event_t *ev)
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(ngx_event_t *ev)
}
} 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_conf(ngx_conf_t *cf)
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);

View File

@ -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;

View File

@ -130,13 +130,6 @@ static ngx_command_t ngx_http_core_commands[] = {
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 *r)
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_request_t *r)
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: %d" _ 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_conf(ngx_conf_t *cf)
*/
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_conf(ngx_conf_t *cf,
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);

View File

@ -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 */

View File

@ -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_ */

View File

@ -159,9 +159,11 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
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_http_request_t *r)
*(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) {

View File

@ -84,11 +84,11 @@ ngx_module_t ngx_http_output_filter_module = {
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_request_t *r, ngx_hunk_t *hunk)
/*
* 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,

View File

@ -9,6 +9,7 @@ static void ngx_http_init_request(ngx_event_t *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_port);
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_line(ngx_event_t *rev)
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_headers(ngx_event_t *rev)
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;
rc = ngx_http_process_request_header(r);
/* 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);
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_header(ngx_http_request_t *r)
}
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_event_t *wev)
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);
}

View File

@ -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;

View File

@ -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(ngx_http_request_t *r, int error)
}
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(ngx_http_request_t *r, int error)
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(ngx_http_request_t *r, int error)
return NGX_OK;
}
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
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);
}

View File

@ -5,11 +5,6 @@
#include <ngx_http.h>
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(ngx_cycle_t *cycle);
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_request_t *r, ngx_chain_t *in)
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_request_t *r, ngx_chain_t *in)
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_create_conf(ngx_conf_t *cf)
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_conf(ngx_conf_t *cf,
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;
}

View File

@ -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;
}