src/event/ngx_event_acceptex.c - nginx source code

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. static void ngx_close_posted_connection(ngx_connection_t *c);


  9. void
  10. ngx_event_acceptex(ngx_event_t *rev)
  11. {
  12.     ngx_listening_t   *ls;
  13.     ngx_connection_t  *c;

  14.     c = rev->data;
  15.     ls = c->listening;

  16.     c->log->handler = ngx_accept_log_error;

  17.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "AcceptEx: %d", c->fd);

  18.     if (rev->ovlp.error) {
  19.         ngx_log_error(NGX_LOG_CRIT, c->log, rev->ovlp.error,
  20.                       "AcceptEx() %V failed", &ls->addr_text);
  21.         return;
  22.     }

  23.     /* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */

  24.     if (setsockopt(c->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
  25.                    (char *) &ls->fd, sizeof(ngx_socket_t))
  26.         == -1)
  27.     {
  28.         ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
  29.                       "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed for %V",
  30.                       &c->addr_text);
  31.         /* TODO: close socket */
  32.         return;
  33.     }

  34.     ngx_getacceptexsockaddrs(c->buffer->pos,
  35.                              ls->post_accept_buffer_size,
  36.                              ls->socklen + 16,
  37.                              ls->socklen + 16,
  38.                              &c->local_sockaddr, &c->local_socklen,
  39.                              &c->sockaddr, &c->socklen);

  40.     if (ls->post_accept_buffer_size) {
  41.         c->buffer->last += rev->available;
  42.         c->buffer->end = c->buffer->start + ls->post_accept_buffer_size;

  43.     } else {
  44.         c->buffer = NULL;
  45.     }

  46.     if (ls->addr_ntop) {
  47.         c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len);
  48.         if (c->addr_text.data == NULL) {
  49.             /* TODO: close socket */
  50.             return;
  51.         }

  52.         c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->socklen,
  53.                                          c->addr_text.data,
  54.                                          ls->addr_text_max_len, 0);
  55.         if (c->addr_text.len == 0) {
  56.             /* TODO: close socket */
  57.             return;
  58.         }
  59.     }

  60.     ngx_event_post_acceptex(ls, 1);

  61.     c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);

  62.     c->start_time = ngx_current_msec;

  63.     ls->handler(c);

  64.     return;

  65. }


  66. ngx_int_t
  67. ngx_event_post_acceptex(ngx_listening_t *ls, ngx_uint_t n)
  68. {
  69.     u_long             rcvd;
  70.     ngx_err_t          err;
  71.     ngx_log_t         *log;
  72.     ngx_uint_t         i;
  73.     ngx_event_t       *rev, *wev;
  74.     ngx_socket_t       s;
  75.     ngx_connection_t  *c;

  76.     for (i = 0; i < n; i++) {

  77.         /* TODO: look up reused sockets */

  78.         s = ngx_socket(ls->sockaddr->sa_family, ls->type, 0);

  79.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &ls->log, 0,
  80.                        ngx_socket_n " s:%d", s);

  81.         if (s == (ngx_socket_t) -1) {
  82.             ngx_log_error(NGX_LOG_ALERT, &ls->log, ngx_socket_errno,
  83.                           ngx_socket_n " failed");

  84.             return NGX_ERROR;
  85.         }

  86.         c = ngx_get_connection(s, &ls->log);

  87.         if (c == NULL) {
  88.             return NGX_ERROR;
  89.         }

  90.         c->pool = ngx_create_pool(ls->pool_size, &ls->log);
  91.         if (c->pool == NULL) {
  92.             ngx_close_posted_connection(c);
  93.             return NGX_ERROR;
  94.         }

  95.         log = ngx_palloc(c->pool, sizeof(ngx_log_t));
  96.         if (log == NULL) {
  97.             ngx_close_posted_connection(c);
  98.             return NGX_ERROR;
  99.         }

  100.         c->buffer = ngx_create_temp_buf(c->pool, ls->post_accept_buffer_size
  101.                                                  + 2 * (ls->socklen + 16));
  102.         if (c->buffer == NULL) {
  103.             ngx_close_posted_connection(c);
  104.             return NGX_ERROR;
  105.         }

  106.         c->local_sockaddr = ngx_palloc(c->pool, ls->socklen);
  107.         if (c->local_sockaddr == NULL) {
  108.             ngx_close_posted_connection(c);
  109.             return NGX_ERROR;
  110.         }

  111.         c->sockaddr = ngx_palloc(c->pool, ls->socklen);
  112.         if (c->sockaddr == NULL) {
  113.             ngx_close_posted_connection(c);
  114.             return NGX_ERROR;
  115.         }

  116.         *log = ls->log;
  117.         c->log = log;

  118.         c->recv = ngx_recv;
  119.         c->send = ngx_send;
  120.         c->recv_chain = ngx_recv_chain;
  121.         c->send_chain = ngx_send_chain;

  122.         c->listening = ls;

  123.         rev = c->read;
  124.         wev = c->write;

  125.         rev->ovlp.event = rev;
  126.         wev->ovlp.event = wev;
  127.         rev->handler = ngx_event_acceptex;

  128.         rev->ready = 1;
  129.         wev->ready = 1;

  130.         rev->log = c->log;
  131.         wev->log = c->log;

  132.         if (ngx_add_event(rev, 0, NGX_IOCP_IO) == NGX_ERROR) {
  133.             ngx_close_posted_connection(c);
  134.             return NGX_ERROR;
  135.         }

  136.         if (ngx_acceptex(ls->fd, s, c->buffer->pos, ls->post_accept_buffer_size,
  137.                          ls->socklen + 16, ls->socklen + 16,
  138.                          &rcvd, (LPOVERLAPPED) &rev->ovlp)
  139.             == 0)
  140.         {
  141.             err = ngx_socket_errno;
  142.             if (err != WSA_IO_PENDING) {
  143.                 ngx_log_error(NGX_LOG_ALERT, &ls->log, err,
  144.                               "AcceptEx() %V failed", &ls->addr_text);

  145.                 ngx_close_posted_connection(c);
  146.                 return NGX_ERROR;
  147.             }
  148.         }
  149.     }

  150.     return NGX_OK;
  151. }


  152. static void
  153. ngx_close_posted_connection(ngx_connection_t *c)
  154. {
  155.     ngx_socket_t  fd;

  156.     ngx_free_connection(c);

  157.     fd = c->fd;
  158.     c->fd = (ngx_socket_t) -1;

  159.     if (ngx_close_socket(fd) == -1) {
  160.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
  161.                       ngx_close_socket_n " failed");
  162.     }

  163.     if (c->pool) {
  164.         ngx_destroy_pool(c->pool);
  165.     }
  166. }


  167. u_char *
  168. ngx_acceptex_log_error(ngx_log_t *log, u_char *buf, size_t len)
  169. {
  170.     return ngx_snprintf(buf, len, " while posting AcceptEx() on %V", log->data);
  171. }