static ngx_int_t ngx_stream_geoip_org_variable(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) { size_t len; char *val; ngx_stream_geoip_conf_t *gcf; gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module); if (gcf->org == NULL) { goto not_found; } #if (NGX_HAVE_GEOIP_V6) val = gcf->org_v6 ? GeoIP_name_by_ipnum_v6(gcf->org, ngx_stream_geoip_addr_v6(s, gcf)) : GeoIP_name_by_ipnum(gcf->org, ngx_stream_geoip_addr(s, gcf)); #else val = GeoIP_name_by_ipnum(gcf->org, ngx_stream_geoip_addr(s, gcf)); #endif if (val == NULL) { goto not_found; } len = ngx_strlen(val); v->data = ngx_pnalloc(s->connection->pool, len); if (v->data == NULL) { ngx_free(val); return NGX_ERROR; } ngx_memcpy(v->data, val, len); v->len = len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; ngx_free(val); return NGX_OK; not_found: v->not_found = 1; return NGX_OK; }
static mrb_value ngx_stream_mrb_connection_init(mrb_state *mrb, mrb_value self) { ngx_uint_t i; mrb_value upstream; ngx_stream_mruby_upstream_context *ctx; ngx_stream_upstream_main_conf_t *umcf; ngx_stream_upstream_srv_conf_t **usp; ngx_stream_mruby_internal_ctx_t *ictx = mrb->ud; ngx_stream_session_t *s = ictx->s; mrb_get_args(mrb, "o", &upstream); ctx = (ngx_stream_mruby_upstream_context *)DATA_PTR(self); if (ctx) { mrb_free(mrb, ctx); } DATA_TYPE(self) = &ngx_stream_mrb_upstream_context_type; DATA_PTR(self) = NULL; ctx = (ngx_stream_mruby_upstream_context *)mrb_malloc(mrb, sizeof(ngx_stream_mruby_upstream_context)); ctx->upstream = upstream; ctx->target = NULL; ctx->peers = NULL; ctx->us = NULL; umcf = ngx_stream_get_module_main_conf(s, ngx_stream_upstream_module); usp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { if (ngx_strncasecmp(usp[i]->host.data, (u_char *)RSTRING_PTR(upstream), RSTRING_LEN(upstream)) == 0) { ctx->us = usp[i]; ctx->peers = usp[i]->peer.data; if (ctx->peers->number > 1) { mrb_raise(mrb, E_RUNTIME_ERROR, "don't support multiple server config"); } ctx->target = ctx->peers->peer; break; } } DATA_PTR(self) = ctx; if (ctx->us == NULL || ctx->peers == NULL) { mrb_raisef(mrb, E_RUNTIME_ERROR, "%S not found upstream config", upstream); } if (ctx->target == NULL) { mrb_raise(mrb, E_RUNTIME_ERROR, "not found server config in upstream"); } return self; }
ngx_stream_variable_value_t * ngx_stream_get_indexed_variable(ngx_stream_session_t *s, ngx_uint_t index) { ngx_stream_variable_t *v; ngx_stream_core_main_conf_t *cmcf; cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); if (cmcf->variables.nelts <= index) { ngx_log_error(NGX_LOG_ALERT, s->connection->log, 0, "unknown variable index: %ui", index); return NULL; } if (s->variables[index].not_found || s->variables[index].valid) { return &s->variables[index]; } v = cmcf->variables.elts; if (ngx_stream_variable_depth == 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "cycle while evaluating variable \"%V\"", &v[index].name); return NULL; } ngx_stream_variable_depth--; if (v[index].get_handler(s, &s->variables[index], v[index].data) == NGX_OK) { ngx_stream_variable_depth++; if (v[index].flags & NGX_STREAM_VAR_NOCACHEABLE) { s->variables[index].no_cacheable = 1; } return &s->variables[index]; } ngx_stream_variable_depth++; s->variables[index].valid = 0; s->variables[index].not_found = 1; return NULL; }
static ngx_int_t ngx_stream_geoip_country_variable(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) { ngx_stream_geoip_variable_handler_pt handler = ngx_stream_geoip_country_functions[data]; #if (NGX_HAVE_GEOIP_V6) ngx_stream_geoip_variable_handler_v6_pt handler_v6 = ngx_stream_geoip_country_v6_functions[data]; #endif const char *val; ngx_stream_geoip_conf_t *gcf; gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module); if (gcf->country == NULL) { goto not_found; } #if (NGX_HAVE_GEOIP_V6) val = gcf->country_v6 ? handler_v6(gcf->country, ngx_stream_geoip_addr_v6(s, gcf)) : handler(gcf->country, ngx_stream_geoip_addr(s, gcf)); #else val = handler(gcf->country, ngx_stream_geoip_addr(s, gcf)); #endif if (val == NULL) { goto not_found; } v->len = ngx_strlen(val); v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = (u_char *) val; return NGX_OK; not_found: v->not_found = 1; return NGX_OK; }
ngx_stream_variable_value_t * ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, ngx_uint_t key) { ngx_stream_variable_t *v; ngx_stream_variable_value_t *vv; ngx_stream_core_main_conf_t *cmcf; cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); if (v) { if (v->flags & NGX_STREAM_VAR_INDEXED) { return ngx_stream_get_flushed_variable(s, v->index); } if (ngx_stream_variable_depth == 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "cycle while evaluating variable \"%V\"", name); return NULL; } ngx_stream_variable_depth--; vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t)); if (vv && v->get_handler(s, vv, v->data) == NGX_OK) { ngx_stream_variable_depth++; return vv; } ngx_stream_variable_depth++; return NULL; } vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t)); if (vv == NULL) { return NULL; } vv->not_found = 1; return vv; }
void ngx_stream_core_run_phases(ngx_stream_session_t *s) { ngx_int_t rc; ngx_stream_phase_handler_t *ph; ngx_stream_core_main_conf_t *cmcf; cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); ph = cmcf->phase_engine.handlers; while (ph[s->phase_handler].checker) { rc = ph[s->phase_handler].checker(s, &ph[s->phase_handler]); if (rc == NGX_OK) { return; } } }
static GeoIPRecord * ngx_stream_geoip_get_city_record(ngx_stream_session_t *s) { ngx_stream_geoip_conf_t *gcf; gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module); if (gcf->city) { #if (NGX_HAVE_GEOIP_V6) return gcf->city_v6 ? GeoIP_record_by_ipnum_v6(gcf->city, ngx_stream_geoip_addr_v6(s, gcf)) : GeoIP_record_by_ipnum(gcf->city, ngx_stream_geoip_addr(s, gcf)); #else return GeoIP_record_by_ipnum(gcf->city, ngx_stream_geoip_addr(s, gcf)); #endif } return NULL; }
// 在ngx_stream_optimize_servers里设置有连接发生时的回调函数 // 调用发生在ngx_event_accept.c:ngx_event_accept() // // 创建一个处理tcp的会话对象 // 要先检查限速和访问限制这两个功能模块 // 最后调用ngx_stream_init_session // 创建ctx数组,用于存储模块的ctx数据 // 调用handler,处理tcp数据,收发等等 void ngx_stream_init_connection(ngx_connection_t *c) { int tcp_nodelay; u_char text[NGX_SOCKADDR_STRLEN]; size_t len; ngx_int_t rc; ngx_uint_t i; struct sockaddr *sa; ngx_stream_port_t *port; struct sockaddr_in *sin; ngx_stream_in_addr_t *addr; ngx_stream_session_t *s; ngx_stream_addr_conf_t *addr_conf; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; ngx_stream_in6_addr_t *addr6; #endif ngx_stream_core_srv_conf_t *cscf; ngx_stream_core_main_conf_t *cmcf; /* find the server configuration for the address:port */ // 取监听同一端口的server信息 port = c->listening->servers; if (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_stream_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 { // 唯一监听端口的server // addr_conf就是端口所在的server的配置数组 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; } } // 创建一个处理tcp的会话对象 s = ngx_pcalloc(c->pool, sizeof(ngx_stream_session_t)); if (s == NULL) { ngx_stream_close_connection(c); return; } // 设置会话对象的标志 s->signature = NGX_STREAM_MODULE; //设置会话正确的配置结构体 // addr_conf就是端口所在的server的配置数组 // 之后就可以用宏正确地获取模块的配置信息 s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; // 设置会话关联的连接对象 s->connection = c; // 连接的data指针指向会话对象 c->data = s; // 获取相关的core配置 cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); ngx_set_connection_log(c, cscf->error_log); len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V", c->number, len, text, &addr_conf->addr_text); // log的一些参数 c->log->connection = c->number; c->log->handler = ngx_stream_log_error; c->log->data = s; c->log->action = "initializing connection"; c->log_error = NGX_ERROR_INFO; // 一个stream{}块只能有一个main conf // 所以连接限速、访问限制的处理函数是相同的 // 但配置参数每个server可以不同 cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); // 是否有连接限速设置,在ngx_stream_limit_conn_module.c里设置 if (cmcf->limit_conn_handler) { rc = cmcf->limit_conn_handler(s); if (rc != NGX_DECLINED) { ngx_stream_close_connection(c); return; } } // 是否有访问限制 if (cmcf->access_handler) { rc = cmcf->access_handler(s); if (rc != NGX_OK && rc != NGX_DECLINED) { ngx_stream_close_connection(c); return; } } // 设置TCP_NODELAY,默认启用 if (cscf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "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_stream_close_connection(c); return; } c->tcp_nodelay = NGX_TCP_NODELAY_SET; } #if (NGX_STREAM_SSL) { ngx_stream_ssl_conf_t *sslcf; sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); 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_stream_close_connection(c); return; } ngx_stream_ssl_init_connection(&sslcf->ssl, c); return; } } #endif // 创建ctx数组,用于存储模块的ctx数据 // 调用handler,处理tcp数据,收发等等 ngx_stream_init_session(c); }
ngx_int_t ngx_stream_upm_create_request(ngx_stream_session_t *s) { ngx_int_t len, uri_len; ngx_str_t method, uri; ngx_buf_t *request_buf, *b; //ngx_stream_upm_ctx_t *ctx; //ngx_stream_upstream_t *u; ngx_stream_upm_main_conf_t *ummcf; ummcf = ngx_stream_get_module_main_conf(s, ngx_stream_upm_module); //u = s->upstream; if (ummcf->request_prepared) { return NGX_OK; } if (ummcf->method.len) { method = ummcf->method; } else { method.data = (u_char *)"GET"; method.len = 3; } //ctx = ngx_stream_get_module_ctx(s, ngx_stream_upm_module); //GET xx_uri VERSION\r\n len = method.len + 1 + sizeof(ngx_stream_upm_http_version_11) - 1 + sizeof(CRLF) - 1; uri_len = ummcf->um_url->uri.len; len += uri_len; uri = ummcf->um_url->uri; //Only one header: "Connection: keep-alive\r\n"; len += 24; //The end \r\n; len += 2; request_buf = &s->upstream->downstream_buf; b = request_buf; /* the request line */ b->last = ngx_copy(b->last, method.data, method.len); *b->last++ = ' '; b->last = ngx_copy(b->last, uri.data, uri.len); /*default use the HTTP/1.1 */ b->last = ngx_cpymem(b->last, ngx_stream_upm_http_version_11, sizeof(ngx_stream_upm_http_version_11) - 1); b->last = ngx_copy(b->last, "Connection: keep-alive\r\n", 24); /* add "\r\n" at the header end */ *b->last++ = CR; *b->last++ = LF; ngx_log_debug2(NGX_LOG_DEBUG_STREAM, r->connection->log, 0, "stream upm header:%N\"%*s\"", (size_t) (b->last - b->pos), b->pos); /*Currently without any body;*/ b->flush = 1; return NGX_OK; }
ngx_int_t ngx_stream_upm_parse_resp_body(ngx_stream_session_t *s) { int port, fail_timeout, max_fail, weight, ta[1024]; char *upname, *host, *t; cJSON *jsroot, *service, *jinsts, *jinst, *tags; ngx_buf_t *b; ngx_uint_t i, j, p, st, sfound, ifound; ngx_conf_t cf; //ngx_pool_t *pool; ngx_array_t *servs, *upstreams; ngx_connection_t *pc; ngx_stream_upstream_t *u; ngx_stream_upm_ctx_t *ctx; ngx_stream_upm_service_t *ums; ngx_stream_upm_main_conf_t *ummcf; ngx_stream_upm_service_inst_t *umsi; ngx_stream_upstream_init_pt init; ngx_stream_upstream_server_t *us; ngx_stream_upstream_srv_conf_t *uscf; ngx_stream_upstream_main_conf_t *umcf; ctx = ngx_stream_get_module_ctx(s, ngx_stream_upm_module); ummcf = ngx_stream_get_module_srv_conf(s, ngx_stream_upm_module); umcf = ngx_stream_get_module_main_conf(s, ngx_stream_upstream_module); upstreams = &umcf->upstreams; b = ctx->resp_body; u = s->upstream; pc = u->peer.connection; /* start to parse the JSON body; */ jsroot = cJSON_Parse((char *)b->start); if (jsroot == NULL) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "upm json parse failed"); return ERR_JSON; } /* start to parse the JSON; */ service = jsroot->child; if (service == NULL) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "upm json with empty service list"); return ERR_JSON; } /*service array */ servs = ngx_array_create(ctx->pool, 16, sizeof(ngx_stream_upm_service_t)); if (servs == NULL) { return NGX_ERROR; } while( service != NULL ) { //Got the service name; upname = service->string; //Got the service related instance; jinsts = service->child; if (jinsts == NULL || jinsts->child == NULL) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "upm service: %s without any instance", upname); } ums = ngx_array_push(servs); if (ums == NULL) { return NGX_ERROR; } ums->service_name.len = ngx_strlen(upname); ums->service_name.data = ngx_pcalloc(ctx->pool, ums->service_name.len); ngx_memcpy(ums->service_name.data, upname, ums->service_name.len); ums->insts = ngx_array_create(ctx->pool, 16, sizeof(ngx_stream_upm_service_inst_t)); if (ums->insts == NULL) { return NGX_ERROR; } //travers all the instance jinst = jinsts; while (jinst != NULL) { //FIXME need check the Item isn't exists; host = cJSON_GetObjectItem(jinst, "Host")->valuestring; port = cJSON_GetObjectItem(jinst, "Port")->valueint; tags = cJSON_GetObjectItem(jinst, "Tags"); fail_timeout = cJSON_GetObjectItem(tags, "fail_timeout")->valueint; max_fail = cJSON_GetObjectItem(tags, "max_fails")->valueint; weight = cJSON_GetObjectItem(tags, "weight")->valueint; umsi = ngx_array_push(ums->insts); if (umsi == NULL) { return NGX_ERROR; } i = ngx_strlen(host); //Here, ip:port, Max port is 65535 umsi->name.data = ngx_pcalloc(ctx->pool, (i + 5) * sizeof(char)); t = (char *)ngx_snprintf(umsi->name.data, i + 5, "%s:%d", (char *)host, port); umsi->name.len = t - (char *)umsi->name.data; umsi->host.data = (u_char *)host; umsi->host.len = i; umsi->port = port; umsi->fail_timeout = fail_timeout; umsi->max_fail = max_fail; umsi->weight = weight; jinst = jinst->next; } service = service->next; } //Process the upstream msg, check wether we need to update the server; cf.name = "ngx_stream_upm_module"; //Here, we create a memory pool, Only use to the upstream init peer; cf.pool = ngx_create_pool(8192, pc->log); cf.module_type = NGX_STREAM_MODULE; cf.cmd_type = NGX_STREAM_SRV_CONF; cf.log = pc->log; if (ummcf->pool == NULL) { ummcf->pool = cf.pool; } else { //pool = cf.pool; ummcf->pool = cf.pool; } for (i = 0; i < servs->nelts; i++) { ums = &((ngx_stream_upm_service_t *)(servs->elts))[i]; sfound = 0; /*First: find the upstream name */ uscf = NULL; for (j = 0; j < upstreams->nelts; j++) { uscf = &((ngx_stream_upstream_srv_conf_t *)upstreams->elts)[j]; if (uscf->host.len == ums->service_name.len && ngx_strncmp(uscf->host.data, ums->service_name.data, uscf->host.len) == 0) { sfound = 1; } } if (sfound == 1) { //reset the temporary array to zero; //the elt == 1, Means update; //the elt == 2, Means create; //the elt == 0, Means need set this server to down; memset(ta, 0, sizeof(ta)); us = NULL; for (p = 0; p < ums->insts->nelts; p++) { umsi = &((ngx_stream_upm_service_inst_t *)ums->insts->elts)[p]; ifound = 0; for (st = 0; st < uscf->servers->nelts; st++) { us = &((ngx_stream_upstream_server_t *)uscf->servers->elts)[st]; if(us->name.len == umsi->name.len && ngx_strncmp(us->name.data, umsi->name.data, us->name.len ) == 0) { ifound = 1; } } //Means server already exists; if (ifound == 1) { us->weight = umsi->weight; us->max_fails = umsi->max_fail; us->fail_timeout = umsi->fail_timeout; us->backup = umsi->backup; us->down = umsi->down; ta[st] = 1; //insert the server; } else { us = ngx_array_push(uscf->servers); us->weight = umsi->weight; us->max_fails = umsi->max_fail; us->fail_timeout = umsi->fail_timeout; us->backup = umsi->backup; us->down = umsi->down; ta[st] = 2; } } for (st = 0; st < uscf->servers->nelts; st++) { us = &((ngx_stream_upstream_server_t *)uscf->servers->elts)[st]; if (ta[st] == 0) { //FIXME: Only set this server to down, // If the backend change very quikly, there are too many down server list; us->down = 1; } } /*Reinit the upstream servers*/ init = uscf->peer.init_upstream ? uscf->peer.init_upstream: ngx_stream_upstream_init_round_robin; if (init(&cf, uscf) != NGX_OK) { return NGX_ERROR; } } else { //TODO: doesn't support auto discovery the service name? //Need alloc the memory from the global; ngx_log_error(NGX_LOG_ERR, pc->log, 0, "config server return uninitilized usptreams: %V", &ums->service_name); } } /*Update the upstream weight*/ return NGX_OK; }
void ngx_stream_init_connection(ngx_connection_t *c) { u_char text[NGX_SOCKADDR_STRLEN]; size_t len; ngx_int_t rc; ngx_uint_t i; struct sockaddr *sa; ngx_stream_port_t *port; struct sockaddr_in *sin; ngx_stream_in_addr_t *addr; ngx_stream_session_t *s; ngx_stream_addr_conf_t *addr_conf; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; ngx_stream_in6_addr_t *addr6; #endif ngx_stream_core_srv_conf_t *cscf; ngx_stream_core_main_conf_t *cmcf; /* 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 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_stream_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 default: /* AF_INET */ addr = port->addrs; addr_conf = &addr[0].conf; break; } } s = ngx_pcalloc(c->pool, sizeof(ngx_stream_session_t)); if (s == NULL) { ngx_stream_close_connection(c); return; } s->signature = NGX_STREAM_MODULE; s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; s->connection = c; c->data = s; cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); ngx_set_connection_log(c, cscf->error_log); len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V", c->number, len, text, &addr_conf->addr_text); c->log->connection = c->number; c->log->handler = ngx_stream_log_error; c->log->data = s; c->log->action = "initializing connection"; c->log_error = NGX_ERROR_INFO; cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); if (cmcf->access_handler) { rc = cmcf->access_handler(s); if (rc != NGX_OK && rc != NGX_DECLINED) { ngx_stream_close_connection(c); return; } } #if (NGX_STREAM_SSL) { ngx_stream_ssl_conf_t *sslcf; sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); 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_stream_close_connection(c); return; } ngx_stream_ssl_init_connection(&sslcf->ssl, c); return; } } #endif ngx_stream_init_session(c); }
/* static void ngx_app_empty_handler(ngx_event_t *wev) { } */ static void ngx_app_wait_request_handler(ngx_event_t *ev) { ngx_connection_t *c; ngx_stream_session_t *s; ngx_stream_app_main_conf_t *cscf; ngx_stream_app_srv_conf_t *ascf; ngx_stream_app_ctx_t *s_ctx; ngx_app_task_t *t; ngx_buf_t *b; ngx_str_t log_buf; ssize_t n; size_t size; u_char *tmp; c = ev->data; s = c->data; if (ev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); ngx_stream_close_connection(c); return; } if (c->close) { ngx_stream_close_connection(c); return; } cscf = ngx_stream_get_module_main_conf(s, ngx_stream_app_module); ascf = ngx_stream_get_module_srv_conf(s, ngx_stream_app_module); s_ctx = ngx_stream_get_module_ctx(s,ngx_stream_app_module); if(s_ctx == NULL){ s_ctx = ngx_palloc(c->pool, sizeof(ngx_stream_app_ctx_t)); if(s_ctx == NULL) return; s_ctx->header = 0; ngx_stream_set_ctx(s,s_ctx,ngx_stream_app_module); } b = c->buffer; if (b == NULL) { size = ascf->header_len; b = ngx_create_temp_buf(c->pool, size); if (b == NULL) { ngx_stream_close_connection(c); return; } c->buffer = b; } else if (b->start == NULL) { size = s_ctx->header == 0?ascf->header_len:s_ctx->body_len; b->start = ngx_palloc(c->pool, size); if (b->start == NULL) { ngx_stream_close_connection(c); return; } b->pos = b->start; b->last = b->start; b->end = b->last + size; } else { size = ascf->header_len + s_ctx->body_len - s->received; // size = b->end - b->last; } n = c->recv(c, b->last, size); if (n == NGX_AGAIN) { if (!c->read->timer_set) { ngx_add_timer(c->read, ascf->client_timeout); } if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_stream_close_connection(c); return; } return; } if (n == NGX_ERROR) { ngx_stream_close_connection(c); return; } if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection"); ngx_stream_close_connection(c); return; } b->last += n; s->received +=n; c->log->action = "reading client request line"; log_buf.len = s->received; log_buf.data = b->start; ngx_log_error(NGX_LOG_ALERT, c->log, 0, "%d recved [%V],[%d:%d]",n,&log_buf,b->end,b->last); if(b->end != b->last){ if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_stream_close_connection(c); return; } } else { if(s_ctx->header == 0){ s_ctx->body_len = ngx_atoi(b->start,ascf->header_len); s_ctx->header = 1; if(s_ctx->body_len > 0 ){ tmp = ngx_pcalloc(c->pool, ascf->header_len + s_ctx->body_len); if (tmp == NULL) { ngx_stream_close_connection(c); return; } ngx_memcpy(tmp,b->start,ascf->header_len); ngx_pfree(c->pool, b->start); b->start = tmp; b->pos = b->start + ascf->header_len; b->last = b->pos; b->end = b->last + s_ctx->body_len; ngx_app_wait_request_handler(ev); } else{ ngx_log_error(NGX_LOG_INFO, c->log, 0, "empty request body"); ngx_stream_close_connection(c); return; } ngx_log_error(NGX_LOG_ALERT, c->log, 0, "recv header,len[%d]",s_ctx->body_len); } else{ // c->read->handler = ngx_app_empty_handler; t = (ngx_app_task_t *)ngx_thread_task_alloc(c->pool, sizeof(ngx_app_task_t) - sizeof(ngx_thread_task_t)); if(t == NULL){ ngx_log_error(NGX_LOG_ERR, c->log, 0, "create thread task failed"); ngx_stream_close_connection(c); } t->data = s; t->task.handler = ngx_stream_app_process; t->task.event.handler = ngx_stream_app_finalize; t->task.event.data= c; ngx_log_error(NGX_LOG_ALERT, c->log, 0, "t->data[%d]=[%d][%d]",t->data,t->task.ctx,t); if(ngx_thread_task_post(cscf->tp,(ngx_thread_task_t *)t) != NGX_OK){ ngx_log_error(NGX_LOG_ERR, c->log, 0, "post task to thread pool failed"); ngx_stream_close_connection(c); return; } ngx_log_error(NGX_LOG_ALERT, c->log, 0, "after post task"); } } return; }
ngx_int_t ngx_stream_regex_exec(ngx_stream_session_t *s, ngx_stream_regex_t *re, ngx_str_t *str) { ngx_int_t rc, index; ngx_uint_t i, n, len; ngx_stream_variable_value_t *vv; ngx_stream_core_main_conf_t *cmcf; cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); if (re->ncaptures) { len = cmcf->ncaptures; if (s->captures == NULL) { s->captures = ngx_palloc(s->connection->pool, len * sizeof(int)); if (s->captures == NULL) { return NGX_ERROR; } } } else { len = 0; } rc = ngx_regex_exec(re->regex, str, s->captures, len); if (rc == NGX_REGEX_NO_MATCHED) { return NGX_DECLINED; } if (rc < 0) { ngx_log_error(NGX_LOG_ALERT, s->connection->log, 0, ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", rc, str, &re->name); return NGX_ERROR; } for (i = 0; i < re->nvariables; i++) { n = re->variables[i].capture; index = re->variables[i].index; vv = &s->variables[index]; vv->len = s->captures[n + 1] - s->captures[n]; vv->valid = 1; vv->no_cacheable = 0; vv->not_found = 0; vv->data = &str->data[s->captures[n]]; #if (NGX_DEBUG) { ngx_stream_variable_t *v; v = cmcf->variables.elts; ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream regex set $%V to \"%v\"", &v[index].name, vv); } #endif } s->ncaptures = rc * 2; s->captures_data = str->data; return NGX_OK; }
static mrb_state *ngx_stream_mrb_state(ngx_stream_session_t *s) { return ((ngx_stream_mruby_main_conf_t *)ngx_stream_get_module_main_conf(s, ngx_stream_mruby_module))->ctx->mrb; }
ngx_stream_variable_value_t * ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, ngx_uint_t key) { size_t len; ngx_uint_t i, n; ngx_stream_variable_t *v; ngx_stream_variable_value_t *vv; ngx_stream_core_main_conf_t *cmcf; cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); if (v) { if (v->flags & NGX_STREAM_VAR_INDEXED) { return ngx_stream_get_flushed_variable(s, v->index); } if (ngx_stream_variable_depth == 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "cycle while evaluating variable \"%V\"", name); return NULL; } ngx_stream_variable_depth--; vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t)); if (vv && v->get_handler(s, vv, v->data) == NGX_OK) { ngx_stream_variable_depth++; return vv; } ngx_stream_variable_depth++; return NULL; } vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t)); if (vv == NULL) { return NULL; } len = 0; v = cmcf->prefix_variables.elts; n = cmcf->prefix_variables.nelts; for (i = 0; i < cmcf->prefix_variables.nelts; i++) { if (name->len >= v[i].name.len && name->len > len && ngx_strncmp(name->data, v[i].name.data, v[i].name.len) == 0) { len = v[i].name.len; n = i; } } if (n != cmcf->prefix_variables.nelts) { if (v[n].get_handler(s, vv, (uintptr_t) name) == NGX_OK) { return vv; } return NULL; } vv->not_found = 1; return vv; }