sf_vartable_t* sf_var_create(char *name, char *value, ngx_pool_t *pool) { #if 0 sf_vartable_t *v = sf_calloc (sizeof(sf_vartable_t)); v->name = sf_strdup(name); v->value = value?sf_strdup(value):strdup(""); #endif sf_vartable_t *v = ngx_pcalloc(pool, sizeof(sf_vartable_t)); v->name = ngx_pstrdup(pool, name); v->value = value?ngx_pstrdup(pool, value):""; return v; }
const char * get_gss_error( ngx_pool_t * p, OM_uint32 error_status, char *prefix) { OM_uint32 maj_stat, min_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; char buf[1024]; size_t len; ngx_str_t str; ngx_snprintf((u_char *) buf, sizeof(buf), "%s: %Z", prefix); len = ngx_strlen(buf); do { maj_stat = gss_display_status(&min_stat, error_status, GSS_C_MECH_CODE, GSS_C_NO_OID, &msg_ctx, &status_string); if (sizeof(buf) > len + status_string.length + 1) { ngx_sprintf((u_char *) buf + len, "%s:%Z", (char *) status_string.value); len += (status_string.length + 1); } gss_release_buffer(&min_stat, &status_string); } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); str.len = len + 1; /* "include" '\0' */ str.data = (u_char *) buf; return (char *) (ngx_pstrdup(p, &str)); }
static ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm) { ngx_int_t rc; u_char *encrypted; rc = ngx_crypt(r->pool, r->headers_in.passwd.data, passwd->data, &encrypted); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "rc: %d user: \"%V\" salt: \"%s\"", rc, &r->headers_in.user, passwd->data); if (rc == NGX_OK) { if (ngx_strcmp(encrypted, passwd->data) == 0) { return NGX_OK; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "encrypted: \"%s\"", encrypted); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "user \"%V\": password mismatch", &r->headers_in.user); return ngx_http_auth_basic_set_realm(r, realm); } if (rc == NGX_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* rc == NGX_AGAIN */ if (ctx == NULL) { ctx = ngx_palloc(r->pool, sizeof(ngx_http_auth_basic_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_auth_basic_module); ctx->passwd.len = passwd->len; passwd->len++; ctx->passwd.data = ngx_pstrdup(r->pool, passwd); if (ctx->passwd.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } /* TODO: add mutex event */ return rc; }
static ngx_int_t ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename) { off_t size; u_char *p; uint32_t hash; ngx_buf_t *buf; ngx_str_node_t *sn; ngx_conf_dump_t *cd; hash = ngx_crc32_long(filename->data, filename->len); sn = ngx_str_rbtree_lookup(&cf->cycle->config_dump_rbtree, filename, hash); if (sn) { cf->conf_file->dump = NULL; return NGX_OK; } p = ngx_pstrdup(cf->cycle->pool, filename); if (p == NULL) { return NGX_ERROR; } cd = ngx_array_push(&cf->cycle->config_dump); if (cd == NULL) { return NGX_ERROR; } size = ngx_file_size(&cf->conf_file->file.info); buf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size); if (buf == NULL) { return NGX_ERROR; } cd->name.data = p; cd->name.len = filename->len; cd->buffer = buf; cf->conf_file->dump = buf; sn = ngx_palloc(cf->temp_pool, sizeof(ngx_str_node_t)); if (sn == NULL) { return NGX_ERROR; } sn->node.key = hash; sn->str = cd->name; ngx_rbtree_insert(&cf->cycle->config_dump_rbtree, &sn->node); return NGX_OK; }
/* Parse the 'mongo' directive. */ static char * ngx_http_mongo(ngx_conf_t *cf, ngx_command_t *cmd, void *void_conf) { ngx_str_t *value; ngx_url_t u; ngx_uint_t i; ngx_uint_t start; ngx_http_mongod_server_t *mongod_server; ngx_http_gridfs_loc_conf_t *gridfs_loc_conf; gridfs_loc_conf = void_conf; value = cf->args->elts; gridfs_loc_conf->mongo = value[1]; gridfs_loc_conf->mongods = ngx_array_create(cf->pool, 7, sizeof(ngx_http_mongod_server_t)); if (gridfs_loc_conf->mongods == NULL) { return NULL; } /* If nelts is greater than 3, then the user has specified more than one * setting in the 'mongo' directive. So we assume that we're connecting * to a replica set and that the first string of the directive is the replica * set name. We also start looking for host-port pairs at position 2; otherwise, * we start at position 1. */ if( cf->args->nelts >= 3 ) { gridfs_loc_conf->replset.len = strlen( (char *)(value + 1)->data ); gridfs_loc_conf->replset.data = ngx_pstrdup( cf->pool, value + 1 ); start = 2; } else start = 1; for (i = start; i < cf->args->nelts; i++) { ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[i]; u.default_port = 27017; if (ngx_parse_url(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in mongo \"%V\"", u.err, &u.url); } return NGX_CONF_ERROR; } mongod_server = ngx_array_push(gridfs_loc_conf->mongods); mongod_server->host = u.host; mongod_server->port = u.port; } return NGX_CONF_OK; }
static u_char * ngx_http_auth_mysql_uchar(ngx_pool_t *pool, ngx_str_t *str) { // strdup will allocate only len bytes, we want an extra one for \0 str->len++; u_char *result = ngx_pstrdup(pool, str); if (result == NULL) { return NULL; } str->len--; result[str->len] = '\0'; return result; }
int main() { ngx_pool_t* pool; yahoo_guy_t* guy; ngx_queue_t* q; yahoo_t* yahoo; pool = ngx_create_pool(1024*10, NULL); //初始化内存池 int i; // 构建队列 const ngx_str_t names[] = { ngx_string("rainx"), ngx_string("xiaozhe"), ngx_string("zhoujian") } ; const int ids[] = {4611, 8322, 6111}; yahoo = ngx_palloc(pool, sizeof(yahoo_t)); ngx_queue_init(&yahoo->queue); //初始化queue for(i = 0; i < 3; i++) { guy = (yahoo_guy_t*) ngx_palloc(pool, sizeof(yahoo_guy_t)); guy->id = ids[i]; //guy->name = (char*) ngx_palloc(pool, (size_t) (strlen(names[i]) + 1) ); guy->name = (u_char*) ngx_pstrdup(pool, (ngx_str_t*) &(names[i]) ); ngx_queue_init(&guy->queue); // 从头部进入队列 ngx_queue_insert_head(&yahoo->queue, &guy->queue); } // 从尾部遍历输出 for(q = ngx_queue_last(&yahoo->queue); q != ngx_queue_sentinel(&yahoo->queue); q = ngx_queue_prev(q) ) { guy = ngx_queue_data(q, yahoo_guy_t, queue); printf("No. %d guy in yahoo is %s \n", guy->id, guy->name); } // 排序从头部输出 ngx_queue_sort(&yahoo->queue, yahoo_no_cmp); printf("sorting....\n"); for(q = ngx_queue_prev(&yahoo->queue); q != ngx_queue_sentinel(&yahoo->queue); q = ngx_queue_last(q) ) { guy = ngx_queue_data(q, yahoo_guy_t, queue); printf("No. %d guy in yahoo is %s \n", guy->id, guy->name); } ngx_destroy_pool(pool); return 0; }
static mrb_value ngx_mrb_rputs(mrb_state *mrb, mrb_value self) { mrb_value argv; ngx_buf_t *b; ngx_mrb_rputs_chain_list_t *chain; u_char *str; ngx_str_t ns; ngx_http_request_t *r = ngx_mrb_get_request(); ngx_http_mruby_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_mruby_module); mrb_get_args(mrb, "o", &argv); if (mrb_type(argv) != MRB_TT_STRING) { argv = mrb_funcall(mrb, argv, "to_s", 0, NULL); } ns.data = (u_char *)RSTRING_PTR(argv); ns.len = ngx_strlen(ns.data); if (ns.len == 0) { return self; } if (ctx->rputs_chain == NULL) { chain = ngx_pcalloc(r->pool, sizeof(ngx_mrb_rputs_chain_list_t)); chain->out = ngx_alloc_chain_link(r->pool); chain->last = &chain->out; } else { chain = ctx->rputs_chain; (*chain->last)->next = ngx_alloc_chain_link(r->pool); chain->last = &(*chain->last)->next; } b = ngx_calloc_buf(r->pool); (*chain->last)->buf = b; (*chain->last)->next = NULL; str = ngx_pstrdup(r->pool, &ns); str[ns.len] = '\0'; (*chain->last)->buf->pos = str; (*chain->last)->buf->last = str + ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; ngx_http_set_ctx(r, ctx, ngx_http_mruby_module); if (r->headers_out.content_length_n == -1) { r->headers_out.content_length_n += ns.len + 1; } else { r->headers_out.content_length_n += ns.len; } return self; }
void append_type(ngx_array_t *types, ngx_str_t *t) { ngx_str_t *type; type = ngx_array_push(types); if (type == NULL) { return; } type->len = t->len; type->data = ngx_pstrdup(types->pool, t); return; }
static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx) { ngx_connection_t *c; ngx_mail_session_t *s; s = ctx->data; c = s->connection; if (ctx->state) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "%V could not be resolved (%i: %s)", &c->addr_text, ctx->state, ngx_resolver_strerror(ctx->state)); if (ctx->state == NGX_RESOLVE_NXDOMAIN) { s->host = smtp_unavailable; } else { s->host = smtp_tempunavail; } ngx_resolve_addr_done(ctx); ngx_mail_smtp_greeting(s, s->connection); return; } c->log->action = "in resolving client hostname"; s->host.data = ngx_pstrdup(c->pool, &ctx->name); if (s->host.data == NULL) { ngx_resolve_addr_done(ctx); ngx_mail_close_connection(c); return; } s->host.len = ctx->name.len; ngx_resolve_addr_done(ctx); ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "address resolved: %V", &s->host); c->read->handler = ngx_mail_smtp_resolve_name; ngx_post_event(c->read, &ngx_posted_events); }
size_t ngx_http_php_code_ub_write(const char *str, size_t str_length TSRMLS_DC) { ngx_buf_t *b; ngx_http_php_rputs_chain_list_t *chain; ngx_http_php_ctx_t *ctx; ngx_http_request_t *r; u_char *u_str; ngx_str_t ns; r = ngx_php_request; ctx = ngx_http_get_module_ctx(r, ngx_http_php_module); if (ctx->output_type & OUTPUT_CONTENT){ ns.data = (u_char *)str; ns.len = str_length; if (ctx->rputs_chain == NULL){ chain = ngx_pcalloc(r->pool, sizeof(ngx_http_php_rputs_chain_list_t)); chain->out = ngx_alloc_chain_link(r->pool); chain->last = &chain->out; }else { chain = ctx->rputs_chain; (*chain->last)->next = ngx_alloc_chain_link(r->pool); chain->last = &(*chain->last)->next; } b = ngx_calloc_buf(r->pool); (*chain->last)->buf = b; (*chain->last)->next = NULL; u_str = ngx_pstrdup(r->pool, &ns); //u_str[ns.len] = '\0'; (*chain->last)->buf->pos = u_str; (*chain->last)->buf->last = u_str + ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; ngx_http_set_ctx(r, ctx, ngx_http_php_module); if (r->headers_out.content_length_n == -1){ r->headers_out.content_length_n += ns.len + 1; }else { r->headers_out.content_length_n += ns.len; } } return r->headers_out.content_length_n; }
static ngx_int_t ngx_dbd_freetds_set_sql(ngx_dbd_t *dbd, u_char *sql, size_t len) { ngx_str_t str; ngx_dbd_freetds_ctx_t *ctx; ngx_log_debug0(NGX_LOG_DEBUG_MYSQL, dbd->log, 0, "dbd freetds set sql"); ctx = dbd->ctx; str.len = len + 1; str.data = sql; ctx->sql = ngx_pstrdup(dbd->pool, &str); return NGX_OK; }
static ngx_int_t ngx_dbd_freetds_set_db(ngx_dbd_t *dbd, u_char *db) { ngx_str_t str; ngx_dbd_freetds_ctx_t *ctx; ngx_log_debug0(NGX_LOG_DEBUG_MYSQL, dbd->log, 0, "dbd freetds set db"); ctx = dbd->ctx; str.len = ngx_strlen(db) + 1; str.data = db; ctx->db_name = ngx_pstrdup(dbd->pool, &str); return NGX_OK; }
/* memcache handler (return counter for the specified ip or NOT_FOUND) */ static void ngx_mail_throttle_ip_success_handler (mc_work_t *w) { ngx_mail_throttle_srv_conf_t * tscf; throttle_callback_t *callback = w->ctx; ngx_str_t ip = *callback->ip; ngx_mail_session_t *s = callback->session; size_t hits; ngx_str_t counter; /* the increment was successful - deep copy w->payload to counter */ counter.data = ngx_pstrdup (callback->pool, &w->payload); if (counter.data == NULL) { /* enomem */ counter = throttle_zero; /* "0" */ } else { counter.len = w->payload.len; } /* check if the limit has exceeded */ ngx_log_debug2(NGX_LOG_DEBUG_MAIL, callback->log, 0, "ip throttle:%V is %V", &ip, &counter); hits = 0; deserialize_number (counter.data, counter.len, &hits); tscf = ngx_mail_get_module_srv_conf(s, ngx_mail_throttle_module); if (tscf->mail_login_ip_max == 0) { //should never reach here because mail handler won't //start throttle control if it's unlimited. ngx_log_error (NGX_LOG_INFO, callback->log, 0, "ip throttle:%V allow [usage:%d,limit:infinity]", &ip, hits); callback->on_allow(callback); } else if (hits <= tscf->mail_login_ip_max) { ngx_log_error (NGX_LOG_INFO, callback->log, 0, "ip throttle:%V allow [usage:%d,limit:%d]", &ip, hits, tscf->mail_login_ip_max); callback->on_allow(callback); } else { ngx_log_error (NGX_LOG_NOTICE, callback->log, 0, "ip throttle:%V deny [usage:%d,limit:%d]", &ip, hits, tscf->mail_login_ip_max); callback->on_deny(callback); } }
static char * ngx_http_xrlt_param(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_xrlt_loc_conf_t *xlcf = conf; ngx_http_xrlt_param_t *param; ngx_http_compile_complex_value_t ccv; ngx_str_t *value; value = cf->args->elts; if (xlcf->params == NULL) { xlcf->params = ngx_array_create(cf->pool, 2, sizeof(ngx_http_xrlt_param_t)); if (xlcf->params == NULL) { return NGX_CONF_ERROR; } } param = ngx_array_push(xlcf->params); if (param == NULL) { return NGX_CONF_ERROR; } param->name.data = ngx_pstrdup(cf->pool, &value[1]); if (param->name.data == NULL) { return NGX_CONF_ERROR; } param->name.len = value[1].len; ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = &value[2]; ccv.complex_value = ¶m->value; ccv.zero = 1; if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static ngx_int_t ngx_dbd_freetds_set_tcp(ngx_dbd_t *dbd, u_char *host, in_port_t port) { ngx_str_t str; ngx_dbd_freetds_ctx_t *ctx; ngx_log_debug0(NGX_LOG_DEBUG_MYSQL, dbd->log, 0, "dbd freetds set tcp"); ctx = dbd->ctx; str.len = ngx_strlen(host) + 1; str.data = host; ctx->server = ngx_pstrdup(dbd->pool, &str); /* TODO: port */ return NGX_OK; }
ngx_int_t yy_sec_waf_re_cache_set_value(ngx_pool_t *pool, ngx_str_t *name, ngx_array_t *value, ngx_rbtree_t *rbtree) { uint32_t hash; ngx_str_t *val; re_cache_node_t *cache_node; hash = ngx_crc32_long(name->data, name->len); cache_node = (re_cache_node_t *) ngx_str_rbtree_lookup(rbtree, name, hash); if (cache_node != NULL) { return NGX_OK; } cache_node = ngx_palloc(pool, sizeof(re_cache_node_t)); if (cache_node == NULL) { return NGX_ERROR; } val = ngx_palloc(pool, sizeof(ngx_str_t)); if (value == NULL) { return NGX_ERROR; } val->len = value->len; val->data = ngx_pstrdup(pool, value); if (val->data == NULL) { return NGX_ERROR; } cache_node->sn.node.key = hash; cache_node->sn.str.len = name->len; cache_node->sn.str.data = name->data; cache_node->value = value; ngx_rbtree_insert(rbtree, &cache_node->sn.node); return NGX_OK; }
static void ngx_mail_throttle_quser_success_handler (mc_work_t *w) { throttle_callback_t *callback = w->ctx; ngx_mail_session_t *s = callback->session; ngx_log_t *log = callback->log; ngx_mail_throttle_srv_conf_t * tscf; size_t hits; ngx_str_t counter; /* increment succeeded / get succeeded */ counter.data = ngx_pstrdup(callback->pool, &w->payload); if (counter.data == NULL) { /* enomem */ counter = throttle_zero; } else { counter.len = w->payload.len; } /* check if the limit has exceeded */ ngx_log_debug2 (NGX_LOG_DEBUG_MAIL, log, 0, "user throttle:%V is %V", callback->user, &counter); hits = 0; deserialize_number (counter.data, counter.len, &hits); tscf = ngx_mail_get_module_srv_conf (s, ngx_mail_throttle_module); if (tscf->mail_login_user_max == 0) { //should never reach here because unlimited case has been handled ngx_log_error (NGX_LOG_INFO, log, 0, "user throttle:%V allow [usage:%d,limit:infinity]", callback->user, hits); callback->on_allow(callback); } else if (hits <= tscf->mail_login_user_max) { ngx_log_error (NGX_LOG_INFO, log, 0, "user throttle:%V allow [usage:%d,limit:%d]", callback->user, hits, tscf->mail_login_user_max); callback->on_allow(callback); } else { ngx_log_error (NGX_LOG_NOTICE, log, 0, "user throttle:%V deny [usage:%d,limit:%d]", callback->user, hits, tscf->mail_login_user_max); callback->on_deny(callback); } }
/* callback to replace login user name with an alias, if any */ static void ngx_mail_throttle_user_success_handler (mc_work_t *w) { throttle_callback_t *callback = w->ctx; ngx_mail_session_t *s = callback->session; ngx_str_t login; //full qualified name /* deep copy w->payload onto s->login (pool is callback->pool) */ login.data = ngx_pstrdup (callback->pool, &w->payload); if (login.data != NULL) { login.len = w->payload.len; s->vlogin = 2; // lookup alias and found s->qlogin = login; ngx_log_error (NGX_LOG_INFO, callback->log, 0, "user throttle: alias %V replaced by %V", callback->user, &s->login); ngx_mail_throttle_quser (&s->login, callback); } else { ngx_mail_throttle_quser (callback->user, callback); } }
//参考: //http://blog.csdn.net/livelylittlefish/article/details/7262750 static char * ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_core_conf_t *ccf = conf; //初始化daemon、master等 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 //初始化pid、oldpid 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) //初始化username,user,group 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); } //初始化lock_file 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"); } //初始化ngx_cycle->lock_file 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; }
ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; char **senv, **env; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; ngx_conf_t conf; ngx_pool_t *pool; ngx_cycle_t *cycle, **old; ngx_shm_zone_t *shm_zone, *oshm_zone; ngx_list_part_t *part, *opart; ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday(); tp->sec = 0; ngx_time_update(); log = old_cycle->log; pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } pool->log = log; cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pool = pool; cycle->log = log; cycle->old_cycle = old_cycle; cycle->conf_prefix.len = old_cycle->conf_prefix.len; cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->prefix.len = old_cycle->prefix.len; cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_file.len = old_cycle->conf_file.len; cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); if (cycle->conf_file.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, old_cycle->conf_file.len + 1); cycle->conf_param.len = old_cycle->conf_param.len; cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); if (cycle->conf_param.data == NULL) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->paths.nelts = 0; cycle->paths.size = sizeof(ngx_path_t *); cycle->paths.nalloc = n; cycle->paths.pool = pool; if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->listening.nelts = 0; cycle->listening.size = sizeof(ngx_listening_t); cycle->listening.nalloc = n; cycle->listening.pool = pool; ngx_queue_init(&cycle->reusable_connections_queue); cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); ngx_destroy_pool(pool); return NULL; } /* on Linux gethostname() silently truncates name that does not fit */ hostname[NGX_MAXHOSTNAMELEN - 1] = '\0'; cycle->hostname.len = ngx_strlen(hostname); cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len); if (cycle->hostname.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_conf) { rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ngx_modules[i]->index] = rv; } } senv = environ; ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; } conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (conf.temp_pool == NULL) { ngx_destroy_pool(pool); return NULL; } conf.ctx = cycle->conf_ctx; conf.cycle = cycle; conf.pool = pool; conf.log = log; conf.module_type = NGX_CORE_MODULE; conf.cmd_type = NGX_MAIN_CONF; #if 0 log->log_level = NGX_LOG_DEBUG_ALL; #endif if (ngx_conf_param(&conf) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_test_config && !ngx_quiet_mode) { ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle; } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_test_config) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_cycle)) { /* * we do not create the pid file in the first ngx_init_cycle() call * because we need to write the demonized process pid */ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (ccf->pid.len != old_ccf->pid.len || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) { /* new pid file name */ if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } ngx_delete_pidfile(old_cycle); } } if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { goto failed; } if (ngx_create_paths(cycle, ccf->user) != NGX_OK) { goto failed; } if (ngx_log_open_default(cycle) != NGX_OK) { goto failed; } /* open the new files */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d \"%s\"", &file[i], file[i].fd, file[i].name.data); if (file[i].fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); goto failed; } #if !(NGX_WIN32) if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); goto failed; } #endif } cycle->log = &cycle->new_log; pool->log = &cycle->new_log; /* create shared memory */ part = &cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } if (shm_zone[i].shm.size == 0) { ngx_log_error(NGX_LOG_EMERG, log, 0, "zero size shared memory zone \"%V\"", &shm_zone[i].shm.name); goto failed; } shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (n = 0; /* void */ ; n++) { if (n >= opart->nelts) { if (opart->next == NULL) { break; } opart = opart->next; oshm_zone = opart->elts; n = 0; } if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { continue; } if (ngx_strncmp(shm_zone[i].shm.name.data, oshm_zone[n].shm.name.data, shm_zone[i].shm.name.len) != 0) { continue; } if (shm_zone[i].tag == oshm_zone[n].tag && shm_zone[i].shm.size == oshm_zone[n].shm.size) { shm_zone[i].shm.addr = oshm_zone[n].shm.addr; if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) != NGX_OK) { goto failed; } goto shm_zone_found; } ngx_shm_free(&oshm_zone[n].shm); break; } if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { goto failed; } if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { goto failed; } shm_zone_found: continue; } /* handle the listening sockets */ if (old_cycle->listening.nelts) { ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { ls[i].remain = 0; } nls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].ignore) { continue; } if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; ls[i].remain = 1; if (ls[n].backlog != nls[i].backlog) { nls[n].listen = 1; } #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /* * FreeBSD, except the most recent versions, * could not remove accept filter */ nls[n].deferred_accept = ls[i].deferred_accept; if (ls[i].accept_filter && nls[n].accept_filter) { if (ngx_strcmp(ls[i].accept_filter, nls[n].accept_filter) != 0) { nls[n].delete_deferred = 1; nls[n].add_deferred = 1; } } else if (ls[i].accept_filter) { nls[n].delete_deferred = 1; } else if (nls[n].accept_filter) { nls[n].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[n].deferred_accept && !nls[n].deferred_accept) { nls[n].delete_deferred = 1; } else if (ls[i].deferred_accept != nls[n].deferred_accept) { nls[n].add_deferred = 1; } #endif break; } } if (nls[n].fd == (ngx_socket_t) -1) { nls[n].open = 1; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) if (nls[n].accept_filter) { nls[n].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (nls[n].deferred_accept) { nls[n].add_deferred = 1; } #endif } } } else { ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { ls[i].open = 1; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) if (ls[i].accept_filter) { ls[i].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[i].deferred_accept) { ls[i].add_deferred = 1; } #endif } } if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } if (!ngx_test_config) { ngx_configure_listening_sockets(cycle); } /* commit the new cycle configuration */ if (!ngx_use_stderr) { (void) ngx_log_redirect_stderr(cycle); } pool->log = cycle->log; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } /* close and delete stuff that lefts from an old cycle */ /* free the unnecessary shared memory */ opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (i = 0; /* void */ ; i++) { if (i >= opart->nelts) { if (opart->next == NULL) { goto old_shm_zone_done; } opart = opart->next; oshm_zone = opart->elts; i = 0; } part = &cycle->shared_memory.part; shm_zone = part->elts; for (n = 0; /* void */ ; n++) { if (n >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; n = 0; } if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len && ngx_strncmp(oshm_zone[i].shm.name.data, shm_zone[n].shm.name.data, oshm_zone[i].shm.name.len) == 0) { goto live_shm_zone; } } ngx_shm_free(&oshm_zone[i].shm); live_shm_zone: continue; } old_shm_zone_done: /* close the unnecessary listening sockets */ ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].remain || ls[i].fd == (ngx_socket_t) -1) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " listening socket on %V failed", &ls[i].addr_text); } #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX) { u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - 1; ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "deleting socket %s", name); if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } } #endif } /* close the unnecessary open files */ part = &old_cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } ngx_destroy_pool(conf.temp_pool); if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { /* * perl_destruct() frees environ, if it is not the same as it was at * perl_construct() time, therefore we save the previous cycle * environment before ngx_conf_parse() where it will be changed. */ env = environ; environ = senv; ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; environ = env; return cycle; } if (ngx_temp_pool == NULL) { ngx_temp_pool = ngx_create_pool(128, cycle->log); if (ngx_temp_pool == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "could not create ngx_temp_pool"); exit(1); } n = 10; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { exit(1); } ngx_old_cycles.nelts = 0; ngx_old_cycles.size = sizeof(ngx_cycle_t *); ngx_old_cycles.nalloc = n; ngx_old_cycles.pool = ngx_temp_pool; ngx_cleaner_event.handler = ngx_clean_old_cycles; ngx_cleaner_event.log = cycle->log; ngx_cleaner_event.data = &dumb; dumb.fd = (ngx_socket_t) -1; } ngx_temp_pool->log = cycle->log; old = ngx_array_push(&ngx_old_cycles); if (old == NULL) { exit(1); } *old = old_cycle; if (!ngx_cleaner_event.timer_set) { ngx_add_timer(&ngx_cleaner_event, 30000); ngx_cleaner_event.timer_set = 1; } return cycle; failed: if (!ngx_is_init_cycle(old_cycle)) { old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (old_ccf->environment) { environ = old_ccf->environment; } } /* rollback the new cycle configuration */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; } ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { if (ls[i].fd == (ngx_socket_t) -1 || !ls[i].open) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } } ngx_destroy_cycle_pools(&conf); return NULL; }
ngx_rtmpt_proxy_session_t *ngx_rtmpt_proxy_create_session(ngx_http_request_t *r) { ngx_rtmpt_proxy_session_t *session; ngx_peer_connection_t *pc; ngx_rtmpt_proxy_loc_conf_t *plcf; ngx_pool_t *pool = NULL; ngx_url_t url; int rc; plcf = ngx_http_get_module_loc_conf(r, ngx_rtmpt_proxy_module); if (!plcf) { goto error; } pool = ngx_create_pool(4096, plcf->log); if (pool == NULL) { ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: cannot create pool for session"); goto error; } session = (ngx_rtmpt_proxy_session_t *) ngx_pcalloc(pool, sizeof(ngx_rtmpt_proxy_session_t)); if (session == NULL) { ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: cannot allocate memory for session"); goto error; } session->name.data=NULL; session->name.len=0; ngx_str_set(&session->name, "1234567890123456"); session->name.data = ngx_pstrdup(pool, &session->name); session_name_create(session->name.data,session->name.len); session->log = plcf->log; session->pool = pool; session->sequence = 0; session->on_finish_send = NULL; session->chain_from_http_request = NULL; session->chain_from_nginx = NULL; session->out_pool = NULL; session->interval_check_time=0; session->interval_check_att=0; session->interval_check_count=0; session->interval_position=1; session->created_at = ngx_cached_time->sec; session->http_requests_count = 0; session->bytes_from_http = session->bytes_to_http = 0; session->create_request_ip.data=ngx_pstrdup(pool,&r->connection->addr_text); session->create_request_ip.len=r->connection->addr_text.len; bzero(session->waiting_requests,NGX_RTMPT_PROXY_REQUESTS_DELAY_SIZE*sizeof(ngx_http_request_t *)); session->in_process = 0; put_session_in_hash(session); pc = ngx_pcalloc(pool, sizeof(ngx_peer_connection_t)); if (pc == NULL) { ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: cannot allocate for peer connection"); goto error; } ngx_memzero(&url, sizeof(ngx_url_t)); url.url.data = plcf->target.data; url.url.len = plcf->target.len; url.default_port = 1935; url.uri_part = 1; if (ngx_parse_url(pool, &url) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: error [%s] failed to parse server name: %V", url.err, &url.url); goto error; } session->target_url.data=ngx_pstrdup(pool,&url.url); session->target_url.len=url.url.len; ngx_memzero(pc, sizeof(ngx_peer_connection_t)); pc->log = session->log; pc->get = ngx_rtmpt_proxy_session_get_peer; pc->free = ngx_rtmpt_proxy_session_free_peer; pc->sockaddr = url.addrs[0].sockaddr; pc->socklen = url.addrs[0].socklen; pc->name = &url.addrs[0].name; rc = ngx_event_connect_peer(pc); if (rc != NGX_OK && rc != NGX_AGAIN ) { ngx_log_error(NGX_LOG_ERR, plcf->log, 0, "rtmpt/session: error in connect peer"); goto error; } pc->connection->data = session; pc->connection->read->handler = ngx_rtmpt_read_from_rtmp; pc->connection->write->handler = ngx_rtmpt_send_chain_to_rtmp; pc->connection->idle = 0; pc->connection->log = session->log; pc->connection->pool = session->pool; pc->connection->pool->log = session->log; pc->connection->read->log = session->log; pc->connection->write->log = session->log; session->connection = pc->connection; return session; error: if (pool) { ngx_destroy_pool(pool); } return NULL; }
static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { ngx_int_t rc; ngx_str_t *value, file; ngx_uint_t i, key; ngx_http_map_conf_ctx_t *ctx; ngx_http_variable_value_t *var, **vp; ctx = cf->ctx; value = cf->args->elts; if (cf->args->nelts == 1 && ngx_strcmp(value[0].data, "hostnames") == 0) { ctx->hostnames = 1; return NGX_CONF_OK; } else if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR; } else if (value[0].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid first parameter"); return NGX_CONF_ERROR; } if (ngx_strcmp(value[0].data, "include") == 0) { file = value[1]; if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); } key = 0; for (i = 0; i < value[1].len; i++) { key = ngx_hash(key, value[1].data[i]); } key %= ctx->keys.hsize; vp = ctx->values_hash[key].elts; if (vp) { for (i = 0; i < ctx->values_hash[key].nelts; i++) { if (value[1].len != (size_t) vp[i]->len) { continue; } if (ngx_strncmp(value[1].data, vp[i]->data, value[1].len) == 0) { var = vp[i]; goto found; } } } else { if (ngx_array_init(&ctx->values_hash[key], cf->pool, 4, sizeof(ngx_http_variable_value_t *)) != NGX_OK) { return NGX_CONF_ERROR; } } var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); if (var == NULL) { return NGX_CONF_ERROR; } var->len = value[1].len; var->data = ngx_pstrdup(ctx->keys.pool, &value[1]); if (var->data == NULL) { return NGX_CONF_ERROR; } var->valid = 1; var->no_cacheable = 0; var->not_found = 0; vp = ngx_array_push(&ctx->values_hash[key]); if (vp == NULL) { return NGX_CONF_ERROR; } *vp = var; found: if (ngx_strcmp(value[0].data, "default") == 0) { if (ctx->default_value) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate default map parameter"); return NGX_CONF_ERROR; } ctx->default_value = var; return NGX_CONF_OK; } if (value[0].len && value[0].data[0] == '!') { value[0].len--; value[0].data++; } rc = ngx_hash_add_key(&ctx->keys, &value[0], var, (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0); if (rc == NGX_OK) { return NGX_CONF_OK; } if (rc == NGX_DECLINED) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hostname or wildcard \"%V\"", &value[0]); } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", &value[0]); } return NGX_CONF_ERROR; }
/* * 包含一个配置文件,并读取解析配置文件 */ char * ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_int_t n; ngx_str_t *value, file, name; ngx_glob_t gl; value = cf->args->elts; file = value[1]; //配置文件名 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } /*是否包含正则表达式*/ if (strpbrk((char *) file.data, "*?[") == NULL) { ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); } ngx_memzero(&gl, sizeof(ngx_glob_t)); gl.pattern = file.data; gl.log = cf->log; gl.test = 1; if (ngx_open_glob(&gl) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_glob_n " \"%s\" failed", file.data); return NGX_CONF_ERROR; } rv = NGX_CONF_OK; /*解析配置文件, 所有满足正则表达式的文件 */ for ( ;; ) { n = ngx_read_glob(&gl, &name); if (n != NGX_OK) { break; } file.len = name.len++; file.data = ngx_pstrdup(cf->pool, &name); if (file.data == NULL) { return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); rv = ngx_conf_parse(cf, &file); if (rv != NGX_CONF_OK) { break; } } ngx_close_glob(&gl); return rv; }
static ngx_int_t ngx_dyups_init_upstream(ngx_http_dyups_srv_conf_t *duscf, ngx_str_t *name, ngx_uint_t index) { void *mconf; ngx_uint_t m; ngx_conf_t cf; ngx_http_module_t *module; ngx_http_conf_ctx_t *ctx; ngx_http_upstream_srv_conf_t *uscf, **uscfp; ngx_http_upstream_main_conf_t *umcf; ngx_http_dyups_upstream_srv_conf_t *dscf; umcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, ngx_http_upstream_module); uscfp = umcf->upstreams.elts; if (duscf->pool) { ngx_destroy_pool(duscf->pool); } uscf = duscf->upstream; duscf->pool = ngx_create_pool(128, ngx_cycle->log); if (duscf->pool == NULL) { return NGX_ERROR; } uscf = ngx_pcalloc(duscf->pool, sizeof(ngx_http_upstream_srv_conf_t)); if (uscf == NULL) { return NGX_ERROR; } uscf->flags = NGX_HTTP_UPSTREAM_CREATE |NGX_HTTP_UPSTREAM_WEIGHT |NGX_HTTP_UPSTREAM_MAX_FAILS |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT |NGX_HTTP_UPSTREAM_DOWN |NGX_HTTP_UPSTREAM_BACKUP; uscf->host.data = ngx_pstrdup(duscf->pool, name); uscf->host.len = name->len; uscf->file_name = (u_char *) "dynamic_upstream"; uscf->line = 0; uscf->port = 0; uscf->default_port = 0; uscfp[index] = uscf; duscf->dynamic = 1; duscf->upstream = uscf; cf.module_type = NGX_HTTP_MODULE; cf.cmd_type = NGX_HTTP_MAIN_CONF; cf.pool = duscf->pool; ctx = ngx_pcalloc(duscf->pool, sizeof(ngx_http_conf_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->main_conf = ((ngx_http_conf_ctx_t *) ngx_cycle->conf_ctx[ngx_http_module.index])->main_conf; ctx->srv_conf = ngx_pcalloc(cf.pool, sizeof(void *) * ngx_http_max_module); if (ctx->srv_conf == NULL) { return NGX_ERROR; } ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf; uscf->srv_conf = ctx->srv_conf; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } if (ngx_modules[m]->index == ngx_http_core_module.index) { continue; } module = ngx_modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(&cf); if (mconf == NULL) { return NGX_ERROR; } ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; } } dscf = uscf->srv_conf[ngx_http_dyups_module.ctx_index]; duscf->count = &dscf->count; return NGX_OK; }
static ngx_int_t ngx_http_storage_handler (ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; ngx_uint_t level; if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body (r); if (rc != NGX_OK && rc != NGX_AGAIN) { return rc; } if (r->headers_in.if_modified_since) { return NGX_HTTP_NOT_MODIFIED; } char filename[PATH_BUFFSIZE]; unsigned int i; for (i = 0; i < r->uri.len; i++) { if (r->uri.data[i] == ':') { break; } } if (i >= r->uri.len) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "secret not found"); return NGX_HTTP_NOT_FOUND; } if (i >= PATH_BUFFSIZE) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "path too long"); return NGX_HTTP_NOT_FOUND; } memcpy (filename, r->uri.data, i); filename[i] = 0; ngx_str_t path; path.len = i; path.data = (u_char *) filename; long long offset; int content_type; char base64url_secret[12]; int parsed_args = sscanf ((char*) &r->uri.data[i+1], "%llx:%11[0-9A-Za-z_-]:%x", &offset, base64url_secret, &content_type); if (parsed_args != 3) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "offset:secret:type not found (parsed_args = %d, %s)", parsed_args, (char *) &r->uri.data[i+1]); return NGX_HTTP_NOT_FOUND; } unsigned long long secret = decode_secret ((unsigned char *) base64url_secret); ngx_http_core_loc_conf_t *clcf = ngx_http_get_module_loc_conf (r, ngx_http_core_module); ngx_open_file_info_t of; ngx_memzero (&of, sizeof (ngx_open_file_info_t)); of.directio = clcf->directio; of.valid = clcf->open_file_cache_valid; of.min_uses = clcf->open_file_cache_min_uses; of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; if (ngx_open_cached_file (clcf->open_file_cache, &path, &of, r->pool) != NGX_OK) { switch (of.err) { case 0: return NGX_HTTP_INTERNAL_SERVER_ERROR; case NGX_ENOENT: case NGX_ENOTDIR: case NGX_ENAMETOOLONG: level = NGX_LOG_ERR; rc = NGX_HTTP_NOT_FOUND; break; case NGX_EACCES: level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; break; default: level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; break; } if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { ngx_log_error (level, r->connection->log, of.err, "%s \"%s\" failed", of.failed, path.data); } return rc; } if (!of.is_file) { 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", path.data); } return NGX_DECLINED; } int fd = of.fd; /* if (fd < 0) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "couldn't open %s", filename); return NGX_HTTP_NOT_FOUND; } */ //ngx_read_file (of.file, &E, sizeof (E), offset); struct lev_storage_file E; if (sizeof (E) != pread (fd, &E, sizeof (E), offset)) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "read fail"); //close (fd); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (E.content_type >= ct_last || E.content_type < 0) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "illegal content type"); //close (fd); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (E.type != LEV_STORAGE_FILE) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "illegal E.type"); //close (fd); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (E.secret != secret) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "secret doesn't match"); //close (fd); return NGX_HTTP_FORBIDDEN; } if (E.content_type != content_type) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "content type doesn't match"); //close (fd); return NGX_HTTP_FORBIDDEN; } char *ct = ContentTypes[content_type]; r->headers_out.content_type.len = strlen (ct); r->headers_out.content_type.data = (u_char *) ct; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = E.size; r->allow_ranges = 1; r->headers_out.last_modified_time = E.mtime; if (r->method == NGX_HTTP_HEAD) { rc = ngx_http_send_header (r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } b = ngx_pcalloc (r->pool, sizeof (ngx_buf_t)); if (b == NULL) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer."); //close (fd); return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file = ngx_pcalloc (r->pool, sizeof (ngx_file_t)); if (b->file == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } rc = ngx_http_send_header (r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } out.buf = b; out.next = NULL; b->file_pos = offset + sizeof (E); b->file_last = b->file_pos + E.size; b->in_file = 1; b->last_buf = 1; b->file->fd = of.fd; b->file->name.len = path.len; b->file->name.data = ngx_pstrdup (r->pool, &path); b->file->log = r->connection->log; b->file->directio = of.is_directio; return ngx_http_output_filter (r, &out); }
char * ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { char *rv; u_char *p; off_t size; ngx_fd_t fd; ngx_int_t rc; ngx_buf_t buf, *tbuf; ngx_conf_file_t *prev, conf_file; ngx_conf_dump_t *cd; enum { parse_file = 0, parse_block, parse_param } type; #if (NGX_SUPPRESS_WARN) fd = NGX_INVALID_FILE; prev = NULL; #endif if (filename) { /* open configuration file */ fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", filename->data); return NGX_CONF_ERROR; } prev = cf->conf_file; cf->conf_file = &conf_file; if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", filename->data); } cf->conf_file->buffer = &buf; buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log); if (buf.start == NULL) { goto failed; } buf.pos = buf.start; buf.last = buf.start; buf.end = buf.last + NGX_CONF_BUFFER; buf.temporary = 1; cf->conf_file->file.fd = fd; cf->conf_file->file.name.len = filename->len; cf->conf_file->file.name.data = filename->data; cf->conf_file->file.offset = 0; cf->conf_file->file.log = cf->log; cf->conf_file->line = 1; type = parse_file; if (ngx_dump_config #if (NGX_DEBUG) || 1 #endif ) { p = ngx_pstrdup(cf->cycle->pool, filename); if (p == NULL) { goto failed; } size = ngx_file_size(&cf->conf_file->file.info); tbuf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size); if (tbuf == NULL) { goto failed; } cd = ngx_array_push(&cf->cycle->config_dump); if (cd == NULL) { goto failed; } cd->name.len = filename->len; cd->name.data = p; cd->buffer = tbuf; cf->conf_file->dump = tbuf; } else { cf->conf_file->dump = NULL; } } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) { type = parse_block; } else { type = parse_param; } for ( ;; ) { rc = ngx_conf_read_token(cf); /* * ngx_conf_read_token() may return * * NGX_ERROR there is error * NGX_OK the token terminated by ";" was found * NGX_CONF_BLOCK_START the token terminated by "{" was found * NGX_CONF_BLOCK_DONE the "}" was found * NGX_CONF_FILE_DONE the configuration file is done */ if (rc == NGX_ERROR) { goto done; } if (rc == NGX_CONF_BLOCK_DONE) { if (type != parse_block) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\""); goto failed; } goto done; } if (rc == NGX_CONF_FILE_DONE) { if (type == parse_block) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected end of file, expecting \"}\""); goto failed; } goto done; } if (rc == NGX_CONF_BLOCK_START) { if (type == parse_param) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "block directives are not supported " "in -g option"); goto failed; } } /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */ if (cf->handler) { /* * the custom handler, i.e., that is used in the http's * "types { ... }" directive */ if (rc == NGX_CONF_BLOCK_START) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\""); goto failed; } rv = (*cf->handler)(cf, NULL, cf->handler_conf); if (rv == NGX_CONF_OK) { continue; } if (rv == NGX_CONF_ERROR) { goto failed; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv); goto failed; } rc = ngx_conf_handler(cf, rc); if (rc == NGX_ERROR) { goto failed; } } failed: rc = NGX_ERROR; done: if (filename) { if (cf->conf_file->buffer->start) { ngx_free(cf->conf_file->buffer->start); } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " %s failed", filename->data); rc = NGX_ERROR; } cf->conf_file = prev; } if (rc == NGX_ERROR) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
ngx_int_t ngx_http_php_socket_tcp_handler(ngx_http_request_t *r) { ngx_php_request = r; ngx_http_php_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_php_module); /*ngx_http_upstream_t *u; u = ctx->request->upstream; for ( ;; ){ usleep(1); if (ctx->enable_async == 1 || ctx->enable_thread == 0){ break; } if (ctx->enable_upstream == 1 || ctx->enable_thread == 0){ break; } } if (ctx->enable_async == 1){ if (ctx->is_capture_multi == 0){ ngx_http_php_subrequest_post(r); } else { ngx_http_php_subrequest_post_multi(r); } return NGX_DONE; } if (ctx->enable_upstream == 1){ ngx_http_php_socket_tcp_create_request(r); u->request_sent = 0; ngx_connection_t *c; c = u->peer.connection; ngx_add_timer(c->write, u->conf->send_timeout); ngx_http_php_upstream_send_request(r, u); return NGX_DONE; } //pthread_join(ctx->pthread_id, NULL); pthread_cond_destroy(&(ctx->cond)); pthread_mutex_destroy(&(ctx->mutex));*/ ngx_int_t rc; ngx_http_php_rputs_chain_list_t *chain; chain = ctx->rputs_chain; if (ctx->rputs_chain == NULL){ ngx_buf_t *b; ngx_str_t ns; u_char *u_str; ns.data = (u_char *)" "; ns.len = 1; chain = ngx_pcalloc(r->pool, sizeof(ngx_http_php_rputs_chain_list_t)); chain->out = ngx_alloc_chain_link(r->pool); chain->last = &chain->out; b = ngx_calloc_buf(r->pool); (*chain->last)->buf = b; (*chain->last)->next = NULL; u_str = ngx_pstrdup(r->pool, &ns); //u_str[ns.len] = '\0'; (*chain->last)->buf->pos = u_str; (*chain->last)->buf->last = u_str + ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; if (r->headers_out.content_length_n == -1){ r->headers_out.content_length_n += ns.len + 1; }else { r->headers_out.content_length_n += ns.len; } } //r->headers_out.content_type.len = sizeof("text/html") - 1; //r->headers_out.content_type.data = (u_char *)"text/html"; if (!r->headers_out.status){ r->headers_out.status = NGX_HTTP_OK; } if (r->method == NGX_HTTP_HEAD){ rc = ngx_http_send_header(r); if (rc != NGX_OK){ return rc; } } if (chain != NULL){ (*chain->last)->buf->last_buf = 1; } rc = ngx_http_send_header(r); if (rc != NGX_OK){ return rc; } ngx_http_output_filter(r, chain->out); ngx_http_set_ctx(r, NULL, ngx_http_php_module); return NGX_OK; }
static ngx_int_t ngx_lua_smtp_parse_args(lua_State *l, ngx_lua_thread_t *thr, ngx_lua_smtp_ctx_t *ctx) { int top; char *errstr; size_t n, i; ngx_str_t str, *to; ngx_log_debug0(NGX_LOG_DEBUG_CORE, thr->log, 0, "lua smtp parse args"); if (!lua_istable(l, 1)) { return luaL_error(l, "invalid the first argument, must be a table"); } top = lua_gettop(l); lua_getfield(l, 1, "host"); str.data = (u_char *) luaL_checklstring(l, -1, &str.len); ctx->u.url.len = str.len; ctx->u.url.data = ngx_pstrdup(ctx->pool, &str); if (ctx->u.url.data == NULL) { errstr = "ngx_pstrdup() failed"; goto error; } lua_getfield(l, 1, "user"); str.data = (u_char *) luaL_checklstring(l, -1, &str.len); ctx->user.len = str.len; ctx->user.data = ngx_pstrdup(ctx->pool, &str); if (ctx->user.data == NULL) { errstr = "ngx_pstrdup() failed"; goto error; } lua_getfield(l, 1, "password"); str.data = (u_char *) luaL_checklstring(l, -1, &str.len); ctx->passwd.len = str.len; ctx->passwd.data = ngx_pstrdup(ctx->pool, &str); if (ctx->passwd.data == NULL) { errstr = "ngx_pstrdup() failed"; goto error; } lua_getfield(l, 1, "from"); str.data = (u_char *) luaL_checklstring(l, -1, &str.len); ctx->from.len = str.len; ctx->from.data = ngx_pstrdup(ctx->pool, &str); if (ctx->from.data == NULL) { errstr = "ngx_pstrdup() failed"; goto error; } lua_getfield(l, 1, "to"); if (!lua_istable(l, -1)) { return luaL_error(l, "invalid value of the argument \"to\"" ", must be a table"); } n = lua_objlen(l, -1); if (n == 0) { return luaL_error(l, "the argument \"to\" is an empty table"); } for (i = 1; i <= n; i++) { to = ngx_array_push(&ctx->to); if (to == NULL) { errstr = "ngx_array_push() failed"; goto error; } lua_rawgeti(l, -1, i); str.data = (u_char *) luaL_checklstring(l, -1, &str.len); to->len = str.len; to->data = ngx_pstrdup(ctx->pool, &str); if (to->data == NULL) { errstr = "ngx_pstrdup() failed"; goto error; } lua_pop(l, 1); } lua_getfield(l, 1, "subject"); str.data = (u_char *) luaL_checklstring(l, -1, &str.len); ctx->subject.len = str.len; ctx->subject.data = ngx_pstrdup(ctx->pool, &str); if (ctx->subject.data == NULL) { errstr = "ngx_pstrdup() failed"; goto error; } lua_getfield(l, 1, "content"); str.data = (u_char *) luaL_checklstring(l, -1, &str.len); ctx->content.len = str.len; ctx->content.data = ngx_pstrdup(ctx->pool, &str); if (ctx->content.data == NULL) { errstr = "ngx_pstrdup() failed"; goto error; } lua_settop(l, top); ctx->connect_timeout = (ngx_msec_t) luaL_optnumber(l, 2, 60000); ctx->send_timeout = (ngx_msec_t) luaL_optnumber(l, 3, 60000); ctx->read_timeout = (ngx_msec_t) luaL_optnumber(l, 4, 60000); return NGX_OK; error: lua_settop(l, top); lua_pushboolean(l, 0); lua_pushstring(l, errstr); return NGX_ERROR; }
ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; char **senv, **env; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; ngx_conf_t conf; ngx_pool_t *pool; ngx_cycle_t *cycle, **old; ngx_shm_zone_t *shm_zone, *oshm_zone; ngx_list_part_t *part, *opart; ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday(); tp->sec = 0; // 这会导致秒级时间流逝而强制更新所有时间数据 ngx_time_update(); log = old_cycle->log; // 创建内存池,然后在内存池中创建cycle,再将该内存池挂到cycle上 pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } pool->log = log; cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pool = pool; cycle->log = log; cycle->new_log.log_level = NGX_LOG_ERR; cycle->old_cycle = old_cycle; // 配置前缀 cycle->conf_prefix.len = old_cycle->conf_prefix.len; cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } // 通用前缀 cycle->prefix.len = old_cycle->prefix.len; cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } // 配置文件 cycle->conf_file.len = old_cycle->conf_file.len; cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); if (cycle->conf_file.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, old_cycle->conf_file.len + 1); // 配置参数 cycle->conf_param.len = old_cycle->conf_param.len; cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); if (cycle->conf_param.data == NULL) { ngx_destroy_pool(pool); return NULL; } // 路径数组,每个元素是一个数组指针 n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10; cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->pathes.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pathes.nelts = 0; cycle->pathes.size = sizeof(ngx_path_t *); cycle->pathes.nalloc = n; cycle->pathes.pool = pool; // 获取打开的文件数目 if (old_cycle->open_files.part.nelts) { // 统计链表所有元素个数 n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } // 初始化新打开的文件列表,ngx_open_file_t的结构很简单,只有 // fd, name,文件头尾指针及位置指针 if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } // 共享内存的初始化类似于上面打开文件的初始化 if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } // 监听数组 n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->listening.nelts = 0; cycle->listening.size = sizeof(ngx_listening_t); cycle->listening.nalloc = n; cycle->listening.pool = pool; // 可重用连接队列 ngx_queue_init(&cycle->reusable_connections_queue); // 创建模块配置数组列表,每个元素是一个指针, // 指向保存了模块的配置对象的create_conf回调创建的配置 cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } // 初始化主机名 if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); ngx_destroy_pool(pool); return NULL; } /* on Linux gethostname() silently truncates name that does not fit */ hostname[NGX_MAXHOSTNAMELEN - 1] = '\0'; cycle->hostname.len = ngx_strlen(hostname); cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len); if (cycle->hostname.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); // 创建核心模块配置,通过调用模块的create_conf函数 for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } // 这个ctx是与模块类型相关的 // 比如NGX_CORE_MODULE类型的模块就是ngx_core_module_t类型 module = ngx_modules[i]->ctx; // ngx_core_module_t的create_conf函数 // 它会创建一个ngx_core_conf_t类型的对象 if (module->create_conf) { // ngx_core_module_t的create_conf函数 rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } // conf_ctx现在指向模块配置数组 // 对于核心模块来说,元素指针指向ngx_core_module_t.create_conf函 // 数创建的ngx_core_conf_t类型的对象,给之 // 后的ngx_core_module_t.init_conf函数初始化 cycle->conf_ctx[ngx_modules[i]->index] = rv; } } senv = environ; // 初始化conf ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ // 配置命令字符串数组 conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; } conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (conf.temp_pool == NULL) { ngx_destroy_pool(pool); return NULL; } conf.ctx = cycle->conf_ctx; // 接管模块配置数组 conf.cycle = cycle; conf.pool = pool; // 挂上cycle的内存池 conf.log = log; conf.module_type = NGX_CORE_MODULE; conf.cmd_type = NGX_MAIN_CONF; // 命令类型 #if 0 log->log_level = NGX_LOG_DEBUG_ALL; #endif // ngx_conf_param函数让ngx_conf_t类型的对象conf挂一个 // 临时的ngx_conf_file_t,再去调用ngx_conf_parse函数解 // 析用户指定的配置参数(cycle->conf_param),ngx_conf_parse函数 // 会以parse_param(还有parse_file和parse_block两种方式)方式执行解析循环 if (ngx_conf_param(&conf) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } // 解析配置文件 if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_test_config && !ngx_quiet_mode) { ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } // 调用ngx_core_module_t的init_conf函数初始化 for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; // ngx_core_module_t if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { // 进程角色是信号发送者,比如nginx -s可以停止已有的nginx进程 return cycle; } // 就是cycle->conf_ctx[ngx_modules[i]->index],ngx_core_conf_t类型 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_test_config) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_cycle)) { /* * we do not create the pid file in the first ngx_init_cycle() call * because we need to write the demonized process pid */ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (ccf->pid.len != old_ccf->pid.len || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) { /* new pid file name */ if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } ngx_delete_pidfile(old_cycle); } } // 测试锁文件 if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { goto failed; } // 创建目录 if (ngx_create_pathes(cycle, ccf->user) != NGX_OK) { goto failed; } // 创建新的日志文件 if (cycle->new_log.file == NULL) { cycle->new_log.file = ngx_conf_open_file(cycle, &error_log); if (cycle->new_log.file == NULL) { goto failed; } } /* open the new files */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d \"%s\"", &file[i], file[i].fd, file[i].name.data); if (file[i].fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); goto failed; } #if !(NGX_WIN32) if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); goto failed; } #endif } cycle->log = &cycle->new_log; pool->log = &cycle->new_log; /* create shared memory */ part = &cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } if (shm_zone[i].shm.size == 0) { ngx_log_error(NGX_LOG_EMERG, log, 0, "zero size shared memory zone \"%V\"", &shm_zone[i].shm.name); goto failed; } shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (n = 0; /* void */ ; n++) { if (n >= opart->nelts) { if (opart->next == NULL) { break; } opart = opart->next; oshm_zone = opart->elts; n = 0; } if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { continue; } if (ngx_strncmp(shm_zone[i].shm.name.data, oshm_zone[n].shm.name.data, shm_zone[i].shm.name.len) != 0) { continue; } if (shm_zone[i].shm.size == oshm_zone[n].shm.size) { shm_zone[i].shm.addr = oshm_zone[n].shm.addr; if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) != NGX_OK) { goto failed; } goto shm_zone_found; } ngx_shm_free(&oshm_zone[n].shm); break; } if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { goto failed; } if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { goto failed; } shm_zone_found: continue; } /* handle the listening sockets */ if (old_cycle->listening.nelts) { ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { ls[i].remain = 0; } nls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].ignore) { continue; } if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; ls[i].remain = 1; if (ls[n].backlog != nls[i].backlog) { nls[n].listen = 1; } #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /* * FreeBSD, except the most recent versions, * could not remove accept filter */ nls[n].deferred_accept = ls[i].deferred_accept; if (ls[i].accept_filter && nls[n].accept_filter) { if (ngx_strcmp(ls[i].accept_filter, nls[n].accept_filter) != 0) { nls[n].delete_deferred = 1; nls[n].add_deferred = 1; } } else if (ls[i].accept_filter) { nls[n].delete_deferred = 1; } else if (nls[n].accept_filter) { nls[n].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[n].deferred_accept && !nls[n].deferred_accept) { nls[n].delete_deferred = 1; } else if (ls[i].deferred_accept != nls[n].deferred_accept) { nls[n].add_deferred = 1; } #endif break; } } if (nls[n].fd == -1) { nls[n].open = 1; } } } else { ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { ls[i].open = 1; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) if (ls[i].accept_filter) { ls[i].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[i].deferred_accept) { ls[i].add_deferred = 1; } #endif } } if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } if (!ngx_test_config) { ngx_configure_listening_sockets(cycle); } /* commit the new cycle configuration */ if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_set_stderr_n " failed"); } } pool->log = cycle->log; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } /* close and delete stuff that lefts from an old cycle */ /* free the unnecessary shared memory */ opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (i = 0; /* void */ ; i++) { if (i >= opart->nelts) { if (opart->next == NULL) { goto old_shm_zone_done; } opart = opart->next; oshm_zone = opart->elts; i = 0; } part = &cycle->shared_memory.part; shm_zone = part->elts; for (n = 0; /* void */ ; n++) { if (n >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; n = 0; } if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len && ngx_strncmp(oshm_zone[i].shm.name.data, shm_zone[n].shm.name.data, oshm_zone[i].shm.name.len) == 0) { goto live_shm_zone; } } ngx_shm_free(&oshm_zone[i].shm); live_shm_zone: continue; } old_shm_zone_done: /* close the unnecessary listening sockets */ ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].remain || ls[i].fd == -1) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " listening socket on %V failed", &ls[i].addr_text); } #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX) { u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - 1; ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "deleting socket %s", name); if (ngx_delete_file(name) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } } #endif } /* close the unnecessary open files */ part = &old_cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } ngx_destroy_pool(conf.temp_pool); if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { /* * perl_destruct() frees environ, if it is not the same as it was at * perl_construct() time, therefore we save the previous cycle * environment before ngx_conf_parse() where it will be changed. */ env = environ; environ = senv; ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; environ = env; return cycle; } if (ngx_temp_pool == NULL) { ngx_temp_pool = ngx_create_pool(128, cycle->log); if (ngx_temp_pool == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "could not create ngx_temp_pool"); exit(1); } n = 10; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { exit(1); } ngx_old_cycles.nelts = 0; ngx_old_cycles.size = sizeof(ngx_cycle_t *); ngx_old_cycles.nalloc = n; ngx_old_cycles.pool = ngx_temp_pool; ngx_cleaner_event.handler = ngx_clean_old_cycles; ngx_cleaner_event.log = cycle->log; ngx_cleaner_event.data = &dumb; dumb.fd = (ngx_socket_t) -1; } ngx_temp_pool->log = cycle->log; old = ngx_array_push(&ngx_old_cycles); if (old == NULL) { exit(1); } *old = old_cycle; if (!ngx_cleaner_event.timer_set) { ngx_add_timer(&ngx_cleaner_event, 30000); ngx_cleaner_event.timer_set = 1; } return cycle; failed: if (!ngx_is_init_cycle(old_cycle)) { old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (old_ccf->environment) { environ = old_ccf->environment; } } /* rollback the new cycle configuration */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; } ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { if (ls[i].fd == -1 || !ls[i].open) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } } ngx_destroy_cycle_pools(&conf); return NULL; }