nginx-0.0.1-2003-03-11-23:38:13 import

This commit is contained in:
Igor Sysoev 2003-03-11 20:38:13 +00:00
parent 0dad629f63
commit b738757f35
23 changed files with 765 additions and 462 deletions

View File

@ -206,7 +206,7 @@ static int ngx_conf_read_token(ngx_conf_t *cf)
cf->args->nelts = 0; cf->args->nelts = 0;
h = cf->conf_file->hunk; h = cf->conf_file->hunk;
start = h->pos.mem; start = h->pos;
#if 0 #if 0
ngx_log_debug(cf->log, "TOKEN START"); ngx_log_debug(cf->log, "TOKEN START");
@ -214,31 +214,31 @@ ngx_log_debug(cf->log, "TOKEN START");
for ( ;; ) { for ( ;; ) {
if (h->pos.mem >= h->last.mem) { if (h->pos >= h->last) {
if (cf->conf_file->file.offset if (cf->conf_file->file.offset
>= ngx_file_size(cf->conf_file->file.info)) { >= ngx_file_size(cf->conf_file->file.info)) {
return NGX_CONF_FILE_DONE; return NGX_CONF_FILE_DONE;
} }
if (h->pos.mem - start) { if (h->pos - start) {
ngx_memcpy(h->start, start, h->pos.mem - start); ngx_memcpy(h->start, start, h->pos - start);
} }
n = ngx_read_file(&cf->conf_file->file, n = ngx_read_file(&cf->conf_file->file,
h->start + (h->pos.mem - start), h->start + (h->pos - start),
h->end - (h->start + (h->pos.mem - start)), h->end - (h->start + (h->pos - start)),
cf->conf_file->file.offset); cf->conf_file->file.offset);
if (n == NGX_ERROR) { if (n == NGX_ERROR) {
return NGX_ERROR; return NGX_ERROR;
} }
h->pos.mem = h->start + (h->pos.mem - start); h->pos = h->start + (h->pos - start);
start = h->start; start = h->start;
h->last.mem = h->pos.mem + n; h->last = h->pos + n;
} }
ch = *h->pos.mem++; ch = *h->pos++;
#if 0 #if 0
ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _ ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _
@ -282,7 +282,7 @@ ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _
continue; continue;
} }
start = h->pos.mem - 1; start = h->pos - 1;
switch (ch) { switch (ch) {
@ -363,11 +363,11 @@ ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _
if (found) { if (found) {
ngx_test_null(word, ngx_push_array(cf->args), NGX_ERROR); ngx_test_null(word, ngx_push_array(cf->args), NGX_ERROR);
ngx_test_null(word->data, ngx_test_null(word->data,
ngx_palloc(cf->pool, h->pos.mem - start + 1), ngx_palloc(cf->pool, h->pos - start + 1),
NGX_ERROR); NGX_ERROR);
for (dst = word->data, src = start, len = 0; for (dst = word->data, src = start, len = 0;
src < h->pos.mem - 1; src < h->pos - 1;
len++) len++)
{ {
if (*src == '\\') { if (*src == '\\') {

View File

@ -10,16 +10,14 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size,
ngx_test_null(h, ngx_palloc(pool, sizeof(ngx_hunk_t)), NULL); ngx_test_null(h, ngx_palloc(pool, sizeof(ngx_hunk_t)), NULL);
#if !(HAVE_OFFSET_EQUAL_PTR)
h->pos.file = h->last.file = 0;
#endif
ngx_test_null(h->pre_start, ngx_palloc(pool, size + before + after), NULL); ngx_test_null(h->pre_start, ngx_palloc(pool, size + before + after), NULL);
h->start = h->pos.mem = h->last.mem = h->pre_start + before;
h->end = h->last.mem + size; h->start = h->pos = h->last = h->pre_start + before;
h->file_pos = h->file_last = 0;
h->end = h->last + size;
h->post_end = h->end + after; h->post_end = h->end + after;
h->type = NGX_HUNK_TEMP; h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
h->tag = 0; h->tag = 0;
h->file = NULL; h->file = NULL;
@ -32,26 +30,24 @@ ngx_hunk_t *ngx_create_hunk_before(ngx_pool_t *pool, ngx_hunk_t *hunk, int size)
ngx_test_null(h, ngx_palloc(pool, sizeof(ngx_hunk_t)), NULL); ngx_test_null(h, ngx_palloc(pool, sizeof(ngx_hunk_t)), NULL);
#if !(HAVE_OFFSET_EQUAL_PTR) if (hunk->type & NGX_HUNK_TEMP && hunk->pos - hunk->pre_start >= size) {
h->pos.file = h->last.file = 0;
#endif
if (hunk->type & NGX_HUNK_TEMP && hunk->pos.mem - hunk->pre_start >= size) {
/* keep hunk->start unchanged - used in restore */ /* keep hunk->start unchanged - used in restore */
h->pre_start = hunk->pre_start; h->pre_start = hunk->pre_start;
h->end = h->post_end = hunk->pre_start = hunk->pos.mem; h->end = h->post_end = hunk->pre_start = hunk->pos;
h->start = h->pos.mem = h->last.mem = h->end - size; h->start = h->pos = h->last = h->end - size;
h->file_pos = h->file_last = 0;
h->type = NGX_HUNK_TEMP; h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
h->tag = 0; h->tag = 0;
h->file = NULL; h->file = NULL;
} else { } else {
ngx_test_null(h->pre_start, ngx_palloc(pool, size), NULL); ngx_test_null(h->pre_start, ngx_palloc(pool, size), NULL);
h->start = h->pos.mem = h->last.mem = h->pre_start; h->start = h->pos = h->last = h->pre_start;
h->end = h->post_end = h->start + size; h->end = h->post_end = h->start + size;
h->file_pos = h->file_last = 0;
h->type = NGX_HUNK_TEMP; h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
h->tag = 0; h->tag = 0;
h->file = NULL; h->file = NULL;
} }
@ -65,27 +61,26 @@ ngx_hunk_t *ngx_create_hunk_after(ngx_pool_t *pool, ngx_hunk_t *hunk, int size)
ngx_test_null(h, ngx_palloc(pool, sizeof(ngx_hunk_t)), NULL); ngx_test_null(h, ngx_palloc(pool, sizeof(ngx_hunk_t)), NULL);
#if !(HAVE_OFFSET_EQUAL_PTR)
h->pos.file = h->last.file = 0;
#endif
if (hunk->type & NGX_HUNK_TEMP if (hunk->type & NGX_HUNK_TEMP
&& hunk->last.mem == hunk->end && hunk->last == hunk->end
&& hunk->post_end - hunk->end >= size) && hunk->post_end - hunk->end >= size)
{ {
h->post_end = hunk->post_end; h->post_end = hunk->post_end;
h->pre_start = h->start = h->pos.mem = h->last.mem = hunk->post_end = h->pre_start = h->start = h->pos = h->last = hunk->post_end =
hunk->last.mem; hunk->last;
h->type = NGX_HUNK_TEMP; h->file_pos = h->file_last = 0;
h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
h->tag = 0; h->tag = 0;
h->file = NULL; h->file = NULL;
} else { } else {
ngx_test_null(h->pre_start, ngx_palloc(pool, size), NULL); ngx_test_null(h->pre_start, ngx_palloc(pool, size), NULL);
h->start = h->pos.mem = h->last.mem = h->pre_start; h->start = h->pos = h->last = h->pre_start;
h->end = h->post_end = h->start + size; h->end = h->post_end = h->start + size;
h->file_pos = h->file_last = 0;
h->type = NGX_HUNK_TEMP; h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
h->tag = 0; h->tag = 0;
h->file = NULL; h->file = NULL;
} }

View File

@ -10,34 +10,34 @@
/* hunk type */ /* hunk type */
/* temp means that hunk's content can be changed */ /* the hunk is in memory */
/* other type means that hunk's content can not be changed */ #define NGX_HUNK_IN_MEMORY 0x0001
#define NGX_HUNK_TEMP 0x0001 /* the hunk's content can be changed */
#define NGX_HUNK_MEMORY 0x0002 #define NGX_HUNK_TEMP 0x0002
#define NGX_HUNK_MMAP 0x0004 /* the hunk's content is in cache and can not be changed */
#define NGX_HUNK_FILE 0x0008 #define NGX_HUNK_MEMORY 0x0004
/* the hunk's content is mmap()ed and can not be changed */
#define NGX_HUNK_MMAP 0x0008
#define NGX_HUNK_RECYCLED 0x0010
/* the hunk is in file */
#define NGX_HUNK_FILE 0x0100
/* hunk flags */ /* hunk flags */
/* in thread state flush means to write the hunk completely before return */ /* in thread state flush means to write the hunk completely before return */
/* in event state flush means to start to write the hunk */ /* in event state flush means to start to write the hunk */
#define NGX_HUNK_FLUSH 0x0100 #define NGX_HUNK_FLUSH 0x1000
/* last hunk */ /* last hunk */
#define NGX_HUNK_LAST 0x0200 #define NGX_HUNK_LAST 0x2000
#if 0
/* can be used with NGX_HUNK_LAST only */
#define NGX_HUNK_SHUTDOWN 0x0400 /
#endif
#define NGX_HUNK_RECYCLED 0x0800
#define NGX_HUNK_IN_MEMORY (NGX_HUNK_TEMP|NGX_HUNK_MEMORY|NGX_HUNK_MMAP)
typedef struct ngx_hunk_s ngx_hunk_t; typedef struct ngx_hunk_s ngx_hunk_t;
struct ngx_hunk_s { struct ngx_hunk_s {
#if 0
union { union {
char *mem; /* start of current data */ char *mem; /* start of current data */
off_t file; off_t file;
@ -46,6 +46,13 @@ struct ngx_hunk_s {
char *mem; /* end of current data */ char *mem; /* end of current data */
off_t file; off_t file;
} last; } last;
#endif
char *pos;
char *last;
off_t file_pos;
off_t file_last;
int type; int type;
char *start; /* start of hunk */ char *start; /* start of hunk */
char *end; /* end of hunk */ char *end; /* end of hunk */
@ -67,6 +74,10 @@ struct ngx_chain_s {
#define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR #define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR
#define ngx_hunk_in_memory_only(h) \
((h->type & (NGX_HUNK_IN_MEMORY|NGX_HUNK_FILE)) == NGX_HUNK_IN_MEMORY)
ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size, ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size,
int before, int after); int before, int after);

View File

@ -12,6 +12,7 @@ typedef struct {
#define ngx_string(str) { sizeof(str) - 1, str } #define ngx_string(str) { sizeof(str) - 1, str }
#define ngx_null_string { 0, NULL }
#if (WIN32) #if (WIN32)

View File

@ -74,12 +74,17 @@ int ngx_kqueue_init(int max_connections, ngx_log_t *log)
ngx_event_flags = NGX_HAVE_LEVEL_EVENT ngx_event_flags = NGX_HAVE_LEVEL_EVENT
|NGX_HAVE_ONESHOT_EVENT |NGX_HAVE_ONESHOT_EVENT
#if (HAVE_CLEAR_EVENT) #if (HAVE_CLEAR_EVENT)
|NGX_HAVE_CLEAR_EVENT |NGX_HAVE_CLEAR_EVENT
#else
|NGX_USE_LEVEL_EVENT
#endif #endif
#if (HAVE_LOWAT_EVENT) #if (HAVE_LOWAT_EVENT)
|NGX_HAVE_LOWAT_EVENT |NGX_HAVE_LOWAT_EVENT
#endif #endif
|NGX_HAVE_KQUEUE_EVENT; |NGX_HAVE_KQUEUE_EVENT;
ngx_write_chain_proc = ngx_freebsd_write_chain; ngx_write_chain_proc = ngx_freebsd_write_chain;

View File

@ -56,7 +56,6 @@ struct ngx_event_s {
/* otherwise: */ /* otherwise: */
/* accept: 1 if accept many, 0 otherwise */ /* accept: 1 if accept many, 0 otherwise */
unsigned level:1;
unsigned oneshot:1; unsigned oneshot:1;
#if 0 #if 0
@ -73,6 +72,7 @@ struct ngx_event_s {
unsigned process:1; unsigned process:1;
unsigned read_discarded:1; unsigned read_discarded:1;
unsigned ignore_econnreset:1;
unsigned unexpected_eof:1; unsigned unexpected_eof:1;
#if (HAVE_DEFERRED_ACCEPT) #if (HAVE_DEFERRED_ACCEPT)
@ -149,7 +149,7 @@ typedef struct {
#define NGX_HAVE_LEVEL_EVENT 1 #define NGX_HAVE_LEVEL_EVENT 1
/* Event filter is deleted after notification - select, poll, kqueue. /* Event filter is deleted after notification - select, poll, kqueue.
Using /dev/poll, epoll it can be implemented with additional syscall */ Using /dev/poll it can be implemented with additional syscall */
#define NGX_HAVE_ONESHOT_EVENT 2 #define NGX_HAVE_ONESHOT_EVENT 2
/* Event filter notifies only changes and initial level - kqueue */ /* Event filter notifies only changes and initial level - kqueue */
@ -159,21 +159,24 @@ typedef struct {
#define NGX_HAVE_KQUEUE_EVENT 8 #define NGX_HAVE_KQUEUE_EVENT 8
/* Event filter supports low water mark - kqueue's NOTE_LOWAT, /* Event filter supports low water mark - kqueue's NOTE_LOWAT,
early kqueue implementations have no NOTE_LOWAT so we need separate flag */ early kqueue implementations have no NOTE_LOWAT so we need a separate flag */
#define NGX_HAVE_LOWAT_EVENT 16 #define NGX_HAVE_LOWAT_EVENT 0x00000010
/* Event filter notifies only changes (edges) but not initial level - epoll */ /* Event filter notifies only changes (edges) but not initial level - epoll */
#define NGX_HAVE_EDGE_EVENT 32 #define NGX_HAVE_EDGE_EVENT 0x00000020
/* No need to add or delete event filters - rt signals */ /* No need to add or delete event filters - rt signals */
#define NGX_HAVE_SIGIO_EVENT 64 #define NGX_HAVE_SIGIO_EVENT 0x00000040
/* No need to add or delete event filters - overlapped, aio_read, aioread */ /* No need to add or delete event filters - overlapped, aio_read, aioread */
#define NGX_HAVE_AIO_EVENT 128 #define NGX_HAVE_AIO_EVENT 0x00000080
/* Need to add socket or halde only once - i/o completion port. /* Need to add socket or handle only once - i/o completion port.
It also requires to set HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT */ It also requires HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT to be set */
#define NGX_HAVE_IOCP_EVENT 256 #define NGX_HAVE_IOCP_EVENT 0x00000100
#define NGX_USE_LEVEL_EVENT 0x00010000
/* Event filter is deleted before closing file. Has no meaning /* Event filter is deleted before closing file. Has no meaning

View File

@ -13,15 +13,20 @@ int ngx_event_close_connection(ngx_event_t *ev)
int rc; int rc;
ngx_connection_t *c = (ngx_connection_t *) ev->data; ngx_connection_t *c = (ngx_connection_t *) ev->data;
ngx_log_debug(c->log, "CLOSE: %d" _ c->fd); ngx_log_debug(c->log, "close connection: %d" _ c->fd);
ngx_assert((c->fd != -1), return NGX_ERROR, c->log, ngx_assert((c->fd != -1), return NGX_ERROR, c->log,
"ngx_event_close: already closed"); "ngx_event_close: already closed");
ngx_destroy_pool(c->pool); if (c->read->timer_set) {
ngx_del_timer(c->read);
c->read->timer_set = 0;
}
ngx_del_timer(c->read); if (c->write->timer_set) {
ngx_del_timer(c->write); ngx_del_timer(c->write);
c->write->timer_set = 0;
}
ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
@ -32,5 +37,7 @@ int ngx_event_close_connection(ngx_event_t *ev)
c->fd = -1; c->fd = -1;
ngx_destroy_pool(c->pool);
return rc; return rc;
} }

View File

@ -10,23 +10,34 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size)
{ {
int n; int n;
ngx_err_t err; ngx_err_t err;
ngx_event_t *ev;
if (c->read->timedout) { ev = c->read;
if (ev->timedout) {
ngx_set_socket_errno(NGX_ETIMEDOUT); ngx_set_socket_errno(NGX_ETIMEDOUT);
ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "recv() failed"); ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "recv() failed");
return NGX_ERROR; return NGX_ERROR;
} }
#if (HAVE_KQUEUE) #if (HAVE_KQUEUE)
ngx_log_debug(c->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _ if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
c->read->eof _ c->read->available _ c->read->error); ngx_log_debug(c->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _
ev->eof _ ev->available _ ev->error);
}
#endif #endif
#if (USE_KQUEUE) #if (USE_KQUEUE)
if (c->read->eof && c->read->available == 0) { if (ev->eof && ev->available == 0) {
if (c->read->error) { if (ev->error) {
ngx_log_error(NGX_LOG_ERR, c->log, c->read->error, ngx_set_socket_errno(ev->error);
if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) {
return 0;
}
ngx_log_error(NGX_LOG_ERR, c->log, ev->error,
"recv() failed"); "recv() failed");
return NGX_ERROR; return NGX_ERROR;
} }
@ -36,10 +47,16 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size)
#elif (HAVE_KQUEUE) #elif (HAVE_KQUEUE)
if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) { if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
if (c->read->eof && c->read->available == 0) { if (ev->eof && ev->available == 0) {
if (c->read->error) { if (ev->error) {
ngx_log_error(NGX_LOG_ERR, c->log, c->read->error, ngx_set_socket_errno(ev->error);
if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) {
return 0;
}
ngx_log_error(NGX_LOG_ERR, c->log, ev->error,
"recv() failed"); "recv() failed");
return NGX_ERROR; return NGX_ERROR;
} }
@ -55,6 +72,10 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size)
if (n == -1) { if (n == -1) {
err = ngx_socket_errno; err = ngx_socket_errno;
if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) {
return 0;
}
if (err == NGX_EAGAIN) { if (err == NGX_EAGAIN) {
ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returns EAGAIN"); ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returns EAGAIN");
return NGX_AGAIN; return NGX_AGAIN;
@ -66,12 +87,12 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size)
#if (USE_KQUEUE) #if (USE_KQUEUE)
c->read->available -= n; ev->available -= n;
#elif (HAVE_KQUEUE) #elif (HAVE_KQUEUE)
if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) { if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
c->read->available -= n; ev->available -= n;
} }
#endif #endif

View File

@ -4,12 +4,53 @@
#include <ngx_string.h> #include <ngx_string.h>
#include <ngx_file.h> #include <ngx_file.h>
#include <ngx_hunk.h> #include <ngx_hunk.h>
#include <ngx_conf_file.h>
#include <ngx_event_write.h> #include <ngx_event_write.h>
#include <ngx_http.h> #include <ngx_http.h>
#include <ngx_http_config.h>
#include <ngx_http_core_module.h>
#include <ngx_http_output_filter.h> #include <ngx_http_output_filter.h>
#include <ngx_http_event_proxy_handler.h> #include <ngx_http_event_proxy_handler.h>
ngx_http_module_t ngx_http_proxy_module_ctx;
static ngx_command_t ngx_http_proxy_commands[] = {
{ngx_string("proxy_large_header"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_proxy_loc_conf_t, large_header)},
{ngx_null_string, 0, NULL, 0, 0}
};
static ngx_http_module_t ngx_http_proxy_module_ctx = {
NGX_HTTP_MODULE,
NULL, /* create server config */
NULL, /* init server config */
NULL, /* create location config */
NULL, /* merge location config */
NULL, /* translate handler */
NULL, /* output header filter */
NULL, /* next output header filter */
NULL, /* output body filter */
NULL /* next output body filter */
};
ngx_module_t ngx_http_proxy_module = {
0, /* module index */
&ngx_http_proxy_module_ctx, /* module context */
ngx_http_proxy_commands, /* module directives */
NGX_HTTP_MODULE_TYPE, /* module type */
NULL /* init module */
};
static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r); static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r);
@ -18,6 +59,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
char *addr_text); char *addr_text);
static int ngx_http_proxy_send_request(ngx_event_t *ev); static int ngx_http_proxy_send_request(ngx_event_t *ev);
static int ngx_http_proxy_init_response(ngx_event_t *ev);
static int ngx_http_proxy_read_response_header(ngx_event_t *ev); static int ngx_http_proxy_read_response_header(ngx_event_t *ev);
static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, static int ngx_http_proxy_process_status_line(ngx_http_request_t *r,
ngx_http_proxy_ctx_t *p); ngx_http_proxy_ctx_t *p);
@ -45,12 +87,13 @@ int ngx_http_proxy_handler(ngx_http_request_t *r)
if (p == NULL) { if (p == NULL) {
ngx_http_create_ctx(r, p, ngx_http_proxy_module_ctx, ngx_http_create_ctx(r, p, ngx_http_proxy_module_ctx,
sizeof(ngx_http_proxy_ctx_t)); sizeof(ngx_http_proxy_ctx_t),
NGX_HTTP_INTERNAL_SERVER_ERROR);
} }
chain = ngx_http_proxy_create_request(r); chain = ngx_http_proxy_create_request(r);
if (chain == NULL) { if (chain == NULL) {
return NGX_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
p->out = chain; p->out = chain;
@ -74,8 +117,13 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r)
/* 2 is for "\r\n" after request line /* 2 is for "\r\n" after request line
and 2 is for "\r\n" at the header end */ and 2 is for "\r\n" at the header end */
/* STUB: "method p->url HTTP/1.0" length */
len = r->request_line.len + 2 + 2; len = r->request_line.len + 2 + 2;
/* TODO: Host length */
/* "Connection: close\r\n" */ /* "Connection: close\r\n" */
len += sizeof(conn_close) - 1; len += sizeof(conn_close) - 1;
@ -98,12 +146,16 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r)
ngx_test_null(hunk, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL); ngx_test_null(hunk, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL);
ngx_add_hunk_to_chain(chain, hunk, r->pool, NULL); ngx_add_hunk_to_chain(chain, hunk, r->pool, NULL);
ngx_memcpy(hunk->last.mem, r->request_line.data, r->request_line.len); /* STUB: "method p->url HTTP/1.0" */
hunk->last.mem += r->request_line.len;
*(hunk->last.mem++) = CR; *(hunk->last.mem++) = LF;
ngx_memcpy(hunk->last.mem, conn_close, sizeof(conn_close) - 1); ngx_memcpy(hunk->last, r->request_line.data, r->request_line.len);
hunk->last.mem += sizeof(conn_close) - 1; hunk->last += r->request_line.len;
*(hunk->last++) = CR; *(hunk->last++) = LF;
/* TODO: Host header */
ngx_memcpy(hunk->last, conn_close, sizeof(conn_close) - 1);
hunk->last += sizeof(conn_close) - 1;
for (i = 0; i < r->headers_in.headers->nelts; i++) { for (i = 0; i < r->headers_in.headers->nelts; i++) {
if (&header[i] == r->headers_in.host) { if (&header[i] == r->headers_in.host) {
@ -114,25 +166,25 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r)
continue; continue;
} }
ngx_memcpy(hunk->last.mem, header[i].key.data, header[i].key.len); ngx_memcpy(hunk->last, header[i].key.data, header[i].key.len);
hunk->last.mem += header[i].key.len; hunk->last += header[i].key.len;
*(hunk->last.mem++) = ':'; *(hunk->last.mem++) = ' '; *(hunk->last++) = ':'; *(hunk->last++) = ' ';
ngx_memcpy(hunk->last.mem, header[i].value.data, header[i].value.len); ngx_memcpy(hunk->last, header[i].value.data, header[i].value.len);
hunk->last.mem += header[i].value.len; hunk->last += header[i].value.len;
*(hunk->last.mem++) = CR; *(hunk->last.mem++) = LF; *(hunk->last++) = CR; *(hunk->last++) = LF;
ngx_log_debug(r->connection->log, "proxy: '%s: %s'" _ ngx_log_debug(r->connection->log, "proxy: '%s: %s'" _
header[i].key.data _ header[i].value.data); header[i].key.data _ header[i].value.data);
} }
/* add "\r\n" at the header end */ /* add "\r\n" at the header end */
*(hunk->last.mem++) = CR; *(hunk->last.mem++) = LF; *(hunk->last++) = CR; *(hunk->last++) = LF;
/* STUB */ *(hunk->last.mem++) = '\0'; /* STUB */ *(hunk->last++) = '\0';
ngx_log_debug(r->connection->log, "PROXY:\n'%s'" _ hunk->pos.mem); ngx_log_debug(r->connection->log, "PROXY:\n'%s'" _ hunk->pos);
return chain; return chain;
} }
@ -142,7 +194,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
struct sockaddr_in *addr, struct sockaddr_in *addr,
char *addr_text) char *addr_text)
{ {
int rc; int rc, event;
ngx_err_t err; ngx_err_t err;
ngx_socket_t s; ngx_socket_t s;
ngx_event_t *rev, *wev; ngx_event_t *rev, *wev;
@ -157,7 +209,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
if (s == -1) { if (s == -1) {
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
ngx_socket_n " failed"); ngx_socket_n " failed");
return NGX_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
#if 0 #if 0
@ -172,7 +224,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
ngx_close_socket_n " failed"); ngx_close_socket_n " failed");
} }
return NGX_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
} }
#endif #endif
@ -186,7 +238,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
ngx_close_socket_n " failed"); ngx_close_socket_n " failed");
} }
return NGX_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
rc = connect(s, (struct sockaddr *) addr, sizeof(struct sockaddr_in)); rc = connect(s, (struct sockaddr *) addr, sizeof(struct sockaddr_in));
@ -201,7 +253,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
ngx_close_socket_n " failed"); ngx_close_socket_n " failed");
} }
return NGX_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
} }
@ -226,21 +278,48 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
ngx_test_null(pc->pool, ngx_test_null(pc->pool,
ngx_create_pool(/* STUB */ 1024 /**/, pc->log), ngx_create_pool(/* STUB */ 1024 /**/, pc->log),
NGX_ERROR); NGX_HTTP_INTERNAL_SERVER_ERROR);
wev->event_handler = ngx_http_proxy_send_request; wev->event_handler = ngx_http_proxy_send_request;
rev->event_handler = ngx_http_proxy_read_response_header; rev->event_handler = ngx_http_proxy_init_response;
#if (USE_KQUEUE)
#if (HAVE_CLEAR_EVENT)
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) {
#else return NGX_HTTP_INTERNAL_SERVER_ERROR;
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) != NGX_OK) {
#endif
return NGX_ERROR;
} }
#else
#if (HAVE_CLEAR_EVENT) /* kqueue */
if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
event = NGX_CLEAR_EVENT;
} else {
event = NGX_LEVEL_EVENT;
}
#else /* select, poll, /dev/poll */
event = NGX_LEVEL_EVENT;
#endif
if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
#endif /* USE_KQUEUE */
/* TODO: aio, iocp */
/* The connection is in a progress */
if (rc == -1) { if (rc == -1) {
return ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT); /* TODO: oneshot */
if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
} }
wev->write = 1; wev->write = 1;
@ -262,7 +341,7 @@ static int ngx_http_proxy_send_request(ngx_event_t *ev)
p = (ngx_http_proxy_ctx_t *) p = (ngx_http_proxy_ctx_t *)
ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx);
chain = ngx_event_write(c, p->out, 0); chain = ngx_write_chain(c, p->out, 0);
if (chain == (ngx_chain_t *) -1) { if (chain == (ngx_chain_t *) -1) {
return NGX_ERROR; return NGX_ERROR;
} }
@ -273,7 +352,7 @@ static int ngx_http_proxy_send_request(ngx_event_t *ev)
} }
static int ngx_http_proxy_read_response_header(ngx_event_t *ev) static int ngx_http_proxy_init_response(ngx_event_t *ev)
{ {
int n; int n;
ngx_hunk_t **ph; ngx_hunk_t **ph;
@ -281,48 +360,126 @@ static int ngx_http_proxy_read_response_header(ngx_event_t *ev)
ngx_http_request_t *r; ngx_http_request_t *r;
ngx_http_proxy_ctx_t *p; ngx_http_proxy_ctx_t *p;
c = (ngx_connection_t *) ev->data;
r = (ngx_http_request_t *) c->data;
if (ev->timedout) { if (ev->timedout) {
return NGX_ERROR; return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT);
} }
p = (ngx_http_proxy_ctx_t *)
ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx);
ngx_test_null(p->header_in,
ngx_create_temp_hunk(r->pool,
/* STUB */ 1024 /**/, 0, 0),
ngx_http_proxy_error(r, p, NGX_HTTP_INTERNAL_SERVER_ERROR));
p->header_in->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY;
ngx_test_null(p->headers_in,
ngx_palloc(r->pool, sizeof(ngx_http_proxy_headers_in_t)),
ngx_http_proxy_error(r, p, NGX_HTTP_INTERNAL_SERVER_ERROR));
ngx_init_array(p->hunks, r->pool,
/* STUB */ 10 /**/,
sizeof(ngx_hunk_t *),
ngx_http_proxy_error(r, p, NGX_HTTP_INTERNAL_SERVER_ERROR));
ngx_test_null(ph, ngx_push_array(&p->hunks), NGX_ERROR);
*ph = p->header_in;
p->state_handler = ngx_http_proxy_process_status_line;
return ngx_http_proxy_read_response_header(ev);
}
static int ngx_http_proxy_read_response_header(ngx_event_t *ev)
{
int n;
ngx_hunk_t **ph;
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_proxy_ctx_t *p;
ngx_http_proxy_loc_conf_t *lcf;
c = (ngx_connection_t *) ev->data; c = (ngx_connection_t *) ev->data;
r = (ngx_http_request_t *) c->data; r = (ngx_http_request_t *) c->data;
p = (ngx_http_proxy_ctx_t *) p = (ngx_http_proxy_ctx_t *)
ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); ngx_http_get_module_ctx(r, ngx_http_proxy_module);
if (p->header_in == NULL) { if (ev->timedout) {
ngx_test_null(p->header_in, return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT);
ngx_create_temp_hunk(r->pool,
/* STUB */ 1024 /**/, 0, 0),
NGX_ERROR);
p->header_in->type = NGX_HUNK_MEMORY;
ngx_test_null(p->headers_in,
ngx_palloc(r->pool, sizeof(ngx_http_proxy_headers_in_t)),
NGX_ERROR);
ngx_init_array(p->hunks, r->pool,
/* STUB */ 10 /**/,
sizeof(ngx_hunk_t *),
NGX_ERROR);
ngx_test_null(ph, ngx_push_array(&p->hunks), NGX_ERROR);
*ph = p->header_in;
p->state_handler = ngx_http_proxy_process_status_line;
} }
n = ngx_event_recv(c, p->header_in->last.mem, lcf = (ngx_http_proxy_loc_conf_t *)
p->header_in->end - p->header_in->last.mem); ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
#if 0
do {
n = ngx_event_recv(c, p->header_in->last,
p->header_in->end - p->header_in->last;
if (n == NGX_AGAIN) {
if (ev->timer_set) {
ngx_del_timer(ev);
} else {
ev->timer_set = 1;
}
ngx_add_timer(ev, lcf->timeout);
return NGX_AGAIN;
}
if (n == NGX_ERROR) {
ngx_http_proxy_close_request(r, p);
return ngx_http_error(r, NGX_HTTP_BAD_GATEWAY);
}
ngx_log_debug(c->log, "http proxy read %d" _ n);
if (n == 0) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client has prematurely closed connection");
ngx_http_proxy_close_request(r, p);
}
p->header_in->last += n;
if (lcf->large_header && p->header_in->end == p->header_in->last) {
again = 1;
} else {
again = 0;
}
#if (HAVE_AIO_EVENT) /* aio, iocp */
if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
again = 1;
}
#endif
} while (rc == NGX_AGAIN && again);
#endif
n = ngx_event_recv(c, p->header_in->last,
p->header_in->end - p->header_in->last);
ngx_log_debug(c->log, "READ:%d" _ n); ngx_log_debug(c->log, "READ:%d" _ n);
p->header_in->last.mem += n; p->header_in->last += n;
/* STUB */ /* STUB */
*p->header_in->last.mem = '\0'; *p->header_in->last = '\0';
ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->header_in->pos.mem); ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->header_in->pos);
/**/ /**/
if (n == 0) { if (n == 0) {
@ -355,13 +512,14 @@ static int ngx_http_proxy_read_response_header(ngx_event_t *ev)
#endif #endif
ev->event_handler = ngx_http_proxy_read_response_body; ev->event_handler = ngx_http_proxy_read_response_body;
if (p->header_in->end - p->header_in->last.mem == 0) { if (p->header_in->end - p->header_in->last == 0) {
return ngx_http_proxy_read_response_body(ev); return ngx_http_proxy_read_response_body(ev);
} }
return NGX_WAITING; return NGX_WAITING;
} }
static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, static int ngx_http_proxy_process_status_line(ngx_http_request_t *r,
ngx_http_proxy_ctx_t *p) ngx_http_proxy_ctx_t *p)
{ {
@ -380,7 +538,7 @@ static int ngx_http_proxy_process_status_line(ngx_http_request_t *r,
p->state_handler = NULL; p->state_handler = NULL;
} }
if (p->header_in->last.mem >= p->header_in->end) { if (p->header_in->last >= p->header_in->end) {
rc = NGX_HTTP_PARSE_TOO_LONG_STATUS_LINE; rc = NGX_HTTP_PARSE_TOO_LONG_STATUS_LINE;
} else if (rc == NGX_AGAIN) { } else if (rc == NGX_AGAIN) {
@ -390,6 +548,7 @@ static int ngx_http_proxy_process_status_line(ngx_http_request_t *r,
/* STUB */ return NGX_ERROR; /* STUB */ return NGX_ERROR;
} }
#if 0 #if 0
static int ngx_http_proxy_process_response_header(ngx_http_request_t *r, static int ngx_http_proxy_process_response_header(ngx_http_request_t *r,
ngx_http_proxy_ctx_t *p) ngx_http_proxy_ctx_t *p)
@ -398,6 +557,7 @@ static int ngx_http_proxy_process_response_header(ngx_http_request_t *r,
} }
#endif #endif
static int ngx_http_proxy_read_response_body(ngx_event_t *ev) static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
{ {
int n; int n;
@ -419,7 +579,7 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
if (p->hunks.nelts > 0) { if (p->hunks.nelts > 0) {
h = ((ngx_hunk_t **) p->hunks.elts)[p->hunks.nelts - 1]; h = ((ngx_hunk_t **) p->hunks.elts)[p->hunks.nelts - 1];
left = h->end - h->last.mem; left = h->end - h->last;
} else { } else {
h = NULL; h = NULL;
@ -453,13 +613,13 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
/* STUB */ 4096 /**/, 0, 0), /* STUB */ 4096 /**/, 0, 0),
NGX_ERROR); NGX_ERROR);
h->type = NGX_HUNK_MEMORY; h->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY;
*ph = h; *ph = h;
} }
if (h != NULL) { if (h != NULL) {
buf = h->last.mem; buf = h->last;
size = h->end - h->last.mem; size = h->end - h->last;
} else { } else {
buf = (char *) &buf; buf = (char *) &buf;
@ -478,12 +638,12 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
return NGX_ERROR; return NGX_ERROR;
} }
h->last.mem += n; h->last += n;
left = h->end - h->last.mem; left = h->end - h->last;
/* STUB */ /* STUB */
*h->last.mem = '\0'; *h->last = '\0';
ngx_log_debug(c->log, "PROXY:\n'%s'" _ h->pos.mem); ngx_log_debug(c->log, "PROXY:\n'%s'" _ h->pos);
/**/ /**/
} while (n > 0 && left == 0); } while (n > 0 && left == 0);
@ -503,6 +663,7 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
/* STUB */ return NGX_WAITING; /* STUB */ return NGX_WAITING;
} }
static int ngx_http_proxy_write_to_client(ngx_event_t *ev) static int ngx_http_proxy_write_to_client(ngx_event_t *ev)
{ {
int rc; int rc;
@ -536,6 +697,15 @@ static int ngx_http_proxy_write_to_client(ngx_event_t *ev)
} }
static int ngx_http_proxy_error(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p,
int error)
{
ngx_event_close_connection(p->connection->read);
return ngx_http_error(r, error);
}
static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx) static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx)
{ {
char ch; char ch;
@ -554,21 +724,16 @@ static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx)
} state; } state;
state = ctx->state; state = ctx->state;
p = ctx->header_in->pos.mem; p = ctx->header_in->pos;
while (p < ctx->header_in->last.mem && state < sw_done) { while (p < ctx->header_in->last && state < sw_done) {
ch = *p++; ch = *p++;
#if 0
fprintf(stderr, "state: %d, pos: %x, end: %x, char: '%c', status: %d\n",
state, p, ctx->header_in->last.mem, ch, ctx->status);
#endif
switch (state) { switch (state) {
/* "HTTP/" */ /* "HTTP/" */
case sw_start: case sw_start:
if (p + 3 >= ctx->header_in->last.mem) { if (p + 3 >= ctx->header_in->last) {
return NGX_AGAIN; return NGX_AGAIN;
} }
@ -684,7 +849,7 @@ fprintf(stderr, "state: %d, pos: %x, end: %x, char: '%c', status: %d\n",
} }
} }
ctx->header_in->pos.mem = p; ctx->header_in->pos = p;
if (state == sw_done) { if (state == sw_done) {
if (ctx->request_end == NULL) { if (ctx->request_end == NULL) {

View File

@ -14,6 +14,12 @@ typedef struct {
int dummy; int dummy;
} ngx_http_proxy_headers_in_t; } ngx_http_proxy_headers_in_t;
typedef struct {
int large_header;
} ngx_http_proxy_loc_conf_t;
typedef struct ngx_http_proxy_ctx_s ngx_http_proxy_ctx_t; typedef struct ngx_http_proxy_ctx_s ngx_http_proxy_ctx_t;
struct ngx_http_proxy_ctx_s { struct ngx_http_proxy_ctx_s {
@ -24,6 +30,7 @@ struct ngx_http_proxy_ctx_s {
int hunk_n; int hunk_n;
ngx_connection_t *connection;
ngx_http_proxy_headers_in_t *headers_in; ngx_http_proxy_headers_in_t *headers_in;
ngx_hunk_t *header_in; ngx_hunk_t *header_in;
@ -36,7 +43,11 @@ struct ngx_http_proxy_ctx_s {
}; };
extern ngx_http_module_t ngx_http_proxy_module; extern ngx_module_t ngx_http_proxy_module;
static int ngx_http_proxy_error(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p,
int error);
#endif /* _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_ */ #endif /* _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_ */

View File

@ -144,8 +144,8 @@ int ngx_http_static_handler(ngx_http_request_t *r)
#if 1 #if 1
h->type = NGX_HUNK_FILE|NGX_HUNK_LAST; h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
h->pos.file = 0; h->file_pos = 0;
h->last.file = ngx_file_size(r->file.info); h->file_last = ngx_file_size(r->file.info);
h->file->fd = r->file.fd; h->file->fd = r->file.fd;
h->file->log = r->connection->log; h->file->log = r->connection->log;

View File

@ -27,11 +27,6 @@ int ngx_http_large_client_header = 1;
int ngx_http_url_in_error_log = 1; int ngx_http_url_in_error_log = 1;
/* STUB: per location */
int ngx_http_lingering_timeout = 5000;
int ngx_http_lingering_time = 30;
/**/
ngx_array_t ngx_http_index_handlers; ngx_array_t ngx_http_index_handlers;

View File

@ -47,29 +47,17 @@
#define NGX_HTTP_NOT_FOUND 404 #define NGX_HTTP_NOT_FOUND 404
#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 #define NGX_HTTP_REQUEST_URI_TOO_LARGE 414
#define NGX_HTTP_INTERNAL_SERVER_ERROR 500 #define NGX_HTTP_INTERNAL_SERVER_ERROR 500
#define NGX_HTTP_NOT_IMPLEMENTED 501
#define NGX_HTTP_BAD_GATEWAY 502
#define NGX_HTTP_SERVICE_UNAVAILABLE 503
#define NGX_HTTP_GATEWAY_TIME_OUT 504
#define NGX_HTTP_STATIC_HANDLER 0 #define NGX_HTTP_STATIC_HANDLER 0
#define NGX_HTTP_DIRECTORY_HANDLER 1 #define NGX_HTTP_DIRECTORY_HANDLER 1
typedef struct {
char *doc_root;
size_t doc_root_len;
size_t connection_pool_size;
size_t request_pool_size;
size_t header_buffer_size;
size_t discarded_buffer_size;
ngx_msec_t header_timeout;
ngx_msec_t lingering_timeout;
time_t lingering_time;
} ngx_http_server_t;
typedef struct { typedef struct {
size_t len; size_t len;
char *data; char *data;
@ -232,9 +220,9 @@ typedef struct {
#define ngx_http_get_module_loc_conf(r, module) r->loc_conf[module.index] #define ngx_http_get_module_loc_conf(r, module) r->loc_conf[module.index]
#define ngx_http_get_module_ctx(r, module) r->ctx[module.index] #define ngx_http_get_module_ctx(r, module) r->ctx[module.index]
#define ngx_http_create_ctx(r, cx, module, size) \ #define ngx_http_create_ctx(r, cx, module, size, error) \
do { \ do { \
ngx_test_null(cx, ngx_pcalloc(r->pool, size), NGX_ERROR); \ ngx_test_null(cx, ngx_pcalloc(r->pool, size), error); \
r->ctx[module.index] = cx; \ r->ctx[module.index] = cx; \
} while (0) } while (0)
@ -279,9 +267,6 @@ extern int ngx_http_client_header_buffer_size;
extern int ngx_http_large_client_header; extern int ngx_http_large_client_header;
extern int ngx_http_discarded_buffer_size; extern int ngx_http_discarded_buffer_size;
extern int ngx_http_lingering_timeout;
extern int ngx_http_lingering_time;
extern int ngx_http_url_in_error_log; extern int ngx_http_url_in_error_log;
extern ngx_array_t ngx_http_index_handlers; extern ngx_array_t ngx_http_index_handlers;

View File

@ -96,6 +96,18 @@ static ngx_command_t ngx_http_core_commands[] = {
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, send_timeout)}, offsetof(ngx_http_core_loc_conf_t, send_timeout)},
{ngx_string("lingering_time"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_time_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, lingering_time)},
{ngx_string("lingering_timeout"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_time_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, lingering_timeout)},
{ngx_string(""), 0, NULL, 0, 0} {ngx_string(""), 0, NULL, 0, 0}
}; };
@ -138,7 +150,7 @@ int ngx_http_handler(ngx_http_request_t *r)
r->connection->unexpected_eof = 0; r->connection->unexpected_eof = 0;
r->lingering_close = 1; r->lingering_close = 1;
r->keepalive = 1; r->keepalive = 0;
#if 1 #if 1
r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY;
@ -264,6 +276,11 @@ ngx_log_debug(r->connection->log, "trans: %s" _ lcf[i]->name.data);
} }
} }
#if 0
/* STUB */ r->handler = ngx_http_proxy_handler;
return NGX_OK;
#endif
if (r->uri.data[r->uri.len - 1] == '/') { if (r->uri.data[r->uri.len - 1] == '/') {
r->handler = ngx_http_core_index_handler; r->handler = ngx_http_core_index_handler;
return NGX_OK; return NGX_OK;
@ -504,44 +521,38 @@ int ngx_http_error(ngx_http_request_t *r, int error)
int ngx_http_close_request(ngx_http_request_t *r) int ngx_http_close_request(ngx_http_request_t *r)
{ {
ngx_connection_t *c;
ngx_http_log_ctx_t *ctx; ngx_http_log_ctx_t *ctx;
ngx_log_debug(r->connection->log, "CLOSE#: %d" _ r->file.fd); c = r->connection;
ngx_http_log_handler(r); ngx_http_log_handler(r);
ngx_assert((r->file.fd != NGX_INVALID_FILE), /* void */ ; ,
r->connection->log, "file already closed");
if (r->file.fd != NGX_INVALID_FILE) { if (r->file.fd != NGX_INVALID_FILE) {
if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
ngx_close_file_n " failed"); ngx_close_file_n " failed");
} }
} }
/*
if (r->logging)
ngx_http_log_request(r);
*/
ctx = (ngx_http_log_ctx_t *) r->connection->log->data;
/* ctx->url was allocated from r->pool */ /* ctx->url was allocated from r->pool */
ctx = (ngx_http_log_ctx_t *) c->log->data;
ctx->url = NULL; ctx->url = NULL;
ngx_destroy_pool(r->pool); ngx_destroy_pool(r->pool);
ngx_log_debug(r->connection->log, "http closed"); if (c->read->timer_set) {
ngx_del_timer(c->read);
if (r->connection->read->timer_set) { c->read->timer_set = 0;
ngx_del_timer(r->connection->read);
} }
if (r->connection->write->timer_set) { if (c->write->timer_set) {
ngx_del_timer(r->connection->write); ngx_del_timer(c->write);
c->write->timer_set = 0;
} }
ngx_log_debug(c->log, "http closed");
return NGX_DONE; return NGX_DONE;
} }
@ -780,7 +791,7 @@ static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool)
lcf->send_timeout = 10; lcf->send_timeout = 10;
lcf->discarded_buffer_size = 1500; lcf->discarded_buffer_size = 1500;
lcf->lingering_time = 30; lcf->lingering_time = 30000;
lcf->lingering_timeout = 5000; lcf->lingering_timeout = 5000;
/* /*
@ -809,8 +820,8 @@ static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
args = (ngx_str_t *) cf->args->elts; args = (ngx_str_t *) cf->args->elts;
ls->port = atoi(args[1].data); ls->port = atoi(args[1].data);
if (ls->port < 0) { if (ls->port < 1 || ls->port > 65536) {
return "port must be greater or equal to zero"; return "port must be between 1 and 65535";
} }
return NGX_CONF_OK; return NGX_CONF_OK;

View File

@ -130,7 +130,6 @@ int ngx_http_init_connection(ngx_connection_t *c)
/* select, poll, /dev/poll */ /* select, poll, /dev/poll */
ev->level = 1;
return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT); return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
#endif /* USE_KQUEUE */ #endif /* USE_KQUEUE */
@ -190,7 +189,7 @@ static int ngx_http_init_request(ngx_event_t *ev)
static int ngx_http_process_request_header(ngx_event_t *ev) static int ngx_http_process_request_header(ngx_event_t *ev)
{ {
int n, rc; int n, rc, again;
ngx_connection_t *c; ngx_connection_t *c;
ngx_http_request_t *r; ngx_http_request_t *r;
ngx_http_log_ctx_t *ctx; ngx_http_log_ctx_t *ctx;
@ -200,18 +199,22 @@ static int ngx_http_process_request_header(ngx_event_t *ev)
ngx_log_debug(ev->log, "http process request"); ngx_log_debug(ev->log, "http process request");
#if (HAVE_AIO_EVENT)
do { do {
#endif
if (r->header_read) { if (r->header_read) {
if (r->header_in->end - r->header_in->last == 0) {
again = 1;
} else {
again = 0;
}
r->header_read = 0; r->header_read = 0;
ngx_log_debug(ev->log, "http preread %d" _ ngx_log_debug(ev->log, "http preread %d" _
r->header_in->last.mem - r->header_in->pos.mem); r->header_in->last - r->header_in->pos);
} else { } else {
n = ngx_event_recv(c, r->header_in->last.mem, n = ngx_event_recv(c, r->header_in->last,
r->header_in->end - r->header_in->last.mem); r->header_in->end - r->header_in->last);
if (n == NGX_AGAIN) { if (n == NGX_AGAIN) {
if (!r->header_timeout_set) { if (!r->header_timeout_set) {
@ -228,8 +231,9 @@ static int ngx_http_process_request_header(ngx_event_t *ev)
return NGX_AGAIN; return NGX_AGAIN;
} }
if (n == NGX_ERROR) if (n == NGX_ERROR) {
return ngx_http_close_request(r); return ngx_http_close_request(r);
}
ngx_log_debug(ev->log, "http read %d" _ n); ngx_log_debug(ev->log, "http read %d" _ n);
@ -239,7 +243,14 @@ static int ngx_http_process_request_header(ngx_event_t *ev)
return ngx_http_close_request(r); return ngx_http_close_request(r);
} }
r->header_in->last.mem += n; r->header_in->last += n;
if (ngx_http_large_client_header
&& r->header_in->end == r->header_in->last) {
again = 1;
} else {
again = 0;
}
} }
/* the state_handlers are called in the following order: /* the state_handlers are called in the following order:
@ -250,16 +261,22 @@ static int ngx_http_process_request_header(ngx_event_t *ev)
/* state_handlers return NGX_OK when the whole header done */ /* state_handlers return NGX_OK when the whole header done */
rc = (r->state_handler)(r); rc = (r->state_handler)(r);
if (rc == NGX_ERROR) if (rc == NGX_ERROR) {
return rc; return rc;
}
} while (rc == NGX_AGAIN } while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last);
&& r->header_in->pos.mem < r->header_in->last.mem);
#if (HAVE_AIO_EVENT) /* aio, iocp */ #if (HAVE_AIO_EVENT) /* aio, iocp */
} while (rc == NGX_AGAIN && ngx_event_flags & NGX_HAVE_AIO_EVENT);
if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
again = 1;
}
#endif #endif
} while (rc == NGX_AGAIN && again);
if (rc == NGX_OK) { if (rc == NGX_OK) {
/* HTTP header done */ /* HTTP header done */
@ -308,7 +325,7 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
ngx_http_close_request(r)); ngx_http_close_request(r));
ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
/* if the large client headers is enabled then /* if the large client headers are enabled then
we need to copy a request line */ we need to copy a request line */
r->request_line.len = r->request_end - r->request_start; r->request_line.len = r->request_end - r->request_start;
@ -376,12 +393,12 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
/* NGX_AGAIN: a request line parsing is still not complete */ /* NGX_AGAIN: a request line parsing is still not complete */
if (r->header_in->last.mem == r->header_in->end) { if (r->header_in->last == r->header_in->end) {
/* If it's a pipelined request and a request line is not complete /* If it's a pipelined request and a request line is not complete
then we need to copy it to the start of r->header_in hunk. then we need to copy it to the start of r->header_in hunk.
We need to copy it here only if the large client header We need to copy it here only if the large client headers
is enabled otherwise a request line had been already copied are enabled otherwise a request line had been already copied
to the start of r->header_in hunk in ngx_http_set_keepalive() */ to the start of r->header_in hunk in ngx_http_set_keepalive() */
if (ngx_http_large_client_header) { if (ngx_http_large_client_header) {
@ -394,10 +411,10 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
} }
ngx_memcpy(r->header_in->start, r->request_start, ngx_memcpy(r->header_in->start, r->request_start,
r->header_in->last.mem - r->request_start); r->header_in->last - r->request_start);
r->header_in->pos.mem -= offset; r->header_in->pos -= offset;
r->header_in->last.mem -= offset; r->header_in->last -= offset;
r->request_start = r->header_in->start; r->request_start = r->header_in->start;
r->request_end -= offset; r->request_end -= offset;
r->uri_start -= offset; r->uri_start -= offset;
@ -437,7 +454,7 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
return NGX_AGAIN; return NGX_AGAIN;
/* the whole header has been parsed successfully */ /* a whole header has been parsed successfully */
} else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
ngx_log_debug(r->connection->log, "HTTP header done"); ngx_log_debug(r->connection->log, "HTTP header done");
@ -468,9 +485,9 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
/* NGX_AGAIN: a header line parsing is still not complete */ /* NGX_AGAIN: a header line parsing is still not complete */
if (r->header_in->last.mem == r->header_in->end) { if (r->header_in->last == r->header_in->end) {
/* if the large client header is enabled then /* if the large client headers are enabled then
we need to compact r->header_in hunk */ we need to compact r->header_in hunk */
if (ngx_http_large_client_header) { if (ngx_http_large_client_header) {
@ -483,10 +500,10 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
} }
ngx_memcpy(r->header_in->start, r->header_name_start, ngx_memcpy(r->header_in->start, r->header_name_start,
r->header_in->last.mem - r->header_name_start); r->header_in->last - r->header_name_start);
r->header_in->last.mem -= offset; r->header_in->last -= offset;
r->header_in->pos.mem -= offset; r->header_in->pos -= offset;
r->header_name_start = r->header_in->start; r->header_name_start = r->header_in->start;
r->header_name_end -= offset; r->header_name_end -= offset;
r->header_start -= offset; r->header_start -= offset;
@ -512,7 +529,7 @@ static int ngx_http_process_request_header_line(ngx_http_request_t *r)
ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR); ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR);
/* if large client header is enabled then /* if large client headers are enabled then
we need to copy header name and value */ we need to copy header name and value */
h->key.len = r->header_name_end - r->header_name_start; h->key.len = r->header_name_end - r->header_name_start;
@ -631,13 +648,11 @@ static int ngx_http_event_request_handler(ngx_http_request_t *r)
} else { } else {
event = NGX_LEVEL_EVENT; event = NGX_LEVEL_EVENT;
wev->level = 1;
} }
#else /* select, poll, /dev/poll */ #else /* select, poll, /dev/poll */
event = NGX_LEVEL_EVENT; event = NGX_LEVEL_EVENT;
wev->level = 1;
#endif #endif
@ -751,11 +766,11 @@ static int ngx_http_block_read(ngx_event_t *ev)
#else #else
if (ev->level) { /* select, poll, /dev/poll */ if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */
ev->blocked = 1; ev->blocked = 1;
return ngx_del_event(ev, NGX_READ_EVENT, 0); return ngx_del_event(ev, NGX_READ_EVENT, 0);
} else { /* kqueue, epoll */ } else { /* kqueue, epoll */
return NGX_OK; return NGX_OK;
} }
@ -831,7 +846,7 @@ static int ngx_http_read_discarded_body(ngx_event_t *ev)
static int ngx_http_set_keepalive(ngx_http_request_t *r) static int ngx_http_set_keepalive(ngx_http_request_t *r)
{ {
int len; int len, blocked;
ngx_hunk_t *h; ngx_hunk_t *h;
ngx_event_t *rev, *wev; ngx_event_t *rev, *wev;
ngx_connection_t *c; ngx_connection_t *c;
@ -841,33 +856,37 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
rev = c->read; rev = c->read;
wev = c->write; wev = c->write;
if (rev->blocked && rev->level) {
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
return NGX_ERROR;
}
rev->blocked = 0;
}
ctx = (ngx_http_log_ctx_t *) c->log->data; ctx = (ngx_http_log_ctx_t *) c->log->data;
ctx->action = "closing request"; ctx->action = "closing request";
ngx_http_close_request(r); ngx_http_close_request(r);
if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
return NGX_ERROR;
}
blocked = 1;
rev->blocked = 0;
} else {
blocked = 0;
}
h = c->buffer; h = c->buffer;
/* pipelined request */ /* pipelined request */
if (h->pos.mem < h->last.mem) { if (h->pos < h->last) {
/* We do not know here whether pipelined request is complete /* We do not know here whether pipelined request is complete
so we need to copy it to the start of c->buffer if the large so if large client headers are not enabled
client header is not enabled. This copy should be rare we need to copy the data to the start of c->buffer.
because clients that support pipelined requests (Mozilla 1.x, This copy should be rare because clients that support
Opera 6.x) are still rare */ pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */
if (!ngx_http_large_client_header) { if (!ngx_http_large_client_header) {
len = h->last.mem - h->pos.mem; len = h->last - h->pos;
ngx_memcpy(h->start, h->pos.mem, len); ngx_memcpy(h->start, h->pos, len);
h->pos.mem = h->start; h->pos = h->start;
h->last.mem = h->start + len; h->last = h->start + len;
} }
c->pipeline = 1; c->pipeline = 1;
@ -877,10 +896,10 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
c->pipeline = 0; c->pipeline = 0;
h->pos.mem = h->last.mem = h->start; h->pos = h->last = h->start;
rev->event_handler = ngx_http_keepalive_handler; rev->event_handler = ngx_http_keepalive_handler;
if (wev->active && wev->level) { if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
return NGX_ERROR; return NGX_ERROR;
} }
@ -890,7 +909,13 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
#if (HAVE_AIO_EVENT) /* aio, iocp */ #if (HAVE_AIO_EVENT) /* aio, iocp */
if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) {
return ngx_http_keepalive_handler(rev);
}
#else
if (blocked) {
return ngx_http_keepalive_handler(rev); return ngx_http_keepalive_handler(rev);
} }
@ -913,11 +938,13 @@ static int ngx_http_keepalive_handler(ngx_event_t *ev)
if (ev->timedout) if (ev->timedout)
return NGX_DONE; return NGX_DONE;
/* TODO: MSIE closes keepalive connection with ECONNRESET /* MSIE closes keepalive connection with RST flag
so we need to handle here this error so we ignore ECONNRESET here */
1) in INFO (not ERR) level, 2) with time elapsed */
n = ngx_event_recv(c, c->buffer->last.mem, ev->ignore_econnreset = 1;
c->buffer->end - c->buffer->last.mem); ngx_set_socket_errno(0);
n = ngx_event_recv(c, c->buffer->last, c->buffer->end - c->buffer->last);
ev->ignore_econnreset = 0;
if (n == NGX_AGAIN || n == NGX_ERROR) if (n == NGX_AGAIN || n == NGX_ERROR)
return n; return n;
@ -926,12 +953,12 @@ static int ngx_http_keepalive_handler(ngx_event_t *ev)
ev->log->handler = NULL; ev->log->handler = NULL;
if (n == 0) { if (n == 0) {
ngx_log_error(NGX_LOG_INFO, ev->log, 0, ngx_log_error(NGX_LOG_INFO, ev->log, ngx_socket_errno,
"client %s closed keepalive connection", ctx->client); "client %s closed keepalive connection", ctx->client);
return NGX_DONE; return NGX_DONE;
} }
c->buffer->last.mem += n; c->buffer->last += n;
ev->log->handler = ngx_http_log_error; ev->log->handler = ngx_http_log_error;
ctx->action = "reading client request line"; ctx->action = "reading client request line";
@ -941,57 +968,67 @@ static int ngx_http_keepalive_handler(ngx_event_t *ev)
static int ngx_http_set_lingering_close(ngx_http_request_t *r) static int ngx_http_set_lingering_close(ngx_http_request_t *r)
{ {
ngx_event_t *ev; int blocked;
ngx_connection_t *c; ngx_event_t *rev, *wev;
ngx_connection_t *c;
ngx_http_core_loc_conf_t *lcf; ngx_http_core_loc_conf_t *lcf;
c = r->connection; c = r->connection;
ev = r->connection->read; rev = c->read;
wev = c->write;
lcf = (ngx_http_core_loc_conf_t *) lcf = (ngx_http_core_loc_conf_t *)
ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
r->lingering_time = ngx_time() + lcf->lingering_time; r->lingering_time = ngx_time() + lcf->lingering_time / 1000;
r->connection->read->event_handler = ngx_http_lingering_close_handler; r->connection->read->event_handler = ngx_http_lingering_close_handler;
if (ev->timer_set) { if (rev->timer_set) {
ngx_del_timer(ev); ngx_del_timer(rev);
} else { } else {
ev->timer_set = 1; rev->timer_set = 1;
} }
ngx_add_timer(ev, lcf->lingering_timeout); ngx_add_timer(rev, lcf->lingering_timeout);
if (ev->blocked) { if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_event_flags & NGX_HAVE_LEVEL_EVENT) { if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
if (ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT) return ngx_http_close_request(r);
== NGX_ERROR) { }
return ngx_http_close_request(r); blocked = 1;
} rev->blocked = 0;
} else {
blocked = 0;
}
if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
return ngx_http_close_request(r);
} }
} }
if (ngx_shutdown_socket(r->connection->fd, NGX_WRITE_SHUTDOWN) == -1) { if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_socket_errno, ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
ngx_shutdown_socket_n " failed"); ngx_shutdown_socket_n " failed");
return ngx_http_close_request(r); return ngx_http_close_request(r);
} }
#if (HAVE_AIO_EVENT) /* aio, iocp */ #if (HAVE_AIO_EVENT) /* aio, iocp */
if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
return ngx_http_lingering_close_handler(ev); if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) {
return ngx_http_lingering_close_handler(rev);
} }
#else
if (blocked) {
return ngx_http_lingering_close_handler(rev);
}
#endif #endif
#if (HAVE_CLEAR_EVENT) /* kqueue */ || (HAVE_EDGE_EVENT) /* epoll */ return NGX_OK;
if (ngx_event_flags & (NGX_HAVE_CLEAR_EVENT|NGX_HAVE_EDGE_EVENT)) {
return NGX_OK;
}
#endif
/* select, poll, /dev/poll */
return ngx_del_event(c->write, NGX_WRITE_EVENT, 0);
} }
@ -1021,9 +1058,14 @@ static int ngx_http_lingering_close_handler(ngx_event_t *ev)
ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
if (r->discarded_buffer == NULL) { if (r->discarded_buffer == NULL) {
if ((size_t)(r->header_in->end - r->header_in->last.mem)
/* TODO: r->header_in->start (if large headers are enabled)
or the end of parsed header (otherwise)
instead of r->header_in->last */
if ((size_t)(r->header_in->end - r->header_in->last)
>= lcf->discarded_buffer_size) { >= lcf->discarded_buffer_size) {
r->discarded_buffer = r->header_in->last.mem; r->discarded_buffer = r->header_in->last;
} else { } else {
ngx_test_null(r->discarded_buffer, ngx_test_null(r->discarded_buffer,

View File

@ -48,22 +48,37 @@ static char server_string[] = "Server: " NGINX_VER CRLF;
static ngx_str_t http_codes[] = { static ngx_str_t http_codes[] = {
ngx_string("200 OK"), ngx_string("200 OK"),
#if 0
{ 6, "200 OK" },
#endif
{ 21, "301 Moved Permanently" }, ngx_string("301 Moved Permanently"),
{ 21, "302 Moved Temporarily" }, ngx_string("302 Moved Temporarily"),
{ 0, NULL }, ngx_null_string, /* 303 */
{ 16, "304 Not Modified" }, ngx_string("304 Not Modified"),
{ 15, "400 Bad Request" }, ngx_string("400 Bad Request"),
{ 0, NULL }, ngx_null_string, /* 401 */
{ 0, NULL }, ngx_null_string, /* 402 */
{ 13, "403 Forbidden" }, ngx_string("403 Forbidden"),
{ 13, "404 Not Found" }, ngx_string("404 Not Found"),
ngx_null_string, /* 405 */
ngx_null_string, /* 406 */
ngx_null_string, /* 407 */
ngx_string("408 Request Time-out"),
ngx_null_string, /* 409 */
ngx_null_string, /* 410 */
ngx_string("411 Length Required"),
ngx_null_string, /* 412 */
ngx_string("413 Request Entity Too Large"),
ngx_null_string, /* "414 Request-URI Too Large" but we never send it
because we treat such requests as HTTP/0.9 requests
and send only the body without the header */
ngx_null_string, /* 415 */
ngx_string("416 Requested Range Not Satisfiable"),
{ 25, "500 Internal Server Error" } ngx_string("500 Internal Server Error"),
ngx_string("501 Method Not Implemented"),
ngx_string("502 Bad Gateway"),
ngx_string("503 Service Temporarily Unavailable"),
ngx_string("504 Gateway Time-out")
}; };
@ -124,7 +139,7 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
} else { } else {
status = r->headers_out.status status = r->headers_out.status
- NGX_HTTP_INTERNAL_SERVER_ERROR + 1 + 4 + 5; - NGX_HTTP_INTERNAL_SERVER_ERROR + 1 + 4 + 17;
} }
len += http_codes[status].len; len += http_codes[status].len;
@ -181,49 +196,49 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 64), NGX_ERROR); ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 64), NGX_ERROR);
/* "HTTP/1.x " */ /* "HTTP/1.x " */
ngx_memcpy(h->last.mem, "HTTP/1.1 ", 9); ngx_memcpy(h->last, "HTTP/1.1 ", 9);
h->last.mem += 9; h->last += 9;
/* status line */ /* status line */
if (r->headers_out.status_line.len) { if (r->headers_out.status_line.len) {
ngx_memcpy(h->last.mem, r->headers_out.status_line.data, ngx_memcpy(h->last, r->headers_out.status_line.data,
r->headers_out.status_line.len); r->headers_out.status_line.len);
h->last.mem += r->headers_out.status_line.len; h->last += r->headers_out.status_line.len;
} else { } else {
ngx_memcpy(h->last.mem, http_codes[status].data, ngx_memcpy(h->last, http_codes[status].data,
http_codes[status].len); http_codes[status].len);
h->last.mem += http_codes[status].len; h->last += http_codes[status].len;
} }
*(h->last.mem++) = CR; *(h->last.mem++) = LF; *(h->last++) = CR; *(h->last++) = LF;
if (!(r->headers_out.server && r->headers_out.server->key.len)) { if (!(r->headers_out.server && r->headers_out.server->key.len)) {
ngx_memcpy(h->last.mem, server_string, sizeof(server_string) - 1); ngx_memcpy(h->last, server_string, sizeof(server_string) - 1);
h->last.mem += sizeof(server_string) - 1; h->last += sizeof(server_string) - 1;
} }
if (!(r->headers_out.date && r->headers_out.date->key.len)) { if (!(r->headers_out.date && r->headers_out.date->key.len)) {
ngx_memcpy(h->last.mem, "Date: ", 6); ngx_memcpy(h->last, "Date: ", 6);
h->last.mem += 6; h->last += 6;
h->last.mem += ngx_http_get_time(h->last.mem, time(NULL)); h->last += ngx_http_get_time(h->last, time(NULL));
*(h->last.mem++) = CR; *(h->last.mem++) = LF; *(h->last++) = CR; *(h->last++) = LF;
} }
/* 2^64 is 20 characters */ /* 2^64 is 20 characters */
if (r->headers_out.content_length >= 0) { if (r->headers_out.content_length >= 0) {
h->last.mem += ngx_snprintf(h->last.mem, 49, h->last += ngx_snprintf(h->last, 49,
"Content-Length: " OFF_FMT CRLF, "Content-Length: " OFF_FMT CRLF,
r->headers_out.content_length); r->headers_out.content_length);
} }
#if 0 #if 0
if (r->headers_out.content_type.len) { if (r->headers_out.content_type.len) {
ngx_memcpy(h->last.mem, "Content-Type: ", 14); ngx_memcpy(h->last, "Content-Type: ", 14);
h->last.mem += 14; h->last += 14;
ngx_memcpy(h->last.mem, r->headers_out.content_type.data, ngx_memcpy(h->last, r->headers_out.content_type.data,
r->headers_out.content_type.len); r->headers_out.content_type.len);
h->last.mem += r->headers_out.content_type.len; h->last += r->headers_out.content_type.len;
*(h->last.mem++) = CR; *(h->last.mem++) = LF; *(h->last++) = CR; *(h->last++) = LF;
} }
#endif #endif
@ -231,20 +246,20 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
&& r->headers_out.last_modified->key.len) && r->headers_out.last_modified->key.len)
&& r->headers_out.last_modified_time != -1) && r->headers_out.last_modified_time != -1)
{ {
ngx_memcpy(h->last.mem, "Last-Modified: ", 15); ngx_memcpy(h->last, "Last-Modified: ", 15);
h->last.mem += 15; h->last += 15;
h->last.mem += ngx_http_get_time(h->last.mem, h->last += ngx_http_get_time(h->last,
r->headers_out.last_modified_time); r->headers_out.last_modified_time);
*(h->last.mem++) = CR; *(h->last.mem++) = LF; *(h->last++) = CR; *(h->last++) = LF;
} }
if (r->keepalive == 0) { if (r->keepalive == 0) {
ngx_memcpy(h->last.mem, "Connection: close" CRLF, 19); ngx_memcpy(h->last, "Connection: close" CRLF, 19);
h->last.mem += 19; h->last += 19;
} else { } else {
ngx_memcpy(h->last.mem, "Connection: keep-alive" CRLF, 24); ngx_memcpy(h->last, "Connection: keep-alive" CRLF, 24);
h->last.mem += 24; h->last += 24;
} }
for (i = 0; i < r->headers_out.headers->nelts; i++) { for (i = 0; i < r->headers_out.headers->nelts; i++) {
@ -252,22 +267,22 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
continue; continue;
} }
ngx_memcpy(h->last.mem, header[i].key.data, header[i].key.len); ngx_memcpy(h->last, header[i].key.data, header[i].key.len);
h->last.mem += header[i].key.len; h->last += header[i].key.len;
*(h->last.mem++) = ':' ; *(h->last.mem++) = ' ' ; *(h->last++) = ':' ; *(h->last++) = ' ' ;
ngx_memcpy(h->last.mem, header[i].value.data, header[i].value.len); ngx_memcpy(h->last, header[i].value.data, header[i].value.len);
h->last.mem += header[i].value.len; h->last += header[i].value.len;
*(h->last.mem++) = CR; *(h->last.mem++) = LF; *(h->last++) = CR; *(h->last++) = LF;
} }
/* STUB */ /* STUB */
*(h->last.mem) = '\0'; *(h->last) = '\0';
ngx_log_debug(r->connection->log, "%s\n" _ h->pos.mem); ngx_log_debug(r->connection->log, "%s\n" _ h->pos);
/**/ /**/
/* end of HTTP header */ /* end of HTTP header */
*(h->last.mem++) = CR; *(h->last.mem++) = LF; *(h->last++) = CR; *(h->last++) = LF;
if (r->header_only) { if (r->header_only) {
h->type |= NGX_HUNK_LAST; h->type |= NGX_HUNK_LAST;

View File

@ -26,7 +26,7 @@ static ngx_command_t ngx_http_output_filter_commands[] = {
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_output_filter_conf_t, hunk_size)}, offsetof(ngx_http_output_filter_conf_t, hunk_size)},
{ngx_string(""), 0, NULL, 0, 0} {ngx_null_string, 0, NULL, 0, 0}
}; };
@ -63,8 +63,8 @@ ngx_module_t ngx_http_output_filter_module = {
#define need_to_copy(r, hunk) \ #define need_to_copy(r, hunk) \
(((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) \ (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) \
&& (hunk->type & NGX_HUNK_FILE)) \ && (hunk->type & NGX_HUNK_FILE)) \
|| ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \ || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \
&& (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))) && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))))
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_hunk_t *hunk)
@ -81,7 +81,7 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
if (ctx == NULL) { if (ctx == NULL) {
ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module, ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module,
sizeof(ngx_http_output_filter_ctx_t)); sizeof(ngx_http_output_filter_ctx_t), NGX_ERROR);
} }
/* the short path for the case when the chain ctx->incoming is empty /* the short path for the case when the chain ctx->incoming is empty
@ -124,7 +124,12 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
ngx_http_output_filter_module); ngx_http_output_filter_module);
if (hunk->type & NGX_HUNK_LAST) { if (hunk->type & NGX_HUNK_LAST) {
size = hunk->last.mem - hunk->pos.mem; if (hunk->type & NGX_HUNK_IN_MEMORY) {
size = hunk->last - hunk->pos;
} else {
size = hunk->file_last - hunk->file_pos;
}
if (size > conf->hunk_size) { if (size > conf->hunk_size) {
size = conf->hunk_size; size = conf->hunk_size;
} }
@ -140,7 +145,7 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
/* our hunk is still busy */ /* our hunk is still busy */
} else if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { } else if (ctx->hunk->pos < ctx->hunk->last) {
rc = next_filter(r, NULL); rc = next_filter(r, NULL);
if (rc == NGX_ERROR || rc == NGX_AGAIN) { if (rc == NGX_ERROR || rc == NGX_AGAIN) {
@ -149,7 +154,7 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
/* NGX_OK */ /* NGX_OK */
/* set our hunk free */ /* set our hunk free */
ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; ctx->hunk->pos = ctx->hunk->last = ctx->hunk->start;
} }
#if (NGX_SUPPRESS_WARN) #if (NGX_SUPPRESS_WARN)
@ -209,11 +214,20 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
/* NGX_OK */ /* NGX_OK */
/* set our hunk free */ /* set our hunk free */
ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; ctx->hunk->pos = ctx->hunk->last = ctx->hunk->start;
/* repeat until we will have copied the whole first hunk from /* repeat until we will have copied the whole first hunk from
the chain ctx->incoming */ the chain ctx->incoming */
} while (ctx->incoming->hunk->pos.mem < ctx->incoming->hunk->last.mem);
if (ctx->incoming->hunk->type & NGX_HUNK_IN_MEMORY) {
size = ctx->incoming->hunk->last - ctx->incoming->hunk->pos;
} else {
size = ctx->incoming->hunk->file_last
- ctx->incoming->hunk->file_pos;
}
} while (size);
/* delete the completed hunk from the incoming chain */ /* delete the completed hunk from the incoming chain */
ctx->incoming = ctx->incoming->next; ctx->incoming = ctx->incoming->next;
@ -229,13 +243,31 @@ static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src)
{ {
ssize_t n, size; ssize_t n, size;
size = src->last.mem - src->pos.mem; if (src->type & NGX_HUNK_IN_MEMORY) {
if (size > (dst->end - dst->pos.mem)) { size = src->last - src->pos;
size = dst->end - dst->pos.mem; } else {
size = src->file_last - src->file_pos;
} }
if (src->type & NGX_HUNK_FILE) { if (size > (dst->end - dst->pos)) {
n = ngx_read_file(src->file, dst->pos.mem, size, src->pos.file); size = dst->end - dst->pos;
}
if (src->type & NGX_HUNK_IN_MEMORY) {
ngx_memcpy(src->pos, dst->pos, size);
src->pos += size;
dst->last += size;
if (src->type & NGX_HUNK_FILE) {
src->file_pos += n;
}
if (src->type & NGX_HUNK_LAST && src->pos == src->last) {
dst->type |= NGX_HUNK_LAST;
}
} else {
n = ngx_read_file(src->file, dst->pos, size, src->file_pos);
if (n == NGX_ERROR) { if (n == NGX_ERROR) {
return n; return n;
@ -256,17 +288,12 @@ static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src)
} }
} }
src->pos.mem += n; src->file_pos += n;
dst->last.mem += n; dst->last += n;
} else { if (src->type & NGX_HUNK_LAST && src->file_pos == src->file_last) {
ngx_memcpy(src->pos.mem, dst->pos.mem, size); dst->type |= NGX_HUNK_LAST;
src->pos.mem += size; }
dst->last.mem += size;
}
if (src->type & NGX_HUNK_LAST && src->pos.mem == src->last.mem) {
dst->type |= NGX_HUNK_LAST;
} }
return NGX_OK; return NGX_OK;

View File

@ -25,16 +25,11 @@ int ngx_read_http_request_line(ngx_http_request_t *r)
} state; } state;
state = r->state; state = r->state;
p = r->header_in->pos.mem; p = r->header_in->pos;
while (p < r->header_in->last.mem && state < sw_done) { while (p < r->header_in->last && state < sw_done) {
ch = *p++; ch = *p++;
/*
printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
state, p, r->header_in->last, ch, p);
*/
/* GCC 2.95.2 and VC 6.0 compile this switch as jump table */ /* GCC 2.95.2 and VC 6.0 compile this switch as jump table */
switch (state) { switch (state) {
@ -45,7 +40,7 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
switch (ch) { switch (ch) {
case 'G': case 'G':
if (p + 1 >= r->header_in->last.mem) { if (p + 1 >= r->header_in->last) {
return NGX_AGAIN; return NGX_AGAIN;
} }
@ -58,7 +53,7 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
break; break;
case 'H': case 'H':
if (p + 2 >= r->header_in->last.mem) { if (p + 2 >= r->header_in->last) {
return NGX_AGAIN; return NGX_AGAIN;
} }
@ -71,7 +66,7 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
break; break;
case 'P': case 'P':
if (p + 2 >= r->header_in->last.mem) { if (p + 2 >= r->header_in->last) {
return NGX_AGAIN; return NGX_AGAIN;
} }
@ -228,9 +223,9 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
/* "TTP/" */ /* "TTP/" */
case sw_http_version: case sw_http_version:
if (p + 2 >= r->header_in->last.mem) { if (p + 2 >= r->header_in->last) {
r->state = sw_http_version; r->state = sw_http_version;
r->header_in->pos.mem = p - 1; r->header_in->pos = p - 1;
return NGX_AGAIN; return NGX_AGAIN;
} }
@ -309,7 +304,7 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
} }
} }
r->header_in->pos.mem = p; r->header_in->pos = p;
if (state == sw_done) { if (state == sw_done) {
if (r->request_end == NULL) { if (r->request_end == NULL) {
@ -348,16 +343,11 @@ int ngx_read_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h)
} state; } state;
state = r->state; state = r->state;
p = h->pos.mem; p = h->pos;
while (p < h->last.mem && state < sw_done) { while (p < h->last && state < sw_done) {
ch = *p++; ch = *p++;
/*
printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
state, p, h->last.mem, ch, p);
*/
switch (state) { switch (state) {
/* first char */ /* first char */
@ -495,7 +485,7 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
} }
} }
h->pos.mem = p; h->pos = p;
if (state == sw_done) { if (state == sw_done) {
r->state = sw_start; r->state = sw_start;

View File

@ -39,6 +39,14 @@ static char error_404_page[] =
; ;
static char error_414_page[] =
"<html>" CRLF
"<head><title>414 Request-URI Too Large</title></head>" CRLF
"<body bgcolor=\"white\">" CRLF
"<center><h1>414 Request-URI Too Large</h1></center>" CRLF
;
static char error_500_page[] = static char error_500_page[] =
"<html>" CRLF "<html>" CRLF
"<head><title>500 Internal Server Error</title></head>" CRLF "<head><title>500 Internal Server Error</title></head>" CRLF
@ -58,6 +66,16 @@ static ngx_str_t error_pages[] = {
{ 0, NULL}, /* 402 */ { 0, NULL}, /* 402 */
{ sizeof(error_403_page) - 1, error_403_page }, { sizeof(error_403_page) - 1, error_403_page },
{ sizeof(error_404_page) - 1, error_404_page }, { sizeof(error_404_page) - 1, error_404_page },
{ 0, NULL}, /* 405 */
{ 0, NULL}, /* 406 */
{ 0, NULL}, /* 407 */
{ 0, NULL}, /* 408 */
{ 0, NULL}, /* 409 */
{ 0, NULL}, /* 410 */
{ 0, NULL}, /* 411 */
{ 0, NULL}, /* 412 */
{ 0, NULL}, /* 413 */
{ sizeof(error_414_page) - 1, error_414_page },
{ sizeof(error_500_page) - 1, error_500_page } { sizeof(error_500_page) - 1, error_500_page }
}; };
@ -79,7 +97,7 @@ int ngx_http_special_response(ngx_http_request_t *r, int error)
err = error - NGX_HTTP_BAD_REQUEST + 4; err = error - NGX_HTTP_BAD_REQUEST + 4;
else else
err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 4 + 5; err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 4 + 15;
if (error_pages[err].len == 0) if (error_pages[err].len == 0)
r->headers_out.content_length = -1; r->headers_out.content_length = -1;
@ -97,9 +115,9 @@ int ngx_http_special_response(ngx_http_request_t *r, int error)
ngx_test_null(message, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), NGX_ERROR); ngx_test_null(message, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), NGX_ERROR);
message->type = NGX_HUNK_MEMORY; message->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY;
message->pos.mem = error_pages[err].data; message->pos = error_pages[err].data;
message->last.mem = error_pages[err].data + error_pages[err].len; message->last = error_pages[err].data + error_pages[err].len;
if (ngx_http_output_filter(r, message) == NGX_ERROR) { if (ngx_http_output_filter(r, message) == NGX_ERROR) {
return NGX_ERROR; return NGX_ERROR;
@ -107,9 +125,9 @@ int ngx_http_special_response(ngx_http_request_t *r, int error)
ngx_test_null(tail, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), NGX_ERROR); ngx_test_null(tail, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), NGX_ERROR);
tail->type = NGX_HUNK_MEMORY|NGX_HUNK_LAST; tail->type = NGX_HUNK_MEMORY|NGX_HUNK_LAST|NGX_HUNK_IN_MEMORY;
tail->pos.mem = error_tail; tail->pos = error_tail;
tail->last.mem = error_tail + sizeof(error_tail); tail->last = error_tail + sizeof(error_tail);
return ngx_http_output_filter(r, tail); return ngx_http_output_filter(r, tail);
} }

View File

@ -70,7 +70,7 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_http_write_filter_module); ngx_http_write_filter_module);
if (ctx == NULL) { if (ctx == NULL) {
ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module, ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module,
sizeof(ngx_http_write_filter_ctx_t)); sizeof(ngx_http_write_filter_ctx_t), NGX_ERROR);
} }
size = flush = 0; size = flush = 0;
@ -80,14 +80,12 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
/* find the size, the flush point and the last entry of saved chain */ /* find the size, the flush point and the last entry of saved chain */
for (ce = ctx->out; ce; ce = ce->next) { for (ce = ctx->out; ce; ce = ce->next) {
le = &ce->next; le = &ce->next;
size += ce->hunk->last.file - ce->hunk->pos.file;
#if (NGX_DEBUG_WRITE_FILTER) if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
ngx_log_debug(r->connection->log, "write filter: old chunk: %x " size += ce->hunk->last - ce->hunk->pos;
QX_FMT " " QD_FMT _ } else {
ce->hunk->type _ ce->hunk->pos.file _ size += ce->hunk->file_last - ce->hunk->file_pos;
ce->hunk->last.file - ce->hunk->pos.file); }
#endif
if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
flush = size; flush = size;
@ -106,14 +104,12 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
ce->next = NULL; ce->next = NULL;
*le = ce; *le = ce;
le = &ce->next; le = &ce->next;
size += ce->hunk->last.file - ce->hunk->pos.file;
#if (NGX_DEBUG_WRITE_FILTER) if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
ngx_log_debug(r->connection->log, "write filter: new hunk: %x " size += ce->hunk->last - ce->hunk->pos;
QX_FMT " " QD_FMT _ } else {
ce->hunk->type _ ce->hunk->pos.file _ size += ce->hunk->file_last - ce->hunk->file_pos;
ce->hunk->last.file - ce->hunk->pos.file); }
#endif
if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
flush = size; flush = size;

View File

@ -14,9 +14,11 @@ typedef int ngx_err_t;
#define NGX_EAGAIN EWOULDBLOCK #define NGX_EAGAIN EWOULDBLOCK
#define NGX_EINPROGRESS EINPROGRESS #define NGX_EINPROGRESS EINPROGRESS
#define NGX_EADDRINUSE EADDRINUSE #define NGX_EADDRINUSE EADDRINUSE
#define NGX_ECONNRESET ECONNRESET
#define NGX_ETIMEDOUT ETIMEDOUT #define NGX_ETIMEDOUT ETIMEDOUT
#define NGX_ECANCELED ECANCELED #define NGX_ECANCELED ECANCELED
#define ngx_errno errno #define ngx_errno errno
#define ngx_socket_errno errno #define ngx_socket_errno errno
#define ngx_set_socket_errno(err) errno = err #define ngx_set_socket_errno(err) errno = err

View File

@ -15,7 +15,7 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx_connection_t *c, ngx_chain_t *in)
{ {
int rc; int rc;
char *prev; char *prev;
size_t hsize; size_t hsize, size;
off_t sent; off_t sent;
struct iovec *iov; struct iovec *iov;
struct sf_hdtr hdtr; struct sf_hdtr hdtr;
@ -32,54 +32,54 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx_connection_t *c, ngx_chain_t *in)
ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
/* create the header iovec */ /* create the header iovec */
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) { if (ngx_hunk_in_memory_only(ce->hunk)) {
prev = NULL; prev = NULL;
iov = NULL; iov = NULL;
/* create the iovec and coalesce the neighbouring chain entries */ /* create the iovec and coalesce the neighbouring chain entries */
while (ce && (ce->hunk->type & NGX_HUNK_IN_MEMORY)) while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
{
if (prev == ce->hunk->pos.mem) { if (prev == ce->hunk->pos) {
iov->iov_len += ce->hunk->last.mem - ce->hunk->pos.mem; iov->iov_len += ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last.mem; prev = ce->hunk->last;
} else { } else {
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
iov->iov_base = ce->hunk->pos.mem; iov->iov_base = ce->hunk->pos;
iov->iov_len = ce->hunk->last.mem - ce->hunk->pos.mem; iov->iov_len = ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last.mem; prev = ce->hunk->last;
} }
#if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG) #if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG)
hsize += ce->hunk->last.mem - ce->hunk->pos.mem; hsize += ce->hunk->last - ce->hunk->pos;
#endif #endif
ce = ce->next; ce = ce->next;
} }
} }
/* TODO: coalesce the neighbouring shadow file hunks */ /* TODO: coalesce the neighbouring file hunks */
if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
file = ce->hunk; file = ce->hunk;
ce = ce->next; ce = ce->next;
} }
/* create the trailer iovec */ /* create the trailer iovec */
if (ce && ce->hunk->type & NGX_HUNK_IN_MEMORY) { if (ce && ngx_hunk_in_memory_only(ce->hunk)) {
prev = NULL; prev = NULL;
iov = NULL; iov = NULL;
/* create the iovec and coalesce the neighbouring chain entries */ /* create the iovec and coalesce the neighbouring chain entries */
while (ce && (ce->hunk->type & NGX_HUNK_IN_MEMORY)) { while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
if (prev == ce->hunk->pos.mem) { if (prev == ce->hunk->pos) {
iov->iov_len += ce->hunk->last.mem - ce->hunk->pos.mem; iov->iov_len += ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last.mem; prev = ce->hunk->last;
} else { } else {
ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR); ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR);
iov->iov_base = ce->hunk->pos.mem; iov->iov_base = ce->hunk->pos;
iov->iov_len = ce->hunk->last.mem - ce->hunk->pos.mem; iov->iov_len = ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last.mem; prev = ce->hunk->last;
} }
ce = ce->next; ce = ce->next;
@ -92,8 +92,8 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx_connection_t *c, ngx_chain_t *in)
hdtr.trailers = (struct iovec *) trailer.elts; hdtr.trailers = (struct iovec *) trailer.elts;
hdtr.trl_cnt = trailer.nelts; hdtr.trl_cnt = trailer.nelts;
rc = sendfile(file->file->fd, c->fd, file->pos.file, rc = sendfile(file->file->fd, c->fd, file->file_pos,
(size_t) (file->last.file - file->pos.file) + hsize, (size_t) (file->file_last - file->file_pos) + hsize,
&hdtr, &sent, 0); &hdtr, &sent, 0);
if (rc == -1) { if (rc == -1) {
@ -110,8 +110,8 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx_connection_t *c, ngx_chain_t *in)
#if (NGX_DEBUG_WRITE_CHAIN) #if (NGX_DEBUG_WRITE_CHAIN)
ngx_log_debug(c->log, "sendfile: %d, @%qd %qd:%d" _ ngx_log_debug(c->log, "sendfile: %d, @%qd %qd:%d" _
rc _ file->pos.file _ *sent _ rc _ file->file_pos _ sent _
(size_t) (file->last.file - file->pos.file) + hsize); (size_t) (file->file_last - file->file_pos) + hsize);
#endif #endif
} else { } else {
@ -142,31 +142,33 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx_connection_t *c, ngx_chain_t *in)
for (ce = in; ce; ce = ce->next) { for (ce = in; ce; ce = ce->next) {
#if (NGX_DEBUG_WRITE_CHAIN) if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
ngx_log_debug(c->log, "write chain: %x %qx %qd" _ size = ce->hunk->last - ce->hunk->pos;
ce->hunk->type _ } else {
ce->hunk->pos.file _ size = ce->hunk->file_last - ce->hunk->file_pos;
ce->hunk->last.file - ce->hunk->pos.file); }
#endif
if (sent >= ce->hunk->last.file - ce->hunk->pos.file) { if (sent >= size) {
sent -= ce->hunk->last.file - ce->hunk->pos.file; sent -= size;
ce->hunk->pos.file = ce->hunk->last.file;
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
ce->hunk->pos = ce->hunk->last;
}
if (ce->hunk->type & NGX_HUNK_FILE) {
ce->hunk->file_pos = ce->hunk->file_last;
}
#if (NGX_DEBUG_WRITE_CHAIN)
ngx_log_debug(c->log, "write chain done: %qx %qd" _
ce->hunk->pos.file _ sent);
#endif
continue; continue;
} }
ce->hunk->pos.file += sent; if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
ce->hunk->pos += sent;
}
#if (NGX_DEBUG_WRITE_CHAIN) if (ce->hunk->type & NGX_HUNK_FILE) {
ngx_log_debug(c->log, "write chain rest: %qx %qd" _ ce->hunk->file_pos += sent;
ce->hunk->pos.file _ }
ce->hunk->last.file - ce->hunk->pos.file);
#endif
break; break;
} }

View File

@ -15,6 +15,7 @@ typedef DWORD ngx_err_t;
#define NGX_EAGAIN WSAEWOULDBLOCK #define NGX_EAGAIN WSAEWOULDBLOCK
#define NGX_EINPROGRESS WSAEINPROGRESS #define NGX_EINPROGRESS WSAEINPROGRESS
#define NGX_EADDRINUSE WSAEADDRINUSE #define NGX_EADDRINUSE WSAEADDRINUSE
#define NGX_ECONNRESET ECONNRESET
#define NGX_ETIMEDOUT WSAETIMEDOUT #define NGX_ETIMEDOUT WSAETIMEDOUT
int ngx_strerror_r(ngx_err_t err, char *errstr, size_t size); int ngx_strerror_r(ngx_err_t err, char *errstr, size_t size);