static void ngx_tcp_proxy_init_session(ngx_tcp_session_t *s) { ngx_connection_t *c; ngx_tcp_proxy_conf_t *pcf; ngx_tcp_core_srv_conf_t *cscf; c = s->connection; ngx_log_debug0(NGX_LOG_DEBUG_TCP, c->log, 0, "tcp proxy init session"); cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); pcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_proxy_module); s->buffer = ngx_create_temp_buf(s->connection->pool, pcf->buffer_size); if (s->buffer == NULL) { ngx_tcp_finalize_session(s); return; } s->out.len = 0; c->write->handler = ngx_tcp_proxy_dummy_write_handler; c->read->handler = ngx_tcp_proxy_dummy_read_handler; ngx_add_timer(c->read, cscf->timeout); ngx_tcp_proxy_init_upstream(c, s); return; }
static void ngx_tcp_websocket_init_session(ngx_tcp_session_t *s) { ngx_connection_t *c; ngx_tcp_websocket_ctx_t *wctx; ngx_tcp_core_srv_conf_t *cscf; ngx_tcp_websocket_conf_t *wcf; c = s->connection; ngx_log_debug0(NGX_LOG_DEBUG_TCP, c->log, 0, "tcp websocket init session"); cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); wcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_websocket_module); wctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_tcp_websocket_ctx_t)); if (wctx == NULL) { ngx_tcp_finalize_session(s); return; } ngx_tcp_set_ctx(s, wctx, ngx_tcp_websocket_module); s->out.len = 0; s->buffer = ngx_create_temp_buf(s->connection->pool, wcf->buffer_size); if (s->buffer == NULL) { ngx_tcp_finalize_session(s); return; } c->write->handler = ngx_tcp_websocket_dummy_write_handler; c->read->handler = ngx_tcp_websocket_init_protocol; ngx_add_timer(c->read, cscf->timeout); if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_tcp_finalize_session(s); } #if (NGX_TCP_SSL) /* * The ssl connection with client may not trigger the read event again, * So I trigger it in this function. * */ if (c->ssl) { ngx_tcp_websocket_init_protocol(c->read); return; } #endif if (c->read->ready) { ngx_tcp_websocket_init_protocol(c->read); } return; }
static void ngx_tcp_ssl_handshake_handler(ngx_connection_t *c) { ngx_tcp_session_t *s; ngx_tcp_core_srv_conf_t *cscf; if (c->ssl->handshaked) { s = c->data; if (s->starttls) { cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); c->read->handler = cscf->protocol->init_protocol; c->write->handler = ngx_tcp_send; cscf->protocol->init_protocol(c->read); return; } c->read->ready = 0; ngx_tcp_init_session(c); return; } ngx_tcp_close_connection(c); }
static void ngx_tcp_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c) { ngx_tcp_session_t *s; ngx_tcp_core_srv_conf_t *cscf; if (ngx_ssl_create_connection(ssl, c, NGX_SSL_BUFFER) == NGX_ERROR) { ngx_tcp_close_connection(c); return; } if (ngx_ssl_handshake(c) == NGX_AGAIN) { s = c->data; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); ngx_add_timer(c->read, cscf->timeout); c->ssl->handler = ngx_tcp_ssl_handshake_handler; return; } ngx_tcp_ssl_handshake_handler(c); }
static void ngx_tcp_set_session_socket(ngx_tcp_session_t *s) { int keepalive; int tcp_nodelay; ngx_tcp_core_srv_conf_t *cscf; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); if (cscf->so_keepalive) { keepalive = 1; if (setsockopt(s->connection->fd, SOL_SOCKET, SO_KEEPALIVE, (const void *) &keepalive, sizeof(int)) == -1) { ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno, "setsockopt(SO_KEEPALIVE) failed"); } } if (cscf->tcp_nodelay) { tcp_nodelay = 1; if (setsockopt(s->connection->fd, IPPROTO_TCP, TCP_NODELAY, (const void *) &tcp_nodelay, sizeof(int)) == -1) { ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno, "setsockopt(TCP_NODELAY) failed"); } s->connection->tcp_nodelay = NGX_TCP_NODELAY_SET; } }
void ngx_tcp_lua_check_client_abort_handler(ngx_tcp_session_t *s) { ngx_connection_t *c; ngx_tcp_lua_ctx_t *ctx; ngx_tcp_lua_srv_conf_t *lscf; c = s->connection; ctx = s->ctx; lscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_lua_module); if (!lscf->check_client_abort) { return; } ngx_log_debug0(NGX_LOG_DEBUG_TCP, c->log, 0, "lua socket check client abort handler"); if (ctx->socket_invalid) { return; } ngx_tcp_test_reading(s); if (c->error) { ctx->ft_type |= NGX_TCP_LUA_REQ_FT_ERROR; ctx->socket_errno = ngx_socket_errno; ctx->socket_invalid = 1; ngx_tcp_lua_close_session(s); } }
static void ngx_tcp_process_session(ngx_event_t *rev) { ngx_connection_t *c; ngx_tcp_session_t *s; ngx_tcp_core_srv_conf_t *cscf; c = rev->data; s = c->data; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); /* process the ACL */ if (ngx_tcp_access_handler(s) == NGX_ERROR) { ngx_tcp_finalize_session(s); return; } if (cscf->protocol == NULL || cscf->protocol->init_session == NULL) { dd("protocol not initialized"); ngx_tcp_finalize_session(s); return; } c->read->handler= ngx_tcp_session_handler; c->write->handler= ngx_tcp_session_handler; s->read_event_handler = cscf->protocol->init_session; rev->handler(rev); }
void ngx_tcp_send(ngx_event_t *wev) { ngx_int_t n; ngx_connection_t *c; ngx_tcp_session_t *s; ngx_tcp_core_srv_conf_t *cscf; c = wev->data; s = c->data; if (wev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); c->timedout = 1; ngx_tcp_close_connection(c); return; } if (s->out.len == 0) { if (ngx_handle_write_event(c->write, 0) != NGX_OK) { ngx_tcp_close_connection(c); } return; } n = c->send(c, s->out.data, s->out.len); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, wev->log, 0, "nginx tcp send:%d", n); if (n > 0) { s->out.len -= n; if (wev->timer_set) { ngx_del_timer(wev); } if (s->quit) { ngx_tcp_close_connection(c); return; } return; } if (n == NGX_ERROR) { ngx_tcp_close_connection(c); return; } /* n == NGX_AGAIN */ cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); ngx_add_timer(c->write, cscf->timeout); if (ngx_handle_write_event(c->write, 0) != NGX_OK) { ngx_tcp_close_connection(c); return; } }
void ngx_tcp_send(ngx_event_t *wev) { ngx_int_t rc; ngx_connection_t *c; ngx_tcp_session_t *s; ngx_tcp_core_srv_conf_t *cscf; c = wev->data; s = c->data; if (wev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "%s|%d|%s|client timed out",__FILE__, __LINE__, __FUNCTION__); c->timedout = 1; ngx_tcp_close_connection(c); return; } if (s->output_buffer_chain == NULL) { return; } // rc = s->output_ctx->output_filter(s->output_ctx->filter_ctx, //s->output_buffer_chain); rc = s->output_ctx->output_filter(s); ngx_chain_update_chains(s->output_ctx->pool, &s->output_ctx->free, &s->output_ctx->busy, &s->output_buffer_chain, s->output_ctx->tag); s->output_buffer_chain = NULL; if (rc == NGX_OK || rc == NGX_DONE) { if (wev->timer_set) { ngx_del_timer(wev); } return; } if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "ngx_tcp_send|client=%V\n", &c->addr_text); ngx_tcp_close_connection(c); return; } /* rc == NGX_AGAIN */ /* ngx_log_error(NGX_LOG_INFO, c->log, 0, "ngx_tcp_send|NGX_AGAIN|client=%V\n", &c->addr_text); */ cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); ngx_add_timer(c->write, cscf->timeout); if (ngx_handle_write_event(c->write, 0) != NGX_OK) { ngx_tcp_close_connection(c); return; } }
void ngx_tcp_session_internal_server_error(ngx_tcp_session_t *s) { ngx_tcp_core_srv_conf_t *cscf; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); s->out = cscf->protocol->internal_server_error; s->quit = 1; ngx_tcp_send(s->connection->write); }
static void ngx_tcp_proxy_init_upstream(ngx_connection_t *c, ngx_tcp_session_t *s) { ngx_tcp_upstream_t *u; ngx_tcp_proxy_ctx_t *p; ngx_tcp_proxy_conf_t *pcf; s->connection->log->action = "ngx_tcp_proxy_init_upstream"; pcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_proxy_module); if (pcf->upstream.upstream == NULL) { ngx_tcp_finalize_session(s); return; } p = ngx_pcalloc(s->connection->pool, sizeof(ngx_tcp_proxy_ctx_t)); if (p == NULL) { ngx_tcp_finalize_session(s); return; } ngx_tcp_set_ctx(s, p, ngx_tcp_proxy_module); if (ngx_tcp_upstream_create(s) != NGX_OK) { ngx_tcp_finalize_session(s); return; } u = s->upstream; u->conf = &pcf->upstream; u->write_event_handler = ngx_tcp_upstream_init_proxy_handler; u->read_event_handler = ngx_tcp_upstream_init_proxy_handler; p->upstream = &u->peer; p->buffer = ngx_create_temp_buf(s->connection->pool, pcf->buffer_size); if (p->buffer == NULL) { ngx_tcp_finalize_session(s); return; } ngx_tcp_upstream_init(s); return; }
void ngx_tcp_starttls_handler(ngx_event_t *rev) { ngx_connection_t *c; ngx_tcp_session_t *s; ngx_tcp_ssl_conf_t *sslcf; c = rev->data; s = c->data; s->starttls = 1; c->log->action = "in starttls state"; sslcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_ssl_module); ngx_tcp_ssl_init_connection(&sslcf->ssl, c); }
ngx_int_t ngx_tcp_starttls_only(ngx_tcp_session_t *s, ngx_connection_t *c) { ngx_tcp_ssl_conf_t *sslcf; if (c->ssl) { return 0; } sslcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_ssl_module); if (sslcf->starttls == NGX_TCP_STARTTLS_ONLY) { return 1; } return 0; }
void ngx_tcp_close_connection(ngx_connection_t *c) { ngx_pool_t *pool; ngx_tcp_session_t *s; ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "ngx_tcp_close_connection|client=%V|fd=%d\n", &c->addr_text, c->fd); s = c->data; if (s != NULL) { ngx_tcp_core_srv_conf_t *cscf; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); if (cscf->protocol != NULL && cscf->protocol->finit_session != NULL) { cscf->protocol->finit_session(s); } } #if (NGX_TCP_SSL) if (c->ssl) { if (ngx_ssl_shutdown(c) == NGX_AGAIN) { c->ssl->handler = ngx_tcp_close_connection; return; } } #endif #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, -1); #endif c->destroyed = 1; pool = c->pool; ngx_close_connection(c); ngx_destroy_pool(pool); }
static void ngx_tcp_init_session(ngx_connection_t *c) { ngx_tcp_session_t *s; ngx_tcp_core_srv_conf_t *cscf; s = c->data; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); s->protocol = cscf->protocol->type; s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_tcp_max_module); if (s->ctx == NULL) { ngx_tcp_session_internal_server_error(s); return; } c->write->handler = ngx_tcp_send; cscf->protocol->init_session(s, c); }
static ngx_tcp_path_upstream_t * ngx_tcp_websocket_find_path_upstream(ngx_tcp_session_t *s, ngx_tcp_websocket_ctx_t *ctx) { ngx_uint_t i; ngx_tcp_path_upstream_t *pu; ngx_tcp_websocket_conf_t *wcf; wcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_websocket_module); pu = wcf->path_upstreams.elts; for (i = 0; i < wcf->path_upstreams.nelts; i++) { if ((pu[i].path.len != ctx->path.len) || ngx_memcmp(pu[i].path.data, ctx->path.data, ctx->path.len) != 0) { continue; } return &pu[i]; } return NULL; }
static void ngx_tcp_lua_init_session(ngx_tcp_session_t *s) { ngx_connection_t *c; ngx_tcp_lua_srv_conf_t *lscf; ngx_tcp_lua_main_conf_t *lmcf; lua_State *L; ngx_int_t rc; u_char *script_path; char *err; c = s->connection; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp lua init and load src"); lscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_lua_module); lmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_lua_module); L = lmcf->lua; if (lscf->lua_src_inline) { /* load Lua inline script (w/ cache) sp = 1 */ rc = ngx_tcp_lua_cache_loadbuffer(L, lscf->lua_src.data, lscf->lua_src.len, lscf->lua_src_key, "process_by_lua", &err, lscf->enable_code_cache ? 1 : 0); if (rc != NGX_OK) { if (err == NULL) { err = "unknown error"; } ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "failed to load Lua inlined code: %s", err); ngx_tcp_finalize_session(s); return; } } else { /* load Lua script file (w/ cache) sp = 1 */ script_path = ngx_tcp_lua_rebase_path(s->pool, lscf->lua_src.data, lscf->lua_src.len); if (script_path == NULL) { ngx_tcp_finalize_session(s); return; } rc = ngx_tcp_lua_cache_loadfile(L, script_path, lscf->lua_src_key, &err, lscf->enable_code_cache ? 1 : 0); if (rc != NGX_OK) { if (err == NULL) { err = "unknown error"; } ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to load Lua code: %s", err); ngx_tcp_finalize_session(s); return; } } /* make sure we have a valid code chunk */ assert(lua_isfunction(L, -1)); s->write_event_handler= ngx_tcp_lua_dummy_write_handler; s->read_event_handler= ngx_tcp_lua_dummy_read_handler; rc = ngx_tcp_lua_process_by_chunk(L, s); if (rc == NGX_DONE || rc == NGX_OK || rc == NGX_ERROR) { ngx_tcp_finalize_session(s); return; } }
ngx_int_t ngx_tcp_log_handler(ngx_tcp_session_t *s) { u_char *line, *p; size_t len; ngx_uint_t l; ngx_connection_t *c; ngx_tcp_log_t *log; ngx_open_file_t *file; #if (nginx_version) >= 1003010 ngx_tcp_log_buf_t *buffer; #endif ngx_tcp_log_srv_conf_t *lscf; ngx_tcp_core_srv_conf_t *cscf; ngx_log_debug0(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "tcp access log handler"); cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); lscf = cscf->access_log; if (lscf->off) { return NGX_OK; } c = s->connection; log = lscf->logs->elts; for (l = 0; l < lscf->logs->nelts; l++) { if (ngx_time() == log[l].disk_full_time) { /* * on FreeBSD writing to a full filesystem with enabled softupdates * may block process for much longer time than writing to non-full * filesystem, so we skip writing to a log for one second */ continue; } len = 0; /* Calculate the length */ len += sizeof("1970/09/28 12:00:00"); /* log time */ len += NGX_INT64_LEN + 2; /* [ngx_pid] */ len += c->addr_text.len + 1; /* client address */ len += s->addr_text->len + 1; /* this session address */ len += sizeof("1970/09/28 12:00:00"); /* accept time */ len += sizeof("255.255.255.255:65536"); /* upstream address */ len += NGX_OFF_T_LEN + 1; /* read bytes from client */ len += NGX_OFF_T_LEN + 1; /* write bytes to client */ len += NGX_LINEFEED_SIZE; file = log[l].file; #if (nginx_version) >= 1003010 if (file && file->data) { buffer = file->data; if (len > (size_t) (buffer->last - buffer->pos)) { ngx_tcp_log_write(s, &log[l], buffer->start, buffer->pos - buffer->start); buffer->pos = buffer->start; } if (len <= (size_t) (buffer->last - buffer->pos)) { p = buffer->pos; p = ngx_tcp_log_fill(s, p); buffer->pos = p; continue; } } #else if (file && file->buffer) { if (len > (size_t) (file->last - file->pos)) { ngx_tcp_log_write(s, &log[l], file->buffer, file->pos - file->buffer); file->pos = file->buffer; } if (len <= (size_t) (file->last - file->pos)) { p = file->pos; p = ngx_tcp_log_fill(s, p); file->pos = p; continue; } } #endif line = ngx_pnalloc(s->pool, len); if (line == NULL) { return NGX_ERROR; } p = line; p = ngx_tcp_log_fill(s, p); ngx_tcp_log_write(s, &log[l], line, p - line); } return NGX_OK; }
static void ngx_tcp_upstream_connect(ngx_tcp_session_t *s, ngx_tcp_upstream_t *u) { int tcp_nodelay; ngx_int_t rc; ngx_connection_t *c; ngx_tcp_core_srv_conf_t *cscf; s->connection->log->action = "connecting to upstream"; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); rc = ngx_event_connect_peer(&u->peer); ngx_log_debug1(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "tcp upstream connect: %d", rc); if (rc != NGX_OK && rc != NGX_AGAIN) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "upstream servers error or busy!"); ngx_tcp_upstream_finalize_session(s, u, 0); return; } /* rc == NGX_OK or rc == NGX_AGAIN */ if (u->peer.check_index != NGX_INVALID_INDEX) { ngx_tcp_check_get_peer(u->peer.check_index); } c = u->peer.connection; c->data = s; c->pool = s->connection->pool; c->log = s->connection->log; c->read->log = c->log; c->write->log = c->log; c->write->handler = ngx_tcp_upstream_handler; c->read->handler = ngx_tcp_upstream_handler; if (cscf->tcp_nodelay) { tcp_nodelay = 1; if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, (const void *) &tcp_nodelay, sizeof(int)) == -1) { ngx_connection_error(c, ngx_socket_errno, "setsockopt(TCP_NODELAY) failed"); ngx_tcp_upstream_finalize_session(s, u, 0); return; } c->tcp_nodelay = NGX_TCP_NODELAY_SET; } if (rc == NGX_AGAIN) { /*connect busy*/ ngx_add_timer(c->write, u->conf->connect_timeout); return; } else { ngx_add_timer(c->read, u->conf->read_timeout); ngx_add_timer(c->write, u->conf->send_timeout); c->write->handler(c->write); } }
void ngx_tcp_upstream_init(ngx_tcp_session_t *s) { ngx_str_t *host; ngx_uint_t i; ngx_connection_t *c; ngx_tcp_cleanup_t *cln; ngx_resolver_ctx_t *ctx, temp; ngx_tcp_upstream_t *u; ngx_tcp_core_srv_conf_t *cscf; ngx_tcp_upstream_srv_conf_t *uscf, **uscfp; ngx_tcp_upstream_main_conf_t *umcf; c = s->connection; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); ngx_log_debug1(NGX_LOG_DEBUG_TCP, c->log, 0, "tcp init upstream, client timer: %d", c->read->timer_set); if (c->read->timer_set) { ngx_del_timer(c->read); } u = s->upstream; cln = ngx_tcp_cleanup_add(s, 0); cln->handler = ngx_tcp_upstream_cleanup; cln->data = s; u->cleanup = &cln->handler; if (u->resolved == NULL) { uscf = u->conf->upstream; } else { /*TODO: support variable in the proxy_pass*/ if (u->resolved->sockaddr) { if (ngx_tcp_upstream_create_round_robin_peer(s, u->resolved) != NGX_OK) { ngx_tcp_finalize_session(s); return; } ngx_tcp_upstream_connect(s, u); return; } host = &u->resolved->host; umcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_upstream_module); uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; if (uscf->host.len == host->len && ((uscf->port == 0 && u->resolved->no_port) || uscf->port == u->resolved->port) && ngx_memcmp(uscf->host.data, host->data, host->len) == 0) { goto found; } } temp.name = *host; ctx = ngx_resolve_start(cscf->resolver, &temp); if (ctx == NULL) { ngx_tcp_finalize_session(s); return; } if (ctx == NGX_NO_RESOLVER) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no resolver defined to resolve %V", host); ngx_tcp_finalize_session(s); return; } ctx->name = *host; ctx->type = NGX_RESOLVE_A; ctx->handler = ngx_tcp_upstream_resolve_handler; ctx->data = s; ctx->timeout = cscf->resolver_timeout; u->resolved->ctx = ctx; if (ngx_resolve_name(ctx) != NGX_OK) { u->resolved->ctx = NULL; ngx_tcp_finalize_session(s); return; } return; } found: if (uscf->peer.init(s, uscf) != NGX_OK) { ngx_tcp_finalize_session(s); return; } ngx_tcp_upstream_connect(s, u); }
static void ngx_tcp_init_session(ngx_event_t *rev) { ngx_time_t *tp; ngx_uint_t i; ngx_connection_t *c; struct sockaddr_in *sin; ngx_tcp_port_t *port; ngx_tcp_in_addr_t *addr; ngx_tcp_log_ctx_t *ctx; ngx_tcp_addr_conf_t *addr_conf; ngx_tcp_session_t *s; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; ngx_tcp_in6_addr_t *addr6; #endif ngx_tcp_core_srv_conf_t *cscf; /* #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); #endif */ c = rev->data; s = c->data; if (s == NULL) { s = ngx_pcalloc(c->pool, sizeof(ngx_tcp_session_t)); if (s == NULL) { ngx_tcp_close_connection(c); return; } c->data = s; } ctx = c->log->data; ctx->session= s; ctx->client= &c->addr_text; c->requests++; s->connection = c; s->signature = NGX_TCP_MODULE; /* find the server configuration for the address:port */ port = c->listening->servers; if (port->naddrs > 1) { /* * there are several addresses on this port and one of them * is an "*:port" wildcard so getsockname() in ngx_tcp_server_addr() * is required to determine a server address */ if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { ngx_tcp_close_connection(c); return; } switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) c->local_sockaddr; addr6 = port->addrs; /* the last address is "*" */ for (i = 0; i < port->naddrs - 1; i++) { if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { break; } } addr_conf = &addr6[i].conf; break; #endif default: /* AF_INET */ sin = (struct sockaddr_in *) c->local_sockaddr; addr = port->addrs; /* the last address is "*" */ for (i = 0; i < port->naddrs - 1; i++) { if (addr[i].addr == sin->sin_addr.s_addr) { break; } } addr_conf = &addr[i].conf; break; } } else { switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: addr6 = port->addrs; addr_conf = &addr6[0].conf; break; #endif default: /* AF_INET */ addr = port->addrs; addr_conf = &addr[0].conf; break; } } if (addr_conf->default_ctx) { s->main_conf = addr_conf->default_ctx->main_conf; s->srv_conf = addr_conf->default_ctx->srv_conf; } else { s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; } s->addr_text = &addr_conf->addr_text; if (rev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); ngx_tcp_close_connection(c); return; } rev->handler = ngx_tcp_process_session; //s->read_event_handler = ngx_tcp_block_reading; /* #if (NGX_HTTP_SSL) { ngx_tcp_ssl_srv_conf_t *sscf; sscf = ngx_tcp_get_module_srv_conf(r, ngx_tcp_ssl_module); if (sscf->enable || addr_conf->ssl) { if (c->ssl == NULL) { c->log->action = "SSL handshaking"; if (addr_conf->ssl && sscf->ssl.ctx == NULL) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no \"ssl_certificate\" is defined " "in server listening on SSL port"); ngx_tcp_close_connection(c); return; } if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) != NGX_OK) { ngx_tcp_close_connection(c); return; } rev->handler = ngx_tcp_ssl_handshake; } r->main_filter_need_in_memory = 1; } } #endif */ s->pool = c->pool; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); if (cscf == NULL) { ngx_tcp_finalize_session(s); return; } s->ctx = ngx_pcalloc(s->pool, sizeof(void *) * ngx_tcp_max_module); if (s->ctx == NULL) { ngx_tcp_finalize_session(s); return; } tp = ngx_timeofday(); s->start_sec = tp->sec; s->start_msec = tp->msec; s->bytes_read = 0; s->bytes_write = 0; ngx_tcp_set_session_socket(s); /* #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); r->stat_reading = 1; (void) ngx_atomic_fetch_add(ngx_stat_requests, 1); #endif */ rev->handler(rev); }
static ngx_int_t ngx_tcp_lua_req_read(ngx_tcp_session_t *s, ngx_tcp_lua_ctx_t *ctx) { ngx_connection_t *c; ngx_tcp_core_srv_conf_t *cscf; ngx_buf_t *b; ngx_event_t *rev; size_t size; ssize_t n; c = s->connection; rev = c->read; if (rev->timedout) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "lua socket read timed out"); ctx->ft_type |= NGX_TCP_LUA_REQ_FT_TIMEOUT; return NGX_ERROR; } b = ctx->buf_in; size = ctx->length - (b->last - b->pos); if (size <= 0) { //log return NGX_OK; } n = c->recv(c, b->last, size); ngx_log_debug1(NGX_LOG_DEBUG_TCP, c->log, 0, "lua socket recv returned %d",(int) n); if (n == NGX_AGAIN) { dd("socket recv busy"); if (!rev->timer_set) { cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); ngx_add_timer(rev, cscf->read_timeout); } if (ngx_handle_read_event(rev, 0) != NGX_OK) { ctx->ft_type |= NGX_TCP_LUA_REQ_FT_ERROR; ctx->socket_invalid = 1; ctx->socket_errno = ngx_socket_errno; return NGX_ERROR; } return NGX_AGAIN; } if (n == 0) { ctx->ft_type |= NGX_TCP_LUA_REQ_FT_CLOSED; ctx->socket_invalid = 1; //ctx->socket_errno = ngx_socket_errno; ngx_log_debug0(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "lua socket closed"); return NGX_ERROR; } if (n == NGX_ERROR) { ctx->ft_type |= NGX_TCP_LUA_REQ_FT_ERROR; ctx->socket_invalid = 1; ctx->socket_errno = ngx_socket_errno; return NGX_ERROR; } b->last += n; if ((size_t)(b->last - b->pos) >= ctx->bytes_atleast) { return NGX_OK; } return NGX_AGAIN; }
static void ngx_tcp_upstream_init_proxy_handler(ngx_tcp_session_t *s, ngx_tcp_upstream_t *u) { ngx_connection_t *c; ngx_tcp_proxy_ctx_t *pctx; ngx_tcp_proxy_conf_t *pcf; c = s->connection; c->log->action = "ngx_tcp_upstream_init_proxy_handler"; ngx_log_debug0(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "tcp proxy upstream init proxy"); pcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_proxy_module); pctx = ngx_tcp_get_module_ctx(s, ngx_tcp_proxy_module); if (pcf == NULL || pctx == NULL) { ngx_tcp_finalize_session(s); return; } pctx->upstream = &s->upstream->peer; c = pctx->upstream->connection; if (c->read->timedout || c->write->timedout) { ngx_tcp_upstream_next(s, u, NGX_TCP_UPSTREAM_FT_TIMEOUT); return; } if (ngx_tcp_upstream_check_broken_connection(s) != NGX_OK){ ngx_tcp_upstream_next(s, u, NGX_TCP_UPSTREAM_FT_ERROR); return; } s->connection->read->handler = ngx_tcp_proxy_handler; s->connection->write->handler = ngx_tcp_proxy_handler; c->read->handler = ngx_tcp_proxy_handler; c->write->handler = ngx_tcp_proxy_handler; ngx_add_timer(c->read, pcf->upstream.read_timeout); ngx_add_timer(c->write, pcf->upstream.send_timeout); if (ngx_handle_read_event(s->connection->read, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } #if (NGX_TCP_SSL) /* * The ssl connection with client may not trigger the read event again, * So I trigger it in this function. * */ if (s->connection->ssl) { ngx_tcp_proxy_handler(s->connection->read); } #endif return; }
static void ngx_tcp_proxy_handler(ngx_event_t *ev) { char *action, *recv_action, *send_action; off_t *read_bytes, *write_bytes; size_t size; ssize_t n; ngx_buf_t *b; ngx_err_t err; ngx_uint_t do_write, first_read; ngx_connection_t *c, *src, *dst; ngx_tcp_session_t *s; ngx_tcp_proxy_conf_t *pcf; ngx_tcp_proxy_ctx_t *pctx; ngx_tcp_core_srv_conf_t *cscf; c = ev->data; s = c->data; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); if (ev->timedout) { c->log->action = "proxying"; ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "proxy timed out"); c->timedout = 1; ngx_tcp_finalize_session(s); return; } pctx = ngx_tcp_get_module_ctx(s, ngx_tcp_proxy_module); if (pctx == NULL) { ngx_tcp_finalize_session(s); return; } read_bytes = NULL; write_bytes = NULL; if (c == s->connection) { if (ev->write) { recv_action = "client write: proxying and reading from upstream"; send_action = "client write: proxying and sending to client"; src = pctx->upstream->connection; dst = c; b = pctx->buffer; write_bytes = &s->bytes_write; } else { recv_action = "client read: proxying and reading from client"; send_action = "client read: proxying and sending to upstream"; src = c; dst = pctx->upstream->connection; b = s->buffer; read_bytes = &s->bytes_read; } } else { if (ev->write) { recv_action = "upstream write: proxying and reading from client"; send_action = "upstream write: proxying and sending to upstream"; src = s->connection; dst = c; b = s->buffer; read_bytes = &s->bytes_read; } else { recv_action = "upstream read: proxying and reading from upstream"; send_action = "upstream read: proxying and sending to client"; src = c; dst = s->connection; b = pctx->buffer; write_bytes = &s->bytes_write; } } do_write = ev->write ? 1 : 0; #if (NGX_TCP_SSL) /* SSL Need this */ if (s->connection->ssl) { first_read = 1; } #else first_read = 0; #endif ngx_log_debug4(NGX_LOG_DEBUG_TCP, ev->log, 0, "tcp proxy handler: %d, #%d > #%d, time:%ui", do_write, src->fd, dst->fd, ngx_current_msec); for ( ;; ) { if (do_write) { size = b->last - b->pos; if (size && dst->write->ready) { c->log->action = send_action; n = dst->send(dst, b->pos, size); err = ngx_socket_errno; ngx_log_debug1(NGX_LOG_DEBUG_TCP, ev->log, 0, "tcp proxy handler send:%d", n); if (n == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, c->log, err, "proxy send error"); ngx_tcp_finalize_session(s); return; } if (n > 0) { b->pos += n; if (write_bytes) { *write_bytes += n; } if (b->pos == b->last) { b->pos = b->start; b->last = b->start; } } } } size = b->end - b->last; if (size) { if (src->read->ready || first_read) { first_read = 0; c->log->action = recv_action; n = src->recv(src, b->last, size); err = ngx_socket_errno; ngx_log_debug1(NGX_LOG_DEBUG_TCP, ev->log, 0, "tcp proxy handler recv:%d", n); if (n == NGX_AGAIN || n == 0) { break; } if (n > 0) { do_write = 1; b->last += n; if (read_bytes) { *read_bytes += n; } continue; } if (n == NGX_ERROR) { src->read->eof = 1; } } } break; } c->log->action = "nginx tcp proxying"; if ((s->connection->read->eof && s->buffer->pos == s->buffer->last) || (pctx->upstream->connection->read->eof && pctx->buffer->pos == pctx->buffer->last) || (s->connection->read->eof && pctx->upstream->connection->read->eof)) { action = c->log->action; c->log->action = NULL; ngx_log_error(NGX_LOG_DEBUG, c->log, 0, "proxied session done"); c->log->action = action; ngx_tcp_finalize_session(s); return; } if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } if (ngx_handle_read_event(dst->read, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } if (ngx_handle_write_event(src->write, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } if (ngx_handle_read_event(src->read, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } pcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_proxy_module); if (c == s->connection) { ngx_add_timer(c->read, cscf->timeout); } if (c == pctx->upstream->connection) { if (ev->write) { ngx_add_timer(c->write, pcf->upstream.send_timeout); } else { ngx_add_timer(c->read, pcf->upstream.read_timeout); } } return; }
static int ngx_tcp_lua_ngx_wait_next_request(lua_State *L) { ngx_tcp_session_t *s; ngx_connection_t *c; int n; ngx_tcp_core_srv_conf_t *cscf; ngx_tcp_lua_ctx_t *ctx; n = lua_gettop(L); if (n != 0) { return luaL_error(L, "expecting 0 arguments"); } s = ngx_tcp_lua_get_session(L); if (s == NULL) { //init_by_lua no session return luaL_error(L, "no session found"); } c = s->connection; ngx_tcp_lua_finalize_light_session(s); ngx_log_debug0(NGX_LOG_DEBUG_TCP, c->log, 0, "lua req calling wait_next_request() method"); ctx = s->ctx; if (ctx->socket_invalid) { c->close = 1; goto yield; } ngx_tcp_test_reading(s); if (c->error) { c->close = 1; goto yield; } if (c->read->ready) { if(ngx_tcp_lua_init_light_session(s) != NGX_OK){ c->close = 1; goto yield; } c->log->action = "continue with new session"; return 0; } yield: if (c->close) { ctx->exited = 1; return lua_yield(L, 0); } cscf = ngx_tcp_get_module_srv_conf(s,ngx_tcp_core_module); c->log->action = "lua_req_keepalive"; c->idle = 1; ngx_reusable_connection(c, 1); s->write_event_handler = ngx_tcp_session_empty_handler; s->read_event_handler = ngx_tcp_lua_req_keepalive_handler; if (!c->read->timer_set && cscf->keepalive_timeout != NGX_CONF_UNSET_MSEC) { ngx_add_timer(c->read, cscf->keepalive_timeout); } //lua_pushliteral(L, "closed"); return lua_yield(L, 0); }
static void ngx_tcp_websocket_parse_protocol(ngx_event_t *ev) { u_char *new_buf; ssize_t size, n; ngx_int_t rc; ngx_connection_t *c; ngx_tcp_session_t *s; ngx_tcp_websocket_ctx_t *wctx; ngx_tcp_websocket_conf_t *wcf; c = ev->data; s = c->data; wcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_websocket_module); wctx = ngx_tcp_get_module_ctx(s, ngx_tcp_websocket_module); while (1) { n = s->buffer->end - s->buffer->last; /*Not enough buffer? Enlarge twice*/ if (n == 0) { size = s->buffer->end - s->buffer->start; if ((size_t)size > wcf->buffer_size << 3) { ngx_log_error(NGX_LOG_ERR, ev->log, 0, "too large websocket handshake packet " "error with client: %V #%d", &c->addr_text, c->fd); ngx_tcp_finalize_session(s); return; } new_buf = ngx_palloc(c->pool, size * 2); if (new_buf == NULL) { goto websocket_recv_fail; } ngx_memcpy(new_buf, s->buffer->start, size); n = s->buffer->pos - s->buffer->start; s->buffer->start = new_buf; s->buffer->pos = new_buf + n; s->buffer->last = new_buf + size; s->buffer->end = new_buf + size * 2; n = s->buffer->end - s->buffer->last; } size = c->recv(c, s->buffer->last, n); #if (NGX_DEBUG) ngx_err_t err; if (size >= 0 || size == NGX_AGAIN) { err = 0; } else { err = ngx_socket_errno; } ngx_log_debug3(NGX_LOG_DEBUG_TCP, ev->log, err, "tcp websocket recv size: %d, client: %V #%d", size, &c->addr_text, c->fd); #endif if (size > 0) { s->buffer->last += size; continue; } else if (size == 0 || size == NGX_AGAIN) { break; } else { c->error = 1; goto websocket_recv_fail; } } rc = websocket_http_request_parser_execute(wctx->parser); ngx_log_debug2(NGX_LOG_DEBUG_TCP, c->log, 0, "tcp websocket parse rc: %d, fd: %d", rc, c->fd); switch (rc) { case NGX_AGAIN: return; case NGX_ERROR: goto websocket_recv_fail; case NGX_OK: /* pass through */ default: ngx_tcp_websocket_init_upstream(c, s); } return; websocket_recv_fail: ngx_log_error(NGX_LOG_ERR, ev->log, 0, "recv websocket handshake packet error with client: %V #%d", &c->addr_text, c->fd); ngx_tcp_finalize_session(s); }
void ngx_tcp_init_connection(ngx_connection_t *c) { ngx_uint_t i; ngx_tcp_port_t *port; struct sockaddr *sa; struct sockaddr_in *sin; ngx_tcp_log_ctx_t *ctx; ngx_tcp_in_addr_t *addr; ngx_tcp_session_t *s; ngx_tcp_addr_conf_t *addr_conf; ngx_tcp_core_srv_conf_t *cscf; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; ngx_tcp_in6_addr_t *addr6; #endif /* find the server configuration for the address:port */ port = c->listening->servers; if (port && port->naddrs > 1) { /* * There are several addresses on this port and one of them * is the "*:port" wildcard so getsockname() is needed to determine * the server address. * * AcceptEx() already gave this address. */ if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { ngx_tcp_close_connection(c); return; } sa = c->local_sockaddr; switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) sa; addr6 = port->addrs; /* the last address is "*" */ for (i = 0; i < port->naddrs - 1; i++) { if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { break; } } addr_conf = &addr6[i].conf; break; #endif default: /* AF_INET */ sin = (struct sockaddr_in *) sa; addr = port->addrs; /* the last address is "*" */ for (i = 0; i < port->naddrs - 1; i++) { if (addr[i].addr == sin->sin_addr.s_addr) { break; } } addr_conf = &addr[i].conf; break; } } else { switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: addr6 = port->addrs; addr_conf = &addr6[0].conf; break; #endif case AF_INET: addr = port->addrs; addr_conf = &addr[0].conf; break; default: /* AF_UNIX */ addr = port->addrs; addr_conf = &addr[0].conf; break; } } cscf = ngx_tcp_get_module_srv_conf(addr_conf->ctx, ngx_tcp_core_module); s = cscf->protocol->create_session(c); if (s == NULL) { ngx_tcp_close_connection(c); return; } s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; s->addr_text = &addr_conf->addr_text; c->data = s; s->connection = c; ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V", c->number, &c->addr_text, s->addr_text); ctx = ngx_palloc(c->pool, sizeof(ngx_tcp_log_ctx_t)); if (ctx == NULL) { ngx_tcp_close_connection(c); return; } ctx->client = &c->addr_text; ctx->session = s; c->log->connection = c->number; c->log->handler = ngx_tcp_log_error_msg; c->log->data = ctx; c->log->action = "sending client greeting line"; c->log_error = NGX_ERROR_INFO; #if (NGX_TCP_SSL) { ngx_tcp_ssl_conf_t *sslcf; sslcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_ssl_module); if (sslcf->enable) { c->log->action = "SSL handshaking"; ngx_tcp_ssl_init_connection(&sslcf->ssl, c); return; } if (addr_conf->ssl) { c->log->action = "SSL handshaking"; if (sslcf->ssl.ctx == NULL) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no \"ssl_certificate\" is defined " "in server listening on SSL port"); ngx_tcp_close_connection(c); return; } ngx_tcp_ssl_init_connection(&sslcf->ssl, c); return; } } #endif ngx_tcp_init_session(c); }
static void ngx_tcp_websocket_init_upstream(ngx_connection_t *c, ngx_tcp_session_t *s) { ngx_tcp_upstream_t *u; ngx_tcp_path_upstream_t *pu; ngx_tcp_upstream_conf_t *ucf; ngx_tcp_websocket_ctx_t *wctx; ngx_tcp_websocket_conf_t *wcf; ngx_tcp_virtual_server_t *vs; s->connection->log->action = "ngx_tcp_websocket_init_upstream"; wctx = ngx_tcp_get_module_ctx(s, ngx_tcp_websocket_module); vs = ngx_tcp_websocket_find_virtual_server(s, wctx); if (vs) { s->main_conf = vs->ctx->main_conf; s->srv_conf = vs->ctx->srv_conf; } wcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_websocket_module); if (wcf->upstream.upstream == NULL) { ngx_tcp_finalize_session(s); return; } ngx_log_debug3(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "tcp websocket init upstream, scheme: \"%V\" " "path: \"%V\", host: \"%V\"", &wcf->scheme, &wctx->path, &wctx->host); c->write->handler = ngx_tcp_websocket_dummy_write_handler; c->read->handler = ngx_tcp_websocket_dummy_read_handler; if (ngx_tcp_upstream_create(s) != NGX_OK) { ngx_tcp_finalize_session(s); return; } u = s->upstream; u->conf = &wcf->upstream; pu = ngx_tcp_websocket_find_path_upstream(s, wctx); if (pu) { ucf = ngx_palloc(s->pool, sizeof(ngx_tcp_upstream_conf_t)); if (ucf == NULL) { ngx_tcp_finalize_session(s); return; } ngx_memcpy(ucf, &wcf->upstream, sizeof(ngx_tcp_upstream_conf_t)); ucf->upstream = pu->upstream; u->conf = ucf; } u->write_event_handler = ngx_tcp_upstream_websocket_proxy_init_handler; u->read_event_handler = ngx_tcp_upstream_websocket_proxy_init_handler; wctx->upstream = &u->peer; wctx->buffer = ngx_create_temp_buf(s->connection->pool, (s->buffer->end - s->buffer->start)); if (wctx->buffer == NULL) { ngx_tcp_finalize_session(s); return; } /* move back to the start position, send the handshake * packet to backend server */ s->buffer->pos = s->buffer->start; s->connection->read->ready = 1; ngx_tcp_upstream_init(s); return; }
static void ngx_tcp_upstream_websocket_proxy_init_handler(ngx_tcp_session_t *s, ngx_tcp_upstream_t *u) { ngx_connection_t *c; ngx_tcp_websocket_ctx_t *wctx; ngx_tcp_websocket_conf_t *wcf; c = s->connection; c->log->action = "ngx_tcp_upstream_websocket_proxy_init_handler"; ngx_log_debug0(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "tcp upstream websocket proxy init handler"); wcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_websocket_module); wctx = ngx_tcp_get_module_ctx(s, ngx_tcp_websocket_module); if (wcf == NULL || wctx == NULL) { ngx_tcp_finalize_session(s); return; } wctx->upstream = &s->upstream->peer; c = wctx->upstream->connection; if (c->read->timedout || c->write->timedout) { ngx_tcp_upstream_next(s, u, NGX_TCP_UPSTREAM_FT_TIMEOUT); return; } if (ngx_tcp_upstream_check_broken_connection(s) != NGX_OK){ ngx_tcp_upstream_next(s, u, NGX_TCP_UPSTREAM_FT_ERROR); return; } s->connection->read->handler = ngx_tcp_websocket_proxy_handler; s->connection->write->handler = ngx_tcp_websocket_proxy_handler; c->read->handler = ngx_tcp_websocket_proxy_handler; c->write->handler = ngx_tcp_websocket_proxy_handler; ngx_add_timer(c->read, wcf->upstream.read_timeout); ngx_add_timer(c->write, wcf->upstream.send_timeout); #if (NGX_TCP_SSL) if (s->connection->ssl) { ngx_tcp_websocket_proxy_handler(s->connection->read); return; } #endif if (ngx_handle_read_event(s->connection->read, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } ngx_tcp_websocket_proxy_handler(s->connection->read); return; }