static int ngx_http_lua_shdict_incr(lua_State *L) { int n; ngx_str_t key; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; double num; u_char *p; ngx_shm_zone_t *zone; double value; n = lua_gettop(L); if (n != 3) { return luaL_error(L, "expecting 3 arguments, but only seen %d", n); } if (lua_type(L, 1) != LUA_TLIGHTUSERDATA) { return luaL_error(L, "bad \"zone\" argument"); } zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } ctx = zone->data; if (lua_isnil(L, 2)) { lua_pushnil(L); lua_pushliteral(L, "nil key"); return 2; } key.data = (u_char *) luaL_checklstring(L, 2, &key.len); if (key.len == 0) { lua_pushnil(L); lua_pushliteral(L, "empty key"); return 2; } if (key.len > 65535) { lua_pushnil(L); lua_pushliteral(L, "key too long"); return 2; } hash = ngx_crc32_short(key.data, key.len); value = luaL_checknumber(L, 3); dd("looking up key %.*s in shared dict %.*s", (int) key.len, key.data, (int) ctx->name.len, ctx->name.data); ngx_shmtx_lock(&ctx->shpool->mutex); #if 1 ngx_http_lua_shdict_expire(ctx, 1); #endif rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); dd("shdict lookup returned %d", (int) rc); if (rc == NGX_DECLINED || rc == NGX_DONE) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnil(L); lua_pushliteral(L, "not found"); return 2; } /* rc == NGX_OK */ if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(double)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnil(L); lua_pushliteral(L, "not a number"); return 2; } ngx_queue_remove(&sd->queue); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); dd("setting value type to %d", (int) sd->value_type); p = sd->data + key.len; num = *(double *) p; num += value; ngx_memcpy(p, (double *) &num, sizeof(double)); ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnumber(L, num); lua_pushnil(L); return 2; }
ngx_int_t ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs, ngx_str_t *script) { size_t i; ngx_int_t rc; u_char *err_msg; size_t len; u_char *data; #if (NGX_PCRE) ngx_pool_t *old_pool; #endif ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("nargs: %d", (int) nargs); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } } else { ngx_http_lua_reset_ctx(r, L, ctx); } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } ctx->context = NGX_HTTP_LUA_CONTEXT_SET; dd("set Lua VM panic handler"); lua_atpanic(L, ngx_http_lua_atpanic); NGX_LUA_EXCEPTION_TRY { dd("initialize nginx context in Lua VM, code chunk at " "stack top sp = 1"); ngx_http_lua_set_by_lua_env(L, r, nargs, args); /* passing directive arguments to the user code */ for (i = 0; i < nargs; i++) { lua_pushlstring(L, (const char *) args[i].data, args[i].len); } #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ old_pool = ngx_http_lua_pcre_malloc_init(r->pool); #endif lua_pushcfunction(L, ngx_http_lua_traceback); lua_insert(L, 1); /* put it under chunk and args */ dd("protected call user code"); rc = lua_pcall(L, nargs, 1, 1); dd("after protected call user code"); lua_remove(L, 1); /* remove traceback function */ #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ ngx_http_lua_pcre_malloc_done(old_pool); #endif if (rc != 0) { /* error occured when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { err_msg = (u_char *) "unknown reason"; len = sizeof("unknown reason") - 1; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to run set_by_lua*: %*s", len, err_msg); lua_settop(L, 0); /* clear remaining elems on stack */ return NGX_ERROR; } data = (u_char *) lua_tolstring(L, -1, &len); if (data) { val->data = ngx_palloc(r->pool, len); if (val->data == NULL) { return NGX_ERROR; } ngx_memcpy(val->data, data, len); val->len = len; } else { val->data = NULL; val->len = 0; } } NGX_LUA_EXCEPTION_CATCH { dd("nginx execution restored"); return NGX_ERROR; } /* clear Lua stack */ lua_settop(L, 0); return NGX_OK; }
ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log) { #if 0 ssize_t n; ngx_err_t err; struct iovec iov[1]; struct msghdr msg; #if (NGX_HAVE_MSGHDR_MSG_CONTROL) union { struct cmsghdr cm; char space[CMSG_SPACE(sizeof(int))]; } cmsg; if (ch->fd == -1) { msg.msg_control = NULL; msg.msg_controllen = 0; } else { msg.msg_control = (caddr_t) &cmsg; msg.msg_controllen = sizeof(cmsg); cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int)); cmsg.cm.cmsg_level = SOL_SOCKET; cmsg.cm.cmsg_type = SCM_RIGHTS; /* * We have to use ngx_memcpy() instead of simple * *(int *) CMSG_DATA(&cmsg.cm) = ch->fd; * because some gcc 4.4 with -O2/3/s optimization issues the warning: * dereferencing type-punned pointer will break strict-aliasing rules * * Fortunately, gcc with -O1 compiles this ngx_memcpy() * in the same simple assigment as in the code above */ ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int)); } msg.msg_flags = 0; #else if (ch->fd == -1) { msg.msg_accrights = NULL; msg.msg_accrightslen = 0; } else { msg.msg_accrights = (caddr_t) &ch->fd; msg.msg_accrightslen = sizeof(int); } #endif iov[0].iov_base = (char *) ch; iov[0].iov_len = size; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 1; n = sendmsg(s, &msg, 0); if (n == -1) { err = ngx_errno; if (err == NGX_EAGAIN) { return NGX_AGAIN; } ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed"); return NGX_ERROR; } #endif return NGX_OK; }
static int ngx_http_lua_ngx_req_append_body(lua_State *L) { ngx_http_request_t *r; int n; ngx_http_request_body_t *rb; ngx_str_t body; size_t size, rest; size_t offset = 0; n = lua_gettop(L); if (n != 1) { return luaL_error(L, "expecting 1 arguments but seen %d", n); } body.data = (u_char *) luaL_checklstring(L, 1, &body.len); r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request found"); } ngx_http_lua_check_fake_request(L, r); if (r->request_body == NULL || r->request_body->buf == NULL || r->request_body->bufs == NULL) { return luaL_error(L, "request_body not initialized"); } rb = r->request_body; rest = body.len; while (rest > 0) { if (rb->buf->last == rb->buf->end) { if (ngx_http_lua_write_request_body(r, rb->bufs) != NGX_OK) { return luaL_error(L, "fail to write file"); } rb->buf->last = rb->buf->start; } size = rb->buf->end - rb->buf->last; if (size > rest) { size = rest; } ngx_memcpy(rb->buf->last, body.data + offset, size); rb->buf->last += size; rest -= size; offset += size; r->headers_in.content_length_n += size; } return 0; }
static ngx_int_t websocket_publish(full_subscriber_t *fsub, ngx_buf_t *buf) { static ngx_str_t nopublishing = ngx_string("Publishing not allowed."); static ngx_str_t POST_REQUEST_STRING = {4, (u_char *)"POST "}; if(!fsub->sub.cf->pub.websocket) { return websocket_send_close_frame(fsub, CLOSE_POLICY_VIOLATION, &nopublishing); } #if (NGX_DEBUG_POOL) ERR("ws request pool size: %V", ngx_http_debug_pool_str(fsub->sub.request->pool)); #endif ngx_http_complex_value_t *publisher_upstream_request_url_ccv; publisher_upstream_request_url_ccv = fsub->sub.cf->publisher_upstream_request_url; if(publisher_upstream_request_url_ccv == NULL) { websocket_publish_continue(fsub, buf); } else { nchan_pub_upstream_stuff_t *psr_stuff; ngx_http_post_subrequest_t *psr; nchan_pub_upstream_data_t *psrd; ngx_http_request_t *r = fsub->sub.request; ngx_http_request_t *sr; ngx_http_request_body_t *fakebody; ngx_chain_t *fakebody_chain; ngx_buf_t *fakebody_buf; size_t sz; if(!fsub->upstream_stuff) { if((psr_stuff = ngx_palloc(r->pool, sizeof(*psr_stuff))) == NULL) { ERR("can't allocate memory for publisher auth subrequest"); websocket_respond_status(&fsub->sub, NGX_HTTP_INTERNAL_SERVER_ERROR, NULL); return NGX_ERROR; } fsub->upstream_stuff = psr_stuff; psr = &psr_stuff->psr; psr->data = &psr_stuff->psr_data; psr->handler = websocket_publisher_upstream_handler; psr_stuff->psr_data.fsub = fsub; psr_stuff->psr_data.tmp_pool = NULL; ngx_http_complex_value(r, publisher_upstream_request_url_ccv, &psr_stuff->psr_data.upstream_request_url); } psrd = &fsub->upstream_stuff->psr_data; psr = &fsub->upstream_stuff->psr; if(psrd->tmp_pool) { //previous upstream request's pool ngx_destroy_pool(psrd->tmp_pool); psrd->tmp_pool = NULL; } psrd->buf = *buf; psrd->original_pool = r->pool; psrd->original_cleanup = r->cleanup; r->cleanup = NULL; psrd->tmp_pool = ngx_create_pool(NCHAN_WS_UPSTREAM_TMP_POOL_SIZE, r->connection->log); r->pool = psrd->tmp_pool; //ERR("request %p tmp pool %p", r, r->pool); fakebody = ngx_pcalloc(r->pool, sizeof(*fakebody)); fakebody_chain = ngx_palloc(r->pool, sizeof(*fakebody_chain)); fakebody_buf = ngx_palloc(r->pool, sizeof(*fakebody_buf)); fakebody->bufs = fakebody_chain; fakebody_chain->next = NULL; fakebody_chain->buf = fakebody_buf; init_msg_buf(fakebody_buf); //just copy the buffer contents. it's inefficient but I don't care at the moment. //this can and should be optimized later sz = ngx_buf_size(buf); fakebody_buf->start = ngx_palloc(r->pool, sz); //huuh? ngx_memcpy(fakebody_buf->start, buf->start, sz); fakebody_buf->end = fakebody_buf->start + sz; fakebody_buf->pos = fakebody_buf->start; fakebody_buf->last = fakebody_buf->end; ngx_http_subrequest(r, &psrd->upstream_request_url, NULL, &sr, psr, NGX_HTTP_SUBREQUEST_IN_MEMORY); nchan_adjust_subrequest(sr, NGX_HTTP_POST, &POST_REQUEST_STRING, fakebody, sz, NULL); /* //http request sudden close cleanup if((psrd->cln = ngx_http_cleanup_add(sr, 0)) == NULL) { ERR("Unable to add request cleanup for websocket upstream request"); return NGX_ERROR; } psrd->cln->data = fsub; psrd->cln->handler = (ngx_http_cleanup_pt )sudden_upstream_request_abort_handler; */ } return NGX_OK; }
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle) { u_char *p; size_t len; if (ngx_prefix) { len = ngx_strlen(ngx_prefix); p = ngx_prefix; if (len && !ngx_path_separator(p[len - 1])) { p = ngx_pnalloc(cycle->pool, len + 1); if (p == NULL) { return NGX_ERROR; } ngx_memcpy(p, ngx_prefix, len); p[len++] = '/'; } cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; } else { #ifndef NGX_PREFIX p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH); if (p == NULL) { return NGX_ERROR; } if (ngx_getcwd(p, NGX_MAX_PATH) == 0) { ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed"); return NGX_ERROR; } len = ngx_strlen(p); p[len++] = '/'; cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; #else #ifdef NGX_CONF_PREFIX ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX); #else ngx_str_set(&cycle->conf_prefix, NGX_PREFIX); #endif ngx_str_set(&cycle->prefix, NGX_PREFIX); #endif } if (ngx_conf_file) { cycle->conf_file.len = ngx_strlen(ngx_conf_file); cycle->conf_file.data = ngx_conf_file; } else { ngx_str_set(&cycle->conf_file, NGX_CONF_PATH); } if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) { return NGX_ERROR; } for (p = cycle->conf_file.data + cycle->conf_file.len - 1; p > cycle->conf_file.data; p--) { if (ngx_path_separator(*p)) { cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1; cycle->conf_prefix.data = ngx_cycle->conf_file.data; break; } } if (ngx_conf_params) { cycle->conf_param.len = ngx_strlen(ngx_conf_params); cycle->conf_param.data = ngx_conf_params; } if (ngx_test_config) { cycle->log->log_level = NGX_LOG_INFO; } return NGX_OK; }
static int ngx_http_lua_socket_udp_send(lua_State *L) { ssize_t n; ngx_http_request_t *r; u_char *p; size_t len; ngx_http_lua_socket_udp_upstream_t *u; int type; const char *msg; ngx_str_t query; ngx_http_lua_loc_conf_t *llcf; if (lua_gettop(L) != 2) { return luaL_error(L, "expecting 2 arguments (including the object), " "but got %d", lua_gettop(L)); } lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "request object not found"); } luaL_checktype(L, 1, LUA_TTABLE); lua_rawgeti(L, 1, SOCKET_CTX_INDEX); u = lua_touserdata(L, -1); lua_pop(L, 1); if (u == NULL || u->udp_connection.connection == NULL) { llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->log_socket_errors) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "attempt to send data on a closed socket: u:%p, c:%p", u, u ? u->udp_connection.connection : NULL); } lua_pushnil(L); lua_pushliteral(L, "closed"); return 2; } if (u->ft_type) { u->ft_type = 0; } if (u->waiting) { lua_pushnil(L); lua_pushliteral(L, "socket busy"); return 2; } type = lua_type(L, 2); switch (type) { case LUA_TNUMBER: case LUA_TSTRING: lua_tolstring(L, 2, &len); break; case LUA_TTABLE: len = ngx_http_lua_calc_strlen_in_table(L, 2, 2, 1 /* strict */); break; default: msg = lua_pushfstring(L, "string, number, boolean, nil, " "or array table expected, got %s", lua_typename(L, type)); return luaL_argerror(L, 2, msg); } query.data = lua_newuserdata(L, len); query.len = len; switch (type) { case LUA_TNUMBER: case LUA_TSTRING: p = (u_char *) lua_tolstring(L, 2, &len); ngx_memcpy(query.data, (u_char *) p, len); break; case LUA_TTABLE: (void) ngx_http_lua_copy_str_in_table(L, 2, query.data); break; default: return luaL_error(L, "impossible to reach here"); } u->ft_type = 0; /* mimic ngx_http_upstream_init_request here */ #if 1 u->waiting = 0; #endif dd("sending query %.*s", (int) query.len, query.data); n = ngx_send(u->udp_connection.connection, query.data, query.len); dd("ngx_send returns %d (query len %d)", (int) n, (int) query.len); if (n == NGX_ERROR || n == NGX_AGAIN) { u->socket_errno = ngx_socket_errno; return ngx_http_lua_socket_error_retval_handler(r, u, L); } if (n != (ssize_t) query.len) { dd("not the while query was sent"); u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_PARTIALWRITE; return ngx_http_lua_socket_error_retval_handler(r, u, L); } dd("n == len"); lua_pushinteger(L, 1); return 1; }
static int ngx_http_lua_ngx_re_sub_helper(lua_State *L, unsigned global) { ngx_http_lua_regex_t *re; ngx_http_request_t *r; ngx_str_t subj; ngx_str_t pat; ngx_str_t opts; ngx_str_t tpl; ngx_http_lua_main_conf_t *lmcf = NULL; ngx_pool_t *pool, *old_pool; ngx_lua_regex_compile_t re_comp; const char *msg; ngx_int_t rc; ngx_uint_t n; ngx_int_t i; int nargs; int *cap = NULL; int ovecsize; int type; unsigned func; int offset; size_t count; luaL_Buffer luabuf; ngx_int_t flags; u_char *p; u_char errstr[NGX_MAX_CONF_ERRSTR + 1]; pcre_extra *sd = NULL; ngx_http_lua_complex_value_t *ctpl = NULL; ngx_http_lua_compile_complex_value_t ccv; nargs = lua_gettop(L); if (nargs != 3 && nargs != 4) { return luaL_error(L, "expecting three or four arguments, but got %d", nargs); } lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } subj.data = (u_char *) luaL_checklstring(L, 1, &subj.len); pat.data = (u_char *) luaL_checklstring(L, 2, &pat.len); func = 0; type = lua_type(L, 3); switch (type) { case LUA_TFUNCTION: func = 1; tpl.len = 0; tpl.data = (u_char *) ""; break; case LUA_TNUMBER: case LUA_TSTRING: tpl.data = (u_char *) lua_tolstring(L, 3, &tpl.len); break; default: msg = lua_pushfstring(L, "string, number, or function expected, " "got %s", lua_typename(L, type)); return luaL_argerror(L, 3, msg); } ngx_memzero(&re_comp, sizeof(ngx_lua_regex_compile_t)); if (nargs == 4) { opts.data = (u_char *) luaL_checklstring(L, 4, &opts.len); lua_pop(L, 1); } else { /* nargs == 3 */ opts.data = (u_char *) ""; opts.len = 0; } /* stack: subj regex repl */ re_comp.options = 0; flags = ngx_http_lua_ngx_re_parse_opts(L, &re_comp, &opts, 4); if (flags & NGX_LUA_RE_COMPILE_ONCE) { lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); pool = lmcf->pool; dd("server pool %p", lmcf->pool); lua_pushlightuserdata(L, &ngx_http_lua_regex_cache_key); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushliteral(L, "s"); lua_pushinteger(L, tpl.len); lua_pushliteral(L, ":"); lua_pushvalue(L, 2); if (tpl.len != 0) { lua_pushvalue(L, 3); } dd("options size: %d", (int) sizeof(re_comp.options)); lua_pushlstring(L, (char *) &re_comp.options, sizeof(re_comp.options)); /* table regex opts */ if (tpl.len == 0) { lua_concat(L, 5); /* table key */ } else { lua_concat(L, 6); /* table key */ } lua_pushvalue(L, -1); /* table key key */ dd("regex cache key: %.*s", (int) (pat.len + sizeof(re_comp.options)), lua_tostring(L, -1)); lua_rawget(L, -3); /* table key re */ re = lua_touserdata(L, -1); lua_pop(L, 1); /* table key */ if (re) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua regex cache hit for sub regex \"%s\" with options " "\"%s\" and replace \"%s\"", pat.data, opts.data, func ? (u_char *) "<func>" : tpl.data); lua_pop(L, 2); dd("restoring regex %p, ncaptures %d, captures %p", re->regex, re->ncaptures, re->captures); re_comp.regex = re->regex; sd = re->regex_sd; re_comp.captures = re->ncaptures; cap = re->captures; ctpl = re->replace; if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; } else { ovecsize = (re->ncaptures + 1) * 3; } goto exec; } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua regex cache miss for %ssub regex \"%s\" with options " "\"%s\" and replace \"%s\"", global ? "g" : "", pat.data, opts.data, func ? (u_char *) "<func>" : tpl.data); if (lmcf->regex_cache_entries >= lmcf->regex_cache_max_entries) { if (lmcf->regex_cache_entries == lmcf->regex_cache_max_entries) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "lua exceeding regex cache max entries (%i)", lmcf->regex_cache_max_entries); lmcf->regex_cache_entries++; } pool = r->pool; flags &= ~NGX_LUA_RE_COMPILE_ONCE; } } else { pool = r->pool; } re_comp.pattern = pat; re_comp.err.len = NGX_MAX_CONF_ERRSTR; re_comp.err.data = errstr; re_comp.pool = pool; dd("compiling regex"); ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua compiling %ssub regex \"%s\" with options \"%s\" " "(compile once: %d) (dfa mode: %d) (jit mode: %d)", global ? "g" : "", pat.data, opts.data, (flags & NGX_LUA_RE_COMPILE_ONCE) != 0, (flags & NGX_LUA_RE_MODE_DFA) != 0, (flags & NGX_LUA_RE_MODE_JIT) != 0); old_pool = ngx_http_lua_pcre_malloc_init(pool); rc = ngx_lua_regex_compile(&re_comp); ngx_http_lua_pcre_malloc_done(old_pool); if (rc != NGX_OK) { dd("compile failed"); re_comp.err.data[re_comp.err.len] = '\0'; msg = lua_pushfstring(L, "failed to compile regex \"%s\": %s", pat.data, re_comp.err.data); return luaL_argerror(L, 2, msg); } #if LUA_HAVE_PCRE_JIT if (flags & NGX_LUA_RE_MODE_JIT) { old_pool = ngx_http_lua_pcre_malloc_init(pool); sd = pcre_study(re_comp.regex, PCRE_STUDY_JIT_COMPILE, &msg); ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) dd("sd = %p", sd); if (msg != NULL) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre study failed with PCRE_STUDY_JIT_COMPILE: %s (%p)", msg, sd); } if (sd != NULL) { int jitted; old_pool = ngx_http_lua_pcre_malloc_init(pool); pcre_fullinfo(re_comp.regex, sd, PCRE_INFO_JIT, &jitted); ngx_http_lua_pcre_malloc_done(old_pool); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre JIT compiling result: %d", jitted); } # endif /* NGX_DEBUG */ } else { old_pool = ngx_http_lua_pcre_malloc_init(pool); sd = pcre_study(re_comp.regex, 0, &msg); ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) dd("sd = %p", sd); if (msg != NULL) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pcre_study failed with PCRE_STUDY_JIT_COMPILE: %s (%p)", msg, sd); } # endif /* NGX_DEBUG */ } #else /* LUA_HAVE_PCRE_JIT */ if (flags & NGX_LUA_RE_MODE_JIT) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "your pcre build does not have JIT support and " "the \"j\" regex option is ignored"); } #endif /* LUA_HAVE_PCRE_JIT */ dd("compile done, captures %d", re_comp.captures); if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; } else { ovecsize = (re_comp.captures + 1) * 3; } cap = ngx_palloc(pool, ovecsize * sizeof(int)); if (cap == NULL) { flags &= ~NGX_LUA_RE_COMPILE_ONCE; msg = "out of memory"; goto error; } if (func) { ctpl = NULL; } else { ctpl = ngx_palloc(pool, sizeof(ngx_http_lua_complex_value_t)); if (ctpl == NULL) { flags &= ~NGX_LUA_RE_COMPILE_ONCE; msg = "out of memory"; goto error; } if ((flags & NGX_LUA_RE_COMPILE_ONCE) && tpl.len != 0) { /* copy the string buffer pointed to by tpl.data from Lua VM */ p = ngx_palloc(pool, tpl.len + 1); if (p == NULL) { flags &= ~NGX_LUA_RE_COMPILE_ONCE; msg = "out of memory"; goto error; } ngx_memcpy(p, tpl.data, tpl.len); p[tpl.len] = '\0'; tpl.data = p; } ngx_memzero(&ccv, sizeof(ngx_http_lua_compile_complex_value_t)); ccv.pool = pool; ccv.log = r->connection->log; ccv.value = &tpl; ccv.complex_value = ctpl; if (ngx_http_lua_compile_complex_value(&ccv) != NGX_OK) { ngx_pfree(pool, cap); ngx_pfree(pool, ctpl); if ((flags & NGX_LUA_RE_COMPILE_ONCE) && tpl.len != 0) { ngx_pfree(pool, tpl.data); } if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } ngx_pfree(pool, re_comp.regex); return luaL_error(L, "bad template for substitution: \"%s\"", lua_tostring(L, 3)); } } if (flags & NGX_LUA_RE_COMPILE_ONCE) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua saving compiled sub regex (%d captures) into the cache " "(entries %i)", re_comp.captures, lmcf ? lmcf->regex_cache_entries : 0); re = ngx_palloc(pool, sizeof(ngx_http_lua_regex_t)); if (re == NULL) { return luaL_error(L, "out of memory"); } dd("saving regex %p, ncaptures %d, captures %p", re_comp.regex, re_comp.captures, cap); re->regex = re_comp.regex; re->regex_sd = sd; re->ncaptures = re_comp.captures; re->captures = cap; re->replace = ctpl; lua_pushlightuserdata(L, re); /* table key value */ lua_rawset(L, -3); /* table */ lua_pop(L, 1); if (lmcf) { lmcf->regex_cache_entries++; } } exec: count = 0; offset = 0; for (;;) { if (subj.len == 0) { break; } if (flags & NGX_LUA_RE_MODE_DFA) { #if LUA_HAVE_PCRE_DFA int ws[NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT]; rc = ngx_http_lua_regex_dfa_exec(re_comp.regex, sd, &subj, offset, cap, ovecsize, ws, NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT); #else /* LUA_HAVE_PCRE_DFA */ msg = "at least pcre 6.0 is required for the DFA mode"; goto error; #endif /* LUA_HAVE_PCRE_DFA */ } else { rc = ngx_http_lua_regex_exec(re_comp.regex, sd, &subj, offset, cap, ovecsize); } if (rc == NGX_REGEX_NO_MATCHED) { break; } if (rc < 0) { msg = lua_pushfstring(L, ngx_regex_exec_n " failed: %d on \"%s\" " "using \"%s\"", (int) rc, subj.data, pat.data); goto error; } if (rc == 0) { if (flags & NGX_LUA_RE_MODE_DFA) { rc = 1; } else { msg = "capture size too small"; goto error; } } dd("rc = %d", (int) rc); count++; if (count == 1) { luaL_buffinit(L, &luabuf); } if (func) { lua_pushvalue(L, -1); lua_createtable(L, rc - 1 /* narr */, 1 /* nrec */); for (i = 0, n = 0; i < rc; i++, n += 2) { dd("capture %d: %d %d", (int) i, cap[n], cap[n + 1]); if (cap[n] < 0) { lua_pushnil(L); } else { lua_pushlstring(L, (char *) &subj.data[cap[n]], cap[n + 1] - cap[n]); dd("pushing capture %s at %d", lua_tostring(L, -1), (int) i); } lua_rawseti(L, -2, (int) i); } dd("stack size at call: %d", lua_gettop(L)); lua_call(L, 1 /* nargs */, 1 /* nresults */); type = lua_type(L, -1); switch (type) { case LUA_TNUMBER: case LUA_TSTRING: tpl.data = (u_char *) lua_tolstring(L, -1, &tpl.len); break; default: msg = lua_pushfstring(L, "string or number expected to be " "returned by the replace function, got %s", lua_typename(L, type)); return luaL_argerror(L, 3, msg); } luaL_addlstring(&luabuf, (char *) &subj.data[offset], cap[0] - offset); luaL_addlstring(&luabuf, (char *) tpl.data, tpl.len); lua_pop(L, 1); offset = cap[1]; if (global) { continue; } break; } rc = ngx_http_lua_complex_value(r, &subj, offset, rc, cap, ctpl, &luabuf); if (rc != NGX_OK) { msg = lua_pushfstring(L, "failed to eval the template for " "replacement: \"%s\"", tpl.data); goto error; } offset = cap[1]; if (global) { continue; } break; } if (count == 0) { dd("no match, just the original subject"); lua_settop(L, 1); } else { if (offset != (int) subj.len) { dd("adding trailer: %s (len %d)", &subj.data[offset], (int) (subj.len - offset)); luaL_addlstring(&luabuf, (char *) &subj.data[offset], subj.len - offset); } luaL_pushresult(&luabuf); dd("the dst string: %s", lua_tostring(L, -1)); } if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } if (re_comp.regex) { ngx_pfree(pool, re_comp.regex); } if (ctpl) { ngx_pfree(pool, ctpl); } if (cap) { ngx_pfree(pool, cap); } } lua_pushinteger(L, count); return 2; error: if (!(flags & NGX_LUA_RE_COMPILE_ONCE)) { if (sd) { ngx_http_lua_regex_free_study_data(pool, sd); } if (re_comp.regex) { ngx_pfree(pool, re_comp.regex); } if (ctpl) { ngx_pfree(pool, ctpl); } if (cap) { ngx_pfree(pool, cap); } } return luaL_error(L, msg); }
static char * ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_mail_core_srv_conf_t *cscf = conf; size_t len, off; in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, m; struct sockaddr *sa; ngx_mail_listen_t *ls; ngx_mail_module_t *module; struct sockaddr_in *sin; ngx_mail_core_main_conf_t *cmcf; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif value = cf->args->elts; ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; u.listen = 1; if (ngx_parse_url(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in \"%V\" of the \"listen\" directive", u.err, &u.url); } return NGX_CONF_ERROR; } cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); ls = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { sa = (struct sockaddr *) ls[i].sockaddr; if (sa->sa_family != u.family) { continue; } switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: off = offsetof(struct sockaddr_in6, sin6_addr); len = 16; sin6 = (struct sockaddr_in6 *) sa; port = sin6->sin6_port; break; #endif default: /* AF_INET */ off = offsetof(struct sockaddr_in, sin_addr); len = 4; sin = (struct sockaddr_in *) sa; port = sin->sin_port; break; } if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) { continue; } if (port != u.port) { continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", &u.url); return NGX_CONF_ERROR; } ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; } ngx_memzero(ls, sizeof(ngx_mail_listen_t)); ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_MAIL_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->protocol == NULL) { continue; } for (i = 0; module->protocol->port[i]; i++) { if (module->protocol->port[i] == u.port) { cscf->protocol = module->protocol; break; } } } for (i = 2; i < cf->args->nelts; i++) { if (ngx_strcmp(value[i].data, "bind") == 0) { ls->bind = 1; continue; } if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; u_char buf[NGX_SOCKADDR_STRLEN]; sa = (struct sockaddr *) ls->sockaddr; if (sa->sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { ls->ipv6only = 2; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid ipv6only flags \"%s\"", &value[i].data[9]); return NGX_CONF_ERROR; } ls->bind = 1; } else { len = ngx_sock_ntop(sa, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "ipv6only is not supported " "on addr \"%*s\", ignored", len, buf); } continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "bind ipv6only is not supported " "on this platform"); return NGX_CONF_ERROR; #endif } if (ngx_strcmp(value[i].data, "ssl") == 0) { #if (NGX_MAIL_SSL) ls->ssl = 1; continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the \"ssl\" parameter requires " "ngx_mail_ssl_module"); return NGX_CONF_ERROR; #endif } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the invalid \"%V\" parameter", &value[i]); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static int ngx_http_lua_shdict_set_helper(lua_State *L, int flags) { int i, n; ngx_str_t key; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; ngx_str_t value; int value_type; double num; u_char c; lua_Number exptime = 0; u_char *p; ngx_rbtree_node_t *node; ngx_time_t *tp; ngx_shm_zone_t *zone; int forcible = 0; /* indicates whether to foricibly override other * valid entries */ int32_t user_flags = 0; n = lua_gettop(L); if (n != 3 && n != 4 && n != 5) { return luaL_error(L, "expecting 3, 4 or 5 arguments, " "but only seen %d", n); } zone = lua_touserdata(L, 1); if (zone == NULL) { return luaL_error(L, "bad \"zone\" argument"); } ctx = zone->data; if (lua_isnil(L, 2)) { lua_pushnil(L); lua_pushliteral(L, "nil key"); return 2; } key.data = (u_char *) luaL_checklstring(L, 2, &key.len); if (key.len == 0) { lua_pushnil(L); lua_pushliteral(L, "empty key"); return 2; } if (key.len > 65535) { lua_pushnil(L); lua_pushliteral(L, "key too long"); return 2; } hash = ngx_crc32_short(key.data, key.len); value_type = lua_type(L, 3); switch (value_type) { case LUA_TSTRING: value.data = (u_char *) lua_tolstring(L, 3, &value.len); break; case LUA_TNUMBER: value.len = sizeof(double); num = lua_tonumber(L, 3); value.data = (u_char *) # break; case LUA_TBOOLEAN: value.len = sizeof(u_char); c = lua_toboolean(L, 3) ? 1 : 0; value.data = &c; break; case LUA_TNIL: if (flags & (NGX_HTTP_LUA_SHDICT_ADD|NGX_HTTP_LUA_SHDICT_REPLACE)) { lua_pushnil(L); lua_pushliteral(L, "attempt to add or replace nil values"); return 2; } ngx_str_null(&value); break; default: lua_pushnil(L); lua_pushliteral(L, "bad value type"); return 2; } if (n >= 4) { exptime = luaL_checknumber(L, 4); if (exptime < 0) { exptime = 0; } } if (n == 5) { user_flags = (uint32_t) luaL_checkinteger(L, 5); } ngx_shmtx_lock(&ctx->shpool->mutex); #if 1 ngx_http_lua_shdict_expire(ctx, 1); #endif rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); dd("shdict lookup returned %d", (int) rc); if (flags & NGX_HTTP_LUA_SHDICT_REPLACE) { if (rc == NGX_DECLINED || rc == NGX_DONE) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "not found"); lua_pushboolean(L, forcible); return 3; } /* rc == NGX_OK */ goto replace; } if (flags & NGX_HTTP_LUA_SHDICT_ADD) { if (rc == NGX_OK) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "exists"); lua_pushboolean(L, forcible); return 3; } if (rc == NGX_DONE) { /* exists but expired */ dd("go to replace"); goto replace; } /* rc == NGX_DECLINED */ dd("go to insert"); goto insert; } if (rc == NGX_OK || rc == NGX_DONE) { if (value_type == LUA_TNIL) { goto remove; } replace: if (value.data && value.len == (size_t) sd->value_len) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry and value " "size matched, reusing it"); ngx_queue_remove(&sd->queue); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); sd->key_len = (u_short) key.len; if (exptime > 0) { tp = ngx_timeofday(); sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + (uint64_t) (exptime * 1000); } else { sd->expires = 0; } sd->user_flags = user_flags; sd->value_len = (uint32_t) value.len; dd("setting value type to %d", value_type); sd->value_type = (uint8_t) value_type; p = ngx_copy(sd->data, key.data, key.len); ngx_memcpy(p, value.data, value.len); ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, forcible); return 3; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry bug value size " "NOT matched, removing it first"); remove: ngx_queue_remove(&sd->queue); node = (ngx_rbtree_node_t *) ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); ngx_rbtree_delete(&ctx->sh->rbtree, node); ngx_slab_free_locked(ctx->shpool, node); } insert: /* rc == NGX_DECLINED or value size unmatch */ if (value.data == NULL) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, 0); return 3; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: creating a new entry"); n = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_lua_shdict_node_t, data) + key.len + value.len; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node == NULL) { if (flags & NGX_HTTP_LUA_SHDICT_SAFE_STORE) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "no memory"); return 2; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: overriding non-expired items " "due to memory shortage for entry \"%V\"", &key); for (i = 0; i < 30; i++) { if (ngx_http_lua_shdict_expire(ctx, 0) == 0) { break; } forcible = 1; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node != NULL) { goto allocated; } } ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 0); lua_pushliteral(L, "no memory"); lua_pushboolean(L, forcible); return 3; } allocated: sd = (ngx_http_lua_shdict_node_t *) &node->color; node->key = hash; sd->key_len = (u_short) key.len; if (exptime > 0) { tp = ngx_timeofday(); sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + (uint64_t) (exptime * 1000); } else { sd->expires = 0; } sd->user_flags = user_flags; sd->value_len = (uint32_t) value.len; dd("setting value type to %d", value_type); sd->value_type = (uint8_t) value_type; p = ngx_copy(sd->data, key.data, key.len); ngx_memcpy(p, value.data, value.len); ngx_rbtree_insert(&ctx->sh->rbtree, node); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushboolean(L, 1); lua_pushnil(L); lua_pushboolean(L, forcible); return 3; }
static char * ngx_rtmp_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { size_t len, off; in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, m; struct sockaddr *sa; ngx_rtmp_listen_t *ls; struct sockaddr_in *sin; ngx_rtmp_core_main_conf_t *cmcf; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif value = cf->args->elts; ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; u.listen = 1; if (ngx_parse_url(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in \"%V\" of the \"listen\" directive", u.err, &u.url); } return NGX_CONF_ERROR; } cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); ls = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { sa = (struct sockaddr *) ls[i].sockaddr; if (sa->sa_family != u.family) { continue; } switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: off = offsetof(struct sockaddr_in6, sin6_addr); len = 16; sin6 = (struct sockaddr_in6 *) sa; port = sin6->sin6_port; break; #endif default: /* AF_INET */ off = offsetof(struct sockaddr_in, sin_addr); len = 4; sin = (struct sockaddr_in *) sa; port = sin->sin_port; break; } if (ngx_memcmp(ls[i].sockaddr + off, (u_char *) &u.sockaddr + off, len) != 0) { continue; } if (port != u.port) { continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", &u.url); return NGX_CONF_ERROR; } ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; } ngx_memzero(ls, sizeof(ngx_rtmp_listen_t)); ngx_memcpy(ls->sockaddr, (u_char *) &u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_RTMP_MODULE) { continue; } } for (i = 2; i < cf->args->nelts; i++) { if (ngx_strcmp(value[i].data, "bind") == 0) { ls->bind = 1; continue; } if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; u_char buf[NGX_SOCKADDR_STRLEN]; sa = (struct sockaddr *) ls->sockaddr; if (sa->sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { ls->ipv6only = 0; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid ipv6only flags \"%s\"", &value[i].data[9]); return NGX_CONF_ERROR; } ls->bind = 1; } else { len = ngx_sock_ntop(sa, #if (nginx_version >= 1005003) ls->socklen, #endif buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "ipv6only is not supported " "on addr \"%*s\", ignored", len, buf); } continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "bind ipv6only is not supported " "on this platform"); return NGX_CONF_ERROR; #endif } if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) { if (ngx_strcmp(&value[i].data[13], "on") == 0) { ls->so_keepalive = 1; } else if (ngx_strcmp(&value[i].data[13], "off") == 0) { ls->so_keepalive = 2; } else { #if (NGX_HAVE_KEEPALIVE_TUNABLE) u_char *p, *end; ngx_str_t s; end = value[i].data + value[i].len; s.data = value[i].data + 13; p = ngx_strlchr(s.data, end, ':'); if (p == NULL) { p = end; } if (p > s.data) { s.len = p - s.data; ls->tcp_keepidle = ngx_parse_time(&s, 1); if (ls->tcp_keepidle == (time_t) NGX_ERROR) { goto invalid_so_keepalive; } } s.data = (p < end) ? (p + 1) : end; p = ngx_strlchr(s.data, end, ':'); if (p == NULL) { p = end; } if (p > s.data) { s.len = p - s.data; ls->tcp_keepintvl = ngx_parse_time(&s, 1); if (ls->tcp_keepintvl == (time_t) NGX_ERROR) { goto invalid_so_keepalive; } } s.data = (p < end) ? (p + 1) : end; if (s.data < end) { s.len = end - s.data; ls->tcp_keepcnt = ngx_atoi(s.data, s.len); if (ls->tcp_keepcnt == NGX_ERROR) { goto invalid_so_keepalive; } } if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0 && ls->tcp_keepcnt == 0) { goto invalid_so_keepalive; } ls->so_keepalive = 1; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the \"so_keepalive\" parameter accepts " "only \"on\" or \"off\" on this platform"); return NGX_CONF_ERROR; #endif } ls->bind = 1; continue; #if (NGX_HAVE_KEEPALIVE_TUNABLE) invalid_so_keepalive: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid so_keepalive value: \"%s\"", &value[i].data[13]); return NGX_CONF_ERROR; #endif } if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) { ls->proxy_protocol = 1; continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the invalid \"%V\" parameter", &value[i]); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
int ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, size_t key_len, int *value_type, u_char **str_value_buf, size_t *str_value_len, double *num_value, int *user_flags, int get_stale, int *is_stale) { ngx_str_t name; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; ngx_str_t value; if (zone == NULL) { return NGX_ERROR; } ctx = zone->data; name = ctx->name; hash = ngx_crc32_short(key, key_len); #if (NGX_DEBUG) ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "fetching key \"%*s\" in shared dict \"%V\"", key_len, key, &name); #endif /* NGX_DEBUG */ ngx_shmtx_lock(&ctx->shpool->mutex); #if 1 if (!get_stale) { ngx_http_lua_shdict_expire(ctx, 1); } #endif rc = ngx_http_lua_shdict_lookup(zone, hash, key, key_len, &sd); dd("shdict lookup returns %d", (int) rc); if (rc == NGX_DECLINED || (rc == NGX_DONE && !get_stale)) { ngx_shmtx_unlock(&ctx->shpool->mutex); *value_type = LUA_TNIL; return NGX_OK; } /* rc == NGX_OK || (rc == NGX_DONE && get_stale) */ *value_type = sd->value_type; dd("data: %p", sd->data); dd("key len: %d", (int) sd->key_len); value.data = sd->data + sd->key_len; value.len = (size_t) sd->value_len; if (*str_value_len < (size_t) value.len) { if (*value_type == LUA_TBOOLEAN) { ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_ERROR; } if (*value_type == LUA_TSTRING) { *str_value_buf = malloc(value.len); if (*str_value_buf == NULL) { ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_ERROR; } } } switch (*value_type) { case LUA_TSTRING: *str_value_len = value.len; ngx_memcpy(*str_value_buf, value.data, value.len); break; case LUA_TNUMBER: if (value.len != sizeof(double)) { ngx_shmtx_unlock(&ctx->shpool->mutex); ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua number value size found for key %*s " "in shared_dict %V: %z", key_len, key, &name, value.len); return NGX_ERROR; } *str_value_len = value.len; *num_value = *(double *) value.data; break; case LUA_TBOOLEAN: if (value.len != sizeof(u_char)) { ngx_shmtx_unlock(&ctx->shpool->mutex); ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua boolean value size found for key %*s " "in shared_dict %V: %z", key_len, key, &name, value.len); return NGX_ERROR; } ngx_memcpy(*str_value_buf, value.data, value.len); break; default: ngx_shmtx_unlock(&ctx->shpool->mutex); ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad value type found for key %*s in " "shared_dict %V: %d", key_len, key, &name, *value_type); return NGX_ERROR; } *user_flags = sd->user_flags; dd("user flags: %d", *user_flags); ngx_shmtx_unlock(&ctx->shpool->mutex); if (get_stale) { /* always return value, flags, stale */ *is_stale = (rc == NGX_DONE); return NGX_OK; } return NGX_OK; }
int ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key, size_t key_len, int value_type, u_char *str_value_buf, size_t str_value_len, double num_value, int exptime, int user_flags, char **errmsg, int *forcible) { int i, n; u_char c, *p; uint32_t hash; ngx_int_t rc; ngx_time_t *tp; ngx_rbtree_node_t *node; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; if (zone == NULL) { return NGX_ERROR; } dd("exptime: %d", exptime); ctx = zone->data; *forcible = 0; hash = ngx_crc32_short(key, key_len); switch (value_type) { case LUA_TSTRING: /* do nothing */ break; case LUA_TNUMBER: dd("num value: %lf", num_value); str_value_buf = (u_char *) &num_value; str_value_len = sizeof(double); break; case LUA_TBOOLEAN: c = num_value ? 1 : 0; str_value_buf = &c; str_value_len = sizeof(u_char); break; case LUA_TNIL: if (op & (NGX_HTTP_LUA_SHDICT_ADD|NGX_HTTP_LUA_SHDICT_REPLACE)) { *errmsg = "attempt to add or replace nil values"; return NGX_ERROR; } str_value_buf = NULL; str_value_len = 0; break; default: *errmsg = "unsupported value type"; return NGX_ERROR; } ngx_shmtx_lock(&ctx->shpool->mutex); #if 1 ngx_http_lua_shdict_expire(ctx, 1); #endif rc = ngx_http_lua_shdict_lookup(zone, hash, key, key_len, &sd); dd("lookup returns %d", (int) rc); if (op & NGX_HTTP_LUA_SHDICT_REPLACE) { if (rc == NGX_DECLINED || rc == NGX_DONE) { ngx_shmtx_unlock(&ctx->shpool->mutex); *errmsg = "not found"; return NGX_DECLINED; } /* rc == NGX_OK */ goto replace; } if (op & NGX_HTTP_LUA_SHDICT_ADD) { if (rc == NGX_OK) { ngx_shmtx_unlock(&ctx->shpool->mutex); *errmsg = "exists"; return NGX_DECLINED; } if (rc == NGX_DONE) { /* exists but expired */ dd("go to replace"); goto replace; } /* rc == NGX_DECLINED */ dd("go to insert"); goto insert; } if (rc == NGX_OK || rc == NGX_DONE) { if (value_type == LUA_TNIL) { goto remove; } replace: if (str_value_buf && str_value_len == (size_t) sd->value_len) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry and value " "size matched, reusing it"); ngx_queue_remove(&sd->queue); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); sd->key_len = (u_short) key_len; if (exptime > 0) { tp = ngx_timeofday(); sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + (uint64_t) exptime; } else { sd->expires = 0; } sd->user_flags = user_flags; sd->value_len = (uint32_t) str_value_len; dd("setting value type to %d", value_type); sd->value_type = (uint8_t) value_type; p = ngx_copy(sd->data, key, key_len); ngx_memcpy(p, str_value_buf, str_value_len); ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_OK; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry bug value size " "NOT matched, removing it first"); remove: ngx_queue_remove(&sd->queue); node = (ngx_rbtree_node_t *) ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); ngx_rbtree_delete(&ctx->sh->rbtree, node); ngx_slab_free_locked(ctx->shpool, node); } insert: /* rc == NGX_DECLINED or value size unmatch */ if (str_value_buf == NULL) { ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_OK; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: creating a new entry"); n = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_lua_shdict_node_t, data) + key_len + str_value_len; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node == NULL) { if (op & NGX_HTTP_LUA_SHDICT_SAFE_STORE) { ngx_shmtx_unlock(&ctx->shpool->mutex); *errmsg = "no memory"; return NGX_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: overriding non-expired items " "due to memory shortage for entry \"%*s\"", key_len, key); for (i = 0; i < 30; i++) { if (ngx_http_lua_shdict_expire(ctx, 0) == 0) { break; } *forcible = 1; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node != NULL) { goto allocated; } } ngx_shmtx_unlock(&ctx->shpool->mutex); *errmsg = "no memory"; return NGX_ERROR; } allocated: sd = (ngx_http_lua_shdict_node_t *) &node->color; node->key = hash; sd->key_len = (u_short) key_len; if (exptime > 0) { tp = ngx_timeofday(); sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + (uint64_t) exptime; } else { sd->expires = 0; } sd->user_flags = user_flags; sd->value_len = (uint32_t) str_value_len; dd("setting value type to %d", value_type); sd->value_type = (uint8_t) value_type; p = ngx_copy(sd->data, key, key_len); ngx_memcpy(p, str_value_buf, str_value_len); ngx_rbtree_insert(&ctx->sh->rbtree, node); ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_OK; }
ngx_int_t ngx_http_lua_shared_dict_get(ngx_shm_zone_t *zone, u_char *key_data, size_t key_len, ngx_http_lua_value_t *value) { u_char *data; size_t len; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; if (zone == NULL) { return NGX_ERROR; } hash = ngx_crc32_short(key_data, key_len); ctx = zone->data; ngx_shmtx_lock(&ctx->shpool->mutex); rc = ngx_http_lua_shdict_lookup(zone, hash, key_data, key_len, &sd); dd("shdict lookup returned %d", (int) rc); if (rc == NGX_DECLINED || rc == NGX_DONE) { ngx_shmtx_unlock(&ctx->shpool->mutex); return rc; } /* rc == NGX_OK */ value->type = sd->value_type; dd("type: %d", (int) value->type); data = sd->data + sd->key_len; len = (size_t) sd->value_len; switch (value->type) { case LUA_TSTRING: if (value->value.s.data == NULL || value->value.s.len == 0) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "no string buffer " "initialized"); ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_ERROR; } if (len > value->value.s.len) { len = value->value.s.len; } else { value->value.s.len = len; } ngx_memcpy(value->value.s.data, data, len); break; case LUA_TNUMBER: if (len != sizeof(double)) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua number " "value size found for key %*s: %lu", key_len, key_data, (unsigned long) len); ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_ERROR; } ngx_memcpy(&value->value.b, data, len); break; case LUA_TBOOLEAN: if (len != sizeof(u_char)) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua boolean " "value size found for key %*s: %lu", key_len, key_data, (unsigned long) len); ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_ERROR; } value->value.b = *data; break; default: ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua value type " "found for key %*s: %d", key_len, key_data, (int) value->type); ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_ERROR; } ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_OK; }
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->data[i] == '\0') { 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; }
//初始化配置结构 static char * ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_core_conf_t *ccf = conf; ngx_conf_init_value(ccf->daemon, 1); ngx_conf_init_value(ccf->master, 1); ngx_conf_init_msec_value(ccf->timer_resolution, 0); ngx_conf_init_value(ccf->worker_processes, 1); ngx_conf_init_value(ccf->debug_points, 0); #if (NGX_HAVE_SCHED_SETAFFINITY) if (ccf->cpu_affinity_n && ccf->cpu_affinity_n != 1 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes) { ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "number of the \"worker_processes\" is not equal to " "the number of the \"worker_cpu_affinity\" mask, " "using last mask for remaining worker processes"); } #endif #if (NGX_THREADS) ngx_conf_init_value(ccf->worker_threads, 0); ngx_threads_n = ccf->worker_threads; ngx_conf_init_size_value(ccf->thread_stack_size, 2 * 1024 * 1024); #endif if (ccf->pid.len == 0) { ngx_str_set(&ccf->pid, NGX_PID_PATH); } //转化成全路径名称,实际上是在pid字符串前面加上NGX_PREFIX /usr/local/nginx if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) { return NGX_CONF_ERROR; } ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);//.oldbin ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len); if (ccf->oldpid.data == NULL) { return NGX_CONF_ERROR; } ///usr/local/nginx/logs/nginx.pid.oldbin---oldpid.data ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len), NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT)); #if !(NGX_WIN32) if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) { struct group *grp; struct passwd *pwd; ngx_set_errno(0); //获取账户信息 pwd = getpwnam(NGX_USER); if (pwd == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "getpwnam(\"" NGX_USER "\") failed"); return NGX_CONF_ERROR; } ccf->username = NGX_USER; ccf->user = pwd->pw_uid; ngx_set_errno(0); //获取用户组信息 grp = getgrnam(NGX_GROUP); if (grp == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "getgrnam(\"" NGX_GROUP "\") failed"); return NGX_CONF_ERROR; } ccf->group = grp->gr_gid; } if (ccf->lock_file.len == 0) { ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH); } //"/usr/local/nginx/logs/nginx.lock" if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) { return NGX_CONF_ERROR; } { ngx_str_t lock_file; lock_file = cycle->old_cycle->lock_file; if (lock_file.len) { lock_file.len--; if (ccf->lock_file.len != lock_file.len || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len) != 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "\"lock_file\" could not be changed, ignored"); } cycle->lock_file.len = lock_file.len + 1; lock_file.len += sizeof(".accept"); //在内存池上分配一个段内存,并将src copy到dest当中 cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file); if (cycle->lock_file.data == NULL) { return NGX_CONF_ERROR; } } else { cycle->lock_file.len = ccf->lock_file.len + 1; cycle->lock_file.data = ngx_pnalloc(cycle->pool, ccf->lock_file.len + sizeof(".accept")); if (cycle->lock_file.data == NULL) { return NGX_CONF_ERROR; } ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data, ccf->lock_file.len), ".accept", sizeof(".accept")); } } #endif return NGX_CONF_OK; }
static char * ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_core_conf_t *ccf = conf; #if (NGX_HAVE_CPU_AFFINITY) ngx_int_t i, n; CPU_SET_T *mask; #endif if (!ccf->worker_processes) { ccf->worker_processes = NGX_CONF_UNSET; } ngx_conf_init_value(ccf->worker_processes, ngx_ncpu); ngx_conf_init_value(ccf->daemon, 1); ngx_conf_init_value(ccf->master, 1); ngx_conf_init_msec_value(ccf->timer_resolution, 0); ngx_conf_init_value(ccf->debug_points, 0); #if (NGX_HAVE_CPU_AFFINITY) if (ccf->cpu_affinity_n == 0) { ccf->cpu_affinity = NULL; n = ngx_ncpu - 1; if (ngx_ncpu > 0 && ngx_ncpu <= CPU_SETSIZE) { mask = ngx_palloc(cycle->pool, ccf->worker_processes * sizeof(CPU_SET_T)); if (mask == NULL) { return NGX_CONF_ERROR; } ccf->cpu_affinity_n = ccf->worker_processes; ccf->cpu_affinity = mask; /* RR for cpu assign */ for (i = 0; i < ccf->worker_processes; i++) { CPU_ZERO(&mask[i]); CPU_SET(n, &mask[i]); if (--n < 0) { n = ngx_ncpu - 1; } } } else { ccf->cpu_affinity_n = 0; ccf->cpu_affinity = NULL; } } if (ccf->cpu_affinity_n && ccf->cpu_affinity_n != 1 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes) { ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "the number of \"worker_processes\" is not equal to " "the number of \"worker_cpu_affinity\" masks, " "using last mask for remaining worker processes"); } #endif #if (NGX_THREADS) ngx_conf_init_value(ccf->worker_threads, 0); ngx_threads_n = ccf->worker_threads; ngx_conf_init_size_value(ccf->thread_stack_size, 2 * 1024 * 1024); #endif if (ccf->pid.len == 0) { ngx_str_set(&ccf->pid, NGX_PID_PATH); } if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) { return NGX_CONF_ERROR; } ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT); ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len); if (ccf->oldpid.data == NULL) { return NGX_CONF_ERROR; } ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len), NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT)); #if !(NGX_WIN32) if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) { struct group *grp; struct passwd *pwd; ngx_set_errno(0); pwd = getpwnam(NGX_USER); if (pwd == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "getpwnam(\"" NGX_USER "\") failed"); return NGX_CONF_ERROR; } ccf->username = NGX_USER; ccf->user = pwd->pw_uid; ngx_set_errno(0); grp = getgrnam(NGX_GROUP); if (grp == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "getgrnam(\"" NGX_GROUP "\") failed"); return NGX_CONF_ERROR; } ccf->group = grp->gr_gid; } if (ccf->lock_file.len == 0) { ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH); } if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) { return NGX_CONF_ERROR; } { ngx_str_t lock_file; lock_file = cycle->old_cycle->lock_file; if (lock_file.len) { lock_file.len--; if (ccf->lock_file.len != lock_file.len || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len) != 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "\"lock_file\" could not be changed, ignored"); } cycle->lock_file.len = lock_file.len + 1; lock_file.len += sizeof(".accept"); cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file); if (cycle->lock_file.data == NULL) { return NGX_CONF_ERROR; } } else { cycle->lock_file.len = ccf->lock_file.len + 1; cycle->lock_file.data = ngx_pnalloc(cycle->pool, ccf->lock_file.len + sizeof(".accept")); if (cycle->lock_file.data == NULL) { return NGX_CONF_ERROR; } ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data, ccf->lock_file.len), ".accept", sizeof(".accept")); } } #endif return NGX_CONF_OK; }
static ngx_int_t ngx_http_limit_conn_handler(ngx_http_request_t *r) { size_t len, n; uint32_t hash; ngx_uint_t i; ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node; ngx_pool_cleanup_t *cln; ngx_http_variable_value_t *vv; ngx_http_limit_conn_ctx_t *ctx; ngx_http_limit_conn_node_t *lc; ngx_http_limit_conn_conf_t *lccf; ngx_http_limit_conn_limit_t *limits; ngx_http_limit_conn_cleanup_t *lccln; if (r->main->limit_conn_set) { return NGX_DECLINED; } lccf = ngx_http_get_module_loc_conf(r, ngx_http_limit_conn_module); limits = lccf->limits.elts; for (i = 0; i < lccf->limits.nelts; i++) { ctx = limits[i].shm_zone->data; vv = ngx_http_get_indexed_variable(r, ctx->index); if (vv == NULL || vv->not_found) { continue; } len = vv->len; if (len == 0) { continue; } if (len > 255) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the value of the \"%V\" variable " "is more than 255 bytes: \"%v\"", &ctx->var, vv); continue; } r->main->limit_conn_set = 1; hash = ngx_crc32_short(vv->data, len); shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); node = ngx_http_limit_conn_lookup(ctx->rbtree, vv, hash); if (node == NULL) { n = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_limit_conn_node_t, data) + len; node = ngx_slab_alloc_locked(shpool, n); if (node == NULL) { ngx_shmtx_unlock(&shpool->mutex); ngx_http_limit_conn_cleanup_all(r->pool); return NGX_HTTP_SERVICE_UNAVAILABLE; } lc = (ngx_http_limit_conn_node_t *) &node->color; node->key = hash; lc->len = (u_char) len; lc->conn = 1; ngx_memcpy(lc->data, vv->data, len); ngx_rbtree_insert(ctx->rbtree, node); } else { lc = (ngx_http_limit_conn_node_t *) &node->color; if ((ngx_uint_t) lc->conn >= limits[i].conn) { ngx_shmtx_unlock(&shpool->mutex); ngx_log_error(lccf->log_level, r->connection->log, 0, "limiting connections by zone \"%V\"", &limits[i].shm_zone->shm.name); ngx_http_limit_conn_cleanup_all(r->pool); return NGX_HTTP_SERVICE_UNAVAILABLE; } lc->conn++; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "limit zone: %08XD %d", node->key, lc->conn); ngx_shmtx_unlock(&shpool->mutex); cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_limit_conn_cleanup_t)); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_limit_conn_cleanup; lccln = cln->data; lccln->shm_zone = limits[i].shm_zone; lccln->node = node; } return NGX_DECLINED; }
static int ngx_http_lua_socket_udp_setpeername(lua_State *L) { ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_str_t host; int port; ngx_resolver_ctx_t *rctx, temp; ngx_http_core_loc_conf_t *clcf; int saved_top; int n; u_char *p; size_t len; ngx_url_t url; ngx_int_t rc; ngx_http_lua_loc_conf_t *llcf; ngx_udp_connection_t *uc; int timeout; ngx_http_lua_socket_udp_upstream_t *u; n = lua_gettop(L); if (n != 2 && n != 3) { return luaL_error(L, "ngx.socket.udp setpeername: expecting 2 or 3 " "arguments (including the object), but seen %d", n); } lua_pushlightuserdata(L, &ngx_http_lua_request_key); lua_rawget(L, LUA_GLOBALSINDEX); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request found"); } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { return luaL_error(L, "no ctx found"); } ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT); luaL_checktype(L, 1, LUA_TTABLE); p = (u_char *) luaL_checklstring(L, 2, &len); host.data = ngx_palloc(r->pool, len + 1); if (host.data == NULL) { return luaL_error(L, "out of memory"); } host.len = len; ngx_memcpy(host.data, p, len); host.data[len] = '\0'; if (n == 3) { port = luaL_checkinteger(L, 3); if (port < 0 || port > 65536) { lua_pushnil(L); lua_pushfstring(L, "bad port number: %d", port); return 2; } } else { /* n == 2 */ port = 0; } lua_rawgeti(L, 1, SOCKET_CTX_INDEX); u = lua_touserdata(L, -1); lua_pop(L, 1); if (u) { if (u->waiting) { lua_pushnil(L); lua_pushliteral(L, "socket busy"); return 2; } if (u->udp_connection.connection) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua udp socket reconnect without shutting down"); ngx_http_lua_socket_udp_finalize(r, u); } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua reuse socket upstream ctx"); } else { u = lua_newuserdata(L, sizeof(ngx_http_lua_socket_udp_upstream_t)); if (u == NULL) { return luaL_error(L, "out of memory"); } #if 1 lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ lua_pushcfunction(L, ngx_http_lua_socket_udp_upstream_destroy); lua_setfield(L, -2, "__gc"); lua_setmetatable(L, -2); #endif lua_rawseti(L, 1, SOCKET_CTX_INDEX); } ngx_memzero(u, sizeof(ngx_http_lua_socket_udp_upstream_t)); u->request = r; /* set the controlling request */ llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); u->conf = llcf; uc = &u->udp_connection; uc->log = *r->connection->log; dd("lua peer connection log: %p", &uc->log); lua_rawgeti(L, 1, SOCKET_TIMEOUT_INDEX); timeout = (ngx_int_t) lua_tointeger(L, -1); lua_pop(L, 1); if (timeout > 0) { u->read_timeout = (ngx_msec_t) timeout; } else { u->read_timeout = u->conf->read_timeout; } ngx_memzero(&url, sizeof(ngx_url_t)); url.url.len = host.len; url.url.data = host.data; url.default_port = port; url.no_resolve = 1; if (ngx_parse_url(r->pool, &url) != NGX_OK) { lua_pushnil(L); if (url.err) { lua_pushfstring(L, "failed to parse host name \"%s\": %s", host.data, url.err); } else { lua_pushfstring(L, "failed to parse host name \"%s\"", host.data); } return 2; } u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); if (u->resolved == NULL) { return luaL_error(L, "out of memory"); } if (url.addrs && url.addrs[0].sockaddr) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua udp socket network address given directly"); u->resolved->sockaddr = url.addrs[0].sockaddr; u->resolved->socklen = url.addrs[0].socklen; u->resolved->naddrs = 1; u->resolved->host = url.addrs[0].name; } else { u->resolved->host = host; u->resolved->port = (in_port_t) port; } if (u->resolved->sockaddr) { rc = ngx_http_lua_socket_resolve_retval_handler(r, u, L); if (rc == NGX_AGAIN) { return lua_yield(L, 0); } return rc; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); temp.name = host; rctx = ngx_resolve_start(clcf->resolver, &temp); if (rctx == NULL) { u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_RESOLVER; lua_pushnil(L); lua_pushliteral(L, "failed to start the resolver"); return 2; } if (rctx == NGX_NO_RESOLVER) { u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_RESOLVER; lua_pushnil(L); lua_pushfstring(L, "no resolver defined to resolve \"%s\"", host.data); return 2; } rctx->name = host; rctx->type = NGX_RESOLVE_A; rctx->handler = ngx_http_lua_socket_resolve_handler; rctx->data = u; rctx->timeout = clcf->resolver_timeout; u->resolved->ctx = rctx; saved_top = lua_gettop(L); if (ngx_resolve_name(rctx) != NGX_OK) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua udp socket fail to run resolver immediately"); u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_RESOLVER; u->resolved->ctx = NULL; lua_pushnil(L); lua_pushfstring(L, "%s could not be resolved", host.data); return 2; } if (u->waiting == 1) { /* resolved and already connecting */ return lua_yield(L, 0); } n = lua_gettop(L) - saved_top; if (n) { /* errors occurred during resolving or connecting * or already connected */ return n; } /* still resolving */ u->waiting = 1; u->prepare_retvals = ngx_http_lua_socket_resolve_retval_handler; ctx->data = u; ctx->udp_socket_busy = 1; ctx->udp_socket_ready = 0; if (ctx->entered_content_phase) { r->write_event_handler = ngx_http_lua_content_wev_handler; } return lua_yield(L, 0); }
static ngx_int_t ngx_stream_limit_conn_handler(ngx_stream_session_t *s) { size_t n; uint32_t hash; ngx_str_t key; ngx_uint_t i; ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node; ngx_pool_cleanup_t *cln; struct sockaddr_in *sin; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif ngx_stream_limit_conn_ctx_t *ctx; ngx_stream_limit_conn_node_t *lc; ngx_stream_limit_conn_conf_t *lccf; ngx_stream_limit_conn_limit_t *limits; ngx_stream_limit_conn_cleanup_t *lccln; switch (s->connection->sockaddr->sa_family) { case AF_INET: sin = (struct sockaddr_in *) s->connection->sockaddr; key.len = sizeof(in_addr_t); key.data = (u_char *) &sin->sin_addr; break; #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) s->connection->sockaddr; key.len = sizeof(struct in6_addr); key.data = sin6->sin6_addr.s6_addr; break; #endif default: return NGX_DECLINED; } hash = ngx_crc32_short(key.data, key.len); lccf = ngx_stream_get_module_srv_conf(s, ngx_stream_limit_conn_module); limits = lccf->limits.elts; for (i = 0; i < lccf->limits.nelts; i++) { ctx = limits[i].shm_zone->data; shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); node = ngx_stream_limit_conn_lookup(ctx->rbtree, &key, hash); if (node == NULL) { n = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_stream_limit_conn_node_t, data) + key.len; node = ngx_slab_alloc_locked(shpool, n); if (node == NULL) { ngx_shmtx_unlock(&shpool->mutex); ngx_stream_limit_conn_cleanup_all(s->connection->pool); return NGX_ABORT; } lc = (ngx_stream_limit_conn_node_t *) &node->color; node->key = hash; lc->len = (u_char) key.len; lc->conn = 1; ngx_memcpy(lc->data, key.data, key.len); ngx_rbtree_insert(ctx->rbtree, node); } else { lc = (ngx_stream_limit_conn_node_t *) &node->color; if ((ngx_uint_t) lc->conn >= limits[i].conn) { ngx_shmtx_unlock(&shpool->mutex); ngx_log_error(lccf->log_level, s->connection->log, 0, "limiting connections by zone \"%V\"", &limits[i].shm_zone->shm.name); ngx_stream_limit_conn_cleanup_all(s->connection->pool); return NGX_ABORT; } lc->conn++; } ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "limit conn: %08XD %d", node->key, lc->conn); ngx_shmtx_unlock(&shpool->mutex); cln = ngx_pool_cleanup_add(s->connection->pool, sizeof(ngx_stream_limit_conn_cleanup_t)); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_stream_limit_conn_cleanup; lccln = cln->data; lccln->shm_zone = limits[i].shm_zone; lccln->node = node; } return NGX_DECLINED; }
static ngx_int_t ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t *cl; ngx_http_sub_ctx_t *ctx; ngx_http_sub_loc_conf_t *slcf; ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module); if (ctx == NULL) { return ngx_http_next_body_filter(r, in); } if ((in == NULL && ctx->buf == NULL && ctx->in == NULL && ctx->busy == NULL)) { return ngx_http_next_body_filter(r, in); } if (ctx->once && (ctx->buf == NULL || ctx->in == NULL)) { if (ctx->busy) { if (ngx_http_sub_output(r, ctx) == NGX_ERROR) { return NGX_ERROR; } } return ngx_http_next_body_filter(r, in); } /* add the incoming chain to the chain ctx->in */ if (in) { if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) { return NGX_ERROR; } } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http sub filter \"%V\"", &r->uri); while (ctx->in || ctx->buf) { if (ctx->buf == NULL ){ ctx->buf = ctx->in->buf; ctx->in = ctx->in->next; ctx->pos = ctx->buf->pos; } if (ctx->state == sub_start_state) { ctx->copy_start = ctx->pos; ctx->copy_end = ctx->pos; } b = NULL; while (ctx->pos < ctx->buf->last) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "saved: \"%V\" state: %d", &ctx->saved, ctx->state); rc = ngx_http_sub_parse(r, ctx); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "parse: %d, looked: \"%V\" %p-%p", rc, &ctx->looked, ctx->copy_start, ctx->copy_end); if (rc == NGX_ERROR) { return rc; } if (ctx->copy_start != ctx->copy_end) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "saved: \"%V\"", &ctx->saved); if (ctx->saved.len) { if (ctx->free) { cl = ctx->free; ctx->free = ctx->free->next; b = cl->buf; ngx_memzero(b, sizeof(ngx_buf_t)); } else { b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; } b->pos = ngx_pnalloc(r->pool, ctx->saved.len); if (b->pos == NULL) { return NGX_ERROR; } ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len); b->last = b->pos + ctx->saved.len; b->memory = 1; *ctx->last_out = cl; ctx->last_out = &cl->next; ctx->saved.len = 0; } if (ctx->free) { cl = ctx->free; ctx->free = ctx->free->next; b = cl->buf; } else { b = ngx_alloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; } ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t)); b->pos = ctx->copy_start; b->last = ctx->copy_end; b->shadow = NULL; b->last_buf = 0; b->recycled = 0; if (b->in_file) { b->file_last = b->file_pos + (b->last - ctx->buf->pos); b->file_pos += b->pos - ctx->buf->pos; } cl->next = NULL; *ctx->last_out = cl; ctx->last_out = &cl->next; } if (ctx->state == sub_start_state) { ctx->copy_start = ctx->pos; ctx->copy_end = ctx->pos; } else { ctx->copy_start = NULL; ctx->copy_end = NULL; } if (rc == NGX_AGAIN) { continue; } /* rc == NGX_OK */ b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); if (ctx->sub.data == NULL) { if (ngx_http_complex_value(r, &slcf->value, &ctx->sub) != NGX_OK) { return NGX_ERROR; } } if (ctx->sub.len) { b->memory = 1; b->pos = ctx->sub.data; b->last = ctx->sub.data + ctx->sub.len; } else { b->sync = 1; } cl->buf = b; cl->next = NULL; *ctx->last_out = cl; ctx->last_out = &cl->next; ctx->once = slcf->once; continue; } if (ctx->buf->last_buf || ngx_buf_in_memory(ctx->buf)) { if (b == NULL) { if (ctx->free) { cl = ctx->free; ctx->free = ctx->free->next; b = cl->buf; ngx_memzero(b, sizeof(ngx_buf_t)); } else { b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; } b->sync = 1; cl->next = NULL; *ctx->last_out = cl; ctx->last_out = &cl->next; } b->last_buf = ctx->buf->last_buf; b->shadow = ctx->buf; b->recycled = ctx->buf->recycled; } ctx->buf = NULL; ctx->saved.len = ctx->looked.len; ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len); } if (ctx->out == NULL && ctx->busy == NULL) { return NGX_OK; } return ngx_http_sub_output(r, ctx); }
static ngx_int_t hexin_http_percn_post_handler(ngx_http_request_t *r) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "进入 hexin_http_percn_post_handler 方法.."); hexin_http_percn_loc_conf_t *plcf; hexin_http_percn_ctx_t *ctx; ngx_http_variable_value_t *receivers, *common, *block_size; u_char *buf, *unescapebuf; ngx_int_t rc; plcf = ngx_http_get_module_loc_conf(r, hexin_http_percn_module); ctx = ngx_http_get_module_ctx(r, hexin_http_percn_module); //获得分割所依据的字段值,并获得所以子请求通用的Form参数 receivers = ngx_http_get_indexed_variable(r, plcf->receivers_index); common = ngx_http_get_indexed_variable(r, plcf->common_index); ctx->common = common; ctx->receivers_complete_val_len = receivers->len; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "接收者为: %v, ----- 通用体: %v", receivers, common); buf = ngx_pnalloc(r->pool, receivers->len); if(buf == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "分配 buf 内存失败!"); return NGX_ERROR; } ngx_memcpy(buf, receivers->data, receivers->len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "URL 解码前: %s", buf); //进行URI 解码 unescapebuf = ngx_pnalloc(r->pool, receivers->len); ngx_unescape_uri(&unescapebuf, &buf, receivers->len, NGX_ESCAPE_ARGS); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "URL 解码后: %s", buf); //获取分割的尺寸大小 block_size = ngx_http_get_indexed_variable(r, plcf->block_size_index); ngx_int_t block_size_int = ngx_atoi(block_size->data, block_size->len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "推送块尺寸为: %d", block_size_int); //以','为分割符进行切割 并循环创建子请求 char *p, *brkt; ngx_int_t count = 1; size_t len = 0; size_t fla_len = 0; u_char* next = receivers->data; for (p = strtok_r( (char *)buf, ",", &brkt); p; p = strtok_r(NULL, ",", &brkt)) { len += ngx_strlen(p); fla_len++; if((count++) % (block_size_int) == 0) { //获得块长度 u_char* part ; size_t mem_len = len + 3 * fla_len; //分配块内存 并拷贝内存赋值 part = ngx_pnalloc(r->pool, mem_len - 3); ngx_memcpy(part, next, mem_len -3); next = next + mem_len; ctx->receivers_part_val_len = mem_len - 3; ctx->receivers_part_val = part; //================= hexin_http_percn_subrequest_t *parsed_sr; ngx_http_request_t *sr; /* subrequest object */ rc = hexin_http_percn_create_subrequest(r, &parsed_sr); if (rc != NGX_OK) { return rc; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "创建子查询."); rc = ngx_http_subrequest(r, parsed_sr->location, NULL, &sr, NULL, 0); if (rc != NGX_OK) { return NGX_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "创建子查询结束, 开始调整参数."); rc = hexin_http_percn_adjust_subrequest(sr, parsed_sr); if (rc != NGX_OK) { return rc; } //================= len = 0; fla_len = 0; } } //剩余请求 if(len != 0) { u_char* part ; size_t mem_len = len + 3 * fla_len; part = ngx_pnalloc(r->pool, mem_len - 3); ngx_memcpy(part, next, mem_len -3); ctx->receivers_part_val_len = mem_len - 3; ctx->receivers_part_val = part; //================= hexin_http_percn_subrequest_t *parsed_sr; ngx_http_request_t *sr; /* subrequest object */ rc = hexin_http_percn_create_subrequest(r, &parsed_sr); if (rc != NGX_OK) { return rc; } rc = ngx_http_subrequest(r, parsed_sr->location, NULL, &sr, NULL, 0); if (rc != NGX_OK) { return NGX_ERROR; } rc = hexin_http_percn_adjust_subrequest(sr, parsed_sr); if (rc != NGX_OK) { return rc; } //================= len = 0; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, " hexin_http_percn_post_handler 方法 结束.."); return NGX_OK; }
static int ngx_http_lua_ngx_req_set_body_file(lua_State *L) { u_char *p; ngx_http_request_t *r; int n; ngx_http_request_body_t *rb; ngx_temp_file_t *tf; ngx_buf_t *b; ngx_str_t name; ngx_int_t rc; int clean; ngx_open_file_info_t of; ngx_str_t key, value; ngx_pool_cleanup_t *cln; ngx_pool_cleanup_file_t *clnf; ngx_err_t err; ngx_chain_t *cl; ngx_buf_tag_t tag; n = lua_gettop(L); if (n != 1 && n != 2) { return luaL_error(L, "expecting 1 or 2 arguments but seen %d", n); } p = (u_char *) luaL_checklstring(L, 1, &name.len); r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request found"); } ngx_http_lua_check_fake_request(L, r); if (r->discard_body) { return luaL_error(L, "request body already discarded asynchronously"); } if (r->request_body == NULL) { return luaL_error(L, "request body not read yet"); } name.data = ngx_palloc(r->pool, name.len + 1); if (name.data == NULL) { return luaL_error(L, "no memory"); } ngx_memcpy(name.data, p, name.len); name.data[name.len] = '\0'; if (n == 2) { luaL_checktype(L, 2, LUA_TBOOLEAN); clean = lua_toboolean(L, 2); } else { clean = 0; } dd("clean: %d", (int) clean); rb = r->request_body; /* clean up existing r->request_body->bufs (if any) */ tag = (ngx_buf_tag_t) &ngx_http_lua_module; if (rb->bufs) { dd("XXX reusing buf"); for (cl = rb->bufs; cl; cl = cl->next) { if (cl->buf->tag == tag && cl->buf->temporary) { dd("free old request body buffer: size:%d", (int) ngx_buf_size(cl->buf)); ngx_pfree(r->pool, cl->buf->start); cl->buf->tag = (ngx_buf_tag_t) NULL; cl->buf->temporary = 0; } } rb->bufs->next = NULL; b = rb->bufs->buf; ngx_memzero(b, sizeof(ngx_buf_t)); b->tag = tag; rb->buf = NULL; } else { dd("XXX creating new buf"); rb->bufs = ngx_alloc_chain_link(r->pool); if (rb->bufs == NULL) { return luaL_error(L, "no memory"); } rb->bufs->next = NULL; b = ngx_calloc_buf(r->pool); if (b == NULL) { return luaL_error(L, "no memory"); } b->tag = tag; rb->bufs->buf = b; rb->buf = NULL; } b->last_in_chain = 1; /* just make r->request_body->temp_file a bare stub */ tf = rb->temp_file; if (tf) { if (tf->file.fd != NGX_INVALID_FILE) { dd("cleaning temp file %.*s", (int) tf->file.name.len, tf->file.name.data); ngx_http_lua_pool_cleanup_file(r->pool, tf->file.fd); ngx_memzero(tf, sizeof(ngx_temp_file_t)); tf->file.fd = NGX_INVALID_FILE; dd("temp file cleaned: %.*s", (int) tf->file.name.len, tf->file.name.data); } } else { tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (tf == NULL) { return luaL_error(L, "no memory"); } tf->file.fd = NGX_INVALID_FILE; rb->temp_file = tf; } /* read the file info and construct an in-file buf */ ngx_memzero(&of, sizeof(ngx_open_file_info_t)); of.directio = NGX_OPEN_FILE_DIRECTIO_OFF; if (ngx_http_lua_open_and_stat_file(name.data, &of, r->connection->log) != NGX_OK) { return luaL_error(L, "%s \"%s\" failed", of.failed, name.data); } dd("XXX new body file fd: %d", of.fd); tf->file.fd = of.fd; tf->file.name = name; tf->file.log = r->connection->log; tf->file.directio = 0; if (of.size == 0) { if (clean) { if (ngx_delete_file(name.data) == NGX_FILE_ERROR) { err = ngx_errno; if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_delete_file_n " \"%s\" failed", name.data); } } } if (ngx_close_file(of.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_file_n " \"%s\" failed", name.data); } r->request_body->bufs = NULL; r->request_body->buf = NULL; goto set_header; } /* register file cleanup hook */ cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t)); if (cln == NULL) { return luaL_error(L, "no memory"); } cln->handler = clean ? ngx_pool_delete_file : ngx_pool_cleanup_file; clnf = cln->data; clnf->fd = of.fd; clnf->name = name.data; clnf->log = r->pool->log; b->file = &tf->file; if (b->file == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("XXX file size: %d", (int) of.size); b->file_pos = 0; b->file_last = of.size; b->in_file = 1; dd("buf file: %p, f:%u", b->file, b->in_file); set_header: /* override input header Content-Length (value must be null terminated) */ value.data = ngx_palloc(r->pool, NGX_OFF_T_LEN + 1); if (value.data == NULL) { return luaL_error(L, "no memory"); } value.len = ngx_sprintf(value.data, "%O", of.size) - value.data; value.data[value.len] = '\0'; r->headers_in.content_length_n = of.size; if (r->headers_in.content_length) { r->headers_in.content_length->value.data = value.data; r->headers_in.content_length->value.len = value.len; } else { ngx_str_set(&key, "Content-Length"); rc = ngx_http_lua_set_input_header(r, key, value, 1 /* override */); if (rc != NGX_OK) { return luaL_error(L, "failed to reset the Content-Length " "input header"); } } return 0; }
ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r, ngx_http_client_body_handler_pt post_handler) { size_t preread; ssize_t size; ngx_buf_t *b; ngx_chain_t *cl, **next; ngx_temp_file_t *tf; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; if (r->request_body || r->discard_body) { post_handler(r); return NGX_OK; } if (ngx_http_test_expect(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (rb == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->request_body = rb; if (r->headers_in.content_length_n < 0) { post_handler(r); return NGX_OK; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_in.content_length_n == 0) { if (r->request_body_in_file_only) { tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (tf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } tf->file.fd = NGX_INVALID_FILE; tf->file.log = r->connection->log; tf->path = clcf->client_body_temp_path; tf->pool = r->pool; tf->warn = "a client request body is buffered to a temporary file"; tf->log_level = r->request_body_file_log_level; tf->persistent = r->request_body_in_persistent_file; tf->clean = r->request_body_in_clean_file; if (r->request_body_file_group_access) { tf->access = 0660; } rb->temp_file = tf; if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, tf->persistent, tf->clean, tf->access) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } post_handler(r); return NGX_OK; } rb->post_handler = post_handler; /* * set by ngx_pcalloc(): * * rb->bufs = NULL; * rb->buf = NULL; * rb->rest = 0; */ preread = r->header_in->last - r->header_in->pos; if (preread) { /* there is the pre-read part of the request body */ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http client request body preread %uz", preread); b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->temporary = 1; b->start = r->header_in->pos; b->pos = r->header_in->pos; b->last = r->header_in->last; b->end = r->header_in->end; rb->bufs = ngx_alloc_chain_link(r->pool); if (rb->bufs == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } rb->bufs->buf = b; rb->bufs->next = NULL; rb->buf = b; if ((off_t) preread >= r->headers_in.content_length_n) { /* the whole request body was pre-read */ r->header_in->pos += (size_t) r->headers_in.content_length_n; r->request_length += r->headers_in.content_length_n; if (r->request_body_in_file_only) { if (ngx_http_write_request_body(r, rb->bufs) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } post_handler(r); return NGX_OK; } /* * to not consider the body as pipelined request in * ngx_http_set_keepalive() */ r->header_in->pos = r->header_in->last; r->request_length += preread; rb->rest = r->headers_in.content_length_n - preread; if (rb->rest <= (off_t) (b->end - b->last)) { /* the whole request body may be placed in r->header_in */ rb->to_write = rb->bufs; r->read_event_handler = ngx_http_read_client_request_body_handler; return ngx_http_do_read_client_request_body(r); } next = &rb->bufs->next; } else { b = NULL; rb->rest = r->headers_in.content_length_n; next = &rb->bufs; } size = clcf->client_body_buffer_size; size += size >> 2; if (rb->rest < size) { size = (ssize_t) rb->rest; if (r->request_body_in_single_buf) { size += preread; } } else { size = clcf->client_body_buffer_size; /* disable copying buffer for r->request_body_in_single_buf */ b = NULL; } rb->buf = ngx_create_temp_buf(r->pool, size); if (rb->buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->buf = rb->buf; cl->next = NULL; if (b && r->request_body_in_single_buf) { size = b->last - b->pos; ngx_memcpy(rb->buf->pos, b->pos, size); rb->buf->last += size; next = &rb->bufs; } *next = cl; if (r->request_body_in_file_only || r->request_body_in_single_buf) { rb->to_write = rb->bufs; } else { rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs; } r->read_event_handler = ngx_http_read_client_request_body_handler; return ngx_http_do_read_client_request_body(r); }
subscriber_t *websocket_subscriber_create(ngx_http_request_t *r, nchan_msg_id_t *msg_id) { ngx_buf_t *b; nchan_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, nchan_module); nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, nchan_module); DBG("create for req %p", r); full_subscriber_t *fsub; if((fsub = ngx_alloc(sizeof(*fsub), ngx_cycle->log)) == NULL) { ERR("Unable to allocate"); return NULL; } ngx_memcpy(&fsub->sub, &new_websocket_sub, sizeof(new_websocket_sub)); fsub->sub.request = r; fsub->cln = NULL; fsub->finalize_request = 0; fsub->holding = 0; fsub->shook_hands = 0; fsub->sub.cf = ngx_http_get_module_loc_conf(r, nchan_module); fsub->sub.enqueued = 0; ngx_memzero(&fsub->ping_ev, sizeof(fsub->ping_ev)); if(msg_id) { nchan_copy_new_msg_id(&fsub->sub.last_msgid, msg_id); } else { fsub->sub.last_msgid.time = 0; fsub->sub.last_msgid.tag.fixed[0] = 0; fsub->sub.last_msgid.tagcount = 1; } ngx_memzero(&fsub->timeout_ev, sizeof(fsub->timeout_ev)); fsub->timeout_handler = empty_handler; fsub->timeout_handler_data = NULL; fsub->dequeue_handler = empty_handler; fsub->dequeue_handler_data = NULL; fsub->awaiting_destruction = 0; //initialize reusable chains and bufs ngx_memzero(&fsub->hdr_buf, sizeof(fsub->hdr_buf)); ngx_memzero(&fsub->msg_buf, sizeof(fsub->msg_buf)); //space for frame header fsub->hdr_buf.start = ngx_pcalloc(r->pool, WEBSOCKET_FRAME_HEADER_MAX_LENGTH); fsub->hdr_chain.buf = &fsub->hdr_buf; fsub->hdr_chain.next = &fsub->msg_chain; fsub->msg_chain.buf = &fsub->msg_buf; fsub->msg_chain.next = NULL; //what should the buffers look like? b = &fsub->msg_buf; b->last_buf = 1; b->last_in_chain = 1; b->flush = 1; b->memory = 1; b->temporary = 0; if(cf->pub.websocket) { fsub->publish_channel_id = nchan_get_channel_id(r, PUB, 0); } fsub->upstream_stuff = NULL; websocket_init_frame(&fsub->frame); fsub->owner = memstore_slot(); //http request sudden close cleanup if((fsub->cln = ngx_http_cleanup_add(r, 0)) == NULL) { ERR("Unable to add request cleanup for websocket subscriber"); return NULL; } fsub->cln->data = fsub; fsub->cln->handler = (ngx_http_cleanup_pt )sudden_abort_handler; DBG("%p created for request %p", &fsub->sub, r); assert(ctx != NULL); ctx->sub = &fsub->sub; //gonna need this for recv ctx->subscriber_type = fsub->sub.name; #if NCHAN_SUBSCRIBER_LEAK_DEBUG subscriber_debug_add(&fsub->sub); #endif return &fsub->sub; }
static ngx_int_t ngx_http_status_ex_handler(ngx_http_request_t *r) { size_t size, index_size; u_char host[URL_LEN]; ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr;// cc;// rt; cJSON *root,*fmt; char *out_cjson; ngx_url_io_array *url_io_array; ngx_tcp_io ngx_io; ngx_tcp_io **url_io; if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } ngx_str_set(&r->headers_out.content_type, "text/plain"); if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } ap = *ngx_stat_accepted; hn = *ngx_stat_handled; ac = *ngx_stat_active; rq = *ngx_stat_requests; rd = *ngx_stat_reading; wr = *ngx_stat_writing; //cc = *ngx_connection_counter; // rt = *ngx_stat_requesttime; //ngx_tcp_io_get(&tcp_in, &tcp_out); ngx_tcp_io_get_ex(&ngx_io); root=cJSON_CreateObject(); cJSON_AddStringToObject(root, "verison", DRAGON_VER); cJSON_AddNumberToObject(root, "code", 0); cJSON_AddItemToObject(root, "result", fmt=cJSON_CreateObject()); cJSON_AddNumberToObject(fmt,"active_connections", ac); cJSON_AddNumberToObject(fmt,"requests", rq); cJSON_AddNumberToObject(fmt,"accepts", ap); cJSON_AddNumberToObject (fmt,"handled", hn); cJSON_AddNumberToObject(fmt,"reading_request", rd); cJSON_AddNumberToObject(fmt,"writing_request", wr); cJSON_AddNumberToObject(fmt,"waitting_request", ac - (rd + wr)); //cJSON_AddNumberToObject(fmt,"connection_", cc); //cJSON_AddNumberToObject(fmt,"respone_time", rt); cJSON_AddItemToObject(root, "stream", fmt=cJSON_CreateObject()); cJSON_AddNumberToObject (fmt,"in_http_stream", ngx_io.in); cJSON_AddNumberToObject (fmt,"out_http_stream", ngx_io.out); cJSON_AddNumberToObject(fmt,"http_1xx", ngx_io.http_1xx); cJSON_AddNumberToObject(fmt,"http_2xx", ngx_io.http_2xx); cJSON_AddNumberToObject(fmt,"http_3xx", ngx_io.http_3xx); cJSON_AddNumberToObject(fmt,"http_4xx", ngx_io.http_4xx); cJSON_AddNumberToObject(fmt,"http_5xx", ngx_io.http_5xx); cJSON_AddNumberToObject(fmt,"http_400", ngx_io.http_400); cJSON_AddNumberToObject(fmt,"http_401", ngx_io.http_401); cJSON_AddNumberToObject(fmt,"http_403", ngx_io.http_403); cJSON_AddNumberToObject(fmt,"http_404", ngx_io.http_404); cJSON_AddNumberToObject(fmt,"http_408", ngx_io.http_408); cJSON_AddNumberToObject(fmt,"http_500", ngx_io.http_500); cJSON_AddNumberToObject(fmt,"http_502", ngx_io.http_502); cJSON_AddNumberToObject(fmt,"http_503", ngx_io.http_503); cJSON_AddNumberToObject(fmt,"http_504", ngx_io.http_504); cJSON_AddNumberToObject(fmt,"http_505", ngx_io.http_505); if (ngx_status_io_get(&url_io_array) == NGX_OK) { cJSON_AddNumberToObject(root,"number", url_io_array->number); url_io = (ngx_tcp_io**)&url_io_array->ngx_tcp_io; for (index_size= 0; index_size<url_io_array->number; index_size++) { ngx_memzero(host, URL_LEN); ngx_memcpy(host, url_io[index_size]->host, url_io[index_size]->host_len); cJSON_AddItemToObject(root, (const char *)host, fmt=cJSON_CreateObject()); cJSON_AddNumberToObject(fmt, "in", url_io[index_size]->in); cJSON_AddNumberToObject(fmt, "out", url_io[index_size]->out); cJSON_AddNumberToObject(fmt, "requests", url_io[index_size]->requests); cJSON_AddNumberToObject(fmt, "http_1xx", url_io[index_size]->http_1xx); cJSON_AddNumberToObject(fmt, "http_2xx", url_io[index_size]->http_2xx); cJSON_AddNumberToObject(fmt, "http_3xx", url_io[index_size]->http_3xx); cJSON_AddNumberToObject(fmt, "http_4xx", url_io[index_size]->http_4xx); cJSON_AddNumberToObject(fmt, "http_5xx", url_io[index_size]->http_5xx); cJSON_AddNumberToObject(fmt, "http_401", url_io[index_size]->http_401); cJSON_AddNumberToObject(fmt, "http_403", url_io[index_size]->http_403); cJSON_AddNumberToObject(fmt, "http_404", url_io[index_size]->http_404); cJSON_AddNumberToObject(fmt, "http_408", url_io[index_size]->http_408); cJSON_AddNumberToObject(fmt, "http_500", url_io[index_size]->http_500); cJSON_AddNumberToObject(fmt, "http_502", url_io[index_size]->http_502); cJSON_AddNumberToObject(fmt, "http_503", url_io[index_size]->http_503); cJSON_AddNumberToObject(fmt, "http_504", url_io[index_size]->http_504); cJSON_AddNumberToObject(fmt, "http_505", url_io[index_size]->http_505); } } out_cjson=cJSON_Print(root); cJSON_Delete(root); size = ngx_strlen(out_cjson); b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } out.buf = b; out.next = NULL; b->last = ngx_cpymem(b->last, out_cjson, size); if (out_cjson) ngx_free(out_cjson); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = 1; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
static char * ngx_mail_imap_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_mail_imap_srv_conf_t *prev = parent; ngx_mail_imap_srv_conf_t *conf = child; u_char *p, *p1, *p2, *p3; size_t size, s1, s2, s3; ngx_str_t *c, *d; ngx_uint_t i; ngx_conf_merge_size_value(conf->client_buffer_size, prev->client_buffer_size, (size_t) 4 * ngx_pagesize); ngx_conf_merge_bitmask_value(conf->auth_methods, prev->auth_methods, (NGX_CONF_BITMASK_SET |NGX_MAIL_AUTH_PLAIN_ENABLED)); if (conf->id_params.nelts == 0) { conf->id_params = prev->id_params; } if (conf->capabilities.nelts == 0) { conf->capabilities = prev->capabilities; } if (conf->capabilities.nelts == 0) { for (d = ngx_mail_imap_default_capabilities; d->len; d++) { c = ngx_array_push(&conf->capabilities); if (c == NULL) { return NGX_CONF_ERROR; } *c = *d; } } s1 = sizeof("* CAPABILITY" CRLF) - 1; s2 = s1; s3 = s1; c = conf->capabilities.elts; for (i = 0; i < conf->capabilities.nelts; i++) { s1 += 1 + c[i].len; s2 += 1 + c[i].len; s3 += 1 + c[i].len; } if (conf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED) { s1 += sizeof (" AUTH=LOGIN") - 1; s2 += sizeof (" AUTH=LOGIN") - 1; } if (conf->auth_methods & NGX_MAIL_AUTH_PLAIN_ENABLED) { s1 += sizeof (" AUTH=PLAIN") - 1; s2 += sizeof (" AUTH=PLAIN") - 1; } if (conf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { s1 += sizeof (" AUTH=CRAM-MD5") - 1; s2 += sizeof (" AUTH=CRAM-MD5") - 1; } if (conf->auth_methods & NGX_MAIL_AUTH_GSSAPI_ENABLED) { s1 += sizeof (" AUTH=GSSAPI") - 1; s2 += sizeof (" AUTH=GSSAPI") - 1; s3 += sizeof (" AUTH=GSSAPI") - 1; } s2 += sizeof (" STARTTLS") - 1; s3 += sizeof (" STARTTLS") - 1; s3 += sizeof (" LOGINDISABLED") - 1; p1 = ngx_palloc(cf->pool, s1); if (p1 == NULL) { return NGX_CONF_ERROR; } p2 = ngx_palloc(cf->pool, s2); if (p2 == NULL) { return NGX_CONF_ERROR; } p3 = ngx_palloc(cf->pool, s3); if (p3 == NULL) { return NGX_CONF_ERROR; } conf->capability.len = s1; conf->capability.data = p1; conf->starttls_capability.len = s2; conf->starttls_capability.data = p2; conf->starttls_only_capability.len = s3; conf->starttls_only_capability.data = p3; p1 = ngx_cpymem(p1, "* CAPABILITY", sizeof("* CAPABILITY") - 1); p2 = ngx_cpymem(p2, "* CAPABILITY", sizeof("* CAPABILITY") - 1); p3 = ngx_cpymem(p3, "* CAPABILITY", sizeof("* CAPABILITY") - 1); c = conf->capabilities.elts; for (i = 0; i < conf->capabilities.nelts; i++) { *p1++ = ' '; p1 = ngx_cpymem(p1,c[i].data,c[i].len); *p2++ = ' '; p2 = ngx_cpymem(p2,c[i].data,c[i].len); *p3++ = ' '; p3 = ngx_cpymem(p3,c[i].data,c[i].len); } if (conf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED) { p1 = ngx_cpymem(p1," AUTH=LOGIN", sizeof(" AUTH=LOGIN") - 1); p2 = ngx_cpymem(p2," AUTH=LOGIN", sizeof(" AUTH=LOGIN") - 1); } if (conf->auth_methods & NGX_MAIL_AUTH_PLAIN_ENABLED) { p1 = ngx_cpymem(p1," AUTH=PLAIN", sizeof(" AUTH=PLAIN") - 1); p2 = ngx_cpymem(p2," AUTH=PLAIN", sizeof(" AUTH=PLAIN") - 1); } if (conf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { p1 = ngx_cpymem(p1," AUTH=CRAM-MD5", sizeof(" AUTH=CRAM-MD5") - 1); p2 = ngx_cpymem(p2," AUTH=CRAM-MD5", sizeof(" AUTH=CRAM-MD5") - 1); } if (conf->auth_methods & NGX_MAIL_AUTH_GSSAPI_ENABLED) { p1 = ngx_cpymem(p1," AUTH=GSSAPI", sizeof(" AUTH=GSSAPI") - 1); p2 = ngx_cpymem(p2," AUTH=GSSAPI", sizeof(" AUTH=GSSAPI") - 1); p3 = ngx_cpymem(p3," AUTH=GSSAPI", sizeof(" AUTH=GSSAPI") - 1); } p2 = ngx_cpymem(p2," STARTTLS",sizeof(" STARTTLS")-1); p3 = ngx_cpymem(p3," STARTTLS",sizeof(" STARTTLS")-1); p3 = ngx_cpymem(p3," LOGINDISABLED",sizeof(" LOGINDISABLED")-1); *p1++ = CR; *p1++ = LF; *p2++ = CR; *p2++ = LF; *p3++ = CR; *p3++ = LF; ngx_conf_merge_str_value(conf->greeting, prev->greeting, ""); if (conf->greeting.len == 0) { conf->greeting = default_imap_greeting; } p = ngx_pnalloc(cf->pool, conf->greeting.len + 2); if (p == NULL) { return NGX_CONF_ERROR; } ngx_memcpy(p, conf->greeting.data, conf->greeting.len); ngx_memcpy(p + conf->greeting.len, CRLF, sizeof(CRLF)-1); conf->greeting.data = p; conf->greeting.len += 2; size = sizeof ("* ID ()" CRLF) - 1; c = conf->id_params.elts; for (i = 0; i < conf->id_params.nelts; ++i) { if (!((c[i].len == 3) && (c[i].data[0] == 'n' || c[i].data[0] == 'N') && (c[i].data[1] == 'i' || c[i].data[1] == 'I') && (c[i].data[2] == 'l' || c[i].data[2] == 'L')) ) { size += 2; // for enclosing quotes } size += c[i].len; size += 1; // for following SP } if (conf->id_params.nelts > 0) { --size; // no SP follows the last parameter } else { size = size - 2 + 3; // take away the () and put nil } p = ngx_pnalloc(cf->pool, size); if (p == NULL) { return NGX_CONF_ERROR; } conf->id.len = size; conf->id.data = p; p = ngx_cpymem (p, "* ID ", sizeof ("* ID ") -1); if (conf->id_params.nelts > 0) { *p++ = '('; for (i = 0; i < conf->id_params.nelts; ++i) { if (!((c[i].len == 3) && (c[i].data[0] == 'n' || c[i].data[0] == 'N') && (c[i].data[1] == 'i' || c[i].data[1] == 'I') && (c[i].data[2] == 'l' || c[i].data[2] == 'L')) ) { *p++ = '"'; p = ngx_cpymem(p, c[i].data, c[i].len); *p++ = '"'; } else { p = ngx_cpymem(p, c[i].data, c[i].len); } if (i < conf->id_params.nelts - 1) *p++ = ' '; } *p++ = ')'; } else { p = ngx_cpymem (p, "nil", sizeof("nil") - 1); } *p++ = CR; *p = LF; ngx_conf_merge_value (conf->literalauth, prev->literalauth,1); return NGX_CONF_OK; }
static ngx_int_t ngx_rtmp_exec_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) { ngx_rtmp_exec_main_conf_t *emcf; ngx_rtmp_exec_app_conf_t *eacf; ngx_rtmp_exec_t *e; ngx_rtmp_exec_conf_t *ec; ngx_rtmp_exec_ctx_t *ctx; size_t n; emcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_exec_module); eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module); if (eacf == NULL || eacf->confs.nelts == 0) { goto next; } if (s->auto_pushed) { goto next; } ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); if (ctx == NULL) { ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_exec_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_exec_module); if (ngx_array_init(&ctx->execs, s->connection->pool, eacf->confs.nelts, sizeof(ngx_rtmp_exec_t)) != NGX_OK) { return NGX_ERROR; } e = ngx_array_push_n(&ctx->execs, eacf->confs.nelts); if (e == NULL) { return NGX_ERROR; } ec = eacf->confs.elts; for (n = 0; n < eacf->confs.nelts; ++n, ++e, ++ec) { ngx_memzero(e, sizeof(*e)); e->conf = ec; e->log = s->connection->log; e->session = s; e->kill_signal = emcf->kill_signal; e->respawn_timeout = (eacf->respawn ? emcf->respawn_timeout : NGX_CONF_UNSET_MSEC); } } ngx_memcpy(ctx->name, v->name, NGX_RTMP_MAX_NAME); ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "exec: run %uz command(s)", ctx->execs.nelts); e = ctx->execs.elts; for (n = 0; n < ctx->execs.nelts; ++n, ++e) { ngx_rtmp_exec_run(e); } next: return next_publish(s, v); }
ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log) { #if 0 ssize_t n; ngx_err_t err; struct iovec iov[1]; struct msghdr msg; #if (NGX_HAVE_MSGHDR_MSG_CONTROL) union { struct cmsghdr cm; char space[CMSG_SPACE(sizeof(int))]; } cmsg; #else int fd; #endif iov[0].iov_base = (char *) ch; iov[0].iov_len = size; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 1; #if (NGX_HAVE_MSGHDR_MSG_CONTROL) msg.msg_control = (caddr_t) &cmsg; msg.msg_controllen = sizeof(cmsg); #else msg.msg_accrights = (caddr_t) &fd; msg.msg_accrightslen = sizeof(int); #endif n = recvmsg(s, &msg, 0); if (n == -1) { err = ngx_errno; if (err == NGX_EAGAIN) { return NGX_AGAIN; } ngx_log_error(NGX_LOG_ALERT, log, err, "recvmsg() failed"); return NGX_ERROR; } if (n == 0) { ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "recvmsg() returned zero"); return NGX_ERROR; } if ((size_t) n < sizeof(ngx_channel_t)) { ngx_log_error(NGX_LOG_ALERT, log, 0, "recvmsg() returned not enough data: %uz", n); return NGX_ERROR; } #if (NGX_HAVE_MSGHDR_MSG_CONTROL) if (ch->command == NGX_CMD_OPEN_CHANNEL) { if (cmsg.cm.cmsg_len < (socklen_t) CMSG_LEN(sizeof(int))) { ngx_log_error(NGX_LOG_ALERT, log, 0, "recvmsg() returned too small ancillary data"); return NGX_ERROR; } if (cmsg.cm.cmsg_level != SOL_SOCKET || cmsg.cm.cmsg_type != SCM_RIGHTS) { ngx_log_error(NGX_LOG_ALERT, log, 0, "recvmsg() returned invalid ancillary data " "level %d or type %d", cmsg.cm.cmsg_level, cmsg.cm.cmsg_type); return NGX_ERROR; } /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */ ngx_memcpy(&ch->fd, CMSG_DATA(&cmsg.cm), sizeof(int)); } if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { ngx_log_error(NGX_LOG_ALERT, log, 0, "recvmsg() truncated data"); } #else if (ch->command == NGX_CMD_OPEN_CHANNEL) { if (msg.msg_accrightslen != sizeof(int)) { ngx_log_error(NGX_LOG_ALERT, log, 0, "recvmsg() returned no ancillary data"); return NGX_ERROR; } ch->fd = fd; } #endif return n; #endif return 0; }
//ngx_http_parse_status_line解析应答行,mytest_upstream_process_header解析头部行中的其中一行 static ngx_int_t mytest_upstream_process_header(ngx_http_request_t *r) { ngx_int_t rc; ngx_table_elt_t *h; ngx_http_upstream_header_t *hh; ngx_http_upstream_main_conf_t *umcf; //这里将upstream模块配置项ngx_http_upstream_main_conf_t取了 //出来,目的只有1个,对将要转发给下游客户端的http响应头部作统一 //处理。该结构体中存储了需要做统一处理的http头部名称和回调方法 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); //循环的解析所有的http头部 for ( ;; ) { // http框架提供了基础性的ngx_http_parse_header_line方法,它用于解析http头部 rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1); //返回NGX_OK表示解析出一行http头部 if (rc == NGX_OK) { //向headers_in.headers这个ngx_list_t链表中添加http头部 h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_ERROR; } //以下开始构造刚刚添加到headers链表中的http头部 h->hash = r->header_hash; h->key.len = r->header_name_end - r->header_name_start; h->value.len = r->header_end - r->header_start; //必须由内存池中分配解析出的这一行信息,存放解析出的这一行http头部的内存 h->key.data = ngx_pnalloc(r->pool, h->key.len + 1 + h->value.len + 1 + h->key.len); if (h->key.data == NULL) { return NGX_ERROR; } /* key + value + 小写key */ h->value.data = h->key.data + h->key.len + 1; //value存放在key后面 h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; //最后存放key的小写字符串 ngx_memcpy(h->key.data, r->header_name_start, h->key.len); h->key.data[h->key.len] = '\0'; ngx_memcpy(h->value.data, r->header_start, h->value.len); h->value.data[h->value.len] = '\0'; if (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); } else { ngx_strlow(h->lowcase_key, h->key.data, h->key.len); } //upstream模块会对一些http头部做特殊处理 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { return NGX_ERROR; } continue; } //返回NGX_HTTP_PARSE_HEADER_DONE表示响应中所有的http头部都解析 //完毕,接下来再接收到的都将是http包体 if (rc == NGX_HTTP_PARSE_HEADER_DONE) { //如果之前解析http头部时没有发现server和date头部,以下会 //根据http协议添加这两个头部 if (r->upstream->headers_in.server == NULL) { h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_ERROR; } h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash( ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r'); ngx_str_set(&h->key, "Server"); ngx_str_null(&h->value); h->lowcase_key = (u_char *) "server"; } if (r->upstream->headers_in.date == NULL) { h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_ERROR; } h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e'); ngx_str_set(&h->key, "Date"); ngx_str_null(&h->value); h->lowcase_key = (u_char *) "date"; } return NGX_OK; } //如果返回NGX_AGAIN则表示状态机还没有解析到完整的http头部, //要求upstream模块继续接收新的字符流再交由process_header //回调方法解析 if (rc == NGX_AGAIN) { return NGX_AGAIN; } //其他返回值都是非法的 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent invalid header"); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } }