#include <ngxe.h>
struct rlimit rlmt;
static ngx_log_t ngx_log;
static ngx_open_file_t ngx_log_file;
static ngx_int_t
ngx_events_modules_init(ngx_cycle_t *cycle)
{
char *rv;
void ***ctx;
ngx_uint_t i;
ngx_event_module_t *m;
ngx_uint_t ngx_event_max_module;
/* count the number of the event modules and set up their indices */
ngx_event_max_module = 0;
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
continue;
}
ngx_modules[i]->ctx_index = ngx_event_max_module++;
}
ctx = ngx_pcalloc(cycle->pool, sizeof(void *));
if (ctx == NULL) {
return NGX_ERROR;
}
*ctx = ngx_pcalloc(cycle->pool, ngx_event_max_module * sizeof(void *));
if (*ctx == NULL) {
return NGX_ERROR;
}
cycle->conf_ctx[ngx_events_module.index] = ctx;
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
continue;
}
m = ngx_modules[i]->ctx;
if (m->create_conf) {
(*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cycle);
if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
return NGX_ERROR;
}
}
}
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
continue;
}
m = ngx_modules[i]->ctx;
if (m->init_conf) {
rv = m->init_conf(cycle, (*ctx)[ngx_modules[i]->ctx_index]);
if (rv != NGX_CONF_OK) {
return NGX_ERROR;
}
}
}
return NGX_OK;
}
static ngx_log_t *
ngx_ngxe_log_init(u_char *logfilename)
{
u_char *name;
size_t nlen;
ngx_log.file = &ngx_log_file;
ngx_log.log_level = NGX_LOG_NOTICE;
/* ngx_log.log_level = NGX_LOG_DEBUG_ALL; */
/*
* we use ngx_strlen() here since BCC warns about
* condition is always false and unreachable code
*/
nlen = ngx_strlen(logfilename);
if (nlen == 0) {
ngx_log_file.fd = ngx_stderr;
return &ngx_log;
}
name = malloc(nlen + 2);
if (name == NULL) {
return NULL;
}
ngx_cpystrn(name, logfilename, nlen + 1);
ngx_log_file.fd = ngx_open_file(name, NGX_FILE_APPEND,
NGX_FILE_CREATE_OR_OPEN,
NGX_FILE_DEFAULT_ACCESS);
if (ngx_log_file.fd == NGX_INVALID_FILE) {
ngx_log_stderr(ngx_errno,
"[alert]: could not open error log file: "
ngx_open_file_n " \"%s\" failed", name);
#if (NGX_WIN32)
ngx_event_log(ngx_errno,
"could not open error log file: "
ngx_open_file_n " \"%s\" failed", name);
#endif
ngx_log_file.fd = ngx_stderr;
}
return &ngx_log;
}
ngx_listening_t *
ngx_ngxe_create_listening(ngx_pool_t *pool, void *sockaddr, socklen_t socklen)
{
size_t len;
ngx_listening_t *ls;
struct sockaddr *sa;
u_char text[NGX_SOCKADDR_STRLEN];
ls = ngx_pcalloc(pool, sizeof(ngx_listening_t));
if (ls == NULL) {
return NULL;
}
ngx_memzero(ls, sizeof(ngx_listening_t));
sa = ngx_palloc(pool, socklen);
if (sa == NULL) {
return NULL;
}
ngx_memcpy(sa, sockaddr, socklen);
ls->sockaddr = sa;
ls->socklen = socklen;
len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
ls->addr_text.len = len;
switch (ls->sockaddr->sa_family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
break;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
len++;
break;
#endif
case AF_INET:
ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
break;
default:
ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
break;
}
ls->addr_text.data = ngx_pnalloc(pool, len);
if (ls->addr_text.data == NULL) {
return NULL;
}
ngx_memcpy(ls->addr_text.data, text, len);
ls->fd = (ngx_socket_t) -1;
ls->type = SOCK_STREAM;
ls->backlog = NGX_LISTEN_BACKLOG;
ls->rcvbuf = -1;
ls->sndbuf = -1;
#if (NGX_HAVE_SETFIB)
ls->setfib = -1;
#endif
return ls;
}
void
ngx_ngxe_open_listening_socket(ngx_listening_t *ls)
{
int reuseaddr;
ngx_err_t err;
ngx_socket_t s;
ngx_log_t *log;
reuseaddr = 1;
log = ls->logp;
if (ls->ignore) {
return;
}
if (ls->fd != -1) {
return;
}
if (ls->inherited) {
/* TODO: close on exit */
/* TODO: nonblocking */
/* TODO: deferred accept */
return;
}
s = ngx_socket(ls->sockaddr->sa_family, ls->type, 0);
if (s == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_socket_n " %V failed", &ls->addr_text);
return;
}
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(const void *) &reuseaddr, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
"setsockopt(SO_REUSEADDR) %V failed",
&ls->addr_text);
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls->addr_text);
}
return;
}
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
if (ls->sockaddr->sa_family == AF_INET6 && ls->ipv6only) {
int ipv6only;
ipv6only = (ls->ipv6only == 1);
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(const void *) &ipv6only, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
"setsockopt(IPV6_V6ONLY) %V failed, ignored",
&ls->addr_text);
}
}
#endif
/* TODO: close on exit */
if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
if (ngx_nonblocking(s) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_nonblocking_n " %V failed",
&ls->addr_text);
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls->addr_text);
}
return;
}
}
ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
"bind() %V #%d ", &ls->addr_text, s);
if (bind(s, ls->sockaddr, ls->socklen) == -1) {
err = ngx_socket_errno;
if (err == NGX_EADDRINUSE && ngx_test_config) {
return;
}
ngx_log_error(NGX_LOG_EMERG, log, err,
"bind() to %V failed", &ls->addr_text);
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls->addr_text);
}
if (err != NGX_EADDRINUSE) {
return;
}
return;
}
#if (NGX_HAVE_UNIX_DOMAIN)
if (ls->sockaddr->sa_family == AF_UNIX) {
mode_t mode;
u_char *name;
name = ls->addr_text.data + sizeof("unix:") - 1;
mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
if (chmod((char *) name, mode) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"chmod() \"%s\" failed", name);
}
if (ngx_test_config) {
if (ngx_delete_file(name) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
ngx_delete_file_n " %s failed", name);
}
}
}
#endif
if (listen(s, ls->backlog) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
"listen() to %V, backlog %d failed",
&ls->addr_text, ls->backlog);
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls->addr_text);
}
return;
}
ls->listen = 1;
ls->fd = s;
}
ngx_int_t
ngx_ngxe_add_listening_connection(ngx_listening_t *ls)
{
ngx_connection_t *c, *old;
ngx_event_t *rev;
c = ngx_get_connection(ls->fd, ls->logp);
if (c == NULL) {
return NGX_ERROR;
}
c->log = ls->logp;
c->listening = ls;
ls->connection = c;
rev = c->read;
rev->log = c->log;
rev->accept = 1;
#if (NGX_HAVE_DEFERRED_ACCEPT)
rev->deferred_accept = ls->deferred_accept;
#endif
if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
if (ls->previous) {
/*
* delete the old accept events that were bound to
* the old cycle read events array
*/
old = ls->previous->connection;
if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)
== NGX_ERROR)
{
return NGX_ERROR;
}
old->fd = (ngx_socket_t) -1;
}
}
#if (NGX_WIN32)
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
ngx_iocp_conf_t *iocpcf;
rev->handler = ngx_event_acceptex;
if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
return NGX_ERROR;
}
ls->log.handler = ngx_acceptex_log_error;
iocpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module);
if (ngx_event_post_acceptex(ls, iocpcf->post_acceptex)
== NGX_ERROR)
{
return NGX_ERROR;
}
} else {
rev->handler = ngx_event_accept;
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
return NGX_ERROR;
}
}
#else
rev->handler = ngx_event_accept;
if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
if (ngx_add_conn(c) == NGX_ERROR) {
return NGX_ERROR;
}
} else {
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
return NGX_ERROR;
}
}
#endif
return NGX_OK;
}
static ngx_int_t
ngx_ngxe_os_init(ngx_log_t *log)
{
ngx_uint_t n;
#if (NGX_HAVE_OS_SPECIFIC_INIT)
if (ngx_os_specific_init(log) != NGX_OK) {
return NGX_ERROR;
}
#endif
/*
* ngx_init_setproctitle(log);
*/
ngx_pagesize = getpagesize();
ngx_cacheline_size = NGX_CPU_CACHE_LINE;
for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
if (ngx_ncpu == 0) {
ngx_ncpu = 1;
}
ngx_cpuinfo();
if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, errno,
"getrlimit(RLIMIT_NOFILE) failed)");
return NGX_ERROR;
}
ngx_max_sockets = (ngx_int_t) rlmt.rlim_cur;
#if (NGX_HAVE_INHERITED_NONBLOCK)
ngx_inherited_nonblocking = 1;
#else
ngx_inherited_nonblocking = 0;
#endif
srandom(ngx_time());
return NGX_OK;
}
ngx_int_t
ngx_ngxe_init_signals()
{
/*
#if !(NGX_WIN32)
if (ngx_init_signals(ngx_cycle->log) != NGX_OK) {
return 1;
}
#endif
*/
return 0;
}
ngx_int_t
ngx_ngxe_init(char *logfilename, int usestderr, int connections)
{
ngx_log_t *log;
ngx_pool_t *pool;
ngx_cycle_t *cycle;
void *rv;
ngx_int_t i;
ngx_max_sockets = -1;
ngx_time_init();
log = ngx_ngxe_log_init((u_char *) logfilename);
if (log == NULL) {
return 1;
}
if (ngx_ngxe_os_init(log) != NGX_OK) {
return 1;
}
pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
if (pool == NULL) {
return 1;
}
pool->log = log;
cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
if (cycle == NULL) {
ngx_destroy_pool(pool);
return 1;
}
cycle->pool = pool;
cycle->log = log;
cycle->new_log.log_level = NGX_LOG_ERR;
cycle->old_cycle = cycle; /* */
ngx_cycle = cycle;
/* ngx_crc32_table_init uses ngx_cycle->log and cannot
* be initialized earlier
*/
if (ngx_crc32_table_init() != NGX_OK) {
return 1;
}
#if !(NGX_WIN32)
if (ngx_init_signals(cycle->log) != NGX_OK) {
ngx_destroy_pool(pool);
return 1;
}
#endif
ngx_os_status(log);
ngx_use_stderr = 0;
if (usestderr)
ngx_use_stderr = 1;
ngx_max_module = 0;
for (i = 0; ngx_modules[i]; i++) {
ngx_modules[i]->index = ngx_max_module++;
}
cycle->conf_ctx = ngx_pcalloc(cycle->pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
ngx_destroy_pool(pool);
return 1;
}
rv = ((ngx_core_module_t *) ngx_core_module.ctx)->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return 1;
}
cycle->conf_ctx[ngx_core_module.index] = rv;
if (((ngx_core_module_t *) ngx_core_module.ctx)->init_conf(cycle,
cycle->conf_ctx[ngx_core_module.index]) == NGX_CONF_ERROR)
{
ngx_destroy_pool(pool);
return 1;
}
rv = ((ngx_event_module_t *) ngx_event_core_module.ctx)->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return 1;
}
cycle->conf_ctx[ngx_event_core_module.index] = rv;
if (((ngx_event_module_t *) ngx_event_core_module.ctx)->init_conf(cycle,
cycle->conf_ctx[ngx_event_core_module.index]) == NGX_CONF_ERROR)
{
ngx_destroy_pool(pool);
return 1;
}
if (ngx_events_modules_init(cycle) == NGX_ERROR) {
ngx_destroy_pool(pool);
return 1;
}
if (ngx_event_core_module.init_module(cycle) == NGX_ERROR) {
ngx_destroy_pool(pool);
return 1;
}
cycle->connection_n = connections;
if (ngx_event_core_module.init_process(cycle) == NGX_ERROR) {
ngx_destroy_pool(pool);
return 1;
}
return 0;
}