ngx_event_accept.c

来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 396 行

C
396
字号
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_event.h>/* the buffer size is enough to hold "struct sockaddr_un" */#define NGX_SOCKLEN  512static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle);static void ngx_close_accepted_connection(ngx_connection_t *c);voidngx_event_accept(ngx_event_t *ev){    socklen_t          socklen;    ngx_err_t          err;    ngx_log_t         *log;    ngx_socket_t       s;    ngx_event_t       *rev, *wev;    ngx_listening_t   *ls;    ngx_connection_t  *c, *lc;    ngx_event_conf_t  *ecf;    char               sa[NGX_SOCKLEN];    ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);    if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {        ev->available = 1;    } else if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) {        ev->available = ecf->multi_accept;    }    lc = ev->data;    ls = lc->listening;    ev->ready = 0;    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,                   "accept on %V, ready: %d", &ls->addr_text, ev->available);    do {        socklen = NGX_SOCKLEN;        s = accept(lc->fd, (struct sockaddr *) sa, &socklen);        if (s == -1) {            err = ngx_socket_errno;            if (err == NGX_EAGAIN) {                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err,                               "accept() not ready");                return;            }            ngx_log_error((err == NGX_ECONNABORTED) ? NGX_LOG_ERR:                                                      NGX_LOG_ALERT,                          ev->log, err, "accept() failed");            if (err == NGX_ECONNABORTED) {                if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {                    ev->available--;                }                if (ev->available) {                    continue;                }            }            return;        }#if (NGX_STAT_STUB)        ngx_atomic_fetch_add(ngx_stat_accepted, 1);#endif        ngx_accept_disabled = NGX_ACCEPT_THRESHOLD                              - ngx_cycle->free_connection_n;        c = ngx_get_connection(s, ev->log);        if (c == NULL) {            if (ngx_close_socket(s) == -1) {                ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,                              ngx_close_socket_n " failed");            }            return;        }#if (NGX_STAT_STUB)        ngx_atomic_fetch_add(ngx_stat_active, 1);#endif        c->pool = ngx_create_pool(ls->pool_size, ev->log);        if (c->pool == NULL) {            ngx_close_accepted_connection(c);            return;        }        c->sockaddr = ngx_palloc(c->pool, socklen);        if (c->sockaddr == NULL) {            ngx_close_accepted_connection(c);            return;        }        ngx_memcpy(c->sockaddr, sa, socklen);        log = ngx_palloc(c->pool, sizeof(ngx_log_t));        if (log == NULL) {            ngx_close_accepted_connection(c);            return;        }        /* set a blocking mode for aio and non-blocking mode for others */        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 " failed");                    ngx_close_accepted_connection(c);                    return;                }            }        } else {            if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {                if (ngx_nonblocking(s) == -1) {                    ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,                                  ngx_nonblocking_n " failed");                    ngx_close_accepted_connection(c);                    return;                }            }        }        *log = ls->log;        c->recv = ngx_recv;        c->send = ngx_send;        c->recv_chain = ngx_recv_chain;        c->send_chain = ngx_send_chain;        c->log = log;        c->pool->log = log;        c->listening = ls;        c->socklen = socklen;        c->unexpected_eof = 1;        rev = c->read;        wev = c->write;        wev->ready = 1;        if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {            /* rtsig, aio, iocp */            rev->ready = 1;        }        if (ev->deferred_accept) {            rev->ready = 1;#if (NGX_HAVE_KQUEUE)            rev->available = 1;#endif        }        rev->log = log;        wev->log = log;        /*         * TODO: MT: - ngx_atomic_fetch_add()         *             or protection by critical section or light mutex         *         * TODO: MP: - allocated in a shared memory         *           - ngx_atomic_fetch_add()         *             or protection by critical section or light mutex         */        c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);#if (NGX_STAT_STUB)        ngx_atomic_fetch_add(ngx_stat_handled, 1);#endif#if (NGX_THREADS)        rev->lock = &c->lock;        wev->lock = &c->lock;        rev->own_lock = &c->lock;        wev->own_lock = &c->lock;#endif        if (ls->addr_ntop) {            c->addr_text.data = ngx_palloc(c->pool, ls->addr_text_max_len);            if (c->addr_text.data == NULL) {                ngx_close_accepted_connection(c);                return;            }            c->addr_text.len = ngx_sock_ntop(ls->family, c->sockaddr,                                             c->addr_text.data,                                             ls->addr_text_max_len);            if (c->addr_text.len == 0) {                ngx_close_accepted_connection(c);                return;            }        }#if (NGX_DEBUG)        {        in_addr_t            i;        ngx_event_debug_t   *dc;        struct sockaddr_in  *sin;        sin = (struct sockaddr_in *) sa;        dc = ecf->debug_connection.elts;        for (i = 0; i < ecf->debug_connection.nelts; i++) {            if ((sin->sin_addr.s_addr & dc[i].mask) == dc[i].addr) {                log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL;                break;            }        }        }#endif        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,                       "*%d accept: %V fd:%d", c->number, &c->addr_text, s);        if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {            if (ngx_add_conn(c) == NGX_ERROR) {                ngx_close_accepted_connection(c);                return;            }        }        log->data = NULL;        log->handler = NULL;        ls->handler(c);        if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {            ev->available--;        }    } while (ev->available);}ngx_int_tngx_trylock_accept_mutex(ngx_cycle_t *cycle){    if (ngx_shmtx_trylock(&ngx_accept_mutex)) {        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,                       "accept mutex locked");        if (ngx_accept_mutex_held            && ngx_accept_events == 0            && !(ngx_event_flags & NGX_USE_RTSIG_EVENT))        {            return NGX_OK;        }        if (ngx_enable_accept_events(cycle) == NGX_ERROR) {            ngx_shmtx_unlock(&ngx_accept_mutex);            return NGX_ERROR;        }        ngx_accept_events = 0;        ngx_accept_mutex_held = 1;        return NGX_OK;    }    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,                   "accept mutex lock failed: %ui", ngx_accept_mutex_held);    if (ngx_accept_mutex_held) {        if (ngx_disable_accept_events(cycle) == NGX_ERROR) {            return NGX_ERROR;        }        ngx_accept_mutex_held = 0;    }    return NGX_OK;}static ngx_int_tngx_enable_accept_events(ngx_cycle_t *cycle){    ngx_uint_t         i;    ngx_listening_t   *ls;    ngx_connection_t  *c;    ls = cycle->listening.elts;    for (i = 0; i < cycle->listening.nelts; i++) {        c = ls[i].connection;        if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {            if (ngx_add_conn(c) == NGX_ERROR) {                return NGX_ERROR;            }        } else {            if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) {                return NGX_ERROR;            }        }    }    return NGX_OK;}static ngx_int_tngx_disable_accept_events(ngx_cycle_t *cycle){    ngx_uint_t         i;    ngx_listening_t   *ls;    ngx_connection_t  *c;    ls = cycle->listening.elts;    for (i = 0; i < cycle->listening.nelts; i++) {        c = ls[i].connection;        if (!c->read->active) {            continue;        }        if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {            if (ngx_del_conn(c, NGX_DISABLE_EVENT) == NGX_ERROR) {                return NGX_ERROR;            }        } else {            if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)                == NGX_ERROR)            {                return NGX_ERROR;            }        }    }    return NGX_OK;}static voidngx_close_accepted_connection(ngx_connection_t *c){    ngx_socket_t  fd;    ngx_free_connection(c);    fd = c->fd;    c->fd = (ngx_socket_t) -1;    if (ngx_close_socket(fd) == -1) {        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,                      ngx_close_socket_n " failed");    }    if (c->pool) {        ngx_destroy_pool(c->pool);    }#if (NGX_STAT_STUB)    ngx_atomic_fetch_add(ngx_stat_active, -1);#endif}u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len){    return ngx_snprintf(buf, len, " while accepting new connection on %V",                        log->data);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?