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); }
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_upstream_resolve_handler(ngx_resolver_ctx_t *ctx) { ngx_tcp_session_t *s; ngx_tcp_upstream_resolved_t *ur; s = ctx->data; s->upstream->resolved->ctx = NULL; if (ctx->state) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "%V could not be resolved (%i: %s)", &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); ngx_resolve_name_done(ctx); ngx_tcp_finalize_session(s); return; } ur = s->upstream->resolved; ur->naddrs = ctx->naddrs; ur->addrs = ctx->addrs; #if (NGX_DEBUG) { in_addr_t addr; ngx_uint_t i; for (i = 0; i < ctx->naddrs; i++) { addr = ntohl(ur->addrs[i]); ngx_log_debug4(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "name was resolved to %ud.%ud.%ud.%ud", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); } } #endif if (ngx_tcp_upstream_create_round_robin_peer(s, ur) != NGX_OK) { ngx_resolve_name_done(ctx); ngx_tcp_finalize_session(s); return; } ngx_resolve_name_done(ctx); ngx_tcp_upstream_connect(s, s->upstream); /*need add the event.*/ }
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_protocol(ngx_event_t *ev) { ngx_connection_t *c; ngx_tcp_session_t *s; ngx_tcp_websocket_ctx_t *wctx; c = ev->data; s = c->data; wctx = ngx_tcp_get_module_ctx(s, ngx_tcp_websocket_module); wctx->parser = ngx_pcalloc(s->connection->pool, sizeof(http_request_parser)); if (wctx->parser == NULL) { ngx_tcp_finalize_session(s); return; } websocket_http_request_parser_init(wctx->parser, s); c->read->handler = ngx_tcp_websocket_parse_protocol; ngx_tcp_websocket_parse_protocol(ev); }
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; }
static void ngx_tcp_upstream_finalize_session(ngx_tcp_session_t *s, ngx_tcp_upstream_t *u, ngx_int_t rc) { ngx_time_t *tp; ngx_log_debug1(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "finalize tcp upstream session: %i", rc); if (u->cleanup) { *u->cleanup = NULL; u->cleanup = NULL; } if (u->state && u->state->response_sec) { tp = ngx_timeofday(); u->state->response_sec = tp->sec - u->state->response_sec; u->state->response_msec = tp->msec - u->state->response_msec; } if (u->peer.free) { u->peer.free(&u->peer, u->peer.data, 0); } if (u->peer.check_index != NGX_INVALID_INDEX) { ngx_tcp_check_free_peer(u->peer.check_index); u->peer.check_index = NGX_INVALID_INDEX; } if (u->peer.connection) { ngx_log_debug1(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "close tcp upstream connection: %d", u->peer.connection->fd); ngx_close_connection(u->peer.connection); } u->peer.connection = NULL; if (rc == NGX_DECLINED || rc == NGX_DONE) { return; } s->connection->log->action = "sending to client"; ngx_tcp_finalize_session(s); }
static void ngx_tcp_proxy_dummy_read_handler(ngx_event_t *rev) { ngx_connection_t *c; ngx_tcp_session_t *s; c = rev->data; s = c->data; ngx_log_debug1(NGX_LOG_DEBUG_TCP, rev->log, 0, "tcp proxy dummy read handler: %d", c->fd); if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_tcp_finalize_session(s); } }
static void ngx_tcp_websocket_dummy_write_handler(ngx_event_t *wev) { ngx_connection_t *c; ngx_tcp_session_t *s; c = wev->data; s = c->data; ngx_log_debug1(NGX_LOG_DEBUG_TCP, wev->log, 0, "tcp websocket dummy write handler: %d", c->fd); if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_tcp_finalize_session(s); } }
static void ngx_tcp_lua_dummy_read_handler(ngx_tcp_session_t *s) { ngx_connection_t *c; ngx_event_t *rev; c = s->connection; rev = c->write; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "tcp lua dummy read handler: %d", c->fd); if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_tcp_finalize_session(s); } }
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 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 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; }
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_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; } }
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; }
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_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); }