static ngx_tcp_virtual_server_t * ngx_tcp_websocket_find_virtual_server(ngx_tcp_session_t *s, ngx_tcp_websocket_ctx_t *ctx) { ngx_uint_t hash, i; ngx_tcp_core_main_conf_t *cmcf; ngx_tcp_virtual_server_t *vs; cmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_core_module); if (ctx->host.len == 0) { return NULL; } hash = ngx_hash_key(ctx->host.data, ctx->host.len); vs = cmcf->virtual_servers.elts; for (i = 0; i < cmcf->virtual_servers.nelts; i++) { if (vs[i].hash != hash) { continue; } if ((vs[i].name.len != ctx->host.len) || ngx_memcmp(vs[i].name.data, ctx->host.data, ctx->host.len) != 0){ continue; } return &vs[i]; } return NULL; }
static ngx_int_t ngx_tcp_cmd_tran_handler(ngx_tcp_ctx_t *ctx, const u_char *pkg, int pkg_len) { ngx_tcp_cmd_pkghead_t *pkghead; ngx_tcp_cmd_pkgtran_t *pkgtran; uint32_t pkg_size; ngx_tcp_cmd_session_t *s; ngx_connection_t *c; ngx_tcp_cmd_session_t *dest_s; ngx_tcp_core_main_conf_t *cmcf; socketfd_info_t *socketfd_info; s = ctx->ngx_tcp_session; c = s->parent.connection; if (ngx_rstrncmp((u_char *)"unix:", c->addr_text.data, sizeof("unix:") - 1) != 0) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "ngx_tcp_cmd_tran_handler|cli=%V\n", &c->addr_text); return NGX_OK; } cmcf = ngx_tcp_get_module_main_conf(((ngx_tcp_session_t *)s), ngx_tcp_core_module); pkghead = (ngx_tcp_cmd_pkghead_t *)(pkg); pkgtran = (ngx_tcp_cmd_pkgtran_t *)(pkghead + 1); pkg_size = pkgtran->data_size; socketfd_info = cmcf->socketfd_shm->info->socketfd_info + pkgtran->dest_fd; dest_s = (ngx_tcp_cmd_session_t *)(socketfd_info->tag); if (dest_s == NULL) { ngx_log_error(NGX_LOG_ERR, s->parent.connection->log, 0, "ngx_tcp_cmd_tran_handler|dest_s=NULL|dest_fd=%d|dest_pid=%d\n", pkgtran->dest_fd, pkgtran->dest_pid); return NGX_OK; } if (dest_s->parent.connection == NULL || pkgtran->dest_fd <= 2) { ngx_log_error(NGX_LOG_ERR, s->parent.connection->log, 0, "ngx_tcp_cmd_tran_handler|dest_c=%p|dest_fd=%d\n", dest_s->parent.connection, pkgtran->dest_fd); return NGX_OK; } if (ngx_pid != pkgtran->dest_pid || ngx_process_slot != socketfd_info->listening_unix_info_i || pkgtran->dest_fd != dest_s->parent.connection->fd) { ngx_log_error(NGX_LOG_ERR, s->parent.connection->log, 0, "ngx_tcp_cmd_tran_handler|conn fd=%d|dest_fd=%d" "|ngx_process_slot=%d|listening_unix_info_i=%d" "|dest_pid=%d|ngx_pid=%d\n", dest_s->parent.connection->fd, pkgtran->dest_fd, ngx_process_slot, socketfd_info->listening_unix_info_i, pkgtran->dest_pid, ngx_pid); return NGX_OK; } ngx_tcp_send_data(&dest_s->parent.tcp_ctx, pkgtran->data, pkg_size); return NGX_OK; }
void ngx_tcp_lua_req_resume(ngx_tcp_session_t *s) { int nret = 0; ngx_int_t rc; ngx_connection_t *c; ngx_tcp_lua_ctx_t *ctx; ngx_tcp_lua_main_conf_t *lmcf; c = s->connection; ctx = s->ctx; if (ctx->prepare_retvals) { nret = ctx->prepare_retvals(s,ctx->co); ctx->prepare_retvals = NULL; } lmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_lua_module); dd("about to run thread for %p ", s); rc = ngx_tcp_lua_run_thread(lmcf->lua, s, ctx, nret); ngx_log_debug1(NGX_LOG_DEBUG_TCP, c->log, 0, "lua run thread returned %d", rc); if (rc == NGX_ERROR || rc == NGX_OK) { ngx_tcp_lua_close_session(s); return; } //NGX_AGAIN return; }
static ngx_int_t ngx_tcp_process_init(ngx_cycle_t *cycle) { ngx_int_t rc; ngx_tcp_core_main_conf_t *cmcf; ngx_tcp_conf_ctx_t *ctx; ngx_listening_t *ls; ngx_connection_t *c; ngx_event_t *rev; ngx_tcp_port_t *mport; ngx_tcp_in_addr_t *addrs; rc = ngx_tcp_instruct_unix_listen(cycle); if (NGX_OK != rc) { return rc; } ctx = (ngx_tcp_conf_ctx_t *)ngx_get_conf(cycle->conf_ctx, ngx_tcp_module); cmcf = ngx_tcp_get_module_main_conf(ctx, ngx_tcp_core_module); ls = cmcf->ls; rc = ngx_tcp_open_listening_socket(ls); if (NGX_OK != rc) { return rc; } mport = ngx_palloc(cycle->pool, sizeof(ngx_tcp_port_t)); if (mport == NULL) { return NGX_ERROR; } mport->naddrs = 1; mport->addrs = ngx_pcalloc(cycle->pool, mport->naddrs * sizeof(ngx_tcp_in_addr_t)); if (mport->addrs == NULL) { return NGX_ERROR; } addrs = mport->addrs; addrs->conf.ctx = ctx; addrs->conf.addr_text= cmcf->unix_url; ls->servers = mport; if (cmcf->error_log == NULL) { ls->logp = cycle->log; } else { ls->logp = cmcf->error_log; } ls->log = *(ls->logp); ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; c = ngx_get_connection(ls->fd, cycle->log); // c->log = &ls->log; c->log = ls->logp; c->listening = ls; ls->connection = c; rev = c->read; rev->log = c->log; rev->accept = 1; #if (NGX_HAVE_DEFERRED_ACCEPT) rev->deferred_accept = ls->deferred_accept; #endif rev->handler = ngx_event_accept; if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { if (ngx_add_conn(c) == NGX_ERROR) { return NGX_ERROR; } } else { if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } } return NGX_OK; }
static ngx_int_t ngx_tcp_instruct_unix_listen(ngx_cycle_t *cycle) { ngx_tcp_core_main_conf_t *cmcf; ngx_tcp_conf_ctx_t *ctx; unix_listening_info_t *unix_info; size_t len; ngx_listening_t *ls; ngx_url_t u; struct sockaddr *sa; u_char text[NGX_SOCKADDR_STRLEN + 1]; ctx = (ngx_tcp_conf_ctx_t *)ngx_get_conf(cycle->conf_ctx, ngx_tcp_module); cmcf = ngx_tcp_get_module_main_conf(ctx, ngx_tcp_core_module); ngx_memzero(&u, sizeof(ngx_url_t)); ngx_conf_full_name(cycle, &cmcf->unix_url, 0); /* ngx_pid to string len is less than 21 - strlen("unix:") */ u.url.data = ngx_pcalloc(cycle->pool, cmcf->unix_url.len + 21); ngx_sprintf(u.url.data, "%s%V%d", "unix:", &cmcf->unix_url, ngx_pid); u.url.len = ngx_strlen(u.url.data); u.listen = 1; cmcf->unix_url = u.url; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "ngx_tcp_instruct_unix_listen|unix_url=%V,len=%d", &u.url, u.url.len); if (ngx_parse_url(cycle->pool, &u) != NGX_OK) { if (u.err) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "%s in \"%V\" of the \"listen\" directive", u.err, &u.url); } return NGX_ERROR; } unix_info = cmcf->socketfd_shm->info->listening_unix_info + ngx_process_slot; ngx_memzero(unix_info, sizeof(unix_listening_info_t)); ngx_memcpy(unix_info, u.url.data, u.url.len); ls = ngx_pcalloc(cycle->pool, sizeof(ngx_listening_t)); if (ls == NULL) { goto failed; } sa = ngx_pcalloc(cycle->pool, u.socklen); if (sa == NULL) { goto failed; } ngx_memcpy(sa, u.sockaddr, u.socklen); ls->sockaddr = sa; ls->socklen = u.socklen; len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1); ls->addr_text.len = len; ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; len++; ls->addr_text.data = ngx_pcalloc(cycle->pool, len); if (ls->addr_text.data == NULL) { goto failed; } ngx_memcpy(ls->addr_text.data, text, len); ls->fd = (ngx_socket_t) -1; ls->type = SOCK_STREAM; ls->backlog = NGX_LISTEN_BACKLOG; ls->rcvbuf = -1; ls->sndbuf = -1; #if (NGX_HAVE_SETFIB) ls->setfib = -1; #endif ls->addr_ntop = 1; ls->handler = ngx_tcp_init_connection; ls->pool_size = 8192; ls->logp = &cycle->new_log; ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; cmcf->ls = ls; return NGX_OK; failed: return NGX_ERROR; }
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; } }
/** * Set nginx internal variable content * * @retval Always return a boolean on Lua stack. Return true when variable * content was modified successfully, false otherwise. * @seealso ngx_tcp_lua_var_get * */ static int ngx_tcp_lua_var_set(lua_State *L) { ngx_tcp_variable_t *v; ngx_tcp_variable_value_t *vv; ngx_tcp_core_main_conf_t *cmcf; u_char *p, *lowcase, *val; size_t len; ngx_str_t name; ngx_uint_t hash; ngx_tcp_session_t *s; int value_type; const char *msg; lua_pushlightuserdata(L, &ngx_tcp_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); s = lua_touserdata(L, -1); lua_pop(L, 1); if (s == NULL) { return luaL_error(L, "no request object found"); } /* we skip the first argument that is the table */ /* we read the variable name */ p = (u_char *) luaL_checklstring(L, 2, &len); lowcase = ngx_palloc(s->pool, len + 1); if (lowcase == NULL) { return luaL_error(L, "memory allocation error"); } lowcase[len] = '\0'; hash = ngx_hash_strlow(lowcase, p, len); name.len = len; name.data = lowcase; /* we read the variable new value */ value_type = lua_type(L, 3); switch (value_type) { case LUA_TNUMBER: case LUA_TSTRING: p = (u_char *) luaL_checklstring(L, 3, &len); val = ngx_palloc(s->pool, len); if (val == NULL) { return luaL_error(L, "memory allocation erorr"); } ngx_memcpy(val, p, len); break; case LUA_TNIL: /* undef the variable */ val = NULL; len = 0; break; default: msg = lua_pushfstring(L, "string, number, or nil expected, " "but got %s", lua_typename(L, value_type)); return luaL_argerror(L, 1, msg); } /* we fetch the variable itself */ cmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_core_module); v = ngx_hash_find(&cmcf->variables_hash, hash, name.data, name.len); if (v) { if (!(v->flags & NGX_TCP_VAR_CHANGEABLE)) { return luaL_error(L, "variable \"%s\" not changeable", lowcase); } if (v->set_handler) { dd("set variables with set_handler"); vv = ngx_palloc(s->pool, sizeof(ngx_tcp_variable_value_t)); if (vv == NULL) { return luaL_error(L, "out of memory"); } if (value_type == LUA_TNIL) { vv->valid = 0; vv->not_found = 1; vv->no_cacheable = 0; vv->data = NULL; vv->len = 0; } else { vv->valid = 1; vv->not_found = 0; vv->no_cacheable = 0; vv->data = val; vv->len = len; } v->set_handler(s, vv, v->data); return 0; } /*if (v->flags & NGX_TCP_VAR_INDEXED) { vv = &s->variables[v->index]; dd("set indexed variable"); if (value_type == LUA_TNIL) { vv->valid = 0; vv->not_found = 1; vv->no_cacheable = 0; vv->data = NULL; vv->len = 0; } else { vv->valid = 1; vv->not_found = 0; vv->no_cacheable = 0; vv->data = val; vv->len = len; } return 0; }*/ return luaL_error(L, "variable \"%s\" cannot be assigned a value", lowcase); } /* variable not found */ return luaL_error(L, "varaible \"%s\" not found for writing; " "maybe it is a built-in variable that is not changeable " "or you sould have used \"set $%s '';\" earlier " "in the config file", lowcase, lowcase); }
ngx_int_t ngx_tcp_regex_exec(ngx_tcp_session_t *s, ngx_tcp_regex_t *re, ngx_str_t *s) { ngx_int_t rc, index; ngx_uint_t i, n, len; ngx_tcp_variable_value_t *vv; ngx_tcp_core_main_conf_t *cmcf; cmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_core_module); if (re->ncaptures) { len = cmcf->ncaptures; if (r->captures == NULL) { r->captures = ngx_palloc(r->pool, len * sizeof(int)); if (r->captures == NULL) { return NGX_ERROR; } } } else { len = 0; } rc = ngx_regex_exec(re->regex, s, r->captures, len); if (rc == NGX_REGEX_NO_MATCHED) { return NGX_DECLINED; } if (rc < 0) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", rc, s, &re->name); return NGX_ERROR; } for (i = 0; i < re->nvariables; i++) { n = re->variables[i].capture; index = re->variables[i].index; vv = &r->variables[index]; vv->len = r->captures[n + 1] - r->captures[n]; vv->valid = 1; vv->no_cacheable = 0; vv->not_found = 0; vv->data = &s->data[r->captures[n]]; #if (NGX_DEBUG) { ngx_tcp_variable_t *v; v = cmcf->variables.elts; ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "tcp regex set $%V to \"%*s\"", &v[index].name, vv->len, vv->data); } #endif } r->ncaptures = rc * 2; r->captures_data = s->data; return NGX_OK; }
ngx_tcp_variable_value_t * ngx_tcp_get_variable(ngx_tcp_session_t *s, ngx_str_t *name, ngx_uint_t key) { ngx_tcp_variable_t *v; ngx_tcp_variable_value_t *vv; ngx_tcp_core_main_conf_t *cmcf; cmcf = ngx_tcp_get_module_main_conf(s, ngx_tcp_core_module); v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); if (v) { if (v->flags & NGX_TCP_VAR_INDEXED) { return NULL;//ngx_tcp_get_flushed_variable(r, v->index); } else { vv = ngx_palloc(s->pool, sizeof(ngx_tcp_variable_value_t)); if (vv && v->get_handler(s, vv, v->data) == NGX_OK) { return vv; } return NULL; } } vv = ngx_palloc(s->pool, sizeof(ngx_tcp_variable_value_t)); if (vv == NULL) { return NULL; } /*if (ngx_strncmp(name->data, "tcp_", 5) == 0) { if (ngx_tcp_variable_unknown_header_in(r, vv, (uintptr_t) name) == NGX_OK) { return vv; } return NULL; } if (ngx_strncmp(name->data, "sent_tcp_", 10) == 0) { if (ngx_tcp_variable_unknown_header_out(r, vv, (uintptr_t) name) == NGX_OK) { return vv; } return NULL; } if (ngx_strncmp(name->data, "upstream_tcp_", 14) == 0) { if (ngx_tcp_upstream_header_variable(r, vv, (uintptr_t) name) == NGX_OK) { return vv; } return NULL; }*/ vv->not_found = 1; return vv; }