nginx-0.0.1-2003-06-02-19:24:30 import

This commit is contained in:
Igor Sysoev 2003-06-02 15:24:30 +00:00
parent aa3436c04c
commit 7578ec9df4
37 changed files with 1192 additions and 291 deletions

View File

@ -32,7 +32,7 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
/* open configuration file */ /* open configuration file */
fd = ngx_open_file(filename->data, NGX_FILE_RDONLY); fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
if (fd == NGX_INVALID_FILE) { if (fd == NGX_INVALID_FILE) {
ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
ngx_open_file_n " %s failed", filename->data); ngx_open_file_n " %s failed", filename->data);
@ -142,7 +142,7 @@ ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data);
if (cmd->type & argument_number[cf->args->nelts - 1]) { if (cmd->type & argument_number[cf->args->nelts - 1]) {
valid = 1; valid = 1;
} else if (cmd->type & NGX_CONF_ANY1) { } else if (cmd->type & NGX_CONF_1MORE) {
if (cf->args->nelts != 1) { if (cf->args->nelts != 1) {
valid = 1; valid = 1;

View File

@ -24,7 +24,7 @@
#define NGX_CONF_TAKE2 0x00000004 #define NGX_CONF_TAKE2 0x00000004
#define NGX_CONF_ARGS_NUMBER 0x0000ffff #define NGX_CONF_ARGS_NUMBER 0x0000ffff
#define NGX_CONF_ANY 0x00010000 #define NGX_CONF_ANY 0x00010000
#define NGX_CONF_ANY1 0x00020000 #define NGX_CONF_1MORE 0x00020000
#define NGX_CONF_BLOCK 0x00040000 #define NGX_CONF_BLOCK 0x00040000
#define NGX_CONF_FLAG 0x00080000 #define NGX_CONF_FLAG 0x00080000

View File

@ -61,6 +61,7 @@ struct ngx_connection_s {
unsigned pipeline:1; unsigned pipeline:1;
unsigned unexpected_eof:1; unsigned unexpected_eof:1;
unsigned tcp_nopush:1;
}; };

View File

@ -18,6 +18,7 @@ typedef struct ngx_event_s ngx_event_t;
#include <ngx_array.h> #include <ngx_array.h>
#include <ngx_string.h> #include <ngx_string.h>
#include <ngx_file.h> #include <ngx_file.h>
#include <ngx_inet.h>
#include <ngx_conf_file.h> #include <ngx_conf_file.h>
#include <ngx_os_init.h> #include <ngx_os_init.h>
#include <ngx_connection.h> #include <ngx_connection.h>

View File

@ -71,11 +71,9 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size,
int before, int after); int before, int after);
#define ngx_alloc_hunk(pool) ngx_palloc(pool, sizeof(ngx_hunk_t)) #define ngx_alloc_hunk(pool) ngx_palloc(pool, sizeof(ngx_hunk_t))
#define ngx_alloc_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t)) #define ngx_calloc_hunk(pool) ngx_pcalloc(pool, sizeof(ngx_hunk_t))
/* STUB */ #define ngx_alloc_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
#define ngx_create_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
/**/
#define ngx_add_hunk_to_chain(chain, h, pool, error) \ #define ngx_add_hunk_to_chain(chain, h, pool, error) \
do { \ do { \

View File

@ -29,10 +29,16 @@ extern ngx_module_t ngx_http_write_filter_module;
extern ngx_module_t ngx_http_output_filter_module; extern ngx_module_t ngx_http_output_filter_module;
extern ngx_module_t ngx_http_header_filter_module; extern ngx_module_t ngx_http_header_filter_module;
extern ngx_module_t ngx_http_chunked_filter_module;
extern ngx_module_t ngx_http_range_filter_module;
extern ngx_module_t ngx_http_charset_filter_module;
extern ngx_module_t ngx_http_index_module; extern ngx_module_t ngx_http_index_module;
extern ngx_module_t ngx_http_static_module; extern ngx_module_t ngx_http_static_module;
extern ngx_module_t ngx_http_proxy_module; extern ngx_module_t ngx_http_proxy_module;
extern ngx_module_t ngx_http_log_module;
ngx_module_t *ngx_modules[] = { ngx_module_t *ngx_modules[] = {
@ -64,13 +70,17 @@ ngx_module_t *ngx_modules[] = {
&ngx_http_output_filter_module, &ngx_http_output_filter_module,
&ngx_http_header_filter_module, &ngx_http_header_filter_module,
&ngx_http_chunked_filter_module,
/* &ngx_http_gzip_filter_module, */ /* &ngx_http_gzip_filter_module, */
/* &ngx_http_range_filter_module, */ &ngx_http_range_filter_module,
/* &ngx_http_ssi_filter_module, */ /* &ngx_http_ssi_filter_module, */
&ngx_http_charset_filter_module,
&ngx_http_index_module, &ngx_http_index_module,
/* &ngx_http_static_module, */ /* &ngx_http_static_module, */
/* &ngx_http_proxy_module, */ /* &ngx_http_proxy_module, */
&ngx_http_log_module,
NULL NULL
}; };

View File

@ -5,17 +5,6 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#if 0
#include <ngx_types.h>
#include <ngx_time.h>
#include <ngx_socket.h>
#include <ngx_log.h>
#include <ngx_alloc.h>
#include <ngx_array.h>
#include <ngx_conf_file.h>
#endif
#define NGX_INVALID_INDEX 0x80000000 #define NGX_INVALID_INDEX 0x80000000
@ -310,10 +299,6 @@ extern int ngx_event_flags;
#endif #endif
#if !(HAVE_EPOLL)
#define ngx_edge_add_event(ev) NGX_ERROR
#endif
#define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */ #define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */

View File

@ -1,10 +1,8 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <nginx.h>
#include <ngx_event.h> #include <ngx_event.h>
#include <nginx.h>
void ngx_event_accept(ngx_event_t *ev) void ngx_event_accept(ngx_event_t *ev)
@ -30,9 +28,11 @@ void ngx_event_accept(ngx_event_t *ev)
do { do {
/* Create the pool before accept() to avoid copy the sockaddr. /*
Although accept() can fail it's uncommon case * Create the pool before accept() to avoid copy the sockaddr.
and the pool can be got from the free pool list */ * Although accept() can fail it's uncommon case
* and the pool can be got from the free pool list
*/
pool = ngx_create_pool(ls->pool_size, ev->log); pool = ngx_create_pool(ls->pool_size, ev->log);
if (pool == NULL) { if (pool == NULL) {
@ -168,7 +168,7 @@ void ngx_event_accept(ngx_event_t *ev)
ngx_memcpy(c->log, ev->log, sizeof(ngx_log_t)); ngx_memcpy(c->log, ev->log, sizeof(ngx_log_t));
rev->log = wev->log = c->log; rev->log = wev->log = c->log;
/* STUB: x86: MT: lock xadd, MP: lock xadd, shared */ /* TODO: x86: MT: lock xadd, MP: lock xadd, shared */
c->number = ngx_connection_counter++; c->number = ngx_connection_counter++;
ngx_log_debug(ev->log, "accept: %d, %d" _ s _ c->number); ngx_log_debug(ev->log, "accept: %d, %d" _ s _ c->number);

View File

@ -0,0 +1,124 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
typedef struct {
ngx_str_t default_charset;
} ngx_http_charset_loc_conf_t;
static void *ngx_http_charset_create_loc_conf(ngx_pool_t *pool);
static char *ngx_http_charset_merge_loc_conf(ngx_pool_t *pool,
void *parent, void *child);
static int ngx_http_charset_filter_init(ngx_pool_t *pool);
static ngx_command_t ngx_http_charset_filter_commands[] = {
{ngx_string("default_charset"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_charset_loc_conf_t, default_charset),
NULL},
ngx_null_command
};
static ngx_http_module_t ngx_http_charset_filter_module_ctx = {
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_charset_create_loc_conf, /* create location configuration */
ngx_http_charset_merge_loc_conf /* merge location configuration */
};
ngx_module_t ngx_http_charset_filter_module = {
NGX_MODULE,
&ngx_http_charset_filter_module_ctx, /* module context */
ngx_http_charset_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
ngx_http_charset_filter_init /* init module */
};
static int (*next_header_filter) (ngx_http_request_t *r);
#if 0
static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
#endif
static int ngx_http_charset_header_filter(ngx_http_request_t *r)
{
ngx_http_charset_loc_conf_t *lcf;
lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
if (r->headers_out.status == NGX_HTTP_MOVED_PERMANENTLY
&& r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
{
/* do not set charset for the redirect because NN 4.x uses this
charset instead of the next page charset */
r->headers_out.charset.len = 0;
} else if (r->headers_out.charset.len == 0) {
r->headers_out.charset = lcf->default_charset;
}
return next_header_filter(r);
}
#if 0
static int ngx_http_charset_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
ngx_log_debug(r->connection->log, "CHARSET BODY");
return next_body_filter(r, in);
}
#endif
static int ngx_http_charset_filter_init(ngx_pool_t *pool)
{
next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_charset_header_filter;
#if 0
next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_charset_body_filter;
#endif
return NGX_OK;
}
static void *ngx_http_charset_create_loc_conf(ngx_pool_t *pool)
{
ngx_http_charset_loc_conf_t *lcf;
ngx_test_null(lcf,
ngx_pcalloc(pool, sizeof(ngx_http_charset_loc_conf_t)),
NGX_CONF_ERROR);
return lcf;
}
static char *ngx_http_charset_merge_loc_conf(ngx_pool_t *pool,
void *parent, void *child)
{
ngx_http_charset_loc_conf_t *prev = parent;
ngx_http_charset_loc_conf_t *conf = child;
ngx_conf_merge_str_value(conf->default_charset,
prev->default_charset, "koi8-r");
return NGX_CONF_OK;
}

View File

@ -0,0 +1,129 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
static int ngx_http_chunked_filter_init(ngx_pool_t *pool);
static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL, /* merge location configuration */
};
ngx_module_t ngx_http_chunked_filter_module = {
NGX_MODULE,
&ngx_http_chunked_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
ngx_http_chunked_filter_init /* init module */
};
static int (*next_header_filter) (ngx_http_request_t *r);
static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
static int ngx_http_chunked_header_filter(ngx_http_request_t *r)
{
if (r->headers_out.content_length == -1) {
if (r->http_version < NGX_HTTP_VERSION_11) {
r->keepalive = 0;
} else {
r->chunked = 1;
}
}
return next_header_filter(r);
}
static int ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
char *chunk;
size_t size, len;
ngx_hunk_t *h;
ngx_chain_t *out, *ce, *te, **le;
if (in == NULL || !r->chunked) {
return next_body_filter(r, in);
}
ngx_test_null(out, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
le = &out->next;
size = 0;
ce = in;
for ( ;; ) {
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
size += ce->hunk->last - ce->hunk->pos;
} else {
size += (size_t) (ce->hunk->file_last - ce->hunk->file_pos);
}
ngx_test_null(te, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
te->hunk = ce->hunk;
*le = te;
le = &te->next;
if (ce->next == NULL) {
break;
}
ce = ce->next;
}
ngx_test_null(chunk, ngx_palloc(r->pool, 11), NGX_ERROR);
len = ngx_snprintf(chunk, 11, "%x" CRLF, size);
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
h->pos = chunk;
h->last = chunk + len;
out->hunk = h;
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
if (ce->hunk->type & NGX_HUNK_LAST) {
ce->hunk->type &= ~NGX_HUNK_LAST;
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY|NGX_HUNK_LAST;
h->pos = CRLF "0" CRLF CRLF;
h->last = h->pos + 7;
} else {
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY;
h->pos = CRLF;
h->last = h->pos + 2;
}
ngx_test_null(te, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
te->hunk = h;
te->next = NULL;
*le = te;
return next_body_filter(r, out);
}
static int ngx_http_chunked_filter_init(ngx_pool_t *pool)
{
next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_chunked_header_filter;
next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_chunked_body_filter;
return NGX_OK;
}

View File

@ -1,5 +1,16 @@
#include <ngx_http_index_handler.h> #include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
typedef struct {
ngx_array_t indices;
size_t max_index_len;
} ngx_http_index_conf_t;
#define NGX_HTTP_DEFAULT_INDEX "index.html"
static int ngx_http_index_test_dir(ngx_http_request_t *r); static int ngx_http_index_test_dir(ngx_http_request_t *r);
@ -14,7 +25,7 @@ static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
static ngx_command_t ngx_http_index_commands[] = { static ngx_command_t ngx_http_index_commands[] = {
{ngx_string("index"), {ngx_string("index"),
NGX_HTTP_LOC_CONF|NGX_CONF_ANY1, NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
ngx_http_index_set_index, ngx_http_index_set_index,
NGX_HTTP_LOC_CONF_OFFSET, NGX_HTTP_LOC_CONF_OFFSET,
0, 0,
@ -46,8 +57,8 @@ ngx_module_t ngx_http_index_module = {
/* /*
Try to open first index file before the test of the directory existence Try to open the first index file before the directory existence test
because the valid requests should be many more then invalid ones. because the valid requests should be many more than invalid ones.
If open() failed then stat() should be more quickly because some data If open() failed then stat() should be more quickly because some data
is already cached in the kernel. is already cached in the kernel.
Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR). Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
@ -57,7 +68,7 @@ ngx_module_t ngx_http_index_module = {
int ngx_http_index_handler(ngx_http_request_t *r) int ngx_http_index_handler(ngx_http_request_t *r)
{ {
int i, rc, test_dir; int i, rc, test_dir, path_not_found;
char *name, *file; char *name, *file;
ngx_str_t redirect, *index; ngx_str_t redirect, *index;
ngx_err_t err; ngx_err_t err;
@ -80,6 +91,7 @@ int ngx_http_index_handler(ngx_http_request_t *r)
r->path.len = file - r->path.data; r->path.len = file - r->path.data;
test_dir = 1; test_dir = 1;
path_not_found = 1;
index = icf->indices.elts; index = icf->indices.elts;
for (i = 0; i < icf->indices.nelts; i++) { for (i = 0; i < icf->indices.nelts; i++) {
@ -92,7 +104,7 @@ int ngx_http_index_handler(ngx_http_request_t *r)
name = index[i].data; name = index[i].data;
} }
fd = ngx_open_file(name, NGX_FILE_RDONLY); fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
if (fd == NGX_INVALID_FILE) { if (fd == NGX_INVALID_FILE) {
err = ngx_errno; err = ngx_errno;
@ -100,7 +112,7 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
"DEBUG: " ngx_open_file_n " %s failed", name); "DEBUG: " ngx_open_file_n " %s failed", name);
if (err == NGX_ENOTDIR) { if (err == NGX_ENOTDIR) {
r->path_not_found = 1; path_not_found = 1;
} else if (err == NGX_EACCES) { } else if (err == NGX_EACCES) {
r->path_err = err; r->path_err = err;
@ -108,7 +120,7 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
} }
if (test_dir) { if (test_dir) {
if (r->path_not_found) { if (path_not_found) {
r->path_err = err; r->path_err = err;
return NGX_HTTP_NOT_FOUND; return NGX_HTTP_NOT_FOUND;
} }

View File

@ -1,22 +0,0 @@
#ifndef _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_
#define _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#define NGX_HTTP_DEFAULT_INDEX "index.html"
typedef struct {
ngx_array_t indices;
size_t max_index_len;
} ngx_http_index_conf_t;
extern ngx_module_t ngx_http_index_module;
#endif /* _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_ */

View File

@ -1,38 +1,82 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_string.h>
#include <ngx_alloc.h>
#include <ngx_time.h>
#include <ngx_http.h> #include <ngx_http.h>
#include <ngx_http_config.h>
ngx_http_module_t ngx_http_log_module; typedef struct {
ngx_file_t file;
} ngx_http_log_conf_t;
static void *ngx_http_log_create_conf(ngx_pool_t *pool);
static char *ngx_http_log_merge_conf(ngx_pool_t *p, void *parent, void *child);
static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_command_t ngx_http_log_commands[] = {
{ngx_string("access_log"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_log_set_log,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL},
ngx_null_command
};
ngx_http_module_t ngx_http_log_module_ctx = {
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_log_create_conf, /* create location configration */
ngx_http_log_merge_conf /* merge location configration */
};
ngx_module_t ngx_http_log_module = {
NGX_MODULE,
&ngx_http_log_module_ctx, /* module context */
ngx_http_log_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init module */
};
static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
int ngx_http_log_handler(ngx_http_request_t *r) int ngx_http_log_handler(ngx_http_request_t *r)
{ {
size_t len; char *line, *p;
char *line, *p; size_t len;
ngx_tm_t tm; ngx_tm_t tm;
ngx_http_log_conf_t *lcf;
ngx_log_debug(r->connection->log, "log handler"); ngx_log_debug(r->connection->log, "log handler");
/* 10:%con, 1:%pipe, 22:%date, 2:"%r", 3:%status, 20:%bytes, lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
6*" ", 2/1: "\r\n" */
/* 10:%con, 1:%pipe, 22:%date, 2:"%r", 3:%status, 20:%bytes, 2:%user-agent,
7*" ", 2/1: "\r\n" */
#if (WIN32) #if (WIN32)
len = 10 + 1 + 22 + 2 + 3 + 20 + 6 + 2; len = 10 + 1 + 22 + 2 + 3 + 20 + 2 + 7 + 2;
#else #else
len = 10 + 1 + 22 + 2 + 3 + 20 + 6 + 1; len = 10 + 1 + 22 + 2 + 3 + 20 + 2 + 7 + 1;
#endif #endif
len += r->connection->addr_text.len; len += r->connection->addr_text.len;
len += r->request_line.len; len += r->request_line.len;
if (r->headers_in.user_agent) {
len += r->headers_in.user_agent->value.len;
}
ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR); ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR);
p = line; p = line;
@ -79,13 +123,80 @@ int ngx_http_log_handler(ngx_http_request_t *r)
p += ngx_snprintf(p, 21, OFF_FMT, r->connection->sent); p += ngx_snprintf(p, 21, OFF_FMT, r->connection->sent);
*p++ = ' ';
*p++ = '"';
if (r->headers_in.user_agent) {
ngx_memcpy(p, r->headers_in.user_agent->value.data,
r->headers_in.user_agent->value.len);
p += r->headers_in.user_agent->value.len;
}
*p++ = '"';
#if (WIN32) #if (WIN32)
*p++ = CR; *p++ = LF; *p++ = CR; *p++ = LF;
#else #else
*p++ = LF; *p++ = LF;
#endif #endif
write(1, line, p - line); write(lcf->file.fd, line, p - line);
return NGX_OK; return NGX_OK;
} }
static void *ngx_http_log_create_conf(ngx_pool_t *pool)
{
ngx_http_log_conf_t *conf;
ngx_test_null(conf, ngx_pcalloc(pool, sizeof(ngx_http_log_conf_t)),
NGX_CONF_ERROR);
return conf;
}
static char *ngx_http_log_merge_conf(ngx_pool_t *p, void *parent, void *child)
{
ngx_http_log_conf_t *prev = parent;
ngx_http_log_conf_t *conf = child;
/* STUB */
*conf = *prev;
return NGX_CONF_OK;
}
static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
ngx_http_log_conf_t *lcf = conf;
int len;
ngx_err_t err;
ngx_str_t *value;
value = cf->args->elts;
lcf->file.name.len = value[1].len;
lcf->file.name.data = value[1].data;
lcf->file.fd = ngx_open_file(lcf->file.name.data,
NGX_FILE_RDWR,
NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
if (lcf->file.fd == NGX_INVALID_FILE) {
err = ngx_errno;
len = ngx_snprintf(ngx_conf_errstr, sizeof(ngx_conf_errstr) - 1,
ngx_open_file_n " \"%s\" failed (%d: ",
lcf->file.name.data, err);
len += ngx_strerror_r(err, ngx_conf_errstr + len,
sizeof(ngx_conf_errstr) - len - 1);
ngx_conf_errstr[len++] = ')';
ngx_conf_errstr[len++] = '\0';
return ngx_conf_errstr;
}
return NGX_CONF_OK;
}

View File

@ -0,0 +1,41 @@
#ifndef _NGX_HTTP_LOG_HANDLER_H_INCLUDED_
#define _NGX_HTTP_LOG_HANDLER_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
typedef struct {
int dummy;
} ngx_http_log_conf_t;
typedef enum {
NGX_HTTP_LOG_HANDLER = 0,
#if 0
/* the ngx_str_t field of the request */
NGX_HTTP_LOG_REQUEST_STR_FIELD,
/* the ngx_str_t field of the r->headers_in */
NGX_HTTP_LOG_REQUEST_HEADER_IN_FIELD,
/* the ngx_str_t field of the r->headers_out */
NGX_HTTP_LOG_REQUEST_HEADER_OUT_FIELD,
#endif
} ngx_http_log_code_e;
typedef struct {
int type;
int size;
char *(*handler) (ngx_http_request_t *r, char *p);
int offset;
} ngx_http_log_code_t;
#endif /* _NGX_HTTP_LOG_HANDLER_H_INCLUDED_ */

View File

@ -0,0 +1,362 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
typedef struct {
ngx_str_t boundary_header;
} ngx_http_range_filter_ctx_t;
static int ngx_http_range_filter_init(ngx_pool_t *pool);
static ngx_http_module_t ngx_http_range_filter_module_ctx = {
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL, /* merge location configuration */
};
ngx_module_t ngx_http_range_filter_module = {
NGX_MODULE,
&ngx_http_range_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
ngx_http_range_filter_init /* init module */
};
static int (*next_header_filter) (ngx_http_request_t *r);
static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
static int ngx_http_range_header_filter(ngx_http_request_t *r)
{
int rc, boundary, len, i;
char *p;
off_t start, end;
ngx_http_range_t *range;
ngx_http_range_filter_ctx_t *ctx;
if (r->main
|| r->http_version < NGX_HTTP_VERSION_10
|| r->headers_out.status != NGX_HTTP_OK
|| r->headers_out.content_length == -1
/* STUB: we currently support ranges for file hunks only */
|| r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY
|| r->headers_in.range == NULL
|| r->headers_in.range->value.len < 7
|| ngx_strncasecmp(r->headers_in.range->value.data, "bytes=", 6) != 0)
{
return next_header_filter(r);
}
ngx_init_array(r->headers_out.ranges, r->pool, 5, sizeof(ngx_http_range_t),
NGX_ERROR);
rc = 0;
p = r->headers_in.range->value.data + 6;
for ( ;; ) {
start = end = 0;
while (*p == ' ') { p++; }
if (*p < '0' || *p > '9') {
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
break;
}
while (*p >= '0' && *p <= '9') {
start = start * 10 + *p++ - '0';
}
while (*p == ' ') { p++; }
if (*p++ != '-') {
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
break;
}
if (start >= r->headers_out.content_length) {
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
break;
}
while (*p == ' ') { p++; }
if (*p == ',' || *p == '\0') {
ngx_test_null(range, ngx_push_array(&r->headers_out.ranges),
NGX_ERROR);
range->start = start;
range->end = r->headers_out.content_length;
if (*p++ == ',') {
continue;
}
break;
}
if (*p < '0' || *p > '9') {
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
break;
}
while (*p >= '0' && *p <= '9') {
end = end * 10 + *p++ - '0';
}
while (*p == ' ') { p++; }
if (*p != ',' && *p != '\0') {
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
break;
}
if (end >= r->headers_out.content_length || start >= end) {
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
break;
}
ngx_test_null(range, ngx_push_array(&r->headers_out.ranges), NGX_ERROR);
range->start = start;
range->end = end + 1;
if (*p++ == ',') {
continue;
}
break;
}
if (rc) {
r->headers_out.status = rc;
r->headers_out.ranges.nelts = 0;
ngx_test_null(r->headers_out.content_range,
ngx_push_table(r->headers_out.headers),
NGX_ERROR);
ngx_test_null(r->headers_out.content_range->value.data,
ngx_palloc(r->pool, 8 + 20 + 1),
NGX_ERROR);
r->headers_out.content_range->value.len =
ngx_snprintf(r->headers_out.content_range->value.data,
8 + 20 + 1, "bytes */" OFF_FMT,
r->headers_out.content_length);
r->headers_out.content_length = -1;
return rc;
} else {
r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
if (r->headers_out.ranges.nelts == 1) {
ngx_test_null(r->headers_out.content_range,
ngx_push_table(r->headers_out.headers),
NGX_ERROR);
ngx_test_null(r->headers_out.content_range->value.data,
ngx_palloc(r->pool, 6 + 20 + 1 + 20 + 1 + 20 + 1),
NGX_ERROR);
r->headers_out.content_range->value.len =
ngx_snprintf(r->headers_out.content_range->value.data,
6 + 20 + 1 + 20 + 1 + 20 + 1,
"bytes " OFF_FMT "-" OFF_FMT "/" OFF_FMT,
range->start, range->end - 1,
r->headers_out.content_length);
r->headers_out.content_length = range->end - range->start;
} else {
#if 0
/* TODO: what if no content_type ?? */
ngx_test_null(r->headers_out.content_type,
ngx_push_table(r->headers_out.headers),
NGX_ERROR);
#endif
ngx_http_create_ctx(r, ctx, ngx_http_range_filter_module,
sizeof(ngx_http_range_filter_ctx_t), NGX_ERROR);
len = 4 + 10 + 2 + 14 + r->headers_out.content_type->value.len
+ 2 + 21 + 1;
if (r->headers_out.charset.len) {
len += 10 + r->headers_out.charset.len;
}
ngx_test_null(ctx->boundary_header.data, ngx_palloc(r->pool, len),
NGX_ERROR);
boundary = ngx_next_temp_number(0);
if (r->headers_out.charset.len) {
ctx->boundary_header.len =
ngx_snprintf(ctx->boundary_header.data, len,
CRLF "--%010u" CRLF
"Content-Type: %s; charset=%s" CRLF
"Content-Range: bytes ",
boundary,
r->headers_out.content_type->value.data,
r->headers_out.charset.data);
r->headers_out.charset.len = 0;
} else {
ctx->boundary_header.len =
ngx_snprintf(ctx->boundary_header.data, len,
CRLF "--%010u" CRLF
"Content-Type: %s" CRLF
"Content-Range: bytes ",
boundary,
r->headers_out.content_type->value.data);
}
ngx_test_null(r->headers_out.content_type->value.data,
ngx_palloc(r->pool, 31 + 10 + 1),
NGX_ERROR);
r->headers_out.content_type->value.len =
ngx_snprintf(r->headers_out.content_type->value.data,
31 + 10 + 1,
"multipart/byteranges; boundary=%010u",
boundary);
/* the last "CRLF--BOUNDARY--CRLF" */
len = 4 + 10 + 4;
range = r->headers_out.ranges.elts;
for (i = 0; i < r->headers_out.ranges.nelts; i++) {
ngx_test_null(range[i].content_range.data,
ngx_palloc(r->pool, 20 + 1 + 20 + 1 + 20 + 5),
NGX_ERROR);
range[i].content_range.len =
ngx_snprintf(range[i].content_range.data,
20 + 1 + 20 + 1 + 20 + 5,
OFF_FMT "-" OFF_FMT "/" OFF_FMT CRLF CRLF,
range[i].start, range[i].end - 1,
r->headers_out.content_length);
len += ctx->boundary_header.len + range[i].content_range.len
+ range[i].end - range[i].start;
}
r->headers_out.content_length = len;
}
}
return next_header_filter(r);
}
static int ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
int i;
ngx_hunk_t *h;
ngx_chain_t *out, *hce, *rce, *dce, **le;
ngx_http_range_t *range;
ngx_http_range_filter_ctx_t *ctx;
if (r->headers_out.ranges.nelts == 0) {
return next_body_filter(r, in);
}
/* the optimized version for the static files only
that are passed in the single file hunk */
if (in
&& in->hunk->type & NGX_HUNK_FILE
&& in->hunk->type & NGX_HUNK_LAST)
{
if (r->headers_out.ranges.nelts == 1) {
range = r->headers_out.ranges.elts;
in->hunk->file_pos = range->start;
in->hunk->file_last = range->end;
return next_body_filter(r, in);
}
ctx = ngx_http_get_module_ctx(r, ngx_http_range_filter_module);
le = &out;
range = r->headers_out.ranges.elts;
for (i = 0; i < r->headers_out.ranges.nelts; i++) {
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY;
h->pos = ctx->boundary_header.data;
h->last = ctx->boundary_header.data + ctx->boundary_header.len;
ngx_test_null(hce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
hce->hunk = h;
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
h->pos = range[i].content_range.data;
h->last = range[i].content_range.data + range[i].content_range.len;
ngx_test_null(rce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
rce->hunk = h;
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_FILE;
h->file_pos = range[i].start;
h->file_last = range[i].end;
h->file = in->hunk->file;
ngx_test_null(dce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
dce->hunk = h;
dce->next = NULL;
*le = hce;
hce->next = rce;
rce->next = dce;
le = &dce->next;
}
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP|NGX_HUNK_LAST;
ngx_test_null(h->pos, ngx_palloc(r->pool, 4 + 10 + 4), NGX_ERROR);
h->last = ngx_cpymem(h->pos, ctx->boundary_header.data, 4 + 10);
*h->last++ = '-'; *h->last++ = '-';
*h->last++ = CR; *h->last++ = LF;
ngx_test_null(hce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
hce->hunk = h;
hce->next = NULL;
*le = hce;
return next_body_filter(r, out);
}
/* TODO: several incoming hunks of proxied responses
and memory hunks on platforms that have no sendfile() */
return next_body_filter(r, in);
}
static int ngx_http_range_filter_init(ngx_pool_t *pool)
{
next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_range_header_filter;
next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_range_body_filter;
return NGX_OK;
}

View File

@ -2,10 +2,6 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.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>
int ngx_http_static_handler(ngx_http_request_t *r) int ngx_http_static_handler(ngx_http_request_t *r)
@ -32,7 +28,8 @@ int ngx_http_static_handler(ngx_http_request_t *r)
ctx->action = "sending response"; ctx->action = "sending response";
if (r->file.fd == NGX_INVALID_FILE) { if (r->file.fd == NGX_INVALID_FILE) {
r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY); r->file.fd = ngx_open_file(r->file.name.data,
NGX_FILE_RDONLY, NGX_FILE_OPEN);
if (r->file.fd == NGX_INVALID_FILE) { if (r->file.fd == NGX_INVALID_FILE) {
err = ngx_errno; err = ngx_errno;
@ -129,6 +126,10 @@ int ngx_http_static_handler(ngx_http_request_t *r)
rc = ngx_http_send_header(r); rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK) {
ngx_http_finalize_request(r, rc);
return NGX_OK;
}
if (r->header_only) { if (r->header_only) {
if (rc == NGX_AGAIN) { if (rc == NGX_AGAIN) {

View File

@ -14,6 +14,7 @@
#include <ngx_http_request.h> #include <ngx_http_request.h>
#include <ngx_http_config.h> #include <ngx_http_config.h>
#include <ngx_http_filter.h>
#include <ngx_http_core_module.h> #include <ngx_http_core_module.h>

View File

@ -1,5 +1,12 @@
/*
* small file in malloc()ed memory, mmap()ed file, file descriptor only,
* file access time only (to estimate can pages pages still be in memory),
* translated URI (ngx_http_index_hanlder),
* compiled script (ngx_http_ssi_filter).
*/
#define NGX_HTTP_CACHE_ENTRY_DELETED 0x00000001 #define NGX_HTTP_CACHE_ENTRY_DELETED 0x00000001
#define NGX_HTTP_CACHE_ENTRY_MMAPED 0x00000002 #define NGX_HTTP_CACHE_ENTRY_MMAPED 0x00000002
@ -7,6 +14,9 @@
/* "/" -> "/index.html" in ngx_http_index_handler */ /* "/" -> "/index.html" in ngx_http_index_handler */
#define NGX_HTTP_CACHE_ENTRY_URI 0x00000004 #define NGX_HTTP_CACHE_ENTRY_URI 0x00000004
/* complied script */
#define NGX_HTTP_CACHE_ENTRY_SCRIPT 0x00000008
#define NGX_HTTP_CACHE_FILTER_FLAGS 0xFFFF0000 #define NGX_HTTP_CACHE_FILTER_FLAGS 0xFFFF0000
@ -42,7 +52,7 @@ int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash,
int hi; int hi;
ngx_http_cache_hash_entry_t *entry; ngx_http_cache_hash_entry_t *entry;
h->crc = ngx_crc32(uri->data, uri->len); h->crc = ngx_crc(uri->data, uri->len);
hi = h->crc % cache_hash->size; hi = h->crc % cache_hash->size;
entry = cache_hash[hi].elts; entry = cache_hash[hi].elts;
@ -61,3 +71,23 @@ int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash,
return NGX_ERROR; return NGX_ERROR;
} }
/* 32-bit crc16 */
int ngx_crc(char *data, size_t len)
{
u_int32_t sum;
for (sum = 0; len; len--) {
/*
* gcc 2.95.2 x86 compiles that operator into the single rol opcode.
* msvc 6.0sp2 compiles it into four opcodes.
*/
sum = sum >> 1 | sum << 31;
sum += *data++;
}
return sum;
}

View File

@ -6,8 +6,6 @@
#include <ngx_listen.h> #include <ngx_listen.h>
#include <ngx_http.h> #include <ngx_http.h>
#include <ngx_http_output_filter.h>
#include <nginx.h> #include <nginx.h>
@ -97,14 +95,18 @@ static ngx_command_t ngx_http_core_commands[] = {
NULL}, NULL},
{ngx_string("listen"), {ngx_string("listen"),
#if 0
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
#else
NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
#endif
ngx_set_listen, ngx_set_listen,
NGX_HTTP_SRV_CONF_OFFSET, NGX_HTTP_SRV_CONF_OFFSET,
0, 0,
NULL}, NULL},
{ngx_string("server_name"), {ngx_string("server_name"),
NGX_HTTP_SRV_CONF|NGX_CONF_ANY1, NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
ngx_set_server_name, ngx_set_server_name,
NGX_HTTP_SRV_CONF_OFFSET, NGX_HTTP_SRV_CONF_OFFSET,
0, 0,
@ -195,12 +197,16 @@ ngx_module_t ngx_http_core_module = {
void ngx_http_handler(ngx_http_request_t *r) void ngx_http_handler(ngx_http_request_t *r)
{ {
int rc, i; int rc, i;
ngx_http_log_ctx_t *lcx;
ngx_http_handler_pt *h; ngx_http_handler_pt *h;
ngx_http_core_loc_conf_t *clcf, **clcfp; ngx_http_core_loc_conf_t *clcf, **clcfp;
ngx_http_core_srv_conf_t *cscf; ngx_http_core_srv_conf_t *cscf;
r->connection->unexpected_eof = 0; r->connection->unexpected_eof = 0;
lcx = r->connection->log->data;
lcx->action = NULL;
r->keepalive = 1; r->keepalive = 1;
if (r->headers_in.content_length_n > 0) { if (r->headers_in.content_length_n > 0) {
@ -337,7 +343,8 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
#else #else
if (r->file.fd == NGX_INVALID_FILE) { if (r->file.fd == NGX_INVALID_FILE) {
r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY); r->file.fd = ngx_open_file(r->file.name.data,
NGX_FILE_RDONLY, NGX_FILE_OPEN);
} }
if (r->file.fd == NGX_INVALID_FILE) { if (r->file.fd == NGX_INVALID_FILE) {
@ -367,6 +374,8 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
r->file.name.data); r->file.name.data);
} }
r->file.fd = NGX_INVALID_FILE;
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
@ -382,6 +391,8 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
ngx_close_file_n " \"%s\" failed", r->file.name.data); ngx_close_file_n " \"%s\" failed", r->file.name.data);
} }
r->file.fd = NGX_INVALID_FILE;
#endif #endif
/* BROKEN: need to include server name */ /* BROKEN: need to include server name */
@ -782,12 +793,13 @@ static char *ngx_http_core_merge_srv_conf(ngx_pool_t *pool,
ngx_http_listen_t *l; ngx_http_listen_t *l;
ngx_http_server_name_t *n; ngx_http_server_name_t *n;
/* TODO: it does not merge, it init only */ /* TODO: it does not merge, it inits only */
if (conf->listen.nelts == 0) { if (conf->listen.nelts == 0) {
ngx_test_null(l, ngx_push_array(&conf->listen), NGX_CONF_ERROR); ngx_test_null(l, ngx_push_array(&conf->listen), NGX_CONF_ERROR);
l->addr = INADDR_ANY; l->addr = INADDR_ANY;
l->port = 8000; /* STUB: getuid() should be cached */
l->port = (getuid() == 0) ? 80 : 8000;
l->family = AF_INET; l->family = AF_INET;
} }
@ -871,8 +883,7 @@ static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool,
int i, key; int i, key;
ngx_http_type_t *t; ngx_http_type_t *t;
ngx_conf_merge_str_value(conf->doc_root, ngx_conf_merge_str_value(conf->doc_root, prev->doc_root, "html");
prev->doc_root, "html");
if (conf->types == NULL) { if (conf->types == NULL) {
if (prev->types) { if (prev->types) {

View File

@ -1,21 +1,8 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_string.h>
#include <ngx_files.h>
#include <ngx_log.h>
#include <ngx_alloc.h>
#include <ngx_array.h>
#include <ngx_table.h>
#include <ngx_hunk.h>
#include <ngx_connection.h>
#include <ngx_event.h> #include <ngx_event.h>
#include <ngx_event_timer.h>
#include <ngx_inet.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>
static void ngx_http_init_request(ngx_event_t *ev); static void ngx_http_init_request(ngx_event_t *ev);
@ -63,12 +50,13 @@ static ngx_http_header_t headers_in[] = {
{ ngx_string("Content-Length"), { ngx_string("Content-Length"),
offsetof(ngx_http_headers_in_t, content_length) }, offsetof(ngx_http_headers_in_t, content_length) },
{ ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) },
#if 0 #if 0
{ ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) },
#endif
{ ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) }, { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
#endif
{ ngx_null_string, 0 } { ngx_null_string, 0 }
}; };
@ -289,6 +277,13 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
/* the request line has been parsed successfully */ /* the request line has been parsed successfully */
/* STUB: we need to handle such URIs */
if (r->complex_uri || r->unusual_uri) {
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_INVALID_REQUEST);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
if (r->http_version >= NGX_HTTP_VERSION_10 if (r->http_version >= NGX_HTTP_VERSION_10
@ -402,7 +397,7 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
if (r->args.data[0] == '\0') { r->args.data = NULL; } if (r->args.data[0] == '\0') { r->args.data = NULL; }
#endif #endif
if (r->http_version == NGX_HTTP_VERSION_9) { if (r->http_version < NGX_HTTP_VERSION_10) {
rev->event_handler = ngx_http_block_read; rev->event_handler = ngx_http_block_read;
ngx_http_handler(r); ngx_http_handler(r);
return; return;
@ -1436,9 +1431,14 @@ static size_t ngx_http_log_error(void *data, char *buf, size_t len)
{ {
ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data; ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data;
if (ctx->url) { if (ctx->action && ctx->url) {
return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s", return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
ctx->action, ctx->client, ctx->url); ctx->action, ctx->client, ctx->url);
} else if (ctx->action == NULL && ctx->url) {
return ngx_snprintf(buf, len, ", client: %s, URL: %s",
ctx->client, ctx->url);
} else { } else {
return ngx_snprintf(buf, len, " while %s, client: %s", return ngx_snprintf(buf, len, " while %s, client: %s",
ctx->action, ctx->client); ctx->action, ctx->client);

View File

@ -0,0 +1,18 @@
#ifndef _NGX_HTTP_FILTER_H_INCLUDED_
#define _NGX_HTTP_FILTER_H_INCLUDED_
#define NGX_HTTP_FILTER_NEED_IN_MEMORY 1
#define NGX_HTTP_FILTER_SSI_NEED_IN_MEMORY 2
#define NGX_HTTP_FILTER_NEED_TEMP 4
int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk);
int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in);
extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r);
extern int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
#endif /* _NGX_HTTP_FILTER_H_INCLUDED_ */

View File

@ -1,8 +1,6 @@
#include <nginx.h>
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_types.h> #include <ngx_core.h>
size_t ngx_http_get_time(char *buf, time_t t) size_t ngx_http_get_time(char *buf, time_t t)

View File

@ -1,11 +1,8 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <nginx.h>
#include <ngx_http.h> #include <ngx_http.h>
#include <ngx_http_write_filter.h> #include <nginx.h>
static int ngx_http_header_filter_init(ngx_pool_t *pool); static int ngx_http_header_filter_init(ngx_pool_t *pool);
@ -52,7 +49,11 @@ static ngx_str_t http_codes[] = {
#endif #endif
ngx_string("301 Moved Permanently"), ngx_string("301 Moved Permanently"),
#if 0
ngx_string("302 Moved Temporarily"), ngx_string("302 Moved Temporarily"),
#else
ngx_string("302 Found"),
#endif
ngx_null_string, /* "303 See Other" */ ngx_null_string, /* "303 See Other" */
ngx_string("304 Not Modified"), ngx_string("304 Not Modified"),
@ -87,11 +88,12 @@ static ngx_str_t http_codes[] = {
static int ngx_http_header_filter(ngx_http_request_t *r) static int ngx_http_header_filter(ngx_http_request_t *r)
{ {
int len, status, text, i; int len, status, i;
time_t ims; time_t ims;
ngx_hunk_t *h; ngx_hunk_t *h;
ngx_chain_t *ch; ngx_chain_t *ch;
ngx_table_elt_t *header; ngx_table_elt_t *header;
ngx_http_range_t *range;
if (r->http_version < NGX_HTTP_VERSION_10) { if (r->http_version < NGX_HTTP_VERSION_10) {
return NGX_OK; return NGX_OK;
@ -170,20 +172,23 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
len += 37; len += 37;
} }
if (r->headers_out.content_range && r->headers_out.content_range->value.len)
{
len += 15 + r->headers_out.content_range->value.len + 2;
}
if (r->headers_out.content_length >= 0) { if (r->headers_out.content_length >= 0) {
/* "Content-Length: ... \r\n", 2^64 is 20 characters */ /* "Content-Length: ... \r\n", 2^64 is 20 characters */
len += 48; len += 48;
} }
text = 0;
if (r->headers_out.content_type && r->headers_out.content_type->value.len) { if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
r->headers_out.content_type->key.len = 0; r->headers_out.content_type->key.len = 0;
len += 16 + r->headers_out.content_type->value.len; len += 16 + r->headers_out.content_type->value.len;
if (ngx_strncasecmp(r->headers_out.content_type->value.data,
"text/", 5) == 0) { if (r->headers_out.charset.len) {
text = 1; /* "; charset= ... " */
/* "; charset=koi8-r" */ len += 10 + r->headers_out.charset.len;
len += 16;
} }
} }
@ -210,6 +215,11 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
len += 46; len += 46;
} }
if (r->chunked) {
/* "Transfer-Encoding: chunked\r\n" */
len += 28;
}
if (r->keepalive == 0) { if (r->keepalive == 0) {
/* "Connection: close\r\n" */ /* "Connection: close\r\n" */
len += 19; len += 19;
@ -253,6 +263,15 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
*(h->last++) = CR; *(h->last++) = LF; *(h->last++) = CR; *(h->last++) = LF;
} }
if (r->headers_out.content_range && r->headers_out.content_range->value.len)
{
h->last = ngx_cpymem(h->last, "Content-Range: ", 15);
h->last = ngx_cpymem(h->last, r->headers_out.content_range->value.data,
r->headers_out.content_range->value.len);
*(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 += ngx_snprintf(h->last, 49, h->last += ngx_snprintf(h->last, 49,
@ -263,10 +282,12 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
if (r->headers_out.content_type && r->headers_out.content_type->value.len) { if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
h->last = ngx_cpymem(h->last, "Content-Type: ", 14); h->last = ngx_cpymem(h->last, "Content-Type: ", 14);
h->last = ngx_cpymem(h->last, r->headers_out.content_type->value.data, h->last = ngx_cpymem(h->last, r->headers_out.content_type->value.data,
r->headers_out.content_type->value.len); r->headers_out.content_type->value.len);
if (text) { if (r->headers_out.charset.len) {
h->last = ngx_cpymem(h->last, "; charset=koi8-r", 16); h->last = ngx_cpymem(h->last, "; charset=", 10);
h->last = ngx_cpymem(h->last, r->headers_out.charset.data,
r->headers_out.charset.len);
} }
*(h->last++) = CR; *(h->last++) = LF; *(h->last++) = CR; *(h->last++) = LF;
@ -299,6 +320,10 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
*(h->last++) = CR; *(h->last++) = LF; *(h->last++) = CR; *(h->last++) = LF;
} }
if (r->chunked) {
h->last = ngx_cpymem(h->last, "Transfer-Encoding: chunked" CRLF, 28);
}
if (r->keepalive == 0) { if (r->keepalive == 0) {
h->last = ngx_cpymem(h->last, "Connection: close" CRLF, 19); h->last = ngx_cpymem(h->last, "Connection: close" CRLF, 19);

View File

@ -1,15 +1,20 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_files.h>
#include <ngx_string.h>
#include <ngx_hunk.h>
#include <ngx_conf_file.h>
#include <ngx_http.h> #include <ngx_http.h>
#include <ngx_http_config.h>
#include <ngx_http_output_filter.h>
typedef struct {
size_t hunk_size;
} ngx_http_output_filter_conf_t;
typedef struct {
ngx_hunk_t *hunk; /* the temporary hunk to copy */
ngx_chain_t *incoming;
ngx_chain_t in; /* one chain entry for input */
ngx_chain_t out; /* one chain entry for output */
} ngx_http_output_filter_ctx_t;
static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src); static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src);

View File

@ -1,34 +0,0 @@
#ifndef _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_
#define _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_
#include <ngx_hunk.h>
#include <ngx_conf_file.h>
#include <ngx_http.h>
#define NGX_HTTP_FILTER_NEED_IN_MEMORY 1
#define NGX_HTTP_FILTER_SSI_NEED_IN_MEMORY 2
#define NGX_HTTP_FILTER_NEED_TEMP 4
typedef struct {
size_t hunk_size;
} ngx_http_output_filter_conf_t;
typedef struct {
ngx_hunk_t *hunk; /* the temporary hunk to copy */
ngx_chain_t *incoming;
ngx_chain_t in; /* one chain entry for input */
ngx_chain_t out; /* one chain entry for output */
} ngx_http_output_filter_ctx_t;
int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk);
extern ngx_module_t ngx_http_output_filter_module;
#endif /* _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_ */

View File

@ -175,7 +175,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
} }
break; break;
/* check "/." or "//" */ /* check "/.", "//", and "%" in URI */
case sw_after_slash_in_uri: case sw_after_slash_in_uri:
switch (ch) { switch (ch) {
case CR: case CR:
@ -193,6 +193,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
state = sw_http_09; state = sw_http_09;
break; break;
case '.': case '.':
case '%':
r->complex_uri = 1; r->complex_uri = 1;
state = sw_uri; state = sw_uri;
break; break;
@ -211,7 +212,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
} }
break; break;
/* check slash in URI */ /* check "/" and "%" in URI */
case sw_check_uri: case sw_check_uri:
switch (ch) { switch (ch) {
case CR: case CR:
@ -235,6 +236,10 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
r->uri_ext = NULL; r->uri_ext = NULL;
state = sw_after_slash_in_uri; state = sw_after_slash_in_uri;
break; break;
case '%':
r->complex_uri = 1;
state = sw_uri;
break;
case '?': case '?':
r->args_start = p; r->args_start = p;
state = sw_uri; state = sw_uri;

View File

@ -40,6 +40,7 @@
#define NGX_HTTP_OK 200 #define NGX_HTTP_OK 200
#define NGX_HTTP_PARTIAL_CONTENT 206
#define NGX_HTTP_SPECIAL_RESPONSE 300 #define NGX_HTTP_SPECIAL_RESPONSE 300
#define NGX_HTTP_MOVED_PERMANENTLY 301 #define NGX_HTTP_MOVED_PERMANENTLY 301
@ -52,6 +53,7 @@
#define NGX_HTTP_NOT_ALLOWED 405 #define NGX_HTTP_NOT_ALLOWED 405
#define NGX_HTTP_REQUEST_TIME_OUT 408 #define NGX_HTTP_REQUEST_TIME_OUT 408
#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 #define NGX_HTTP_REQUEST_URI_TOO_LARGE 414
#define NGX_HTTP_RANGE_NOT_SATISFIABLE 416
#define NGX_HTTP_INTERNAL_SERVER_ERROR 500 #define NGX_HTTP_INTERNAL_SERVER_ERROR 500
#define NGX_HTTP_NOT_IMPLEMENTED 501 #define NGX_HTTP_NOT_IMPLEMENTED 501
@ -79,6 +81,8 @@ typedef struct {
ngx_table_elt_t *connection; ngx_table_elt_t *connection;
ngx_table_elt_t *if_modified_since; ngx_table_elt_t *if_modified_since;
ngx_table_elt_t *content_length; ngx_table_elt_t *content_length;
ngx_table_elt_t *range;
ngx_table_elt_t *accept_encoding; ngx_table_elt_t *accept_encoding;
ngx_table_elt_t *user_agent; ngx_table_elt_t *user_agent;
@ -99,6 +103,13 @@ typedef struct {
} ngx_http_request_body_t; } ngx_http_request_body_t;
typedef struct {
off_t start;
off_t end;
ngx_str_t content_range;
} ngx_http_range_t;
typedef struct { typedef struct {
int status; int status;
ngx_str_t status_line; ngx_str_t status_line;
@ -108,11 +119,14 @@ typedef struct {
ngx_table_elt_t *content_type; ngx_table_elt_t *content_type;
ngx_table_elt_t *location; ngx_table_elt_t *location;
ngx_table_elt_t *last_modified; ngx_table_elt_t *last_modified;
ngx_table_elt_t *content_range;
ngx_str_t charset;
ngx_array_t ranges;
ngx_table_t *headers; ngx_table_t *headers;
off_t content_length; off_t content_length;
char *charset;
char *etag; char *etag;
time_t date_time; time_t date_time;
time_t last_modified_time; time_t last_modified_time;
@ -140,7 +154,7 @@ struct ngx_http_request_s {
int (*handler)(ngx_http_request_t *r); int (*handler)(ngx_http_request_t *r);
time_t lingering_time; time_t lingering_time;
int method; int method;
int http_version; int http_version;
@ -161,46 +175,44 @@ struct ngx_http_request_s {
ngx_str_t *server_name; ngx_str_t *server_name;
ngx_array_t *virtual_names; ngx_array_t *virtual_names;
int filter;
char *discarded_buffer; char *discarded_buffer;
ngx_str_t path; ngx_str_t path;
int path_err; int path_err;
unsigned proxy:1; /* URI is not started with '/' - "GET http://" */
unsigned cachable:1; unsigned unusual_uri:1;
unsigned pipeline:1; /* URI with "/.", "%" and on Win32 with "//" */
unsigned keepalive:1; unsigned complex_uri:1;
unsigned lingering_close:1; unsigned header_timeout_set:1;
unsigned header_read:1; unsigned proxy:1;
unsigned header_timeout_set:1; #if 0
unsigned cachable:1;
unsigned logging:1;
unsigned header_only:1;
unsigned unusual_uri:1; /* URI is not started with '/' - "GET http://" */
unsigned complex_uri:1; /* URI with "/." or with "//" (WIN32) */
unsigned path_not_found:1;
#ifdef NGX_EVENT
unsigned write_level_event:1;
#endif #endif
unsigned pipeline:1;
int state; unsigned chunked:1;
char *uri_start; unsigned header_only:1;
char *uri_end; unsigned keepalive:1;
char *uri_ext; unsigned lingering_close:1;
char *args_start;
char *request_start; /* TODO: use filter or bits ???? */
char *request_end; int filter;
char *header_name_start;
char *header_name_end; /* used to parse HTTP headers */
char *header_start; int state;
char *header_end; char *uri_start;
#ifdef NGX_EVENT char *uri_end;
int (*state_handler)(ngx_http_request_t *r); char *uri_ext;
#endif char *args_start;
char *request_start;
char *request_end;
char *header_name_start;
char *header_name_end;
char *header_start;
char *header_end;
}; };

View File

@ -0,0 +1,49 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
char *ngx_http_script_copy(ngx_http_request_t *r,
ngx_http_script_code_t *code,
char *p, size_t len)
{
return ngx_cpymem(p, code->offset, code->len < len ? code->len : len);
}
char *ngx_http_script_header_in(ngx_http_request_t *r,
ngx_http_script_code_t *code,
char *p, size_t len)
{
ngx_str_t *s;
s = (ngx_str_t *) (((char *) r->headers_in) + code->offset);
return ngx_cpymem(p, s->data, s->len < len ? s->len : len);
}
/* the log script codes */
char *ngx_http_script_request_line(ngx_http_request_t *r, char *p, size_t len)
{
return ngx_cpymem(p, r->request_line.data,
r->request_line.len < len ? r->request_line.len : len);
}
char *ngx_http_script_status(ngx_http_request_t *r, char *p, size_t len)
{
p += ngx_snprintf(p, len, "%d", r->headers_out.status);
return p;
}
char *ngx_http_script_sent(ngx_http_request_t *r, char *p, size_t len)
{
p += ngx_snprintf(p, len, OFF_FMT, r->connection->sent);
return p;
}

View File

@ -0,0 +1,12 @@
#ifndef _NGX_HTTP_SCRIPT_H_INCLUDED_
#define _NGX_HTTP_SCRIPT_H_INCLUDED_
typedef struct {
handler;
offset / data;
size;
} ngx_http_script_code_t;
#endif /* _NGX_HTTP_SCRIPT_H_INCLUDED_ */

View File

@ -1,11 +1,8 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <nginx.h>
#include <ngx_http.h> #include <ngx_http.h>
#include <ngx_http_output_filter.h> #include <nginx.h>
static char error_tail[] = static char error_tail[] =
@ -15,6 +12,14 @@ static char error_tail[] =
; ;
static char error_302_page[] =
"<html>" CRLF
"<head><title>302 Found</title></head>" CRLF
"<body bgcolor=\"white\">" CRLF
"<center><h1>302 Found</h1></center>" CRLF
;
static char error_400_page[] = static char error_400_page[] =
"<html>" CRLF "<html>" CRLF
"<head><title>400 Bad Request</title></head>" CRLF "<head><title>400 Bad Request</title></head>" CRLF
@ -63,6 +68,14 @@ static char error_414_page[] =
; ;
static char error_416_page[] =
"<html>" CRLF
"<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF
"<body bgcolor=\"white\">" CRLF
"<center><h1>416 Requested Range Not Satisfiable</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
@ -88,8 +101,9 @@ static char error_504_page[] =
static ngx_str_t error_pages[] = { static ngx_str_t error_pages[] = {
ngx_null_string, /* 300 */
ngx_null_string, /* 301 */ ngx_null_string, /* 301 */
ngx_null_string, /* 302 */ ngx_string(error_302_page),
ngx_null_string, /* 303 */ ngx_null_string, /* 303 */
ngx_string(error_400_page), ngx_string(error_400_page),
@ -108,7 +122,7 @@ static ngx_str_t error_pages[] = {
ngx_null_string, /* 413 */ ngx_null_string, /* 413 */
ngx_string(error_414_page), ngx_string(error_414_page),
ngx_null_string, /* 415 */ ngx_null_string, /* 415 */
ngx_null_string, /* 416 */ ngx_string(error_416_page),
ngx_string(error_500_page), ngx_string(error_500_page),
ngx_null_string, /* 501 */ ngx_null_string, /* 501 */
@ -120,35 +134,22 @@ static ngx_str_t error_pages[] = {
int ngx_http_special_response_handler(ngx_http_request_t *r, int error) int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
{ {
int err, len; int err;
ngx_hunk_t *message, *tail; ngx_hunk_t *message, *tail;
len = 0;
r->headers_out.status = error; r->headers_out.status = error;
if (error < NGX_HTTP_BAD_REQUEST) { if (error < NGX_HTTP_BAD_REQUEST) {
/* 3XX */ /* 3XX */
err = error - NGX_HTTP_MOVED_PERMANENTLY; err = error - NGX_HTTP_MOVED_PERMANENTLY;
} else if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) {
/* 4XX */
err = error - NGX_HTTP_BAD_REQUEST + 4;
} else { } else {
ngx_test_null(r->headers_out.content_type, /* 5XX */
ngx_push_table(r->headers_out.headers), err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 4 + 17;
NGX_HTTP_INTERNAL_SERVER_ERROR);
r->headers_out.content_type->key.len = 12;
r->headers_out.content_type->key.data = "Content-Type";
r->headers_out.content_type->value.len = 9;
r->headers_out.content_type->value.data = "text/html";
if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) {
/* 4XX */
err = error - NGX_HTTP_BAD_REQUEST + 3;
} else {
/* 5XX */
err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17;
}
} }
if (r->keepalive != 0) { if (r->keepalive != 0) {
@ -169,11 +170,21 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
} }
} }
if (error_pages[err].len == 0) { if (error_pages[err].len) {
r->headers_out.content_length = -1;
} else {
r->headers_out.content_length = error_pages[err].len r->headers_out.content_length = error_pages[err].len
+ len + sizeof(error_tail); + sizeof(error_tail);
ngx_test_null(r->headers_out.content_type,
ngx_push_table(r->headers_out.headers),
NGX_HTTP_INTERNAL_SERVER_ERROR);
r->headers_out.content_type->key.len = 12;
r->headers_out.content_type->key.data = "Content-Type";
r->headers_out.content_type->value.len = 9;
r->headers_out.content_type->value.data = "text/html";
} else {
r->headers_out.content_length = -1;
} }
if (ngx_http_send_header(r) == NGX_ERROR) { if (ngx_http_send_header(r) == NGX_ERROR) {

View File

@ -1,16 +1,17 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_hunk.h>
#include <ngx_conf_file.h>
#include <ngx_connection.h>
#include <ngx_event_write.h>
#include <ngx_http.h> #include <ngx_http.h>
#include <ngx_http_config.h>
#include <ngx_http_write_filter.h>
typedef struct {
size_t buffer_output;
} ngx_http_write_filter_conf_t;
typedef struct {
ngx_chain_t *out;
} ngx_http_write_filter_ctx_t;
static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool); static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool);
@ -96,7 +97,7 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
/* add the new chain to the existent one */ /* add the new chain to the existent one */
for (/* void */; in; in = in->next) { for (/* void */; in; in = in->next) {
ngx_test_null(ce, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR); ngx_test_null(ce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
ce->hunk = in->hunk; ce->hunk = in->hunk;
ce->next = NULL; ce->next = NULL;

View File

@ -1,25 +0,0 @@
#ifndef _NGX_HTTP_WRITE_FILTER_H_INCLUDED_
#define _NGX_HTTP_WRITE_FILTER_H_INCLUDED_
#include <ngx_hunk.h>
#include <ngx_http.h>
typedef struct {
size_t buffer_output;
} ngx_http_write_filter_conf_t;
typedef struct {
ngx_chain_t *out;
} ngx_http_write_filter_ctx_t;
int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in);
extern ngx_module_t ngx_http_write_filter_module;
#endif /* _NGX_HTTP_WRITE_FILTER_H_INCLUDED_ */

View File

@ -15,20 +15,29 @@
#define ngx_open_file open #define ngx_open_file(name, access, create) \
open(name, access|create, 0644)
#define ngx_open_file_n "open()" #define ngx_open_file_n "open()"
#define NGX_FILE_RDONLY O_RDONLY
#define NGX_FILE_RDWR O_RDWR
#define NGX_FILE_CREATE_OR_OPEN O_CREAT
#define NGX_FILE_OPEN 0
#define NGX_FILE_APPEND O_APPEND
#define ngx_close_file close #define ngx_close_file close
#define ngx_close_file_n "close()" #define ngx_close_file_n "close()"
#define ngx_open_tempfile(name, persistent) \ #define ngx_open_tempfile(name, persistent) \
open(name, O_CREAT|O_EXCL|O_RDWR, 0600) open(name, O_CREAT|O_EXCL|O_RDWR, 0600)
#define ngx_open_tempfile_n "open()" #define ngx_open_tempfile_n "open()"
ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset); ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset);
#define ngx_read_file_n "read()" #define ngx_read_file_n "read()"
#define NGX_FILE_RDONLY O_RDONLY
ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset); ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset);

View File

@ -9,6 +9,7 @@ int ngx_freebsd_kern_osreldate;
int ngx_freebsd_hw_ncpu; int ngx_freebsd_hw_ncpu;
int ngx_freebsd_net_inet_tcp_sendspace; int ngx_freebsd_net_inet_tcp_sendspace;
int ngx_freebsd_sendfile_nbytes_bug; int ngx_freebsd_sendfile_nbytes_bug;
int ngx_freebsd_tcp_nopush_flush;
/* FreeBSD 5.0 */ /* FreeBSD 5.0 */
int ngx_freebsd_kern_ipc_zero_copy_send; int ngx_freebsd_kern_ipc_zero_copy_send;
@ -39,6 +40,8 @@ sysctl_t sysctls[] = {
&ngx_freebsd_net_inet_tcp_sendspace, &ngx_freebsd_net_inet_tcp_sendspace,
sizeof(int)}, sizeof(int)},
/* FreeBSD 5.0 */
{"kern.ipc.zero_copy.send", {"kern.ipc.zero_copy.send",
&ngx_freebsd_kern_ipc_zero_copy_send, &ngx_freebsd_kern_ipc_zero_copy_send,
sizeof(int)}, sizeof(int)},
@ -49,7 +52,7 @@ sysctl_t sysctls[] = {
int ngx_os_init(ngx_log_t *log) int ngx_os_init(ngx_log_t *log)
{ {
int i; int i, version;
size_t size; size_t size;
ngx_err_t err; ngx_err_t err;
@ -81,9 +84,11 @@ int ngx_os_init(ngx_log_t *log)
return NGX_ERROR; return NGX_ERROR;
} }
version = ngx_freebsd_kern_osreldate;
ngx_log_error(NGX_LOG_INFO, log, 0, ngx_log_error(NGX_LOG_INFO, log, 0,
"kern.osreldate: %d, built on %d", "kern.osreldate: %d, built on %d",
ngx_freebsd_kern_osreldate, __FreeBSD_version); version, __FreeBSD_version);
#if (HAVE_FREEBSD_SENDFILE) #if (HAVE_FREEBSD_SENDFILE)
@ -91,12 +96,12 @@ int ngx_os_init(ngx_log_t *log)
/* The determination of the sendfile() nbytes bug is complex enough. /* The determination of the sendfile() nbytes bug is complex enough.
There're two sendfile() syscalls: a new 393 has no bug while There're two sendfile() syscalls: a new 393 has no bug while
an old 336 has the bug in some versions and has not in others. an old 336 has the bug in some versions and has not in others.
libc_r wrapper also emulates the bug in some versions. Besides libc_r wrapper also emulates the bug in some versions.
There's no way to say exactly if a given FreeBSD version has bug. There's no way to say exactly if a given FreeBSD version has bug.
Here is the algorithm that work at least for RELEASEs Here is the algorithm that works at least for RELEASEs
and for syscalls only (not libc_r wrapper). */ and for syscalls only (not libc_r wrapper). */
/* detect was the new sendfile() version available at the compile time /* detect the new sendfile() version available at the compile time
to allow an old binary to run correctly on an updated FreeBSD system. */ to allow an old binary to run correctly on an updated FreeBSD system. */
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \ #if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \
@ -115,6 +120,11 @@ int ngx_os_init(ngx_log_t *log)
#endif /* HAVE_FREEBSD_SENDFILE */ #endif /* HAVE_FREEBSD_SENDFILE */
if ((version < 500000 && version >= 440003) || version >= 500017) {
ngx_freebsd_tcp_nopush_flush = 1;
}
for (i = 0; sysctls[i].name; i++) { for (i = 0; sysctls[i].name; i++) {
*sysctls[i].value = 0; *sysctls[i].value = 0;
size = sysctls[i].size; size = sysctls[i].size;

View File

@ -20,6 +20,8 @@ extern int ngx_freebsd_kern_osreldate;
extern int ngx_freebsd_hw_ncpu; extern int ngx_freebsd_hw_ncpu;
extern int ngx_freebsd_net_inet_tcp_sendspace; extern int ngx_freebsd_net_inet_tcp_sendspace;
extern int ngx_freebsd_sendfile_nbytes_bug; extern int ngx_freebsd_sendfile_nbytes_bug;
extern int ngx_freebsd_tcp_nopush_flush;
extern int ngx_freebsd_kern_ipc_zero_copy_send;
#endif /* _NGX_FREEBSD_INIT_H_INCLUDED_ */ #endif /* _NGX_FREEBSD_INIT_H_INCLUDED_ */

View File

@ -13,9 +13,9 @@
and the first part of the file in one packet but also sends 4K pages and the first part of the file in one packet but also sends 4K pages
in the full packets. in the full packets.
The turning TCP_NOPUSH off flushes any pending data at least in FreeBSD 4.2, Until FreeBSD 4.5 the turning TCP_NOPUSH off does not not flush
although there's special fix in src/sys/netinet/tcp_usrreq.c just before the pending data that less than MSS and the data sent with 5 second delay.
FreeBSD 4.5. So we use TCP_NOPUSH on FreeBSD 4.5+ only.
*/ */
@ -105,14 +105,15 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
if (file) { if (file) {
if (tcp_nopush == 0) { if (!c->tcp_nopush && ngx_freebsd_tcp_nopush_flush) {
c->tcp_nopush = 1;
tcp_nopush = 1; tcp_nopush = 1;
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH, if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH,
(const void *) &tcp_nopush, (const void *) &tcp_nopush,
sizeof(int)) == -1) sizeof(int)) == -1)
{ {
ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno, ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
"setsockopt(TCP_NO_PUSH) failed"); "setsockopt(TCP_NOPUSH) failed");
return NGX_CHAIN_ERROR; return NGX_CHAIN_ERROR;
} }
} }
@ -221,14 +222,18 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
} while ((tail && tail == ce) || eintr); } while ((tail && tail == ce) || eintr);
if (tcp_nopush == 1) { /* STUB: should be in app code, no need to clear TCP_NOPUSH
if the conneciton close()d or shutdown()ed */
if (c->tcp_nopush) {
c->tcp_nopush = 0;
tcp_nopush = 0; tcp_nopush = 0;
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH, if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH,
(const void *) &tcp_nopush, (const void *) &tcp_nopush,
sizeof(int)) == -1) sizeof(int)) == -1)
{ {
ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno, ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
"setsockopt(!TCP_NO_PUSH) failed"); "setsockopt(!TCP_NOPUSH) failed");
return NGX_CHAIN_ERROR; return NGX_CHAIN_ERROR;
} }
} }

View File

@ -18,13 +18,20 @@
#define ngx_open_file(name, flags) \ #define ngx_open_file(name, access, create) \
CreateFile(name, flags, \ CreateFile(name, flags, \
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, \ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, \
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL) NULL, create, FILE_FLAG_BACKUP_SEMANTICS, NULL)
/* /*
NULL, OPEN_EXISTING, 0, NULL) NULL, OPEN_EXISTING, 0, NULL)
*/ */
#define ngx_open_file_n "CreateFile()"
#define NGX_FILE_RDONLY GENERIC_READ
#define NGX_FILE_RDWR GENERIC_READ|GENERIC_WRITE
#define NGX_FILE_CREATE_OR_OPEN OPEN_ALWAYS
#define NGX_FILE_OPEN OPEN_EXISTING
#define ngx_open_tempfile(name, persistent) \ #define ngx_open_tempfile(name, persistent) \
CreateFile(name, \ CreateFile(name, \
@ -40,10 +47,6 @@
#define ngx_open_file_n "CreateFile()"
#define NGX_FILE_RDONLY GENERIC_READ
#define ngx_close_file CloseHandle #define ngx_close_file CloseHandle
#define ngx_close_file_n "CloseHandle()" #define ngx_close_file_n "CloseHandle()"