mirror of
https://github.com/nginx/nginx.git
synced 2024-12-20 06:03:31 -06:00
nginx-0.0.1-2003-03-11-23:38:13 import
This commit is contained in:
parent
0dad629f63
commit
b738757f35
@ -206,7 +206,7 @@ static int ngx_conf_read_token(ngx_conf_t *cf)
|
||||
|
||||
cf->args->nelts = 0;
|
||||
h = cf->conf_file->hunk;
|
||||
start = h->pos.mem;
|
||||
start = h->pos;
|
||||
|
||||
#if 0
|
||||
ngx_log_debug(cf->log, "TOKEN START");
|
||||
@ -214,31 +214,31 @@ ngx_log_debug(cf->log, "TOKEN START");
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
if (h->pos.mem >= h->last.mem) {
|
||||
if (h->pos >= h->last) {
|
||||
if (cf->conf_file->file.offset
|
||||
>= ngx_file_size(cf->conf_file->file.info)) {
|
||||
return NGX_CONF_FILE_DONE;
|
||||
}
|
||||
|
||||
if (h->pos.mem - start) {
|
||||
ngx_memcpy(h->start, start, h->pos.mem - start);
|
||||
if (h->pos - start) {
|
||||
ngx_memcpy(h->start, start, h->pos - start);
|
||||
}
|
||||
|
||||
n = ngx_read_file(&cf->conf_file->file,
|
||||
h->start + (h->pos.mem - start),
|
||||
h->end - (h->start + (h->pos.mem - start)),
|
||||
h->start + (h->pos - start),
|
||||
h->end - (h->start + (h->pos - start)),
|
||||
cf->conf_file->file.offset);
|
||||
|
||||
if (n == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
h->pos.mem = h->start + (h->pos.mem - start);
|
||||
h->pos = h->start + (h->pos - 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
|
||||
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;
|
||||
}
|
||||
|
||||
start = h->pos.mem - 1;
|
||||
start = h->pos - 1;
|
||||
|
||||
switch (ch) {
|
||||
|
||||
@ -363,11 +363,11 @@ ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _
|
||||
if (found) {
|
||||
ngx_test_null(word, ngx_push_array(cf->args), NGX_ERROR);
|
||||
ngx_test_null(word->data,
|
||||
ngx_palloc(cf->pool, h->pos.mem - start + 1),
|
||||
ngx_palloc(cf->pool, h->pos - start + 1),
|
||||
NGX_ERROR);
|
||||
|
||||
for (dst = word->data, src = start, len = 0;
|
||||
src < h->pos.mem - 1;
|
||||
src < h->pos - 1;
|
||||
len++)
|
||||
{
|
||||
if (*src == '\\') {
|
||||
|
@ -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);
|
||||
|
||||
#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);
|
||||
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->type = NGX_HUNK_TEMP;
|
||||
h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
|
||||
h->tag = 0;
|
||||
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);
|
||||
|
||||
#if !(HAVE_OFFSET_EQUAL_PTR)
|
||||
h->pos.file = h->last.file = 0;
|
||||
#endif
|
||||
|
||||
if (hunk->type & NGX_HUNK_TEMP && hunk->pos.mem - hunk->pre_start >= size) {
|
||||
if (hunk->type & NGX_HUNK_TEMP && hunk->pos - hunk->pre_start >= size) {
|
||||
/* keep hunk->start unchanged - used in restore */
|
||||
h->pre_start = hunk->pre_start;
|
||||
h->end = h->post_end = hunk->pre_start = hunk->pos.mem;
|
||||
h->start = h->pos.mem = h->last.mem = h->end - size;
|
||||
h->end = h->post_end = hunk->pre_start = hunk->pos;
|
||||
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->file = NULL;
|
||||
|
||||
} else {
|
||||
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->file_pos = h->file_last = 0;
|
||||
|
||||
h->type = NGX_HUNK_TEMP;
|
||||
h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
|
||||
h->tag = 0;
|
||||
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);
|
||||
|
||||
#if !(HAVE_OFFSET_EQUAL_PTR)
|
||||
h->pos.file = h->last.file = 0;
|
||||
#endif
|
||||
|
||||
if (hunk->type & NGX_HUNK_TEMP
|
||||
&& hunk->last.mem == hunk->end
|
||||
&& hunk->last == hunk->end
|
||||
&& hunk->post_end - hunk->end >= size)
|
||||
{
|
||||
h->post_end = hunk->post_end;
|
||||
h->pre_start = h->start = h->pos.mem = h->last.mem = hunk->post_end =
|
||||
hunk->last.mem;
|
||||
h->type = NGX_HUNK_TEMP;
|
||||
h->pre_start = h->start = h->pos = h->last = hunk->post_end =
|
||||
hunk->last;
|
||||
h->file_pos = h->file_last = 0;
|
||||
|
||||
h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
|
||||
h->tag = 0;
|
||||
h->file = NULL;
|
||||
|
||||
} else {
|
||||
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->file_pos = h->file_last = 0;
|
||||
|
||||
h->type = NGX_HUNK_TEMP;
|
||||
h->type = NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY;
|
||||
h->tag = 0;
|
||||
h->file = NULL;
|
||||
}
|
||||
|
@ -10,34 +10,34 @@
|
||||
|
||||
/* hunk type */
|
||||
|
||||
/* temp means that hunk's content can be changed */
|
||||
/* other type means that hunk's content can not be changed */
|
||||
#define NGX_HUNK_TEMP 0x0001
|
||||
#define NGX_HUNK_MEMORY 0x0002
|
||||
#define NGX_HUNK_MMAP 0x0004
|
||||
#define NGX_HUNK_FILE 0x0008
|
||||
/* the hunk is in memory */
|
||||
#define NGX_HUNK_IN_MEMORY 0x0001
|
||||
/* the hunk's content can be changed */
|
||||
#define NGX_HUNK_TEMP 0x0002
|
||||
/* the hunk's content is in cache and can not be changed */
|
||||
#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 */
|
||||
|
||||
/* in thread state flush means to write the hunk completely before return */
|
||||
/* in event state flush means to start to write the hunk */
|
||||
#define NGX_HUNK_FLUSH 0x0100
|
||||
#define NGX_HUNK_FLUSH 0x1000
|
||||
/* last hunk */
|
||||
#define NGX_HUNK_LAST 0x0200
|
||||
#if 0
|
||||
/* can be used with NGX_HUNK_LAST only */
|
||||
#define NGX_HUNK_SHUTDOWN 0x0400 /
|
||||
#endif
|
||||
#define NGX_HUNK_LAST 0x2000
|
||||
|
||||
#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;
|
||||
struct ngx_hunk_s {
|
||||
#if 0
|
||||
union {
|
||||
char *mem; /* start of current data */
|
||||
off_t file;
|
||||
@ -46,6 +46,13 @@ struct ngx_hunk_s {
|
||||
char *mem; /* end of current data */
|
||||
off_t file;
|
||||
} last;
|
||||
#endif
|
||||
|
||||
char *pos;
|
||||
char *last;
|
||||
off_t file_pos;
|
||||
off_t file_last;
|
||||
|
||||
int type;
|
||||
char *start; /* start 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_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,
|
||||
int before, int after);
|
||||
|
||||
|
@ -12,6 +12,7 @@ typedef struct {
|
||||
|
||||
|
||||
#define ngx_string(str) { sizeof(str) - 1, str }
|
||||
#define ngx_null_string { 0, NULL }
|
||||
|
||||
|
||||
#if (WIN32)
|
||||
|
@ -74,12 +74,17 @@ int ngx_kqueue_init(int max_connections, ngx_log_t *log)
|
||||
|
||||
ngx_event_flags = NGX_HAVE_LEVEL_EVENT
|
||||
|NGX_HAVE_ONESHOT_EVENT
|
||||
|
||||
#if (HAVE_CLEAR_EVENT)
|
||||
|NGX_HAVE_CLEAR_EVENT
|
||||
#else
|
||||
|NGX_USE_LEVEL_EVENT
|
||||
#endif
|
||||
|
||||
#if (HAVE_LOWAT_EVENT)
|
||||
|NGX_HAVE_LOWAT_EVENT
|
||||
#endif
|
||||
|
||||
|NGX_HAVE_KQUEUE_EVENT;
|
||||
|
||||
ngx_write_chain_proc = ngx_freebsd_write_chain;
|
||||
|
@ -56,7 +56,6 @@ struct ngx_event_s {
|
||||
/* otherwise: */
|
||||
/* accept: 1 if accept many, 0 otherwise */
|
||||
|
||||
unsigned level:1;
|
||||
unsigned oneshot:1;
|
||||
|
||||
#if 0
|
||||
@ -73,6 +72,7 @@ struct ngx_event_s {
|
||||
unsigned process:1;
|
||||
unsigned read_discarded:1;
|
||||
|
||||
unsigned ignore_econnreset:1;
|
||||
unsigned unexpected_eof:1;
|
||||
|
||||
#if (HAVE_DEFERRED_ACCEPT)
|
||||
@ -149,7 +149,7 @@ typedef struct {
|
||||
#define NGX_HAVE_LEVEL_EVENT 1
|
||||
|
||||
/* 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
|
||||
|
||||
/* Event filter notifies only changes and initial level - kqueue */
|
||||
@ -159,21 +159,24 @@ typedef struct {
|
||||
#define NGX_HAVE_KQUEUE_EVENT 8
|
||||
|
||||
/* Event filter supports low water mark - kqueue's NOTE_LOWAT,
|
||||
early kqueue implementations have no NOTE_LOWAT so we need separate flag */
|
||||
#define NGX_HAVE_LOWAT_EVENT 16
|
||||
early kqueue implementations have no NOTE_LOWAT so we need a separate flag */
|
||||
#define NGX_HAVE_LOWAT_EVENT 0x00000010
|
||||
|
||||
/* 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 */
|
||||
#define NGX_HAVE_SIGIO_EVENT 64
|
||||
#define NGX_HAVE_SIGIO_EVENT 0x00000040
|
||||
|
||||
/* 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.
|
||||
It also requires to set HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT */
|
||||
#define NGX_HAVE_IOCP_EVENT 256
|
||||
/* Need to add socket or handle only once - i/o completion port.
|
||||
It also requires HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT to be set */
|
||||
#define NGX_HAVE_IOCP_EVENT 0x00000100
|
||||
|
||||
|
||||
#define NGX_USE_LEVEL_EVENT 0x00010000
|
||||
|
||||
|
||||
/* Event filter is deleted before closing file. Has no meaning
|
||||
|
@ -13,15 +13,20 @@ int ngx_event_close_connection(ngx_event_t *ev)
|
||||
int rc;
|
||||
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_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);
|
||||
ngx_del_timer(c->write);
|
||||
if (c->write->timer_set) {
|
||||
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->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
|
||||
@ -32,5 +37,7 @@ int ngx_event_close_connection(ngx_event_t *ev)
|
||||
|
||||
c->fd = -1;
|
||||
|
||||
ngx_destroy_pool(c->pool);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -10,23 +10,34 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size)
|
||||
{
|
||||
int n;
|
||||
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_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "recv() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
#if (HAVE_KQUEUE)
|
||||
ngx_log_debug(c->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _
|
||||
c->read->eof _ c->read->available _ c->read->error);
|
||||
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
|
||||
ngx_log_debug(c->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _
|
||||
ev->eof _ ev->available _ ev->error);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (USE_KQUEUE)
|
||||
|
||||
if (c->read->eof && c->read->available == 0) {
|
||||
if (c->read->error) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, c->read->error,
|
||||
if (ev->eof && ev->available == 0) {
|
||||
if (ev->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");
|
||||
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)
|
||||
|
||||
if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) {
|
||||
if (c->read->eof && c->read->available == 0) {
|
||||
if (c->read->error) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, c->read->error,
|
||||
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
|
||||
if (ev->eof && ev->available == 0) {
|
||||
if (ev->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");
|
||||
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) {
|
||||
err = ngx_socket_errno;
|
||||
|
||||
if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (err == NGX_EAGAIN) {
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returns EAGAIN");
|
||||
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)
|
||||
|
||||
c->read->available -= n;
|
||||
ev->available -= n;
|
||||
|
||||
#elif (HAVE_KQUEUE)
|
||||
|
||||
if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) {
|
||||
c->read->available -= n;
|
||||
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
|
||||
ev->available -= n;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -4,12 +4,53 @@
|
||||
#include <ngx_string.h>
|
||||
#include <ngx_file.h>
|
||||
#include <ngx_hunk.h>
|
||||
#include <ngx_conf_file.h>
|
||||
#include <ngx_event_write.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_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);
|
||||
@ -18,6 +59,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
|
||||
char *addr_text);
|
||||
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_process_status_line(ngx_http_request_t *r,
|
||||
ngx_http_proxy_ctx_t *p);
|
||||
@ -45,12 +87,13 @@ int ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
|
||||
if (p == NULL) {
|
||||
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);
|
||||
if (chain == NULL) {
|
||||
return NGX_ERROR;
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
/* TODO: Host length */
|
||||
|
||||
/* "Connection: close\r\n" */
|
||||
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_add_hunk_to_chain(chain, hunk, r->pool, NULL);
|
||||
|
||||
ngx_memcpy(hunk->last.mem, r->request_line.data, r->request_line.len);
|
||||
hunk->last.mem += r->request_line.len;
|
||||
*(hunk->last.mem++) = CR; *(hunk->last.mem++) = LF;
|
||||
/* STUB: "method p->url HTTP/1.0" */
|
||||
|
||||
ngx_memcpy(hunk->last.mem, conn_close, sizeof(conn_close) - 1);
|
||||
hunk->last.mem += sizeof(conn_close) - 1;
|
||||
ngx_memcpy(hunk->last, r->request_line.data, r->request_line.len);
|
||||
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++) {
|
||||
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;
|
||||
}
|
||||
|
||||
ngx_memcpy(hunk->last.mem, header[i].key.data, header[i].key.len);
|
||||
hunk->last.mem += header[i].key.len;
|
||||
ngx_memcpy(hunk->last, header[i].key.data, 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);
|
||||
hunk->last.mem += header[i].value.len;
|
||||
ngx_memcpy(hunk->last, header[i].value.data, 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'" _
|
||||
header[i].key.data _ header[i].value.data);
|
||||
}
|
||||
|
||||
/* 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';
|
||||
ngx_log_debug(r->connection->log, "PROXY:\n'%s'" _ hunk->pos.mem);
|
||||
/* STUB */ *(hunk->last++) = '\0';
|
||||
ngx_log_debug(r->connection->log, "PROXY:\n'%s'" _ hunk->pos);
|
||||
|
||||
return chain;
|
||||
}
|
||||
@ -142,7 +194,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
|
||||
struct sockaddr_in *addr,
|
||||
char *addr_text)
|
||||
{
|
||||
int rc;
|
||||
int rc, event;
|
||||
ngx_err_t err;
|
||||
ngx_socket_t s;
|
||||
ngx_event_t *rev, *wev;
|
||||
@ -157,7 +209,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
|
||||
if (s == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
|
||||
ngx_socket_n " failed");
|
||||
return NGX_ERROR;
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -172,7 +224,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
|
||||
ngx_close_socket_n " failed");
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -186,7 +238,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
|
||||
ngx_close_socket_n " failed");
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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_create_pool(/* STUB */ 1024 /**/, pc->log),
|
||||
NGX_ERROR);
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
|
||||
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) {
|
||||
#else
|
||||
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) != NGX_OK) {
|
||||
#endif
|
||||
return NGX_ERROR;
|
||||
return NGX_HTTP_INTERNAL_SERVER_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) {
|
||||
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;
|
||||
@ -262,7 +341,7 @@ static int ngx_http_proxy_send_request(ngx_event_t *ev)
|
||||
p = (ngx_http_proxy_ctx_t *)
|
||||
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) {
|
||||
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;
|
||||
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_proxy_ctx_t *p;
|
||||
|
||||
c = (ngx_connection_t *) ev->data;
|
||||
r = (ngx_http_request_t *) c->data;
|
||||
|
||||
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;
|
||||
r = (ngx_http_request_t *) c->data;
|
||||
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) {
|
||||
ngx_test_null(p->header_in,
|
||||
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;
|
||||
if (ev->timedout) {
|
||||
return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT);
|
||||
}
|
||||
|
||||
n = ngx_event_recv(c, p->header_in->last.mem,
|
||||
p->header_in->end - p->header_in->last.mem);
|
||||
lcf = (ngx_http_proxy_loc_conf_t *)
|
||||
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);
|
||||
|
||||
p->header_in->last.mem += n;
|
||||
p->header_in->last += n;
|
||||
|
||||
/* STUB */
|
||||
*p->header_in->last.mem = '\0';
|
||||
ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->header_in->pos.mem);
|
||||
*p->header_in->last = '\0';
|
||||
ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->header_in->pos);
|
||||
/**/
|
||||
|
||||
if (n == 0) {
|
||||
@ -355,13 +512,14 @@ static int ngx_http_proxy_read_response_header(ngx_event_t *ev)
|
||||
#endif
|
||||
|
||||
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_WAITING;
|
||||
}
|
||||
|
||||
|
||||
static int ngx_http_proxy_process_status_line(ngx_http_request_t *r,
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static int ngx_http_proxy_process_response_header(ngx_http_request_t *r,
|
||||
ngx_http_proxy_ctx_t *p)
|
||||
@ -398,6 +557,7 @@ static int ngx_http_proxy_process_response_header(ngx_http_request_t *r,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
|
||||
{
|
||||
int n;
|
||||
@ -419,7 +579,7 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
|
||||
|
||||
if (p->hunks.nelts > 0) {
|
||||
h = ((ngx_hunk_t **) p->hunks.elts)[p->hunks.nelts - 1];
|
||||
left = h->end - h->last.mem;
|
||||
left = h->end - h->last;
|
||||
|
||||
} else {
|
||||
h = NULL;
|
||||
@ -453,13 +613,13 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
|
||||
/* STUB */ 4096 /**/, 0, 0),
|
||||
NGX_ERROR);
|
||||
|
||||
h->type = NGX_HUNK_MEMORY;
|
||||
h->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY;
|
||||
*ph = h;
|
||||
}
|
||||
|
||||
if (h != NULL) {
|
||||
buf = h->last.mem;
|
||||
size = h->end - h->last.mem;
|
||||
buf = h->last;
|
||||
size = h->end - h->last;
|
||||
|
||||
} else {
|
||||
buf = (char *) &buf;
|
||||
@ -478,12 +638,12 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
h->last.mem += n;
|
||||
left = h->end - h->last.mem;
|
||||
h->last += n;
|
||||
left = h->end - h->last;
|
||||
|
||||
/* STUB */
|
||||
*h->last.mem = '\0';
|
||||
ngx_log_debug(c->log, "PROXY:\n'%s'" _ h->pos.mem);
|
||||
*h->last = '\0';
|
||||
ngx_log_debug(c->log, "PROXY:\n'%s'" _ h->pos);
|
||||
/**/
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
||||
static int ngx_http_proxy_write_to_client(ngx_event_t *ev)
|
||||
{
|
||||
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)
|
||||
{
|
||||
char ch;
|
||||
@ -554,21 +724,16 @@ static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *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++;
|
||||
|
||||
#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) {
|
||||
|
||||
/* "HTTP/" */
|
||||
case sw_start:
|
||||
if (p + 3 >= ctx->header_in->last.mem) {
|
||||
if (p + 3 >= ctx->header_in->last) {
|
||||
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 (ctx->request_end == NULL) {
|
||||
|
@ -14,6 +14,12 @@ typedef struct {
|
||||
int dummy;
|
||||
} 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;
|
||||
|
||||
struct ngx_http_proxy_ctx_s {
|
||||
@ -24,6 +30,7 @@ struct ngx_http_proxy_ctx_s {
|
||||
|
||||
int hunk_n;
|
||||
|
||||
ngx_connection_t *connection;
|
||||
ngx_http_proxy_headers_in_t *headers_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_ */
|
||||
|
@ -144,8 +144,8 @@ int ngx_http_static_handler(ngx_http_request_t *r)
|
||||
#if 1
|
||||
|
||||
h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
|
||||
h->pos.file = 0;
|
||||
h->last.file = ngx_file_size(r->file.info);
|
||||
h->file_pos = 0;
|
||||
h->file_last = ngx_file_size(r->file.info);
|
||||
|
||||
h->file->fd = r->file.fd;
|
||||
h->file->log = r->connection->log;
|
||||
|
@ -27,11 +27,6 @@ int ngx_http_large_client_header = 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;
|
||||
|
||||
|
@ -47,29 +47,17 @@
|
||||
#define NGX_HTTP_NOT_FOUND 404
|
||||
#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414
|
||||
#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_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 {
|
||||
size_t len;
|
||||
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_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 { \
|
||||
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; \
|
||||
} 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_discarded_buffer_size;
|
||||
|
||||
extern int ngx_http_lingering_timeout;
|
||||
extern int ngx_http_lingering_time;
|
||||
|
||||
extern int ngx_http_url_in_error_log;
|
||||
|
||||
extern ngx_array_t ngx_http_index_handlers;
|
||||
|
@ -96,6 +96,18 @@ static ngx_command_t ngx_http_core_commands[] = {
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
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}
|
||||
};
|
||||
|
||||
@ -138,7 +150,7 @@ int ngx_http_handler(ngx_http_request_t *r)
|
||||
r->connection->unexpected_eof = 0;
|
||||
|
||||
r->lingering_close = 1;
|
||||
r->keepalive = 1;
|
||||
r->keepalive = 0;
|
||||
|
||||
#if 1
|
||||
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] == '/') {
|
||||
r->handler = ngx_http_core_index_handler;
|
||||
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)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
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_assert((r->file.fd != NGX_INVALID_FILE), /* void */ ; ,
|
||||
r->connection->log, "file already closed");
|
||||
|
||||
if (r->file.fd != NGX_INVALID_FILE) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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 = (ngx_http_log_ctx_t *) c->log->data;
|
||||
ctx->url = NULL;
|
||||
|
||||
ngx_destroy_pool(r->pool);
|
||||
|
||||
ngx_log_debug(r->connection->log, "http closed");
|
||||
|
||||
if (r->connection->read->timer_set) {
|
||||
ngx_del_timer(r->connection->read);
|
||||
if (c->read->timer_set) {
|
||||
ngx_del_timer(c->read);
|
||||
c->read->timer_set = 0;
|
||||
}
|
||||
|
||||
if (r->connection->write->timer_set) {
|
||||
ngx_del_timer(r->connection->write);
|
||||
if (c->write->timer_set) {
|
||||
ngx_del_timer(c->write);
|
||||
c->write->timer_set = 0;
|
||||
}
|
||||
|
||||
ngx_log_debug(c->log, "http closed");
|
||||
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
@ -780,7 +791,7 @@ static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool)
|
||||
|
||||
lcf->send_timeout = 10;
|
||||
lcf->discarded_buffer_size = 1500;
|
||||
lcf->lingering_time = 30;
|
||||
lcf->lingering_time = 30000;
|
||||
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;
|
||||
|
||||
ls->port = atoi(args[1].data);
|
||||
if (ls->port < 0) {
|
||||
return "port must be greater or equal to zero";
|
||||
if (ls->port < 1 || ls->port > 65536) {
|
||||
return "port must be between 1 and 65535";
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
|
@ -130,7 +130,6 @@ int ngx_http_init_connection(ngx_connection_t *c)
|
||||
|
||||
/* select, poll, /dev/poll */
|
||||
|
||||
ev->level = 1;
|
||||
return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
|
||||
|
||||
#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)
|
||||
{
|
||||
int n, rc;
|
||||
int n, rc, again;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_request_t *r;
|
||||
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");
|
||||
|
||||
#if (HAVE_AIO_EVENT)
|
||||
do {
|
||||
#endif
|
||||
|
||||
if (r->header_read) {
|
||||
if (r->header_in->end - r->header_in->last == 0) {
|
||||
again = 1;
|
||||
} else {
|
||||
again = 0;
|
||||
}
|
||||
|
||||
r->header_read = 0;
|
||||
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 {
|
||||
n = ngx_event_recv(c, r->header_in->last.mem,
|
||||
r->header_in->end - r->header_in->last.mem);
|
||||
n = ngx_event_recv(c, r->header_in->last,
|
||||
r->header_in->end - r->header_in->last);
|
||||
|
||||
if (n == NGX_AGAIN) {
|
||||
if (!r->header_timeout_set) {
|
||||
@ -228,8 +231,9 @@ static int ngx_http_process_request_header(ngx_event_t *ev)
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (n == NGX_ERROR)
|
||||
if (n == NGX_ERROR) {
|
||||
return ngx_http_close_request(r);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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:
|
||||
@ -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 */
|
||||
rc = (r->state_handler)(r);
|
||||
|
||||
if (rc == NGX_ERROR)
|
||||
if (rc == NGX_ERROR) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
} while (rc == NGX_AGAIN
|
||||
&& r->header_in->pos.mem < r->header_in->last.mem);
|
||||
} while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last);
|
||||
|
||||
#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
|
||||
|
||||
} while (rc == NGX_AGAIN && again);
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
/* 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_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 */
|
||||
|
||||
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 */
|
||||
|
||||
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
|
||||
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
|
||||
is enabled otherwise a request line had been already copied
|
||||
We need to copy it here only if the large client headers
|
||||
are enabled otherwise a request line had been already copied
|
||||
to the start of r->header_in hunk in ngx_http_set_keepalive() */
|
||||
|
||||
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,
|
||||
r->header_in->last.mem - r->request_start);
|
||||
r->header_in->last - r->request_start);
|
||||
|
||||
r->header_in->pos.mem -= offset;
|
||||
r->header_in->last.mem -= offset;
|
||||
r->header_in->pos -= offset;
|
||||
r->header_in->last -= offset;
|
||||
r->request_start = r->header_in->start;
|
||||
r->request_end -= offset;
|
||||
r->uri_start -= offset;
|
||||
@ -437,7 +454,7 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
|
||||
|
||||
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) {
|
||||
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 */
|
||||
|
||||
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 */
|
||||
|
||||
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,
|
||||
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->pos.mem -= offset;
|
||||
r->header_in->last -= offset;
|
||||
r->header_in->pos -= offset;
|
||||
r->header_name_start = r->header_in->start;
|
||||
r->header_name_end -= 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);
|
||||
|
||||
/* if large client header is enabled then
|
||||
/* if large client headers are enabled then
|
||||
we need to copy header name and value */
|
||||
|
||||
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 {
|
||||
event = NGX_LEVEL_EVENT;
|
||||
wev->level = 1;
|
||||
}
|
||||
|
||||
#else /* select, poll, /dev/poll */
|
||||
|
||||
event = NGX_LEVEL_EVENT;
|
||||
wev->level = 1;
|
||||
|
||||
#endif
|
||||
|
||||
@ -751,11 +766,11 @@ static int ngx_http_block_read(ngx_event_t *ev)
|
||||
|
||||
#else
|
||||
|
||||
if (ev->level) { /* select, poll, /dev/poll */
|
||||
if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */
|
||||
ev->blocked = 1;
|
||||
return ngx_del_event(ev, NGX_READ_EVENT, 0);
|
||||
|
||||
} else { /* kqueue, epoll */
|
||||
} else { /* kqueue, epoll */
|
||||
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)
|
||||
{
|
||||
int len;
|
||||
int len, blocked;
|
||||
ngx_hunk_t *h;
|
||||
ngx_event_t *rev, *wev;
|
||||
ngx_connection_t *c;
|
||||
@ -841,33 +856,37 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
|
||||
rev = c->read;
|
||||
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->action = "closing request";
|
||||
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;
|
||||
|
||||
/* pipelined request */
|
||||
if (h->pos.mem < h->last.mem) {
|
||||
if (h->pos < h->last) {
|
||||
|
||||
/* 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
|
||||
client header is not enabled. This copy should be rare
|
||||
because clients that support pipelined requests (Mozilla 1.x,
|
||||
Opera 6.x) are still rare */
|
||||
so if large client headers are not enabled
|
||||
we need to copy the data to the start of c->buffer.
|
||||
This copy should be rare because clients that support
|
||||
pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */
|
||||
|
||||
if (!ngx_http_large_client_header) {
|
||||
len = h->last.mem - h->pos.mem;
|
||||
ngx_memcpy(h->start, h->pos.mem, len);
|
||||
h->pos.mem = h->start;
|
||||
h->last.mem = h->start + len;
|
||||
len = h->last - h->pos;
|
||||
ngx_memcpy(h->start, h->pos, len);
|
||||
h->pos = h->start;
|
||||
h->last = h->start + len;
|
||||
}
|
||||
|
||||
c->pipeline = 1;
|
||||
@ -877,10 +896,10 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
|
||||
|
||||
c->pipeline = 0;
|
||||
|
||||
h->pos.mem = h->last.mem = h->start;
|
||||
h->pos = h->last = h->start;
|
||||
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) {
|
||||
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 (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);
|
||||
}
|
||||
|
||||
@ -913,11 +938,13 @@ static int ngx_http_keepalive_handler(ngx_event_t *ev)
|
||||
if (ev->timedout)
|
||||
return NGX_DONE;
|
||||
|
||||
/* TODO: MSIE closes keepalive connection with ECONNRESET
|
||||
so we need to handle here this error
|
||||
1) in INFO (not ERR) level, 2) with time elapsed */
|
||||
n = ngx_event_recv(c, c->buffer->last.mem,
|
||||
c->buffer->end - c->buffer->last.mem);
|
||||
/* MSIE closes keepalive connection with RST flag
|
||||
so we ignore ECONNRESET here */
|
||||
|
||||
ev->ignore_econnreset = 1;
|
||||
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)
|
||||
return n;
|
||||
@ -926,12 +953,12 @@ static int ngx_http_keepalive_handler(ngx_event_t *ev)
|
||||
ev->log->handler = NULL;
|
||||
|
||||
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);
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
c->buffer->last.mem += n;
|
||||
c->buffer->last += n;
|
||||
ev->log->handler = ngx_http_log_error;
|
||||
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)
|
||||
{
|
||||
ngx_event_t *ev;
|
||||
ngx_connection_t *c;
|
||||
int blocked;
|
||||
ngx_event_t *rev, *wev;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_core_loc_conf_t *lcf;
|
||||
|
||||
c = r->connection;
|
||||
ev = r->connection->read;
|
||||
rev = c->read;
|
||||
wev = c->write;
|
||||
|
||||
lcf = (ngx_http_core_loc_conf_t *)
|
||||
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;
|
||||
|
||||
if (ev->timer_set) {
|
||||
ngx_del_timer(ev);
|
||||
if (rev->timer_set) {
|
||||
ngx_del_timer(rev);
|
||||
} 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 (ngx_event_flags & NGX_HAVE_LEVEL_EVENT) {
|
||||
if (ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
|
||||
== NGX_ERROR) {
|
||||
return 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_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) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_socket_errno,
|
||||
if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
|
||||
ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
|
||||
ngx_shutdown_socket_n " failed");
|
||||
return ngx_http_close_request(r);
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
#if (HAVE_CLEAR_EVENT) /* kqueue */ || (HAVE_EDGE_EVENT) /* epoll */
|
||||
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);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
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) {
|
||||
r->discarded_buffer = r->header_in->last.mem;
|
||||
r->discarded_buffer = r->header_in->last;
|
||||
|
||||
} else {
|
||||
ngx_test_null(r->discarded_buffer,
|
||||
|
@ -48,22 +48,37 @@ static char server_string[] = "Server: " NGINX_VER CRLF;
|
||||
static ngx_str_t http_codes[] = {
|
||||
|
||||
ngx_string("200 OK"),
|
||||
#if 0
|
||||
{ 6, "200 OK" },
|
||||
#endif
|
||||
|
||||
{ 21, "301 Moved Permanently" },
|
||||
{ 21, "302 Moved Temporarily" },
|
||||
{ 0, NULL },
|
||||
{ 16, "304 Not Modified" },
|
||||
ngx_string("301 Moved Permanently"),
|
||||
ngx_string("302 Moved Temporarily"),
|
||||
ngx_null_string, /* 303 */
|
||||
ngx_string("304 Not Modified"),
|
||||
|
||||
{ 15, "400 Bad Request" },
|
||||
{ 0, NULL },
|
||||
{ 0, NULL },
|
||||
{ 13, "403 Forbidden" },
|
||||
{ 13, "404 Not Found" },
|
||||
ngx_string("400 Bad Request"),
|
||||
ngx_null_string, /* 401 */
|
||||
ngx_null_string, /* 402 */
|
||||
ngx_string("403 Forbidden"),
|
||||
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 {
|
||||
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;
|
||||
@ -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);
|
||||
|
||||
/* "HTTP/1.x " */
|
||||
ngx_memcpy(h->last.mem, "HTTP/1.1 ", 9);
|
||||
h->last.mem += 9;
|
||||
ngx_memcpy(h->last, "HTTP/1.1 ", 9);
|
||||
h->last += 9;
|
||||
|
||||
/* status line */
|
||||
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);
|
||||
h->last.mem += r->headers_out.status_line.len;
|
||||
h->last += r->headers_out.status_line.len;
|
||||
|
||||
} else {
|
||||
ngx_memcpy(h->last.mem, http_codes[status].data,
|
||||
ngx_memcpy(h->last, http_codes[status].data,
|
||||
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)) {
|
||||
ngx_memcpy(h->last.mem, server_string, sizeof(server_string) - 1);
|
||||
h->last.mem += sizeof(server_string) - 1;
|
||||
ngx_memcpy(h->last, server_string, sizeof(server_string) - 1);
|
||||
h->last += sizeof(server_string) - 1;
|
||||
}
|
||||
|
||||
if (!(r->headers_out.date && r->headers_out.date->key.len)) {
|
||||
ngx_memcpy(h->last.mem, "Date: ", 6);
|
||||
h->last.mem += 6;
|
||||
h->last.mem += ngx_http_get_time(h->last.mem, time(NULL));
|
||||
*(h->last.mem++) = CR; *(h->last.mem++) = LF;
|
||||
ngx_memcpy(h->last, "Date: ", 6);
|
||||
h->last += 6;
|
||||
h->last += ngx_http_get_time(h->last, time(NULL));
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
/* 2^64 is 20 characters */
|
||||
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,
|
||||
r->headers_out.content_length);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (r->headers_out.content_type.len) {
|
||||
ngx_memcpy(h->last.mem, "Content-Type: ", 14);
|
||||
h->last.mem += 14;
|
||||
ngx_memcpy(h->last.mem, r->headers_out.content_type.data,
|
||||
ngx_memcpy(h->last, "Content-Type: ", 14);
|
||||
h->last += 14;
|
||||
ngx_memcpy(h->last, r->headers_out.content_type.data,
|
||||
r->headers_out.content_type.len);
|
||||
h->last.mem += r->headers_out.content_type.len;
|
||||
*(h->last.mem++) = CR; *(h->last.mem++) = LF;
|
||||
h->last += r->headers_out.content_type.len;
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
#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_time != -1)
|
||||
{
|
||||
ngx_memcpy(h->last.mem, "Last-Modified: ", 15);
|
||||
h->last.mem += 15;
|
||||
h->last.mem += ngx_http_get_time(h->last.mem,
|
||||
ngx_memcpy(h->last, "Last-Modified: ", 15);
|
||||
h->last += 15;
|
||||
h->last += ngx_http_get_time(h->last,
|
||||
r->headers_out.last_modified_time);
|
||||
*(h->last.mem++) = CR; *(h->last.mem++) = LF;
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
if (r->keepalive == 0) {
|
||||
ngx_memcpy(h->last.mem, "Connection: close" CRLF, 19);
|
||||
h->last.mem += 19;
|
||||
ngx_memcpy(h->last, "Connection: close" CRLF, 19);
|
||||
h->last += 19;
|
||||
|
||||
} else {
|
||||
ngx_memcpy(h->last.mem, "Connection: keep-alive" CRLF, 24);
|
||||
h->last.mem += 24;
|
||||
ngx_memcpy(h->last, "Connection: keep-alive" CRLF, 24);
|
||||
h->last += 24;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ngx_memcpy(h->last.mem, header[i].key.data, header[i].key.len);
|
||||
h->last.mem += header[i].key.len;
|
||||
*(h->last.mem++) = ':' ; *(h->last.mem++) = ' ' ;
|
||||
ngx_memcpy(h->last, header[i].key.data, header[i].key.len);
|
||||
h->last += header[i].key.len;
|
||||
*(h->last++) = ':' ; *(h->last++) = ' ' ;
|
||||
|
||||
ngx_memcpy(h->last.mem, header[i].value.data, header[i].value.len);
|
||||
h->last.mem += header[i].value.len;
|
||||
*(h->last.mem++) = CR; *(h->last.mem++) = LF;
|
||||
ngx_memcpy(h->last, header[i].value.data, header[i].value.len);
|
||||
h->last += header[i].value.len;
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
/* STUB */
|
||||
*(h->last.mem) = '\0';
|
||||
ngx_log_debug(r->connection->log, "%s\n" _ h->pos.mem);
|
||||
*(h->last) = '\0';
|
||||
ngx_log_debug(r->connection->log, "%s\n" _ h->pos);
|
||||
/**/
|
||||
|
||||
/* end of HTTP header */
|
||||
*(h->last.mem++) = CR; *(h->last.mem++) = LF;
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
|
||||
if (r->header_only) {
|
||||
h->type |= NGX_HUNK_LAST;
|
||||
|
@ -26,7 +26,7 @@ static ngx_command_t ngx_http_output_filter_commands[] = {
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
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) \
|
||||
(((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) \
|
||||
&& (hunk->type & NGX_HUNK_FILE)) \
|
||||
|| ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \
|
||||
&& (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))))
|
||||
|| ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \
|
||||
&& (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))))
|
||||
|
||||
|
||||
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) {
|
||||
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
|
||||
@ -124,7 +124,12 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
|
||||
ngx_http_output_filter_module);
|
||||
|
||||
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) {
|
||||
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 */
|
||||
} else if (ctx->hunk->pos.mem < ctx->hunk->last.mem) {
|
||||
} else if (ctx->hunk->pos < ctx->hunk->last) {
|
||||
rc = next_filter(r, NULL);
|
||||
|
||||
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 */
|
||||
/* 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)
|
||||
@ -209,11 +214,20 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
|
||||
|
||||
/* NGX_OK */
|
||||
/* 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
|
||||
the chain ctx->incoming */
|
||||
} while (ctx->incoming->hunk->pos.mem < ctx->incoming->hunk->last.mem);
|
||||
/* repeat until we will have copied the whole first hunk from
|
||||
the chain ctx->incoming */
|
||||
|
||||
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 */
|
||||
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;
|
||||
|
||||
size = src->last.mem - src->pos.mem;
|
||||
if (size > (dst->end - dst->pos.mem)) {
|
||||
size = dst->end - dst->pos.mem;
|
||||
if (src->type & NGX_HUNK_IN_MEMORY) {
|
||||
size = src->last - src->pos;
|
||||
} else {
|
||||
size = src->file_last - src->file_pos;
|
||||
}
|
||||
|
||||
if (src->type & NGX_HUNK_FILE) {
|
||||
n = ngx_read_file(src->file, dst->pos.mem, size, src->pos.file);
|
||||
if (size > (dst->end - dst->pos)) {
|
||||
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) {
|
||||
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;
|
||||
dst->last.mem += n;
|
||||
src->file_pos += n;
|
||||
dst->last += n;
|
||||
|
||||
} else {
|
||||
ngx_memcpy(src->pos.mem, dst->pos.mem, size);
|
||||
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;
|
||||
if (src->type & NGX_HUNK_LAST && src->file_pos == src->file_last) {
|
||||
dst->type |= NGX_HUNK_LAST;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
@ -25,16 +25,11 @@ int ngx_read_http_request_line(ngx_http_request_t *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++;
|
||||
|
||||
/*
|
||||
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 */
|
||||
|
||||
switch (state) {
|
||||
@ -45,7 +40,7 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
|
||||
|
||||
switch (ch) {
|
||||
case 'G':
|
||||
if (p + 1 >= r->header_in->last.mem) {
|
||||
if (p + 1 >= r->header_in->last) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
@ -58,7 +53,7 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if (p + 2 >= r->header_in->last.mem) {
|
||||
if (p + 2 >= r->header_in->last) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
@ -71,7 +66,7 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
if (p + 2 >= r->header_in->last.mem) {
|
||||
if (p + 2 >= r->header_in->last) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
@ -228,9 +223,9 @@ printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
|
||||
|
||||
/* "TTP/" */
|
||||
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->header_in->pos.mem = p - 1;
|
||||
r->header_in->pos = p - 1;
|
||||
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 (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 = 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++;
|
||||
|
||||
/*
|
||||
printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
|
||||
state, p, h->last.mem, ch, p);
|
||||
*/
|
||||
|
||||
switch (state) {
|
||||
|
||||
/* 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) {
|
||||
r->state = sw_start;
|
||||
|
@ -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[] =
|
||||
"<html>" CRLF
|
||||
"<head><title>500 Internal Server Error</title></head>" CRLF
|
||||
@ -58,6 +66,16 @@ static ngx_str_t error_pages[] = {
|
||||
{ 0, NULL}, /* 402 */
|
||||
{ sizeof(error_403_page) - 1, error_403_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 }
|
||||
};
|
||||
@ -79,7 +97,7 @@ int ngx_http_special_response(ngx_http_request_t *r, int error)
|
||||
err = error - NGX_HTTP_BAD_REQUEST + 4;
|
||||
|
||||
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)
|
||||
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);
|
||||
|
||||
message->type = NGX_HUNK_MEMORY;
|
||||
message->pos.mem = error_pages[err].data;
|
||||
message->last.mem = error_pages[err].data + error_pages[err].len;
|
||||
message->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY;
|
||||
message->pos = error_pages[err].data;
|
||||
message->last = error_pages[err].data + error_pages[err].len;
|
||||
|
||||
if (ngx_http_output_filter(r, message) == 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);
|
||||
|
||||
tail->type = NGX_HUNK_MEMORY|NGX_HUNK_LAST;
|
||||
tail->pos.mem = error_tail;
|
||||
tail->last.mem = error_tail + sizeof(error_tail);
|
||||
tail->type = NGX_HUNK_MEMORY|NGX_HUNK_LAST|NGX_HUNK_IN_MEMORY;
|
||||
tail->pos = error_tail;
|
||||
tail->last = error_tail + sizeof(error_tail);
|
||||
|
||||
return ngx_http_output_filter(r, tail);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
ngx_http_write_filter_module);
|
||||
if (ctx == NULL) {
|
||||
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;
|
||||
@ -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 */
|
||||
for (ce = ctx->out; ce; ce = ce->next) {
|
||||
le = &ce->next;
|
||||
size += ce->hunk->last.file - ce->hunk->pos.file;
|
||||
|
||||
#if (NGX_DEBUG_WRITE_FILTER)
|
||||
ngx_log_debug(r->connection->log, "write filter: old chunk: %x "
|
||||
QX_FMT " " QD_FMT _
|
||||
ce->hunk->type _ ce->hunk->pos.file _
|
||||
ce->hunk->last.file - ce->hunk->pos.file);
|
||||
#endif
|
||||
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;
|
||||
@ -106,14 +104,12 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
ce->next = NULL;
|
||||
*le = ce;
|
||||
le = &ce->next;
|
||||
size += ce->hunk->last.file - ce->hunk->pos.file;
|
||||
|
||||
#if (NGX_DEBUG_WRITE_FILTER)
|
||||
ngx_log_debug(r->connection->log, "write filter: new hunk: %x "
|
||||
QX_FMT " " QD_FMT _
|
||||
ce->hunk->type _ ce->hunk->pos.file _
|
||||
ce->hunk->last.file - ce->hunk->pos.file);
|
||||
#endif
|
||||
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;
|
||||
|
@ -14,9 +14,11 @@ typedef int ngx_err_t;
|
||||
#define NGX_EAGAIN EWOULDBLOCK
|
||||
#define NGX_EINPROGRESS EINPROGRESS
|
||||
#define NGX_EADDRINUSE EADDRINUSE
|
||||
#define NGX_ECONNRESET ECONNRESET
|
||||
#define NGX_ETIMEDOUT ETIMEDOUT
|
||||
#define NGX_ECANCELED ECANCELED
|
||||
|
||||
|
||||
#define ngx_errno errno
|
||||
#define ngx_socket_errno errno
|
||||
#define ngx_set_socket_errno(err) errno = err
|
||||
|
@ -15,7 +15,7 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx_connection_t *c, ngx_chain_t *in)
|
||||
{
|
||||
int rc;
|
||||
char *prev;
|
||||
size_t hsize;
|
||||
size_t hsize, size;
|
||||
off_t sent;
|
||||
struct iovec *iov;
|
||||
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);
|
||||
|
||||
/* create the header iovec */
|
||||
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
if (ngx_hunk_in_memory_only(ce->hunk)) {
|
||||
prev = NULL;
|
||||
iov = NULL;
|
||||
|
||||
/* create the iovec and coalesce the neighbouring chain entries */
|
||||
while (ce && (ce->hunk->type & NGX_HUNK_IN_MEMORY))
|
||||
{
|
||||
if (prev == ce->hunk->pos.mem) {
|
||||
iov->iov_len += ce->hunk->last.mem - ce->hunk->pos.mem;
|
||||
prev = ce->hunk->last.mem;
|
||||
while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
|
||||
|
||||
if (prev == ce->hunk->pos) {
|
||||
iov->iov_len += ce->hunk->last - ce->hunk->pos;
|
||||
prev = ce->hunk->last;
|
||||
|
||||
} else {
|
||||
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
|
||||
iov->iov_base = ce->hunk->pos.mem;
|
||||
iov->iov_len = ce->hunk->last.mem - ce->hunk->pos.mem;
|
||||
prev = ce->hunk->last.mem;
|
||||
iov->iov_base = ce->hunk->pos;
|
||||
iov->iov_len = ce->hunk->last - ce->hunk->pos;
|
||||
prev = ce->hunk->last;
|
||||
}
|
||||
|
||||
#if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG)
|
||||
hsize += ce->hunk->last.mem - ce->hunk->pos.mem;
|
||||
hsize += ce->hunk->last - ce->hunk->pos;
|
||||
#endif
|
||||
ce = ce->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: coalesce the neighbouring shadow file hunks */
|
||||
/* TODO: coalesce the neighbouring file hunks */
|
||||
if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
|
||||
file = ce->hunk;
|
||||
ce = ce->next;
|
||||
}
|
||||
|
||||
/* create the trailer iovec */
|
||||
if (ce && ce->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
if (ce && ngx_hunk_in_memory_only(ce->hunk)) {
|
||||
prev = NULL;
|
||||
iov = NULL;
|
||||
|
||||
/* 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) {
|
||||
iov->iov_len += ce->hunk->last.mem - ce->hunk->pos.mem;
|
||||
prev = ce->hunk->last.mem;
|
||||
if (prev == ce->hunk->pos) {
|
||||
iov->iov_len += ce->hunk->last - ce->hunk->pos;
|
||||
prev = ce->hunk->last;
|
||||
|
||||
} else {
|
||||
ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR);
|
||||
iov->iov_base = ce->hunk->pos.mem;
|
||||
iov->iov_len = ce->hunk->last.mem - ce->hunk->pos.mem;
|
||||
prev = ce->hunk->last.mem;
|
||||
iov->iov_base = ce->hunk->pos;
|
||||
iov->iov_len = ce->hunk->last - ce->hunk->pos;
|
||||
prev = ce->hunk->last;
|
||||
}
|
||||
|
||||
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.trl_cnt = trailer.nelts;
|
||||
|
||||
rc = sendfile(file->file->fd, c->fd, file->pos.file,
|
||||
(size_t) (file->last.file - file->pos.file) + hsize,
|
||||
rc = sendfile(file->file->fd, c->fd, file->file_pos,
|
||||
(size_t) (file->file_last - file->file_pos) + hsize,
|
||||
&hdtr, &sent, 0);
|
||||
|
||||
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)
|
||||
ngx_log_debug(c->log, "sendfile: %d, @%qd %qd:%d" _
|
||||
rc _ file->pos.file _ *sent _
|
||||
(size_t) (file->last.file - file->pos.file) + hsize);
|
||||
rc _ file->file_pos _ sent _
|
||||
(size_t) (file->file_last - file->file_pos) + hsize);
|
||||
#endif
|
||||
|
||||
} 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) {
|
||||
|
||||
#if (NGX_DEBUG_WRITE_CHAIN)
|
||||
ngx_log_debug(c->log, "write chain: %x %qx %qd" _
|
||||
ce->hunk->type _
|
||||
ce->hunk->pos.file _
|
||||
ce->hunk->last.file - ce->hunk->pos.file);
|
||||
#endif
|
||||
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 (sent >= ce->hunk->last.file - ce->hunk->pos.file) {
|
||||
sent -= ce->hunk->last.file - ce->hunk->pos.file;
|
||||
ce->hunk->pos.file = ce->hunk->last.file;
|
||||
if (sent >= size) {
|
||||
sent -= size;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ce->hunk->pos.file += sent;
|
||||
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
ce->hunk->pos += sent;
|
||||
}
|
||||
|
||||
#if (NGX_DEBUG_WRITE_CHAIN)
|
||||
ngx_log_debug(c->log, "write chain rest: %qx %qd" _
|
||||
ce->hunk->pos.file _
|
||||
ce->hunk->last.file - ce->hunk->pos.file);
|
||||
#endif
|
||||
if (ce->hunk->type & NGX_HUNK_FILE) {
|
||||
ce->hunk->file_pos += sent;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ typedef DWORD ngx_err_t;
|
||||
#define NGX_EAGAIN WSAEWOULDBLOCK
|
||||
#define NGX_EINPROGRESS WSAEINPROGRESS
|
||||
#define NGX_EADDRINUSE WSAEADDRINUSE
|
||||
#define NGX_ECONNRESET ECONNRESET
|
||||
#define NGX_ETIMEDOUT WSAETIMEDOUT
|
||||
|
||||
int ngx_strerror_r(ngx_err_t err, char *errstr, size_t size);
|
||||
|
Loading…
Reference in New Issue
Block a user