mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 17:52:38 +08:00
nginx-0.0.1-2002-08-06-20:39:45 import
The first code that uses "ngx_" prefix, the previous one used "gx_" prefix. At that point the code is not yet usable. The first draft ideas are dated back to 23.10.2001.
This commit is contained in:
commit
6de5c2cb63
118
src/core/nginx.c
Normal file
118
src/core/nginx.c
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
|
||||||
|
#include <nginx.h>
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_string.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
#include <ngx_server.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
#include <ngx_listen.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <ngx_http.h>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if !(WIN32)
|
||||||
|
static int ngx_options(int argc, char *const *argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *ngx_root = "/home/is/work/xml/xml/html";
|
||||||
|
|
||||||
|
int ngx_http_init_connection(void *data);
|
||||||
|
|
||||||
|
|
||||||
|
int ngx_max_conn = 512;
|
||||||
|
struct sockaddr_in ngx_addr = {0, AF_INET, 0, 0, 0};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_pool_t ngx_pool;
|
||||||
|
ngx_log_t ngx_log;
|
||||||
|
ngx_server_t ngx_server;
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *const *argv)
|
||||||
|
{
|
||||||
|
char addr_text[22];
|
||||||
|
ngx_socket_t fd;
|
||||||
|
ngx_listen_t ls;
|
||||||
|
#if (WIN32)
|
||||||
|
WSADATA wsd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
ngx_log.log_level = NGX_LOG_DEBUG;
|
||||||
|
ngx_pool.log = &ngx_log;
|
||||||
|
ngx_addr.sin_port = htons(8000);
|
||||||
|
ngx_addr.sin_family = AF_INET;
|
||||||
|
|
||||||
|
#if !(WIN32)
|
||||||
|
if (ngx_options(argc, argv) == -1)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, (&ngx_log), 0, "invalid argument");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngx_log_debug((&ngx_log), "%d, %s:%d" _ ngx_max_conn _
|
||||||
|
inet_ntoa(ngx_addr.sin_addr) _ ntohs(ngx_addr.sin_port));
|
||||||
|
|
||||||
|
#if (WIN32)
|
||||||
|
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, (&ngx_log), ngx_socket_errno,
|
||||||
|
"WSAStartup 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);
|
||||||
|
|
||||||
|
ngx_server.buff_size = 1024;
|
||||||
|
ngx_server.handler = ngx_http_init_connection;
|
||||||
|
|
||||||
|
/* daemon */
|
||||||
|
|
||||||
|
ls.fd = fd;
|
||||||
|
ls.server = &ngx_server;
|
||||||
|
ls.log = &ngx_log;
|
||||||
|
|
||||||
|
/* fork */
|
||||||
|
|
||||||
|
ngx_worker(&ls, 1, &ngx_pool, &ngx_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !(WIN32)
|
||||||
|
extern char *optarg;
|
||||||
|
|
||||||
|
static int ngx_options(int argc, char *const *argv)
|
||||||
|
{
|
||||||
|
char ch, *pos;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "l:c:")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'l':
|
||||||
|
if (pos = strchr(optarg, ':')) {
|
||||||
|
*(pos) = '\0';
|
||||||
|
if ((port = atoi(pos + 1)) <= 0)
|
||||||
|
return -1;
|
||||||
|
ngx_addr.sin_port = htons(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ngx_addr.sin_addr.s_addr = inet_addr(optarg)) == INADDR_NONE)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
if ((ngx_max_conn = atoi(optarg)) <= 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
8
src/core/nginx.h
Normal file
8
src/core/nginx.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _NGINX_H_INCLUDED_
|
||||||
|
#define _NGINX_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
extern char *gx_root;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGINX_H_INCLUDED_ */
|
136
src/core/ngx_alloc.c
Normal file
136
src/core/ngx_alloc.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
#include <ngx_errno.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
|
||||||
|
|
||||||
|
void *ngx_alloc(size_t size, ngx_log_t *log)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
p = malloc(size);
|
||||||
|
if (p == NULL)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||||
|
"ngx_alloc: malloc %d bytes failed", size);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ngx_calloc(size_t size, ngx_log_t *log)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
p = ngx_alloc(size, log);
|
||||||
|
if (p)
|
||||||
|
ngx_memzero(p, size);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log)
|
||||||
|
{
|
||||||
|
ngx_pool_t *p;
|
||||||
|
|
||||||
|
ngx_test_null(p, ngx_alloc(size, log), NULL);
|
||||||
|
|
||||||
|
p->last = (char *) p + sizeof(ngx_pool_t);
|
||||||
|
p->end = (char *) p + size;
|
||||||
|
p->next = NULL;
|
||||||
|
p->large = NULL;
|
||||||
|
p->log = log;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngx_destroy_pool(ngx_pool_t *pool)
|
||||||
|
{
|
||||||
|
ngx_pool_t *p, *n;
|
||||||
|
ngx_pool_large_t *l;
|
||||||
|
|
||||||
|
for (l = pool->large; l; l = l->next)
|
||||||
|
free(l->alloc);
|
||||||
|
|
||||||
|
for (p = pool, n = pool->next; /* void */; p = n, n = n->next) {
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
if (n == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ngx_palloc(ngx_pool_t *pool, size_t size)
|
||||||
|
{
|
||||||
|
void *m;
|
||||||
|
ngx_pool_t *p, *n;
|
||||||
|
ngx_pool_large_t *large, *last;
|
||||||
|
|
||||||
|
if (size <= NGX_MAX_ALLOC_FROM_POOL) {
|
||||||
|
|
||||||
|
for (p = pool, n = pool->next; /* void */; p = n, n = n->next) {
|
||||||
|
if ((size_t) (p->end - p->last) >= size) {
|
||||||
|
m = p->last;
|
||||||
|
p->last += size;
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* alloc new pool block */
|
||||||
|
ngx_test_null(n, ngx_create_pool(p->end - (char *) p, p->log), NULL);
|
||||||
|
p->next = n;
|
||||||
|
m = n->last;
|
||||||
|
n->last += size;
|
||||||
|
return m;
|
||||||
|
|
||||||
|
/* alloc large block */
|
||||||
|
} else {
|
||||||
|
large = NULL;
|
||||||
|
last = NULL;
|
||||||
|
|
||||||
|
if (pool->large) {
|
||||||
|
for (last = pool->large; /* void */; last = last->next) {
|
||||||
|
if (last->alloc == NULL) {
|
||||||
|
large = last;
|
||||||
|
last = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last->next == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (large == NULL) {
|
||||||
|
ngx_test_null(large, ngx_palloc(pool, sizeof(ngx_pool_large_t)),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_test_null(p, ngx_alloc(size, pool->log), NULL);
|
||||||
|
|
||||||
|
if (pool->large == NULL) {
|
||||||
|
pool->large = large;
|
||||||
|
|
||||||
|
} else if (last) {
|
||||||
|
last->next = large;
|
||||||
|
}
|
||||||
|
|
||||||
|
large->alloc = p;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ngx_pcalloc(ngx_pool_t *pool, size_t size)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
p = ngx_palloc(pool, size);
|
||||||
|
if (p)
|
||||||
|
ngx_memzero(p, size);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
42
src/core/ngx_alloc.h
Normal file
42
src/core/ngx_alloc.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef _NGX_ALLOC_H_INCLUDED_
|
||||||
|
#define _NGX_ALLOC_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
#include <ngx_log.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_MAX_ALLOC_FROM_POOL (8192 - sizeof(ngx_pool_t))
|
||||||
|
#define NGX_DEFAULT_POOL_SIZE (16 * 1024)
|
||||||
|
|
||||||
|
#define ngx_test_null(p, alloc, rc) if ((p = alloc) == NULL) return rc
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ngx_pool_large_s ngx_pool_large_t;
|
||||||
|
struct ngx_pool_large_s {
|
||||||
|
ngx_pool_large_t *next;
|
||||||
|
void *alloc;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ngx_pool_s ngx_pool_t;
|
||||||
|
struct ngx_pool_s {
|
||||||
|
char *last;
|
||||||
|
char *end;
|
||||||
|
ngx_pool_t *next;
|
||||||
|
ngx_pool_large_t *large;
|
||||||
|
ngx_log_t *log;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void *ngx_alloc(size_t size, ngx_log_t *log);
|
||||||
|
void *ngx_calloc(size_t size, ngx_log_t *log);
|
||||||
|
|
||||||
|
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);
|
||||||
|
void ngx_destroy_pool(ngx_pool_t *pool);
|
||||||
|
|
||||||
|
void *ngx_palloc(ngx_pool_t *pool, size_t size);
|
||||||
|
void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_ALLOC_H_INCLUDED_ */
|
69
src/core/ngx_array.c
Normal file
69
src/core/ngx_array.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
#include <ngx_array.h>
|
||||||
|
|
||||||
|
ngx_array_t *ngx_create_array(ngx_pool_t *p, int n, size_t size)
|
||||||
|
{
|
||||||
|
ngx_array_t *a;
|
||||||
|
|
||||||
|
a = ngx_palloc(p, sizeof(ngx_array_t));
|
||||||
|
if (a == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
a->elts = ngx_palloc(p, n * size);
|
||||||
|
if (a->elts == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
a->pool = p;
|
||||||
|
a->nelts = 0;
|
||||||
|
a->nalloc = n;
|
||||||
|
a->size = size;
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngx_destroy_array(ngx_array_t *a)
|
||||||
|
{
|
||||||
|
ngx_pool_t *p = a->pool;
|
||||||
|
|
||||||
|
if (a->elts + a->size * a->nalloc == p->last)
|
||||||
|
p->last -= a->size * a->nalloc;
|
||||||
|
|
||||||
|
if ((char *) a + sizeof(ngx_array_t) == p->last)
|
||||||
|
p->last = (char *) a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ngx_push_array(ngx_array_t *a)
|
||||||
|
{
|
||||||
|
void *elt;
|
||||||
|
|
||||||
|
/* array is full */
|
||||||
|
if (a->nelts == a->nalloc) {
|
||||||
|
ngx_pool_t *p = a->pool;
|
||||||
|
|
||||||
|
/* array allocation is the last in the pool */
|
||||||
|
if (a->elts + a->size * a->nelts == p->last
|
||||||
|
&& (unsigned) (p->end - p->last) >= a->size)
|
||||||
|
{
|
||||||
|
p->last += a->size;
|
||||||
|
a->nalloc++;
|
||||||
|
|
||||||
|
/* allocate new array */
|
||||||
|
} else {
|
||||||
|
void *new = ngx_palloc(p, 2 * a->nalloc * a->size);
|
||||||
|
if (new == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memcpy(new, a->elts, a->nalloc * a->size);
|
||||||
|
a->elts = new;
|
||||||
|
a->nalloc *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elt = a->elts + a->size * a->nelts;
|
||||||
|
a->nelts++;
|
||||||
|
|
||||||
|
return elt;
|
||||||
|
}
|
23
src/core/ngx_array.h
Normal file
23
src/core/ngx_array.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _NGX_ARRAY_H_INCLUDED_
|
||||||
|
#define _NGX_ARRAY_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *elts;
|
||||||
|
int nelts;
|
||||||
|
size_t size;
|
||||||
|
int nalloc;
|
||||||
|
ngx_pool_t *pool;
|
||||||
|
} ngx_array_t;
|
||||||
|
|
||||||
|
|
||||||
|
ngx_array_t *ngx_create_array(ngx_pool_t *p, int n, size_t size);
|
||||||
|
void ngx_destroy_array(ngx_array_t *a);
|
||||||
|
void *ngx_push_array(ngx_array_t *a);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_ARRAY_H_INCLUDED_ */
|
4
src/core/ngx_auto_config.h
Normal file
4
src/core/ngx_auto_config.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
#ifndef OFF_EQUAL_PTR
|
||||||
|
#define OFF_EQUAL_PTR 0
|
||||||
|
#endif
|
130
src/core/ngx_config.h
Normal file
130
src/core/ngx_config.h
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#ifndef _NGX_CONFIG_H_INCLUDED_
|
||||||
|
#define _NGX_CONFIG_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_auto_config.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
auto_conf
|
||||||
|
ngx_inline inline __inline __inline__
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FD_SETSIZE 1024
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#define WIN32 1
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <mswsock.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define ngx_inline __inline
|
||||||
|
|
||||||
|
#define ngx_memzero ZeroMemory
|
||||||
|
|
||||||
|
#define ngx_close_socket closesocket
|
||||||
|
|
||||||
|
#ifndef HAVE_WIN32_TRANSMITPACKETS
|
||||||
|
#define HAVE_WIN32_TRANSMITPACKETS 1
|
||||||
|
#define HAVE_WIN32_TRANSMITFILE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_WIN32_TRANSMITFILE
|
||||||
|
#define HAVE_WIN32_TRANSMITFILE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (HAVE_WIN32_TRANSMITPACKETS) || (HAVE_WIN32_TRANSMITFILE)
|
||||||
|
#define HAVE_SENDFILE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* POSIX */
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define ngx_inline inline
|
||||||
|
|
||||||
|
#define ngx_memzero bzero
|
||||||
|
|
||||||
|
#define ngx_close_socket close
|
||||||
|
|
||||||
|
#endif /* POSIX */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define LF 10
|
||||||
|
#define CR 13
|
||||||
|
#define CRLF "\x0d\x0a"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined SO_ACCEPTFILTER || defined TCP_DEFER_ACCEPT
|
||||||
|
|
||||||
|
#ifndef HAVE_DEFERRED_ACCEPT
|
||||||
|
#define HAVE_DEFERRED_ACCEPT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
|
||||||
|
#include <osreldate.h>
|
||||||
|
|
||||||
|
#if __FreeBSD_version >= 300007
|
||||||
|
|
||||||
|
#ifndef HAVE_FREEBSD_SENDFILE
|
||||||
|
#define HAVE_FREEBSD_SENDFILE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_FREEBSD_SENDFILE_NBYTES_BUG
|
||||||
|
#define HAVE_FREEBSD_SENDFILE_NBYTES_BUG 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 460100) \
|
||||||
|
|| __FreeBSD_version == 460001
|
||||||
|
|| __FreeBSD_version >= 500029
|
||||||
|
|
||||||
|
#if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG == 2)
|
||||||
|
#define HAVE_FREEBSD_SENDFILE_NBYTES_BUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (HAVE_FREEBSD_SENDFILE)
|
||||||
|
#define HAVE_SENDFILE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 410000) \
|
||||||
|
|| __FreeBSD_version >= 500011
|
||||||
|
|
||||||
|
#ifndef HAVE_KQUEUE
|
||||||
|
#define HAVE_KQUEUE 1
|
||||||
|
#include <sys/event.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __FreeBSD__ */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_CONFIG_H_INCLUDED_ */
|
54
src/core/ngx_connection.h
Normal file
54
src/core/ngx_connection.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef _NGX_CONNECTION_H_INCLUDED_
|
||||||
|
#define _NGX_CONNECTION_H_INCLUDED_
|
||||||
|
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
#include <ngx_server.h>
|
||||||
|
|
||||||
|
typedef struct ngx_connection_s ngx_connection_t;
|
||||||
|
|
||||||
|
#ifdef NGX_EVENT
|
||||||
|
#include <ngx_event.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ngx_connection_s {
|
||||||
|
ngx_socket_t fd;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
#ifdef NGX_EVENT
|
||||||
|
ngx_event_t *read;
|
||||||
|
ngx_event_t *write;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngx_log_t *log;
|
||||||
|
ngx_server_t *server;
|
||||||
|
ngx_server_t *servers;
|
||||||
|
ngx_pool_t *pool;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
cached file
|
||||||
|
int fd; -2 unused, -1 closed (but read or mmaped), >=0 open
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
void *buf; addr if read or mmaped
|
||||||
|
aiocb* if aio_read
|
||||||
|
OVERLAPPED if TransmitFile or TransmitPackets
|
||||||
|
NULL if sendfile
|
||||||
|
|
||||||
|
size_t buf_size; for plain read
|
||||||
|
off_t offset; for plain read
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
time_t mod;
|
||||||
|
char *last_mod; 'Sun, 17 Mar 2002 19:39:50 GMT'
|
||||||
|
char *etag; '"a6d08-1302-3c94f106"'
|
||||||
|
char *len; '4866'
|
||||||
|
|
||||||
|
EV_VNODE should notify by some signal if diretory tree is changed
|
||||||
|
or stat if aged >= N seconds (big enough)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* _NGX_CONNECTION_H_INCLUDED_ */
|
85
src/core/ngx_hunk.c
Normal file
85
src/core/ngx_hunk.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_hunk.h>
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
#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->post_end = h->end + after;
|
||||||
|
|
||||||
|
h->type = NGX_HUNK_TEMP;
|
||||||
|
h->tag = 0;
|
||||||
|
h->fd = (ngx_file_t) -1;
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (hunk->type & NGX_HUNK_TEMP && hunk->pos.p - 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->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->end = h->post_end = h->start + size;
|
||||||
|
|
||||||
|
h->type = NGX_HUNK_TEMP;
|
||||||
|
h->tag = 0;
|
||||||
|
h->fd = (ngx_file_t) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (hunk->type & NGX_HUNK_TEMP
|
||||||
|
&& hunk->last.p == 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->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->end = h->post_end = h->start + size;
|
||||||
|
|
||||||
|
h->type = NGX_HUNK_TEMP;
|
||||||
|
h->tag = 0;
|
||||||
|
h->fd = (ngx_file_t) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
57
src/core/ngx_hunk.h
Normal file
57
src/core/ngx_hunk.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef _NGX_CHUNK_H_INCLUDED_
|
||||||
|
#define _NGX_CHUNK_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* type */
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
#define NGX_HUNK_SHUTDOWN 0x10000
|
||||||
|
/* can be used with NGX_HUNK_LAST only */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ngx_hunk_s ngx_hunk_t;
|
||||||
|
struct ngx_hunk_s {
|
||||||
|
union {
|
||||||
|
char *p; /* start of current data */
|
||||||
|
off_t f;
|
||||||
|
} pos;
|
||||||
|
union {
|
||||||
|
char *p; /* end of current data */
|
||||||
|
off_t f;
|
||||||
|
} last;
|
||||||
|
int type;
|
||||||
|
char *start; /* start of hunk */
|
||||||
|
char *end; /* end of hunk */
|
||||||
|
char *pre_start; /* start of pre-allocated hunk */
|
||||||
|
char *post_end; /* end of post-allocated hunk */
|
||||||
|
int tag;
|
||||||
|
ngx_file_t fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ngx_chain_s ngx_chain_t;
|
||||||
|
struct ngx_chain_s {
|
||||||
|
ngx_hunk_t *hunk;
|
||||||
|
ngx_chain_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_hunk_t *ngx_get_hunk(ngx_pool_t *pool, int size, int before, int after);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_CHUNK_H_INCLUDED_ */
|
44
src/core/ngx_listen.c
Normal file
44
src/core/ngx_listen.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_errno.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_listen.h>
|
||||||
|
|
||||||
|
ngx_socket_t ngx_listen(struct sockaddr *addr, int backlog,
|
||||||
|
ngx_log_t *log, char *addr_text)
|
||||||
|
{
|
||||||
|
ngx_socket_t s;
|
||||||
|
int reuseaddr = 1;
|
||||||
|
#if (WIN32)
|
||||||
|
unsigned long nb = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, 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, log, ngx_socket_errno,
|
||||||
|
"ngx_listen: setsockopt (SO_REUSEADDR) failed");
|
||||||
|
|
||||||
|
#if (WIN32)
|
||||||
|
if (ioctlsocket(s, FIONBIO, &nb) == -1)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||||
|
"ngx_listen: ioctlsocket (FIONBIO) failed");
|
||||||
|
#else
|
||||||
|
if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||||
|
"ngx_listen: fcntl (O_NONBLOCK) failed");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *) addr, sizeof(struct sockaddr_in)) == -1)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||||
|
"ngx_listen: bind to %s failed", addr_text);
|
||||||
|
|
||||||
|
if (listen(s, backlog) == -1)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||||
|
"ngx_listen: listen to %s failed", addr_text);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
9
src/core/ngx_listen.h
Normal file
9
src/core/ngx_listen.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _NGX_LISTEN_H_INCLUDED_
|
||||||
|
#define _NGX_LISTEN_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
ngx_socket_t ngx_listen(struct sockaddr *addr, int backlog,
|
||||||
|
ngx_log_t *log, char *addr_text);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_LISTEN_H_INCLUDED_ */
|
116
src/core/ngx_log.c
Normal file
116
src/core/ngx_log.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
TODO: log pid and tid
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
"[time as ctime()] [alert] 412:3 (32)Broken pipe: anything"
|
||||||
|
|
||||||
|
"[time as ctime()] [alert] (32)Broken pipe: anything"
|
||||||
|
"[time as ctime()] [alert] anything"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_errno.h>
|
||||||
|
#include <ngx_time.h>
|
||||||
|
#include <ngx_string.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char *err_levels[] = {
|
||||||
|
"emerg", "alert", "crit", "error", "warn", "notice", "info", "debug"
|
||||||
|
};
|
||||||
|
|
||||||
|
#if (HAVE_VARIADIC_MACROS)
|
||||||
|
void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err,
|
||||||
|
const char *fmt, ...)
|
||||||
|
#else
|
||||||
|
void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err,
|
||||||
|
const char *fmt, va_list args)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
char errstr[MAX_ERROR_STR];
|
||||||
|
ngx_tm_t tm;
|
||||||
|
size_t len;
|
||||||
|
#if (HAVE_VARIADIC_MACROS)
|
||||||
|
va_list args;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngx_localtime(&tm);
|
||||||
|
len = ngx_snprintf(errstr, sizeof(errstr), "%02d:%02d:%02d",
|
||||||
|
tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
if ((unsigned) err < 0x80000000)
|
||||||
|
len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1,
|
||||||
|
" [%s] (%d)",
|
||||||
|
err_levels[level], err);
|
||||||
|
len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1,
|
||||||
|
" [%s] (%X)",
|
||||||
|
err_levels[level], err);
|
||||||
|
|
||||||
|
len += ngx_strerror_r(err, errstr + len, sizeof(errstr) - len - 1);
|
||||||
|
if (len < sizeof(errstr) - 2) {
|
||||||
|
errstr[len++] = ':';
|
||||||
|
errstr[len++] = ' ';
|
||||||
|
} else {
|
||||||
|
len = sizeof(errstr) - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1,
|
||||||
|
" [%s] ", err_levels[level]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (HAVE_VARIADIC_MACROS)
|
||||||
|
va_start(args, fmt);
|
||||||
|
len += ngx_vsnprintf(errstr + len, sizeof(errstr) - len - 1, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
#else
|
||||||
|
len += ngx_vsnprintf(errstr + len, sizeof(errstr) - len - 1, fmt, args);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (len > sizeof(errstr) - 2)
|
||||||
|
len = sizeof(errstr) - 2;
|
||||||
|
errstr[len] = '\n';
|
||||||
|
errstr[len + 1] = '\0';
|
||||||
|
|
||||||
|
fputs(errstr, stderr);
|
||||||
|
|
||||||
|
if (level == NGX_LOG_EMERG)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !(HAVE_VARIADIC_MACROS)
|
||||||
|
|
||||||
|
void ngx_log_error(int level, ngx_log_t *log, ngx_err_t err,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (log->log_level >= level) {
|
||||||
|
va_start(args, fmt);
|
||||||
|
ngx_log_error_core(level, log, err, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngx_log_debug_core(ngx_log_t *log, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
ngx_log_error_core(NGX_LOG_DEBUG, log, 0, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngx_assert_core(ngx_log_t *log, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
ngx_log_error_core(NGX_LOG_ALERT, log, 0, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
118
src/core/ngx_log.h
Normal file
118
src/core/ngx_log.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#ifndef _NGX_LOG_H_INCLUDED_
|
||||||
|
#define _NGX_LOG_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_errno.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NGX_LOG_EMERG = 0,
|
||||||
|
NGX_LOG_ALERT,
|
||||||
|
NGX_LOG_CRIT,
|
||||||
|
NGX_LOG_ERR,
|
||||||
|
NGX_LOG_WARN,
|
||||||
|
NGX_LOG_NOTICE,
|
||||||
|
NGX_LOG_INFO,
|
||||||
|
NGX_LOG_DEBUG
|
||||||
|
} ngx_log_e;
|
||||||
|
|
||||||
|
/*
|
||||||
|
"... while ", action = "reading client request headers"
|
||||||
|
"... while reading client request headers"
|
||||||
|
"... while ", action = "reading client request headers"
|
||||||
|
context: pop3 user account
|
||||||
|
"... while reading client command for 'john_doe'"
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int log_level;
|
||||||
|
char *action;
|
||||||
|
char *context;
|
||||||
|
/* char *func(ngx_log_t *log); */
|
||||||
|
} ngx_log_t;
|
||||||
|
|
||||||
|
#define MAX_ERROR_STR 2048
|
||||||
|
|
||||||
|
#define _ ,
|
||||||
|
|
||||||
|
|
||||||
|
#if (HAVE_GCC_VARIADIC_MACROS)
|
||||||
|
|
||||||
|
#define HAVE_VARIADIC_MACROS 1
|
||||||
|
|
||||||
|
#define ngx_log_error(level, log, args...) \
|
||||||
|
if (log->log_level >= level) ngx_log_error_core(level, log, args)
|
||||||
|
|
||||||
|
#ifdef NGX_DEBUG
|
||||||
|
#define ngx_log_debug(log, args...) \
|
||||||
|
if (log->log_level == NGX_LOG_DEBUG) \
|
||||||
|
ngx_log_error_core(NGX_LOG_DEBUG, log, 0, args)
|
||||||
|
#else
|
||||||
|
#define ngx_log_debug(log, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ngx_assert(assert, fallback, log, args...) \
|
||||||
|
if (!(assert)) { \
|
||||||
|
if (log->log_level >= NGX_LOG_ALERT) \
|
||||||
|
ngx_log_error_core(NGX_LOG_ALERT, log, 0, args); \
|
||||||
|
fallback; \
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err,
|
||||||
|
const char *fmt, ...);
|
||||||
|
|
||||||
|
#elif (HAVE_C99_VARIADIC_MACROS)
|
||||||
|
|
||||||
|
#define HAVE_VARIADIC_MACROS 1
|
||||||
|
|
||||||
|
#define ngx_log_error(level, log, ...) \
|
||||||
|
if (log->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
|
||||||
|
|
||||||
|
#ifdef NGX_DEBUG
|
||||||
|
#define ngx_log_debug(log, ...) \
|
||||||
|
if (log->log_level == NGX_LOG_DEBUG) \
|
||||||
|
ngx_log_error_core(NGX_LOG_DEBUG, log, 0, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define ngx_log_debug(log, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ngx_assert(assert, fallback, log, ...) \
|
||||||
|
if (!(assert)) { \
|
||||||
|
if (log->log_level >= NGX_LOG_ALERT) \
|
||||||
|
ngx_log_error_core(NGX_LOG_ALERT, log, 0, __VA_ARGS__); \
|
||||||
|
fallback; \
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err,
|
||||||
|
const char *fmt, ...);
|
||||||
|
|
||||||
|
#else /* NO VARIADIC MACROS */
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifdef NGX_DEBUG
|
||||||
|
#define ngx_log_debug(log, text) \
|
||||||
|
if (log->log_level == NGX_LOG_DEBUG) \
|
||||||
|
ngx_log_debug_core(log, text)
|
||||||
|
#else
|
||||||
|
#define ngx_log_debug(log, text)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ngx_assert(assert, fallback, log, text) \
|
||||||
|
if (!(assert)) { \
|
||||||
|
if (log->log_level >= NGX_LOG_ALERT) \
|
||||||
|
ngx_assert_core(log, text); \
|
||||||
|
fallback; \
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngx_log_error(int level, ngx_log_t *log, ngx_err_t err,
|
||||||
|
const char *fmt, ...);
|
||||||
|
void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err,
|
||||||
|
const char *fmt, va_list args);
|
||||||
|
void ngx_log_debug_core(ngx_log_t *log, const char *fmt, ...);
|
||||||
|
void ngx_assert_core(ngx_log_t *log, const char *fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* VARIADIC MACROS */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_LOG_H_INCLUDED_ */
|
30
src/core/ngx_server.h
Normal file
30
src/core/ngx_server.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef _NGX_SERVER_H_INCLUDED_
|
||||||
|
#define _NGX_SERVER_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int log_level;
|
||||||
|
ngx_pool_t *pool;
|
||||||
|
int (*handler)(void *data);
|
||||||
|
int buff_size;
|
||||||
|
} ngx_server_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_socket_t fd;
|
||||||
|
|
||||||
|
ngx_log_t *log;
|
||||||
|
ngx_server_t *server;
|
||||||
|
|
||||||
|
unsigned shared:1;
|
||||||
|
#if (HAVE_DEFERRED_ACCEPT)
|
||||||
|
unsigned accept_filter:1;
|
||||||
|
#endif
|
||||||
|
} ngx_listen_t;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_SERVER_H_INCLUDED_ */
|
21
src/core/ngx_string.c
Normal file
21
src/core/ngx_string.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_string.h>
|
||||||
|
|
||||||
|
|
||||||
|
char *ngx_cpystrn(char *dst, char *src, size_t n)
|
||||||
|
{
|
||||||
|
if (n == 0)
|
||||||
|
return dst;
|
||||||
|
|
||||||
|
for (/* void */; --n; dst++, src++) {
|
||||||
|
*dst = *src;
|
||||||
|
|
||||||
|
if (*dst == '\0')
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = '\0';
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
26
src/core/ngx_string.h
Normal file
26
src/core/ngx_string.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _NGX_STRING_H_INCLUDED_
|
||||||
|
#define _NGX_STRING_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if (WIN32)
|
||||||
|
|
||||||
|
#define ngx_snprintf _snprintf
|
||||||
|
#define ngx_vsnprintf _vsnprintf
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define ngx_snprintf snprintf
|
||||||
|
#define ngx_vsnprintf vsnprintf
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ngx_memcpy(dst, src, n) memcpy(dst, src, n)
|
||||||
|
#define ngx_cpymem(dst, src, n) memcpy(dst, src, n) + n
|
||||||
|
|
||||||
|
char *ngx_cpystrn(char *dst, char *src, size_t n);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_STRING_H_INCLUDED_ */
|
37
src/event/modules/ngx_aio_module.c
Normal file
37
src/event/modules/ngx_aio_module.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
int ngx_posix_aio_process_events(ngx_log_t *log)
|
||||||
|
{
|
||||||
|
unmask signal
|
||||||
|
|
||||||
|
listen via signal;
|
||||||
|
|
||||||
|
aio_suspend()/aiowait()/aio_waitcomplete();
|
||||||
|
|
||||||
|
mask signal
|
||||||
|
|
||||||
|
if (ngx_socket_errno == NGX_EINTR)
|
||||||
|
look listen
|
||||||
|
select()/accept() nb listen sockets
|
||||||
|
else
|
||||||
|
aio
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_posix_aio_process_events(ngx_log_t *log)
|
||||||
|
{
|
||||||
|
unmask signal
|
||||||
|
|
||||||
|
/* BUG: signal can be delivered before select() */
|
||||||
|
|
||||||
|
select(listen);
|
||||||
|
|
||||||
|
mask signal
|
||||||
|
|
||||||
|
if (ngx_socket_errno == NGX_EINTR)
|
||||||
|
look ready array
|
||||||
|
}
|
||||||
|
|
||||||
|
void aio_sig_handler(int signo, siginfo_t *siginfo, void *context)
|
||||||
|
{
|
||||||
|
push siginfo->si_value.sival_ptr
|
||||||
|
}
|
||||||
|
|
240
src/event/modules/ngx_kqueue_module.c
Normal file
240
src/event/modules/ngx_kqueue_module.c
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Igor Sysoev, http://sysoev.ru
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
NEED ? : unify change_list and event_list:
|
||||||
|
event_list = change_list;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
#include <ngx_event.h>
|
||||||
|
#include <ngx_kqueue_module.h>
|
||||||
|
|
||||||
|
#if (USE_KQUEUE) && !(HAVE_KQUEUE)
|
||||||
|
#error "kqueue is not supported on this platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void ngx_add_timer(ngx_event_t *ev, u_int timer);
|
||||||
|
static void ngx_inline ngx_del_timer(ngx_event_t *ev);
|
||||||
|
|
||||||
|
|
||||||
|
static int kq;
|
||||||
|
static struct kevent *change_list, *event_list;
|
||||||
|
static int nchanges, nevents;
|
||||||
|
|
||||||
|
static ngx_event_t timer_queue;
|
||||||
|
|
||||||
|
void ngx_kqueue_init(int max_connections, ngx_log_t *log)
|
||||||
|
{
|
||||||
|
int size = sizeof(struct kevent) * 512;
|
||||||
|
|
||||||
|
nchanges = 0;
|
||||||
|
nevents = 512;
|
||||||
|
|
||||||
|
if ((kq = kqueue()) == -1)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||||
|
"ngx_kqueue_init: kqueue failed");
|
||||||
|
|
||||||
|
change_list = ngx_alloc(size, log);
|
||||||
|
event_list = ngx_alloc(size, log);
|
||||||
|
|
||||||
|
timer_queue.timer_prev = &timer_queue;
|
||||||
|
timer_queue.timer_next = &timer_queue;
|
||||||
|
|
||||||
|
#if !(USE_KQUEUE)
|
||||||
|
ngx_event_actions.add = ngx_kqueue_add_event;
|
||||||
|
ngx_event_actions.del = ngx_kqueue_del_event;
|
||||||
|
ngx_event_actions.process = ngx_kqueue_process_events;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
|
||||||
|
{
|
||||||
|
if (event == NGX_TIMER_EVENT) {
|
||||||
|
ngx_add_timer(ev, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_kqueue_set_event(ev, event, EV_ADD | flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_kqueue_del_event(ngx_event_t *ev, int event)
|
||||||
|
{
|
||||||
|
if (event == NGX_TIMER_EVENT) {
|
||||||
|
ngx_del_timer(ev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_kqueue_set_event(ev, event, EV_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
|
||||||
|
{
|
||||||
|
struct timespec ts = { 0, 0 };
|
||||||
|
ngx_connection_t *cn = (ngx_connection_t *) ev->data;
|
||||||
|
|
||||||
|
ngx_log_debug(ev->log, "ngx_kqueue_set_event: %d: ft:%d f:%08x" _
|
||||||
|
cn->fd _ filter _ flags);
|
||||||
|
|
||||||
|
if (nchanges >= nevents) {
|
||||||
|
ngx_log_error(NGX_LOG_WARN, ev->log, 0,
|
||||||
|
"ngx_kqueue_set_event: change list is filled up");
|
||||||
|
|
||||||
|
if (kevent(kq, change_list, nchanges, NULL, 0, &ts) == -1) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
|
||||||
|
"ngx_kqueue_set_event: kevent failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
nchanges = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_list[nchanges].ident = cn->fd;
|
||||||
|
change_list[nchanges].filter = filter;
|
||||||
|
change_list[nchanges].flags = flags;
|
||||||
|
change_list[nchanges].fflags = 0;
|
||||||
|
change_list[nchanges].data = 0;
|
||||||
|
change_list[nchanges].udata = ev;
|
||||||
|
nchanges++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_kqueue_process_events(ngx_log_t *log)
|
||||||
|
{
|
||||||
|
int events, i;
|
||||||
|
u_int timer = 0, delta = 0;
|
||||||
|
ngx_event_t *ev, *nx;
|
||||||
|
struct timeval tv;
|
||||||
|
struct timespec ts, *tp = NULL;
|
||||||
|
|
||||||
|
if (timer_queue.timer_next != &timer_queue) {
|
||||||
|
timer = timer_queue.timer_next->timer_delta;
|
||||||
|
ts.tv_sec = timer / 1000;
|
||||||
|
ts.tv_nsec = (timer % 1000) * 1000000;
|
||||||
|
tp = &ts;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
delta = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_kqueue_process_events: timer: %d" _ timer);
|
||||||
|
|
||||||
|
if ((events = kevent(kq, change_list, nchanges, event_list, nevents, tp))
|
||||||
|
== -1) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||||
|
"ngx_kqueue_process_events: kevent failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nchanges = 0;
|
||||||
|
|
||||||
|
if (timer) {
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_assert((events != 0), return -1, log,
|
||||||
|
"ngx_kqueue_process_events: "
|
||||||
|
"kevent returns no events without timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_kqueue_process_events: "
|
||||||
|
"timer: %d, delta: %d" _ timer _ delta);
|
||||||
|
|
||||||
|
if (timer) {
|
||||||
|
if (delta >= timer) {
|
||||||
|
for (ev = timer_queue.timer_next;
|
||||||
|
ev != &timer_queue && delta >= ev->timer_delta;
|
||||||
|
/* void */)
|
||||||
|
{
|
||||||
|
delta -= ev->timer_delta;
|
||||||
|
nx = ev->timer_next;
|
||||||
|
ngx_del_timer(ev);
|
||||||
|
if (ev->timer_handler(ev) == -1)
|
||||||
|
ev->close_handler(ev);
|
||||||
|
ev = nx;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
timer_queue.timer_next->timer_delta -= delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < events; i++) {
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_kqueue_process_events: kevent: "
|
||||||
|
"%d: ft:%d f:%08x ff:%08x d:%d ud:%08x" _
|
||||||
|
event_list[i].ident _ event_list[i].filter _
|
||||||
|
event_list[i].flags _ event_list[i].fflags _
|
||||||
|
event_list[i].data _ event_list[i].udata);
|
||||||
|
|
||||||
|
if (event_list[i].flags & EV_ERROR) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, log, event_list[i].data,
|
||||||
|
"ngx_kqueue_process_events: kevent error");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ev = (ngx_event_t *) event_list[i].udata;
|
||||||
|
|
||||||
|
switch (event_list[i].filter) {
|
||||||
|
|
||||||
|
case EVFILT_READ:
|
||||||
|
case EVFILT_WRITE:
|
||||||
|
ev->ready = 1;
|
||||||
|
ev->available = event_list[i].data;
|
||||||
|
|
||||||
|
if (event_list[i].flags & EV_EOF) {
|
||||||
|
ev->eof = 1;
|
||||||
|
ev->error = event_list[i].fflags;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->event_handler(ev) == -1)
|
||||||
|
ev->close_handler(ev);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ngx_assert(0, /* void */, log,
|
||||||
|
"ngx_kqueue_process_events: unknown filter %d" _
|
||||||
|
event_list[i].filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ngx_add_timer(ngx_event_t *ev, u_int timer)
|
||||||
|
{
|
||||||
|
ngx_event_t *e;
|
||||||
|
|
||||||
|
for (e = timer_queue.timer_next;
|
||||||
|
e != &timer_queue && timer > e->timer_delta;
|
||||||
|
e = e->timer_next)
|
||||||
|
timer -= e->timer_delta;
|
||||||
|
|
||||||
|
ev->timer_delta = timer;
|
||||||
|
|
||||||
|
ev->timer_next = e;
|
||||||
|
ev->timer_prev = e->timer_prev;
|
||||||
|
|
||||||
|
e->timer_prev->timer_next = ev;
|
||||||
|
e->timer_prev = ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ngx_inline ngx_del_timer(ngx_event_t *ev)
|
||||||
|
{
|
||||||
|
if (ev->timer_prev)
|
||||||
|
ev->timer_prev->timer_next = ev->timer_next;
|
||||||
|
|
||||||
|
if (ev->timer_next) {
|
||||||
|
ev->timer_next->timer_prev = ev->timer_prev;
|
||||||
|
ev->timer_prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->timer_prev)
|
||||||
|
ev->timer_next = NULL;
|
||||||
|
}
|
16
src/event/modules/ngx_kqueue_module.h
Normal file
16
src/event/modules/ngx_kqueue_module.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _NGX_KQUEUE_MODULE_H_INCLUDED_
|
||||||
|
#define _NGX_KQUEUE_MODULE_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_event.h>
|
||||||
|
|
||||||
|
void ngx_kqueue_init(int max_connections, ngx_log_t *log);
|
||||||
|
int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags);
|
||||||
|
int ngx_kqueue_del_event(ngx_event_t *ev, int event);
|
||||||
|
int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags);
|
||||||
|
int ngx_kqueue_process_events(ngx_log_t *log);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_KQUEUE_MODULE_H_INCLUDED_ */
|
17
src/event/modules/ngx_overlapped_module.c
Normal file
17
src/event/modules/ngx_overlapped_module.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
int ngx_overlapped_process_events(ngx_log_t *log)
|
||||||
|
{
|
||||||
|
if (acceptex)
|
||||||
|
event = SleepEx(timer, 1);
|
||||||
|
else
|
||||||
|
event = WSAWaitForMultipleEvents(n_events, events, 0, timer, 1);
|
||||||
|
|
||||||
|
if (event == WSA_IO_COMPLETION)
|
||||||
|
look ready array
|
||||||
|
}
|
||||||
|
|
||||||
|
void CALLBACK overlapped_completion_procedure(DWORD error, DWORD nbytes,
|
||||||
|
LPWSAOVERLAPPED overlapped, DWORD flags)
|
||||||
|
{
|
||||||
|
push overlapped;
|
||||||
|
}
|
349
src/event/modules/ngx_select_module.c
Normal file
349
src/event/modules/ngx_select_module.c
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_time.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
#include <ngx_event.h>
|
||||||
|
#include <ngx_select_module.h>
|
||||||
|
|
||||||
|
static fd_set master_read_fds;
|
||||||
|
static fd_set master_write_fds;
|
||||||
|
static fd_set work_read_fds;
|
||||||
|
static fd_set work_write_fds;
|
||||||
|
|
||||||
|
#if (WIN32)
|
||||||
|
static int max_read;
|
||||||
|
static int max_write;
|
||||||
|
#else
|
||||||
|
static int max_fd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static ngx_event_t event_queue;
|
||||||
|
static ngx_event_t timer_queue;
|
||||||
|
|
||||||
|
|
||||||
|
static void ngx_add_timer(ngx_event_t *ev, u_int timer);
|
||||||
|
static void ngx_inline ngx_del_timer(ngx_event_t *ev);
|
||||||
|
|
||||||
|
static fd_set *ngx_select_get_fd_set(ngx_socket_t fd, int event,
|
||||||
|
ngx_log_t *log);
|
||||||
|
|
||||||
|
void ngx_select_init(int max_connections, ngx_log_t *log)
|
||||||
|
{
|
||||||
|
#if (WIN32)
|
||||||
|
if (max_connections > FD_SETSIZE)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, log, 0,
|
||||||
|
"ngx_select_init: maximum number of descriptors "
|
||||||
|
"supported by select() is %d",
|
||||||
|
FD_SETSIZE);
|
||||||
|
#else
|
||||||
|
if (max_connections >= FD_SETSIZE)
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, log, 0,
|
||||||
|
"ngx_select_init: maximum descriptor number"
|
||||||
|
"supported by select() is %d",
|
||||||
|
FD_SETSIZE - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FD_ZERO(&master_read_fds);
|
||||||
|
FD_ZERO(&master_write_fds);
|
||||||
|
|
||||||
|
event_queue.prev = &event_queue;
|
||||||
|
event_queue.next = &event_queue;
|
||||||
|
|
||||||
|
timer_queue.timer_prev = &timer_queue;
|
||||||
|
timer_queue.timer_next = &timer_queue;
|
||||||
|
|
||||||
|
ngx_event_actions.add = ngx_select_add_event;
|
||||||
|
ngx_event_actions.del = ngx_select_del_event;
|
||||||
|
ngx_event_actions.process = ngx_select_process_events;
|
||||||
|
|
||||||
|
#if (WIN32)
|
||||||
|
max_read = max_write = 0;
|
||||||
|
#else
|
||||||
|
max_fd = -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags)
|
||||||
|
{
|
||||||
|
fd_set *fds;
|
||||||
|
ngx_connection_t *cn = (ngx_connection_t *) ev->data;
|
||||||
|
|
||||||
|
if (event == NGX_TIMER_EVENT) {
|
||||||
|
ngx_add_timer(ev, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_assert((flags != NGX_ONESHOT_EVENT), return -1, ev->log,
|
||||||
|
"ngx_select_add_event: NGX_ONESHOT_EVENT is not supported");
|
||||||
|
|
||||||
|
fds = ngx_select_get_fd_set(cn->fd, event, ev->log);
|
||||||
|
if (fds == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ev->prev = &event_queue;
|
||||||
|
ev->next = event_queue.next;
|
||||||
|
event_queue.next->prev = ev;
|
||||||
|
event_queue.next = ev;
|
||||||
|
|
||||||
|
FD_SET(cn->fd, fds);
|
||||||
|
|
||||||
|
#if (WIN32)
|
||||||
|
switch (event) {
|
||||||
|
case NGX_READ_EVENT:
|
||||||
|
max_read++;
|
||||||
|
break;
|
||||||
|
case NGX_WRITE_EVENT:
|
||||||
|
max_write++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (max_fd != -1 && max_fd < cn->fd)
|
||||||
|
max_fd = cn->fd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_select_del_event(ngx_event_t *ev, int event)
|
||||||
|
{
|
||||||
|
fd_set *fds;
|
||||||
|
ngx_connection_t *cn = (ngx_connection_t *) ev->data;
|
||||||
|
|
||||||
|
if (event == NGX_TIMER_EVENT) {
|
||||||
|
ngx_del_timer(ev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fds = ngx_select_get_fd_set(cn->fd, event, ev->log);
|
||||||
|
if (fds == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ev->prev)
|
||||||
|
ev->prev->next = ev->next;
|
||||||
|
|
||||||
|
if (ev->next) {
|
||||||
|
ev->next->prev = ev->prev;
|
||||||
|
ev->prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->prev)
|
||||||
|
ev->next = NULL;
|
||||||
|
|
||||||
|
FD_CLR(cn->fd, fds);
|
||||||
|
|
||||||
|
#if (WIN32)
|
||||||
|
switch (event) {
|
||||||
|
case NGX_READ_EVENT:
|
||||||
|
max_read--;
|
||||||
|
break;
|
||||||
|
case NGX_WRITE_EVENT:
|
||||||
|
max_write--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (max_fd == cn->fd)
|
||||||
|
max_fd = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fd_set *ngx_select_get_fd_set(ngx_socket_t fd, int event, ngx_log_t *log)
|
||||||
|
{
|
||||||
|
ngx_log_debug(log, "ngx_select_get_fd_set: %d %d" _ fd _ event);
|
||||||
|
|
||||||
|
#if !(WIN32)
|
||||||
|
if (fd >= FD_SETSIZE) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, log, 0,
|
||||||
|
"ngx_select_get_event: maximum descriptor number"
|
||||||
|
"supported by select() is %d",
|
||||||
|
FD_SETSIZE - 1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case NGX_READ_EVENT:
|
||||||
|
#if (WIN32)
|
||||||
|
if (max_read >= FD_SETSIZE) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, log, 0,
|
||||||
|
"ngx_select_get_event: maximum number of descriptors "
|
||||||
|
"supported by select() is %d",
|
||||||
|
FD_SETSIZE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return &master_read_fds;
|
||||||
|
|
||||||
|
case NGX_WRITE_EVENT:
|
||||||
|
#if (WIN32)
|
||||||
|
if (max_write >= FD_SETSIZE) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, log, 0,
|
||||||
|
"ngx_select_get_event: maximum number of descriptors "
|
||||||
|
"supported by select() is %d",
|
||||||
|
FD_SETSIZE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return &master_write_fds;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ngx_assert(0, return NULL, log,
|
||||||
|
"ngx_select_get_fd_set: invalid event %d" _ event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_select_process_events(ngx_log_t *log)
|
||||||
|
{
|
||||||
|
int ready, found;
|
||||||
|
u_int timer, delta;
|
||||||
|
ngx_event_t *ev, *nx;
|
||||||
|
ngx_connection_t *cn;
|
||||||
|
struct timeval tv, *tp;
|
||||||
|
|
||||||
|
work_read_fds = master_read_fds;
|
||||||
|
work_write_fds = master_write_fds;
|
||||||
|
|
||||||
|
if (timer_queue.timer_next != &timer_queue) {
|
||||||
|
timer = timer_queue.timer_next->timer_delta;
|
||||||
|
tv.tv_sec = timer / 1000;
|
||||||
|
tv.tv_usec = (timer % 1000) * 1000;
|
||||||
|
tp = &tv;
|
||||||
|
|
||||||
|
delta = ngx_msec();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
timer = 0;
|
||||||
|
tp = NULL;
|
||||||
|
delta = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !(WIN32)
|
||||||
|
if (max_fd == -1) {
|
||||||
|
for (ev = event_queue.next; ev != &event_queue; ev = ev->next) {
|
||||||
|
cn = (ngx_connection_t *) ev->data;
|
||||||
|
if (max_fd < cn->fd)
|
||||||
|
max_fd = cn->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_select_process_events: change max_fd: %d" _
|
||||||
|
max_fd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_select_process_events: timer: %d" _ timer);
|
||||||
|
|
||||||
|
#if (WIN32)
|
||||||
|
if ((ready = select(0, &work_read_fds, &work_write_fds, NULL, tp))
|
||||||
|
#else
|
||||||
|
if ((ready = select(max_fd + 1, &work_read_fds, &work_write_fds, NULL, tp))
|
||||||
|
#endif
|
||||||
|
== -1) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
|
||||||
|
"ngx_select_process_events: select failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_select_process_events: ready %d" _ ready);
|
||||||
|
|
||||||
|
if (timer) {
|
||||||
|
delta = ngx_msec() - delta;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_assert((ready != 0), return -1, log,
|
||||||
|
"ngx_select_process_events: "
|
||||||
|
"select returns no events without timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_select_process_events: "
|
||||||
|
"timer: %d, delta: %d" _ timer _ delta);
|
||||||
|
|
||||||
|
if (timer) {
|
||||||
|
if (delta >= timer) {
|
||||||
|
for (ev = timer_queue.timer_next;
|
||||||
|
ev != &timer_queue && delta >= ev->timer_delta;
|
||||||
|
/* void */)
|
||||||
|
{
|
||||||
|
delta -= ev->timer_delta;
|
||||||
|
nx = ev->timer_next;
|
||||||
|
ngx_del_timer(ev);
|
||||||
|
if (ev->timer_handler(ev) == -1)
|
||||||
|
ev->close_handler(ev);
|
||||||
|
ev = nx;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
timer_queue.timer_next->timer_delta -= delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ev = event_queue.next; ev != &event_queue; ev = ev->next) {
|
||||||
|
cn = (ngx_connection_t *) ev->data;
|
||||||
|
found = 0;
|
||||||
|
|
||||||
|
if (ev->write) {
|
||||||
|
if (FD_ISSET(cn->fd, &work_write_fds)) {
|
||||||
|
ngx_log_debug(log, "ngx_select_process_events: write %d" _
|
||||||
|
cn->fd);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (FD_ISSET(cn->fd, &work_read_fds)) {
|
||||||
|
ngx_log_debug(log, "ngx_select_process_events: read %d" _
|
||||||
|
cn->fd);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
ev->ready = 1;
|
||||||
|
if (ev->event_handler(ev) == -1)
|
||||||
|
ev->close_handler(ev);
|
||||||
|
|
||||||
|
ready--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_assert((ready == 0), return 0, log,
|
||||||
|
"ngx_select_process_events: ready != events");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ngx_add_timer(ngx_event_t *ev, u_int timer)
|
||||||
|
{
|
||||||
|
ngx_event_t *e;
|
||||||
|
|
||||||
|
for (e = timer_queue.timer_next;
|
||||||
|
e != &timer_queue && timer > e->timer_delta;
|
||||||
|
e = e->timer_next)
|
||||||
|
timer -= e->timer_delta;
|
||||||
|
|
||||||
|
ev->timer_delta = timer;
|
||||||
|
|
||||||
|
ev->timer_next = e;
|
||||||
|
ev->timer_prev = e->timer_prev;
|
||||||
|
|
||||||
|
e->timer_prev->timer_next = ev;
|
||||||
|
e->timer_prev = ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ngx_inline ngx_del_timer(ngx_event_t *ev)
|
||||||
|
{
|
||||||
|
if (ev->timer_prev)
|
||||||
|
ev->timer_prev->timer_next = ev->timer_next;
|
||||||
|
|
||||||
|
if (ev->timer_next) {
|
||||||
|
ev->timer_next->timer_prev = ev->timer_prev;
|
||||||
|
ev->timer_prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->timer_prev)
|
||||||
|
ev->timer_next = NULL;
|
||||||
|
}
|
16
src/event/modules/ngx_select_module.h
Normal file
16
src/event/modules/ngx_select_module.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _NGX_SELECT_MODULE_H_INCLUDED_
|
||||||
|
#define _NGX_SELECT_MODULE_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_event.h>
|
||||||
|
|
||||||
|
void ngx_select_init(int max_connections, ngx_log_t *log);
|
||||||
|
int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags);
|
||||||
|
int ngx_select_del_event(ngx_event_t *ev, int event);
|
||||||
|
int ngx_select_set_event(ngx_event_t *ev, int filter, u_int flags);
|
||||||
|
int ngx_select_process_events(ngx_log_t *log);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_SELECT_MODULE_H_INCLUDED_ */
|
87
src/event/ngx_event.c
Normal file
87
src/event/ngx_event.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
#include <ngx_event.h>
|
||||||
|
#include <ngx_event_accept.h>
|
||||||
|
|
||||||
|
#include <ngx_select_module.h>
|
||||||
|
#if (HAVE_KQUEUE)
|
||||||
|
#include <ngx_kqueue_module.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
ngx_connection_t *ngx_connections;
|
||||||
|
ngx_event_t *ngx_read_events, *ngx_write_events;
|
||||||
|
|
||||||
|
#if !(USE_KQUEUE)
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
ngx_event_type_e ngx_event_type = NGX_SELECT_EVENT;
|
||||||
|
#else
|
||||||
|
ngx_event_type_e ngx_event_type = NGX_KQUEUE_EVENT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngx_event_actions_t ngx_event_actions;
|
||||||
|
|
||||||
|
/* ngx_event_type_e order */
|
||||||
|
static void (*ngx_event_init[]) (int max_connections, ngx_log_t *log) = {
|
||||||
|
ngx_select_init,
|
||||||
|
#if (HAVE_POLL)
|
||||||
|
ngx_poll_init,
|
||||||
|
#endif
|
||||||
|
#if (HAVE_KQUEUE)
|
||||||
|
ngx_kqueue_init
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* USE_KQUEUE */
|
||||||
|
|
||||||
|
|
||||||
|
void ngx_worker(ngx_listen_t *sock, int n, ngx_pool_t *pool, ngx_log_t *log)
|
||||||
|
{
|
||||||
|
int i, fd;
|
||||||
|
|
||||||
|
/* per group */
|
||||||
|
int max_connections = 512;
|
||||||
|
|
||||||
|
ngx_init_events(max_connections, log);
|
||||||
|
|
||||||
|
ngx_read_events = ngx_alloc(sizeof(ngx_event_t) * max_connections, log);
|
||||||
|
ngx_write_events = ngx_alloc(sizeof(ngx_event_t) * max_connections, log);
|
||||||
|
ngx_connections = ngx_alloc(sizeof(ngx_connection_t)
|
||||||
|
* max_connections, log);
|
||||||
|
|
||||||
|
/* for each listening socket */
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
fd = sock[i].fd;
|
||||||
|
|
||||||
|
ngx_memzero(&ngx_read_events[fd], sizeof(ngx_event_t));
|
||||||
|
ngx_memzero(&ngx_write_events[fd], sizeof(ngx_event_t));
|
||||||
|
ngx_memzero(&ngx_connections[fd], sizeof(ngx_connection_t));
|
||||||
|
|
||||||
|
ngx_connections[fd].fd = fd;
|
||||||
|
ngx_connections[fd].server = sock[i].server;
|
||||||
|
ngx_connections[fd].read = (void *) &ngx_read_events[fd].data;
|
||||||
|
ngx_read_events[fd].data = &ngx_connections[fd];
|
||||||
|
ngx_read_events[fd].log = ngx_connections[fd].log = sock[i].log;
|
||||||
|
ngx_read_events[fd].data = &ngx_connections[fd];
|
||||||
|
ngx_read_events[fd].event_handler = &ngx_event_accept;
|
||||||
|
ngx_read_events[fd].listening = 1;
|
||||||
|
|
||||||
|
ngx_read_events[fd].available = 0;
|
||||||
|
|
||||||
|
#if (HAVE_DEFERRED_ACCEPT)
|
||||||
|
ngx_read_events[fd].accept_filter = sock->accept_filter;
|
||||||
|
#endif
|
||||||
|
ngx_add_event(&ngx_read_events[fd], NGX_READ_EVENT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ngx_log_debug(log, "ngx_worker cycle");
|
||||||
|
|
||||||
|
ngx_process_events(log);
|
||||||
|
}
|
||||||
|
}
|
127
src/event/ngx_event.h
Normal file
127
src/event/ngx_event.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#ifndef _NGX_EVENT_H_INCLUDED_
|
||||||
|
#define _NGX_EVENT_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
|
||||||
|
typedef struct ngx_event_s ngx_event_t;
|
||||||
|
|
||||||
|
struct ngx_event_s {
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
int (*event_handler)(ngx_event_t *ev);
|
||||||
|
int (*close_handler)(ngx_event_t *ev);
|
||||||
|
void *context;
|
||||||
|
char *action;
|
||||||
|
|
||||||
|
ngx_event_t *prev; /* queue in select(), poll() */
|
||||||
|
ngx_event_t *next;
|
||||||
|
|
||||||
|
int (*timer_handler)(ngx_event_t *ev);
|
||||||
|
ngx_event_t *timer_prev;
|
||||||
|
ngx_event_t *timer_next;
|
||||||
|
|
||||||
|
u_int timer_delta;
|
||||||
|
u_int timer;
|
||||||
|
|
||||||
|
ngx_log_t *log;
|
||||||
|
|
||||||
|
int available; /* kqueue only: */
|
||||||
|
/* accept: number of sockets that wait */
|
||||||
|
/* to be accepted */
|
||||||
|
/* read: bytes to read */
|
||||||
|
/* write: available space in buffer */
|
||||||
|
/* otherwise: */
|
||||||
|
/* accept: 1 if accept many, 0 otherwise */
|
||||||
|
|
||||||
|
/* flags - int are probably faster on write then bits ??? */
|
||||||
|
unsigned listening:1;
|
||||||
|
unsigned write:1;
|
||||||
|
|
||||||
|
unsigned ready:1;
|
||||||
|
unsigned timedout:1;
|
||||||
|
unsigned process:1;
|
||||||
|
unsigned read_discarded:1;
|
||||||
|
|
||||||
|
unsigned unexpected_eof:1;
|
||||||
|
|
||||||
|
#if (HAVE_DEFERRED_ACCEPT)
|
||||||
|
unsigned accept_filter:1;
|
||||||
|
#endif
|
||||||
|
#if (HAVE_KQUEUE)
|
||||||
|
unsigned eof:1;
|
||||||
|
int errno;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NGX_SELECT_EVENT = 0,
|
||||||
|
#if (HAVE_POLL)
|
||||||
|
NGX_POLL_EVENT,
|
||||||
|
#endif
|
||||||
|
#if (HAVE_KQUEUE)
|
||||||
|
NGX_KQUEUE_EVENT,
|
||||||
|
#endif
|
||||||
|
} ngx_event_type_e ;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
#if (HAVE_KQUEUE)
|
||||||
|
|
||||||
|
#define NGX_READ_EVENT EVFILT_READ
|
||||||
|
#define NGX_WRITE_EVENT EVFILT_WRITE
|
||||||
|
#define NGX_TIMER_EVENT (-EVFILT_SYSCOUNT - 1)
|
||||||
|
|
||||||
|
#define NGX_ONESHOT_EVENT EV_ONESHOT
|
||||||
|
#define NGX_CLEAR_EVENT EV_CLEAR
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define NGX_READ_EVENT 0
|
||||||
|
#define NGX_WRITE_EVENT 1
|
||||||
|
#define NGX_TIMER_EVENT 2
|
||||||
|
|
||||||
|
#define NGX_ONESHOT_EVENT 1
|
||||||
|
#define NGX_CLEAR_EVENT 2
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
||||||
|
#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
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
extern ngx_event_t *ngx_read_events;
|
||||||
|
extern ngx_event_t *ngx_write_events;
|
||||||
|
extern ngx_connection_t *ngx_connections;
|
||||||
|
|
||||||
|
#if !(USE_KQUEUE)
|
||||||
|
extern ngx_event_actions_t ngx_event_actions;
|
||||||
|
extern ngx_event_type_e ngx_event_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void ngx_worker(ngx_listen_t *sock, int n, ngx_pool_t *pool, ngx_log_t *log);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_EVENT_H_INCLUDED_ */
|
83
src/event/ngx_event_accept.c
Normal file
83
src/event/ngx_event_accept.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
#include <ngx_event.h>
|
||||||
|
#include <ngx_event_close.h>
|
||||||
|
#include <ngx_event_accept.h>
|
||||||
|
|
||||||
|
|
||||||
|
int ngx_event_accept(ngx_event_t *ev)
|
||||||
|
{
|
||||||
|
ngx_err_t err;
|
||||||
|
ngx_socket_t s;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
int addrlen = sizeof(struct sockaddr_in);
|
||||||
|
ngx_connection_t *cn = (ngx_connection_t *) ev->data;
|
||||||
|
|
||||||
|
ngx_log_debug(ev->log, "ngx_event_accept: accept ready: %d" _
|
||||||
|
ev->available);
|
||||||
|
|
||||||
|
ev->ready = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((s = accept(cn->fd, (struct sockaddr *) &addr, &addrlen)) == -1) {
|
||||||
|
err = ngx_socket_errno;
|
||||||
|
if (err == NGX_EAGAIN) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, ev->log, err,
|
||||||
|
"ngx_event_accept: EAGAIN while accept");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_ERR, ev->log, err,
|
||||||
|
"ngx_event_accept: accept failed");
|
||||||
|
/* if we return -1 listen socket would be closed */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug(ev->log, "ngx_event_accept: accepted socket: %d" _ s);
|
||||||
|
|
||||||
|
ngx_memzero(&ngx_read_events[s], sizeof(ngx_event_t));
|
||||||
|
ngx_memzero(&ngx_write_events[s], sizeof(ngx_event_t));
|
||||||
|
ngx_memzero(&ngx_connections[s], sizeof(ngx_connection_t));
|
||||||
|
|
||||||
|
ngx_read_events[s].data = ngx_write_events[s].data
|
||||||
|
= &ngx_connections[s];
|
||||||
|
ngx_connections[s].read = &ngx_read_events[s];
|
||||||
|
ngx_connections[s].write = &ngx_write_events[s];
|
||||||
|
|
||||||
|
ngx_connections[s].fd = s;
|
||||||
|
ngx_read_events[s].unexpected_eof = 1;
|
||||||
|
ngx_write_events[s].ready = 1;
|
||||||
|
|
||||||
|
ngx_write_events[s].timer = ngx_read_events[s].timer = 10000;
|
||||||
|
|
||||||
|
ngx_write_events[s].timer_handler =
|
||||||
|
ngx_read_events[s].timer_handler = ngx_event_close;
|
||||||
|
|
||||||
|
ngx_write_events[s].close_handler =
|
||||||
|
ngx_read_events[s].close_handler = ngx_event_close;
|
||||||
|
|
||||||
|
ngx_connections[s].server = cn->server;
|
||||||
|
ngx_connections[s].servers = cn->servers;
|
||||||
|
ngx_connections[s].log =
|
||||||
|
ngx_read_events[s].log = ngx_write_events[s].log = ev->log;
|
||||||
|
|
||||||
|
#if (HAVE_DEFERRED_ACCEPT)
|
||||||
|
if (ev->accept_filter)
|
||||||
|
ngx_read_events[s].ready = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cn->server->handler(&ngx_connections[s]);
|
||||||
|
|
||||||
|
#if (HAVE_KQUEUE)
|
||||||
|
#if !(USE_KQUEUE)
|
||||||
|
if (ngx_event_type == NGX_KQUEUE_EVENT)
|
||||||
|
#endif
|
||||||
|
ev->available--;
|
||||||
|
#endif
|
||||||
|
} while (ev->available);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
10
src/event/ngx_event_accept.h
Normal file
10
src/event/ngx_event_accept.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _NGX_EVENT_ACCEPT_H_INCLUDED_
|
||||||
|
#define _NGX_EVENT_ACCEPT_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_event.h>
|
||||||
|
|
||||||
|
int ngx_event_accept(ngx_event_t *ev);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_EVENT_ACCEPT_H_INCLUDED_ */
|
29
src/event/ngx_event_close.c
Normal file
29
src/event/ngx_event_close.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
#include <ngx_event_close.h>
|
||||||
|
|
||||||
|
|
||||||
|
int ngx_event_close(ngx_event_t *ev)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
ngx_connection_t *cn = (ngx_connection_t *) ev->data;
|
||||||
|
|
||||||
|
ngx_assert((cn->fd != -1), return -1, ev->log,
|
||||||
|
"ngx_event_close: already closed");
|
||||||
|
|
||||||
|
if ((rc = ngx_close_socket(cn->fd)) == -1)
|
||||||
|
ngx_log_error(NGX_LOG_ERR, ev->log, ngx_socket_errno,
|
||||||
|
"ngx_event_close: close failed");
|
||||||
|
|
||||||
|
if (cn->read->next)
|
||||||
|
ngx_del_event(cn->read, NGX_READ_EVENT);
|
||||||
|
|
||||||
|
if (cn->write->next)
|
||||||
|
ngx_del_event(cn->write, NGX_WRITE_EVENT);
|
||||||
|
|
||||||
|
cn->fd = -1;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
10
src/event/ngx_event_close.h
Normal file
10
src/event/ngx_event_close.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _NGX_EVENT_CLOSE_H_INCLUDED_
|
||||||
|
#define _NGX_EVENT_CLOSE_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_event.h>
|
||||||
|
|
||||||
|
int ngx_event_close(ngx_event_t *ev);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_EVENT_CLOSE_H_INCLUDED_ */
|
55
src/event/ngx_event_read.c
Normal file
55
src/event/ngx_event_read.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_errno.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
|
||||||
|
int ngx_event_recv(ngx_connection_t *c, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
ngx_err_t err;
|
||||||
|
ngx_event_t *ev = c->read;
|
||||||
|
|
||||||
|
#if (HAVE_KQUEUE)
|
||||||
|
#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);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
n = recv(c->fd, buf, size, 0);
|
||||||
|
|
||||||
|
if (n == -1) {
|
||||||
|
err = ngx_socket_errno;
|
||||||
|
|
||||||
|
if (err == NGX_EAGAIN) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, ev->log, err,
|
||||||
|
"ngx_event_recv: EAGAIN while %s", ev->log->action);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_INFO, ev->log, err,
|
||||||
|
"ngx_event_recv: recv failed while %s", ev->log->action);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (HAVE_KQUEUE)
|
||||||
|
#if !(USE_KQUEUE)
|
||||||
|
if (ngx_event_type == NGX_KQUEUE_EVENT)
|
||||||
|
#endif
|
||||||
|
ev->available -= n;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
136
src/event/ngx_event_write.c
Normal file
136
src/event/ngx_event_write.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
#include <ngx_array.h>
|
||||||
|
#include <ngx_hunk.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
#include <ngx_sendv.h>
|
||||||
|
#include <ngx_sendfile.h>
|
||||||
|
#include <ngx_event_write.h>
|
||||||
|
|
||||||
|
|
||||||
|
ngx_chain_t *ngx_event_writer(ngx_connection_t *cn, ngx_chain_t *in,
|
||||||
|
off_t flush)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char *last;
|
||||||
|
off_t sent;
|
||||||
|
ngx_iovec_t *iov;
|
||||||
|
ngx_array_t *header, *trailer;
|
||||||
|
ngx_hunk_t *file;
|
||||||
|
ngx_chain_t *ch;
|
||||||
|
|
||||||
|
ch = in;
|
||||||
|
file = NULL;
|
||||||
|
|
||||||
|
ngx_test_null(header, ngx_create_array(cn->pool, 10, sizeof(ngx_iovec_t)),
|
||||||
|
(ngx_chain_t *) -1);
|
||||||
|
|
||||||
|
ngx_test_null(trailer, ngx_create_array(cn->pool, 10, sizeof(ngx_iovec_t)),
|
||||||
|
(ngx_chain_t *) -1);
|
||||||
|
|
||||||
|
do {
|
||||||
|
header->nelts = 0;
|
||||||
|
trailer->nelts = 0;
|
||||||
|
|
||||||
|
if (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)) {
|
||||||
|
last = NULL;
|
||||||
|
iov = NULL;
|
||||||
|
|
||||||
|
while (ch
|
||||||
|
&& (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = ch->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch && (ch->hunk->type & NGX_HUNK_FILE)) {
|
||||||
|
file = ch->hunk;
|
||||||
|
ch = ch->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (HAVE_MAX_SENDFILE_IOVEC)
|
||||||
|
if (file && header->nelts > HAVE_MAX_SENDFILE_IOVEC) {
|
||||||
|
rc = ngx_sendv(cn->fd, (ngx_iovec_t *) header->elts, header->nelts,
|
||||||
|
&sent);
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
if (ch && ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)) {
|
||||||
|
last = NULL;
|
||||||
|
iov = NULL;
|
||||||
|
|
||||||
|
while (ch
|
||||||
|
&& (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = ch->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
(ngx_iovec_t *) trailer->elts, trailer->nelts,
|
||||||
|
&sent, cn->log);
|
||||||
|
} else {
|
||||||
|
rc = ngx_sendv(cn->fd, (ngx_iovec_t *) header->elts,
|
||||||
|
header->nelts, (size_t *) &sent);
|
||||||
|
}
|
||||||
|
#if (HAVE_MAX_SENDFILE_IOVEC)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* save sent for logging */
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
return (ngx_chain_t *) -1;
|
||||||
|
|
||||||
|
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;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch->hunk->pos.f += sent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (flush > 0);
|
||||||
|
|
||||||
|
ngx_destroy_array(trailer);
|
||||||
|
ngx_destroy_array(header);
|
||||||
|
|
||||||
|
return ch;
|
||||||
|
}
|
13
src/event/ngx_event_write.h
Normal file
13
src/event/ngx_event_write.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _NGX_EVENT_WRITE_H_INCLUDED_
|
||||||
|
#define _NGX_EVENT_WRITE_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_hunk.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
|
||||||
|
ngx_chain_t *ngx_event_write(ngx_connection_t *cn, ngx_chain_t *in,
|
||||||
|
off_t flush);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_EVENT_WRITE_H_INCLUDED_ */
|
123
src/http/modules/ngx_http_index_handler.c
Normal file
123
src/http/modules/ngx_http_index_handler.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
#include <ngx_strings.h>
|
||||||
|
#include <ngx_open.h>
|
||||||
|
#include <ngx_stat.h>
|
||||||
|
|
||||||
|
#include <ngx_http.h>
|
||||||
|
|
||||||
|
int ngx_http_index_handler(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
int index_len, err, i;
|
||||||
|
char *name, *loc, *file
|
||||||
|
ngx_file_t fd;
|
||||||
|
|
||||||
|
ngx_http_index_t *index;
|
||||||
|
ngx_http_index_handler_loc_conf_t *cf;
|
||||||
|
|
||||||
|
cf = (ngx_http_index_handler_loc_conf_t *)
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* URI without / on the end - check directory */
|
||||||
|
if (index_len == 0) {
|
||||||
|
|
||||||
|
if (ngx_stat(name, &r->stat) == -1) {
|
||||||
|
err = ngx_errno;
|
||||||
|
ngx_log_error(GX_LOG_ERR, r->connection->log, err,
|
||||||
|
"ngx_http_handler: " ngx_stat_n " %s failed", name);
|
||||||
|
|
||||||
|
if (err == NGX_ENOENT)
|
||||||
|
return NGX_HTTP_NOT_FOUND;
|
||||||
|
else
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_is_dir(r->stat)) {
|
||||||
|
*file++ = '/';
|
||||||
|
*file = '\0';
|
||||||
|
r->headers_out->location = loc;
|
||||||
|
return NGX_HTTP_MOVED_PERMANENTLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->file = name;
|
||||||
|
r->stat_valid = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for index file */
|
||||||
|
index = (ngx_http_index_t *) cf->indices->elts;
|
||||||
|
for (i = 0; i < cf->indices->nelts; i++) {
|
||||||
|
ngx_memcpy(file, index[i].name; index[i].len);
|
||||||
|
|
||||||
|
fd = ngx_open(name, O_RDONLY);
|
||||||
|
if (fd != -1) {
|
||||||
|
r->file = name;
|
||||||
|
r->fd = fd;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_HTTP_FORBIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
84
src/http/ngx_http.h
Normal file
84
src/http/ngx_http.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#ifndef _NGX_HTTP_H_INCLUDED_
|
||||||
|
#define _NGX_HTTP_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_SYS_ERROR -1
|
||||||
|
#define NGX_HTTP_INVALID_METHOD -2
|
||||||
|
#define NGX_HTTP_INVALID_REQUEST -3
|
||||||
|
#define NGX_HTTP_INVALID_HEADER -4
|
||||||
|
|
||||||
|
#define NGX_HTTP_GET 1
|
||||||
|
#define NGX_HTTP_HEAD 2
|
||||||
|
#define NGX_HTTP_POST 3
|
||||||
|
|
||||||
|
#define NGX_HTTP_CONN_CLOSE 0
|
||||||
|
#define NGX_HTTP_CONN_KEEP_ALIVE 1
|
||||||
|
|
||||||
|
#define NGX_HTTP_OK 200
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *buff;
|
||||||
|
char *pos;
|
||||||
|
char *last;
|
||||||
|
char *end;
|
||||||
|
} ngx_buff_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int status;
|
||||||
|
int connection;
|
||||||
|
size_t content_length;
|
||||||
|
char *content_type;
|
||||||
|
char *charset;
|
||||||
|
char *etag;
|
||||||
|
time_t date;
|
||||||
|
time_t last_modified;
|
||||||
|
} ngx_http_header_out_t;
|
||||||
|
|
||||||
|
typedef struct ngx_http_request_s ngx_http_request_t;
|
||||||
|
|
||||||
|
struct ngx_http_request_s {
|
||||||
|
int method;
|
||||||
|
|
||||||
|
int http_version;
|
||||||
|
int http_major;
|
||||||
|
int http_minor;
|
||||||
|
|
||||||
|
char *uri;
|
||||||
|
ngx_http_request_t *main;
|
||||||
|
|
||||||
|
ngx_connection_t *connection;
|
||||||
|
ngx_buff_t *buff;
|
||||||
|
ngx_pool_t *pool;
|
||||||
|
|
||||||
|
/* internal */
|
||||||
|
unsigned unusual_uri:1;
|
||||||
|
unsigned complex_uri:1;
|
||||||
|
|
||||||
|
int state;
|
||||||
|
char *uri_start;
|
||||||
|
char *uri_end;
|
||||||
|
char *uri_ext;
|
||||||
|
char *args_start;
|
||||||
|
char *header_name_start;
|
||||||
|
char *header_name_end;
|
||||||
|
char *header_start;
|
||||||
|
char *header_end;
|
||||||
|
#ifdef NGX_EVENT
|
||||||
|
int (*state_handler)(ngx_http_request_t *r);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_INDEX "index.html"
|
||||||
|
|
||||||
|
|
||||||
|
int ngx_http_init_connection(ngx_connection_t *c);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_HTTP_H_INCLUDED_ */
|
273
src/http/ngx_http_event.c
Normal file
273
src/http/ngx_http_event.c
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_alloc.h>
|
||||||
|
#include <ngx_hunk.h>
|
||||||
|
#include <ngx_connection.h>
|
||||||
|
|
||||||
|
#include <ngx_http.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
ngx_read should check errors (if we ask) and return
|
||||||
|
-2 EAGAIN
|
||||||
|
-1 error
|
||||||
|
0 EOF
|
||||||
|
>0 number of bytes
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ngx_http_init_connection(ngx_connection_t *c);
|
||||||
|
static int ngx_http_init_request(ngx_event_t *ev);
|
||||||
|
static int ngx_http_process_request(ngx_event_t *ev);
|
||||||
|
|
||||||
|
static int ngx_process_http_request_line(ngx_http_request_t *r);
|
||||||
|
static int ngx_process_http_request_header(ngx_http_request_t *r);
|
||||||
|
|
||||||
|
static int ngx_process_http_request(ngx_http_request_t *r);
|
||||||
|
|
||||||
|
static int ngx_http_close_request(ngx_event_t *ev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns
|
||||||
|
-1 if error
|
||||||
|
0 need more data or EOF (filter is deleted)
|
||||||
|
1 there is unread data
|
||||||
|
*/
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
/* XXX: ev->timer ? */
|
||||||
|
if (ngx_add_event(ev, NGX_TIMER_EVENT, ev->timer) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#if (HAVE_DEFERRED_ACCEPT)
|
||||||
|
if (ev->ready)
|
||||||
|
return ngx_http_init_request(ev);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#if (NGX_CLEAR_EVENT)
|
||||||
|
return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
|
||||||
|
#else
|
||||||
|
return ngx_add_event(ev, NGX_READ_EVENT, NGX_ONESHOT_EVENT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
int ngx_http_init_request(ngx_event_t *ev)
|
||||||
|
{
|
||||||
|
ngx_connection_t *c = (ngx_connection_t *) ev->data;
|
||||||
|
ngx_http_request_t *r;
|
||||||
|
|
||||||
|
ngx_log_debug(ev->log, "ngx_http_init_request: entered");
|
||||||
|
|
||||||
|
ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)), -1);
|
||||||
|
|
||||||
|
c->data = r;
|
||||||
|
r->connection = c;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
r->buff->pos = r->buff->last = r->buff->buff;
|
||||||
|
r->buff->end = r->buff->buff + c->server->buff_size;
|
||||||
|
|
||||||
|
r->state_handler = ngx_process_http_request_line;
|
||||||
|
|
||||||
|
ev->event_handler = ngx_http_process_request;
|
||||||
|
ev->close_handler = ngx_http_close_request;
|
||||||
|
c->write->close_handler = ngx_http_close_request;
|
||||||
|
return ngx_http_process_request(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngx_http_process_request(ngx_event_t *ev)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
ngx_connection_t *c = (ngx_connection_t *) ev->data;
|
||||||
|
ngx_http_request_t *r = (ngx_http_request_t *) c->data;
|
||||||
|
|
||||||
|
ngx_log_debug(ev->log, "http process request");
|
||||||
|
|
||||||
|
ngx_log_debug(ev->log, "http: eof:%d, avail:%d", ev->eof, ev->available);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
if (ev->unexpected_eof) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, ev->log, 0,
|
||||||
|
"ngx_http_process_request: "
|
||||||
|
"connection is closed while %s", ev->action);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_close_request(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
n == r->buff->end - r->buff->last;
|
||||||
|
|
||||||
|
if (!ev->read_discarded) {
|
||||||
|
r->buff->last += n;
|
||||||
|
|
||||||
|
/* state_handlers are called in following order:
|
||||||
|
ngx_process_http_request_line()
|
||||||
|
ngx_process_http_request_header() */
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((r->state_handler)(r) < 0)
|
||||||
|
return -1;
|
||||||
|
} while (r->buff->pos < r->buff->last);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_del_event(ev, NGX_TIMER_EVENT) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ngx_add_event(ev, NGX_TIMER_EVENT, ev->timer) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ngx_process_http_request_line(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
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);
|
||||||
|
r->state_handler = ngx_process_http_request_header;
|
||||||
|
r->connection->read->action = "reading client request headers";
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ngx_process_http_request_header(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n != 2)
|
||||||
|
return n;
|
||||||
|
|
||||||
|
r->state_handler = NULL;
|
||||||
|
r->connection->read->action = "reading client request body";
|
||||||
|
|
||||||
|
r->connection->read->read_discarded = 1;
|
||||||
|
r->connection->read->unexpected_eof = 0;
|
||||||
|
ngx_log_debug(r->connection->log, "HTTP header done");
|
||||||
|
|
||||||
|
return ngx_process_http_request(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ngx_process_http_request(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct stat sb;
|
||||||
|
ngx_http_header_out_t *header_out;
|
||||||
|
ngx_chunk_t *header, *ch;
|
||||||
|
|
||||||
|
int index = (*(r->uri_end - 1) == '/') ? sizeof(NGX_INDEX) : 1;
|
||||||
|
char *name = ngx_palloc(r->pool,
|
||||||
|
r->uri_end - r->uri_start + strlen(ngx_root) + index);
|
||||||
|
strcpy(name, ngx_root);
|
||||||
|
strcat(name, r->uri_start);
|
||||||
|
if (*(r->uri_end - 1) == '/')
|
||||||
|
strcat(name, NGX_INDEX);
|
||||||
|
|
||||||
|
ngx_log_debug(r->connection->log, "HTTP URI: '%s'", name);
|
||||||
|
|
||||||
|
if ((fd = open(name, O_RDONLY)) == -1) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, errno,
|
||||||
|
"open %s failed", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fstat(fd, &sb) == -1) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, errno,
|
||||||
|
"fstat %s failed", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
header_out = ngx_palloc(r->pool, sizeof(ngx_http_header_out_t));
|
||||||
|
|
||||||
|
header_out->status = NGX_HTTP_OK;
|
||||||
|
header_out->content_length = sb.st_size;
|
||||||
|
header_out->last_modified = sb.st_mtime;
|
||||||
|
header_out->content_type = "text/html";
|
||||||
|
header_out->charset = "koi8-r";
|
||||||
|
header_out->date = time(NULL);
|
||||||
|
header_out->connection = NGX_HTTP_CONN_CLOSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
header_out->connection = NGX_HTTP_CONN_KEEP_ALIVE;
|
||||||
|
r->connection->read->event_handler = ngx_http_init_request;
|
||||||
|
*/
|
||||||
|
|
||||||
|
header = ngx_http_header(r, header_out);
|
||||||
|
ch = ngx_palloc(r->pool, sizeof(ngx_chunk_t));
|
||||||
|
ch->ident = fd;
|
||||||
|
ch->offset = 0;
|
||||||
|
ch->size = sb.st_size;
|
||||||
|
ch->next = NULL;
|
||||||
|
header->next = ch;
|
||||||
|
|
||||||
|
ngx_event_write(r->connection, header);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ngx_http_close_request(ngx_event_t *ev)
|
||||||
|
{
|
||||||
|
ngx_connection_t *c = (ngx_connection_t *) ev->data;
|
||||||
|
|
||||||
|
ngx_log_debug(ev->log, "http close");
|
||||||
|
|
||||||
|
ngx_del_event(c->read, NGX_TIMER_EVENT);
|
||||||
|
ngx_del_event(c->write, NGX_TIMER_EVENT);
|
||||||
|
|
||||||
|
return ngx_event_close(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
2
src/http/ngx_http_header.h
Normal file
2
src/http/ngx_http_header.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
gx_chunk_t *gx_http_header(gx_http_request_t *r, gx_http_header_out_t *out);
|
21
src/os/unix/ngx_errno.h
Normal file
21
src/os/unix/ngx_errno.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef _NGX_ERRNO_H_INCLUDED_
|
||||||
|
#define _NGX_ERRNO_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef int ngx_err_t;
|
||||||
|
|
||||||
|
#define NGX_ENOENT ENOENT
|
||||||
|
#define NGX_EINTR EINTR
|
||||||
|
#define NGX_EAGAIN EWOULDBLOCK
|
||||||
|
|
||||||
|
#define ngx_errno errno
|
||||||
|
#define ngx_socket_errno errno
|
||||||
|
|
||||||
|
#define ngx_strerror_r(err, errstr, size) \
|
||||||
|
ngx_cpystrn(errstr, strerror(err), size) - (errstr)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_ERRNO_H_INCLUDED_ */
|
65
src/os/unix/ngx_sendfile.c
Normal file
65
src/os/unix/ngx_sendfile.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_errno.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_sendv.h>
|
||||||
|
#include <ngx_sendfile.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
FreeBSD:
|
||||||
|
check sent if errno == EINTR then should return right sent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns
|
||||||
|
0 done
|
||||||
|
-1 error
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (HAVE_FREEBSD_SENDFILE)
|
||||||
|
|
||||||
|
int ngx_sendfile(ngx_socket_t s,
|
||||||
|
ngx_iovec_t *headers, int hdr_cnt,
|
||||||
|
ngx_file_t fd, off_t offset, size_t nbytes,
|
||||||
|
ngx_iovec_t *trailers, int trl_cnt,
|
||||||
|
off_t *sent,
|
||||||
|
ngx_log_t *log)
|
||||||
|
{
|
||||||
|
int rc, i;
|
||||||
|
ngx_err_t err;
|
||||||
|
struct sf_hdtr hdtr;
|
||||||
|
|
||||||
|
hdtr.headers = headers;
|
||||||
|
hdtr.hdr_cnt = hdr_cnt;
|
||||||
|
hdtr.trailers = trailers;
|
||||||
|
hdtr.trl_cnt = trl_cnt;
|
||||||
|
|
||||||
|
#if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG)
|
||||||
|
for (i = 0; i < hdr_cnt; i++)
|
||||||
|
nbytes += headers[i].iov_len;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = sendfile(fd, s, offset, nbytes, &hdtr, sent, 0);
|
||||||
|
|
||||||
|
if (rc == -1) {
|
||||||
|
err = ngx_socket_errno;
|
||||||
|
if (err != NGX_EAGAIN && err != NGX_EINTR) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, log, err,
|
||||||
|
"ngx_sendfile: sendfile failed");
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, log, err,
|
||||||
|
"ngx_sendfile: sendfile sent only %qd bytes", *sent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_sendfile: %d, @%qd %d:%qd" _
|
||||||
|
rc _ offset _ nbytes _ *sent);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
17
src/os/unix/ngx_sendfile.h
Normal file
17
src/os/unix/ngx_sendfile.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _NGX_SENDFILE_H_INCLUDED_
|
||||||
|
#define _NGX_SENDFILE_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_sendv.h>
|
||||||
|
|
||||||
|
int ngx_sendfile(ngx_socket_t s,
|
||||||
|
ngx_iovec_t *headers, int hdr_cnt,
|
||||||
|
ngx_file_t fd, off_t offset, size_t nbytes,
|
||||||
|
ngx_iovec_t *trailers, int trl_cnt,
|
||||||
|
off_t *sent,
|
||||||
|
ngx_log_t *log);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_SENDFILE_H_INCLUDED_ */
|
14
src/os/unix/ngx_sendv.c
Normal file
14
src/os/unix/ngx_sendv.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_sendv.h>
|
||||||
|
|
||||||
|
ssize_t ngx_sendv(ngx_socket_t s, ngx_iovec_t *iovec, int n, size_t *sent)
|
||||||
|
{
|
||||||
|
ssize_t rc = writev(s, iovec, n);
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*sent = rc;
|
||||||
|
return 0;
|
||||||
|
}
|
14
src/os/unix/ngx_sendv.h
Normal file
14
src/os/unix/ngx_sendv.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _NGX_SENDV_H_INCLUDED_
|
||||||
|
#define _NGX_SENDV_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_types.h>
|
||||||
|
|
||||||
|
typedef struct iovec ngx_iovec_t;
|
||||||
|
#define ngx_iov_base iov_base
|
||||||
|
#define ngx_iov_len iov_len
|
||||||
|
|
||||||
|
ssize_t ngx_sendv(ngx_socket_t s, ngx_iovec_t *iovec, int n, size_t *sent);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_SENDV_H_INCLUDED_ */
|
19
src/os/unix/ngx_stat.h
Normal file
19
src/os/unix/ngx_stat.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _NGX_STAT_H_INCLUDED_
|
||||||
|
#define _NGX_STAT_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
typedef struct stat ngx_stat_t;
|
||||||
|
|
||||||
|
#define ngx_is_dir(sb) (S_ISDIR(sb.st_mode))
|
||||||
|
|
||||||
|
#define ngx_stat(file, sb) stat(file, sb)
|
||||||
|
#define ngx_stat_n "stat"
|
||||||
|
|
||||||
|
#define ngx_fstat(file, fd, sb) fstat(fd, sb)
|
||||||
|
#define ngx_fstat_n "stat"
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_STAT_H_INCLUDED_ */
|
19
src/os/unix/ngx_time.c
Normal file
19
src/os/unix/ngx_time.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_time.h>
|
||||||
|
|
||||||
|
void ngx_localtime(ngx_tm_t *tm)
|
||||||
|
{
|
||||||
|
time_t clock = time(NULL);
|
||||||
|
localtime_r(&clock, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int ngx_msec(void)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
}
|
||||||
|
|
22
src/os/unix/ngx_time.h
Normal file
22
src/os/unix/ngx_time.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _NGX_TIME_H_INCLUDED_
|
||||||
|
#define _NGX_TIME_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
typedef struct tm ngx_tm_t;
|
||||||
|
|
||||||
|
#define ngx_tm_sec tm_sec
|
||||||
|
#define ngx_tm_min tm_min
|
||||||
|
#define ngx_tm_hour tm_hour
|
||||||
|
#define ngx_tm_mday tm_mday
|
||||||
|
#define ngx_tm_mon tm_mon
|
||||||
|
#define ngx_tm_year tm_year
|
||||||
|
#define ngx_tm_wday tm_wday
|
||||||
|
|
||||||
|
void ngx_localtime(ngx_tm_t *tm);
|
||||||
|
|
||||||
|
u_int ngx_msec(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_TIME_H_INCLUDED_ */
|
12
src/os/unix/ngx_types.h
Normal file
12
src/os/unix/ngx_types.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _NGX_TYPES_H_INCLUDED_
|
||||||
|
#define _NGX_TYPES_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef int ngx_file_t;
|
||||||
|
typedef int ngx_socket_t;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_TYPES_H_INCLUDED_ */
|
38
src/os/win32/ngx_errno.c
Normal file
38
src/os/win32/ngx_errno.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
add WSA error messages
|
||||||
|
test for English only messages
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_string.h>
|
||||||
|
#include <ngx_errno.h>
|
||||||
|
|
||||||
|
int ngx_strerror_r(ngx_err_t err, char *errstr, size_t size)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
||||||
|
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, err,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
errstr, size, NULL);
|
||||||
|
|
||||||
|
/* add WSA error messages */
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
|
||||||
|
len = ngx_snprintf(errstr, size,
|
||||||
|
"FormatMessage error:(%d)", GetLastError());
|
||||||
|
return len;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove ".\r\n\0" */
|
||||||
|
while (errstr[len] == '\0' || errstr[len] == CR
|
||||||
|
|| errstr[len] == LF || errstr[len] == '.')
|
||||||
|
--len;
|
||||||
|
|
||||||
|
return ++len;
|
||||||
|
}
|
18
src/os/win32/ngx_errno.h
Normal file
18
src/os/win32/ngx_errno.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _NGX_ERRNO_H_INCLUDED_
|
||||||
|
#define _NGX_ERRNO_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
typedef DWORD ngx_err_t;
|
||||||
|
|
||||||
|
#define ngx_errno GetLastError()
|
||||||
|
#define ngx_socket_errno WSAGetLastError()
|
||||||
|
|
||||||
|
#define NGX_ENOENT ERROR_FILE_NOT_FOUND
|
||||||
|
#define NGX_EAGAIN WSAEWOULDBLOCK
|
||||||
|
|
||||||
|
int ngx_strerror_r(ngx_err_t err, char *errstr, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_ERRNO_H_INCLUDED_ */
|
89
src/os/win32/ngx_sendfile.c
Normal file
89
src/os/win32/ngx_sendfile.c
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_errno.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_sendv.h>
|
||||||
|
#include <ngx_sendfile.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
various flags
|
||||||
|
TransmitPackets
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
returns
|
||||||
|
0 done
|
||||||
|
-1 error
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (HAVE_WIN32_TRANSMITFILE)
|
||||||
|
|
||||||
|
int ngx_sendfile(ngx_socket_t s,
|
||||||
|
ngx_iovec_t *headers, int hdr_cnt,
|
||||||
|
ngx_file_t fd, off_t offset, size_t nbytes,
|
||||||
|
ngx_iovec_t *trailers, int trl_cnt,
|
||||||
|
off_t *sent,
|
||||||
|
ngx_log_t *log)
|
||||||
|
{
|
||||||
|
int tfrc, rc;
|
||||||
|
ngx_err_t tf_err, err;
|
||||||
|
OVERLAPPED olp;
|
||||||
|
TRANSMIT_FILE_BUFFERS tfb, *ptfb;
|
||||||
|
|
||||||
|
tf_err = 0;
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
olp.Internal = 0;
|
||||||
|
olp.InternalHigh = 0;
|
||||||
|
olp.Offset = (DWORD) offset;
|
||||||
|
olp.OffsetHigh = (DWORD) (offset >> 32);
|
||||||
|
olp.hEvent = NULL;
|
||||||
|
|
||||||
|
if (headers || trailers) {
|
||||||
|
tfb.Head = headers->ngx_iov_base;
|
||||||
|
tfb.HeadLength = headers->ngx_iov_len;
|
||||||
|
tfb.Tail = trailers->ngx_iov_base;
|
||||||
|
tfb.TailLength = trailers->ngx_iov_len;
|
||||||
|
ptfb = &tfb;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ptfb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tfrc = TransmitFile(s, fd, nbytes, 0, &olp, ptfb, 0);
|
||||||
|
|
||||||
|
if (tfrc == 0)
|
||||||
|
tf_err = ngx_socket_errno;
|
||||||
|
|
||||||
|
/* set sent */
|
||||||
|
rc = WSAGetOverlappedResult(s, &olp, (unsigned long *) sent, 0, NULL);
|
||||||
|
|
||||||
|
ngx_log_debug(log, "ngx_sendfile: %d, @%qd %d:%qd" _
|
||||||
|
tfrc _ offset _ nbytes _ *sent);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
err = ngx_socket_errno;
|
||||||
|
ngx_log_error(NGX_LOG_ERR, log, err,
|
||||||
|
"ngx_sendfile: WSAGetOverlappedResult failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tfrc == 0) {
|
||||||
|
if (tf_err != NGX_EAGAIN) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, log, tf_err,
|
||||||
|
"ngx_sendfile: TransmitFile failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_INFO, log, tf_err,
|
||||||
|
"ngx_sendfile: TransmitFile sent only %qd bytes", *sent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
18
src/os/win32/ngx_sendfile.h
Normal file
18
src/os/win32/ngx_sendfile.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _NGX_SENDFILE_H_INCLUDED_
|
||||||
|
#define _NGX_SENDFILE_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_types.h>
|
||||||
|
#include <ngx_log.h>
|
||||||
|
#include <ngx_sendv.h>
|
||||||
|
|
||||||
|
int ngx_sendfile(ngx_socket_t s,
|
||||||
|
ngx_iovec_t *headers, int hdr_cnt,
|
||||||
|
ngx_file_t fd, off_t offset, size_t nbytes,
|
||||||
|
ngx_iovec_t *trailers, int trl_cnt,
|
||||||
|
off_t *sent,
|
||||||
|
ngx_log_t *log);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_SENDFILE_H_INCLUDED_ */
|
14
src/os/win32/ngx_sendv.h
Normal file
14
src/os/win32/ngx_sendv.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _NGX_SENDV_H_INCLUDED_
|
||||||
|
#define _NGX_SENDV_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
typedef WSABUF ngx_iovec_t;
|
||||||
|
#define ngx_iov_base buf
|
||||||
|
#define ngx_iov_len len
|
||||||
|
|
||||||
|
#define ngx_sendv(s, iovec, n, sent) WSASend(s, iovec, n, sent, 0, NULL, NULL)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_SENDV_H_INCLUDED_ */
|
15
src/os/win32/ngx_stat.c
Normal file
15
src/os/win32/ngx_stat.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <ngx_stat.h>
|
||||||
|
|
||||||
|
int ngx_stat(char *file, ngx_stat_t *sb)
|
||||||
|
{
|
||||||
|
*sb = GetFileAttributes(file);
|
||||||
|
|
||||||
|
if (*sb == INVALID_FILE_ATTRIBUTES) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
26
src/os/win32/ngx_stat.h
Normal file
26
src/os/win32/ngx_stat.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _NGX_STAT_H_INCLUDED_
|
||||||
|
#define _NGX_STAT_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/* INVALID_FILE_ATTRIBUTES specified but never defined */
|
||||||
|
#ifndef INVALID_FILE_ATTRIBUTES
|
||||||
|
#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef DWORD ngx_stat_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define ngx_is_dir(sb) (*sb & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
|
||||||
|
#define ngx_stat_n "GetFileAttributes"
|
||||||
|
|
||||||
|
#define ngx_fstat(file, fd, sb) ngx_stat(file, sb)
|
||||||
|
#define ngx_fstat_n "GetFileAttributes"
|
||||||
|
|
||||||
|
|
||||||
|
int ngx_stat(char *file, ngx_stat_t *sb);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_STAT_H_INCLUDED_ */
|
21
src/os/win32/ngx_time.h
Normal file
21
src/os/win32/ngx_time.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef _NGX_TIME_H_INCLUDED_
|
||||||
|
#define _NGX_TIME_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
typedef SYSTEMTIME ngx_tm_t;
|
||||||
|
|
||||||
|
#define ngx_tm_sec wSecond
|
||||||
|
#define ngx_tm_min wMinute
|
||||||
|
#define ngx_tm_hour wHour
|
||||||
|
#define ngx_tm_mday wDay
|
||||||
|
#define ngx_tm_mon wMonth
|
||||||
|
#define ngx_tm_year wYear
|
||||||
|
#define ngx_tm_wday wDayOfWeek
|
||||||
|
|
||||||
|
#define ngx_localtime GetLocalTime
|
||||||
|
#define ngx_msec GetTickCount
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_TIME_H_INCLUDED_ */
|
14
src/os/win32/ngx_types.h
Normal file
14
src/os/win32/ngx_types.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _NGX_TYPES_H_INCLUDED_
|
||||||
|
#define _NGX_TYPES_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef HANDLE ngx_file_t;
|
||||||
|
typedef SOCKET ngx_socket_t;
|
||||||
|
typedef long time_t;
|
||||||
|
typedef unsigned __int64 off_t;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NGX_TYPES_H_INCLUDED_ */
|
Loading…
Reference in New Issue
Block a user