Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Roman Arutyunyan
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 #include <ngx_stream.h>
0012 
0013 
0014 static void ngx_stream_log_session(ngx_stream_session_t *s);
0015 static void ngx_stream_close_connection(ngx_connection_t *c);
0016 static u_char *ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len);
0017 static void ngx_stream_proxy_protocol_handler(ngx_event_t *rev);
0018 
0019 
0020 void
0021 ngx_stream_init_connection(ngx_connection_t *c)
0022 {
0023     u_char                        text[NGX_SOCKADDR_STRLEN];
0024     size_t                        len;
0025     ngx_uint_t                    i;
0026     ngx_time_t                   *tp;
0027     ngx_event_t                  *rev;
0028     struct sockaddr              *sa;
0029     ngx_stream_port_t            *port;
0030     struct sockaddr_in           *sin;
0031     ngx_stream_in_addr_t         *addr;
0032     ngx_stream_session_t         *s;
0033     ngx_stream_addr_conf_t       *addr_conf;
0034 #if (NGX_HAVE_INET6)
0035     struct sockaddr_in6          *sin6;
0036     ngx_stream_in6_addr_t        *addr6;
0037 #endif
0038     ngx_stream_core_srv_conf_t   *cscf;
0039     ngx_stream_core_main_conf_t  *cmcf;
0040 
0041     /* find the server configuration for the address:port */
0042 
0043     port = c->listening->servers;
0044 
0045     if (port->naddrs > 1) {
0046 
0047         /*
0048          * There are several addresses on this port and one of them
0049          * is the "*:port" wildcard so getsockname() is needed to determine
0050          * the server address.
0051          *
0052          * AcceptEx() and recvmsg() already gave this address.
0053          */
0054 
0055         if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
0056             ngx_stream_close_connection(c);
0057             return;
0058         }
0059 
0060         sa = c->local_sockaddr;
0061 
0062         switch (sa->sa_family) {
0063 
0064 #if (NGX_HAVE_INET6)
0065         case AF_INET6:
0066             sin6 = (struct sockaddr_in6 *) sa;
0067 
0068             addr6 = port->addrs;
0069 
0070             /* the last address is "*" */
0071 
0072             for (i = 0; i < port->naddrs - 1; i++) {
0073                 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
0074                     break;
0075                 }
0076             }
0077 
0078             addr_conf = &addr6[i].conf;
0079 
0080             break;
0081 #endif
0082 
0083         default: /* AF_INET */
0084             sin = (struct sockaddr_in *) sa;
0085 
0086             addr = port->addrs;
0087 
0088             /* the last address is "*" */
0089 
0090             for (i = 0; i < port->naddrs - 1; i++) {
0091                 if (addr[i].addr == sin->sin_addr.s_addr) {
0092                     break;
0093                 }
0094             }
0095 
0096             addr_conf = &addr[i].conf;
0097 
0098             break;
0099         }
0100 
0101     } else {
0102         switch (c->local_sockaddr->sa_family) {
0103 
0104 #if (NGX_HAVE_INET6)
0105         case AF_INET6:
0106             addr6 = port->addrs;
0107             addr_conf = &addr6[0].conf;
0108             break;
0109 #endif
0110 
0111         default: /* AF_INET */
0112             addr = port->addrs;
0113             addr_conf = &addr[0].conf;
0114             break;
0115         }
0116     }
0117 
0118     s = ngx_pcalloc(c->pool, sizeof(ngx_stream_session_t));
0119     if (s == NULL) {
0120         ngx_stream_close_connection(c);
0121         return;
0122     }
0123 
0124     s->signature = NGX_STREAM_MODULE;
0125     s->main_conf = addr_conf->ctx->main_conf;
0126     s->srv_conf = addr_conf->ctx->srv_conf;
0127 
0128 #if (NGX_STREAM_SSL)
0129     s->ssl = addr_conf->ssl;
0130 #endif
0131 
0132     if (c->buffer) {
0133         s->received += c->buffer->last - c->buffer->pos;
0134     }
0135 
0136     s->connection = c;
0137     c->data = s;
0138 
0139     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
0140 
0141     ngx_set_connection_log(c, cscf->error_log);
0142 
0143     len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1);
0144 
0145     ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA %sclient %*s connected to %V",
0146                   c->number, c->type == SOCK_DGRAM ? "udp " : "",
0147                   len, text, &addr_conf->addr_text);
0148 
0149     c->log->connection = c->number;
0150     c->log->handler = ngx_stream_log_error;
0151     c->log->data = s;
0152     c->log->action = "initializing session";
0153     c->log_error = NGX_ERROR_INFO;
0154 
0155     s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_stream_max_module);
0156     if (s->ctx == NULL) {
0157         ngx_stream_close_connection(c);
0158         return;
0159     }
0160 
0161     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
0162 
0163     s->variables = ngx_pcalloc(s->connection->pool,
0164                                cmcf->variables.nelts
0165                                * sizeof(ngx_stream_variable_value_t));
0166 
0167     if (s->variables == NULL) {
0168         ngx_stream_close_connection(c);
0169         return;
0170     }
0171 
0172     tp = ngx_timeofday();
0173     s->start_sec = tp->sec;
0174     s->start_msec = tp->msec;
0175 
0176     rev = c->read;
0177     rev->handler = ngx_stream_session_handler;
0178 
0179     if (addr_conf->proxy_protocol) {
0180         c->log->action = "reading PROXY protocol";
0181 
0182         rev->handler = ngx_stream_proxy_protocol_handler;
0183 
0184         if (!rev->ready) {
0185             ngx_add_timer(rev, cscf->proxy_protocol_timeout);
0186 
0187             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0188                 ngx_stream_finalize_session(s,
0189                                             NGX_STREAM_INTERNAL_SERVER_ERROR);
0190             }
0191 
0192             return;
0193         }
0194     }
0195 
0196     if (ngx_use_accept_mutex) {
0197         ngx_post_event(rev, &ngx_posted_events);
0198         return;
0199     }
0200 
0201     rev->handler(rev);
0202 }
0203 
0204 
0205 static void
0206 ngx_stream_proxy_protocol_handler(ngx_event_t *rev)
0207 {
0208     u_char                      *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
0209     size_t                       size;
0210     ssize_t                      n;
0211     ngx_err_t                    err;
0212     ngx_connection_t            *c;
0213     ngx_stream_session_t        *s;
0214     ngx_stream_core_srv_conf_t  *cscf;
0215 
0216     c = rev->data;
0217     s = c->data;
0218 
0219     ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
0220                    "stream PROXY protocol handler");
0221 
0222     if (rev->timedout) {
0223         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0224         ngx_stream_finalize_session(s, NGX_STREAM_OK);
0225         return;
0226     }
0227 
0228     n = recv(c->fd, (char *) buf, sizeof(buf), MSG_PEEK);
0229 
0230     err = ngx_socket_errno;
0231 
0232     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "recv(): %z", n);
0233 
0234     if (n == -1) {
0235         if (err == NGX_EAGAIN) {
0236             rev->ready = 0;
0237 
0238             if (!rev->timer_set) {
0239                 cscf = ngx_stream_get_module_srv_conf(s,
0240                                                       ngx_stream_core_module);
0241 
0242                 ngx_add_timer(rev, cscf->proxy_protocol_timeout);
0243             }
0244 
0245             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0246                 ngx_stream_finalize_session(s,
0247                                             NGX_STREAM_INTERNAL_SERVER_ERROR);
0248             }
0249 
0250             return;
0251         }
0252 
0253         ngx_connection_error(c, err, "recv() failed");
0254 
0255         ngx_stream_finalize_session(s, NGX_STREAM_OK);
0256         return;
0257     }
0258 
0259     if (rev->timer_set) {
0260         ngx_del_timer(rev);
0261     }
0262 
0263     p = ngx_proxy_protocol_read(c, buf, buf + n);
0264 
0265     if (p == NULL) {
0266         ngx_stream_finalize_session(s, NGX_STREAM_BAD_REQUEST);
0267         return;
0268     }
0269 
0270     size = p - buf;
0271 
0272     if (c->recv(c, buf, size) != (ssize_t) size) {
0273         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
0274         return;
0275     }
0276 
0277     c->log->action = "initializing session";
0278 
0279     ngx_stream_session_handler(rev);
0280 }
0281 
0282 
0283 void
0284 ngx_stream_session_handler(ngx_event_t *rev)
0285 {
0286     ngx_connection_t      *c;
0287     ngx_stream_session_t  *s;
0288 
0289     c = rev->data;
0290     s = c->data;
0291 
0292     ngx_stream_core_run_phases(s);
0293 }
0294 
0295 
0296 void
0297 ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc)
0298 {
0299     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
0300                    "finalize stream session: %i", rc);
0301 
0302     s->status = rc;
0303 
0304     ngx_stream_log_session(s);
0305 
0306     ngx_stream_close_connection(s->connection);
0307 }
0308 
0309 
0310 static void
0311 ngx_stream_log_session(ngx_stream_session_t *s)
0312 {
0313     ngx_uint_t                    i, n;
0314     ngx_stream_handler_pt        *log_handler;
0315     ngx_stream_core_main_conf_t  *cmcf;
0316 
0317     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
0318 
0319     log_handler = cmcf->phases[NGX_STREAM_LOG_PHASE].handlers.elts;
0320     n = cmcf->phases[NGX_STREAM_LOG_PHASE].handlers.nelts;
0321 
0322     for (i = 0; i < n; i++) {
0323         log_handler[i](s);
0324     }
0325 }
0326 
0327 
0328 static void
0329 ngx_stream_close_connection(ngx_connection_t *c)
0330 {
0331     ngx_pool_t  *pool;
0332 
0333     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
0334                    "close stream connection: %d", c->fd);
0335 
0336 #if (NGX_STREAM_SSL)
0337 
0338     if (c->ssl) {
0339         if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
0340             c->ssl->handler = ngx_stream_close_connection;
0341             return;
0342         }
0343     }
0344 
0345 #endif
0346 
0347 #if (NGX_STAT_STUB)
0348     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
0349 #endif
0350 
0351     pool = c->pool;
0352 
0353     ngx_close_connection(c);
0354 
0355     ngx_destroy_pool(pool);
0356 }
0357 
0358 
0359 static u_char *
0360 ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len)
0361 {
0362     u_char                *p;
0363     ngx_stream_session_t  *s;
0364 
0365     if (log->action) {
0366         p = ngx_snprintf(buf, len, " while %s", log->action);
0367         len -= p - buf;
0368         buf = p;
0369     }
0370 
0371     s = log->data;
0372 
0373     p = ngx_snprintf(buf, len, ", %sclient: %V, server: %V",
0374                      s->connection->type == SOCK_DGRAM ? "udp " : "",
0375                      &s->connection->addr_text,
0376                      &s->connection->listening->addr_text);
0377     len -= p - buf;
0378     buf = p;
0379 
0380     if (s->log_handler) {
0381         p = s->log_handler(log, buf, len);
0382     }
0383 
0384     return p;
0385 }