ngx_int_t ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types, ngx_str_t *default_type) { ngx_hash_key_t *type; *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t)); if (*types == NULL) { return NGX_ERROR; } while (default_type->len) { type = ngx_array_push(*types); if (type == NULL) { return NGX_ERROR; } type->key = *default_type; type->key_hash = ngx_hash_key(default_type->data, default_type->len); type->value = (void *) 4; default_type++; } return NGX_OK; }
uint32_t dvt_cache_label_value_id_from_name(dvt_cache_t *cache, uint32_t label_id, ngx_str_t *name) { ngx_uint_t key_hash = ngx_hash_key(name->data, name->len); ngx_hash_t *sh = &(((ngx_hash_t *)cache->label_value_ids->elts)[label_id]); int64_t r = (uint64_t)ngx_hash_find(sh, key_hash, name->data, name->len) - ARBITRARY_OFFSET_TO_AVOID_PTR_EQ_NULL; return (uint32_t)r; }
static ngx_str_t * sc_for_req_get_header_vaule_by_hash(ngx_list_part_t *part, u_char *lowcase_key, size_t len) { ngx_uint_t i, hash; ngx_table_elt_t *header; hash = ngx_hash_key(lowcase_key, len); header = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].hash == hash) { return &header->value; } } return NULL; }
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_rtmp_play_leave(ngx_rtmp_session_t *s) { ngx_rtmp_play_ctx_t *ctx, **pctx; ngx_rtmp_play_app_conf_t *pacf; ngx_uint_t h; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: leave"); pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx == NULL || !ctx->joined) { return NGX_ERROR; } h = ngx_hash_key(ctx->name, ngx_strlen(ctx->name)); pctx = &pacf->ctx[h % pacf->nbuckets]; while (*pctx && *pctx != ctx) { pctx = &(*pctx)->next; } if (*pctx == NULL) { return NGX_ERROR; } *pctx = (*pctx)->next; ctx->joined = 0; return NGX_OK; }
static ngx_int_t ngx_tcp_add_virtual_servers(ngx_conf_t *cf, ngx_tcp_core_main_conf_t *cmcf, ngx_tcp_listen_t *listen) { ngx_tcp_core_srv_conf_t *cscf; ngx_tcp_virtual_server_t *vs; cscf = listen->conf; if (cscf == NULL || cscf->server_name.len == 0) { return NGX_OK; } vs = ngx_array_push(&cmcf->virtual_servers); if (vs == NULL) { return NGX_ERROR; } vs->name.len = cscf->server_name.len; vs->name.data = cscf->server_name.data; vs->hash = ngx_hash_key(vs->name.data, vs->name.len); vs->listen = listen; vs->ctx = listen->ctx; return NGX_OK; }
static ngx_int_t ngx_rtmp_play_join(ngx_rtmp_session_t *s) { ngx_rtmp_play_ctx_t *ctx, **pctx; ngx_rtmp_play_app_conf_t *pacf; ngx_uint_t h; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: join"); pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx == NULL || ctx->joined) { return NGX_ERROR; } h = ngx_hash_key(ctx->name, ngx_strlen(ctx->name)); pctx = &pacf->ctx[h % pacf->nbuckets]; while (*pctx) { if (!ngx_strncmp((*pctx)->name, ctx->name, NGX_RTMP_MAX_NAME)) { break; } pctx = &(*pctx)->next; } ctx->next = *pctx; *pctx = ctx; ctx->joined = 1; return NGX_OK; }
static ngx_int_t ngx_http_secure_cookie_md5_number(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { u_char *last; ngx_str_t number, val; ngx_uint_t hash; ngx_http_secure_cookie_conf_t *sclcf; sclcf = ngx_http_get_module_loc_conf(r, ngx_http_secure_cookie_module); if (sclcf == NULL) { goto not_found; } if (sclcf->md5_number == NULL) { goto not_found; } if (ngx_http_complex_value(r, sclcf->md5_number, &val) != NGX_OK) { goto not_found; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure cookie md5 number base string: \"%V\"", &val); if (val.len == 0) { goto not_found; } hash = ngx_hash_key(val.data, val.len); number.len = 32; number.data = ngx_pcalloc(r->pool, number.len); if (number.data == NULL) { goto not_found; } last = ngx_snprintf(number.data, number.len, "%ud", hash); number.len = last - number.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "secure cookie md5 number: \"%V\"", &number); v->len = number.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = number.data; return NGX_OK; not_found: v->not_found = 1; return NGX_OK; }
static jlong JNICALL jni_ngx_http_clojure_mem_get_variable(JNIEnv *env, jclass cls, jlong r, jlong nname, jlong varlenPtr) { ngx_http_request_t *req = (ngx_http_request_t *) r; ngx_str_t *name = (ngx_str_t *)nname; ngx_http_variable_value_t *vp = ngx_http_get_variable(req, name, ngx_hash_key(name->data, name->len)); if (vp->not_found) { return 0; } *((u_int *)varlenPtr) = vp->len; return (uintptr_t)vp; }
static ngx_int_t ngx_rtmp_relay_create(ngx_rtmp_session_t *s, ngx_str_t *name, ngx_rtmp_relay_target_t *target, ngx_rtmp_relay_create_ctx_pt create_publish_ctx, ngx_rtmp_relay_create_ctx_pt create_play_ctx) { ngx_rtmp_relay_app_conf_t *racf; ngx_rtmp_relay_ctx_t *publish_ctx, *play_ctx, **cctx; ngx_uint_t hash; racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_relay_module); if (racf == NULL) { return NGX_ERROR; } play_ctx = create_play_ctx(s, name, target); if (play_ctx == NULL) { return NGX_ERROR; } hash = ngx_hash_key(name->data, name->len); cctx = &racf->ctx[hash % racf->nbuckets]; for (; *cctx; cctx = &(*cctx)->next) { if ((*cctx)->name.len == name->len && !ngx_memcmp(name->data, (*cctx)->name.data, name->len)) { break; } } if (*cctx) { play_ctx->publish = (*cctx)->publish; play_ctx->next = (*cctx)->play; (*cctx)->play = play_ctx; return NGX_OK; } publish_ctx = create_publish_ctx(s, name, target); if (publish_ctx == NULL) { ngx_rtmp_finalize_session(play_ctx->session); return NGX_ERROR; } publish_ctx->publish = publish_ctx; publish_ctx->play = play_ctx; play_ctx->publish = publish_ctx; *cctx = publish_ctx; return NGX_OK; }
static ngx_int_t nchan_process_legacy_channel_id(ngx_http_request_t *r, nchan_loc_conf_t *cf, ngx_str_t **ret_id) { static ngx_str_t channel_id_var_name = ngx_string("push_channel_id"); ngx_uint_t key = ngx_hash_key(channel_id_var_name.data, channel_id_var_name.len); ngx_http_variable_value_t *vv = NULL; ngx_str_t *group = &cf->channel_group; ngx_str_t tmpid; ngx_str_t *id; size_t sz; u_char *cur; nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, nchan_module); ctx->channel_id_count = 0; vv = ngx_http_get_variable(r, &channel_id_var_name, key); if (vv == NULL || vv->not_found || vv->len == 0) { //ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "nchan: the legacy $push_channel_id variable is not set"); return NGX_ABORT; } else { tmpid.len = vv->len; tmpid.data = vv->data; } if(validate_id(r, &tmpid, cf) != NGX_OK) { *ret_id = NULL; return NGX_DECLINED; } sz = group->len + 1 + tmpid.len; if((id = ngx_palloc(r->pool, sizeof(*id) + sz)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "nchan: can't allocate space for legacy channel id"); *ret_id = NULL; return NGX_ERROR; } id->len = sz; id->data = (u_char *)&id[1]; cur = id->data; ngx_memcpy(cur, group->data, group->len); cur += group->len; cur[0]='/'; cur++; ngx_memcpy(cur, tmpid.data, tmpid.len); ctx->channel_id_count = 1; ctx->channel_id[0] = *id; *ret_id = id; return NGX_OK; }
static ngx_rtmpt_proxy_session_t *get_session_from_hash(u_char *name, ngx_uint_t size) { ngx_rtmpt_proxy_session_t **sessions, *ts; int hash=ngx_hash_key(name,size)%RTMPT_HASHMAX; sessions = ngx_rtmpt_proxy_sessions_global; for (ts=sessions[hash];ts;ts=ts->next) { if (ts->name.len==size && ngx_strncmp(ts->name.data,name,size)==0) { return ts; } } return NULL; }
static int ngx_http_modsecurity_save_headers_in_visitor(void *data, const char *key, const char *value) { ngx_http_request_t *r = data; ngx_table_elt_t *h; ngx_http_header_t *hh; ngx_http_core_main_conf_t *cmcf; h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { return 0; } h->key.data = (u_char *)key; h->key.len = ngx_strlen(key); h->value.data = (u_char *)value; h->value.len = ngx_strlen(value); h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); if (h->lowcase_key == NULL) { return 0; } ngx_strlow(h->lowcase_key, h->key.data, h->key.len); h->hash = ngx_hash_key(h->lowcase_key, h->key.len); cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { return 0; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: save headers in: \"%V: %V\"", &h->key, &h->value); return 1; }
static void put_session_in_hash(ngx_rtmpt_proxy_session_t *session) { ngx_rtmpt_proxy_session_t **sessions, *ts=NULL, *cs=NULL; int hash=ngx_hash_key(session->name.data,session->name.len)%RTMPT_HASHMAX; sessions = ngx_rtmpt_proxy_sessions_global; if (!sessions[hash]) { sessions[hash]=session; return; } for (ts=sessions[hash];ts;ts=ts->next) { cs=ts; } cs->next=session; session->prev=cs; }
static const char * ngx_rtmp_control_walk_app(ngx_http_request_t *r, ngx_rtmp_core_app_conf_t *cacf) { size_t len; ngx_str_t name; const char *s; ngx_uint_t n; ngx_rtmp_live_stream_t *ls; ngx_rtmp_live_app_conf_t *lacf; lacf = cacf->app_conf[ngx_rtmp_live_module.ctx_index]; if (ngx_http_arg(r, (u_char *) "name", sizeof("name") - 1, &name) != NGX_OK) { for (n = 0; n < (ngx_uint_t) lacf->nbuckets; ++n) { for (ls = lacf->streams[n]; ls; ls = ls->next) { s = ngx_rtmp_control_walk_stream(r, ls); if (s != NGX_CONF_OK) { return s; } } } return NGX_CONF_OK; } for (ls = lacf->streams[ngx_hash_key(name.data, name.len) % lacf->nbuckets]; ls; ls = ls->next) { len = ngx_strlen(ls->name); if (name.len != len || ngx_strncmp(name.data, ls->name, name.len)) { continue; } s = ngx_rtmp_control_walk_stream(r, ls); if (s != NGX_CONF_OK) { return s; } } return NGX_CONF_OK; }
static int ngx_http_modsecurity_save_headers_out_visitor(void *data, const char *key, const char *value) { ngx_http_request_t *r = data; ngx_table_elt_t *h, he; ngx_http_upstream_header_t *hh; ngx_http_upstream_main_conf_t *umcf; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); h = &he; h->key.data = (u_char *)key; h->key.len = ngx_strlen(key); h->value.data = (u_char *)value; h->value.len = ngx_strlen(value); h->lowcase_key = ngx_palloc(r->pool, h->key.len); if (h->lowcase_key == NULL) { return 0; } ngx_strlow(h->lowcase_key, h->key.data, h->key.len); h->hash = ngx_hash_key(h->lowcase_key, h->key.len); hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); if (hh) { /* copy all */ if (hh->copy_handler(r, h, hh->conf) != NGX_OK) { return 0; } } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: save headers out: \"%V: %V\"", &h->key, &h->value); return 1; }
static void request_known_headers_calc_hash (void) { static ngx_int_t is_calc_request_hash = 0; request_known_headers_t *header; if (is_calc_request_hash) { return; } is_calc_request_hash = 1; header = request_known_headers; while (header->name.len != 0) { header->hash = ngx_hash_key(header->name.data, header->name.len); header++; } }
static void remove_session_from_hash(u_char *name, ngx_uint_t size) { ngx_rtmpt_proxy_session_t **sessions, *ts=NULL; int hash=ngx_hash_key(name,size)%RTMPT_HASHMAX; sessions = ngx_rtmpt_proxy_sessions_global; for (ts=sessions[hash];ts;ts=ts->next) { if (ts->name.len==size && ngx_strncmp(ts->name.data,name,size)==0) { if (ts->next) { ts->next->prev=ts->prev; } if (ts->prev) { ts->prev->next=ts->next; } if (ts == sessions[hash]) { sessions[hash]=ts->next; } return; } } return; }
static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c, ngx_http_virtual_names_t *virtual_names, ngx_str_t *host, ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp) { ngx_http_core_srv_conf_t *cscf; if (virtual_names == NULL) { return NGX_DECLINED; } cscf = ngx_hash_find_combined(&virtual_names->names, ngx_hash_key(host->data, host->len), host->data, host->len); if (cscf) { *cscfp = cscf; return NGX_OK; } #if (NGX_PCRE) if (host->len && virtual_names->nregex) { ngx_int_t n; ngx_uint_t i; ngx_http_server_name_t *sn; sn = virtual_names->regex; #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME) if (r == NULL) { ngx_http_connection_t *hc; for (i = 0; i < virtual_names->nregex; i++) { n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0); if (n == NGX_REGEX_NO_MATCHED) { continue; } if (n >= 0) { hc = c->data; hc->ssl_servername_regex = sn[i].regex; *cscfp = sn[i].server; return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, c->log, 0, ngx_regex_exec_n " failed: %i " "on \"%V\" using \"%V\"", n, host, &sn[i].regex->name); return NGX_ERROR; } return NGX_DECLINED; } #endif /* NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME */ for (i = 0; i < virtual_names->nregex; i++) { n = ngx_http_regex_exec(r, sn[i].regex, host); if (n == NGX_DECLINED) { continue; } if (n == NGX_OK) { *cscfp = sn[i].server; return NGX_OK; } return NGX_ERROR; } } #endif /* NGX_PCRE */ return NGX_DECLINED; }
static ngx_inline ngx_int_t ngx_http_modsecurity_load_headers_out(ngx_http_request_t *r) { ngx_http_modsecurity_ctx_t *ctx; char *data; request_rec *req; u_char *content_type; ngx_uint_t content_type_len; ngx_http_variable_value_t *vv; ngx_list_part_t *part; ngx_table_elt_t *h; ngx_uint_t i; char *key, *value; u_char *buf = NULL; size_t size = 0; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity); req = ctx->req; req->status = r->headers_out.status; req->status_line = (char *)ngx_pstrdup0(r->pool, &r->headers_out.status_line); if (r->headers_out.charset.len) { content_type_len = r->headers_out.content_type.len + r->headers_out.charset.len + ngx_strlen("; charset=") + 1; content_type = ngx_palloc(r->pool, content_type_len); if (content_type == NULL) { return NGX_ERROR; } ngx_snprintf(content_type, content_type_len, "%V; charset=%V%Z", &r->headers_out.content_type, &r->headers_out.charset); r->headers_out.content_type.data = content_type; r->headers_out.content_type.len = content_type_len; } /* deep copy */ part = &r->headers_out.headers.part; h = part->elts; for (i = 0; ; i++) { if (i >= part->nelts) { if (part->next == NULL) break; part = part->next; h = part->elts; i = 0; } size += h[i].key.len + h[i].value.len + 2; buf = ngx_palloc(r->pool, size); if (buf == NULL) { return NGX_ERROR; } key = (char *)buf; buf = ngx_cpymem(buf, h[i].key.data, h[i].key.len); *buf++ = '\0'; value = (char *)buf; buf = ngx_cpymem(buf, h[i].value.data, h[i].value.len); *buf++ = '\0'; apr_table_addn(req->headers_out, key, value); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out: \"%V: %V\"", &h[i].key, &h[i].value); } for (i = 0; special_headers_out[i].name; i++) { vv = ngx_http_get_variable(r, &special_headers_out[i].variable_name, ngx_hash_key(special_headers_out[i].variable_name.data, special_headers_out[i].variable_name.len)); if (vv && !vv->not_found) { data = ngx_palloc(r->pool, vv->len + 1); if (data == NULL) { return NGX_ERROR; } ngx_memcpy(data,vv->data, vv->len); data[vv->len] = '\0'; apr_table_setn(req->headers_out, special_headers_out[i].name, data); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out: \"%s: %s\"", special_headers_out[i].name, data); } } req->content_type = apr_table_get(ctx->req->headers_out, "Content-Type"); req->content_encoding = apr_table_get(ctx->req->headers_out, "Content-Encoding"); data = (char *)apr_table_get(ctx->req->headers_out, "Content-Languages"); if(data != NULL) { ctx->req->content_languages = apr_array_make(ctx->req->pool, 1, sizeof(const char *)); *(const char **)apr_array_push(ctx->req->content_languages) = data; } /* req->chunked = r->chunked; may be useless */ req->clength = r->headers_out.content_length_n; req->mtime = apr_time_make(r->headers_out.last_modified_time, 0); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: load headers out done"); return NGX_OK; }
static ngx_int_t ngx_rtmp_control_record(ngx_http_request_t *r, ngx_str_t *method) { ngx_rtmp_record_app_conf_t *racf; ngx_rtmp_core_main_conf_t *cmcf; ngx_rtmp_core_srv_conf_t **pcscf, *cscf; ngx_rtmp_core_app_conf_t **pcacf, *cacf; ngx_rtmp_live_app_conf_t *lacf; ngx_rtmp_live_stream_t *ls; ngx_rtmp_live_ctx_t *lctx; ngx_rtmp_session_t *s; ngx_chain_t cl; ngx_uint_t sn, rn, n; ngx_str_t srv, app, rec, name, path; ngx_str_t msg; ngx_buf_t *b; ngx_int_t rc; size_t len; sn = 0; if (ngx_http_arg(r, (u_char *) "srv", sizeof("srv") - 1, &srv) == NGX_OK) { sn = ngx_atoi(srv.data, srv.len); } if (ngx_http_arg(r, (u_char *) "app", sizeof("app") - 1, &app) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "rtmp_control: app not specified"); ngx_str_set(&msg, "Application not specified"); goto error; } ngx_memzero(&rec, sizeof(rec)); ngx_http_arg(r, (u_char *) "rec", sizeof("rec") - 1, &rec); ngx_memzero(&name, sizeof(name)); ngx_http_arg(r, (u_char *) "name", sizeof("name") - 1, &name); cmcf = ngx_rtmp_core_main_conf; if (cmcf == NULL) { ngx_str_set(&msg, "Missing main RTMP conf"); goto error; } /* find server */ if (sn >= cmcf->servers.nelts) { ngx_str_set(&msg, "Server index out of range"); goto error; } pcscf = cmcf->servers.elts; pcscf += sn; cscf = *pcscf; /* find application */ pcacf = cscf->applications.elts; cacf = NULL; for (n = 0; n < cscf->applications.nelts; ++n, ++pcacf) { if ((*pcacf)->name.len == app.len && ngx_strncmp((*pcacf)->name.data, app.data, app.len) == 0) { cacf = *pcacf; break; } } if (cacf == NULL) { ngx_str_set(&msg, "Application not found"); goto error; } lacf = cacf->app_conf[ngx_rtmp_live_module.ctx_index]; racf = cacf->app_conf[ngx_rtmp_record_module.ctx_index]; /* find live stream by name */ for (ls = lacf->streams[ngx_hash_key(name.data, name.len) % lacf->nbuckets]; ls; ls = ls->next) { len = ngx_strlen(ls->name); if (name.len == len && ngx_strncmp(name.data, ls->name, name.len) == 0) { break; } } if (ls == NULL) { ngx_str_set(&msg, "Live stream not found"); goto error; } /* find publisher context */ for (lctx = ls->ctx; lctx; lctx = lctx->next) { if (lctx->flags & NGX_RTMP_LIVE_PUBLISHING) { break; } } if (lctx == NULL) { ngx_str_set(&msg, "No publisher"); goto error; } s = lctx->session; /* find recorder */ rn = ngx_rtmp_record_find(racf, &rec); if (rn == NGX_CONF_UNSET_UINT) { ngx_str_set(&msg, "Recorder not found"); goto error; } ngx_memzero(&path, sizeof(path)); if (method->len == sizeof("start") - 1 && ngx_strncmp(method->data, "start", method->len) == 0) { rc = ngx_rtmp_record_open(s, rn, &path); } else if (method->len == sizeof("stop") - 1 && ngx_strncmp(method->data, "stop", method->len) == 0) { rc = ngx_rtmp_record_close(s, rn, &path); } else { ngx_str_set(&msg, "Undefined method"); goto error; } if (rc == NGX_ERROR) { ngx_str_set(&msg, "Recorder error"); goto error; } if (rc == NGX_AGAIN) { /* already opened/closed */ ngx_str_null(&path); r->header_only = 1; } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = path.len; b = ngx_create_temp_buf(r->pool, path.len); if (b == NULL) { return NGX_ERROR; } ngx_memzero(&cl, sizeof(cl)); cl.buf = b; b->last = ngx_cpymem(b->pos, path.data, path.len); b->last_buf = 1; ngx_http_send_header(r); return ngx_http_output_filter(r, &cl); error: r->headers_out.status = NGX_HTTP_BAD_REQUEST; r->headers_out.content_length_n = msg.len; b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } ngx_memzero(&cl, sizeof(cl)); cl.buf = b; b->start = b->pos = msg.data; b->end = b->last = msg.data + msg.len; b->memory = 1; b->last_buf = 1; ngx_http_send_header(r); return ngx_http_output_filter(r, &cl); }
char * ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_array_t **types; ngx_str_t *value, *default_type; ngx_uint_t i, n, hash; ngx_hash_key_t *type; types = (ngx_array_t **) (p + cmd->offset); if (*types == (void *) -1) { return NGX_CONF_OK; } default_type = cmd->post; if (*types == NULL) { *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t)); if (*types == NULL) { return NGX_CONF_ERROR; } if (default_type) { type = ngx_array_push(*types); if (type == NULL) { return NGX_CONF_ERROR; } type->key = *default_type; type->key_hash = ngx_hash_key(default_type->data, default_type->len); type->value = (void *) 4; } } value = cf->args->elts; for (i = 1; i < cf->args->nelts; i++) { if (value[i].len == 1 && value[i].data[0] == '*') { *types = (void *) -1; return NGX_CONF_OK; } hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len); value[i].data[value[i].len] = '\0'; type = (*types)->elts; for (n = 0; n < (*types)->nelts; n++) { if (ngx_strcmp(value[i].data, type[n].key.data) == 0) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate MIME type \"%V\"", &value[i]); continue; } } type = ngx_array_push(*types); if (type == NULL) { return NGX_CONF_ERROR; } type->key = value[i]; type->key_hash = hash; type->value = (void *) 4; } return NGX_CONF_OK; }
/*----------------------------------------------------------------------------*/ ngx_int_t rp_bazaar_cmd_handler(ngx_http_request_t *r) { ngx_http_rp_loc_conf_t *lc; rp_bazaar_ctx_t *ctx; size_t i = 0; ctx = ngx_pcalloc(r->pool, sizeof(rp_bazaar_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->redirect = ngx_pcalloc(r->pool, c_redirect_len); if (ctx->redirect == NULL) { return NGX_ERROR; } ctx->json_root = NULL; ctx->finalize_on_post_handler = 0; ctx->in_buffer = NULL; ctx->in_buffer_len = 0; ctx->in_status = 0; ngx_http_set_ctx(r, ctx, ngx_http_rp_module); lc = ngx_http_get_module_loc_conf(r, ngx_http_rp_module); /* Just test local directory here - we would need to check it for almost * all calls anyway */ if(lc->bazaar_dir.data == NULL) { fprintf(stderr, "Bazaar local directory not found\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->json_root = cJSON_CreateObject(r->pool); if(ctx->json_root == NULL) { fprintf(stderr, "Cannot allocate cJSON object\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* Bazaar commands */ for(i = 0; bazaar_cmds[i].name != NULL; i++) { ngx_str_t arg_name = { strlen(bazaar_cmds[i].name), (u_char *)bazaar_cmds[i].name }; ngx_uint_t arg_key = ngx_hash_key(arg_name.data, arg_name.len); ngx_http_variable_value_t *arg_val = NULL; int rc; char **arg_argv = NULL; int arg_argc = 0; arg_val = ngx_http_get_variable(r, &arg_name, arg_key); /* check validity of the specified http variables * note: not all attributes of arg_value are set within ngx_http_get_variable, thus * the order of the following checks are important otherwise it could come to the usage * of uninitialized value what would lead to invalid processing */ if (!arg_val) continue; if (arg_val->not_found == 1) continue; if (arg_val->valid == 0) continue; arg_val->data[arg_val->len] = '\0'; arg_argc = rp_module_cmd_parse_args((const char *)arg_val->data, arg_val->len, &arg_argv); fprintf(stderr, "Calling application: %s\n", &bazaar_cmds[i].name[4]); /* Install/Remove special case */ if ( !strncmp(&bazaar_cmds[i].name[4], "install", 7) || !strncmp(&bazaar_cmds[i].name[4], "remove", 6) ) { if(arg_argv) { for(i = 0; i < (size_t)arg_argc; i++) { if(arg_argv[i]) { free(arg_argv[i]); arg_argv[i] = NULL; } } free(arg_argv); } return rp_bazaar_install(r); } if((rc = bazaar_cmds[i].func(r, &ctx->json_root, arg_argc, arg_argv)) < 0) { /* error - fill the output buffer and send it back */ fprintf(stderr, "Application %s failed: %d\n", bazaar_cmds[i].name, rc); } if(arg_argv) { for(i = 0; i < (size_t)arg_argc; i++) { if(arg_argv[i]) { free(arg_argv[i]); arg_argv[i] = NULL; } } free(arg_argv); } /* Prepare response header & body */ return rp_module_send_response(r, &ctx->json_root); } int ret = 0; /* Unknown command response */ if (i >= sizeof(bazaar_cmds)/sizeof(rp_module_cmd_t)) { rp_module_cmd_error(&ctx->json_root, "Unknown command.", NULL, r->pool); return rp_module_send_response(r, &ctx->json_root); } /* Default Bazaar entry point - list of applications with versions */ cJSON *json_tok = NULL; char *host = (char *)r->headers_in.server.data; char mac[18]; sprintf(mac, "00:00:00:00:00:00"); if (rp_bazaar_get_mac("/sys/class/net/eth0/address", mac)) { fprintf(stderr, "Cannot obtain MAC address.\n"); } static unsigned long long dna = 0; if (!dna || dna == 1) { if (rp_bazaar_get_dna(&dna)) { fprintf(stderr, "Cannot obtain DNA number.\n"); } } char dna_s[64]; sprintf(dna_s, "%016llx", dna); /* Get Ecosystem version */ char ecoversion[64]; sprintf(ecoversion, "unknown"); cJSON *ecoinfo = NULL; if (!get_info(&ecoinfo, (const char *)lc->bazaar_dir.data, "", r->pool)) { fprintf(stderr, "Cannot obtain Ecosystem version.\n"); } else { if (ecoinfo != NULL) { cJSON *j_ver = cJSON_GetObjectItem(ecoinfo, "version"); if(j_ver == NULL) { fprintf(stderr, "Cannot get version from ecoinfo JSON.\n"); } else { strncpy(ecoversion, j_ver->valuestring, sizeof ecoversion); cJSON_Delete(j_ver, r->pool); } cJSON_Delete(ecoinfo, r->pool); } } /* Populate JSON */ cJSON_AddItemToObject(ctx->json_root, "version", cJSON_CreateString(ecoversion, r->pool), r->pool); cJSON_AddItemToObject(ctx->json_root, "dna", cJSON_CreateString(dna_s, r->pool), r->pool); cJSON_AddItemToObject(ctx->json_root, "mac", cJSON_CreateString(mac, r->pool), r->pool); // TODO: Serial number? cJSON_AddItemToObject(ctx->json_root, "host", cJSON_CreateString(host, r->pool), r->pool); cJSON *apps_root; cJSON_AddItemToObject(ctx->json_root, "apps", apps_root=cJSON_CreateObject(r->pool), r->pool); if(apps_root == NULL) { fprintf(stderr, "Can not allocate cJSON object\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } fprintf(stderr, "Making list of apps\n"); /* Add the non-verbose list of apps */ rp_bazaar_app_get_local_list((const char *)lc->bazaar_dir.data, &apps_root, r->pool, 0); /* Issue a POST with JSON defined above to Bazaar server */ char *js = cJSON_Print(ctx->json_root, r->pool); cJSON_Minify(js); fprintf(stderr, "Bazaar handshake:\n%s", js); char *jse = NULL; char *jsp = NULL; char *bazaar_dv = NULL; const char *c_payload = "payload="; const char *c_device = "/device"; jse = url_encode(js); jsp = malloc(strlen(jse) + strlen(c_payload) + 1); if (!jsp) { fprintf(stderr, "Cannot malloc() payload.\n"); ret = NGX_HTTP_INTERNAL_SERVER_ERROR; goto out; } sprintf(jsp, "%s%s", c_payload, jse); bazaar_dv = (char *)malloc(strlen((char *)lc->bazaar_server.data) + strlen(c_device) + 1); if (!bazaar_dv) { fprintf(stderr, "Cannot malloc() device.\n"); ret = NGX_HTTP_INTERNAL_SERVER_ERROR; goto out; } sprintf(bazaar_dv, "%s%s", lc->bazaar_server.data, c_device); fprintf(stderr, "post bazaar_dv %s\n", bazaar_dv); post_resp_t resp = { NULL, 0 }; if (post(jsp, bazaar_dv, &resp)) { if (resp.data) free(resp.data); /* Redirect to Bazaar access error */ fprintf(stderr, "Cannot access %s.\n", bazaar_dv); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_access.html", host); goto out; } /* Get token from POST response */ if (resp.data) { fprintf(stderr,"Bazaar handshake response:\n%s", resp.data); json_tok = cJSON_Parse(resp.data, r->pool); if (!json_tok) { /* Redirect to Bazaar protocol error */ fprintf(stderr,"No JSON found in the following response:\n\"%s\"\n", resp.data); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_proto.html", host); } else { cJSON *jtok = cJSON_GetObjectItem(json_tok, "token"); if (!jtok) { /* Redirect to Bazaar protocol error */ fprintf(stderr, "No token found in the following JSON:\n\"%s\"\n", resp.data); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_proto.html", host); } else { /* Redirect to Bazaar with token */ snprintf(ctx->redirect, c_redirect_len, "%s/token/%s", lc->bazaar_server.data, jtok->valuestring); /* Store token for session control */ strncpy(g_token, jtok->valuestring, c_token_len); g_token[c_token_len - 1] = '\0'; } } free(resp.data); } out: if (jsp) free(jsp); if (jse) free(jse); if (bazaar_dv) free(bazaar_dv); //TODO: Is ctx->json_root handled by the pool deallocator? //if (ctx->json_root) cJSON_Delete(ctx->json_root, r->pool); if (json_tok) cJSON_Delete(json_tok, r->pool); if (ret) return ret; fprintf(stderr, "Redirecting to: %s\n", ctx->redirect); return rp_module_redirect(r, ctx->redirect); }
static ngx_int_t ngx_rtmp_relay_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t *v) { ngx_rtmp_relay_app_conf_t *racf; ngx_rtmp_relay_ctx_t *ctx, **cctx; ngx_uint_t hash; racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_relay_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module); if (ctx == NULL || ctx->publish == NULL) { goto next; } /* play end disconnect? */ if (ctx->publish != ctx) { for (cctx = &ctx->publish->play; *cctx; cctx = &(*cctx)->next) { if (*cctx == ctx) { *cctx = ctx->next; break; } } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0, "relay: play disconnect app='%V' name='%V'", &ctx->app, &ctx->name); /* push reconnect */ if (ctx->relay && ctx->tag == &ngx_rtmp_relay_module && !ctx->publish->push_evt.timer_set) { ngx_add_timer(&ctx->publish->push_evt, racf->push_reconnect); } #ifdef NGX_DEBUG { ngx_uint_t n = 0; for (cctx = &ctx->publish->play; *cctx; cctx = &(*cctx)->next, ++n); ngx_log_debug3(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0, "relay: play left after disconnect app='%V' name='%V': %ui", &ctx->app, &ctx->name, n); } #endif if (ctx->publish->play == NULL && ctx->publish->relay) { ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ctx->publish->session->connection->log, 0, "relay: publish disconnect empty app='%V' name='%V'", &ctx->app, &ctx->name); ngx_rtmp_finalize_session(ctx->publish->session); } ctx->publish = NULL; goto next; } /* publish end disconnect */ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0, "relay: publish disconnect app='%V' name='%V'", &ctx->app, &ctx->name); if (ctx->push_evt.timer_set) { ngx_del_timer(&ctx->push_evt); } for (cctx = &ctx->play; *cctx; cctx = &(*cctx)->next) { (*cctx)->publish = NULL; ngx_log_debug2(NGX_LOG_DEBUG_RTMP, (*cctx)->session->connection->log, 0, "relay: play disconnect orphan app='%V' name='%V'", &(*cctx)->app, &(*cctx)->name); ngx_rtmp_finalize_session((*cctx)->session); } ctx->publish = NULL; hash = ngx_hash_key(ctx->name.data, ctx->name.len); cctx = &racf->ctx[hash % racf->nbuckets]; for (; *cctx && *cctx != ctx; cctx = &(*cctx)->next); if (*cctx) { *cctx = ctx->next; } next: return next_delete_stream(s, v); }
static ngx_int_t ngx_http_auth_request_handler(ngx_http_request_t *r) { ngx_uint_t i; ngx_int_t rc; ngx_list_part_t *part; ngx_table_elt_t *h, *hi; ngx_http_request_t *sr; ngx_http_post_subrequest_t *ps; ngx_http_auth_request_ctx_t *ctx; ngx_http_auth_request_conf_t *arcf; arcf = ngx_http_get_module_loc_conf(r, ngx_http_shibboleth_module); if (arcf->uri.len == 0) { return NGX_DECLINED; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "shib request handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_shibboleth_module); if (ctx != NULL) { if (!ctx->done) { return NGX_AGAIN; } /* * as soon as we are done - explicitly set variables to make * sure they will be available after internal redirects */ if (ngx_http_auth_request_set_variables(r, arcf, ctx) != NGX_OK) { return NGX_ERROR; } /* * Handle the subrequest * as per the FastCGI authorizer specification. */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "shib request authorizer handler"); sr = ctx->subrequest; if (ctx->status == NGX_HTTP_OK) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "shib request authorizer allows access"); if (arcf->use_headers) { /* * 200 response may include headers prefixed with `Variable-`, * copy these into main request headers */ part = &sr->headers_out.headers.part; h = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; h = part->elts; i = 0; } if (h[i].hash == 0) { continue; } if (h[i].key.len >= 9 && ngx_strncasecmp(h[i].key.data, (u_char *) "Variable-", 9) == 0) { /* copy header into original request */ hi = ngx_list_push(&r->headers_in.headers); if (hi == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* Strip the Variable- prefix */ hi->key.len = h[i].key.len - 9; hi->key.data = h[i].key.data + 9; hi->hash = ngx_hash_key(hi->key.data, hi->key.len); hi->value = h[i].value; hi->lowcase_key = ngx_pnalloc(r->pool, hi->key.len); if (hi->lowcase_key == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_strlow(hi->lowcase_key, hi->key.data, hi->key.len); ngx_log_debug2( NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "shib request authorizer copied header: \"%V: %V\"", &hi->key, &hi->value); } } } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "shib request authorizer not using headers"); } return NGX_OK; } /* * Unconditionally return subrequest response status, headers * and content as per FastCGI spec (section 6.3). * * The subrequest response body cannot be returned as Nginx does not * currently support NGX_HTTP_SUBREQUEST_IN_MEMORY. */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "shib request authorizer returning sub-response"); /* copy status */ r->headers_out.status = sr->headers_out.status; /* copy headers */ part = &sr->headers_out.headers.part; h = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; h = part->elts; i = 0; } rc = ngx_http_set_output_header(r, h[i].key, h[i].value); if (rc == NGX_ERROR) { return NGX_ERROR; } ngx_log_debug2( NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "shib request authorizer returning header: \"%V: %V\"", &h[i].key, &h[i].value); } return ctx->status; } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_auth_request_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (ps == NULL) { return NGX_ERROR; } ps->handler = ngx_http_auth_request_done; ps->data = ctx; if (ngx_http_subrequest(r, &arcf->uri, NULL, &sr, ps, NGX_HTTP_SUBREQUEST_WAITED) != NGX_OK) { return NGX_ERROR; } /* * allocate fake request body to avoid attempts to read it and to make * sure real body file (if already read) won't be closed by upstream */ sr->request_body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (sr->request_body == NULL) { return NGX_ERROR; } /* * true FastCGI authorizers should always return the subrequest * response body but the Nginx FastCGI handler does not support * NGX_HTTP_SUBREQUEST_IN_MEMORY at present. */ sr->header_only = 1; ctx->subrequest = sr; ngx_http_set_ctx(r, ctx, ngx_http_shibboleth_module); return NGX_AGAIN; }
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r, ngx_http_shib_request_header_val_t *hv, ngx_str_t *value, ngx_table_elt_t **output_header, unsigned no_create) { ngx_table_elt_t *h; ngx_list_part_t *part; ngx_uint_t i; unsigned matched = 0; #if 1 if (r->headers_out.location && r->headers_out.location->value.len && r->headers_out.location->value.data[0] == '/') { /* XXX ngx_http_core_find_config_phase, for example, * may not initialize the "key" and "hash" fields * for a nasty optimization purpose, and * we have to work-around it here */ r->headers_out.location->hash = ngx_hash_key((u_char *) "location", 8); ngx_str_set(&r->headers_out.location->key, "Location"); } #endif part = &r->headers_out.headers.part; h = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; h = part->elts; i = 0; } if (h[i].hash != 0 && h[i].key.len == hv->key.len && ngx_strncasecmp(hv->key.data, h[i].key.data, h[i].key.len) == 0) { if (value->len == 0 || matched) { h[i].value.len = 0; h[i].hash = 0; } else { h[i].value = *value; h[i].hash = hv->hash; } if (output_header) { *output_header = &h[i]; } /* return NGX_OK; */ matched = 1; } } if (matched) { return NGX_OK; } if (no_create && value->len == 0) { return NGX_OK; } /* XXX we still need to create header slot even if the value * is empty because some builtin headers like Last-Modified * relies on this to get cleared */ h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return NGX_ERROR; } if (value->len == 0) { h->hash = 0; } else { h->hash = hv->hash; } h->key = hv->key; h->value = *value; h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); if (h->lowcase_key == NULL) { return NGX_ERROR; } ngx_strlow(h->lowcase_key, h->key.data, h->key.len); if (output_header) { *output_header = h; } return NGX_OK; }
uint32_t dvt_cache_label_id_from_name(dvt_cache_t *cache, ngx_str_t *name) { ngx_uint_t key_hash = ngx_hash_key(name->data, name->len); int64_t r = (uint64_t)ngx_hash_find(cache->label_ids, key_hash, name->data, name->len); return (uint32_t) r - ARBITRARY_OFFSET_TO_AVOID_PTR_EQ_NULL; }
dvt_cache_t *dvt_cache_init(ngx_pool_t *pool) { dvt_cache_t *cache = ngx_palloc(pool, sizeof(dvt_cache_t)); cache->label_and_value_summary_json = NGX_CONF_UNSET_PTR; cache->label_names = NGX_CONF_UNSET_PTR; cache->label_ids = NGX_CONF_UNSET_PTR; cache->label_value_names = NGX_CONF_UNSET_PTR; cache->label_value_ids = NGX_CONF_UNSET_PTR; uint64_t i, j; ngx_str_t *jsn = NGX_CONF_UNSET_PTR; ngx_array_t* series_collection; ngx_array_t* lavs; // labels and values ngx_str_t *current_str; ngx_array_t *hash_elts; ngx_hash_key_t *el; ngx_array_t **ael; ngx_hash_init_t hash_spec; // ### json summary. series_collection = load_test_exposition(pool); if (series_collection) { lavs = lavs_from_series_set(series_collection, pool); jsn = lavs_to_json(lavs, pool, pool); } cache->label_and_value_summary_json = jsn; // ### label_id -> label_names array cache->label_names = ngx_array_create(pool, 32, sizeof(ngx_str_t)); for (i=0; i<lavs->nelts; ++i) { current_str = ngx_array_push(cache->label_names); *current_str = ((dvt_label_summary_info_t *)lavs->elts)[i].label_name; } // ### label_name -> label_id hash hash_elts = ngx_array_create(pool, 32, sizeof(ngx_hash_key_t)); for (i=0; i<cache->label_names->nelts; ++i) { el = ngx_array_push(hash_elts); el->key = ((ngx_str_t *)cache->label_names->elts)[i]; el->key_hash = ngx_hash_key(el->key.data, el->key.len); el->value = (void *)(i + ARBITRARY_OFFSET_TO_AVOID_PTR_EQ_NULL); } cache->label_ids = ngx_palloc(pool, sizeof(ngx_hash_t)); hash_spec.hash = cache->label_ids; hash_spec.key = ngx_hash_key; hash_spec.max_size = 1024; hash_spec.bucket_size = ngx_align(64, ngx_cacheline_size); hash_spec.name = "label_ids"; hash_spec.pool = pool; if (ngx_hash_init(&hash_spec, hash_elts->elts, hash_elts->nelts) != NGX_OK) { return NGX_CONF_ERROR; } // ### label_value_names cache->label_value_names = ngx_array_create( pool, cache->label_names->nelts, sizeof(ngx_array_t *)); for (i=0; i<cache->label_names->nelts; ++i) { dvt_label_summary_info_t *labsum = &(((dvt_label_summary_info_t *)lavs->elts)[i]); ael = ngx_array_push(cache->label_value_names); *ael = ngx_array_create( pool, labsum->label_values->nelts, sizeof(ngx_str_t *)); for (j=0; j<labsum->label_values->nelts; ++j) { dvt_label_value_summary_info_t* labval_info = &((dvt_label_value_summary_info_t *)labsum->label_values->elts)[j]; ngx_str_t *lval = &labval_info->label_value_name; ngx_str_t **p = ngx_array_push(*ael); *p = lval; } } // ### label_value_ids cache->label_value_ids = ngx_array_create( pool, cache->label_names->nelts, sizeof(ngx_hash_t)); for (i=0; i<cache->label_names->nelts; ++i) { hash_elts = ngx_array_create(pool, 32, sizeof(ngx_hash_key_t)); ngx_array_t *value_names = ((ngx_array_t **)cache->label_value_names->elts)[i]; for (j=0; j<value_names->nelts; ++j) { el = ngx_array_push(hash_elts); el->key = *((ngx_str_t **)value_names->elts)[j]; el->key_hash = ngx_hash_key(el->key.data, el->key.len); el->value = (void *)(j + ARBITRARY_OFFSET_TO_AVOID_PTR_EQ_NULL); } ngx_hash_t *hel = ngx_array_push(cache->label_value_ids); hash_spec.hash = hel; hash_spec.key = ngx_hash_key; hash_spec.max_size = 1024; hash_spec.bucket_size = ngx_align(64, ngx_cacheline_size); hash_spec.name = "label_value_ids"; hash_spec.pool = pool; if (ngx_hash_init(&hash_spec, hash_elts->elts, hash_elts->nelts) != NGX_OK) { return NGX_CONF_ERROR; } } // TODO: some sort of partitioning. // Probably binary. // Goal is to keep as balanced as possible. // ### all series ngx_array_init(&cache->all_series, pool, 128, sizeof(uint32_t *)); for (i=0; i<series_collection->nelts; ++i) { ngx_array_t *series_kvps = ((ngx_array_t **)series_collection->elts)[i]; uint32_t **loc = ngx_array_push(&cache->all_series); *loc = dvt_series_spec_from_kv_array(cache, series_kvps, pool); dbg_ngx(dvt_series_spec_to_text(cache, *loc, pool), pool); } return cache; }
//get the index static ngx_http_dclass_kvdata_str *ngx_http_dclass_index(ngx_http_request_t *r) { ngx_uint_t i; u_char *hfield=NULL; ngx_uint_t key; ngx_str_t str; ngx_http_variable_value_t *val; const dclass_keyvalue *kvd; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_http_dclass_conf_t *cf; ngx_http_dclass_kvdata_str *kvs; cf = ngx_http_get_module_loc_conf(r,ngx_http_dclass_module); if(!cf->enable || !cf->head[0]) return NULL; ngx_str_set(&str,"dclass_ptr"); key=ngx_hash_key(str.data,str.len); val=ngx_http_get_variable(r, &str, key); if(val && val->valid && val->data && !ngx_rstrncmp((u_char*)"ptr",val->data,3)) { kvs=(ngx_http_dclass_kvdata_str*)val->data; ngx_log_error(NGX_HTTP_DCLASS_LOGLEVEL,r->connection->log,0,"dClass: classify cache: '%s'",kvs->kvd[0]->id); return kvs; } if(!*cf->hfield.data) { if(r->headers_in.user_agent) hfield = r->headers_in.user_agent->value.data; } else { part=&r->headers_in.headers.part; header=part->elts; for (i=0;;i++) { if(i>=part->nelts) { if(part->next==NULL) break; part=part->next; header=part->elts; i=0; } if(!ngx_strcasecmp(cf->hfield.data,header[i].key.data)) { hfield=header[i].value.data; break; } } } if(hfield==NULL) return NULL; kvs=(ngx_http_dclass_kvdata_str*)ngx_pcalloc(r->pool,sizeof(ngx_http_dclass_kvdata_str)); if(kvs==NULL) return NULL; for(i=0;i<NGX_HTTP_DCLASS_INDEXES && cf->head[i];i++) { kvd=dclass_classify(cf->head[i],(char*)hfield); kvs->kvd[i]=kvd; ngx_cpystrn(kvs->data,(u_char*)"ptr",4); ngx_log_error(NGX_HTTP_DCLASS_LOGLEVEL,r->connection->log,0,"dClass: classify %d: '%s' => '%s'",i,hfield,kvd->id); } return kvs; }
ngx_int_t ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value, ngx_uint_t flags) { size_t len; u_char *p; ngx_str_t *name; ngx_uint_t i, k, n, skip, last; ngx_array_t *keys, *hwc; ngx_hash_key_t *hk; last = key->len; if (flags & NGX_HASH_WILDCARD_KEY) { /* * supported wildcards: * "*.example.com", ".example.com", and "www.example.*" */ n = 0; for (i = 0; i < key->len; i++) { if (key->data[i] == '*') { if (++n > 1) { return NGX_DECLINED; } } if (key->data[i] == '.' && key->data[i + 1] == '.') { return NGX_DECLINED; } } if (key->len > 1 && key->data[0] == '.') { skip = 1; goto wildcard; } if (key->len > 2) { if (key->data[0] == '*' && key->data[1] == '.') { skip = 2; goto wildcard; } if (key->data[i - 2] == '.' && key->data[i - 1] == '*') { skip = 0; last -= 2; goto wildcard; } } if (n) { return NGX_DECLINED; } } /* exact hash */ k = 0; for (i = 0; i < last; i++) { if (!(flags & NGX_HASH_READONLY_KEY)) { key->data[i] = ngx_tolower(key->data[i]); } k = ngx_hash(k, key->data[i]); } k %= ha->hsize; /* check conflicts in exact hash */ name = ha->keys_hash[k].elts; if (name) { for (i = 0; i < ha->keys_hash[k].nelts; i++) { if (last != name[i].len) { continue; } if (ngx_strncmp(key->data, name[i].data, last) == 0) { return NGX_BUSY; } } } else { if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK) { return NGX_ERROR; } } name = ngx_array_push(&ha->keys_hash[k]); if (name == NULL) { return NGX_ERROR; } *name = *key; hk = ngx_array_push(&ha->keys); if (hk == NULL) { return NGX_ERROR; } hk->key = *key; hk->key_hash = ngx_hash_key(key->data, last); hk->value = value; return NGX_OK; wildcard: /* wildcard hash */ k = ngx_hash_strlow(&key->data[skip], &key->data[skip], last - skip); k %= ha->hsize; if (skip == 1) { /* check conflicts in exact hash for ".example.com" */ name = ha->keys_hash[k].elts; if (name) { len = last - skip; for (i = 0; i < ha->keys_hash[k].nelts; i++) { if (len != name[i].len) { continue; } if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) { return NGX_BUSY; } } } else { if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK) { return NGX_ERROR; } } name = ngx_array_push(&ha->keys_hash[k]); if (name == NULL) { return NGX_ERROR; } name->len = last - 1; name->data = ngx_pnalloc(ha->temp_pool, name->len); if (name->data == NULL) { return NGX_ERROR; } ngx_memcpy(name->data, &key->data[1], name->len); } if (skip) { /* * convert "*.example.com" to "com.example.\0" * and ".example.com" to "com.example\0" */ p = ngx_pnalloc(ha->temp_pool, last); if (p == NULL) { return NGX_ERROR; } len = 0; n = 0; for (i = last - 1; i; i--) { if (key->data[i] == '.') { ngx_memcpy(&p[n], &key->data[i + 1], len); n += len; p[n++] = '.'; len = 0; continue; } len++; } if (len) { ngx_memcpy(&p[n], &key->data[1], len); n += len; } p[n] = '\0'; hwc = &ha->dns_wc_head; keys = &ha->dns_wc_head_hash[k]; } else { /* convert "www.example.*" to "www.example\0" */ last++; p = ngx_pnalloc(ha->temp_pool, last); if (p == NULL) { return NGX_ERROR; } ngx_cpystrn(p, key->data, last); hwc = &ha->dns_wc_tail; keys = &ha->dns_wc_tail_hash[k]; } /* check conflicts in wildcard hash */ name = keys->elts; if (name) { len = last - skip; for (i = 0; i < keys->nelts; i++) { if (len != name[i].len) { continue; } if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) { return NGX_BUSY; } } } else { if (ngx_array_init(keys, ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK) { return NGX_ERROR; } } name = ngx_array_push(keys); if (name == NULL) { return NGX_ERROR; } name->len = last - skip; name->data = ngx_pnalloc(ha->temp_pool, name->len); if (name->data == NULL) { return NGX_ERROR; } ngx_memcpy(name->data, key->data + skip, name->len); /* add to wildcard hash */ hk = ngx_array_push(hwc); if (hk == NULL) { return NGX_ERROR; } hk->key.len = last - 1; hk->key.data = p; hk->key_hash = 0; hk->value = value; return NGX_OK; }