1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Roman Arutyunyan
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_stream.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_stream_core_preconfiguration(ngx_conf_t *cf);
14e18a033bSKonstantin Ananyevstatic void *ngx_stream_core_create_main_conf(ngx_conf_t *cf);
15e18a033bSKonstantin Ananyevstatic char *ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf);
16e18a033bSKonstantin Ananyevstatic void *ngx_stream_core_create_srv_conf(ngx_conf_t *cf);
17e18a033bSKonstantin Ananyevstatic char *ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent,
18e18a033bSKonstantin Ananyev    void *child);
19e18a033bSKonstantin Ananyevstatic char *ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
20e18a033bSKonstantin Ananyev    void *conf);
21e18a033bSKonstantin Ananyevstatic char *ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
22e18a033bSKonstantin Ananyev    void *conf);
23e18a033bSKonstantin Ananyevstatic char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
24e18a033bSKonstantin Ananyev    void *conf);
25e18a033bSKonstantin Ananyevstatic char *ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
26e18a033bSKonstantin Ananyev    void *conf);
27e18a033bSKonstantin Ananyev
28e18a033bSKonstantin Ananyev
29e18a033bSKonstantin Ananyevstatic ngx_command_t  ngx_stream_core_commands[] = {
30e18a033bSKonstantin Ananyev
31e18a033bSKonstantin Ananyev    { ngx_string("variables_hash_max_size"),
32e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
33e18a033bSKonstantin Ananyev      ngx_conf_set_num_slot,
34e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF_OFFSET,
35e18a033bSKonstantin Ananyev      offsetof(ngx_stream_core_main_conf_t, variables_hash_max_size),
36e18a033bSKonstantin Ananyev      NULL },
37e18a033bSKonstantin Ananyev
38e18a033bSKonstantin Ananyev    { ngx_string("variables_hash_bucket_size"),
39e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
40e18a033bSKonstantin Ananyev      ngx_conf_set_num_slot,
41e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF_OFFSET,
42e18a033bSKonstantin Ananyev      offsetof(ngx_stream_core_main_conf_t, variables_hash_bucket_size),
43e18a033bSKonstantin Ananyev      NULL },
44e18a033bSKonstantin Ananyev
45e18a033bSKonstantin Ananyev    { ngx_string("server"),
46e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
47e18a033bSKonstantin Ananyev      ngx_stream_core_server,
48e18a033bSKonstantin Ananyev      0,
49e18a033bSKonstantin Ananyev      0,
50e18a033bSKonstantin Ananyev      NULL },
51e18a033bSKonstantin Ananyev
52e18a033bSKonstantin Ananyev    { ngx_string("listen"),
53e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
54e18a033bSKonstantin Ananyev      ngx_stream_core_listen,
55e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF_OFFSET,
56e18a033bSKonstantin Ananyev      0,
57e18a033bSKonstantin Ananyev      NULL },
58e18a033bSKonstantin Ananyev
59e18a033bSKonstantin Ananyev    { ngx_string("error_log"),
60e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
61e18a033bSKonstantin Ananyev      ngx_stream_core_error_log,
62e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF_OFFSET,
63e18a033bSKonstantin Ananyev      0,
64e18a033bSKonstantin Ananyev      NULL },
65e18a033bSKonstantin Ananyev
66e18a033bSKonstantin Ananyev    { ngx_string("resolver"),
67e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
68e18a033bSKonstantin Ananyev      ngx_stream_core_resolver,
69e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF_OFFSET,
70e18a033bSKonstantin Ananyev      0,
71e18a033bSKonstantin Ananyev      NULL },
72e18a033bSKonstantin Ananyev
73e18a033bSKonstantin Ananyev    { ngx_string("resolver_timeout"),
74e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
75e18a033bSKonstantin Ananyev      ngx_conf_set_msec_slot,
76e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF_OFFSET,
77e18a033bSKonstantin Ananyev      offsetof(ngx_stream_core_srv_conf_t, resolver_timeout),
78e18a033bSKonstantin Ananyev      NULL },
79e18a033bSKonstantin Ananyev
80e18a033bSKonstantin Ananyev    { ngx_string("proxy_protocol_timeout"),
81e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
82e18a033bSKonstantin Ananyev      ngx_conf_set_msec_slot,
83e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF_OFFSET,
84e18a033bSKonstantin Ananyev      offsetof(ngx_stream_core_srv_conf_t, proxy_protocol_timeout),
85e18a033bSKonstantin Ananyev      NULL },
86e18a033bSKonstantin Ananyev
87e18a033bSKonstantin Ananyev    { ngx_string("tcp_nodelay"),
88e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
89e18a033bSKonstantin Ananyev      ngx_conf_set_flag_slot,
90e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF_OFFSET,
91e18a033bSKonstantin Ananyev      offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay),
92e18a033bSKonstantin Ananyev      NULL },
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyev    { ngx_string("preread_buffer_size"),
95e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
96e18a033bSKonstantin Ananyev      ngx_conf_set_size_slot,
97e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF_OFFSET,
98e18a033bSKonstantin Ananyev      offsetof(ngx_stream_core_srv_conf_t, preread_buffer_size),
99e18a033bSKonstantin Ananyev      NULL },
100e18a033bSKonstantin Ananyev
101e18a033bSKonstantin Ananyev    { ngx_string("preread_timeout"),
102e18a033bSKonstantin Ananyev      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
103e18a033bSKonstantin Ananyev      ngx_conf_set_msec_slot,
104e18a033bSKonstantin Ananyev      NGX_STREAM_SRV_CONF_OFFSET,
105e18a033bSKonstantin Ananyev      offsetof(ngx_stream_core_srv_conf_t, preread_timeout),
106e18a033bSKonstantin Ananyev      NULL },
107e18a033bSKonstantin Ananyev
108e18a033bSKonstantin Ananyev      ngx_null_command
109e18a033bSKonstantin Ananyev};
110e18a033bSKonstantin Ananyev
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyevstatic ngx_stream_module_t  ngx_stream_core_module_ctx = {
113e18a033bSKonstantin Ananyev    ngx_stream_core_preconfiguration,      /* preconfiguration */
114e18a033bSKonstantin Ananyev    NULL,                                  /* postconfiguration */
115e18a033bSKonstantin Ananyev
116e18a033bSKonstantin Ananyev    ngx_stream_core_create_main_conf,      /* create main configuration */
117e18a033bSKonstantin Ananyev    ngx_stream_core_init_main_conf,        /* init main configuration */
118e18a033bSKonstantin Ananyev
119e18a033bSKonstantin Ananyev    ngx_stream_core_create_srv_conf,       /* create server configuration */
120e18a033bSKonstantin Ananyev    ngx_stream_core_merge_srv_conf         /* merge server configuration */
121e18a033bSKonstantin Ananyev};
122e18a033bSKonstantin Ananyev
123e18a033bSKonstantin Ananyev
124e18a033bSKonstantin Ananyevngx_module_t  ngx_stream_core_module = {
125e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
126e18a033bSKonstantin Ananyev    &ngx_stream_core_module_ctx,           /* module context */
127e18a033bSKonstantin Ananyev    ngx_stream_core_commands,              /* module directives */
128e18a033bSKonstantin Ananyev    NGX_STREAM_MODULE,                     /* module type */
129e18a033bSKonstantin Ananyev    NULL,                                  /* init master */
130e18a033bSKonstantin Ananyev    NULL,                                  /* init module */
131e18a033bSKonstantin Ananyev    NULL,                                  /* init process */
132e18a033bSKonstantin Ananyev    NULL,                                  /* init thread */
133e18a033bSKonstantin Ananyev    NULL,                                  /* exit thread */
134e18a033bSKonstantin Ananyev    NULL,                                  /* exit process */
135e18a033bSKonstantin Ananyev    NULL,                                  /* exit master */
136e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
137e18a033bSKonstantin Ananyev};
138e18a033bSKonstantin Ananyev
139e18a033bSKonstantin Ananyev
140e18a033bSKonstantin Ananyevvoid
141e18a033bSKonstantin Ananyevngx_stream_core_run_phases(ngx_stream_session_t *s)
142e18a033bSKonstantin Ananyev{
143e18a033bSKonstantin Ananyev    ngx_int_t                     rc;
144e18a033bSKonstantin Ananyev    ngx_stream_phase_handler_t   *ph;
145e18a033bSKonstantin Ananyev    ngx_stream_core_main_conf_t  *cmcf;
146e18a033bSKonstantin Ananyev
147e18a033bSKonstantin Ananyev    cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
148e18a033bSKonstantin Ananyev
149e18a033bSKonstantin Ananyev    ph = cmcf->phase_engine.handlers;
150e18a033bSKonstantin Ananyev
151e18a033bSKonstantin Ananyev    while (ph[s->phase_handler].checker) {
152e18a033bSKonstantin Ananyev
153e18a033bSKonstantin Ananyev        rc = ph[s->phase_handler].checker(s, &ph[s->phase_handler]);
154e18a033bSKonstantin Ananyev
155e18a033bSKonstantin Ananyev        if (rc == NGX_OK) {
156e18a033bSKonstantin Ananyev            return;
157e18a033bSKonstantin Ananyev        }
158e18a033bSKonstantin Ananyev    }
159e18a033bSKonstantin Ananyev}
160e18a033bSKonstantin Ananyev
161e18a033bSKonstantin Ananyev
162e18a033bSKonstantin Ananyevngx_int_t
163e18a033bSKonstantin Ananyevngx_stream_core_generic_phase(ngx_stream_session_t *s,
164e18a033bSKonstantin Ananyev    ngx_stream_phase_handler_t *ph)
165e18a033bSKonstantin Ananyev{
166e18a033bSKonstantin Ananyev    ngx_int_t  rc;
167e18a033bSKonstantin Ananyev
168e18a033bSKonstantin Ananyev    /*
169e18a033bSKonstantin Ananyev     * generic phase checker,
170e18a033bSKonstantin Ananyev     * used by all phases, except for preread and content
171e18a033bSKonstantin Ananyev     */
172e18a033bSKonstantin Ananyev
173e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
174e18a033bSKonstantin Ananyev                   "generic phase: %ui", s->phase_handler);
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev    rc = ph->handler(s);
177e18a033bSKonstantin Ananyev
178e18a033bSKonstantin Ananyev    if (rc == NGX_OK) {
179e18a033bSKonstantin Ananyev        s->phase_handler = ph->next;
180e18a033bSKonstantin Ananyev        return NGX_AGAIN;
181e18a033bSKonstantin Ananyev    }
182e18a033bSKonstantin Ananyev
183e18a033bSKonstantin Ananyev    if (rc == NGX_DECLINED) {
184e18a033bSKonstantin Ananyev        s->phase_handler++;
185e18a033bSKonstantin Ananyev        return NGX_AGAIN;
186e18a033bSKonstantin Ananyev    }
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev    if (rc == NGX_AGAIN || rc == NGX_DONE) {
189e18a033bSKonstantin Ananyev        return NGX_OK;
190e18a033bSKonstantin Ananyev    }
191e18a033bSKonstantin Ananyev
192e18a033bSKonstantin Ananyev    if (rc == NGX_ERROR) {
193e18a033bSKonstantin Ananyev        rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
194e18a033bSKonstantin Ananyev    }
195e18a033bSKonstantin Ananyev
196e18a033bSKonstantin Ananyev    ngx_stream_finalize_session(s, rc);
197e18a033bSKonstantin Ananyev
198e18a033bSKonstantin Ananyev    return NGX_OK;
199e18a033bSKonstantin Ananyev}
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyev
202e18a033bSKonstantin Ananyevngx_int_t
203e18a033bSKonstantin Ananyevngx_stream_core_preread_phase(ngx_stream_session_t *s,
204e18a033bSKonstantin Ananyev    ngx_stream_phase_handler_t *ph)
205e18a033bSKonstantin Ananyev{
206e18a033bSKonstantin Ananyev    size_t                       size;
207e18a033bSKonstantin Ananyev    ssize_t                      n;
208e18a033bSKonstantin Ananyev    ngx_int_t                    rc;
209e18a033bSKonstantin Ananyev    ngx_connection_t            *c;
210e18a033bSKonstantin Ananyev    ngx_stream_core_srv_conf_t  *cscf;
211e18a033bSKonstantin Ananyev
212e18a033bSKonstantin Ananyev    c = s->connection;
213e18a033bSKonstantin Ananyev
214e18a033bSKonstantin Ananyev    c->log->action = "prereading client data";
215e18a033bSKonstantin Ananyev
216e18a033bSKonstantin Ananyev    cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
217e18a033bSKonstantin Ananyev
218e18a033bSKonstantin Ananyev    if (c->read->timedout) {
219e18a033bSKonstantin Ananyev        rc = NGX_STREAM_OK;
220e18a033bSKonstantin Ananyev
221e18a033bSKonstantin Ananyev    } else if (c->read->timer_set) {
222e18a033bSKonstantin Ananyev        rc = NGX_AGAIN;
223e18a033bSKonstantin Ananyev
224e18a033bSKonstantin Ananyev    } else {
225e18a033bSKonstantin Ananyev        rc = ph->handler(s);
226e18a033bSKonstantin Ananyev    }
227e18a033bSKonstantin Ananyev
228e18a033bSKonstantin Ananyev    while (rc == NGX_AGAIN) {
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev        if (c->buffer == NULL) {
231e18a033bSKonstantin Ananyev            c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
232e18a033bSKonstantin Ananyev            if (c->buffer == NULL) {
233e18a033bSKonstantin Ananyev                rc = NGX_ERROR;
234e18a033bSKonstantin Ananyev                break;
235e18a033bSKonstantin Ananyev            }
236e18a033bSKonstantin Ananyev        }
237e18a033bSKonstantin Ananyev
238e18a033bSKonstantin Ananyev        size = c->buffer->end - c->buffer->last;
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev        if (size == 0) {
241e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
242e18a033bSKonstantin Ananyev            rc = NGX_STREAM_BAD_REQUEST;
243e18a033bSKonstantin Ananyev            break;
244e18a033bSKonstantin Ananyev        }
245e18a033bSKonstantin Ananyev
246e18a033bSKonstantin Ananyev        if (c->read->eof) {
247e18a033bSKonstantin Ananyev            rc = NGX_STREAM_OK;
248e18a033bSKonstantin Ananyev            break;
249e18a033bSKonstantin Ananyev        }
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyev        if (!c->read->ready) {
252e18a033bSKonstantin Ananyev            if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
253e18a033bSKonstantin Ananyev                rc = NGX_ERROR;
254e18a033bSKonstantin Ananyev                break;
255e18a033bSKonstantin Ananyev            }
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev            if (!c->read->timer_set) {
258e18a033bSKonstantin Ananyev                ngx_add_timer(c->read, cscf->preread_timeout);
259e18a033bSKonstantin Ananyev            }
260e18a033bSKonstantin Ananyev
261e18a033bSKonstantin Ananyev            c->read->handler = ngx_stream_session_handler;
262e18a033bSKonstantin Ananyev
263e18a033bSKonstantin Ananyev            return NGX_OK;
264e18a033bSKonstantin Ananyev        }
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev        n = c->recv(c, c->buffer->last, size);
267e18a033bSKonstantin Ananyev
268e18a033bSKonstantin Ananyev        if (n == NGX_ERROR) {
269e18a033bSKonstantin Ananyev            rc = NGX_STREAM_OK;
270e18a033bSKonstantin Ananyev            break;
271e18a033bSKonstantin Ananyev        }
272e18a033bSKonstantin Ananyev
273e18a033bSKonstantin Ananyev        if (n > 0) {
274e18a033bSKonstantin Ananyev            c->buffer->last += n;
275e18a033bSKonstantin Ananyev        }
276e18a033bSKonstantin Ananyev
277e18a033bSKonstantin Ananyev        rc = ph->handler(s);
278e18a033bSKonstantin Ananyev    }
279e18a033bSKonstantin Ananyev
280e18a033bSKonstantin Ananyev    if (c->read->timer_set) {
281e18a033bSKonstantin Ananyev        ngx_del_timer(c->read);
282e18a033bSKonstantin Ananyev    }
283e18a033bSKonstantin Ananyev
284e18a033bSKonstantin Ananyev    if (rc == NGX_OK) {
285e18a033bSKonstantin Ananyev        s->phase_handler = ph->next;
286e18a033bSKonstantin Ananyev        return NGX_AGAIN;
287e18a033bSKonstantin Ananyev    }
288e18a033bSKonstantin Ananyev
289e18a033bSKonstantin Ananyev    if (rc == NGX_DECLINED) {
290e18a033bSKonstantin Ananyev        s->phase_handler++;
291e18a033bSKonstantin Ananyev        return NGX_AGAIN;
292e18a033bSKonstantin Ananyev    }
293e18a033bSKonstantin Ananyev
294e18a033bSKonstantin Ananyev    if (rc == NGX_DONE) {
295e18a033bSKonstantin Ananyev        return NGX_OK;
296e18a033bSKonstantin Ananyev    }
297e18a033bSKonstantin Ananyev
298e18a033bSKonstantin Ananyev    if (rc == NGX_ERROR) {
299e18a033bSKonstantin Ananyev        rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
300e18a033bSKonstantin Ananyev    }
301e18a033bSKonstantin Ananyev
302e18a033bSKonstantin Ananyev    ngx_stream_finalize_session(s, rc);
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev    return NGX_OK;
305e18a033bSKonstantin Ananyev}
306e18a033bSKonstantin Ananyev
307e18a033bSKonstantin Ananyev
308e18a033bSKonstantin Ananyevngx_int_t
309e18a033bSKonstantin Ananyevngx_stream_core_content_phase(ngx_stream_session_t *s,
310e18a033bSKonstantin Ananyev    ngx_stream_phase_handler_t *ph)
311e18a033bSKonstantin Ananyev{
312e18a033bSKonstantin Ananyev    int                          tcp_nodelay;
313e18a033bSKonstantin Ananyev    ngx_connection_t            *c;
314e18a033bSKonstantin Ananyev    ngx_stream_core_srv_conf_t  *cscf;
315e18a033bSKonstantin Ananyev
316e18a033bSKonstantin Ananyev    c = s->connection;
317e18a033bSKonstantin Ananyev
318e18a033bSKonstantin Ananyev    c->log->action = NULL;
319e18a033bSKonstantin Ananyev
320e18a033bSKonstantin Ananyev    cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
321e18a033bSKonstantin Ananyev
322e18a033bSKonstantin Ananyev    if (c->type == SOCK_STREAM
323e18a033bSKonstantin Ananyev        && cscf->tcp_nodelay
324e18a033bSKonstantin Ananyev        && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
325e18a033bSKonstantin Ananyev    {
326e18a033bSKonstantin Ananyev        ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay");
327e18a033bSKonstantin Ananyev
328e18a033bSKonstantin Ananyev        tcp_nodelay = 1;
329e18a033bSKonstantin Ananyev
330e18a033bSKonstantin Ananyev        if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
331e18a033bSKonstantin Ananyev                       (const void *) &tcp_nodelay, sizeof(int)) == -1)
332e18a033bSKonstantin Ananyev        {
333e18a033bSKonstantin Ananyev            ngx_connection_error(c, ngx_socket_errno,
334e18a033bSKonstantin Ananyev                                 "setsockopt(TCP_NODELAY) failed");
335e18a033bSKonstantin Ananyev            ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
336e18a033bSKonstantin Ananyev            return NGX_OK;
337e18a033bSKonstantin Ananyev        }
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev        c->tcp_nodelay = NGX_TCP_NODELAY_SET;
340e18a033bSKonstantin Ananyev    }
341e18a033bSKonstantin Ananyev
342e18a033bSKonstantin Ananyev    cscf->handler(s);
343e18a033bSKonstantin Ananyev
344e18a033bSKonstantin Ananyev    return NGX_OK;
345e18a033bSKonstantin Ananyev}
346e18a033bSKonstantin Ananyev
347e18a033bSKonstantin Ananyev
348e18a033bSKonstantin Ananyevstatic ngx_int_t
349e18a033bSKonstantin Ananyevngx_stream_core_preconfiguration(ngx_conf_t *cf)
350e18a033bSKonstantin Ananyev{
351e18a033bSKonstantin Ananyev    return ngx_stream_variables_add_core_vars(cf);
352e18a033bSKonstantin Ananyev}
353e18a033bSKonstantin Ananyev
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyevstatic void *
356e18a033bSKonstantin Ananyevngx_stream_core_create_main_conf(ngx_conf_t *cf)
357e18a033bSKonstantin Ananyev{
358e18a033bSKonstantin Ananyev    ngx_stream_core_main_conf_t  *cmcf;
359e18a033bSKonstantin Ananyev
360e18a033bSKonstantin Ananyev    cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_main_conf_t));
361e18a033bSKonstantin Ananyev    if (cmcf == NULL) {
362e18a033bSKonstantin Ananyev        return NULL;
363e18a033bSKonstantin Ananyev    }
364e18a033bSKonstantin Ananyev
365e18a033bSKonstantin Ananyev    if (ngx_array_init(&cmcf->servers, cf->pool, 4,
366e18a033bSKonstantin Ananyev                       sizeof(ngx_stream_core_srv_conf_t *))
367e18a033bSKonstantin Ananyev        != NGX_OK)
368e18a033bSKonstantin Ananyev    {
369e18a033bSKonstantin Ananyev        return NULL;
370e18a033bSKonstantin Ananyev    }
371e18a033bSKonstantin Ananyev
372e18a033bSKonstantin Ananyev    if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_stream_listen_t))
373e18a033bSKonstantin Ananyev        != NGX_OK)
374e18a033bSKonstantin Ananyev    {
375e18a033bSKonstantin Ananyev        return NULL;
376e18a033bSKonstantin Ananyev    }
377e18a033bSKonstantin Ananyev
378e18a033bSKonstantin Ananyev    cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
379e18a033bSKonstantin Ananyev    cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
380e18a033bSKonstantin Ananyev
381e18a033bSKonstantin Ananyev    return cmcf;
382e18a033bSKonstantin Ananyev}
383e18a033bSKonstantin Ananyev
384e18a033bSKonstantin Ananyev
385e18a033bSKonstantin Ananyevstatic char *
386e18a033bSKonstantin Ananyevngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf)
387e18a033bSKonstantin Ananyev{
388e18a033bSKonstantin Ananyev    ngx_stream_core_main_conf_t *cmcf = conf;
389e18a033bSKonstantin Ananyev
390e18a033bSKonstantin Ananyev    ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
391e18a033bSKonstantin Ananyev    ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
392e18a033bSKonstantin Ananyev
393e18a033bSKonstantin Ananyev    cmcf->variables_hash_bucket_size =
394e18a033bSKonstantin Ananyev               ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
395e18a033bSKonstantin Ananyev
396e18a033bSKonstantin Ananyev    if (cmcf->ncaptures) {
397e18a033bSKonstantin Ananyev        cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
398e18a033bSKonstantin Ananyev    }
399e18a033bSKonstantin Ananyev
400e18a033bSKonstantin Ananyev    return NGX_CONF_OK;
401e18a033bSKonstantin Ananyev}
402e18a033bSKonstantin Ananyev
403e18a033bSKonstantin Ananyev
404e18a033bSKonstantin Ananyevstatic void *
405e18a033bSKonstantin Ananyevngx_stream_core_create_srv_conf(ngx_conf_t *cf)
406e18a033bSKonstantin Ananyev{
407e18a033bSKonstantin Ananyev    ngx_stream_core_srv_conf_t  *cscf;
408e18a033bSKonstantin Ananyev
409e18a033bSKonstantin Ananyev    cscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_srv_conf_t));
410e18a033bSKonstantin Ananyev    if (cscf == NULL) {
411e18a033bSKonstantin Ananyev        return NULL;
412e18a033bSKonstantin Ananyev    }
413e18a033bSKonstantin Ananyev
414e18a033bSKonstantin Ananyev    /*
415e18a033bSKonstantin Ananyev     * set by ngx_pcalloc():
416e18a033bSKonstantin Ananyev     *
417e18a033bSKonstantin Ananyev     *     cscf->handler = NULL;
418e18a033bSKonstantin Ananyev     *     cscf->error_log = NULL;
419