src/stream/ngx_stream_core_module.c - nginx source code

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Roman Arutyunyan
  3. * Copyright (C) Nginx, Inc.
  4. */


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


  8. static ngx_uint_t ngx_stream_preread_can_peek(ngx_connection_t *c);
  9. static ngx_int_t ngx_stream_preread_peek(ngx_stream_session_t *s,
  10.     ngx_stream_phase_handler_t *ph);
  11. static ngx_int_t ngx_stream_preread(ngx_stream_session_t *s,
  12.     ngx_stream_phase_handler_t *ph);
  13. static ngx_int_t ngx_stream_core_preconfiguration(ngx_conf_t *cf);
  14. static void *ngx_stream_core_create_main_conf(ngx_conf_t *cf);
  15. static char *ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf);
  16. static void *ngx_stream_core_create_srv_conf(ngx_conf_t *cf);
  17. static char *ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent,
  18.     void *child);
  19. static char *ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
  20.     void *conf);
  21. static char *ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
  22.     void *conf);
  23. static char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
  24.     void *conf);
  25. static char *ngx_stream_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
  26.     void *conf);
  27. static char *ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
  28.     void *conf);


  29. static ngx_command_t  ngx_stream_core_commands[] = {

  30.     { ngx_string("variables_hash_max_size"),
  31.       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
  32.       ngx_conf_set_num_slot,
  33.       NGX_STREAM_MAIN_CONF_OFFSET,
  34.       offsetof(ngx_stream_core_main_conf_t, variables_hash_max_size),
  35.       NULL },

  36.     { ngx_string("variables_hash_bucket_size"),
  37.       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
  38.       ngx_conf_set_num_slot,
  39.       NGX_STREAM_MAIN_CONF_OFFSET,
  40.       offsetof(ngx_stream_core_main_conf_t, variables_hash_bucket_size),
  41.       NULL },

  42.     { ngx_string("server_names_hash_max_size"),
  43.       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
  44.       ngx_conf_set_num_slot,
  45.       NGX_STREAM_MAIN_CONF_OFFSET,
  46.       offsetof(ngx_stream_core_main_conf_t, server_names_hash_max_size),
  47.       NULL },

  48.     { ngx_string("server_names_hash_bucket_size"),
  49.       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
  50.       ngx_conf_set_num_slot,
  51.       NGX_STREAM_MAIN_CONF_OFFSET,
  52.       offsetof(ngx_stream_core_main_conf_t, server_names_hash_bucket_size),
  53.       NULL },

  54.     { ngx_string("server"),
  55.       NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
  56.       ngx_stream_core_server,
  57.       0,
  58.       0,
  59.       NULL },

  60.     { ngx_string("listen"),
  61.       NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
  62.       ngx_stream_core_listen,
  63.       NGX_STREAM_SRV_CONF_OFFSET,
  64.       0,
  65.       NULL },

  66.     { ngx_string("server_name"),
  67.       NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
  68.       ngx_stream_core_server_name,
  69.       NGX_STREAM_SRV_CONF_OFFSET,
  70.       0,
  71.       NULL },

  72.     { ngx_string("error_log"),
  73.       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
  74.       ngx_stream_core_error_log,
  75.       NGX_STREAM_SRV_CONF_OFFSET,
  76.       0,
  77.       NULL },

  78.     { ngx_string("resolver"),
  79.       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
  80.       ngx_stream_core_resolver,
  81.       NGX_STREAM_SRV_CONF_OFFSET,
  82.       0,
  83.       NULL },

  84.     { ngx_string("resolver_timeout"),
  85.       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
  86.       ngx_conf_set_msec_slot,
  87.       NGX_STREAM_SRV_CONF_OFFSET,
  88.       offsetof(ngx_stream_core_srv_conf_t, resolver_timeout),
  89.       NULL },

  90.     { ngx_string("proxy_protocol_timeout"),
  91.       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
  92.       ngx_conf_set_msec_slot,
  93.       NGX_STREAM_SRV_CONF_OFFSET,
  94.       offsetof(ngx_stream_core_srv_conf_t, proxy_protocol_timeout),
  95.       NULL },

  96.     { ngx_string("tcp_nodelay"),
  97.       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
  98.       ngx_conf_set_flag_slot,
  99.       NGX_STREAM_SRV_CONF_OFFSET,
  100.       offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay),
  101.       NULL },

  102.     { ngx_string("preread_buffer_size"),
  103.       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
  104.       ngx_conf_set_size_slot,
  105.       NGX_STREAM_SRV_CONF_OFFSET,
  106.       offsetof(ngx_stream_core_srv_conf_t, preread_buffer_size),
  107.       NULL },

  108.     { ngx_string("preread_timeout"),
  109.       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
  110.       ngx_conf_set_msec_slot,
  111.       NGX_STREAM_SRV_CONF_OFFSET,
  112.       offsetof(ngx_stream_core_srv_conf_t, preread_timeout),
  113.       NULL },

  114.       ngx_null_command
  115. };


  116. static ngx_stream_module_t  ngx_stream_core_module_ctx = {
  117.     ngx_stream_core_preconfiguration,      /* preconfiguration */
  118.     NULL,                                  /* postconfiguration */

  119.     ngx_stream_core_create_main_conf,      /* create main configuration */
  120.     ngx_stream_core_init_main_conf,        /* init main configuration */

  121.     ngx_stream_core_create_srv_conf,       /* create server configuration */
  122.     ngx_stream_core_merge_srv_conf         /* merge server configuration */
  123. };


  124. ngx_module_t  ngx_stream_core_module = {
  125.     NGX_MODULE_V1,
  126.     &ngx_stream_core_module_ctx,           /* module context */
  127.     ngx_stream_core_commands,              /* module directives */
  128.     NGX_STREAM_MODULE,                     /* module type */
  129.     NULL,                                  /* init master */
  130.     NULL,                                  /* init module */
  131.     NULL,                                  /* init process */
  132.     NULL,                                  /* init thread */
  133.     NULL,                                  /* exit thread */
  134.     NULL,                                  /* exit process */
  135.     NULL,                                  /* exit master */
  136.     NGX_MODULE_V1_PADDING
  137. };


  138. void
  139. ngx_stream_core_run_phases(ngx_stream_session_t *s)
  140. {
  141.     ngx_int_t                     rc;
  142.     ngx_stream_phase_handler_t   *ph;
  143.     ngx_stream_core_main_conf_t  *cmcf;

  144.     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);

  145.     ph = cmcf->phase_engine.handlers;

  146.     while (ph[s->phase_handler].checker) {

  147.         rc = ph[s->phase_handler].checker(s, &ph[s->phase_handler]);

  148.         if (rc == NGX_OK) {
  149.             return;
  150.         }
  151.     }
  152. }


  153. ngx_int_t
  154. ngx_stream_core_generic_phase(ngx_stream_session_t *s,
  155.     ngx_stream_phase_handler_t *ph)
  156. {
  157.     ngx_int_t  rc;

  158.     /*
  159.      * generic phase checker,
  160.      * used by all phases, except for preread and content
  161.      */

  162.     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
  163.                    "generic phase: %ui", s->phase_handler);

  164.     rc = ph->handler(s);

  165.     if (rc == NGX_OK) {
  166.         s->phase_handler = ph->next;
  167.         return NGX_AGAIN;
  168.     }

  169.     if (rc == NGX_DECLINED) {
  170.         s->phase_handler++;
  171.         return NGX_AGAIN;
  172.     }

  173.     if (rc == NGX_AGAIN || rc == NGX_DONE) {
  174.         return NGX_OK;
  175.     }

  176.     if (rc == NGX_ERROR) {
  177.         rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
  178.     }

  179.     ngx_stream_finalize_session(s, rc);

  180.     return NGX_OK;
  181. }


  182. ngx_int_t
  183. ngx_stream_core_preread_phase(ngx_stream_session_t *s,
  184.     ngx_stream_phase_handler_t *ph)
  185. {
  186.     ngx_int_t                    rc;
  187.     ngx_connection_t            *c;
  188.     ngx_stream_core_srv_conf_t  *cscf;

  189.     c = s->connection;

  190.     c->log->action = "prereading client data";

  191.     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);

  192.     if (c->read->timedout) {
  193.         rc = NGX_STREAM_OK;
  194.         goto done;
  195.     }

  196.     if (!c->read->timer_set) {
  197.         rc = ph->handler(s);

  198.         if (rc != NGX_AGAIN) {
  199.             goto done;
  200.         }
  201.     }

  202.     if (c->buffer == NULL) {
  203.         c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
  204.         if (c->buffer == NULL) {
  205.             rc = NGX_ERROR;
  206.             goto done;
  207.         }
  208.     }

  209.     if (ngx_stream_preread_can_peek(c)) {
  210.         rc = ngx_stream_preread_peek(s, ph);

  211.     } else {
  212.         rc = ngx_stream_preread(s, ph);
  213.     }

  214. done:

  215.     if (rc == NGX_AGAIN) {
  216.         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  217.             ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  218.             return NGX_OK;
  219.         }

  220.         if (!c->read->timer_set) {
  221.             ngx_add_timer(c->read, cscf->preread_timeout);
  222.         }

  223.         c->read->handler = ngx_stream_session_handler;

  224.         return NGX_OK;
  225.     }

  226.     if (c->read->timer_set) {
  227.         ngx_del_timer(c->read);
  228.     }

  229.     if (rc == NGX_OK) {
  230.         s->phase_handler = ph->next;
  231.         return NGX_AGAIN;
  232.     }

  233.     if (rc == NGX_DECLINED) {
  234.         s->phase_handler++;
  235.         return NGX_AGAIN;
  236.     }

  237.     if (rc == NGX_DONE) {
  238.         return NGX_OK;
  239.     }

  240.     if (rc == NGX_ERROR) {
  241.         rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
  242.     }

  243.     ngx_stream_finalize_session(s, rc);

  244.     return NGX_OK;
  245. }


  246. static ngx_uint_t
  247. ngx_stream_preread_can_peek(ngx_connection_t *c)
  248. {
  249. #if (NGX_STREAM_SSL)
  250.     if (c->ssl) {
  251.         return 0;
  252.     }
  253. #endif

  254.     if ((ngx_event_flags & NGX_USE_CLEAR_EVENT) == 0) {
  255.         return 0;
  256.     }

  257. #if (NGX_HAVE_KQUEUE)
  258.     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  259.         return 1;
  260.     }
  261. #endif

  262. #if (NGX_HAVE_EPOLLRDHUP)
  263.     if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) {
  264.         return 1;
  265.     }
  266. #endif

  267.     return 0;
  268. }


  269. static ngx_int_t
  270. ngx_stream_preread_peek(ngx_stream_session_t *s, ngx_stream_phase_handler_t *ph)
  271. {
  272.     ssize_t            n;
  273.     ngx_int_t          rc;
  274.     ngx_err_t          err;
  275.     ngx_connection_t  *c;

  276.     c = s->connection;

  277.     n = recv(c->fd, (char *) c->buffer->last,
  278.              c->buffer->end - c->buffer->last, MSG_PEEK);

  279.     err = ngx_socket_errno;

  280.     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream recv(): %z", n);

  281.     if (n == -1) {
  282.         if (err == NGX_EAGAIN) {
  283.             c->read->ready = 0;
  284.             return NGX_AGAIN;
  285.         }

  286.         ngx_connection_error(c, err, "recv() failed");
  287.         return NGX_STREAM_OK;
  288.     }

  289.     if (n == 0) {
  290.         return NGX_STREAM_OK;
  291.     }

  292.     c->buffer->last += n;

  293.     rc = ph->handler(s);

  294.     if (rc != NGX_AGAIN) {
  295.         c->buffer->last = c->buffer->pos;
  296.         return rc;
  297.     }

  298.     if (c->buffer->last == c->buffer->end) {
  299.         ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
  300.         return NGX_STREAM_BAD_REQUEST;
  301.     }

  302.     if (c->read->pending_eof) {
  303.         return NGX_STREAM_OK;
  304.     }

  305.     c->buffer->last = c->buffer->pos;

  306.     return NGX_AGAIN;
  307. }


  308. static ngx_int_t
  309. ngx_stream_preread(ngx_stream_session_t *s, ngx_stream_phase_handler_t *ph)
  310. {
  311.     ssize_t            n;
  312.     ngx_int_t          rc;
  313.     ngx_connection_t  *c;

  314.     c = s->connection;

  315.     while (c->read->ready) {

  316.         n = c->recv(c, c->buffer->last, c->buffer->end - c->buffer->last);

  317.         if (n == NGX_AGAIN) {
  318.             return NGX_AGAIN;
  319.         }

  320.         if (n == NGX_ERROR || n == 0) {
  321.             return NGX_STREAM_OK;
  322.         }

  323.         c->buffer->last += n;

  324.         rc = ph->handler(s);

  325.         if (rc != NGX_AGAIN) {
  326.             return rc;
  327.         }

  328.         if (c->buffer->last == c->buffer->end) {
  329.             ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
  330.             return NGX_STREAM_BAD_REQUEST;
  331.         }
  332.     }

  333.     return NGX_AGAIN;
  334. }


  335. ngx_int_t
  336. ngx_stream_core_content_phase(ngx_stream_session_t *s,
  337.     ngx_stream_phase_handler_t *ph)
  338. {
  339.     ngx_connection_t            *c;
  340.     ngx_stream_core_srv_conf_t  *cscf;

  341.     c = s->connection;

  342.     c->log->action = NULL;

  343.     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);

  344.     if (c->type == SOCK_STREAM
  345.         && cscf->tcp_nodelay
  346.         && ngx_tcp_nodelay(c) != NGX_OK)
  347.     {
  348.         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  349.         return NGX_OK;
  350.     }

  351.     if (cscf->handler == NULL) {
  352.         ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
  353.                        "no handler for server");
  354.         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  355.         return NGX_OK;
  356.     }

  357.     cscf->handler(s);

  358.     return NGX_OK;
  359. }


  360. ngx_int_t
  361. ngx_stream_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
  362. {
  363.     u_char  *h, ch;
  364.     size_t   i, dot_pos, host_len;

  365.     enum {
  366.         sw_usual = 0,
  367.         sw_literal,
  368.         sw_rest
  369.     } state;

  370.     dot_pos = host->len;
  371.     host_len = host->len;

  372.     h = host->data;

  373.     state = sw_usual;

  374.     for (i = 0; i < host->len; i++) {
  375.         ch = h[i];

  376.         switch (ch) {

  377.         case '.':
  378.             if (dot_pos == i - 1) {
  379.                 return NGX_DECLINED;
  380.             }
  381.             dot_pos = i;
  382.             break;

  383.         case ':':
  384.             if (state == sw_usual) {
  385.                 host_len = i;
  386.                 state = sw_rest;
  387.             }
  388.             break;

  389.         case '[':
  390.             if (i == 0) {
  391.                 state = sw_literal;
  392.             }
  393.             break;

  394.         case ']':
  395.             if (state == sw_literal) {
  396.                 host_len = i + 1;
  397.                 state = sw_rest;
  398.             }
  399.             break;

  400.         default:

  401.             if (ngx_path_separator(ch)) {
  402.                 return NGX_DECLINED;
  403.             }

  404.             if (ch <= 0x20 || ch == 0x7f) {
  405.                 return NGX_DECLINED;
  406.             }

  407.             if (ch >= 'A' && ch <= 'Z') {
  408.                 alloc = 1;
  409.             }

  410.             break;
  411.         }
  412.     }

  413.     if (dot_pos == host_len - 1) {
  414.         host_len--;
  415.     }

  416.     if (host_len == 0) {
  417.         return NGX_DECLINED;
  418.     }

  419.     if (alloc) {
  420.         host->data = ngx_pnalloc(pool, host_len);
  421.         if (host->data == NULL) {
  422.             return NGX_ERROR;
  423.         }

  424.         ngx_strlow(host->data, h, host_len);
  425.     }

  426.     host->len = host_len;

  427.     return NGX_OK;
  428. }


  429. ngx_int_t
  430. ngx_stream_find_virtual_server(ngx_stream_session_t *s,
  431.     ngx_str_t *host, ngx_stream_core_srv_conf_t **cscfp)
  432. {
  433.     ngx_stream_core_srv_conf_t  *cscf;

  434.     if (s->virtual_names == NULL) {
  435.         return NGX_DECLINED;
  436.     }

  437.     cscf = ngx_hash_find_combined(&s->virtual_names->names,
  438.                                   ngx_hash_key(host->data, host->len),
  439.                                   host->data, host->len);

  440.     if (cscf) {
  441.         *cscfp = cscf;
  442.         return NGX_OK;
  443.     }

  444. #if (NGX_PCRE)

  445.     if (host->len && s->virtual_names->nregex) {
  446.         ngx_int_t                  n;
  447.         ngx_uint_t                 i;
  448.         ngx_stream_server_name_t  *sn;

  449.         sn = s->virtual_names->regex;

  450.         for (i = 0; i < s->virtual_names->nregex; i++) {

  451.             n = ngx_stream_regex_exec(s, sn[i].regex, host);

  452.             if (n == NGX_DECLINED) {
  453.                 continue;
  454.             }

  455.             if (n == NGX_OK) {
  456.                 *cscfp = sn[i].server;
  457.                 return NGX_OK;
  458.             }

  459.             return NGX_ERROR;
  460.         }
  461.     }

  462. #endif /* NGX_PCRE */

  463.     return NGX_DECLINED;
  464. }


  465. static ngx_int_t
  466. ngx_stream_core_preconfiguration(ngx_conf_t *cf)
  467. {
  468.     return ngx_stream_variables_add_core_vars(cf);
  469. }


  470. static void *
  471. ngx_stream_core_create_main_conf(ngx_conf_t *cf)
  472. {
  473.     ngx_stream_core_main_conf_t  *cmcf;

  474.     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_main_conf_t));
  475.     if (cmcf == NULL) {
  476.         return NULL;
  477.     }

  478.     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
  479.                        sizeof(ngx_stream_core_srv_conf_t *))
  480.         != NGX_OK)
  481.     {
  482.         return NULL;
  483.     }

  484.     cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
  485.     cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;

  486.     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
  487.     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;

  488.     return cmcf;
  489. }


  490. static char *
  491. ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf)
  492. {
  493.     ngx_stream_core_main_conf_t *cmcf = conf;

  494.     ngx_conf_init_uint_value(cmcf->server_names_hash_max_size, 512);
  495.     ngx_conf_init_uint_value(cmcf->server_names_hash_bucket_size,
  496.                              ngx_cacheline_size);

  497.     cmcf->server_names_hash_bucket_size =
  498.             ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);


  499.     ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
  500.     ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);

  501.     cmcf->variables_hash_bucket_size =
  502.                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);

  503.     if (cmcf->ncaptures) {
  504.         cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
  505.     }

  506.     return NGX_CONF_OK;
  507. }


  508. static void *
  509. ngx_stream_core_create_srv_conf(ngx_conf_t *cf)
  510. {
  511.     ngx_stream_core_srv_conf_t  *cscf;

  512.     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_srv_conf_t));
  513.     if (cscf == NULL) {
  514.         return NULL;
  515.     }

  516.     /*
  517.      * set by ngx_pcalloc():
  518.      *
  519.      *     cscf->handler = NULL;
  520.      *     cscf->error_log = NULL;
  521.      */

  522.     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
  523.                        sizeof(ngx_stream_server_name_t))
  524.         != NGX_OK)
  525.     {
  526.         return NULL;
  527.     }

  528.     cscf->file_name = cf->conf_file->file.name.data;
  529.     cscf->line = cf->conf_file->line;
  530.     cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
  531.     cscf->proxy_protocol_timeout = NGX_CONF_UNSET_MSEC;
  532.     cscf->tcp_nodelay = NGX_CONF_UNSET;
  533.     cscf->preread_buffer_size = NGX_CONF_UNSET_SIZE;
  534.     cscf->preread_timeout = NGX_CONF_UNSET_MSEC;

  535.     return cscf;
  536. }


  537. static char *
  538. ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
  539. {
  540.     ngx_stream_core_srv_conf_t *prev = parent;
  541.     ngx_stream_core_srv_conf_t *conf = child;

  542.     ngx_str_t                  name;
  543.     ngx_stream_server_name_t  *sn;

  544.     ngx_conf_merge_msec_value(conf->resolver_timeout,
  545.                               prev->resolver_timeout, 30000);

  546.     if (conf->resolver == NULL) {

  547.         if (prev->resolver == NULL) {

  548.             /*
  549.              * create dummy resolver in stream {} context
  550.              * to inherit it in all servers
  551.              */

  552.             prev->resolver = ngx_resolver_create(cf, NULL, 0);
  553.             if (prev->resolver == NULL) {
  554.                 return NGX_CONF_ERROR;
  555.             }
  556.         }

  557.         conf->resolver = prev->resolver;
  558.     }

  559.     if (conf->error_log == NULL) {
  560.         if (prev->error_log) {
  561.             conf->error_log = prev->error_log;
  562.         } else {
  563.             conf->error_log = &cf->cycle->new_log;
  564.         }
  565.     }

  566.     ngx_conf_merge_msec_value(conf->proxy_protocol_timeout,
  567.                               prev->proxy_protocol_timeout, 30000);

  568.     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);

  569.     ngx_conf_merge_size_value(conf->preread_buffer_size,
  570.                               prev->preread_buffer_size, 16384);

  571.     ngx_conf_merge_msec_value(conf->preread_timeout,
  572.                               prev->preread_timeout, 30000);

  573.     if (conf->server_names.nelts == 0) {
  574.         /* the array has 4 empty preallocated elements, so push cannot fail */
  575.         sn = ngx_array_push(&conf->server_names);
  576. #if (NGX_PCRE)
  577.         sn->regex = NULL;
  578. #endif
  579.         sn->server = conf;
  580.         ngx_str_set(&sn->name, "");
  581.     }

  582.     sn = conf->server_names.elts;
  583.     name = sn[0].name;

  584. #if (NGX_PCRE)
  585.     if (sn->regex) {
  586.         name.len++;
  587.         name.data--;
  588.     } else
  589. #endif

  590.     if (name.data[0] == '.') {
  591.         name.len--;
  592.         name.data++;
  593.     }

  594.     conf->server_name.len = name.len;
  595.     conf->server_name.data = ngx_pstrdup(cf->pool, &name);
  596.     if (conf->server_name.data == NULL) {
  597.         return NGX_CONF_ERROR;
  598.     }

  599.     return NGX_CONF_OK;
  600. }


  601. static char *
  602. ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  603. {
  604.     ngx_stream_core_srv_conf_t  *cscf = conf;

  605.     return ngx_log_set_log(cf, &cscf->error_log);
  606. }


  607. static char *
  608. ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  609. {
  610.     char                         *rv;
  611.     void                         *mconf;
  612.     ngx_uint_t                    m;
  613.     ngx_conf_t                    pcf;
  614.     ngx_stream_module_t          *module;
  615.     ngx_stream_conf_ctx_t        *ctx, *stream_ctx;
  616.     ngx_stream_core_srv_conf_t   *cscf, **cscfp;
  617.     ngx_stream_core_main_conf_t  *cmcf;

  618.     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t));
  619.     if (ctx == NULL) {
  620.         return NGX_CONF_ERROR;
  621.     }

  622.     stream_ctx = cf->ctx;
  623.     ctx->main_conf = stream_ctx->main_conf;

  624.     /* the server{}'s srv_conf */

  625.     ctx->srv_conf = ngx_pcalloc(cf->pool,
  626.                                 sizeof(void *) * ngx_stream_max_module);
  627.     if (ctx->srv_conf == NULL) {
  628.         return NGX_CONF_ERROR;
  629.     }

  630.     for (m = 0; cf->cycle->modules[m]; m++) {
  631.         if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
  632.             continue;
  633.         }

  634.         module = cf->cycle->modules[m]->ctx;

  635.         if (module->create_srv_conf) {
  636.             mconf = module->create_srv_conf(cf);
  637.             if (mconf == NULL) {
  638.                 return NGX_CONF_ERROR;
  639.             }

  640.             ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf;
  641.         }
  642.     }

  643.     /* the server configuration context */

  644.     cscf = ctx->srv_conf[ngx_stream_core_module.ctx_index];
  645.     cscf->ctx = ctx;

  646.     cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index];

  647.     cscfp = ngx_array_push(&cmcf->servers);
  648.     if (cscfp == NULL) {
  649.         return NGX_CONF_ERROR;
  650.     }

  651.     *cscfp = cscf;


  652.     /* parse inside server{} */

  653.     pcf = *cf;
  654.     cf->ctx = ctx;
  655.     cf->cmd_type = NGX_STREAM_SRV_CONF;

  656.     rv = ngx_conf_parse(cf, NULL);

  657.     *cf = pcf;

  658.     if (rv == NGX_CONF_OK && !cscf->listen) {
  659.         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  660.                       "no \"listen\" is defined for server in %s:%ui",
  661.                       cscf->file_name, cscf->line);
  662.         return NGX_CONF_ERROR;
  663.     }

  664.     return rv;
  665. }


  666. static char *
  667. ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  668. {
  669.     ngx_stream_core_srv_conf_t  *cscf = conf;

  670.     ngx_str_t                *value, size;
  671.     ngx_url_t                 u;
  672.     ngx_uint_t                n, i, backlog;
  673.     ngx_stream_listen_opt_t   lsopt;

  674.     cscf->listen = 1;

  675.     value = cf->args->elts;

  676.     ngx_memzero(&u, sizeof(ngx_url_t));

  677.     u.url = value[1];
  678.     u.listen = 1;

  679.     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
  680.         if (u.err) {
  681.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  682.                                "%s in \"%V\" of the \"listen\" directive",
  683.                                u.err, &u.url);
  684.         }

  685.         return NGX_CONF_ERROR;
  686.     }

  687.     ngx_memzero(&lsopt, sizeof(ngx_stream_listen_opt_t));

  688.     lsopt.backlog = NGX_LISTEN_BACKLOG;
  689.     lsopt.type = SOCK_STREAM;
  690.     lsopt.rcvbuf = -1;
  691.     lsopt.sndbuf = -1;
  692. #if (NGX_HAVE_SETFIB)
  693.     lsopt.setfib = -1;
  694. #endif
  695. #if (NGX_HAVE_TCP_FASTOPEN)
  696.     lsopt.fastopen = -1;
  697. #endif
  698. #if (NGX_HAVE_INET6)
  699.     lsopt.ipv6only = 1;
  700. #endif

  701.     backlog = 0;

  702.     for (i = 2; i < cf->args->nelts; i++) {

  703.         if (ngx_strcmp(value[i].data, "default_server") == 0) {
  704.             lsopt.default_server = 1;
  705.             continue;
  706.         }

  707. #if !(NGX_WIN32)
  708.         if (ngx_strcmp(value[i].data, "udp") == 0) {
  709.             lsopt.type = SOCK_DGRAM;
  710.             continue;
  711.         }
  712. #endif

  713.         if (ngx_strcmp(value[i].data, "bind") == 0) {
  714.             lsopt.set = 1;
  715.             lsopt.bind = 1;
  716.             continue;
  717.         }

  718. #if (NGX_HAVE_SETFIB)
  719.         if (ngx_strncmp(value[i].data, "setfib=", 7) == 0) {
  720.             lsopt.setfib = ngx_atoi(value[i].data + 7, value[i].len - 7);
  721.             lsopt.set = 1;
  722.             lsopt.bind = 1;

  723.             if (lsopt.setfib == NGX_ERROR) {
  724.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  725.                                    "invalid setfib \"%V\"", &value[i]);
  726.                 return NGX_CONF_ERROR;
  727.             }

  728.             continue;
  729.         }
  730. #endif

  731. #if (NGX_HAVE_TCP_FASTOPEN)
  732.         if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) {
  733.             lsopt.fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9);
  734.             lsopt.set = 1;
  735.             lsopt.bind = 1;

  736.             if (lsopt.fastopen == NGX_ERROR) {
  737.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  738.                                    "invalid fastopen \"%V\"", &value[i]);
  739.                 return NGX_CONF_ERROR;
  740.             }

  741.             continue;
  742.         }
  743. #endif

  744.         if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
  745.             lsopt.backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
  746.             lsopt.set = 1;
  747.             lsopt.bind = 1;

  748.             if (lsopt.backlog == NGX_ERROR || lsopt.backlog == 0) {
  749.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  750.                                    "invalid backlog \"%V\"", &value[i]);
  751.                 return NGX_CONF_ERROR;
  752.             }

  753.             backlog = 1;

  754.             continue;
  755.         }

  756.         if (ngx_strncmp(value[i].data, "rcvbuf=", 7) == 0) {
  757.             size.len = value[i].len - 7;
  758.             size.data = value[i].data + 7;

  759.             lsopt.rcvbuf = ngx_parse_size(&size);
  760.             lsopt.set = 1;
  761.             lsopt.bind = 1;

  762.             if (lsopt.rcvbuf == NGX_ERROR) {
  763.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  764.                                    "invalid rcvbuf \"%V\"", &value[i]);
  765.                 return NGX_CONF_ERROR;
  766.             }

  767.             continue;
  768.         }

  769.         if (ngx_strncmp(value[i].data, "sndbuf=", 7) == 0) {
  770.             size.len = value[i].len - 7;
  771.             size.data = value[i].data + 7;

  772.             lsopt.sndbuf = ngx_parse_size(&size);
  773.             lsopt.set = 1;
  774.             lsopt.bind = 1;

  775.             if (lsopt.sndbuf == NGX_ERROR) {
  776.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  777.                                    "invalid sndbuf \"%V\"", &value[i]);
  778.                 return NGX_CONF_ERROR;
  779.             }

  780.             continue;
  781.         }

  782.         if (ngx_strncmp(value[i].data, "accept_filter=", 14) == 0) {
  783. #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
  784.             lsopt.accept_filter = (char *) &value[i].data[14];
  785.             lsopt.set = 1;
  786.             lsopt.bind = 1;
  787. #else
  788.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  789.                                "accept filters \"%V\" are not supported "
  790.                                "on this platform, ignored",
  791.                                &value[i]);
  792. #endif
  793.             continue;
  794.         }

  795.         if (ngx_strcmp(value[i].data, "deferred") == 0) {
  796. #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
  797.             lsopt.deferred_accept = 1;
  798.             lsopt.set = 1;
  799.             lsopt.bind = 1;
  800. #else
  801.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  802.                                "the deferred accept is not supported "
  803.                                "on this platform, ignored");
  804. #endif
  805.             continue;
  806.         }

  807.         if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
  808. #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
  809.             if (ngx_strcmp(&value[i].data[10], "n") == 0) {
  810.                 lsopt.ipv6only = 1;

  811.             } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
  812.                 lsopt.ipv6only = 0;

  813.             } else {
  814.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  815.                                    "invalid ipv6only flags \"%s\"",
  816.                                    &value[i].data[9]);
  817.                 return NGX_CONF_ERROR;
  818.             }

  819.             lsopt.set = 1;
  820.             lsopt.bind = 1;

  821.             continue;
  822. #else
  823.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  824.                                "ipv6only is not supported "
  825.                                "on this platform");
  826.             return NGX_CONF_ERROR;
  827. #endif
  828.         }

  829.         if (ngx_strcmp(value[i].data, "reuseport") == 0) {
  830. #if (NGX_HAVE_REUSEPORT)
  831.             lsopt.reuseport = 1;
  832.             lsopt.set = 1;
  833.             lsopt.bind = 1;
  834. #else
  835.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  836.                                "reuseport is not supported "
  837.                                "on this platform, ignored");
  838. #endif
  839.             continue;
  840.         }

  841.         if (ngx_strcmp(value[i].data, "ssl") == 0) {
  842. #if (NGX_STREAM_SSL)
  843.             lsopt.ssl = 1;
  844.             continue;
  845. #else
  846.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  847.                                "the \"ssl\" parameter requires "
  848.                                "ngx_stream_ssl_module");
  849.             return NGX_CONF_ERROR;
  850. #endif
  851.         }

  852.         if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {

  853.             if (ngx_strcmp(&value[i].data[13], "on") == 0) {
  854.                 lsopt.so_keepalive = 1;

  855.             } else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
  856.                 lsopt.so_keepalive = 2;

  857.             } else {

  858. #if (NGX_HAVE_KEEPALIVE_TUNABLE)
  859.                 u_char     *p, *end;
  860.                 ngx_str_t   s;

  861.                 end = value[i].data + value[i].len;
  862.                 s.data = value[i].data + 13;

  863.                 p = ngx_strlchr(s.data, end, ':');
  864.                 if (p == NULL) {
  865.                     p = end;
  866.                 }

  867.                 if (p > s.data) {
  868.                     s.len = p - s.data;

  869.                     lsopt.tcp_keepidle = ngx_parse_time(&s, 1);
  870.                     if (lsopt.tcp_keepidle == (time_t) NGX_ERROR) {
  871.                         goto invalid_so_keepalive;
  872.                     }
  873.                 }

  874.                 s.data = (p < end) ? (p + 1) : end;

  875.                 p = ngx_strlchr(s.data, end, ':');
  876.                 if (p == NULL) {
  877.                     p = end;
  878.                 }

  879.                 if (p > s.data) {
  880.                     s.len = p - s.data;

  881.                     lsopt.tcp_keepintvl = ngx_parse_time(&s, 1);
  882.                     if (lsopt.tcp_keepintvl == (time_t) NGX_ERROR) {
  883.                         goto invalid_so_keepalive;
  884.                     }
  885.                 }

  886.                 s.data = (p < end) ? (p + 1) : end;

  887.                 if (s.data < end) {
  888.                     s.len = end - s.data;

  889.                     lsopt.tcp_keepcnt = ngx_atoi(s.data, s.len);
  890.                     if (lsopt.tcp_keepcnt == NGX_ERROR) {
  891.                         goto invalid_so_keepalive;
  892.                     }
  893.                 }

  894.                 if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0
  895.                     && lsopt.tcp_keepcnt == 0)
  896.                 {
  897.                     goto invalid_so_keepalive;
  898.                 }

  899.                 lsopt.so_keepalive = 1;

  900. #else

  901.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  902.                                    "the \"so_keepalive\" parameter accepts "
  903.                                    "only \"on\" or \"off\" on this platform");
  904.                 return NGX_CONF_ERROR;

  905. #endif
  906.             }

  907.             lsopt.set = 1;
  908.             lsopt.bind = 1;

  909.             continue;

  910. #if (NGX_HAVE_KEEPALIVE_TUNABLE)
  911.         invalid_so_keepalive:

  912.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  913.                                "invalid so_keepalive value: \"%s\"",
  914.                                &value[i].data[13]);
  915.             return NGX_CONF_ERROR;
  916. #endif
  917.         }

  918.         if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
  919.             lsopt.proxy_protocol = 1;
  920.             continue;
  921.         }

  922.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  923.                            "invalid parameter \"%V\"", &value[i]);
  924.         return NGX_CONF_ERROR;
  925.     }

  926.     if (lsopt.type == SOCK_DGRAM) {
  927. #if (NGX_HAVE_TCP_FASTOPEN)
  928.         if (lsopt.fastopen != -1) {
  929.             return "\"fastopen\" parameter is incompatible with \"udp\"";
  930.         }
  931. #endif

  932.         if (backlog) {
  933.             return "\"backlog\" parameter is incompatible with \"udp\"";
  934.         }

  935. #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
  936.         if (lsopt.accept_filter) {
  937.             return "\"accept_filter\" parameter is incompatible with \"udp\"";
  938.         }
  939. #endif

  940. #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
  941.         if (lsopt.deferred_accept) {
  942.             return "\"deferred\" parameter is incompatible with \"udp\"";
  943.         }
  944. #endif

  945. #if (NGX_STREAM_SSL)
  946.         if (lsopt.ssl) {
  947.             return "\"ssl\" parameter is incompatible with \"udp\"";
  948.         }
  949. #endif

  950.         if (lsopt.so_keepalive) {
  951.             return "\"so_keepalive\" parameter is incompatible with \"udp\"";
  952.         }

  953.         if (lsopt.proxy_protocol) {
  954.             return "\"proxy_protocol\" parameter is incompatible with \"udp\"";
  955.         }
  956.     }

  957.     for (n = 0; n < u.naddrs; n++) {

  958.         for (i = 0; i < n; i++) {
  959.             if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
  960.                                  u.addrs[i].sockaddr, u.addrs[i].socklen, 1)
  961.                 == NGX_OK)
  962.             {
  963.                 goto next;
  964.             }
  965.         }

  966.         lsopt.sockaddr = u.addrs[n].sockaddr;
  967.         lsopt.socklen = u.addrs[n].socklen;
  968.         lsopt.addr_text = u.addrs[n].name;
  969.         lsopt.wildcard = ngx_inet_wildcard(lsopt.sockaddr);

  970.         if (ngx_stream_add_listen(cf, cscf, &lsopt) != NGX_OK) {
  971.             return NGX_CONF_ERROR;
  972.         }

  973.     next:
  974.         continue;
  975.     }

  976.     return NGX_CONF_OK;
  977. }


  978. static char *
  979. ngx_stream_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  980. {
  981.     ngx_stream_core_srv_conf_t *cscf = conf;

  982.     u_char                     ch;
  983.     ngx_str_t                 *value;
  984.     ngx_uint_t                 i;
  985.     ngx_stream_server_name_t  *sn;

  986.     value = cf->args->elts;

  987.     for (i = 1; i < cf->args->nelts; i++) {

  988.         ch = value[i].data[0];

  989.         if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
  990.             || (ch == '.' && value[i].len < 2))
  991.         {
  992.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  993.                                "server name \"%V\" is invalid", &value[i]);
  994.             return NGX_CONF_ERROR;
  995.         }

  996.         if (ngx_strchr(value[i].data, '/')) {
  997.             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  998.                                "server name \"%V\" has suspicious symbols",
  999.                                &value[i]);
  1000.         }

  1001.         sn = ngx_array_push(&cscf->server_names);
  1002.         if (sn == NULL) {
  1003.             return NGX_CONF_ERROR;
  1004.         }

  1005. #if (NGX_PCRE)
  1006.         sn->regex = NULL;
  1007. #endif
  1008.         sn->server = cscf;

  1009.         if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) {
  1010.             sn->name = cf->cycle->hostname;

  1011.         } else {
  1012.             sn->name = value[i];
  1013.         }

  1014.         if (value[i].data[0] != '~') {
  1015.             ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
  1016.             continue;
  1017.         }

  1018. #if (NGX_PCRE)
  1019.         {
  1020.         u_char               *p;
  1021.         ngx_regex_compile_t   rc;
  1022.         u_char                errstr[NGX_MAX_CONF_ERRSTR];

  1023.         if (value[i].len == 1) {
  1024.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1025.                                "empty regex in server name \"%V\"", &value[i]);
  1026.             return NGX_CONF_ERROR;
  1027.         }

  1028.         value[i].len--;
  1029.         value[i].data++;

  1030.         ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

  1031.         rc.pattern = value[i];
  1032.         rc.err.len = NGX_MAX_CONF_ERRSTR;
  1033.         rc.err.data = errstr;

  1034.         for (p = value[i].data; p < value[i].data + value[i].len; p++) {
  1035.             if (*p >= 'A' && *p <= 'Z') {
  1036.                 rc.options = NGX_REGEX_CASELESS;
  1037.                 break;
  1038.             }
  1039.         }

  1040.         sn->regex = ngx_stream_regex_compile(cf, &rc);
  1041.         if (sn->regex == NULL) {
  1042.             return NGX_CONF_ERROR;
  1043.         }

  1044.         sn->name = value[i];
  1045.         cscf->captures = (rc.captures > 0);
  1046.         }
  1047. #else
  1048.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1049.                            "using regex \"%V\" "
  1050.                            "requires PCRE library", &value[i]);

  1051.         return NGX_CONF_ERROR;
  1052. #endif
  1053.     }

  1054.     return NGX_CONF_OK;
  1055. }


  1056. static char *
  1057. ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1058. {
  1059.     ngx_stream_core_srv_conf_t  *cscf = conf;

  1060.     ngx_str_t  *value;

  1061.     if (cscf->resolver) {
  1062.         return "is duplicate";
  1063.     }

  1064.     value = cf->args->elts;

  1065.     cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
  1066.     if (cscf->resolver == NULL) {
  1067.         return NGX_CONF_ERROR;
  1068.     }

  1069.     return NGX_CONF_OK;
  1070. }