nginx-0.0.1-2003-05-12-19:52:24 import

This commit is contained in:
Igor Sysoev 2003-05-12 15:52:24 +00:00
parent 4fe262b682
commit 6b863e353d
17 changed files with 760 additions and 355 deletions

View File

@ -67,6 +67,10 @@ int main(int argc, char *const *argv)
#endif
if (ngx_os_init(&ngx_log) == NGX_ERROR) {
exit(1);
}
ngx_init_array(ngx_listening_sockets, ngx_pool, 10, sizeof(ngx_listen_t),
1);

View File

@ -141,7 +141,7 @@ int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
if (nchanges > 0
&& ev->index < nchanges
&& change_list[ev->index].udata == ev)
&& (void *) ((uintptr_t) change_list[ev->index].udata & ~1) == ev)
{
#if (NGX_DEBUG_EVENT)
ngx_connection_t *c = (ngx_connection_t *) ev->data;
@ -159,8 +159,9 @@ int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
return NGX_OK;
}
/* when a socket is closed kqueue automatically deletes its filters
so we do not need to delete a event explicity before a socket closing */
/* when the file descriptor is closed a kqueue automatically deletes
its filters so we do not need to delete explicity the event
before the closing the file descriptor */
if (flags & NGX_CLOSE_EVENT) {
return NGX_OK;
@ -200,7 +201,7 @@ int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
change_list[nchanges].ident = c->fd;
change_list[nchanges].filter = filter;
change_list[nchanges].flags = flags;
change_list[nchanges].udata = ev;
change_list[nchanges].udata = (void *) ((uintptr_t) ev | ev->instance);
#if (HAVE_LOWAT_EVENT)
@ -230,7 +231,7 @@ int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
int ngx_kqueue_process_events(ngx_log_t *log)
{
int events, i;
int events, instance, i;
ngx_msec_t timer, delta;
ngx_event_t *ev;
struct timeval tv;
@ -310,12 +311,15 @@ int ngx_kqueue_process_events(ngx_log_t *log)
}
ev = (ngx_event_t *) event_list[i].udata;
instance = (uintptr_t) ev & 1;
ev = (void *) ((uintptr_t) ev & ~1);
/* It's a stale event from a socket
/* It's a stale event from a file descriptor
that was just closed in this iteration */
if (!ev->active) {
continue;
if (ev->active == 0 || ev->instance != instance) {
ngx_log_debug(log, "stale kevent");
continue;
}
switch (event_list[i].filter) {
@ -323,28 +327,6 @@ int ngx_kqueue_process_events(ngx_log_t *log)
case EVFILT_READ:
case EVFILT_WRITE:
if (ev->first) {
if (nchanges > 0
&& ev->index < nchanges
&& change_list[ev->index].udata == ev) {
/* It's a stale event from a socket that was just closed
in this iteration and during processing another socket
was opened with the same number by accept() or socket()
and its event has been added the event to the change_list
but has not been passed to a kernel. Nevertheless
there's small chance that ngx_kqueue_set_event() has
flushed the new event if the change_list was filled up.
In this very rare case we would get EAGAIN while
a reading or a writing */
continue;
} else {
ev->first = 0;
}
}
ev->available = event_list[i].data;
if (event_list[i].flags & EV_EOF) {

View File

@ -63,7 +63,9 @@ struct ngx_event_s {
#endif
unsigned write:1;
unsigned first:1;
unsigned instance:1; /* used to detect stale events in kqueue,
rt signals and epoll */
unsigned active:1;
unsigned ready:1;
unsigned timedout:1;
@ -114,6 +116,7 @@ struct ngx_event_s {
#endif
};
typedef enum {
NGX_SELECT_EVENT_N = 0,
#if (HAVE_POLL)

View File

@ -16,6 +16,7 @@
int ngx_event_accept(ngx_event_t *ev)
{
int instance;
socklen_t len;
struct sockaddr *sa;
ngx_err_t err;
@ -95,6 +96,8 @@ int ngx_event_accept(ngx_event_t *ev)
wev = &ngx_write_events[s];
c = &ngx_connections[s];
instance = rev->instance;
ngx_memzero(rev, sizeof(ngx_event_t));
ngx_memzero(wev, sizeof(ngx_event_t));
ngx_memzero(c, sizeof(ngx_connection_t));
@ -108,6 +111,8 @@ int ngx_event_accept(ngx_event_t *ev)
c->addr_text_max_len = ls->addr_text_max_len;
c->post_accept_timeout = ls->post_accept_timeout;
rev->instance = wev->instance = !instance;
rev->index = wev->index = NGX_INVALID_INDEX;
rev->data = wev->data = c;
@ -117,7 +122,6 @@ int ngx_event_accept(ngx_event_t *ev)
c->fd = s;
c->unexpected_eof = 1;
wev->write = 1;
rev->first = wev->first = 1;
#if (USE_KQUEUE)
wev->ready = 1;

View File

@ -0,0 +1,126 @@
#include <ngx_event_connect.h>
int ngx_event_connect_peer(ngx_connect_peer_t *cp)
{
if (cp->peers->number > 1) {
/* it's a first try - get current peer */
if (cp->tries == cp->peers->number) {
/* Here is the race condition
when the peers are shared between
the threads or the processes but it should not be serious */
cp->cur_peer = cp->peers->current++;
if (cp->peers->current >= cp->peers->number) {
cp->peers->current = 0;
}
/* */
#if (NGX_MULTITHREADED || NGX_MULTIPROCESSED)
/* eliminate the sequences of the race condition */
if (cp->cur_peer >= cp->peers->number) {
cp->cur_peer = 0;
}
#endif
}
if (cp->peers->max_fails > 0) {
for ( ;; ) {
peer = &cp->peers->peers[cp->cur_peer];
/* Here is the race condition
when the peers are shared between
the threads or the processes but it should not be serious */
if (peer->fails <= cp->peers->max_fails
|| (now - peer->accessed > cp->peers->fail_timeout))
{
break;
}
/* */
cp->cur_peer++;
if (cp->cur_peer >= cp->peers->number) {
cp->cur_peer = 0;
}
cp->tries--;
if (cp->tries == 0) {
return NGX_ERROR;
}
}
}
}
s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0);
if (s == -1) {
ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno,
ngx_socket_n " failed");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (cn->rcvbuf) {
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
(const void *) &cn->rcvbuf, sizeof(int)) == -1) {
ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno,
"setsockopt(SO_RCVBUF) failed");
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno,
ngx_close_socket_n " failed");
}
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
if (ngx_nonblocking(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno,
ngx_nonblocking_n " failed");
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno,
ngx_close_socket_n " failed");
}
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
c = &ngx_connections[s];
rev = &ngx_read_events[s];
wev = &ngx_write_events[s];
instance = rev->instance;
ngx_memzero(c, sizeof(ngx_connection_t));
ngx_memzero(rev, sizeof(ngx_event_t));
ngx_memzero(wev, sizeof(ngx_event_t));
rev->index = wev->index = NGX_INVALID_INDEX;
rev->data = wev->data = c;
c->read = rev;
c->write = wev;
rev->instance = wev->instance = !instance;
rev->log = wev->log = c->log = cn->log;
c->fd = s;
wev->close_handler = rev->close_handler = ngx_event_close_connection;

View File

@ -0,0 +1,43 @@
#ifndef _NGX_EVENT_CONNECT_H_INCLUDED_
#define _NGX_EVENT_CONNECT_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_string.h>
#include <ngx_log.h>
#include <ngx_event.h>
#include <ngx_connection.h>
typedef struct {
u_int32_t addr;
ngx_str_t host;
int port;
ngx_str_t addr_port_name;
int fails;
time_t accessed;
} ngx_peer_t;
typedef struct {
int current;
int number;
int max_fails;
int fail_timeout;
/* ngx_mutex_t *mutex; */
/* ngx_connection_t *cached; */
ngx_peer_t peers[1];
} ngx_peers_t;
typedef struct {
ngx_peers_t *peers;
int cur_peer;
int tries;
} ngx_connect_peer_t;
#endif /* _NGX_EVENT_CONNECT_H_INCLUDED_ */

View File

@ -45,7 +45,8 @@ void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
#if (NGX_DEBUG_EVENT)
ngx_connection_t *c = (ngx_connection_t *) ev->data;
ngx_log_debug(ev->log, "set timer: %d:%d" _ c->fd _ timer);
ngx_log_debug(ev->log, "set timer: %d:%d, slot: %d" _
c->fd _ timer _ ngx_timer_cur_queue);
#endif
if (ev->timer_next || ev->timer_prev) {
@ -53,10 +54,6 @@ void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
return;
}
#if (NGX_DEBUG_EVENT)
ngx_log_debug(ev->log, "timer slot: %d" _ ngx_timer_cur_queue);
#endif
for (e = ngx_timer_queue[ngx_timer_cur_queue].timer_next;
e != &ngx_timer_queue[ngx_timer_cur_queue] && timer > e->timer_delta;
e = e->timer_next)

View File

@ -481,7 +481,7 @@ static int ngx_http_proxy_process_upstream(ngx_http_proxy_ctx_t *p,
static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
{
int rc, event;
int rc, event, instance;
struct sockaddr_in *addr;
ngx_err_t err;
ngx_socket_t s;
@ -590,6 +590,8 @@ static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
rev = &ngx_read_events[s];
wev = &ngx_write_events[s];
instance = rev->instance;
ngx_memzero(c, sizeof(ngx_connection_t));
ngx_memzero(rev, sizeof(ngx_event_t));
ngx_memzero(wev, sizeof(ngx_event_t));
@ -598,7 +600,9 @@ static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
rev->data = wev->data = c;
c->read = rev;
c->write = wev;
rev->first = wev->first = 1;
rev->instance = wev->instance = !instance;
rev->log = wev->log = c->log = p->log;
c->fd = s;
wev->close_handler = rev->close_handler = ngx_event_close_connection;
@ -1002,7 +1006,7 @@ static int ngx_http_proxy_process_upstream_headers(ngx_http_proxy_ctx_t *p)
r = p->request;
for ( ;; ) {
rc = ngx_read_http_header_line(r, p->header_in);
rc = ngx_parse_http_header_line(r, p->header_in);
/* a header line has been parsed successfully */

View File

@ -231,9 +231,9 @@ typedef int (*ngx_http_output_body_filter_p)
int ngx_http_init(ngx_pool_t *pool, ngx_log_t *log);
/**/
int ngx_http_init_connection(ngx_connection_t *c);
int ngx_read_http_request_line(ngx_http_request_t *r);
int ngx_read_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h);
void ngx_http_init_connection(ngx_connection_t *c);
int ngx_parse_http_request_line(ngx_http_request_t *r);
int ngx_parse_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h);
int ngx_http_handler(ngx_http_request_t *r);

View File

@ -568,9 +568,9 @@ int ngx_http_close_request(ngx_http_request_t *r, int error)
c->write->timer_set = 0;
}
ngx_log_debug(c->log, "http closed");
ngx_log_debug(c->log, "http request closed");
return NGX_ERROR; /* to close connection */
return 0;
}

View File

@ -18,10 +18,17 @@
#include <ngx_http_output_filter.h>
static int ngx_http_init_request(ngx_event_t *ev);
static void ngx_http_init_request(ngx_event_t *ev);
static void ngx_http_process_request_line(ngx_event_t *rev);
static void ngx_http_process_request_headers(ngx_event_t *rev);
static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
static int ngx_http_process_request(ngx_event_t *ev);
static int ngx_http_process_request_line(ngx_http_request_t *r);
static int ngx_http_process_request_headers(ngx_http_request_t *r);
static int ngx_http_process_request_header_line(ngx_http_request_t *r);
static int ngx_http_request_handler(ngx_http_request_t *r, int error);
@ -33,11 +40,12 @@ static int ngx_http_keepalive_handler(ngx_event_t *ev);
static int ngx_http_set_lingering_close(ngx_http_request_t *r);
static int ngx_http_lingering_close_handler(ngx_event_t *ev);
static int ngx_http_close_connection(ngx_event_t *ev);
static int ngx_http_close_connection(ngx_connection_t *c);
static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err);
static size_t ngx_http_log_error(void *data, char *buf, size_t len);
/* NGX_HTTP_PARSE_ ... errors */
static char *header_errors[] = {
"client %s sent invalid method",
@ -67,127 +75,142 @@ static ngx_http_header_t headers_in[] = {
};
int ngx_http_init_connection(ngx_connection_t *c)
void ngx_http_init_connection(ngx_connection_t *c)
{
int event;
ngx_event_t *rev;
ngx_http_log_ctx_t *ctx;
ngx_http_log_ctx_t *lcx;
c->addr_text.data = ngx_palloc(c->pool, c->addr_text_max_len);
if (c->addr_text.data == NULL) {
ngx_http_close_connection(c);
return;
}
c->addr_text.len = ngx_sock_ntop(c->family, c->sockaddr,
c->addr_text.data, c->addr_text_max_len);
if (c->addr_text.len == 0) {
ngx_http_close_connection(c);
return;
}
lcx = ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t));
if (lcx == NULL) {
ngx_http_close_connection(c);
return;
}
lcx->client = c->addr_text.data;
lcx->action = "reading client request line";
c->log->data = lcx;
c->log->handler = ngx_http_log_error;
rev = c->read;
rev->event_handler = ngx_http_init_request;
rev->close_handler = ngx_http_close_connection;
c->write->close_handler = ngx_http_close_connection;
ngx_test_null(c->addr_text.data, ngx_palloc(c->pool, c->addr_text_max_len),
NGX_ERROR);
c->addr_text.len = ngx_sock_ntop(c->family, c->sockaddr,
c->addr_text.data, c->addr_text_max_len);
if (c->addr_text.len == 0) {
return NGX_ERROR;
}
ngx_test_null(ctx, ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)),
NGX_ERROR);
ctx->client = c->addr_text.data;
ctx->action = "reading client request line";
c->log->data = ctx;
c->log->handler = ngx_http_log_error;
#if (HAVE_DEFERRED_ACCEPT)
if (rev->ready) {
return ngx_http_init_request(rev);
/* deferred accept */
ngx_http_init_request(rev);
return;
}
#endif
ngx_add_timer(rev, c->post_accept_timeout);
rev->timer_set = 1;
#if (USE_KQUEUE)
return ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
#else
/* kqueue */
if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
/* aio, iocp, epoll */
ngx_http_init_request(rev);
return;
}
if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
return ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
/* kqueue */
event = NGX_CLEAR_EVENT;
} else {
/* select, poll, /dev/poll */
event = NGX_LEVEL_EVENT;
}
/* aio, iocp, epoll */
if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
return ngx_http_init_request(rev);
if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
ngx_http_close_connection(c);
}
/* select, poll, /dev/poll */
return ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
#endif /* USE_KQUEUE */
return;
}
static int ngx_http_init_request(ngx_event_t *rev)
static void ngx_http_init_request(ngx_event_t *rev)
{
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_conf_ctx_t *ctx;
c = (ngx_connection_t *) rev->data;
c->sent = 0;
ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)),
NGX_ERROR);
c->data = r;
r->connection = c;
r->file.fd = NGX_INVALID_FILE;
if (c->buffer == NULL) {
ngx_test_null(c->buffer,
ngx_create_temp_hunk(c->pool,
ngx_http_client_header_buffer_size,
0, 0),
NGX_ERROR);
} else {
r->header_read = 1;
c->buffer = ngx_create_temp_hunk(c->pool,
ngx_http_client_header_buffer_size,
0, 0);
if (c->buffer == NULL) {
ngx_http_close_connection(c);
return;
}
}
r->pipeline = c->pipeline;
r->header_in = c->buffer;
r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
if (r == NULL) {
ngx_http_close_connection(c);
return;
}
ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, c->log),
NGX_ERROR);
r->pool = ngx_create_pool(ngx_http_request_pool_size, c->log);
if (r->pool == NULL) {
ngx_http_close_connection(c);
return;
}
ngx_test_null(r->ctx,
ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module),
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR));
r->headers_out.headers = ngx_create_table(r->pool, 10);
if (r->headers_out.headers == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_http_close_connection(c);
return;
}
r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
if (r->ctx == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_http_close_connection(c);
return;
}
ctx = (ngx_http_conf_ctx_t *) c->ctx;
r->srv_conf = ctx->srv_conf;
r->loc_conf = ctx->loc_conf;
c->sent = 0;
c->data = r;
r->connection = c;
r->pipeline = c->pipeline;
r->header_in = c->buffer;
r->file.fd = NGX_INVALID_FILE;
r->headers_in.content_length_n = -1;
r->headers_out.headers = ngx_create_table(r->pool, 10);
r->headers_out.content_length = -1;
r->headers_out.last_modified_time = -1;
rev->event_handler = ngx_http_process_request;
r->state_handler = ngx_http_process_request_line;
rev->event_handler = ngx_http_process_request_line;
ngx_http_process_request_line(rev);
return ngx_http_process_request(rev);
return;
}
static int ngx_http_process_request(ngx_event_t *rev)
static void ngx_http_process_request_line(ngx_event_t *rev)
{
int n, rc;
ngx_event_t *wev;
int rc, offset;
ssize_t n;
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_log_ctx_t *lcx;
@ -195,139 +218,35 @@ static int ngx_http_process_request(ngx_event_t *rev)
c = (ngx_connection_t *) rev->data;
r = (ngx_http_request_t *) c->data;
ngx_log_debug(c->log, "http process request");
ngx_log_debug(rev->log, "http process request line");
if (rev->timedout) {
return ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
ngx_http_close_connection(c);
return;
}
do {
if (r->header_read) {
r->header_read = 0;
ngx_log_debug(c->log, "http preread %d" _
r->header_in->last - r->header_in->pos);
} else {
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) {
if (rev->timer_set) {
ngx_del_timer(rev);
} else {
rev->timer_set = 1;
}
ngx_add_timer(rev, ngx_http_client_header_timeout);
r->header_timeout_set = 1;
}
return NGX_AGAIN;
}
if (n == NGX_ERROR) {
return ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
}
ngx_log_debug(c->log, "http read %d" _ n);
if (n == 0) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client closed prematurely connection");
return ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
}
r->header_in->last += n;
}
/* the state handlers are called in the following order:
ngx_http_process_request_line(r)
ngx_http_process_request_headers(r) */
do {
rc = r->state_handler(r);
} while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last);
} while (rc == NGX_AGAIN
&& (rev->ready || ngx_event_flags & NGX_HAVE_AIO_EVENT));
if (rc >= NGX_OK) {
/* HTTP header done */
rev->event_handler = ngx_http_block_read;
if (rc != NGX_OK) {
return ngx_http_finalize_request(r, rc);
}
lcx = c->log->data;
lcx->action = "processing client request";
#if 0
wev = c->write;
ngx_add_timer(wev, 5000);
wev->delayed = 1;
wev->timer_set = 1;
#endif
rc = ngx_http_handler(r);
/* a handler does its own processing */
if (rc == NGX_DONE) {
return rc;
}
if (rc == NGX_ERROR) {
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
}
return ngx_http_finalize_request(r, rc);
n = ngx_http_read_request_header(r);
if (n == NGX_AGAIN || n == NGX_ERROR) {
return;
}
/* NGX_AGAIN */
if (!r->header_timeout_set) {
if (rev->timer_set) {
ngx_del_timer(rev);
} else {
rev->timer_set = 1;
}
ngx_add_timer(rev, ngx_http_client_header_timeout);
r->header_timeout_set = 1;
}
return rc;
}
static int ngx_http_process_request_line(ngx_http_request_t *r)
{
int rc, offset;
ngx_connection_t *c;
ngx_http_log_ctx_t *lcx;
rc = ngx_read_http_request_line(r);
c = r->connection;
/* a request line has been parsed successfully */
rc = ngx_parse_http_request_line(r);
if (rc == NGX_OK) {
/* the request line has been parsed successfully */
if (r->http_version >= NGX_HTTP_VERSION_10
&& ngx_http_large_client_header == 0
&& r->header_in->pos == r->header_in->end)
{
/* no space for "\r\n" at the end of the header */
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
return NGX_HTTP_REQUEST_URI_TOO_LARGE;
ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
return;
}
/* copy URI */
@ -338,20 +257,28 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
r->uri.len = r->uri_end - r->uri_start;
}
ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1),
NGX_HTTP_INTERNAL_SERVER_ERROR);
r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);
if (r->uri.data == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_http_close_connection(c);
return;
}
ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
r->request_line.len = r->request_end - r->request_start;
/* if the large client headers are enabled then
/* if the large client header is enabled then
we need to copy a request line */
if (ngx_http_large_client_header) {
ngx_test_null(r->request_line.data,
ngx_palloc(r->pool, r->request_line.len + 1),
NGX_HTTP_INTERNAL_SERVER_ERROR);
r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1);
if (r->request_line.data == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_http_close_connection(c);
return;
}
ngx_cpystrn(r->request_line.data, r->request_start,
r->request_line.len + 1);
@ -370,9 +297,12 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
r->exten.len = r->uri_end - r->uri_ext;
}
ngx_test_null(r->exten.data,
ngx_palloc(r->pool, r->exten.len + 1),
NGX_HTTP_INTERNAL_SERVER_ERROR);
r->exten.data = ngx_palloc(r->pool, r->exten.len + 1);
if (r->exten.data == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_http_close_connection(c);
return;
}
ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
}
@ -382,53 +312,45 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
if (r->args_start && r->uri_end > r->args_start) {
r->args.len = r->uri_end - r->args_start;
ngx_test_null(r->args.data,
ngx_palloc(r->pool, r->args.len + 1),
NGX_HTTP_INTERNAL_SERVER_ERROR);
r->args.data = ngx_palloc(r->pool, r->args.len + 1);
if (r->args.data == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_http_close_connection(c);
return;
}
ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1);
}
#if 1
if (r->exten.data == NULL) {
r->exten.data = "";
}
if (r->args.data == NULL) {
r->args.data = "";
}
ngx_log_debug(r->connection->log, "HTTP: %d, %d, '%s', '%s', '%s'" _
#if 1 /* DEBUG */
if (r->exten.data == NULL) { r->exten.data = ""; }
if (r->args.data == NULL) { r->args.data = ""; }
ngx_log_debug(c->log, "HTTP: %d, %d, '%s', '%s', '%s'" _
r->method _ r->http_version _
r->uri.data _ r->exten.data _ r->args.data);
if (r->exten.data[0] == '\0') {
r->exten.data = NULL;
}
if (r->args.data[0] == '\0') {
r->args.data = NULL;
}
if (r->exten.data[0] == '\0') { r->exten.data = NULL; }
if (r->args.data[0] == '\0') { r->args.data = NULL; }
#endif
lcx = r->connection->log->data;
lcx = c->log->data;
if (ngx_http_url_in_error_log) {
ngx_test_null(lcx->url,
ngx_palloc(r->pool, r->uri_end - r->uri_start + 1),
NGX_HTTP_INTERNAL_SERVER_ERROR);
lcx->url = ngx_palloc(r->pool, r->uri_end - r->uri_start + 1);
if (lcx->url == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_http_close_connection(c);
return;
}
ngx_cpystrn(lcx->url, r->uri_start, r->uri_end - r->uri_start + 1);
}
/* if we need to parse the headers then return NGX_AGAIN
becuase of HTTP/0.9 has no headers so return NGX_OK */
if (r->http_version == NGX_HTTP_VERSION_9) {
r->state_handler = NULL;
return NGX_OK;
/* STUB */ return;
}
r->headers_in.headers = ngx_create_table(r->pool, 10);
r->state_handler = ngx_http_process_request_headers;
lcx->action = "reading client request headers";
r->headers_in.headers = ngx_create_table(r->pool, 10);
if (ngx_http_large_client_header
&& r->header_in->pos == r->header_in->last)
@ -436,13 +358,13 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
r->header_in->pos = r->header_in->last = r->header_in->start;
}
return NGX_AGAIN;
/* there was error while a request line parsing */
} else if (rc != NGX_AGAIN) {
/* there was error while a request line parsing */
ngx_http_header_parse_error(r, rc);
return NGX_HTTP_BAD_REQUEST;
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
/* NGX_AGAIN: a request line parsing is still not complete */
@ -450,17 +372,18 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
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.
then we need to copy it to the start of the r->header_in hunk.
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() */
to the start of the r->header_in hunk in ngx_http_set_keepalive() */
if (ngx_http_large_client_header) {
offset = r->request_start - r->header_in->start;
if (offset == 0) {
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
return NGX_HTTP_REQUEST_URI_TOO_LARGE;
ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
return;
}
ngx_memcpy(r->header_in->start, r->request_start,
@ -481,22 +404,41 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
} else {
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
return NGX_HTTP_REQUEST_URI_TOO_LARGE;
ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
return;
}
}
return NGX_AGAIN;
rev->event_handler = ngx_http_process_request_headers;
ngx_http_process_request_headers(rev);
return;
}
static int ngx_http_process_request_headers(ngx_http_request_t *r)
static void ngx_http_process_request_headers(ngx_event_t *rev)
{
int rc, offset;
size_t len;
ssize_t n;
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_log_ctx_t *ctx;
if (rev->timedout) {
ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
ngx_http_close_connection(c);
return;
}
n = ngx_http_read_request_header(r);
if (n == NGX_AGAIN || n == NGX_ERROR) {
return;
}
for ( ;; ) {
rc = ngx_read_http_header_line(r, r->header_in);
rc = ngx_parse_http_header_line(r, r->header_in);
/* a header line has been parsed successfully */
@ -792,6 +734,53 @@ static int ngx_http_writer(ngx_event_t *wev)
}
static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
{
ssize_t n;
ngx_event_t *rev;
n = r->header_in->last - r->header_in->pos;
if (n > 0) {
return n;
}
n = ngx_event_recv(r->connection, r->header_in->last,
r->header_in->end - r->header_in->last);
if (n == NGX_AGAIN) {
if (!r->header_timeout_set) {
rev = r->connection->read;
if (rev->timer_set) {
ngx_del_timer(rev);
} else {
rev->timer_set = 1;
}
ngx_add_timer(rev, ngx_http_client_header_timeout);
r->header_timeout_set = 1;
}
return NGX_AGAIN;
}
if (n == 0) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client closed prematurely connection");
if (n == 0 || n == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
ngx_http_close_connection(c);
return NGX_ERROR;
}
r->header_in->last += n;
return n;
}
static int ngx_http_block_read(ngx_event_t *ev)
{
ngx_log_debug(ev->log, "http read blocked");
@ -1144,7 +1133,46 @@ static int ngx_http_lingering_close_handler(ngx_event_t *rev)
}
static int ngx_http_close_connection(ngx_event_t *ev)
static void ngx_http_close_connection(ngx_connection_t *c)
{
ngx_log_debug(c->log, "close connection: %d" _ c->fd);
if (c->fd == -1) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
return;
}
if (c->read->timer_set) {
ngx_del_timer(c->read);
c->read->timer_set = 0;
}
if (c->read->active) {
ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
}
if (c->write->timer_set) {
ngx_del_timer(c->write);
c->write->timer_set = 0;
}
if (c->write->active) {
ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
}
if (ngx_close_socket(c->fd) == -1) {
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
ngx_close_socket_n " failed");
}
c->fd = -1;
ngx_destroy_pool(c->pool);
return;
}
static int ngx_http_close_connection0(ngx_event_t *ev)
{
return ngx_event_close_connection(ev);
}

View File

@ -3,7 +3,7 @@
#include <ngx_core.h>
#include <ngx_http.h>
int ngx_read_http_request_line(ngx_http_request_t *r)
int ngx_parse_http_request_line(ngx_http_request_t *r)
{
char ch;
char *p;
@ -326,7 +326,7 @@ int ngx_read_http_request_line(ngx_http_request_t *r)
}
}
int ngx_read_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h)
int ngx_parse_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h)
{
char c, ch;
char *p;

80
src/os/unix/ngx_daemon.c Normal file
View File

@ -0,0 +1,80 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_log.h>
/* daemon in Linux */
int ngx_daemon(ngx_log_t *log)
{
int fd;
switch (fork()) {
case -1:
ngx_log_error(NGX_LOG_ALERT, log, errno, "fork() failed");
return NGX_ERROR;
case 0:
break;
default:
exit(0);
}
if (setsid() == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno, "setsid() failed");
return NGX_ERROR;
}
#if (__SVR4 || linux)
/* need HUP IGN ? check in Solaris and Linux */
switch (fork()) {
case -1:
ngx_log_error(NGX_LOG_ALERT, log, errno, "fork() failed");
return NGX_ERROR;
case 0:
break;
default:
exit(0);
}
#endif
umask(0);
#if 0
fd = open("/dev/null", O_RDWR);
if (fd == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno, "open(\"/dev/null\") failed");
return NGX_ERROR;
}
if (dup2(fd, STDIN_FILENO) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno, "dup2(STDIN) failed");
return NGX_ERROR;
}
if (dup2(fd, STDOUT_FILENO) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno, "dup2(STDOUT) failed");
return NGX_ERROR;
}
if (dup2(fd, STDERR_FILENO) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno, "dup2(STDERR) failed");
return NGX_ERROR;
}
if (fd > STDERR_FILENO) {
if (close(fd) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno, "close() failed");
return NGX_ERROR;
}
}
#endif
return NGX_OK;
}

View File

@ -0,0 +1,67 @@
#include <ngx_freebsd_init.h>
int freebsd_kern_osreldate;
int freebsd_hw_ncpu;
int freebsd_sendfile_nbytes_bug;
int ngx_os_init(ngx_log_t *log)
{
size_t size;
size = 4;
if (sysctlbyname("kern.osreldate",
&freebsd_kern_osreldate, &size, NULL, 0) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"sysctlbyname(kern.osreldate) failed");
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_INFO, log, 0,
"kern.osreldate: %d, built on %d",
freebsd_kern_osreldate, __FreeBSD_version);
#if HAVE_FREEBSD_SENDFILE
/* The determination of the sendfile() nbytes bug is complex enough.
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.
libc_r wrapper also emulates the bug in some versions.
There's no way to say exactly if a given FreeBSD version has bug.
Here is the algorithm that work at least for RELEASEs
and for syscalls only (not libc_r wrapper). */
/* detect was the new sendfile() version available at the compile time
to allow an old binary to run correctly on an updated FreeBSD system. */
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \
|| __FreeBSD_version == 460002 || __FreeBSD_version >= 500039
/* a new syscall without the bug */
freebsd_sendfile_nbytes_bug = 0;
#else
/* an old syscall that can have the bug */
freebsd_sendfile_nbytes_bug = 1;
#endif
#endif /* HAVE_FREEBSD_SENDFILE */
size = 4;
if (sysctlbyname("hw.ncpu", &freebsd_hw_ncpu, &size, NULL, 0) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"sysctlbyname(hw.ncpu) failed");
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_INFO, log, 0, "hw.ncpu: %d", freebsd_hw_ncpu);
return NGX_OK;
}

View File

@ -0,0 +1,18 @@
#ifndef _NGX_OS_INIT_H_INCLUDED_
#define _NGX_OS_INIT_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_log.h>
#include <sys/sysctl.h>
int ngx_os_init(ngx_log_t *log);
extern int freebsd_kern_osreldate;
extern int freebsd_hw_ncpu;
#endif /* _NGX_OS_INIT_H_INCLUDED_ */

View File

@ -11,57 +11,76 @@ extern int __isthreaded;
typedef int ngx_tid_t;
#define NGX_MAX_THREADS 10
static inline int ngx_gettid();
static char *stacks_start;
static char *stacks_end;
static size_t stack_size;
static char *last_stack;
static int last_thread;
static ngx_log_t *log;
static ngx_tid_t tids[NGX_MAX_THREADS];
static char *usrstack;
static int red_zone = 4096;
static size_t stack_size;
static size_t usable_stack_size;
static char *last_stack;
static int threads;
static int nthreads;
static ngx_tid_t *tids;
/* the thread-safe errno */
static int errnos[NGX_MAX_THREADS];
static int errno0; /* the main thread's errno */
static int *errnos;
int *__error()
{
return &errnos[ngx_gettid()];
int tid;
tid = ngx_gettid();
return tid ? &errnos[tid - 1] : &errno0;
}
int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg)
int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg,
ngx_log_t *log)
{
int id, err;
char *stack_top;
char *stack, *stack_top;
last_stack += stack_size;
stack_top = last_stack - red_zone;
if (stack_top > stacks_end) {
ngx_log_error(NGX_LOG_CRIT, log, 0, "no more threads allocated");
if (threads >= nthreads) {
ngx_log_error(NGX_LOG_CRIT, log, 0,
"no more than %d threads can be created", nthreads);
return NGX_ERROR;
}
#if 0
id = rfork(RFFDG|RFCFDG);
#elif 0
id = rfork_thread(RFFDG|RFCFDG, stack_top, func, arg);
#elif 0
id = rfork_thread(RFPROC|RFMEM, stack_top, func, arg);
#else
last_stack -= stack_size;
stack = mmap(last_stack, usable_stack_size, PROT_READ|PROT_WRITE,
MAP_STACK, -1, 0);
if (stack == MAP_FAILED) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"mmap(%08X:%d, MAP_STACK) thread stack failed",
last_stack, usable_stack_size);
return NGX_ERROR;
}
if (stack != last_stack) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "stack address was changed");
}
stack_top = stack + usable_stack_size;
printf("stack: %08X-%08X\n", stack, stack_top);
#if 1
id = rfork_thread(RFPROC|RFTHREAD|RFMEM, stack_top, func, arg);
#elif 1
id = rfork_thread(RFPROC|RFMEM, stack_top, func, arg);
#elif 1
id = rfork_thread(RFFDG|RFCFDG, stack_top, func, arg);
#else
id = rfork(RFFDG|RFCFDG);
#endif
err = errno;
if (id == -1) {
@ -69,7 +88,8 @@ int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg)
} else {
*tid = id;
tids[last_thread++] = id;
threads = (usrstack - stack_top) / stack_size;
tids[threads] = id;
/* allow the spinlock in libc malloc() */
__isthreaded = 1;
@ -79,14 +99,12 @@ int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg)
}
int ngx_init_thread_env(int n, size_t size, ngx_log_t *lg)
int ngx_init_thread_env(int n, size_t size, ngx_log_t *log)
{
int len, i;
char *usrstack, *zone;
int len;
char *rz, *zone;
log = lg;
/* create the thread stacks */
nthreads = n;
len = 4;
if (sysctlbyname("kern.usrstack", &usrstack, &len, NULL, 0) == -1) {
@ -96,41 +114,37 @@ int ngx_init_thread_env(int n, size_t size, ngx_log_t *lg)
}
printf("usrstack: %08X\n", usrstack);
printf("red zone: %08X\n", usrstack - (size + red_zone));
#if 1
/* red zone */
zone = mmap(usrstack - (size + red_zone), red_zone,
PROT_NONE, MAP_ANON, -1, 0);
rz = usrstack - (size + red_zone);
printf("red zone: %08X\n", rz);
zone = mmap(rz, red_zone, PROT_NONE, MAP_ANON, -1, 0);
if (zone == MAP_FAILED) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"mmap(%d, PROT_NONE, MAP_ANON) failed", red_zone);
"mmap(%08X:%d, PROT_NONE, MAP_ANON) red zone failed",
rz, red_zone);
return NGX_ERROR;
}
#else
zone = usrstack - (size + red_zone);
#endif
last_stack = zone + red_zone;
for (i = 0; i < n; i++) {
last_stack -= size + red_zone;
printf("stack: %08X\n", last_stack);
last_stack = mmap(last_stack, size, PROT_READ|PROT_WRITE,
MAP_STACK, -1, 0);
if (last_stack == MAP_FAILED) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"mmap(%d, MAP_STACK) failed", size);
return NGX_ERROR;
}
if (zone != rz) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "red zone address was changed");
}
stacks_start = last_stack;
stack_size = size + red_zone;
stacks_end = stacks_start + n * stack_size;
/* create the thread errno array */
ngx_test_null(errnos, ngx_calloc(n * sizeof(int), log), NGX_ERROR);
/* create the thread tid array */
ngx_test_null(tids, ngx_calloc((n + 1) * sizeof(ngx_tid_t), log),
NGX_ERROR);
tids[0] = ngx_getpid();
last_thread = 1;
threads = 1;
last_stack = zone + red_zone;
usable_stack_size = size;
stack_size = size + red_zone;
return NGX_OK;
}
@ -138,7 +152,18 @@ printf("stack: %08X\n", last_stack);
ngx_tid_t ngx_thread_self()
{
return tids[ngx_gettid()];
int tid;
ngx_tid_t pid;
tid = ngx_gettid();
if (tids[tid] == 0) {
pid = ngx_getpid();
tids[tid] = pid;
return pid;
}
return tids[tid];
}
@ -146,7 +171,11 @@ static inline int ngx_gettid()
{
char *sp;
if (stack_size == 0) {
return 0;
}
__asm__ ("mov %%esp, %0" : "=q" (sp));
return (sp > stacks_end) ? 0 : ((sp - stacks_start) / stack_size + 1);
return (usrstack - sp) / stack_size;
}

20
src/os/unix/ngx_init.c Normal file
View File

@ -0,0 +1,20 @@
int ngx_unix_init(ngx_log_t *log)
{
struct rlimit rlmt;
if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"getrlimit(RLIMIT_NOFILE) failed)");
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_INFO, log, 0,
"getrlimit(RLIMIT_NOFILE): %d", rlmt.rlim_cur);
RLIM_INFINITY
max_connections =< rlmt.rlim_cur;
return NGX_OK;
}