mirror of
https://github.com/nginx/nginx.git
synced 2024-11-23 20:19:02 +08:00
nginx-0.0.1-2002-08-15-21:20:26 import
This commit is contained in:
parent
6de5c2cb63
commit
0c331d9f66
@ -25,7 +25,7 @@ int ngx_http_init_connection(void *data);
|
||||
|
||||
int ngx_max_conn = 512;
|
||||
struct sockaddr_in ngx_addr = {0, AF_INET, 0, 0, 0};
|
||||
|
||||
int ngx_backlog = 0;
|
||||
|
||||
ngx_pool_t ngx_pool;
|
||||
ngx_log_t ngx_log;
|
||||
@ -35,10 +35,12 @@ ngx_server_t ngx_server;
|
||||
int main(int argc, char *const *argv)
|
||||
{
|
||||
char addr_text[22];
|
||||
ngx_socket_t fd;
|
||||
ngx_socket_t s;
|
||||
ngx_listen_t ls;
|
||||
int reuseaddr = 1;
|
||||
#if (WIN32)
|
||||
WSADATA wsd;
|
||||
unsigned long nb = 1;
|
||||
#endif
|
||||
|
||||
|
||||
@ -61,16 +63,45 @@ int main(int argc, char *const *argv)
|
||||
"WSAStartup failed");
|
||||
#endif
|
||||
|
||||
/* for each listening socket */
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == -1)
|
||||
ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
|
||||
"socket failed");
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *) &reuseaddr, sizeof(int)) == -1)
|
||||
ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
|
||||
"setsockopt (SO_REUSEADDR) failed");
|
||||
|
||||
#if (WIN32)
|
||||
if (ioctlsocket(s, FIONBIO, &nb) == -1)
|
||||
ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
|
||||
"ioctlsocket (FIONBIO) failed");
|
||||
#else
|
||||
if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
|
||||
ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
|
||||
"fcntl (O_NONBLOCK) failed");
|
||||
#endif
|
||||
|
||||
ngx_snprintf(ngx_cpystrn(addr_text, inet_ntoa(ngx_addr.sin_addr), 16),
|
||||
7, ":%d", ntohs(ngx_addr.sin_port));
|
||||
fd = ngx_listen((struct sockaddr *) &ngx_addr, -1, &ngx_log, addr_text);
|
||||
|
||||
if (bind(s, (struct sockaddr *) &ngx_addr,
|
||||
sizeof(struct sockaddr_in)) == -1)
|
||||
ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
|
||||
"bind to %s failed", addr_text);
|
||||
|
||||
if (listen(s, ngx_backlog) == -1)
|
||||
ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
|
||||
"listen to %s failed", addr_text);
|
||||
|
||||
ngx_server.buff_size = 1024;
|
||||
ngx_server.handler = ngx_http_init_connection;
|
||||
|
||||
/* daemon */
|
||||
|
||||
ls.fd = fd;
|
||||
ls.fd = s;
|
||||
ls.server = &ngx_server;
|
||||
ls.log = &ngx_log;
|
||||
|
||||
|
@ -48,8 +48,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
|
@ -8,12 +8,12 @@ ngx_hunk_t *ngx_get_hunk(ngx_pool_t *pool, int size, int before, int after)
|
||||
ngx_hunk_t *h = ngx_palloc(pool, sizeof(ngx_hunk_t));
|
||||
|
||||
#ifndef OFF_EQUAL_PTR
|
||||
h->pos.f = h->last.f = 0;
|
||||
h->pos.file = h->last.file = 0;
|
||||
#endif
|
||||
|
||||
h->pre_start = ngx_palloc(pool, size + before + after);
|
||||
h->start = h->pos.p = h->last.p = h->pre_start + before;
|
||||
h->end = h->last.p + size;
|
||||
h->start = h->pos.mem = h->last.mem = h->pre_start + before;
|
||||
h->end = h->last.mem + size;
|
||||
h->post_end = h->end + after;
|
||||
|
||||
h->type = NGX_HUNK_TEMP;
|
||||
@ -28,21 +28,22 @@ ngx_hunk_t *ngx_get_hunk_before(ngx_pool_t *pool, ngx_hunk_t *hunk, int size)
|
||||
ngx_hunk_t *h = ngx_palloc(pool, sizeof(ngx_hunk_t));
|
||||
|
||||
#ifndef OFF_EQUAL_PTR
|
||||
h->pos.f = h->last.f = 0;
|
||||
h->pos.file = h->last.file = 0;
|
||||
#endif
|
||||
|
||||
if (hunk->type & NGX_HUNK_TEMP && hunk->pos.p - hunk->pre_start >= size) {
|
||||
if (hunk->type & NGX_HUNK_TEMP && hunk->pos.mem - hunk->pre_start >= size) {
|
||||
/* keep hunk->start unchanged - used in restore */
|
||||
h->pre_start = hunk->pre_start;
|
||||
h->end = h->post_end = hunk->pre_start = hunk->pos.p;
|
||||
h->start = h->pos.p = h->last.p = h->end - size;
|
||||
h->end = h->post_end = hunk->pre_start = hunk->pos.mem;
|
||||
h->start = h->pos.mem = h->last.mem = h->end - size;
|
||||
|
||||
h->type = NGX_HUNK_TEMP;
|
||||
h->tag = 0;
|
||||
h->fd = (ngx_file_t) -1;
|
||||
|
||||
} else {
|
||||
h->pre_start = h->start = h->pos.p = h->last.p = ngx_palloc(pool, size);
|
||||
h->pre_start = h->start = h->pos.mem = h->last.mem
|
||||
= ngx_palloc(pool, size);
|
||||
h->end = h->post_end = h->start + size;
|
||||
|
||||
h->type = NGX_HUNK_TEMP;
|
||||
@ -58,22 +59,23 @@ ngx_hunk_t *ngx_get_hunk_after(ngx_pool_t *pool, ngx_hunk_t *hunk, int size)
|
||||
ngx_hunk_t *h = ngx_palloc(pool, sizeof(ngx_hunk_t));
|
||||
|
||||
#ifndef OFF_EQUAL_PTR
|
||||
h->pos.f = h->last.f = 0;
|
||||
h->pos.file = h->last.file = 0;
|
||||
#endif
|
||||
|
||||
if (hunk->type & NGX_HUNK_TEMP
|
||||
&& hunk->last.p == hunk->end
|
||||
&& hunk->last.mem == hunk->end
|
||||
&& hunk->post_end - hunk->end >= size)
|
||||
{
|
||||
h->post_end = hunk->post_end;
|
||||
h->pre_start = h->start = h->pos.p = h->last.p = hunk->post_end =
|
||||
hunk->last.p;
|
||||
h->pre_start = h->start = h->pos.mem = h->last.mem = hunk->post_end =
|
||||
hunk->last.mem;
|
||||
h->type = NGX_HUNK_TEMP;
|
||||
h->tag = 0;
|
||||
h->fd = (ngx_file_t) -1;
|
||||
|
||||
} else {
|
||||
h->pre_start = h->start = h->pos.p = h->last.p = ngx_palloc(pool, size);
|
||||
h->pre_start = h->start = h->pos.mem = h->last.mem =
|
||||
ngx_palloc(pool, size);
|
||||
h->end = h->post_end = h->start + size;
|
||||
|
||||
h->type = NGX_HUNK_TEMP;
|
||||
|
@ -7,33 +7,39 @@
|
||||
#include <ngx_alloc.h>
|
||||
|
||||
|
||||
/* type */
|
||||
/* hunk type */
|
||||
|
||||
/* temp means that hunk's content can be changed */
|
||||
/* other type means that hunk's content can not be changed */
|
||||
#define NGX_HUNK_TEMP 0x0001
|
||||
#define NGX_HUNK_MEMORY 0x0002
|
||||
#define NGX_HUNK_MMAP 0x0004
|
||||
#define NGX_HUNK_FILE 0x0008
|
||||
#define NGX_HUNK_FLUSH 0x0010
|
||||
/* in thread state flush means to write the hunk completely before return
|
||||
in event-driven state flush means to start to write the hunk */
|
||||
#define NGX_HUNK_LAST 0x0020
|
||||
|
||||
#define NGX_HUNK_IN_MEMORY (NGX_HUNK_TEMP | NGX_HUNK_MEMORY | NGX_HUNK_MMAP )
|
||||
#define NGX_HUNK_TYPE 0x0ffff
|
||||
/* hunk flags */
|
||||
|
||||
/* flags */
|
||||
#define NGX_HUNK_SHUTDOWN 0x10000
|
||||
/* in thread state flush means to write the hunk completely before return */
|
||||
/* in event state flush means to start to write the hunk */
|
||||
#define NGX_HUNK_FLUSH 0x0100
|
||||
/* last hunk */
|
||||
#define NGX_HUNK_LAST 0x0200
|
||||
/* can be used with NGX_HUNK_LAST only */
|
||||
#define NGX_HUNK_SHUTDOWN 0x0400
|
||||
|
||||
|
||||
#define NGX_HUNK_IN_MEMORY (NGX_HUNK_TEMP|NGX_HUNK_MEMORY|NGX_HUNK_MMAP)
|
||||
|
||||
|
||||
|
||||
typedef struct ngx_hunk_s ngx_hunk_t;
|
||||
struct ngx_hunk_s {
|
||||
union {
|
||||
char *p; /* start of current data */
|
||||
off_t f;
|
||||
char *mem; /* start of current data */
|
||||
off_t file;
|
||||
} pos;
|
||||
union {
|
||||
char *p; /* end of current data */
|
||||
off_t f;
|
||||
char *mem; /* end of current data */
|
||||
off_t file;
|
||||
} last;
|
||||
int type;
|
||||
char *start; /* start of hunk */
|
||||
|
@ -45,6 +45,7 @@ void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err,
|
||||
len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1,
|
||||
" [%s] (%d)",
|
||||
err_levels[level], err);
|
||||
else
|
||||
len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1,
|
||||
" [%s] (%X)",
|
||||
err_levels[level], err);
|
||||
|
@ -1,17 +1,41 @@
|
||||
|
||||
|
||||
event = WSACreateEvent(void);
|
||||
WSAEventSelect(s, event, FD_ACCEPT);
|
||||
|
||||
|
||||
int ngx_overlapped_process_events(ngx_log_t *log)
|
||||
{
|
||||
if (acceptex)
|
||||
event = SleepEx(timer, 1);
|
||||
n = SleepEx(timer, 1);
|
||||
else
|
||||
event = WSAWaitForMultipleEvents(n_events, events, 0, timer, 1);
|
||||
n = WSAWaitForMultipleEvents(nevents, events, 0, timer, 1);
|
||||
|
||||
if (event == WSA_IO_COMPLETION)
|
||||
look ready array
|
||||
if (n == WSA_WAIT_TIMEOUT)
|
||||
close some event;
|
||||
|
||||
if (n == WSA_IO_COMPLETION)
|
||||
again
|
||||
|
||||
/* try it with AcceptEx() on NT to detect connected sockets */
|
||||
if (!acceptex) {
|
||||
WSAEnumNetworkEvents(
|
||||
sockets[n - WSA_WAIT_EVENT_0],
|
||||
events[n - WSA_WAIT_EVENT_0],
|
||||
net_events);
|
||||
|
||||
if (net_events.lNetworkEvents & FD_ACCEPT) {
|
||||
if (net_events.iErrorCode[FD_ACCEPT_BIT] != 0)
|
||||
accept error
|
||||
again
|
||||
|
||||
ngx_event_accept(); OR post AcceptEx();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK overlapped_completion_procedure(DWORD error, DWORD nbytes,
|
||||
LPWSAOVERLAPPED overlapped, DWORD flags)
|
||||
{
|
||||
push overlapped;
|
||||
run event handler
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ struct ngx_event_s {
|
||||
void *context;
|
||||
char *action;
|
||||
|
||||
ngx_event_t *prev; /* queue in select(), poll() */
|
||||
ngx_event_t *next;
|
||||
ngx_event_t *prev; /* queue in select(), poll(), mutex(), */
|
||||
ngx_event_t *next; /* aio_read(), aio_write() */
|
||||
|
||||
int (*timer_handler)(ngx_event_t *ev);
|
||||
ngx_event_t *timer_prev;
|
||||
@ -52,7 +52,7 @@ struct ngx_event_s {
|
||||
#endif
|
||||
#if (HAVE_KQUEUE)
|
||||
unsigned eof:1;
|
||||
int errno;
|
||||
int error;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -70,12 +70,20 @@ typedef struct {
|
||||
int (*add)(ngx_event_t *ev, int event, u_int flags);
|
||||
int (*del)(ngx_event_t *ev, int event);
|
||||
int (*process)(ngx_log_t *log);
|
||||
/*
|
||||
int (*read)(ngx_event_t *ev, char *buf, size_t size);
|
||||
/*
|
||||
int (*write)(ngx_event_t *ev, char *buf, size_t size);
|
||||
*/
|
||||
} ngx_event_actions_t;
|
||||
|
||||
/*
|
||||
|
||||
NGX_LEVEL_EVENT (default) select, poll, kqueue
|
||||
requires to read whole data
|
||||
NGX_ONESHOT_EVENT kqueue
|
||||
NGX_CLEAR_EVENT kqueue
|
||||
|
||||
*/
|
||||
|
||||
#if (HAVE_KQUEUE)
|
||||
|
||||
@ -99,15 +107,21 @@ typedef struct {
|
||||
|
||||
|
||||
#if (USE_KQUEUE)
|
||||
|
||||
#define ngx_init_events ngx_kqueue_init
|
||||
#define ngx_process_events ngx_kqueue_process_events
|
||||
#define ngx_add_event ngx_kqueue_add_event
|
||||
#define ngx_del_event ngx_kqueue_del_event
|
||||
#define ngx_event_recv ngx_event_recv_core
|
||||
|
||||
#else
|
||||
|
||||
#define ngx_init_events (ngx_event_init[ngx_event_type])
|
||||
#define ngx_process_events ngx_event_actions.process
|
||||
#define ngx_add_event ngx_event_actions.add
|
||||
#define ngx_del_event ngx_event_actions.del
|
||||
#define ngx_event_recv ngx_event_recv_core
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
14
src/event/ngx_event_mutex.c
Normal file
14
src/event/ngx_event_mutex.c
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
spinlock_max depend on CPU number and mutex type.
|
||||
1 CPU 1
|
||||
ngx_malloc_mutex 1000 ?
|
||||
|
||||
|
||||
int ngx_event_mutex_trylock(ngx_mutex_t *mtx)
|
||||
{
|
||||
for(i = mtx->spinlock_max; i; i--)
|
||||
if (trylock(mtx->lock))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
@ -2,23 +2,28 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_errno.h>
|
||||
#include <ngx_log.h>
|
||||
#include <ngx_recv.h>
|
||||
#include <ngx_connection.h>
|
||||
|
||||
int ngx_event_recv(ngx_connection_t *c, char *buf, size_t size)
|
||||
int ngx_event_recv_core(ngx_event_t *ev, char *buf, size_t size)
|
||||
{
|
||||
int n;
|
||||
ngx_err_t err;
|
||||
ngx_event_t *ev = c->read;
|
||||
int n;
|
||||
ngx_err_t err;
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = (ngx_connection_t *) ev->data;
|
||||
|
||||
#if (HAVE_KQUEUE)
|
||||
ngx_log_debug(ev->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _
|
||||
ev->eof _ ev->available _ ev->error);
|
||||
#if !(USE_KQUEUE)
|
||||
if (ngx_event_type == NGX_KQUEUE_EVENT)
|
||||
#endif
|
||||
if (ev->eof && ev->available == 0) {
|
||||
if (ev->error) {
|
||||
ngx_log_error(NGX_LOG_ERR, ev->log, ev->error,
|
||||
"ngx_event_recv: recv failed while %s",
|
||||
ev->log->action);
|
||||
"ngx_event_recv: recv failed while %s",
|
||||
ev->log->action);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -27,7 +32,7 @@ int ngx_event_recv(ngx_connection_t *c, char *buf, size_t size)
|
||||
}
|
||||
#endif
|
||||
|
||||
n = recv(c->fd, buf, size, 0);
|
||||
n = ngx_recv(c->fd, buf, size, 0);
|
||||
|
||||
if (n == -1) {
|
||||
err = ngx_socket_errno;
|
@ -10,8 +10,8 @@
|
||||
#include <ngx_event_write.h>
|
||||
|
||||
|
||||
ngx_chain_t *ngx_event_writer(ngx_connection_t *cn, ngx_chain_t *in,
|
||||
off_t flush)
|
||||
ngx_chain_t *ngx_event_write(ngx_connection_t *cn, ngx_chain_t *in,
|
||||
off_t flush)
|
||||
{
|
||||
int rc;
|
||||
char *last;
|
||||
@ -34,25 +34,21 @@ ngx_chain_t *ngx_event_writer(ngx_connection_t *cn, ngx_chain_t *in,
|
||||
header->nelts = 0;
|
||||
trailer->nelts = 0;
|
||||
|
||||
if (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)) {
|
||||
if (ch->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
last = NULL;
|
||||
iov = NULL;
|
||||
|
||||
while (ch
|
||||
&& (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)))
|
||||
while (ch && (ch->hunk->type & NGX_HUNK_IN_MEMORY))
|
||||
{
|
||||
if (ch->hunk->type & NGX_HUNK_FLUSH)
|
||||
continue;
|
||||
|
||||
if (last == ch->hunk->pos.p) {
|
||||
iov->ngx_iov_len += ch->hunk->last.p - ch->hunk->pos.p;
|
||||
if (last == ch->hunk->pos.mem) {
|
||||
iov->ngx_iov_len += ch->hunk->last.mem - ch->hunk->pos.mem;
|
||||
|
||||
} else {
|
||||
ngx_test_null(iov, ngx_push_array(header),
|
||||
(ngx_chain_t *) -1);
|
||||
iov->ngx_iov_base = ch->hunk->pos.p;
|
||||
iov->ngx_iov_len = ch->hunk->last.p - ch->hunk->pos.p;
|
||||
last = ch->hunk->last.p;
|
||||
iov->ngx_iov_base = ch->hunk->pos.mem;
|
||||
iov->ngx_iov_len = ch->hunk->last.mem - ch->hunk->pos.mem;
|
||||
last = ch->hunk->last.mem;
|
||||
}
|
||||
|
||||
ch = ch->next;
|
||||
@ -70,25 +66,23 @@ ngx_chain_t *ngx_event_writer(ngx_connection_t *cn, ngx_chain_t *in,
|
||||
&sent);
|
||||
} else {
|
||||
#endif
|
||||
if (ch && ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)) {
|
||||
if (ch && ch->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
last = NULL;
|
||||
iov = NULL;
|
||||
|
||||
while (ch
|
||||
&& (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)))
|
||||
{
|
||||
if (ch->hunk->type & NGX_HUNK_FLUSH)
|
||||
continue;
|
||||
while (ch && (ch->hunk->type & NGX_HUNK_IN_MEMORY)) {
|
||||
|
||||
if (last == ch->hunk->pos.p) {
|
||||
iov->ngx_iov_len += ch->hunk->last.p - ch->hunk->pos.p;
|
||||
if (last == ch->hunk->pos.mem) {
|
||||
iov->ngx_iov_len +=
|
||||
ch->hunk->last.mem - ch->hunk->pos.mem;
|
||||
|
||||
} else {
|
||||
ngx_test_null(iov, ngx_push_array(trailer),
|
||||
(ngx_chain_t *) -1);
|
||||
iov->ngx_iov_base = ch->hunk->pos.p;
|
||||
iov->ngx_iov_len = ch->hunk->last.p - ch->hunk->pos.p;
|
||||
last = ch->hunk->last.p;
|
||||
iov->ngx_iov_base = ch->hunk->pos.mem;
|
||||
iov->ngx_iov_len =
|
||||
ch->hunk->last.mem - ch->hunk->pos.mem;
|
||||
last = ch->hunk->last.mem;
|
||||
}
|
||||
|
||||
ch = ch->next;
|
||||
@ -98,8 +92,8 @@ ngx_chain_t *ngx_event_writer(ngx_connection_t *cn, ngx_chain_t *in,
|
||||
if (file) {
|
||||
rc = ngx_sendfile(cn->fd,
|
||||
(ngx_iovec_t *) header->elts, header->nelts,
|
||||
file->fd, file->pos.f,
|
||||
(size_t) (file->last.f - file->pos.f),
|
||||
file->fd, file->pos.file,
|
||||
(size_t) (file->last.file - file->pos.file),
|
||||
(ngx_iovec_t *) trailer->elts, trailer->nelts,
|
||||
&sent, cn->log);
|
||||
} else {
|
||||
@ -117,17 +111,18 @@ ngx_chain_t *ngx_event_writer(ngx_connection_t *cn, ngx_chain_t *in,
|
||||
flush -= sent;
|
||||
|
||||
for (ch = in; ch && !(ch->hunk->type & NGX_HUNK_LAST); ch = ch->next) {
|
||||
if (sent >= ch->hunk->last.f - ch->hunk->pos.f) {
|
||||
sent -= ch->hunk->last.f - ch->hunk->pos.f;
|
||||
ch->hunk->last.f = ch->hunk->pos.f;
|
||||
if (sent >= ch->hunk->last.file - ch->hunk->pos.file) {
|
||||
sent -= ch->hunk->last.file - ch->hunk->pos.file;
|
||||
ch->hunk->last.file = ch->hunk->pos.file;
|
||||
continue;
|
||||
}
|
||||
|
||||
ch->hunk->pos.f += sent;
|
||||
ch->hunk->pos.file += sent;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (flush > 0);
|
||||
/* flush hunks if threaded state */
|
||||
} while (cn->write->context && flush > 0);
|
||||
|
||||
ngx_destroy_array(trailer);
|
||||
ngx_destroy_array(header);
|
||||
|
55
src/http/modules/ngx_http_header_filter.c
Normal file
55
src/http/modules/ngx_http_header_filter.c
Normal file
@ -0,0 +1,55 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
char *line;
|
||||
} line;
|
||||
|
||||
|
||||
static line http_codes[] = {
|
||||
{ 6, "200 OK" }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
int status;
|
||||
ngx_hunk_t *h;
|
||||
|
||||
ngx_test_null(h, ngx_get_hunk(r->pool, 1024, 0, 64), NGX_HTTP_FILTER_ERROR);
|
||||
|
||||
status = r->headers_out->status - GX_HTTP_OK;
|
||||
|
||||
ngx_memcpy(h->pos.mem, "HTTP/1.0 ", 9);
|
||||
h->pos.mem += 9;
|
||||
ngx_memcpy(h->pos.mem, http_codes[status].line, http_codes[status].len);
|
||||
h->pos.mem += http_codes[status].len;
|
||||
*(h->pos.mem++) = CR; *(h->pos.mem++) = LF;
|
||||
|
||||
memcpy(h->pos.mem, "Date: ", 6);
|
||||
h->pos.mem += 6;
|
||||
h->pos.mem += ngx_http_get_time(h->pos.mem, time());
|
||||
*(h->pos.mem++) = CR; *(h->pos.mem++) = LF;
|
||||
|
||||
/* 2^64 is 20 characters */
|
||||
if (r->headers_out->content_length)
|
||||
h->pos.mem += ngx_snprintf(h->pos.mem, 49, "Content-Length: %d" CRLF,
|
||||
r->headers_out->content_length);
|
||||
|
||||
/* check */
|
||||
|
||||
memcpy(h->pos.mem, "Server: ", 8);
|
||||
h->pos.mem += 8;
|
||||
if (r->headers_out->server) {
|
||||
h->pos.mem = ngx_cpystrn(h->pos.mem, r->headers_out->server,
|
||||
h->last.mem - h->pos.mem);
|
||||
check space
|
||||
} else {
|
||||
ngx_memcpy(h->pos.mem, NGINX_VER, sizeof(NGINX_VER));
|
||||
h->pos.mem += sizeof(NGINX_VER);
|
||||
}
|
||||
*(h->pos.mem++) = CR; *(h->pos.mem++) = LF;
|
||||
|
||||
}
|
@ -20,10 +20,11 @@ int ngx_http_index_handler(ngx_http_request_t *r)
|
||||
ngx_get_module_loc_conf(r, &ngx_http_index_handler_module);
|
||||
|
||||
index_len = (*(r->uri_end - 1) == '/') ? cf->max_index_len : 0;
|
||||
name = ngx_palloc(r->pool, r->uri_end - r->uri_start + index_len
|
||||
+ r->server->doc_root_len);
|
||||
if (name == NULL)
|
||||
return NGX_ERROR;
|
||||
|
||||
ngx_test_null(name,
|
||||
ngx_palloc(r->pool, r->uri_end - r->uri_start + index_len
|
||||
+ r->server->doc_root_len),
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
|
||||
loc = ngx_cpystrn(name, r->server->doc_root, r->server->doc_root_len);
|
||||
file = ngx_cpystrn(loc, r->uri_start, r->uri_end - r->uri_start + 1);
|
||||
@ -39,7 +40,7 @@ int ngx_http_index_handler(ngx_http_request_t *r)
|
||||
if (err == NGX_ENOENT)
|
||||
return NGX_HTTP_NOT_FOUND;
|
||||
else
|
||||
return NGX_ERROR;
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_is_dir(r->stat)) {
|
||||
|
101
src/http/modules/ngx_http_static_handler.c
Normal file
101
src/http/modules/ngx_http_static_handler.c
Normal file
@ -0,0 +1,101 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
|
||||
#include <ngx_strings.h>
|
||||
#include <ngx_open.h>
|
||||
#include <ngx_stat.h>
|
||||
|
||||
#include <ngx_http.h>
|
||||
|
||||
int ngx_http_static_handler(ngx_http_request_t *r)
|
||||
{
|
||||
int index_len, err, i;
|
||||
char *name, *loc, *file
|
||||
ngx_file_t fd;
|
||||
|
||||
ngx_http_header_out_t out;
|
||||
ngx_http_event_static_handler_loc_conf_t *cf;
|
||||
|
||||
cf = (ngx_http_event_static_handler_loc_conf_t *)
|
||||
ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module);
|
||||
|
||||
ngx_assert(r->fd, return NGX_HTTP_INTERNAL_SERVER_ERROR,
|
||||
r->connection->log, "ngx_http_static_handler: no file");
|
||||
|
||||
out.status = NGX_HTTP_OK;
|
||||
out.content_length = r->stat.sb_size;
|
||||
out.last_modified = r->stat.sb_mtime;
|
||||
|
||||
/* */
|
||||
out.content_type = "text/html";
|
||||
|
||||
rc = ngx_send_http_header(&out);
|
||||
if (r->header_only)
|
||||
return rc;
|
||||
|
||||
/* NGX_HTTP_INTERNAL_SERVER_ERROR is too late */
|
||||
|
||||
ngx_test_null(h, ngx_create_hunk(r->pool), NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
h->type = NGX_HUNK_FILE | NGX_HUNK_LAST;
|
||||
h->fd = r->fd;
|
||||
h->pos.file = 0;
|
||||
h->end.file = r->stat.sb_size;
|
||||
|
||||
ngx_test_null(ch, ngx_create_chain(r->pool),
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
ch->hunk = h;
|
||||
ch->next = NULL;
|
||||
|
||||
return ngx_http_filter(ch);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
static void *ngx_create_index_config()
|
||||
{
|
||||
ngx_http_index_handler_loc_conf_t *cf;
|
||||
|
||||
ngx_check_null(cf, ngx_alloc(p, sizeof(ngx_http_index_handler_loc_conf)),
|
||||
NULL);
|
||||
|
||||
cf->indices = ngx_create_array(p, sizeof(ngx_http_index_t), 5);
|
||||
if (cf->indices == NULL)
|
||||
return NULL;
|
||||
|
||||
cf->max_index_len = 0;
|
||||
|
||||
return cf;
|
||||
}
|
||||
|
||||
static void *ngx_merge_index_config()
|
||||
{
|
||||
if (p->indices->nelts > 0) {
|
||||
|
||||
copy and check dups
|
||||
|
||||
if (c->max_index_len < c->max_index_len)
|
||||
c->max_index_len < c->max_index_len);
|
||||
}
|
||||
}
|
||||
|
||||
static void *ngx_set_index()
|
||||
{
|
||||
if (*conf == NULL) {
|
||||
cf = ngx_create_index_conf();
|
||||
if (cf == NULL)
|
||||
return "can not create config";
|
||||
}
|
||||
|
||||
while (args) {
|
||||
index = ngx_push_array(cf->indices);
|
||||
index->name = arg;
|
||||
index->len = ngx_strlen(arg) + 1;
|
||||
|
||||
if (cf->max_index_len < index->len)
|
||||
cf->max_index_len = index->len;
|
||||
}
|
||||
|
||||
*conf = cf;
|
||||
}
|
||||
|
||||
*/
|
@ -22,6 +22,13 @@
|
||||
#define NGX_HTTP_OK 200
|
||||
|
||||
|
||||
typedef struct {
|
||||
void *ctx; /* STUB */
|
||||
} ngx_http_module_t;
|
||||
|
||||
/* STUB */
|
||||
#define ngx_get_module_ctx(r, module) (module)->ctx
|
||||
|
||||
typedef struct {
|
||||
char *buff;
|
||||
char *pos;
|
||||
|
@ -38,10 +38,7 @@ int ngx_http_init_connection(ngx_connection_t *c)
|
||||
ngx_event_t *ev;
|
||||
|
||||
ev = c->read;
|
||||
/*
|
||||
ev->event_handler = ngx_http_init_request;
|
||||
*/
|
||||
ev->event_handler = NULL;
|
||||
ev->log->action = "reading client request line";
|
||||
|
||||
ngx_log_debug(ev->log, "ngx_http_init_connection: entered");
|
||||
@ -62,8 +59,6 @@ int ngx_http_init_connection(ngx_connection_t *c)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
int ngx_http_init_request(ngx_event_t *ev)
|
||||
{
|
||||
ngx_connection_t *c = (ngx_connection_t *) ev->data;
|
||||
@ -71,11 +66,13 @@ int ngx_http_init_request(ngx_event_t *ev)
|
||||
|
||||
ngx_log_debug(ev->log, "ngx_http_init_request: entered");
|
||||
|
||||
ngx_test_null(c->pool, ngx_create_pool(16384, ev->log), -1);
|
||||
ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)), -1);
|
||||
|
||||
c->data = r;
|
||||
r->connection = c;
|
||||
|
||||
ngx_test_null(r->pool, ngx_create_pool(16384, ev->log), -1);
|
||||
ngx_test_null(r->buff, ngx_palloc(r->pool, sizeof(ngx_buff_t)), -1);
|
||||
ngx_test_null(r->buff->buff,
|
||||
ngx_pcalloc(r->pool, sizeof(c->server->buff_size)), -1);
|
||||
@ -99,33 +96,15 @@ int ngx_http_process_request(ngx_event_t *ev)
|
||||
|
||||
ngx_log_debug(ev->log, "http process request");
|
||||
|
||||
ngx_log_debug(ev->log, "http: eof:%d, avail:%d", ev->eof, ev->available);
|
||||
n = ngx_event_recv(ev, r->buff->last, r->buff->end - r->buff->last);
|
||||
|
||||
if (ev->eof && ev->available == 0) {
|
||||
if (ev->err_no)
|
||||
ngx_log_error(NGX_LOG_ERR, ev->log, ev->err_no,
|
||||
"ngx_http_process_request: "
|
||||
"read failed while %s", ev->action);
|
||||
if (n == -2)
|
||||
return 0;
|
||||
|
||||
if (n == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((n = read(c->fd, r->buff->last, r->buff->end - r->buff->last)) == -1) {
|
||||
|
||||
if (errno == NGX_EWOULDBLOCK) {
|
||||
ngx_log_error(NGX_LOG_INFO, ev->log, errno,
|
||||
"ngx_http_process_request: "
|
||||
"EAGAIN while %s", ev->action);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, ev->log, errno,
|
||||
"ngx_http_process_request: "
|
||||
"read failed while %s", ev->action);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ngx_log_debug(ev->log, "http read %d", n);
|
||||
ngx_log_debug(ev->log, "http read %d" _ n);
|
||||
|
||||
if (n == 0) {
|
||||
if (ev->unexpected_eof) {
|
||||
@ -138,8 +117,6 @@ int ngx_http_process_request(ngx_event_t *ev)
|
||||
return ngx_http_close_request(ev);
|
||||
}
|
||||
|
||||
n == r->buff->end - r->buff->last;
|
||||
|
||||
if (!ev->read_discarded) {
|
||||
r->buff->last += n;
|
||||
|
||||
@ -168,8 +145,8 @@ static int ngx_process_http_request_line(ngx_http_request_t *r)
|
||||
|
||||
if ((n = ngx_read_http_request_line(r)) == 1) {
|
||||
*r->uri_end = '\0';
|
||||
ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s",
|
||||
r->method, r->http_version, r->uri_start);
|
||||
ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s" _
|
||||
r->method _ r->http_version _ r->uri_start);
|
||||
r->state_handler = ngx_process_http_request_header;
|
||||
r->connection->read->action = "reading client request headers";
|
||||
}
|
||||
@ -184,8 +161,8 @@ static int ngx_process_http_request_header(ngx_http_request_t *r)
|
||||
while ((n = ngx_read_http_header_line(r)) == 1) {
|
||||
*r->header_name_end = '\0';
|
||||
*r->header_end = '\0';
|
||||
ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'",
|
||||
r->header_name_start, r->header_start);
|
||||
ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _
|
||||
r->header_name_start _ r->header_start);
|
||||
}
|
||||
|
||||
if (n != 2)
|
||||
@ -201,6 +178,13 @@ static int ngx_process_http_request_header(ngx_http_request_t *r)
|
||||
return ngx_process_http_request(r);
|
||||
}
|
||||
|
||||
static int ngx_process_http_request(ngx_http_request_t *r)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static int ngx_process_http_request(ngx_http_request_t *r)
|
||||
{
|
||||
int fd;
|
||||
@ -258,6 +242,8 @@ static int ngx_process_http_request(ngx_http_request_t *r)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int ngx_http_close_request(ngx_event_t *ev)
|
||||
{
|
||||
ngx_connection_t *c = (ngx_connection_t *) ev->data;
|
||||
@ -269,5 +255,3 @@ static int ngx_http_close_request(ngx_event_t *ev)
|
||||
|
||||
return ngx_event_close(ev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
10
src/http/ngx_http_filter.h
Normal file
10
src/http/ngx_http_filter.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _NGX_HTTP_FILTER_H_INCLUDED_
|
||||
#define _NGX_HTTP_FILTER_H_INCLUDED_
|
||||
|
||||
|
||||
#define NGX_HTTP_FILTER_ERROR -1
|
||||
#define NGX_HTTP_FILTER_AGAIN 0
|
||||
#define NGX_HTTP_FILTER_DONE 1
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_FILTER_H_INCLUDED_ */
|
475
src/http/ngx_http_parse.c
Normal file
475
src/http/ngx_http_parse.c
Normal file
@ -0,0 +1,475 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
int ngx_read_http_request_line(ngx_http_request_t *r)
|
||||
{
|
||||
char ch;
|
||||
char *buff = r->buff->buff;
|
||||
char *p = r->buff->pos;
|
||||
enum {
|
||||
rl_start = 0,
|
||||
rl_space_after_method,
|
||||
rl_spaces_before_uri,
|
||||
rl_after_slash_in_uri,
|
||||
rl_check_uri,
|
||||
rl_uri,
|
||||
rl_http_09,
|
||||
rl_http_version,
|
||||
rl_first_major_digit,
|
||||
rl_major_digit,
|
||||
rl_first_minor_digit,
|
||||
rl_minor_digit,
|
||||
rl_almost_done,
|
||||
rl_done
|
||||
} state = r->state;
|
||||
|
||||
while (p < r->buff->last && state < rl_done) {
|
||||
ch = *p++;
|
||||
|
||||
/*
|
||||
printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
|
||||
state, p, r->buff->last, ch, p);
|
||||
*/
|
||||
|
||||
/* GCC complie it as jump table */
|
||||
|
||||
switch (state) {
|
||||
|
||||
/* HTTP methods: GET, HEAD, POST */
|
||||
case rl_start:
|
||||
switch (ch) {
|
||||
case 'G':
|
||||
if (p + 1 >= r->buff->last)
|
||||
return 0;
|
||||
|
||||
if (*p != 'E' || *(p + 1) != 'T')
|
||||
return NGX_HTTP_INVALID_METHOD;
|
||||
|
||||
r->method = NGX_HTTP_GET;
|
||||
p += 2;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if (p + 2 >= r->buff->last)
|
||||
return 0;
|
||||
|
||||
if (*p != 'E' || *(p + 1) != 'A' || *(p + 2) != 'D')
|
||||
return NGX_HTTP_INVALID_METHOD;
|
||||
|
||||
r->method = NGX_HTTP_HEAD;
|
||||
p += 3;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
if (p + 2 >= r->buff->last)
|
||||
return 0;
|
||||
|
||||
if (*p != 'O' || *(p + 1) != 'S' || *(p + 2) != 'T')
|
||||
return NGX_HTTP_INVALID_METHOD;
|
||||
|
||||
r->method = NGX_HTTP_POST;
|
||||
p += 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NGX_HTTP_INVALID_METHOD;
|
||||
}
|
||||
|
||||
state = rl_space_after_method;
|
||||
break;
|
||||
|
||||
/* single space after method */
|
||||
case rl_space_after_method:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
state = rl_spaces_before_uri;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_INVALID_METHOD;
|
||||
}
|
||||
break;
|
||||
|
||||
/* space* before URI */
|
||||
case rl_spaces_before_uri:
|
||||
switch (ch) {
|
||||
case '/':
|
||||
r->uri_start = p - 1;
|
||||
state = rl_after_slash_in_uri;
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
r->unusual_uri = 1;
|
||||
r->uri_start = p - 1;
|
||||
state = rl_uri;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* check dot after slash */
|
||||
case rl_after_slash_in_uri:
|
||||
switch (ch) {
|
||||
case CR:
|
||||
r->uri_end = p - 1;
|
||||
r->http_minor = 9;
|
||||
state = rl_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->uri_end = p - 1;
|
||||
r->http_minor = 9;
|
||||
state = rl_done;
|
||||
break;
|
||||
case ' ':
|
||||
r->uri_end = p - 1;
|
||||
state = rl_http_09;
|
||||
break;
|
||||
case '.':
|
||||
r->complex_uri = 1;
|
||||
state = rl_uri;
|
||||
break;
|
||||
case '/':
|
||||
r->complex_uri = 1;
|
||||
state = rl_uri;
|
||||
break;
|
||||
case '?':
|
||||
r->args_start = p;
|
||||
state = rl_uri;
|
||||
break;
|
||||
default:
|
||||
state = rl_check_uri;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* check slash in URI */
|
||||
case rl_check_uri:
|
||||
switch (ch) {
|
||||
case CR:
|
||||
r->uri_end = p - 1;
|
||||
r->http_minor = 9;
|
||||
state = rl_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->uri_end = p - 1;
|
||||
r->http_minor = 9;
|
||||
state = rl_done;
|
||||
break;
|
||||
case ' ':
|
||||
r->uri_end = p - 1;
|
||||
state = rl_http_09;
|
||||
break;
|
||||
case '.':
|
||||
r->uri_ext = p;
|
||||
break;
|
||||
case '/':
|
||||
r->uri_ext = NULL;
|
||||
state = rl_after_slash_in_uri;
|
||||
break;
|
||||
case '?':
|
||||
r->args_start = p;
|
||||
state = rl_uri;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* URI */
|
||||
case rl_uri:
|
||||
switch (ch) {
|
||||
case CR:
|
||||
r->uri_end = p - 1;
|
||||
r->http_minor = 9;
|
||||
state = rl_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->uri_end = p - 1;
|
||||
r->http_minor = 9;
|
||||
state = rl_done;
|
||||
break;
|
||||
case ' ':
|
||||
r->uri_end = p - 1;
|
||||
state = rl_http_09;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* space+ after URI */
|
||||
case rl_http_09:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case CR:
|
||||
r->http_minor = 9;
|
||||
state = rl_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->http_minor = 9;
|
||||
state = rl_done;
|
||||
break;
|
||||
case 'H':
|
||||
state = rl_http_version;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_INVALID_REQUEST;
|
||||
}
|
||||
break;
|
||||
|
||||
/* TTP/ */
|
||||
case rl_http_version:
|
||||
if (p + 2 >= r->buff->last) {
|
||||
r->state = rl_http_version;
|
||||
r->buff->pos = p - 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ch != 'T' || *p != 'T' || *(p + 1) != 'P' || *(p + 2) != '/')
|
||||
return NGX_HTTP_INVALID_REQUEST;
|
||||
|
||||
p += 3;
|
||||
state = rl_first_major_digit;
|
||||
break;
|
||||
|
||||
/* first digit of major HTTP version */
|
||||
case rl_first_major_digit:
|
||||
if (ch < '1' || ch > '9')
|
||||
return NGX_HTTP_INVALID_REQUEST;
|
||||
|
||||
r->http_major = ch - '0';
|
||||
state = rl_major_digit;
|
||||
break;
|
||||
|
||||
/* major HTTP version or dot */
|
||||
case rl_major_digit:
|
||||
if (ch == '.') {
|
||||
state = rl_first_minor_digit;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch < '0' || ch > '9')
|
||||
return NGX_HTTP_INVALID_REQUEST;
|
||||
|
||||
r->http_major = r->http_major * 10 + ch - '0';
|
||||
break;
|
||||
|
||||
/* first digit of minor HTTP version */
|
||||
case rl_first_minor_digit:
|
||||
if (ch < '0' || ch > '9')
|
||||
return NGX_HTTP_INVALID_REQUEST;
|
||||
|
||||
r->http_minor = ch - '0';
|
||||
|
||||
state = rl_minor_digit;
|
||||
break;
|
||||
|
||||
/* minor HTTP version or end of request line */
|
||||
case rl_minor_digit:
|
||||
if (ch == CR) {
|
||||
state = rl_almost_done;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == LF) {
|
||||
state = rl_done;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch < '0' || ch > '9')
|
||||
return NGX_HTTP_INVALID_REQUEST;
|
||||
|
||||
r->http_minor = r->http_minor * 10 + ch - '0';
|
||||
break;
|
||||
|
||||
/* end of request line */
|
||||
case rl_almost_done:
|
||||
switch (ch) {
|
||||
case LF:
|
||||
state = rl_done;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_INVALID_METHOD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
r->buff->pos = p;
|
||||
|
||||
if (state == rl_done) {
|
||||
r->http_version = r->http_major * 1000 + r->http_minor;
|
||||
r->state = rl_start;
|
||||
return 1;
|
||||
} else {
|
||||
r->state = state;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ngx_read_http_header_line(ngx_http_request_t *r)
|
||||
{
|
||||
char c, ch;
|
||||
char *buff = r->buff->buff;
|
||||
char *p = r->buff->pos;
|
||||
enum {
|
||||
hl_start = 0,
|
||||
hl_name,
|
||||
hl_space_before_value,
|
||||
hl_value,
|
||||
hl_space_after_value,
|
||||
hl_almost_done,
|
||||
header_almost_done,
|
||||
hl_done,
|
||||
header_done
|
||||
} state = r->state;
|
||||
|
||||
while (p < r->buff->last && state < hl_done) {
|
||||
ch = *p++;
|
||||
|
||||
/*
|
||||
printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
|
||||
state, p, r->buff->last, ch, p);
|
||||
*/
|
||||
|
||||
switch (state) {
|
||||
|
||||
/* first char */
|
||||
case hl_start:
|
||||
switch (ch) {
|
||||
case CR:
|
||||
r->header_end = p - 1;
|
||||
state = header_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->header_end = p - 1;
|
||||
state = header_done;
|
||||
break;
|
||||
default:
|
||||
state = hl_name;
|
||||
r->header_name_start = p - 1;
|
||||
|
||||
c = ch | 0x20;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
break;
|
||||
|
||||
if (ch == '-')
|
||||
break;
|
||||
|
||||
if (ch >= '0' && ch <= '9')
|
||||
break;
|
||||
|
||||
return NGX_HTTP_INVALID_HEADER;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
/* header name */
|
||||
case hl_name:
|
||||
c = ch | 0x20;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
break;
|
||||
|
||||
if (ch == ':') {
|
||||
r->header_name_end = p - 1;
|
||||
state = hl_space_before_value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '-')
|
||||
break;
|
||||
|
||||
if (ch >= '0' && ch <= '9')
|
||||
break;
|
||||
|
||||
return NGX_HTTP_INVALID_HEADER;
|
||||
|
||||
/* space* before header value */
|
||||
case hl_space_before_value:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case CR:
|
||||
r->header_start = r->header_end = p - 1;
|
||||
state = hl_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->header_start = r->header_end = p - 1;
|
||||
state = hl_done;
|
||||
break;
|
||||
default:
|
||||
r->header_start = p - 1;
|
||||
state = hl_value;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* header value */
|
||||
case hl_value:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
r->header_end = p - 1;
|
||||
state = hl_space_after_value;
|
||||
break;
|
||||
case CR:
|
||||
r->header_end = p - 1;
|
||||
state = hl_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->header_end = p - 1;
|
||||
state = hl_done;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* space* before end of header line */
|
||||
case hl_space_after_value:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case CR:
|
||||
state = hl_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
state = hl_done;
|
||||
break;
|
||||
default:
|
||||
state = hl_value;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* end of header line */
|
||||
case hl_almost_done:
|
||||
switch (ch) {
|
||||
case LF:
|
||||
state = hl_done;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_INVALID_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
/* end of header */
|
||||
case header_almost_done:
|
||||
switch (ch) {
|
||||
case LF:
|
||||
state = header_done;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_INVALID_HEADER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
r->buff->pos = p;
|
||||
|
||||
if (state == hl_done) {
|
||||
r->state = hl_start;
|
||||
return 1;
|
||||
} else if (state == header_done) {
|
||||
r->state = hl_start;
|
||||
return 2;
|
||||
} else {
|
||||
r->state = state;
|
||||
return 0;
|
||||
}
|
||||
}
|
82
src/http/ngx_http_write_filter.c
Normal file
82
src/http/ngx_http_write_filter.c
Normal file
@ -0,0 +1,82 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
|
||||
#include <ngx_hunk.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_filter.h>
|
||||
#include <ngx_event_write.h>
|
||||
|
||||
#include <ngx_http_write_filter.h>
|
||||
|
||||
|
||||
ngx_http_module_t ngx_http_write_filter_module;
|
||||
|
||||
|
||||
/* STUB */
|
||||
static ngx_http_write_filter_ctx_t module_ctx;
|
||||
|
||||
void ngx_http_write_filter_init()
|
||||
{
|
||||
module_ctx.buffer_output = 10240;
|
||||
module_ctx.out = NULL;
|
||||
|
||||
ngx_http_write_filter_module.ctx = &module_ctx;
|
||||
}
|
||||
/* */
|
||||
|
||||
|
||||
int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
{
|
||||
int last;
|
||||
off_t size, flush;
|
||||
ngx_chain_t *ch, **prev, *chain;
|
||||
ngx_http_write_filter_ctx_t *ctx;
|
||||
|
||||
ctx = (ngx_http_write_filter_ctx_t *)
|
||||
ngx_get_module_ctx(r->main ? r->main : r,
|
||||
&ngx_http_write_filter_module);
|
||||
size = flush = 0;
|
||||
last = 0;
|
||||
prev = &ctx->out;
|
||||
|
||||
/* find size, flush point and last link of saved chain */
|
||||
for (ch = ctx->out; ch; ch = ch->next) {
|
||||
prev = &ch->next;
|
||||
size += ch->hunk->last.file - ch->hunk->pos.file;
|
||||
|
||||
if (ch->hunk->type & NGX_HUNK_FLUSH)
|
||||
flush = size;
|
||||
|
||||
if (ch->hunk->type & NGX_HUNK_LAST)
|
||||
last = 1;
|
||||
}
|
||||
|
||||
/* add new chain to existent one */
|
||||
for (/* void */; in; in = in->next) {
|
||||
ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)),
|
||||
NGX_HTTP_FILTER_ERROR);
|
||||
|
||||
ch->hunk = in->hunk;
|
||||
ch->next = NULL;
|
||||
*prev = ch;
|
||||
prev = &ch->next;
|
||||
size += ch->hunk->last.file - ch->hunk->pos.file;
|
||||
|
||||
if (ch->hunk->type & NGX_HUNK_FLUSH)
|
||||
flush = size;
|
||||
|
||||
if (ch->hunk->type & NGX_HUNK_LAST)
|
||||
last = 1;
|
||||
}
|
||||
|
||||
if (flush == 0 && size < ctx->buffer_output)
|
||||
return NGX_HTTP_FILTER_DONE;
|
||||
|
||||
chain = ngx_event_write(r->connection, ctx->out, flush);
|
||||
if (chain == (ngx_chain_t *) -1)
|
||||
return NGX_HTTP_FILTER_ERROR;
|
||||
|
||||
ctx->out = chain;
|
||||
|
||||
return (chain ? NGX_HTTP_FILTER_AGAIN : NGX_HTTP_FILTER_DONE);
|
||||
}
|
11
src/http/ngx_http_write_filter.h
Normal file
11
src/http/ngx_http_write_filter.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef _NGX_HTTP_WRITE_FILTER_H_INCLUDED_
|
||||
#define _NGX_HTTP_WRITE_FILTER_H_INCLUDED_
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_chain_t *out;
|
||||
size_t buffer_output;
|
||||
} ngx_http_write_filter_ctx_t;
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_WRITE_FILTER_H_INCLUDED_ */
|
64
src/os/freebsd/ngx_os_thread.c
Normal file
64
src/os/freebsd/ngx_os_thread.c
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
#include <ngx_os_thread.h>
|
||||
|
||||
char *ngx_stacks_start;
|
||||
char *ngx_stacks_end;
|
||||
size_t ngx_stack_size;
|
||||
|
||||
|
||||
/* handle thread-safe errno */
|
||||
static int errno0; /* errno for main thread */
|
||||
static int *errnos;
|
||||
|
||||
int *__error()
|
||||
{
|
||||
ngx_tid_t tid = ngx_gettid();
|
||||
return tid ? &(errnos[ngx_gettid()]) : &errno0;
|
||||
}
|
||||
|
||||
|
||||
int ngx_create_os_thread(ngx_os_tid_t *tid, void *stack,
|
||||
int (*func)(void *arg), void *arg, ngx_log_t log)
|
||||
{
|
||||
int id, err;
|
||||
|
||||
id = rfork_thread(RFPROC|RFMEM, stack, func, arg);
|
||||
err = ngx_errno;
|
||||
|
||||
if (id == -1)
|
||||
ngx_log_error(NGX_LOG_ERR, log, err,
|
||||
"ngx_create_os_thread: rfork failed");
|
||||
else
|
||||
*tid = id;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int ngx_create_os_thread_env(int n, size_t size, ngx_log_t log)
|
||||
{
|
||||
char *addr;
|
||||
|
||||
/* create thread stacks */
|
||||
addr = mmap(NULL, n * size, PROT_READ|PROT_WRITE, MAP_ANON, -1, NULL);
|
||||
if (addr == MAP_FAILED) {
|
||||
ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
|
||||
"ngx_create_os_thread_stacks: mmap failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nxg_stacks_start = addr;
|
||||
nxg_stacks_end = addr + n * size;
|
||||
nxg_stack_size = size;
|
||||
|
||||
/* create thread errno array */
|
||||
ngx_test_null(errnos, ngx_calloc(n * sizeof(int)), -1);
|
||||
|
||||
/* create thread tid array */
|
||||
ngx_test_null(ngx_os_tids, ngx_calloc(n * sizeof(ngx_os_tid_t)), -1);
|
||||
|
||||
/* allow spinlock in malloc() */
|
||||
__isthreaded = 1;
|
||||
|
||||
return 0;
|
||||
}
|
24
src/os/freebsd/ngx_os_thread.h
Normal file
24
src/os/freebsd/ngx_os_thread.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef _NGX_OS_THREAD_H_INCLUDED_
|
||||
#define _NGX_OS_THREAD_H_INCLUDED_
|
||||
|
||||
|
||||
typedef int ngx_os_tid_t;
|
||||
typedef int ngx_tid_t;
|
||||
|
||||
|
||||
extern char *ngx_stacks_start;
|
||||
extern char *ngx_stacks_end;
|
||||
extern size_t ngx_stack_size;
|
||||
|
||||
|
||||
static inline ngx_tid_t ngx_gettid()
|
||||
{
|
||||
char *sp;
|
||||
|
||||
__asm__ ("mov %%esp,%0" : "=r" (sp));
|
||||
return (sp > ngx_stacks_end) ? 0:
|
||||
(sp - ngx_stacks_start) / ngx_stack_size + 1;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _NGX_OS_THREAD_H_INCLUDED_ */
|
10
src/os/unix/ngx_recv.h
Normal file
10
src/os/unix/ngx_recv.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _NGX_RECV_H_INCLUDED_
|
||||
#define _NGX_RECV_H_INCLUDED_
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define ngx_recv(fd, buf, size, flags) recv(fd, buf, size, flags)
|
||||
|
||||
|
||||
#endif /* _NGX_RECV_H_INCLUDED_ */
|
@ -17,3 +17,70 @@ u_int ngx_msec(void)
|
||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
typedef struct {
|
||||
int busy;
|
||||
u_int_64 msec;
|
||||
time_t sec;
|
||||
tm;
|
||||
http_time_len;
|
||||
http_time[n];
|
||||
};
|
||||
|
||||
volatile *ngx_time_p;
|
||||
|
||||
ngx_time()
|
||||
{
|
||||
p = ngx_time_p;
|
||||
}
|
||||
|
||||
ngx_update_time()
|
||||
{
|
||||
u_int64 msec;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
msec = (unsigned long) tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
p = ngx_time_p;
|
||||
|
||||
/* minimum can be for example 0, 10, 50 or 100 ms */
|
||||
if (tv_sec > p->sec || msec - p->msec >= minimum) {
|
||||
old_p = p;
|
||||
/* max_tries < max_slots - 10,
|
||||
max_slots should be more than max of threads */
|
||||
for (/* void */; i < max_tries; i++) {
|
||||
if (++p >= last_slot)
|
||||
p = first_slot;
|
||||
|
||||
if (!test_and_set(p->busy)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == max_tries) {
|
||||
ngx_log_error();
|
||||
return;
|
||||
}
|
||||
|
||||
if (tv_sec > p->sec) {
|
||||
p->sec = tv.tv.sec;
|
||||
p->msec = msec;
|
||||
localtime_r(&tv.tv_sec, tm);
|
||||
make http stirng;
|
||||
|
||||
} else {
|
||||
ngx_memcpy(p->sec, old_p->sec, sizeof() - offset_of(, sec));
|
||||
p->msec = msec;
|
||||
}
|
||||
|
||||
/* here can be too seldom and non-critical race condition */
|
||||
if (ngx_time_p == old_p)
|
||||
ngx_time_p = p;
|
||||
|
||||
unlock(p->busy);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
10
src/os/win32/ngx_recv.h
Normal file
10
src/os/win32/ngx_recv.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _NGX_RECV_H_INCLUDED_
|
||||
#define _NGX_RECV_H_INCLUDED_
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define ngx_recv(fd, buf, size, flags) recv(fd, buf, size, flags)
|
||||
|
||||
|
||||
#endif /* _NGX_RECV_H_INCLUDED_ */
|
Loading…
Reference in New Issue
Block a user