nginx-0.0.1-2003-05-21-17:28:21 import

This commit is contained in:
Igor Sysoev 2003-05-21 13:28:21 +00:00
parent 1c13c662f0
commit fa73aac774
38 changed files with 1049 additions and 379 deletions

View File

@ -4,218 +4,59 @@
#include <ngx_auto_config.h>
/*
auto_conf
ngx_inline inline __inline __inline__
*/
/* STUB */
#if defined __FreeBSD__
#include <ngx_freebsd_config.h>
#elif defined __linux__
#include <ngx_linux_config.h>
/* Solaris */
#elif defined(sun) && (defined(__svr4__) || defined(__SVR4))
#include <ngx_solaris_config.h>
#elif defined _WIN32
/* STUB to allocate a big ngx_connections */
#undef FD_SETSIZE
#define FD_SETSIZE 1024
#include <ngx_win32_config.h>
/* auto_conf */
#define NGX_ALIGN (4 - 1)
#define NGX_ALIGN_TYPE unsigned
#define ngx_align(p) (char *) (((NGX_ALIGN_TYPE) p + NGX_ALIGN) & ~NGX_ALIGN)
#else /* posix */
#endif
/* Platform specific: array[NGX_INVALID_ARRAY_INDEX] should cause SIGSEGV */
/* TODO: platform specific: array[NGX_INVALID_ARRAY_INDEX] must cause SIGSEGV */
#define NGX_INVALID_ARRAY_INDEX 0x80000000
#ifdef _WIN32
/* TODO: auto_conf */
#define NGX_ALIGN (4 - 1)
#define NGX_ALIGN_TYPE (unsigned int)
#define WIN32 1
#include <winsock2.h>
#include <mswsock.h>
#include <stddef.h> /* offsetof */
#include <stdio.h>
#include <stdarg.h>
#define ngx_inline __inline
#ifndef HAVE_INHERITED_NONBLOCK
#define HAVE_INHERITED_NONBLOCK 1
#endif
#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 */
/* Solaris */
#if defined(sun) && (defined(__svr4__) || defined(__SVR4))
#define SOLARIS 1
#define _FILE_OFFSET_BITS 64 /* should be before sys/types.h */
#ifndef HAVE_INHERITED_NONBLOCK
#define HAVE_INHERITED_NONBLOCK 1
#endif
#include <sys/stropts.h> /* INFTIM */
#endif /* Solaris */
#include <unistd.h>
#include <stddef.h> /* offsetof */
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifndef HAVE_POLL
#define HAVE_POLL 1
#include <poll.h>
#endif
#if (HAVE_DEVPOLL) && !(TEST_DEVPOLL)
#include <sys/ioctl.h>
#include <sys/devpoll.h> /* Solaris, HP/UX */
#endif
#if (HAVE_AIO)
#include <aio.h>
#endif
#define ngx_align(p) (char *) ((NGX_ALIGN_TYPE p + NGX_ALIGN) & ~NGX_ALIGN)
/* TODO: auto_conf: ngx_inline inline __inline __inline__ */
#ifndef ngx_inline
#define ngx_inline inline
#endif
#endif /* POSIX */
#define LF 10
#define CR 13
#define CRLF "\x0d\x0a"
#ifndef INADDR_NONE /* Solaris */
#define INADDR_NONE ((unsigned long) -1)
#endif
#ifndef INET_ADDRSTRLEN
#define INET_ADDRSTRLEN 16
#endif
#if defined SO_ACCEPTFILTER || defined TCP_DEFER_ACCEPT
#ifndef HAVE_DEFERRED_ACCEPT
#define HAVE_DEFERRED_ACCEPT 1
#endif
#endif
#ifndef HAVE_SELECT
#define HAVE_SELECT 1
#endif
#ifdef __FreeBSD__
#include <osreldate.h>
#ifndef HAVE_INHERITED_NONBLOCK
#define HAVE_INHERITED_NONBLOCK 1
#endif
/* FreeBSD sendfile */
#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 /* FreeBSD sendfile */
/* FreeBSD sendfile nbytes bug */
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 460100) \
|| __FreeBSD_version == 460001 \
|| __FreeBSD_version >= 500029
#if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG == 2)
#undef HAVE_FREEBSD_SENDFILE_NBYTES_BUG
#define HAVE_FREEBSD_SENDFILE_NBYTES_BUG 0
#endif
#endif /* FreeBSD sendfile nbytes bug */
#if (HAVE_FREEBSD_SENDFILE)
#define HAVE_SENDFILE 1
#endif
/* FreeBSD kqueue */
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 410000) \
|| __FreeBSD_version >= 500011
#ifndef HAVE_KQUEUE
#define HAVE_KQUEUE 1
#include <sys/event.h>
#endif
/* kqueue's NOTE_LOWAT */
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \
|| __FreeBSD_version >= 500018
#ifndef HAVE_LOWAT_EVENT
#define HAVE_LOWAT_EVENT 1
#endif
#endif
#endif /* FreeBSD kqueue */
#endif /* __FreeBSD__ */
#ifdef __SOME_OS_TEMPLATE__
#ifndef HAVE_INHERITED_NONBLOCK
#define HAVE_INHERITED_NONBLOCK 1
#endif
#endif
#endif /* _NGX_CONFIG_H_INCLUDED_ */

View File

@ -37,6 +37,12 @@ typedef struct ngx_event_s ngx_event_t;
*/
#define LF 10
#define CR 13
#define CRLF "\x0d\x0a"
#define NGX_MAXHOSTNAMELEN 32
/*
#define NGX_MAXHOSTNAMELEN MAXHOSTNAMELEN

View File

@ -17,6 +17,9 @@ extern ngx_module_t ngx_kqueue_module;
#if (HAVE_DEVPOLL)
extern ngx_module_t ngx_devpoll_module;
#endif
#if (HAVE_AIO)
extern ngx_module_t ngx_aio_module;
#endif
extern ngx_module_t ngx_http_module;
@ -47,6 +50,9 @@ ngx_module_t *ngx_modules[] = {
#if (HAVE_DEVPOLL)
&ngx_devpoll_module,
#endif
#if (HAVE_AIO)
&ngx_aio_module,
#endif
/* http */

View File

@ -4,23 +4,40 @@
#include <ngx_config.h>
#include <ngx_core.h>
#if 0
#include <ngx_connection.h>
#define NGX_IO_SENDFILE 1
#define NGX_IO_ZEROCOPY 2
#if (HAVE_SENDFILE)
#define NGX_HAVE_SENDFILE NGX_IO_SENDFILE
#else
#define NGX_HAVE_SENDFILE 0
#endif
#if (HAVE_ZEROCOPY)
#define NGX_HAVE_ZEROCOPY NGX_IO_ZEROCOPY
#else
#define NGX_HAVE_ZEROCOPY 0
#endif
typedef struct {
ssize_t (*recv)(ngx_connection_t *c, char *buf, size_t size);
void *dummy_recv_chain;
void *dummy_send;
ngx_chain_t *(*send_chain)(ngx_connection_t *c, ngx_chain_t *in);
int flags;
} ngx_os_io_t;
int ngx_os_init(ngx_log_t *log);
extern ngx_os_io_t ngx_os_io;
extern int ngx_max_sockets;
extern int ngx_inherited_nonblocking;
#endif /* _NGX_OS_INIT_H_INCLUDED_ */

View File

@ -1,39 +1,109 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_types.h>
#include <ngx_log.h>
#include <ngx_connection.h>
#include <ngx_event.h>
#include <ngx_event_timer.h>
#include <ngx_aio.h>
#if (HAVE_KQUEUE)
#include <ngx_kqueue_module.h>
#endif
int ngx_aio_init(int max_connections, ngx_log_t *log)
{
static int ngx_aio_init(ngx_log_t *log);
static void ngx_aio_done(ngx_log_t *log);
static int ngx_aio_add_event(ngx_event_t *ev, int event, u_int flags);
static int ngx_aio_del_event(ngx_event_t *ev, int event, u_int flags);
static int ngx_aio_process_events(ngx_log_t *log);
ngx_os_io_t ngx_os_aio = {
ngx_aio_read,
NULL,
ngx_aio_write,
ngx_aio_write_chain,
NGX_HAVE_ZEROCOPY
};
static ngx_str_t aio_name = ngx_string("aio");
ngx_event_module_t ngx_aio_module_ctx = {
NGX_EVENT_MODULE,
&aio_name,
NULL, /* create configuration */
NULL, /* init configuration */
{
ngx_aio_add_event, /* add an event */
ngx_aio_del_event, /* delete an event */
NULL, /* enable an event */
NULL, /* disable an event */
NULL, /* add an connection */
NULL, /* delete an connection */
ngx_aio_process_events, /* process the events */
ngx_aio_init, /* init the events */
ngx_aio_done /* done the events */
}
};
ngx_module_t ngx_aio_module = {
&ngx_aio_module_ctx, /* module context */
0, /* module index */
NULL, /* module directives */
NGX_EVENT_MODULE_TYPE, /* module type */
NULL /* init module */
};
#if (HAVE_KQUEUE)
int rc;
rc = ngx_kqueue_init(max_connections, log);
static int ngx_aio_init(ngx_log_t *log)
{
if (ngx_kqueue_module_ctx.actions.init(log) == NGX_ERROR) {
return NGX_ERROR;
}
ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_USE_AIO_EVENT;
ngx_write_chain_proc = ngx_aio_write_chain;
ngx_event_actions = ngx_aio_module_ctx.actions;
ngx_io = ngx_os_aio;
return rc;
#endif
return NGX_OK;
}
static void ngx_aio_done(ngx_log_t *log)
{
ngx_kqueue_module_ctx.actions.done(log);
}
/* The event adding and deleteing are needed for the listening sockets */
static int ngx_aio_add_event(ngx_event_t *ev, int event, u_int flags)
{
return ngx_kqueue_module_ctx.actions.add(ev, event, flags);
}
static int ngx_aio_del_event(ngx_event_t *ev, int event, u_int flags)
{
return ngx_kqueue_module_ctx.actions.del(ev, event, flags);
}
static int ngx_aio_process_events(ngx_log_t *log)
{
return ngx_kqueue_module_ctx.actions.process(log);
}
#endif
#if 0
/* 1 */
int ngx_posix_aio_process_events(ngx_log_t *log)
{
@ -66,6 +136,7 @@ int ngx_posix_aio_process_events(ngx_log_t *log)
/* 3 */
int ngx_posix_aio_process_events(ngx_log_t *log)
{
#if 0
unmask signal
/* BUG: AIO signal can be delivered before select() */
@ -73,6 +144,9 @@ int ngx_posix_aio_process_events(ngx_log_t *log)
select(listen);
mask signal
#endif
pselect(listen, mask);
if (ngx_socket_errno == NGX_EINTR)
look ready array
@ -82,4 +156,5 @@ void aio_sig_handler(int signo, siginfo_t *siginfo, void *context)
{
push siginfo->si_value.sival_ptr
}
#endif

View File

@ -10,7 +10,7 @@
#include <ngx_event.h>
#if (TEST_DEVPOLL)
#if (TEST_BUILD_DEVPOLL)
/* Solaris declarations */

View File

@ -66,7 +66,7 @@ ngx_event_module_t ngx_kqueue_module_ctx = {
NULL, /* delete an connection */
ngx_kqueue_process_events, /* process the events */
ngx_kqueue_init, /* init the events */
ngx_kqueue_done, /* done the events */
ngx_kqueue_done /* done the events */
}
};
@ -343,6 +343,12 @@ static int ngx_kqueue_process_events(ngx_log_t *log)
}
ev = (ngx_event_t *) event_list[i].udata;
switch (event_list[i].filter) {
case EVFILT_READ:
case EVFILT_WRITE:
instance = (uintptr_t) ev & 1;
ev = (void *) ((uintptr_t) ev & ~1);
@ -354,11 +360,6 @@ static int ngx_kqueue_process_events(ngx_log_t *log)
continue;
}
switch (event_list[i].filter) {
case EVFILT_READ:
case EVFILT_WRITE:
ev->available = event_list[i].data;
if (event_list[i].flags & EV_EOF) {

View File

@ -9,6 +9,8 @@ typedef struct {
extern int ngx_kqueue;
/* STUB */ extern ngx_event_module_t ngx_kqueue_module_ctx;
#endif /* _NGX_KQUEUE_MODULE_H_INCLUDED_ */

View File

@ -31,7 +31,7 @@ extern ngx_event_module_t ngx_devpoll_module_ctx;
static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
static void *ngx_event_create_conf(ngx_pool_t *pool);
static char *ngx_event_init_conf(ngx_pool_t *pool, void *conf);
@ -84,9 +84,9 @@ static ngx_command_t ngx_event_commands[] = {
offsetof(ngx_event_conf_t, connections),
NULL},
{ngx_string("type"),
{ngx_string("use"),
NGX_EVENT_CONF|NGX_CONF_TAKE1,
ngx_event_set_type,
ngx_event_use,
0,
0,
NULL},
@ -135,7 +135,7 @@ int ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log)
ecf = ngx_event_get_conf(ngx_event_module_ctx);
ngx_log_debug(log, "CONN: %d" _ ecf->connections);
ngx_log_debug(log, "TYPE: %d" _ ecf->type);
ngx_log_debug(log, "TYPE: %d" _ ecf->use);
for (m = 0; ngx_modules[m]; m++) {
if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
@ -143,7 +143,7 @@ ngx_log_debug(log, "TYPE: %d" _ ecf->type);
}
module = ngx_modules[m]->ctx;
if (module->index == ecf->type) {
if (module->index == ecf->use) {
if (module->actions.init(log) == NGX_ERROR) {
return NGX_ERROR;
}
@ -317,7 +317,7 @@ static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
}
static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
{
ngx_event_conf_t *ecf = (ngx_event_conf_t *) conf;
@ -325,8 +325,8 @@ static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
ngx_str_t *args;
ngx_event_module_t *module;
if (ecf->type != NGX_CONF_UNSET) {
return "duplicate event type" ;
if (ecf->use != NGX_CONF_UNSET) {
return "is duplicate" ;
}
args = cf->args->elts;
@ -339,7 +339,7 @@ static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
module = ngx_modules[m]->ctx;
if (module->name->len == args[1].len) {
if (ngx_strcmp(module->name->data, args[1].data) == 0) {
ecf->type = module->index;
ecf->use = module->index;
return NGX_CONF_OK;
}
}
@ -358,7 +358,7 @@ static void *ngx_event_create_conf(ngx_pool_t *pool)
ecf->connections = NGX_CONF_UNSET;
ecf->timer_queues = NGX_CONF_UNSET;
ecf->type = NGX_CONF_UNSET;
ecf->use = NGX_CONF_UNSET;
return ecf;
}
@ -380,19 +380,19 @@ static char *ngx_event_init_conf(ngx_pool_t *pool, void *conf)
#endif
ngx_conf_init_value(ecf->connections, DEF_CONNECTIONS);
ngx_conf_init_value(ecf->type, ngx_kqueue_module_ctx.index);
ngx_conf_init_value(ecf->use, ngx_kqueue_module_ctx.index);
#elif (HAVE_DEVPOLL)
ngx_conf_init_value(ecf->connections, DEF_CONNECTIONS);
ngx_conf_init_value(ecf->type, ngx_devpoll_module_ctx.index);
ngx_conf_init_value(ecf->use, ngx_devpoll_module_ctx.index);
#else /* HAVE_SELECT */
ngx_conf_init_value(ecf->connections,
FD_SETSIZE < DEF_CONNECTIONS ? FD_SETSIZE : DEF_CONNECTIONS);
ngx_conf_init_value(ecf->type, ngx_select_module_ctx.index);
ngx_conf_init_value(ecf->use, ngx_select_module_ctx.index);
#endif

View File

@ -327,7 +327,7 @@ extern int ngx_event_flags;
typedef struct {
int connections;
int timer_queues;
int type;
int use;
} ngx_event_conf_t;

View File

@ -65,39 +65,28 @@ void ngx_event_accept(ngx_event_t *ev)
return;
}
/* set a blocking mode for aio and non-blocking mode for others */
#if (HAVE_INHERITED_NONBLOCK)
#if (HAVE_AIO_EVENT)
if ((ngx_event_flags & NGX_HAVE_AIO_EVENT)) {
if (ngx_inherited_nonblocking) {
if ((ngx_event_flags & NGX_USE_AIO_EVENT)) {
if (ngx_blocking(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
ngx_blocking_n " %s failed", ls->addr_text.data);
ngx_blocking_n " %s failed",
ls->addr_text.data);
return;
}
}
#endif
#else /* !HAVE_INHERITED_NONBLOCK */
#if (HAVE_AIO_EVENT)
if (!(ngx_event_flags & NGX_HAVE_AIO_EVENT)) {
} else {
if ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0) {
if (ngx_nonblocking(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
ngx_nonblocking_n " %s failed", ls->addr_text.data);
ngx_nonblocking_n " %s failed",
ls->addr_text.data);
return;
}
}
#else
if (ngx_nonblocking(s) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
ngx_nonblocking_n " %s failed", ls->addr_text.data);
return;
}
#endif
#endif /* HAVE_INHERITED_NONBLOCK */
rev = &ngx_read_events[s];
wev = &ngx_write_events[s];
@ -130,15 +119,9 @@ void ngx_event_accept(ngx_event_t *ev)
c->unexpected_eof = 1;
wev->write = 1;
#if (USE_KQUEUE)
wev->ready = 1;
#else
if ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0) {
wev->ready = 1;
}
#endif
/* STUB ? */ wev->timer = rev->timer = 10000;
c->ctx = ls->ctx;
c->servers = ls->servers;
@ -174,17 +157,10 @@ void ngx_event_accept(ngx_event_t *ev)
ls->handler(c);
#if (USE_KQUEUE)
ev->available--;
#elif (HAVE_KQUEUE)
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
ev->available--;
}
#endif
} while (ev->available);
return;

View File

@ -29,6 +29,22 @@ int ngx_event_acceptex(ngx_event_t *ev)
return NGX_OK;
}
#if 0
/* can we do SO_UPDATE_ACCEPT_CONTEXT just before shutdown() ???
or AcceptEx's context will be lost ??? */
/* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */
if (setsockopt(context->accept_socket, SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT, (char *)&nsd,
sizeof(nsd))) {
ap_log_error(APLOG_MARK, APLOG_ERR, WSAGetLastError(), server_conf,
"setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed.");
/* non fatal - we can not only do lingering close */
#endif
getacceptexsockaddrs(c->data, 0,
c->socklen + 16, c->socklen + 16,
&c->local_sockaddr, &c->local_socklen,

View File

@ -134,6 +134,13 @@ static ngx_command_t ngx_http_core_commands[] = {
offsetof(ngx_http_core_loc_conf_t, send_timeout),
NULL},
{ngx_string("keepalive_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, keepalive_timeout),
NULL},
{ngx_string("lingering_time"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@ -912,6 +919,7 @@ static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool)
lcf->send_timeout = NGX_CONF_UNSET;
lcf->discarded_buffer_size = NGX_CONF_UNSET;
lcf->keepalive_timeout = NGX_CONF_UNSET;
lcf->lingering_time = NGX_CONF_UNSET;
lcf->lingering_timeout = NGX_CONF_UNSET;
@ -981,6 +989,8 @@ static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool,
ngx_conf_merge_size_value(conf->discarded_buffer_size,
prev->discarded_buffer_size, 1500);
ngx_conf_merge_msec_value(conf->keepalive_timeout, prev->keepalive_timeout,
70000);
ngx_conf_merge_msec_value(conf->lingering_time, prev->lingering_time,
30000);
ngx_conf_merge_msec_value(conf->lingering_timeout, prev->lingering_timeout,

View File

@ -100,6 +100,7 @@ typedef struct {
ngx_msec_t send_timeout; /* send_timeout */
size_t send_lowat; /* send_lowa */
size_t discarded_buffer_size; /* discarded_buffer_size */
ngx_msec_t keepalive_timeout; /* keepalive_timeout */
ngx_msec_t lingering_time; /* lingering_time */
ngx_msec_t lingering_timeout; /* lingering_timeout */

View File

@ -996,6 +996,7 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
ngx_connection_t *c;
ngx_http_log_ctx_t *ctx;
ngx_http_core_main_conf_t *cmcf;
ngx_http_core_loc_conf_t *clcf;
c = (ngx_connection_t *) r->connection;
rev = c->read;
@ -1004,6 +1005,17 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
ctx->action = "closing request";
ngx_http_close_request(r, 0);
if (rev->timer_set) {
ngx_del_timer(rev);
} else {
rev->timer_set = 1;
}
clcf = (ngx_http_core_loc_conf_t *)
ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
ngx_add_timer(rev, clcf->keepalive_timeout);
if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
ngx_http_close_connection(c);

13
src/os/unix/ngx_aio.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef _NGX_AIO_H_INCLUDED_
#define _NGX_AIO_H_INCLUDED_
#include <ngx_core.h>
ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size);
ssize_t ngx_aio_write(ngx_connection_t *c, char *buf, size_t size);
ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in);
#endif /* _NGX_AIO_H_INCLUDED_ */

110
src/os/unix/ngx_aio_read.c Normal file
View File

@ -0,0 +1,110 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_aio.h>
#if (HAVE_KQUEUE)
#include <ngx_kqueue_module.h>
#endif
/*
The data is ready - 3 syscalls:
aio_read(), aio_error(), aio_return()
The data is not ready - 4 (kqueue) or 5 syscalls:
aio_read(), aio_error(), notifiction,
aio_error(), aio_return()
aio_cancel(), aio_error()
*/
ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size)
{
int rc, first, canceled;
ngx_event_t *ev;
ev = c->read;
canceled = 0;
if (ev->timedout) {
ngx_set_socket_errno(NGX_ETIMEDOUT);
ngx_log_error(NGX_LOG_ERR, ev->log, 0, "aio_read() timed out");
rc = aio_cancel(c->fd, &ev->aiocb);
if (rc == -1) {
ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno,
"aio_cancel() failed");
return NGX_ERROR;
}
ngx_log_debug(ev->log, "aio_cancel: %d" _ rc);
canceled = 1;
ev->ready = 1;
}
first = 0;
if (!ev->ready) {
ngx_memzero(&ev->aiocb, sizeof(struct aiocb));
ev->aiocb.aio_fildes = c->fd;
ev->aiocb.aio_buf = buf;
ev->aiocb.aio_nbytes = size;
#if (HAVE_KQUEUE)
ev->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue;
ev->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
ev->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev;
#endif
if (aio_read(&ev->aiocb) == -1) {
ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno,
"aio_read() failed");
return NGX_ERROR;
}
ngx_log_debug(ev->log, "aio_read: OK");
ev->active = 1;
first = 1;
}
ev->ready = 0;
rc = aio_error(&ev->aiocb);
if (rc == -1) {
ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, "aio_error() failed");
return NGX_ERROR;
}
if (rc != 0) {
if (rc == NGX_EINPROGRESS) {
if (!first) {
ngx_log_error(NGX_LOG_CRIT, ev->log, rc,
"aio_read() still in progress");
}
return NGX_AGAIN;
}
if (rc == NGX_ECANCELED && canceled) {
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_CRIT, ev->log, rc, "aio_read() failed");
return NGX_ERROR;
}
rc = aio_return(&ev->aiocb);
if (rc == -1) {
ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, "aio_return() failed");
return NGX_ERROR;
}
ngx_log_debug(ev->log, "aio_read: %d" _ rc);
return rc;
}

112
src/os/unix/ngx_aio_write.c Normal file
View File

@ -0,0 +1,112 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_aio.h>
#if (HAVE_KQUEUE)
#include <ngx_kqueue_module.h>
#endif
/*
The data is ready - 3 syscalls:
aio_write(), aio_error(), aio_return()
The data is not ready - 4 (kqueue) or 5 syscalls:
aio_write(), aio_error(), notifiction,
aio_error(), aio_return()
aio_cancel(), aio_error()
*/
ssize_t ngx_aio_write(ngx_connection_t *c, char *buf, size_t size)
{
int rc, first, canceled;
ngx_event_t *ev;
ev = c->write;
canceled = 0;
ngx_log_debug(ev->log, "aio: ev->ready: %d" _ ev->ready);
ngx_log_debug(ev->log, "aio: aiocb: %08x" _ &ev->aiocb);
if (ev->timedout) {
ngx_set_socket_errno(NGX_ETIMEDOUT);
ngx_log_error(NGX_LOG_ERR, ev->log, 0, "aio_write() timed out");
rc = aio_cancel(c->fd, &ev->aiocb);
if (rc == -1) {
ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno,
"aio_cancel() failed");
return NGX_ERROR;
}
ngx_log_debug(ev->log, "aio_cancel: %d" _ rc);
canceled = 1;
ev->ready = 1;
}
first = 0;
if (!ev->ready) {
ngx_memzero(&ev->aiocb, sizeof(struct aiocb));
ev->aiocb.aio_fildes = c->fd;
ev->aiocb.aio_buf = buf;
ev->aiocb.aio_nbytes = size;
#if (HAVE_KQUEUE)
ev->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue;
ev->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
ev->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev;
#endif
if (aio_write(&ev->aiocb) == -1) {
ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno,
"aio_write() failed");
return NGX_ERROR;
}
ngx_log_debug(ev->log, "aio_write: OK");
ev->active = 1;
first = 1;
}
ev->ready = 0;
rc = aio_error(&ev->aiocb);
if (rc == -1) {
ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, "aio_error() failed");
return NGX_ERROR;
}
if (rc != 0) {
if (rc == NGX_EINPROGRESS) {
if (!first) {
ngx_log_error(NGX_LOG_CRIT, ev->log, rc,
"aio_write() still in progress");
}
return NGX_AGAIN;
}
if (rc == NGX_ECANCELED && canceled) {
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_CRIT, ev->log, rc, "aio_write() failed");
return NGX_ERROR;
}
rc = aio_return(&ev->aiocb);
if (rc == -1) {
ngx_log_error(NGX_LOG_CRIT, ev->log, ngx_errno, "aio_return() failed");
return NGX_ERROR;
}
ngx_log_debug(ev->log, "aio_write: %d" _ rc);
return rc;
}

View File

@ -1,14 +1,7 @@
#include <ngx_config.h>
#include <ngx_core.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_aio.h>
ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in)
@ -25,19 +18,19 @@ ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in)
while (ce) {
ngx_log_debug(c->log, "aio_write ce: %x" _ ce->hunk->pos.mem);
ngx_log_debug(c->log, "aio_write ce: %x" _ ce->hunk->pos);
buf = prev = ce->hunk->pos.mem;
buf = prev = ce->hunk->pos;
size = 0;
/* coalesce the neighbouring chain entries */
while (ce && prev == ce->hunk->pos.mem) {
size += ce->hunk->last.mem - ce->hunk->pos.mem;
prev = ce->hunk->last.mem;
while (ce && prev == ce->hunk->pos) {
size += ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last;
ce = ce->next;
}
rc = ngx_event_aio_write(c, buf, size);
rc = ngx_aio_write(c, buf, size);
ngx_log_debug(c->log, "aio_write rc: %d" _ rc);
@ -62,27 +55,27 @@ ngx_log_debug(c->log, "aio_write rc: %d" _ rc);
#if (NGX_DEBUG_WRITE_CHAIN)
ngx_log_debug(c->log, "write chain: %x %qx %qd" _
ce->hunk->type _
ce->hunk->pos.file _
ce->hunk->last.file - ce->hunk->pos.file);
ce->hunk->file_pos _
ce->hunk->file_last - ce->hunk->file_pos);
#endif
if (sent >= ce->hunk->last.file - ce->hunk->pos.file) {
sent -= ce->hunk->last.file - ce->hunk->pos.file;
ce->hunk->pos.file = ce->hunk->last.file;
if (sent >= ce->hunk->file_last - ce->hunk->file_pos) {
sent -= ce->hunk->file_last - ce->hunk->file_pos;
ce->hunk->file_pos = ce->hunk->file_last;
#if (NGX_DEBUG_WRITE_CHAIN)
ngx_log_debug(c->log, "write chain done: %qx %qd" _
ce->hunk->pos.file _ sent);
ce->hunk->file_pos _ sent);
#endif
continue;
}
ce->hunk->pos.file += sent;
ce->hunk->file_pos += sent;
#if (NGX_DEBUG_WRITE_CHAIN)
ngx_log_debug(c->log, "write chain rest: %qx %qd" _
ce->hunk->pos.file _
ce->hunk->last.file - ce->hunk->pos.file);
ce->hunk->file_pos _
ce->hunk->file_last - ce->hunk->file_pos);
#endif
break;

View File

@ -0,0 +1,112 @@
#ifndef _NGX_FREEBSD_CONFIG_H_INCLUDED_
#define _NGX_FREEBSD_CONFIG_H_INCLUDED_
#include <unistd.h>
#include <stddef.h> /* offsetof */
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <osreldate.h>
#ifndef HAVE_SELECT
#define HAVE_SELECT 1
#endif
#ifndef HAVE_POLL
#define HAVE_POLL 1
#endif
#if (HAVE_POLL)
#include <poll.h>
#endif
/* FreeBSD aio supported via kqueue */
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \
|| __FreeBSD_version >= 500014
#ifndef HAVE_AIO
#define HAVE_AIO 1
#endif
#endif
#if (HAVE_AIO)
#include <aio.h>
#endif
#if defined SO_ACCEPTFILTER && !defined HAVE_DEFERRED_ACCEPT
#define HAVE_DEFERRED_ACCEPT 1
#endif
/* FreeBSD sendfile */
#if __FreeBSD_version >= 300007
#ifndef HAVE_FREEBSD_SENDFILE
#define HAVE_FREEBSD_SENDFILE 1
#endif
#endif
#if (HAVE_FREEBSD_SENDFILE)
#define HAVE_SENDFILE 1
#endif
/* FreeBSD kqueue */
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 410000) \
|| __FreeBSD_version >= 500011
#ifndef HAVE_KQUEUE
#define HAVE_KQUEUE 1
#endif
#endif
#if (HAVE_KQUEUE)
#include <sys/event.h>
#endif
/* kqueue's NOTE_LOWAT */
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \
|| __FreeBSD_version >= 500018
#ifndef HAVE_LOWAT_EVENT
#define HAVE_LOWAT_EVENT 1
#endif
#endif
#ifndef HAVE_INHERITED_NONBLOCK
#define HAVE_INHERITED_NONBLOCK 1
#endif
#endif /* _NGX_FREEBSD_CONFIG_H_INCLUDED_ */

View File

@ -12,9 +12,10 @@ int ngx_freebsd_sendfile_nbytes_bug;
ngx_os_io_t ngx_os_io = {
ngx_unix_recv,
ngx_readv_chain,
NULL,
NULL,
ngx_freebsd_write_chain
ngx_freebsd_write_chain,
NGX_HAVE_SENDFILE|NGX_HAVE_ZEROCOPY
};
@ -107,5 +108,5 @@ int ngx_os_init(ngx_log_t *log)
ngx_log_error(NGX_LOG_INFO, log, 0, "net.inet.tcp.sendspace: %d",
ngx_freebsd_net_inet_tcp_sendspace);
return ngx_unix_init(log);
return ngx_posix_init(log);
}

View File

@ -7,8 +7,11 @@
#include <sys/sysctl.h>
int ngx_unix_init(ngx_log_t *log);
/* STUB */
int ngx_posix_init(ngx_log_t *log);
ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size);
ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry);
/* */
extern int ngx_freebsd_kern_osreldate;

View File

@ -0,0 +1,48 @@
#ifndef _NGX_LINUX_CONFIG_H_INCLUDED_
#define _NGX_LINUX_CONFIG_H_INCLUDED_
#include <unistd.h>
#include <stddef.h> /* offsetof */
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifndef HAVE_SELECT
#define HAVE_SELECT 1
#endif
#ifndef HAVE_POLL
#define HAVE_POLL 1
#endif
#if (HAVE_POLL)
#include <poll.h>
#endif
#if defined TCP_DEFER_ACCEPT && !defined HAVE_DEFERRED_ACCEPT
#define HAVE_DEFERRED_ACCEPT 1
#endif
#ifndef HAVE_INHERITED_NONBLOCK
#define HAVE_INHERITED_NONBLOCK 1
#endif
#endif /* _NGX_LINUX_CONFIG_H_INCLUDED_ */

View File

@ -0,0 +1,70 @@
#include <ngx_config.h>
#include <ngx_core.h>
int ngx_max_sockets;
int ngx_inherited_nonblocking;
int ngx_posix_init(ngx_log_t *log)
{
struct sigaction sa;
struct rlimit rlmt;
ngx_memzero(&sa, sizeof(struct sigaction));
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGPIPE, &sa, NULL) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"sigaction(SIGPIPE, SIG_IGN) failed");
return NGX_ERROR;
}
if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"getrlimit(RLIMIT_NOFILE) failed)");
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_INFO, log, 0,
"getrlimit(RLIMIT_NOFILE): %qd:%qd",
rlmt.rlim_cur, rlmt.rlim_max);
ngx_max_sockets = rlmt.rlim_cur;
#if (HAVE_INHERITED_NONBLOCK)
ngx_inherited_nonblocking = 1;
#else
ngx_inherited_nonblocking = 0;
#endif
return NGX_OK;
}
int ngx_posix_post_conf_init(ngx_log_t *log)
{
ngx_fd_t pp[2];
if (pipe(pp) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "pipe() failed");
return NGX_ERROR;
}
if (dup2(pp[1], STDERR_FILENO) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, errno, "dup2(STDERR) failed");
return NGX_ERROR;
}
if (pp[1] > STDERR_FILENO) {
if (close(pp[1]) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, errno, "close() failed");
return NGX_ERROR;
}
}
return NGX_OK;
}

View File

@ -1,12 +1,9 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_errno.h>
#include <ngx_log.h>
#include <ngx_connection.h>
ssize_t ngx_recv_chain(ngx_connection_t *c, ngx_chain_t *entry)
ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry)
{
ssize_t n;
struct iovec *iov;

View File

@ -17,7 +17,7 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
#if (HAVE_KQUEUE) /* DEBUG */
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
ngx_log_debug(c->log, "ngx_recv: eof:%d, avail:%d, err:%d" _
ngx_log_debug(c->log, "recv: eof:%d, avail:%d, err:%d" _
ev->eof _ ev->available _ ev->error);
}
#endif
@ -38,7 +38,7 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
} else {
n = recv(c->fd, buf, size, 0);
ngx_log_debug(c->log, "ngx_recv: read:%d:%d" _ n _ size);
ngx_log_debug(c->log, "recv: read:%d:%d" _ n _ size);
if (n == -1) {
err = ngx_socket_errno;
@ -49,6 +49,8 @@ ngx_log_debug(c->log, "ngx_recv: read:%d:%d" _ n _ size);
n = recv(c->fd, buf, size, 0);
ngx_log_debug(c->log, "recv: read:%d:%d" _ n _ size);
if (n == -1) {
err = ngx_socket_errno;
}

View File

@ -2,12 +2,15 @@
#include <ngx_socket.h>
/* ioctl(FIONBIO) set blocking mode with one syscall only while
/*
ioctl(FIONBIO) set blocking mode with one syscall only while
fcntl(F_SETFL, ~O_NONBLOCK) need to know previous state
using fcntl(F_GETFL).
On FreeBSD both are syscall */
#ifdef __FreeBSD__
ioctl() and fcntl() are syscalls on FreeBSD, Solaris 7/8 and Linux
*/
#if 1
int ngx_nonblocking(ngx_socket_t s)
{

View File

@ -4,10 +4,6 @@
#include <ngx_config.h>
#ifdef __FreeBSD__
#include <sys/ioctl.h>
#endif
#define NGX_WRITE_SHUTDOWN SHUT_WR
@ -17,7 +13,7 @@ typedef int ngx_socket_t;
#define ngx_socket_n "socket()"
#ifdef __FreeBSD__
#if 1
int ngx_nonblocking(ngx_socket_t s);
int ngx_blocking(ngx_socket_t s);

View File

@ -0,0 +1,64 @@
#ifndef _NGX_SOLARIS_CONFIG_H_INCLUDED_
#define _NGX_SOLARIS_CONFIG_H_INCLUDED_
#define SOLARIS 1
#define _FILE_OFFSET_BITS 64 /* must be before sys/types.h */
#include <unistd.h>
#include <stddef.h> /* offsetof */
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <strings.h> /* bzero() */
#include <sys/types.h>
#include <sys/filio.h> /* FIONBIO */
#include <sys/stropts.h> /* INFTIM */
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
typedef uint32_t u_int32_t;
#ifndef HAVE_SELECT
#define HAVE_SELECT 1
#endif
#ifndef HAVE_POLL
#define HAVE_POLL 1
#endif
#if (HAVE_POLL)
#include <poll.h>
#endif
#if (HAVE_AIO)
#include <aio.h>
#endif
#if (HAVE_DEVPOLL)
#include <sys/ioctl.h>
#include <sys/devpoll.h>
#endif
#ifndef HAVE_INHERITED_NONBLOCK
#define HAVE_INHERITED_NONBLOCK 1
#endif
#endif /* _NGX_SOLARIS_CONFIG_H_INCLUDED_ */

View File

@ -3,61 +3,30 @@
#include <ngx_core.h>
int ngx_max_sockets;
/* STUB */
ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size);
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in);
int ngx_posix_init(ngx_log_t *log);
int ngx_posix_post_conf_init(ngx_log_t *log);
/* */
int ngx_unix_init(ngx_log_t *log)
ngx_os_io_t ngx_os_io = {
ngx_unix_recv,
NULL,
NULL,
ngx_writev_chain,
NGX_HAVE_ZEROCOPY
};
int ngx_os_init(ngx_log_t *log)
{
struct sigaction sa;
struct rlimit rlmt;
ngx_memzero(&sa, sizeof(struct sigaction));
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGPIPE, &sa, NULL) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"sigaction(SIGPIPE, SIG_IGN) failed");
return NGX_ERROR;
}
if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"getrlimit(RLIMIT_NOFILE) failed)");
return NGX_ERROR;
}
ngx_log_error(NGX_LOG_INFO, log, 0,
"getrlimit(RLIMIT_NOFILE): %qd:%qd",
rlmt.rlim_cur, rlmt.rlim_max);
ngx_max_sockets = rlmt.rlim_cur;
return NGX_OK;
return ngx_posix_init(log);
}
int ngx_unix_post_conf_init(ngx_log_t *log)
int ngx_os_post_conf_init(ngx_log_t *log)
{
ngx_fd_t pp[2];
if (pipe(pp) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "pipe() failed");
return NGX_ERROR;
}
if (dup2(pp[1], STDERR_FILENO) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, errno, "dup2(STDERR) failed");
return NGX_ERROR;
}
if (pp[1] > STDERR_FILENO) {
if (close(pp[1]) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, errno, "close() failed");
return NGX_ERROR;
}
}
return NGX_OK;
return ngx_posix_post_conf_init(log);
}

View File

@ -0,0 +1,93 @@
#include <ngx_config.h>
#include <ngx_core.h>
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
{
char *prev;
size_t size;
ssize_t n;
off_t sent;
struct iovec *iov;
ngx_err_t err;
ngx_array_t io;
ngx_chain_t *ce;
ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
prev = NULL;
iov = NULL;
/* create the iovec and coalesce the neighbouring chain entries */
for (ce = in; ce; ce = ce->next) {
if (prev == ce->hunk->pos) {
iov->iov_len += ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last;
} else {
ngx_test_null(iov, ngx_push_array(&io), NGX_CHAIN_ERROR);
iov->iov_base = ce->hunk->pos;
iov->iov_len = ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last;
}
}
n = writev(c->fd, (struct iovec *) io.elts, io.nelts);
if (n == -1) {
err = ngx_errno;
if (err == NGX_EAGAIN) {
ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN");
} else if (err == NGX_EINTR) {
ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
} else {
ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
return NGX_CHAIN_ERROR;
}
}
sent = n > 0 ? n : 0;
#if (NGX_DEBUG_WRITE_CHAIN)
ngx_log_debug(c->log, "writev: %qd" _ sent);
#endif
c->sent += sent;
for (ce = in; ce && sent > 0; ce = ce->next) {
size = ce->hunk->last - ce->hunk->pos;
if (sent >= size) {
sent -= size;
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
ce->hunk->pos = ce->hunk->last;
}
if (ce->hunk->type & NGX_HUNK_FILE) {
ce->hunk->file_pos = ce->hunk->file_last;
}
continue;
}
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
ce->hunk->pos += sent;
}
if (ce->hunk->type & NGX_HUNK_FILE) {
ce->hunk->file_pos += sent;
}
break;
}
ngx_destroy_array(&io);
return ce;
}

View File

@ -7,17 +7,10 @@ int ngx_max_sockets;
ngx_os_io_t ngx_os_io = {
#if 0
ngx_unix_recv,
NULL,
NULL,
ngx_freebsd_write_chain
#else
NULL,
ngx_wsarecv,
NULL,
NULL,
NULL
#endif
};

93
src/os/win32/ngx_recv.c Normal file
View File

@ -0,0 +1,93 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
{
int rc;
u_int flags;
size_t bytes;
ngx_err_t err;
WSABUF wsabuf[1];
ngx_event_t *ev;
LPWSAOVERLAPPED_COMPLETION_ROUTINE handler;
ev = c->read;
/* DEBUG */ bytes = 0;
if (ev->timedout) {
ngx_set_socket_errno(NGX_ETIMEDOUT);
ngx_log_error(NGX_LOG_ERR, ev->log, 0, "WSARecv() timed out");
return NGX_ERROR;
}
if (ev->ready) {
ev->ready = 0;
#if (HAVE_IOCP_EVENT) /* iocp */
if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
if (ev->ovlp.error) {
ngx_log_error(NGX_LOG_ERR, c->log, ev->ovlp.error,
"WSARecv() failed");
return NGX_ERROR;
}
return ev->available;
}
#endif
if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &ev->ovlp,
&bytes, 0, NULL) == 0) {
err = ngx_socket_errno;
ngx_log_error(NGX_LOG_CRIT, ev->log, err,
"WSARecv() or WSAGetOverlappedResult() failed");
return NGX_ERROR;
}
return bytes;
}
ngx_memzero(&ev->ovlp, sizeof(WSAOVERLAPPED));
wsabuf[0].buf = buf;
wsabuf[0].len = size;
flags = 0;
#if 0
handler = ev->handler;
#else
handler = NULL;
#endif
rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags,
(LPWSAOVERLAPPED) &ev->ovlp, handler);
ngx_log_debug(ev->log, "WSARecv: %d:%d" _ rc _ bytes);
if (rc == -1) {
err = ngx_socket_errno;
if (err == WSA_IO_PENDING) {
return NGX_AGAIN;
} else {
ngx_log_error(NGX_LOG_CRIT, ev->log, err, "WSARecv() failed");
return NGX_ERROR;
}
}
#if (HAVE_IOCP_EVENT) /* iocp */
if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
return NGX_AGAIN;
}
#endif
return bytes;
}

View File

@ -0,0 +1,35 @@
#ifndef _NGX_WIN32_CONFIG_H_INCLUDED_
#define _NGX_WIN32_CONFIG_H_INCLUDED_
#define WIN32 1
#include <winsock2.h>
#include <mswsock.h>
#include <stddef.h> /* offsetof */
#include <stdio.h>
#include <stdarg.h>
#define ngx_inline __inline
#ifndef HAVE_INHERITED_NONBLOCK
#define HAVE_INHERITED_NONBLOCK 1
#endif
#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
#endif /* _NGX_WIN32_CONFIG_H_INCLUDED_ */