void ngx_http_push_stream_websocket_reading(ngx_http_request_t *r) { ngx_http_push_stream_main_conf_t *mcf = ngx_http_get_module_main_conf(r, ngx_http_push_stream_module); ngx_http_push_stream_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module); ngx_http_push_stream_module_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_push_stream_module); ngx_int_t rc = NGX_OK; ngx_event_t *rev; ngx_connection_t *c; uint64_t i; ngx_buf_t buf; ngx_queue_t *q; ngx_http_push_stream_set_buffer(&buf, ctx->frame->header, ctx->frame->last, 8); c = r->connection; rev = c->read; for (;;) { if (c->error || c->timedout || c->close || c->destroyed || rev->closed || rev->eof) { goto finalize; } switch (ctx->frame->step) { case NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_START_STEP: //reading frame header if ((rc = ngx_http_push_stream_recv(c, rev, &buf, 2)) != NGX_OK) { goto exit; } ctx->frame->fin = (ctx->frame->header[0] >> 7) & 1; ctx->frame->rsv1 = (ctx->frame->header[0] >> 6) & 1; ctx->frame->rsv2 = (ctx->frame->header[0] >> 5) & 1; ctx->frame->rsv3 = (ctx->frame->header[0] >> 4) & 1; ctx->frame->opcode = ctx->frame->header[0] & 0xf; ctx->frame->mask = (ctx->frame->header[1] >> 7) & 1; ctx->frame->payload_len = ctx->frame->header[1] & 0x7f; ctx->frame->step = NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_GET_REAL_SIZE_STEP; break; case NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_GET_REAL_SIZE_STEP: if (ctx->frame->payload_len == 126) { if ((rc = ngx_http_push_stream_recv(c, rev, &buf, 2)) != NGX_OK) { goto exit; } uint16_t len; ngx_memcpy(&len, ctx->frame->header, 2); ctx->frame->payload_len = ntohs(len); } else if (ctx->frame->payload_len == 127) { if ((rc = ngx_http_push_stream_recv(c, rev, &buf, 8)) != NGX_OK) { goto exit; } uint64_t len; ngx_memcpy(&len, ctx->frame->header, 8); ctx->frame->payload_len = ngx_http_push_stream_ntohll(len); } ctx->frame->step = NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_GET_MASK_KEY_STEP; break; case NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_GET_MASK_KEY_STEP: if (ctx->frame->mask) { if ((rc = ngx_http_push_stream_recv(c, rev, &buf, 4)) != NGX_OK) { goto exit; } ngx_memcpy(ctx->frame->mask_key, buf.start, 4); } ctx->frame->step = NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_GET_PAYLOAD_STEP; break; case NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_GET_PAYLOAD_STEP: if ( (ctx->frame->opcode != NGX_HTTP_PUSH_STREAM_WEBSOCKET_TEXT_OPCODE) && (ctx->frame->opcode != NGX_HTTP_PUSH_STREAM_WEBSOCKET_CLOSE_OPCODE) && (ctx->frame->opcode != NGX_HTTP_PUSH_STREAM_WEBSOCKET_PING_OPCODE) && (ctx->frame->opcode != NGX_HTTP_PUSH_STREAM_WEBSOCKET_PONG_OPCODE) ) { rc = ngx_http_push_stream_send_response_text(r, NGX_HTTP_PUSH_STREAM_WEBSOCKET_CLOSE_LAST_FRAME_BYTE, sizeof(NGX_HTTP_PUSH_STREAM_WEBSOCKET_CLOSE_LAST_FRAME_BYTE), 1); goto finalize; } if (ctx->frame->payload_len > 0) { //create a temporary pool to allocate temporary elements if (ctx->temp_pool == NULL) { if ((ctx->temp_pool = ngx_create_pool(4096, r->connection->log)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to allocate memory for temporary pool"); goto finalize; } if ((ctx->frame->payload = ngx_pcalloc(ctx->temp_pool, ctx->frame->payload_len)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to allocate memory for payload"); goto finalize; } ctx->frame->last = ctx->frame->payload; } ngx_http_push_stream_set_buffer(&buf, ctx->frame->payload, ctx->frame->last, ctx->frame->payload_len); if ((rc = ngx_http_push_stream_recv(c, rev, &buf, ctx->frame->payload_len)) != NGX_OK) { goto exit; } if (ctx->frame->mask) { for (i = 0; i < ctx->frame->payload_len; i++) { ctx->frame->payload[i] = ctx->frame->payload[i] ^ ctx->frame->mask_key[i % 4]; } } if (!ngx_http_push_stream_is_utf8(ctx->frame->payload, ctx->frame->payload_len)) { goto finalize; } if (cf->websocket_allow_publish && (ctx->frame->opcode == NGX_HTTP_PUSH_STREAM_WEBSOCKET_TEXT_OPCODE)) { for (q = ngx_queue_head(&ctx->subscriber->subscriptions); q != ngx_queue_sentinel(&ctx->subscriber->subscriptions); q = ngx_queue_next(q)) { ngx_http_push_stream_subscription_t *subscription = ngx_queue_data(q, ngx_http_push_stream_subscription_t, queue); if (subscription->channel->for_events) { // skip events channel on publish by websocket connections continue; } if (ngx_http_push_stream_add_msg_to_channel(mcf, r->connection->log, subscription->channel, ctx->frame->payload, ctx->frame->payload_len, NULL, NULL, cf->store_messages, ctx->temp_pool) != NGX_OK) { goto finalize; } } } if (ctx->temp_pool != NULL) { ngx_destroy_pool(ctx->temp_pool); ctx->temp_pool = NULL; } } ctx->frame->step = NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_START_STEP; ctx->frame->last = NULL; if (ctx->frame->opcode == NGX_HTTP_PUSH_STREAM_WEBSOCKET_PING_OPCODE) { ngx_http_push_stream_send_response_text(r, NGX_HTTP_PUSH_STREAM_WEBSOCKET_PONG_LAST_FRAME_BYTE, sizeof(NGX_HTTP_PUSH_STREAM_WEBSOCKET_PONG_LAST_FRAME_BYTE), 1); } if (ctx->frame->opcode == NGX_HTTP_PUSH_STREAM_WEBSOCKET_CLOSE_OPCODE) { rc = ngx_http_push_stream_send_response_text(r, NGX_HTTP_PUSH_STREAM_WEBSOCKET_CLOSE_LAST_FRAME_BYTE, sizeof(NGX_HTTP_PUSH_STREAM_WEBSOCKET_CLOSE_LAST_FRAME_BYTE), 1); goto finalize; } return; break; default: ngx_log_debug(NGX_LOG_DEBUG, c->log, 0, "push stream module: unknown websocket step (%d)", ctx->frame->step); goto finalize; break; } ngx_http_push_stream_set_buffer(&buf, ctx->frame->header, NULL, 8); } exit: if (rc == NGX_AGAIN) { ctx->frame->last = buf.last; if (!c->read->ready) { if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno, "push stream module: failed to restore read events"); goto finalize; } } } if (rc == NGX_ERROR) { rev->eof = 1; c->error = 1; ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno, "push stream module: client closed prematurely connection"); goto finalize; } return; finalize: ngx_http_push_stream_run_cleanup_pool_handler(r->pool, (ngx_pool_cleanup_pt) ngx_http_push_stream_cleanup_request_context); ngx_http_finalize_request(r, c->error ? NGX_HTTP_CLIENT_CLOSED_REQUEST : NGX_OK); }
static char * ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void ***ctx; ngx_uint_t i; ngx_conf_t pcf; ngx_event_module_t *m; if (*(void **) conf) { return "is duplicate"; } /* count the number of the event modules and set up their indices */ ngx_event_max_module = 0; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } ngx_modules[i]->ctx_index = ngx_event_max_module++; } ctx = ngx_pcalloc(cf->pool, sizeof(void *)); if (ctx == NULL) { return NGX_CONF_ERROR; } *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *)); if (*ctx == NULL) { return NGX_CONF_ERROR; } *(void **) conf = ctx; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } m = ngx_modules[i]->ctx; if (m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle); if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } } pcf = *cf; cf->ctx = ctx; cf->module_type = NGX_EVENT_MODULE; cf->cmd_type = NGX_EVENT_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv != NGX_CONF_OK) { return rv; } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } m = ngx_modules[i]->ctx; if (m->init_conf) { rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]); if (rv != NGX_CONF_OK) { return rv; } } } return NGX_CONF_OK; }
/** * nginx post-read-request handler to feed request line and headers to IronBee. * * @param[in] r The nginx request object. * @return Declined (ignored) or error status. */ static ngx_int_t ironbee_post_read_request(ngx_http_request_t *r) { ngxib_req_ctx *ctx; ib_conn_t *iconn; ib_parsed_req_line_t *rline; ib_parsed_header_wrapper_t *ibhdrs; ib_status_t rc; ngx_list_part_t *part; ngx_table_elt_t *hdr; unsigned int i; /* Don't process internal requests */ if (r->internal) return NGX_DECLINED; ngx_regex_malloc_init(r->pool); ctx = ngx_pcalloc(r->pool, sizeof(ngxib_req_ctx)); ctx->r = r; ngx_http_set_ctx(r, ctx, ngx_ironbee_module); iconn = ngxib_conn_get(ctx); ib_tx_create(&ctx->tx, iconn, ctx); /* Notify IronBee of request line and headers */ rc = ib_parsed_req_line_create(ctx->tx, &rline, (const char*)r->request_line.data, r->request_line.len, (const char*)r->method_name.data, r->method_name.len, (const char*)r->unparsed_uri.data, r->unparsed_uri.len, (const char*)r->http_protocol.data, r->http_protocol.len); if (rc != IB_OK) cleanup_return NGX_ERROR; ib_state_notify_request_started(ctx->tx->ib, ctx->tx, rline); rc = ib_parsed_name_value_pair_list_wrapper_create(&ibhdrs, ctx->tx); if (rc != IB_OK) cleanup_return NGX_ERROR; for (part = &r->headers_in.headers.part; part != NULL; part = part->next) { hdr = part->elts; for (i = 0; i < part->nelts; ++i) { ib_parsed_name_value_pair_list_add(ibhdrs, (const char*)hdr->key.data, hdr->key.len, (const char*)hdr->value.data, hdr->value.len); ++hdr; } } rc = ib_state_notify_request_header_data(ctx->tx->ib, ctx->tx, ibhdrs); if (rc != IB_OK) cleanup_return NGX_ERROR; rc = ib_state_notify_request_header_finished(ctx->tx->ib, ctx->tx); if (rc != IB_OK) cleanup_return NGX_ERROR; if (!ngxib_has_request_body(r, ctx)) { rc = ib_state_notify_request_finished(ctx->tx->ib, ctx->tx); if (rc != IB_OK) cleanup_return NGX_ERROR; } ctx->hdrs_in = 1; if (STATUS_IS_ERROR(ctx->status)) { ctx->internal_errordoc = 1; cleanup_return ctx->status; } cleanup_return NGX_DECLINED; }
static void * ngx_http_aclog_bypass_create_loc_conf(ngx_conf_t *cf) { return ngx_pcalloc(cf->pool, sizeof(ngx_http_aclog_bypass_conf_t)); }
static ngx_int_t ngx_stream_lua_set_ssl(ngx_conf_t *cf, ngx_stream_lua_srv_conf_t *lscf) { ngx_pool_cleanup_t *cln; lscf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); if (lscf->ssl == NULL) { return NGX_ERROR; } lscf->ssl->log = cf->log; if (ngx_ssl_create(lscf->ssl, lscf->ssl_protocols, NULL) != NGX_OK) { return NGX_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_ssl_cleanup_ctx; cln->data = lscf->ssl; if (SSL_CTX_set_cipher_list(lscf->ssl->ctx, (const char *) lscf->ssl_ciphers.data) == 0) { ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &lscf->ssl_ciphers); return NGX_ERROR; } if (lscf->ssl_trusted_certificate.len) { #if defined(nginx_version) && nginx_version >= 1003007 if (ngx_ssl_trusted_certificate(cf, lscf->ssl, &lscf->ssl_trusted_certificate, lscf->ssl_verify_depth) != NGX_OK) { return NGX_ERROR; } #else ngx_log_error(NGX_LOG_CRIT, cf->log, 0, "at least nginx 1.3.7 is " "required for the \"lua_ssl_trusted_certificate\" " "directive"); return NGX_ERROR; #endif } dd("ssl crl: %.*s", (int) lscf->ssl_crl.len, lscf->ssl_crl.data); if (ngx_ssl_crl(cf, lscf->ssl, &lscf->ssl_crl) != NGX_OK) { return NGX_ERROR; } return NGX_OK; }
ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) { int cc_ref; lua_State *cc; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("content by chunk"); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx, ctx = %p", ctx); ctx->cc_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; /* {{{ new coroutine to handle request */ cc = ngx_http_lua_new_thread(r, L, &cc_ref); if (cc == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-content-by-chunk) failed to create new coroutine " "to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, cc, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(cc, LUA_GLOBALSINDEX); lua_setfenv(cc, -2); /* save reference of code to ease forcing stopping */ lua_pushvalue(cc, -1); lua_setglobal(cc, GLOBALS_SYMBOL_RUNCODE); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(cc, r); lua_setglobal(cc, GLOBALS_SYMBOL_REQUEST); /* }}} */ ctx->cc = cc; ctx->cc_ref = cc_ref; /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ return ngx_http_lua_run_thread(L, r, ctx, 0); }
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); 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->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); if(msg_id) { fsub->sub.last_msg_id.time = msg_id->time; fsub->sub.last_msg_id.tag = msg_id->tag; } 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->already_enqueued = 0; fsub->awaiting_destruction = 0; fsub->reserved = 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); } 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); ngx_http_set_ctx(r, fsub, nchan_module); //gonna need this for recv return &fsub->sub; }
static char * ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_uint_t i, m, mi, s; ngx_conf_t pcf; ngx_array_t ports; ngx_stream_listen_t *listen; ngx_stream_module_t *module; ngx_stream_conf_ctx_t *ctx; ngx_stream_core_srv_conf_t **cscfp; ngx_stream_core_main_conf_t *cmcf; if (*(ngx_stream_conf_ctx_t **) conf) { return "is duplicate"; } /* the main stream context */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } *(ngx_stream_conf_ctx_t **) conf = ctx; /* count the number of the stream modules and set up their indices */ ngx_stream_max_module = ngx_count_modules(cf->cycle, NGX_STREAM_MODULE); /* the stream main_conf context, it's the same in the all stream contexts */ ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->main_conf == NULL) { return NGX_CONF_ERROR; } /* * the stream null srv_conf context, it is used to merge * the server{}s' srv_conf's */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } /* * create the main_conf's and the null srv_conf's of the all stream modules */ for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; mi = cf->cycle->modules[m]->ctx_index; if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); if (ctx->main_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_srv_conf) { ctx->srv_conf[mi] = module->create_srv_conf(cf); if (ctx->srv_conf[mi] == NULL) { return NGX_CONF_ERROR; } } } pcf = *cf; cf->ctx = ctx; for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; if (module->preconfiguration) { if (module->preconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; } } } /* parse inside the stream{} block */ cf->module_type = NGX_STREAM_MODULE; cf->cmd_type = NGX_STREAM_MAIN_CONF; rv = ngx_conf_parse(cf, NULL); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } /* init stream{} main_conf's, merge the server{}s' srv_conf's */ cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; cscfp = cmcf->servers.elts; for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; mi = cf->cycle->modules[m]->ctx_index; /* init stream{} main_conf's */ cf->ctx = ctx; if (module->init_main_conf) { rv = module->init_main_conf(cf, ctx->main_conf[mi]); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } } for (s = 0; s < cmcf->servers.nelts; s++) { /* merge the server{}s' srv_conf's */ cf->ctx = cscfp[s]->ctx; if (module->merge_srv_conf) { rv = module->merge_srv_conf(cf, ctx->srv_conf[mi], cscfp[s]->ctx->srv_conf[mi]); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } } } } if (ngx_stream_init_phases(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR; } for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; if (module->postconfiguration) { if (module->postconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; } } } if (ngx_stream_variables_init_vars(cf) != NGX_OK) { return NGX_CONF_ERROR; } *cf = pcf; if (ngx_stream_init_phase_handlers(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t)) != NGX_OK) { return NGX_CONF_ERROR; } listen = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { if (ngx_stream_add_ports(cf, &ports, &listen[i]) != NGX_OK) { return NGX_CONF_ERROR; } } return ngx_stream_optimize_servers(cf, &ports); }
ngx_int_t ngx_postgres_upstream_init_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *uscf) { ngx_postgres_upstream_peer_data_t *pgdt; ngx_postgres_upstream_srv_conf_t *pgscf; ngx_postgres_loc_conf_t *pglcf; ngx_postgres_ctx_t *pgctx; ngx_http_core_loc_conf_t *clcf; ngx_http_upstream_t *u; ngx_postgres_mixed_t *query; ngx_str_t sql; ngx_uint_t i; dd("entering"); pgdt = ngx_pcalloc(r->pool, sizeof(ngx_postgres_upstream_peer_data_t)); if (pgdt == NULL) { goto failed; } u = r->upstream; pgdt->upstream = u; pgdt->request = r; pgscf = ngx_http_conf_upstream_srv_conf(uscf, ngx_postgres_module); pglcf = ngx_http_get_module_loc_conf(r, ngx_postgres_module); pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module); pgdt->srv_conf = pgscf; pgdt->loc_conf = pglcf; u->peer.data = pgdt; u->peer.get = ngx_postgres_upstream_get_peer; u->peer.free = ngx_postgres_upstream_free_peer; if (pglcf->query.methods_set & r->method) { /* method-specific query */ dd("using method-specific query"); query = pglcf->query.methods->elts; for (i = 0; i < pglcf->query.methods->nelts; i++) { if (query[i].key & r->method) { query = &query[i]; break; } } if (i == pglcf->query.methods->nelts) { goto failed; } } else { /* default query */ dd("using default query"); query = pglcf->query.def; } if (query->cv) { /* complex value */ dd("using complex value"); if (ngx_http_complex_value(r, query->cv, &sql) != NGX_OK) { goto failed; } if (sql.len == 0) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "postgres: empty \"postgres_query\" (was: \"%V\")" " in location \"%V\"", &query->cv->value, &clcf->name); goto failed; } pgdt->query = sql; } else { /* simple value */ dd("using simple value"); pgdt->query = query->sv; } /* set $postgres_query */ pgctx->var_query = pgdt->query; dd("returning NGX_OK"); return NGX_OK; failed: #if defined(nginx_version) && (nginx_version >= 8017) dd("returning NGX_ERROR"); return NGX_ERROR; #else r->upstream->peer.data = NULL; dd("returning NGX_OK (NGX_ERROR)"); return NGX_OK; #endif }
static ngx_int_t ngx_live_relay_simple_relay(ngx_rtmp_session_t *s, ngx_live_relay_t *relay, unsigned publishing) { ngx_rtmp_session_t *rs; ngx_live_relay_ctx_t *ctx, *pctx; ngx_live_relay_app_conf_t *lracf; ngx_live_relay_simple_ctx_t *sctx; rs = ngx_rtmp_create_relay_session(s, &ngx_live_relay_simple_module); if (rs == NULL) { ngx_log_error(NGX_LOG_ERR, s->log, 0, "relay simple, create relay session failed"); return NGX_DECLINED; } rs->publishing = publishing; rs->live_stream = s->live_stream; ngx_live_create_ctx(rs, publishing); sctx = ngx_pcalloc(rs->pool, sizeof(ngx_live_relay_simple_ctx_t)); if (sctx == NULL) { ngx_log_error(NGX_LOG_ERR, rs->log, 0, "relay simple, create simple relay ctx failed"); ngx_rtmp_finalize_session(rs); return NGX_OK; } ngx_rtmp_set_ctx(rs, sctx, ngx_live_relay_simple_module); sctx->relay = relay; ctx = ngx_rtmp_get_module_ctx(rs, ngx_live_relay_module); ctx->reconnect.log = rs->log; ctx->reconnect.data = rs; ctx->reconnect.handler = ngx_live_relay_simple_handler; if (s->publishing != rs->publishing) { ngx_post_event(&ctx->reconnect, &ngx_posted_events); return NGX_OK; } // normal publisher close, need to trigger pull if (s->publishing && !s->relay) { ngx_post_event(&ctx->reconnect, &ngx_posted_events); return NGX_OK; } // reconnect pctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); if (pctx->successd) { // prev relay successd ngx_post_event(&ctx->reconnect, &ngx_posted_events); return NGX_OK; } ctx->idx = pctx->idx; ctx->failed_reconnect = pctx->failed_reconnect; if (ctx->idx < relay->urls.nelts) { // retry backup url immediately ngx_post_event(&ctx->reconnect, &ngx_posted_events); return NGX_OK; } lracf = ngx_rtmp_get_module_app_conf(rs, ngx_live_relay_module); if (!pctx->reconnect.timer_set) { // prev relay timeout ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, lracf->relay_reconnect); ngx_post_event(&ctx->reconnect, &ngx_posted_events); return NGX_OK; } if (pctx->failed_reconnect) { ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, lracf->relay_reconnect); } else { ctx->failed_reconnect = lracf->failed_reconnect; } ctx->failed_delay = 1; ngx_add_timer(&ctx->reconnect, ctx->failed_reconnect); return NGX_OK; }
static ngx_int_t ngx_stream_ssl_preread_handler(ngx_stream_session_t *s) { u_char *last, *p; size_t len; ngx_int_t rc; ngx_connection_t *c; ngx_stream_ssl_preread_ctx_t *ctx; ngx_stream_ssl_preread_srv_conf_t *sscf; c = s->connection; ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "ssl preread handler"); sscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_preread_module); if (!sscf->enabled) { return NGX_DECLINED; } if (c->type != SOCK_STREAM) { return NGX_DECLINED; } if (c->buffer == NULL) { return NGX_AGAIN; } ctx = ngx_stream_get_module_ctx(s, ngx_stream_ssl_preread_module); if (ctx == NULL) { ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_ssl_preread_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_stream_set_ctx(s, ctx, ngx_stream_ssl_preread_module); ctx->pool = c->pool; ctx->log = c->log; ctx->pos = c->buffer->pos; } p = ctx->pos; last = c->buffer->last; while (last - p >= 5) { if (p[0] != 0x16) { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, "ssl preread: not a handshake"); return NGX_DECLINED; } if (p[1] != 3) { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, "ssl preread: unsupported SSL version"); return NGX_DECLINED; } len = (p[3] << 8) + p[4]; /* read the whole record before parsing */ if ((size_t) (last - p) < len + 5) { break; } p += 5; rc = ngx_stream_ssl_preread_parse_record(ctx, p, p + len); if (rc != NGX_AGAIN) { return rc; } p += len; } ctx->pos = p; return NGX_AGAIN; }
void ngx_http_sub_auth(ngx_http_request_t *r) { u_char *data, *key; u_char str[12] = {'\0'}, str1[12] = {'\0'}; ngx_uint_t len = 0, i; ngx_str_t *sub; ngx_http_oauth_sub_shm_t *sub_shm; ngx_http_oauth_service_ctx_t *ctx; ngx_http_oauth_keepalive_peer_data_t *mkp; ctx = ngx_http_get_module_ctx(r, ngx_http_oauth_service_module); sub = &ctx->sub; sub_shm = sub_ctx->sub_shm; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "sub auth: %V", sub); mkp = ngx_palloc(r->pool, sizeof(ngx_http_oauth_keepalive_peer_data_t)); mkp->request = r; ngx_memzero(&mkp->pc, sizeof(ngx_peer_connection_t)); mkp->pc.get = ngx_event_get_peer; mkp->pc.log = r->connection->log; mkp->pc.log_error = NGX_ERROR_ERR; mkp->pc.cached = 0; mkp->pc.connection = NULL; mkp->state = 0; mkp->check_timeout_ev.timer_set = 0; if (sub->len == 0) { ngx_http_finalize_request_failed(mkp); return; } ngx_sub_validate(r, sub, &data, sub_shm->key->sub); if (data == NULL) { ctx->sub_signed_flag = 1; ngx_http_finalize_request_failed(mkp); return; } if (ngx_http_memcache_make_key(r, data + 1) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } uint64_t ctime = (uint64_t)(ctx->ctime.data[3] & 0xff); ctime |= (uint64_t)((ctx->ctime.data[2] << 8) & 0xff00); ctime |= (uint64_t)((ctx->ctime.data[1] << 16) & 0xff0000); ctime |= (uint64_t)((ctx->ctime.data[0] << 24) & 0xff000000); ctime -= FIXED_TIME; ngx_base62_encode(ctime, str1, 12); u_char *str2 = ngx_pcalloc(r->pool, ctx->domain.len * 12); for (i = 0; i < ctx->domain.len; i++) { ngx_base62_encode((uint64_t)ctx->domain.data[i], str, 12); ngx_sprintf(str2 + len, "%s", str); len = ngx_strlen(str2); ngx_memset(str, '\0', 12); } ctx->memcache_key.len = ctx->uid.len +ctx->rand.len +ngx_strlen(str2) +ngx_strlen(str1) +ngx_strlen("{}_"); ctx->memcache_key.data = ngx_pcalloc(r->pool, ctx->memcache_key.len); key = ctx->memcache_key.data; ngx_sprintf(key, "{%*s}_", ctx->uid.len, ctx->uid.data); len = ngx_strlen(key); ngx_sprintf(key + len, "%*s", ctx->rand.len, ctx->rand.data); len = ngx_strlen(key); ngx_sprintf(key + len, "%s", str2); len = ngx_strlen(key); ngx_sprintf(key + len, "%s", str1); if (ngx_http_memcache_connect_handler(mkp) != NGX_OK) { ngx_http_finalize_request_success(mkp); } }
ngx_rtmp_session_t * ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf) { ngx_rtmp_session_t *s; ngx_rtmp_core_srv_conf_t *cscf; ngx_rtmp_error_log_ctx_t *ctx; s = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_session_t) + sizeof(ngx_chain_t *) * ((ngx_rtmp_core_srv_conf_t *) addr_conf->ctx-> srv_conf[ngx_rtmp_core_module .ctx_index])->out_queue); if (s == NULL) { ngx_rtmp_close_connection(c); return NULL; } s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; s->addr_text = &addr_conf->addr_text; c->data = s; s->connection = c; ctx = ngx_palloc(c->pool, sizeof(ngx_rtmp_error_log_ctx_t)); if (ctx == NULL) { ngx_rtmp_close_connection(c); return NULL; } ctx->client = &c->addr_text; ctx->session = s; c->log->connection = c->number; c->log->handler = ngx_rtmp_log_error; c->log->data = ctx; c->log->action = NULL; c->log_error = NGX_ERROR_INFO; s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_rtmp_max_module); if (s->ctx == NULL) { ngx_rtmp_close_connection(c); return NULL; } cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); s->out_queue = cscf->out_queue; s->out_cork = cscf->out_cork; s->in_streams = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_stream_t) * cscf->max_streams); if (s->in_streams == NULL) { ngx_rtmp_close_connection(c); return NULL; } s->epoch = ngx_current_msec; s->timeout = cscf->timeout; ngx_rtmp_set_chunk_size(s, NGX_RTMP_DEFAULT_CHUNK_SIZE); if (ngx_rtmp_fire_event(s, NGX_RTMP_CONNECT, NULL, NULL) != NGX_OK) { ngx_rtmp_finalize_session(s); return NULL; } return s; }
static ngx_int_t ngx_http_push_stream_websocket_handler(ngx_http_request_t *r) { #if !(NGX_HAVE_SHA1) ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: sha1 support is needed to use WebSocket"); return NGX_OK; #endif ngx_http_push_stream_main_conf_t *mcf = ngx_http_get_module_main_conf(r, ngx_http_push_stream_module); ngx_http_push_stream_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module); ngx_http_push_stream_subscriber_t *worker_subscriber; ngx_http_push_stream_requested_channel_t *requested_channels, *requested_channel; ngx_queue_t *q; ngx_http_push_stream_module_ctx_t *ctx; ngx_int_t tag; time_t if_modified_since; ngx_str_t *last_event_id = NULL; ngx_int_t status_code; ngx_str_t *explain_error_message; ngx_str_t *upgrade_header, *connection_header, *sec_key_header, *sec_version_header, *sec_accept_header, *user_agent; ngx_int_t version; // WebSocket connections must not use keepalive r->keepalive = 0; // only accept GET method if (!(r->method & NGX_HTTP_GET)) { ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ALLOW, &NGX_HTTP_PUSH_STREAM_ALLOW_GET); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_NOT_ALLOWED, NULL); } ngx_http_push_stream_set_expires(r, NGX_HTTP_PUSH_STREAM_EXPIRES_EPOCH, 0); upgrade_header = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_UPGRADE); connection_header = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_CONNECTION); sec_key_header = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_SEC_WEBSOCKET_KEY); sec_version_header = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_SEC_WEBSOCKET_VERSION); user_agent = ngx_http_push_stream_get_header(r, &NGX_HTTP_HEADER_USER_AGENT); if ((upgrade_header == NULL) || (connection_header == NULL) || (sec_key_header == NULL) || (sec_version_header == NULL)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: %V, user_agent: %s, key %s, version: %s", &NGX_HTTP_PUSH_STREAM_NO_MANDATORY_HEADERS_MESSAGE, user_agent == NULL ? (void*)"N/A" : user_agent->data, sec_key_header == NULL ? (void*)"N/A" : sec_key_header == NULL ? (void*)"N/A" : sec_key_header->data, sec_version_header == NULL ? (void*)"N/A" : sec_version_header->data); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, ":%d, %d, %d, %d:", upgrade_header == NULL ? 0 : upgrade_header->len, connection_header == NULL ? 0 : connection_header->len, sec_key_header == NULL ? 0 : sec_key_header->len, sec_version_header == NULL ? 0 : sec_version_header->len); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_NO_MANDATORY_HEADERS_MESSAGE); } version = ngx_atoi(sec_version_header->data, sec_version_header->len); if ((version != NGX_HTTP_PUSH_STREAM_WEBSOCKET_VERSION_8) && (version != NGX_HTTP_PUSH_STREAM_WEBSOCKET_VERSION_13)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: version: %d %V", version, &NGX_HTTP_PUSH_STREAM_WRONG_WEBSOCKET_VERSION_MESSAGE); ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_SEC_WEBSOCKET_VERSION, &NGX_HTTP_PUSH_STREAM_WEBSOCKET_SUPPORTED_VERSIONS); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_WRONG_WEBSOCKET_VERSION_MESSAGE); } if ((ctx = ngx_http_push_stream_add_request_context(r)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to create request context"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if ((ctx->frame = ngx_pcalloc(r->pool, sizeof(ngx_http_push_stream_frame_t))) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to create frame structure"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->frame->step = NGX_HTTP_PUSH_STREAM_WEBSOCKET_READ_START_STEP; ctx->frame->last = NULL; ctx->frame->payload = NULL; if ((sec_accept_header = ngx_http_push_stream_generate_websocket_accept_value(r, sec_key_header, ctx->temp_pool)) == NULL) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: could not generate security accept header value"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_UPGRADE, &NGX_HTTP_PUSH_STREAM_WEBSOCKET_UPGRADE); ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_CONNECTION, &NGX_HTTP_PUSH_STREAM_WEBSOCKET_CONNECTION); ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_SEC_WEBSOCKET_ACCEPT, sec_accept_header); r->headers_out.status_line = NGX_HTTP_PUSH_STREAM_101_STATUS_LINE; ngx_http_push_stream_send_only_added_headers(r); //get channels ids and backtracks from path requested_channels = ngx_http_push_stream_parse_channels_ids_from_path(r, ctx->temp_pool); if ((requested_channels == NULL) || ngx_queue_empty(&requested_channels->queue)) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: the push_stream_channels_path is required but is not set"); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_NO_CHANNEL_ID_MESSAGE); } //validate channels: name, length and quantity. check if channel exists when authorized_channels_only is on. check if channel is full of subscribers if (ngx_http_push_stream_validate_channels(r, requested_channels, &status_code, &explain_error_message) == NGX_ERROR) { return ngx_http_push_stream_send_websocket_close_frame(r, status_code, explain_error_message); } // get control values ngx_http_push_stream_get_last_received_message_values(r, &if_modified_since, &tag, &last_event_id); // stream access if ((worker_subscriber = ngx_http_push_stream_subscriber_prepare_request_to_keep_connected(r)) == NULL) { return ngx_http_push_stream_send_websocket_close_frame(r, NGX_HTTP_INTERNAL_SERVER_ERROR, &NGX_HTTP_PUSH_STREAM_EMPTY); } // sending response content header if (ngx_http_push_stream_send_response_content_header(r, cf) == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: could not send content header to subscriber"); return ngx_http_push_stream_send_websocket_close_frame(r, NGX_HTTP_INTERNAL_SERVER_ERROR, &NGX_HTTP_PUSH_STREAM_EMPTY); } if (ngx_http_push_stream_registry_subscriber(r, worker_subscriber) == NGX_ERROR) { return ngx_http_push_stream_send_websocket_close_frame(r, NGX_HTTP_INTERNAL_SERVER_ERROR, &NGX_HTTP_PUSH_STREAM_EMPTY); } // adding subscriber to channel(s) and send backtrack messages for (q = ngx_queue_head(&requested_channels->queue); q != ngx_queue_sentinel(&requested_channels->queue); q = ngx_queue_next(q)) { requested_channel = ngx_queue_data(q, ngx_http_push_stream_requested_channel_t, queue); if (ngx_http_push_stream_subscriber_assign_channel(mcf, cf, r, requested_channel, if_modified_since, tag, last_event_id, worker_subscriber, ctx->temp_pool) != NGX_OK) { return ngx_http_push_stream_send_websocket_close_frame(r, NGX_HTTP_INTERNAL_SERVER_ERROR, &NGX_HTTP_PUSH_STREAM_EMPTY); } } if (ctx->temp_pool != NULL) { ngx_destroy_pool(ctx->temp_pool); ctx->temp_pool = NULL; } return NGX_DONE; }
static ngx_http_modsecurity_ctx_t * ngx_http_modsecurity_create_ctx(ngx_http_request_t *r) { ngx_http_modsecurity_loc_conf_t *cf; ngx_pool_cleanup_t *cln; ngx_http_modsecurity_ctx_t *ctx; apr_sockaddr_t *asa; struct sockaddr_in *sin; char *txid; unsigned char salt[TXID_SIZE]; int i; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_modsecurity_ctx_t)); if (ctx == NULL) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "modSecurity: ctx memory allocation error"); return NULL; } cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_modsecurity_ctx_t)); if (cln == NULL) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "modSecurity: ctx memory allocation error"); return NULL; } cln->handler = ngx_http_modsecurity_cleanup; cln->data = ctx; ctx->r = r; if (r->connection->requests == 0 || ctx->connection == NULL) { /* TODO: set server_rec, why igonre return value? */ ctx->connection = modsecNewConnection(); /* fill apr_sockaddr_t */ asa = ngx_palloc(r->pool, sizeof(apr_sockaddr_t)); asa->pool = ctx->connection->pool; asa->hostname = (char *)ngx_pstrdup0(r->pool, &r->connection->addr_text); asa->servname = asa->hostname; asa->next = NULL; asa->salen = r->connection->socklen; ngx_memcpy(&asa->sa, r->connection->sockaddr, asa->salen); asa->family = ((struct sockaddr *)&asa->sa)->sa_family; switch ( asa->family) { #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *)&asa->sa; asa->ipaddr_ptr = &sin6->sin6_addr; asa->ipaddr_len = sizeof(sin6->sin6_addr); asa->port = ntohs(sin6->sin6_port); asa->addr_str_len = NGX_INET6_ADDRSTRLEN + 1; break; #endif default: /* AF_INET */ sin = (struct sockaddr_in *) &asa->sa; asa->ipaddr_ptr = &sin->sin_addr; asa->ipaddr_len = sizeof(sin->sin_addr); asa->port = ntohs(sin->sin_port); asa->addr_str_len = NGX_INET_ADDRSTRLEN + 1; break; } #if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3 ctx->connection->remote_addr = asa; ctx->connection->remote_ip = asa->hostname; #else ctx->connection->client_addr = asa; ctx->connection->client_ip = asa->hostname; #endif ctx->connection->remote_host = NULL; modsecProcessConnection(ctx->connection); } cf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity); ctx->req = modsecNewRequest(ctx->connection, cf->config); apr_table_setn(ctx->req->notes, NOTE_NGINX_REQUEST_CTX, (const char *) ctx); apr_generate_random_bytes(salt, TXID_SIZE); txid = apr_pcalloc (ctx->req->pool, TXID_SIZE); apr_base64_encode (txid, (const char*)salt, TXID_SIZE); for(i=0;i<TXID_SIZE;i++) { if((salt[i] >= 0x30) && (salt[i] <= 0x39)) {} else if((salt[i] >= 0x40) && (salt[i] <= 0x5A)) {} else if((salt[i] >= 0x61) && (salt[i] <= 0x7A)) {} else { if((i%2)==0) salt[i] = 0x41; else salt[i] = 0x63; } } salt[TXID_SIZE-1] = '\0'; apr_table_setn(ctx->req->subprocess_env, "UNIQUE_ID", apr_psprintf(ctx->req->pool, "%s", salt)); ctx->brigade = apr_brigade_create(ctx->req->pool, ctx->req->connection->bucket_alloc); if (ctx->brigade == NULL) { return NULL; } return ctx; }
ngx_int_t ngx_postgres_upstream_init(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *uscf) { ngx_postgres_upstream_srv_conf_t *pgscf; ngx_postgres_upstream_server_t *server; ngx_postgres_upstream_peers_t *peers; ngx_uint_t i, j, n; dd("entering"); uscf->peer.init = ngx_postgres_upstream_init_peer; pgscf = ngx_http_conf_upstream_srv_conf(uscf, ngx_postgres_module); if (pgscf->servers == NULL || pgscf->servers->nelts == 0) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "postgres: no \"postgres_server\" defined" " in upstream \"%V\" in %s:%ui", &uscf->host, uscf->file_name, uscf->line); dd("returning NGX_ERROR"); return NGX_ERROR; } /* pgscf->servers != NULL */ server = uscf->servers->elts; n = 0; for (i = 0; i < uscf->servers->nelts; i++) { n += server[i].naddrs; } peers = ngx_pcalloc(cf->pool, sizeof(ngx_postgres_upstream_peers_t) + sizeof(ngx_postgres_upstream_peer_t) * (n - 1)); if (peers == NULL) { dd("returning NGX_ERROR"); return NGX_ERROR; } peers->single = (n == 1); peers->number = n; peers->name = &uscf->host; n = 0; for (i = 0; i < uscf->servers->nelts; i++) { for (j = 0; j < server[i].naddrs; j++) { peers->peer[n].sockaddr = server[i].addrs[j].sockaddr; peers->peer[n].socklen = server[i].addrs[j].socklen; peers->peer[n].name = server[i].addrs[j].name; peers->peer[n].port = server[i].port; peers->peer[n].dbname = server[i].dbname; peers->peer[n].user = server[i].user; peers->peer[n].password = server[i].password; peers->peer[n].host.data = ngx_pnalloc(cf->pool, NGX_SOCKADDR_STRLEN); if (peers->peer[n].host.data == NULL) { dd("returning NGX_ERROR"); return NGX_ERROR; } peers->peer[n].host.len = ngx_sock_ntop(peers->peer[n].sockaddr, peers->peer[n].host.data, NGX_SOCKADDR_STRLEN, 0); if (peers->peer[n].host.len == 0) { dd("returning NGX_ERROR"); return NGX_ERROR; } n++; } } pgscf->peers = peers; pgscf->active_conns = 0; if (pgscf->max_cached) { dd("returning"); return ngx_postgres_keepalive_init(cf->pool, pgscf); } dd("returning NGX_OK"); return NGX_OK; }
ngx_int_t ngx_http_lua_content_handler(ngx_http_request_t *r) { ngx_http_lua_loc_conf_t *llcf; ngx_http_lua_ctx_t *ctx; ngx_int_t rc; llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->content_handler == NULL) { dd("no content handler found"); return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx: ctx = %p", ctx); ctx->cc_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } dd("entered? %d", (int) ctx->entered_content_phase); if (ctx->waiting_more_body) { return NGX_DONE; } if (ctx->entered_content_phase) { dd("calling wev handler"); rc = ngx_http_lua_wev_handler(r); dd("wev handler returns %d", (int) rc); return rc; } if (llcf->force_read_body && !ctx->read_body_done) { r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; rc = ngx_http_read_client_request_body(r, ngx_http_lua_content_phase_post_read); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (rc == NGX_AGAIN) { ctx->waiting_more_body = 1; return NGX_DONE; } } dd("setting entered"); ctx->entered_content_phase = 1; dd("calling content handler"); return llcf->content_handler(r); }
ngx_int_t ngx_file_reader_dump_file_part(void* context, off_t start, off_t end) { ngx_file_reader_state_t* state = context; ngx_http_request_t* r = state->r; ngx_buf_t *b; ngx_int_t rc; ngx_chain_t out; b = ngx_calloc_buf(r->pool); if (b == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, state->log, 0, "ngx_file_reader_dump_file_part: ngx_pcalloc failed (1)"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); if (b->file == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, state->log, 0, "ngx_file_reader_dump_file_part: ngx_pcalloc failed (2)"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file_pos = start; if (end != 0) { if (end > state->file_size) { ngx_log_error(NGX_LOG_ERR, state->log, ngx_errno, "ngx_file_reader_dump_file_part: end offset %O exceeds file size %O, probably a truncated file", end, state->file_size); return NGX_HTTP_NOT_FOUND; } b->file_last = end; } else { b->file_last = state->file_size; } b->in_file = b->file_last ? 1 : 0; b->last_buf = (r == r->main) ? 1 : 0; b->last_in_chain = 1; b->file->fd = state->file.fd; b->file->name = state->file.name; b->file->log = state->log; b->file->directio = state->file.directio; out.buf = b; out.next = NULL; rc = ngx_http_output_filter(r, &out); if (rc != NGX_OK && rc != NGX_AGAIN) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, state->log, 0, "ngx_file_reader_dump_file_part: ngx_http_output_filter failed %i", rc); return rc; } return NGX_OK; }
static ngx_int_t ngx_http_geoip2_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_geoip2_ctx_t *geoip2 = (ngx_http_geoip2_ctx_t *) data; ngx_http_geoip2_db_t *database = geoip2->database; int mmdb_error; MMDB_entry_data_s entry_data; ngx_http_geoip2_conf_t *gcf; ngx_addr_t addr; ngx_array_t *xfwd; u_char *p; #if (NGX_HAVE_INET6) uint8_t address[16], *addressp = address; #else unsigned long address; #endif gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip2_module); addr.sockaddr = r->connection->sockaddr; addr.socklen = r->connection->socklen; xfwd = &r->headers_in.x_forwarded_for; if (xfwd->nelts > 0 && gcf->proxies != NULL) { (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL, gcf->proxies, gcf->proxy_recursive); } switch (addr.sockaddr->sa_family) { case AF_INET: #if (NGX_HAVE_INET6) ngx_memset(addressp, 0, 12); ngx_memcpy(addressp + 12, &((struct sockaddr_in *) addr.sockaddr)->sin_addr.s_addr, 4); break; case AF_INET6: ngx_memcpy(addressp, &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr.s6_addr, 16); #else address = ((struct sockaddr_in *)addr.sockaddr)->sin_addr.s_addr; #endif break; default: goto not_found; } #if (NGX_HAVE_INET6) if (ngx_memcmp(&address, &database->address, sizeof(address)) != 0) { #else if (address != database->address) { #endif memcpy(&database->address, &address, sizeof(address)); database->result = MMDB_lookup_sockaddr(&database->mmdb, addr.sockaddr, &mmdb_error); if (mmdb_error != MMDB_SUCCESS) { goto not_found; } } if (!database->result.found_entry || MMDB_aget_value(&database->result.entry, &entry_data, geoip2->lookup) != MMDB_SUCCESS) { goto not_found; } if (!entry_data.has_data) { goto not_found; } switch (entry_data.type) { case MMDB_DATA_TYPE_UTF8_STRING: v->data = (u_char *) entry_data.utf8_string; v->len = entry_data.data_size; break; case MMDB_DATA_TYPE_UINT32: p = ngx_palloc(r->pool, NGX_OFF_T_LEN); if (p == NULL) { return NGX_ERROR; } v->len = ngx_sprintf(p, "%O", entry_data.uint32) - p; v->data = p; break; default: goto not_found; } v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; not_found: if (geoip2->default_value.len > 0) { v->data = geoip2->default_value.data; v->len = geoip2->default_value.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; } else { v->not_found = 1; } return NGX_OK; } static void * ngx_http_geoip2_create_conf(ngx_conf_t *cf) { ngx_pool_cleanup_t *cln; ngx_http_geoip2_conf_t *conf; conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip2_conf_t)); if (conf == NULL) { return NULL; } conf->proxy_recursive = NGX_CONF_UNSET; cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NULL; } cln->handler = ngx_http_geoip2_cleanup; cln->data = conf; return conf; }
/* cached session fetching callback to be set with SSL_CTX_sess_set_get_cb */ ngx_ssl_session_t * ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, int *copy) { lua_State *L; ngx_int_t rc; ngx_connection_t *c, *fc = NULL; ngx_http_request_t *r = NULL; ngx_pool_cleanup_t *cln; ngx_http_connection_t *hc; ngx_http_lua_ssl_ctx_t *cctx; ngx_http_lua_srv_conf_t *lscf; ngx_http_core_loc_conf_t *clcf; /* set copy to 0 as we expect OpenSSL to handle * the memory of returned session */ *copy = 0; c = ngx_ssl_get_connection(ssl_conn); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl session fetch: connection reusable: %ud", c->reusable); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); dd("ssl sess_fetch handler, sess_fetch-ctx=%p", cctx); if (cctx && cctx->entered_sess_fetch_handler) { /* not the first time */ dd("here: %d", (int) cctx->entered_sess_fetch_handler); if (cctx->done) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_fetch_by_lua*: " "sess get cb exit code: %d", cctx->exit_code); dd("lua ssl sess_fetch done, finally"); return cctx->session; } #ifdef SSL_ERROR_PENDING_SESSION return SSL_magic_pending_session_ptr(); #else ngx_log_error(NGX_LOG_CRIT, c->log, 0, "lua: cannot yield in sess get cb: " "missing async sess get cb support in OpenSSL"); return NULL; #endif } dd("first time"); ngx_reusable_connection(c, 0); hc = c->data; fc = ngx_http_lua_create_fake_connection(NULL); if (fc == NULL) { goto failed; } fc->log->handler = ngx_http_lua_log_ssl_sess_fetch_error; fc->log->data = fc; fc->addr_text = c->addr_text; fc->listening = c->listening; r = ngx_http_lua_create_fake_request(fc); if (r == NULL) { goto failed; } r->main_conf = hc->conf_ctx->main_conf; r->srv_conf = hc->conf_ctx->srv_conf; r->loc_conf = hc->conf_ctx->loc_conf; fc->log->file = c->log->file; fc->log->log_level = c->log->log_level; fc->ssl = c->ssl; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); #if defined(nginx_version) && nginx_version >= 1003014 # if nginx_version >= 1009000 ngx_set_connection_log(fc, clcf->error_log); # else ngx_http_set_connection_log(fc, clcf->error_log); # endif #else fc->log->file = clcf->error_log->file; if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { fc->log->log_level = clcf->error_log->log_level; } #endif if (cctx == NULL) { cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); if (cctx == NULL) { goto failed; /* error */ } } cctx->exit_code = 1; /* successful by default */ cctx->connection = c; cctx->request = r; cctx->session_id.data = id; cctx->session_id.len = len; cctx->entered_sess_fetch_handler = 1; cctx->done = 0; dd("setting cctx = %p", cctx); if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); goto failed; } lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); /* TODO honor lua_code_cache off */ L = ngx_http_lua_get_lua_vm(r, NULL); c->log->action = "fetching SSL session by lua"; rc = lscf->srv.ssl_sess_fetch_handler(r, lscf, L); if (rc >= NGX_OK || rc == NGX_ERROR) { cctx->done = 1; if (cctx->cleanup) { *cctx->cleanup = NULL; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_fetch_by_lua*: handler return value: %i, " "sess get cb exit code: %d", rc, cctx->exit_code); c->log->action = "SSL handshaking"; return cctx->session; } /* rc == NGX_DONE */ cln = ngx_pool_cleanup_add(fc->pool, 0); if (cln == NULL) { goto failed; } cln->handler = ngx_http_lua_ssl_sess_fetch_done; cln->data = cctx; if (cctx->cleanup == NULL) { /* we only want exactly one cleanup handler to be registered with the * connection to clean up cctx when connection is aborted */ cln = ngx_pool_cleanup_add(c->pool, 0); if (cln == NULL) { goto failed; } cln->data = cctx; cctx->cleanup = &cln->handler; } *cctx->cleanup = ngx_http_lua_ssl_sess_fetch_aborted; #ifdef SSL_ERROR_PENDING_SESSION return SSL_magic_pending_session_ptr(); #else ngx_log_error(NGX_LOG_CRIT, c->log, 0, "lua: cannot yield in sess get cb: " "missing async sess get cb support in OpenSSL"); /* fall through to the "failed" label below */ #endif failed: if (r && r->pool) { ngx_http_lua_free_fake_request(r); } if (fc) { ngx_http_lua_close_fake_connection(fc); } return NULL; }
/* 加载配置文件,并回调create_conf,init_conf, init_module等; 初始化各个配置,并打开监听端口,设置优化选项; */ ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) {//整个程序的主要初始化,配置加载,解析,各个模块的初始化回调函数,指令的set回调函数调用,监听端口打开,共享内存申请等等都在这里. 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();//k : ngx_cached_time tp->sec = 0;//秒设置为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也是包含在pool里面的! ,也就是,释放了cycle->pool后,cycle也释放了 cycle->log = log; cycle->new_log.log_level = NGX_LOG_ERR; cycle->old_cycle = old_cycle; //下面拷贝一下旧的配置路径什么的,参数等到新的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; } 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; //为每个模块分配一个配置上下文指针,用来保存每个模块设置的配置数据 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); //k:for core modules. 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) {//如果核心模块设置了create_conf回调,则调用它们 rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ ngx_modules[i]->index ] = rv;//帮模块们保存create_conf返回的数据。后续可以方便取到 } } senv = environ;//保留老的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) {//调用ngx_conf_parse解析全局指令,貌似是做参数准备的。 environ = senv;//还原老的environ,因为perl会改变它 ngx_destroy_cycle_pools(&conf); return NULL; } //解析配置文件,调用各个配置文件的set函数等。 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) {//这就是经典的那个-t参数啦 ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } for (i = 0; ngx_modules[i]; i++) { //刚才各个配置指令已经调用了其set函数的。下面调用一下每个模块的init_conf,也就是每个模块的各个指令已经设置,现在开始模块本身了。 if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } //对于NGX_CORE_MODULE,调用它他们的init_conf回调 module = ngx_modules[i]->ctx;//得到模块初始化设置的数据,然后调用其init_conf if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])== NGX_CONF_ERROR){ //第二个参数是在create_conf回调返回的东西 environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle;//如果是加-s reload等启动的,这里可以返回了。服务需要重启啥的,不是全新启动。在这里设置的ngx_get_options } // 最核心的配置 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);//k conf_ctx[module.index] if (ngx_test_config) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_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) {//找到"logs/error.log"的ngx_open_file_t*结构,不open打开 cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);//"logs/error.log" if (cycle->new_log.file == NULL) { goto failed; } } /* open the new files */ part = &cycle->open_files.part; file = part->elts; //一个个打开这些文件,APPEND模式打开 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; } //真正打开这些文件,append模式 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) // 这里设置为FD_CLOEXEC表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程。close-on-exec 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; } if (shm_zone[i].init == NULL) { /* unused shared zone */ continue; } 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) {//如果设置了继承SOCK,就拷贝到cycle来 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) {//如果地址完全相同,那后面就不需要关闭,直接拷贝fd就行了 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 } } //下面一个个打开cycle->listening的listen的端口,并设置为listening端口 //这些监听端口的可读事件是在ngx_event_core_module模块中设置的,其进程初始化函数为ngx_event_process_init里面会放入epoll里面 if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } if (!ngx_test_config) {//如果不是测试配置,设置一下各个优化选项,比如发送,接收缓冲区大小,TCP_DEFER_ACCEPT等 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) {//对所有模块,调用其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;//需要保留或者fd无效,不用删除,因为已经拷贝到cycle中了 } 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)) {//ngx_is_init_cycle第一次调用false //这是怎么进来的? /* * 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, "can 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) {//如果还没有设置定时器,设置定时器,30秒后清除老的cycle? 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; }
static char * ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { u_char *p; size_t size, len; ngx_str_t *value, name, s; ngx_int_t rate, scale; ngx_uint_t i; ngx_array_t *variables; ngx_shm_zone_t *shm_zone; ngx_http_limit_req_ctx_t *ctx; ngx_http_limit_req_variable_t *v; value = cf->args->elts; ctx = NULL; v = NULL; size = 0; rate = 1; scale = 1; name.len = 0; variables = ngx_array_create(cf->pool, 5, sizeof(ngx_http_limit_req_variable_t)); if (variables == NULL) { return NGX_CONF_ERROR; } for (i = 1; i < cf->args->nelts; i++) { if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { name.data = value[i].data + 5; p = (u_char *) ngx_strchr(name.data, ':'); if (p) { *p = '\0'; name.len = p - name.data; p++; s.len = value[i].data + value[i].len - p; s.data = p; size = ngx_parse_size(&s); if (size > 8191) { continue; } } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid zone size \"%V\"", &value[i]); return NGX_CONF_ERROR; } if (ngx_strncmp(value[i].data, "rate=", 5) == 0) { len = value[i].len; p = value[i].data + len - 3; if (ngx_strncmp(p, "r/s", 3) == 0) { scale = 1; len -= 3; } else if (ngx_strncmp(p, "r/m", 3) == 0) { scale = 60; len -= 3; } rate = ngx_atoi(value[i].data + 5, len - 5); if (rate <= NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid rate \"%V\"", &value[i]); return NGX_CONF_ERROR; } continue; } if (value[i].data[0] == '$') { value[i].len--; value[i].data++; v = ngx_array_push(variables); if (v == NULL) { return NGX_CONF_ERROR; } v->index = ngx_http_get_variable_index(cf, &value[i]); if (v->index == NGX_ERROR) { return NGX_CONF_ERROR; } v->var = value[i]; continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; } if (name.len == 0 || size == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%V\" must have \"zone\" parameter", &cmd->name); return NGX_CONF_ERROR; } if (variables->nelts == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no variable is defined for limit_req_zone \"%V\"", &cmd->name); return NGX_CONF_ERROR; } ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } ctx->rate = rate * 1000 / scale; ctx->limit_vars = variables; shm_zone = ngx_shared_memory_add(cf, &name, size, &ngx_http_limit_req_module); if (shm_zone == NULL) { return NGX_CONF_ERROR; } if (shm_zone->data) { ctx = shm_zone->data; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "limit_req_zone \"%V\" is already bound to variable \"%V\"", &value[1], &v->var); return NGX_CONF_ERROR; } shm_zone->init = ngx_http_limit_req_init_zone; shm_zone->data = ctx; return NGX_CONF_OK; }
static ngx_int_t ngx_http_gzip_static_handler(ngx_http_request_t *r) { u_char *p; size_t root; ngx_str_t path; ngx_int_t rc; ngx_uint_t level; ngx_log_t *log; ngx_buf_t *b; ngx_chain_t out; ngx_table_elt_t *h; ngx_open_file_info_t of; ngx_http_core_loc_conf_t *clcf; ngx_http_gzip_static_conf_t *gzcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_DECLINED; } if (r->uri.data[r->uri.len - 1] == '/') { return NGX_DECLINED; } gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module); if (!gzcf->enable) { return NGX_DECLINED; } rc = ngx_http_gzip_ok(r); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (!clcf->gzip_vary && rc != NGX_OK) { return NGX_DECLINED; } log = r->connection->log; p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".gz") - 1); if (p == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } *p++ = '.'; *p++ = 'g'; *p++ = 'z'; *p = '\0'; path.len = p - path.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http filename: \"%s\"", path.data); 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: return NGX_DECLINED; case NGX_EACCES: level = NGX_LOG_ERR; break; default: level = NGX_LOG_CRIT; break; } ngx_log_error(level, log, of.err, "%s \"%s\" failed", of.failed, path.data); return NGX_DECLINED; } r->gzip_vary = 1; if (rc != NGX_OK) { return NGX_DECLINED; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd); if (of.is_dir) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir"); return NGX_DECLINED; } #if !(NGX_WIN32) /* the not regular files are probably Unix specific */ if (!of.is_file) { ngx_log_error(NGX_LOG_CRIT, log, 0, "\"%s\" is not a regular file", path.data); return NGX_HTTP_NOT_FOUND; } #endif r->root_tested = !r->error_page; rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } log->action = "sending response to client"; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = of.size; r->headers_out.last_modified_time = of.mtime; if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return NGX_ERROR; } h->hash = 1; h->key.len = sizeof("Content-Encoding") - 1; h->key.data = (u_char *) "Content-Encoding"; h->value.len = sizeof("gzip") - 1; h->value.data = (u_char *) "gzip"; r->headers_out.content_encoding = h; r->ignore_content_encoding = 1; /* we need to allocate all before the header would be sent */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { 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; } b->file_pos = 0; b->file_last = of.size; b->in_file = b->file_last ? 1 : 0; b->last_buf = 1; b->last_in_chain = 1; b->file->fd = of.fd; b->file->name = path; b->file->log = log; b->file->directio = of.is_directio; out.buf = b; out.next = NULL; return ngx_http_output_filter(r, &out); }
void ngx_http_perl_handle_request(ngx_http_request_t *r) { SV *sub; ngx_int_t rc; ngx_str_t uri, args, *handler; ngx_http_perl_ctx_t *ctx; ngx_http_perl_loc_conf_t *plcf; ngx_http_perl_main_conf_t *pmcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t)); if (ctx == NULL) { ngx_http_finalize_request(r, NGX_ERROR); return; } ngx_http_set_ctx(r, ctx, ngx_http_perl_module); } pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); if (ctx->next == NULL) { plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module); sub = plcf->sub; handler = &plcf->handler; } else { sub = ctx->next; handler = &ngx_null_name; ctx->next = NULL; } rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sub, NULL, handler, NULL); } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler done: %i", rc); if (rc == NGX_DONE) { ngx_http_finalize_request(r, rc); return; } if (rc > 600) { rc = NGX_OK; } if (ctx->redirect_uri.len) { uri = ctx->redirect_uri; args = ctx->redirect_args; } else { uri.len = 0; } ctx->filename.data = NULL; ctx->redirect_uri.len = 0; if (ctx->done || ctx->next) { ngx_http_finalize_request(r, NGX_DONE); return; } if (uri.len) { ngx_http_internal_redirect(r, &uri, &args); ngx_http_finalize_request(r, NGX_DONE); return; } if (rc == NGX_OK || rc == NGX_HTTP_OK) { ngx_http_send_special(r, NGX_HTTP_LAST); ctx->done = 1; } ngx_http_finalize_request(r, rc); }
static char * ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void *mconf; ngx_uint_t m; ngx_conf_t pcf; ngx_stream_module_t *module; ngx_stream_conf_ctx_t *ctx, *stream_ctx; ngx_stream_core_srv_conf_t *cscf, **cscfp; ngx_stream_core_main_conf_t *cmcf; ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } stream_ctx = cf->ctx; ctx->main_conf = stream_ctx->main_conf; /* the server{}'s srv_conf */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf; } } /* the server configuration context */ cscf = ctx->srv_conf[ngx_stream_core_module.ctx_index]; cscf->ctx = ctx; cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; cscfp = ngx_array_push(&cmcf->servers); if (cscfp == NULL) { return NGX_CONF_ERROR; } *cscfp = cscf; /* parse inside server{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_STREAM_SRV_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv == NGX_CONF_OK && !cscf->listen) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"listen\" is defined for server in %s:%ui", cscf->file_name, cscf->line); return NGX_CONF_ERROR; } return rv; }
static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params) { SV *sv, **asv; ngx_int_t rc; ngx_str_t *handler, **args; ngx_uint_t i; ngx_http_perl_ctx_t *ctx; ngx_http_perl_main_conf_t *pmcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_perl_module); } pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); ctx->ssi = ssi_ctx; handler = params[NGX_HTTP_PERL_SSI_SUB]; handler->data[handler->len] = '\0'; { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); #if 0 /* the code is disabled to force the precompiled perl code using only */ ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv); if (sv == &PL_sv_undef) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "eval_pv(\"%V\") failed", handler); return NGX_ERROR; } if (sv == NULL) { sv = newSVpvn((char *) handler->data, handler->len); } #endif sv = newSVpvn((char *) handler->data, handler->len); args = ¶ms[NGX_HTTP_PERL_SSI_ARG]; if (args) { for (i = 0; args[i]; i++) { /* void */ } asv = ngx_pcalloc(r->pool, (i + 1) * sizeof(SV *)); if (asv == NULL) { SvREFCNT_dec(sv); return NGX_ERROR; } asv[0] = (SV *) i; for (i = 0; args[i]; i++) { asv[i + 1] = newSVpvn((char *) args[i]->data, args[i]->len); } } else { asv = NULL; } rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, asv, handler, NULL); SvREFCNT_dec(sv); } ctx->filename.data = NULL; ctx->redirect_uri.len = 0; ctx->ssi = NULL; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi done"); return rc; }
/** * A body filter to intercept response body and feed it to IronBee, * and to buffer the data if required by IronBee configuration. * * @param[in] r The nginx request object. * @param[in] in The data to filter. * @return status propagated from next filter, or OK/Error */ static ngx_int_t ironbee_body_out(ngx_http_request_t *r, ngx_chain_t *in) { ngxib_req_ctx *ctx; ngx_chain_t *link; ib_status_t rc; ib_num_t num; ngx_int_t rv = NGX_OK; ib_txdata_t itxdata; if (r->internal) return ngx_http_next_body_filter(r, in); ctx = ngx_http_get_module_ctx(r, ngx_ironbee_module); assert((ctx != NULL) && (ctx->tx != NULL)); ib_log_debug_tx(ctx->tx, "ironbee_body_out"); if (in == NULL) { /* FIXME: could this happen in circumstances when we should * notify IronBee of end-of-response ? */ ib_log_debug_tx(ctx->tx, "ironbee_body_out: input was null"); cleanup_return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_ironbee_module); if (ctx->output_filter_done) { ib_log_debug_tx(ctx->tx, "ironbee_body_out: already done"); cleanup_return ngx_http_next_body_filter(r, in); } if (!ctx->output_filter_init) { ctx->output_filter_init = 1; if (ctx->internal_errordoc) { /* If it's our own errordoc, pass it straight through */ /* Should we log anything here? The error will already * have been logged. */ ctx->output_buffering = IOBUF_NOBUF; ctx->response_buf = NULL; ib_log_debug_tx(ctx->tx, "ironbee_body_out: in internal errordoc"); } else { /* Determine whether we're configured to buffer */ rc = ib_context_get(ctx->tx->ctx, "buffer_res", ib_ftype_num_out(&num), NULL); ib_log_debug_tx(ctx->tx, "ironbee_body_out: buffer_res is %d", (int)num); if (rc != IB_OK) ib_log_error_tx(ctx->tx, "Can't determine output buffer configuration!"); if (num == 0) { ib_log_debug_tx(ctx->tx, "ironbee_body_out: NOBUF"); ctx->output_buffering = IOBUF_NOBUF; ctx->response_buf = NULL; } else { /* If we're buffering, initialize the buffer */ ib_log_debug_tx(ctx->tx, "ironbee_body_out: BUFFER"); ctx->output_buffering = IOBUF_BUFFER; } } } ngx_regex_malloc_init(r->pool); for (link = in; link != NULL; link = link->next) { /* Feed the data to ironbee */ itxdata.data = link->buf->pos; itxdata.dlen = link->buf->last - link->buf->pos; ib_log_debug_tx(ctx->tx, "ironbee_body_out: %d bytes", (int)itxdata.dlen); if (itxdata.dlen > 0) { ib_state_notify_response_body_data(ctx->tx->ib, ctx->tx, &itxdata); } /* If IronBee just signaled an error, switch to discard data mode, * and dump anything we already have buffered, */ if ( (STATUS_IS_ERROR(ctx->status)) && !ctx->internal_errordoc && (ctx->output_buffering != IOBUF_DISCARD) ) { ib_log_debug_tx(ctx->tx, "ironbee_body_out: error %d", ctx->status); free_chain(r->pool, ctx->response_buf); ctx->response_buf = NULL; ctx->output_buffering = IOBUF_DISCARD; } else if (ctx->output_buffering == IOBUF_BUFFER) { /* Copy any data to our buffer */ if (ctx->response_buf == NULL) { ctx->response_buf = ngx_pcalloc(r->pool, sizeof(ngx_chain_t)); ctx->response_ptr = ctx->response_buf; } else { ctx->response_ptr->next = ngx_pcalloc(r->pool, sizeof(ngx_chain_t)); ctx->response_ptr = ctx->response_ptr->next; } /* Not sure if any data types need setaside, but let's be safe */ #if NO_COPY_REQUIRED ctx->response_ptr->buf = link->buf; #else if (itxdata.dlen > 0) { ctx->response_ptr->buf = ngx_create_temp_buf(r->pool, itxdata.dlen); memcpy(ctx->response_ptr->buf->pos, link->buf->pos, itxdata.dlen); ctx->response_ptr->buf->last += itxdata.dlen; } else { ctx->response_ptr->buf = ngx_palloc(r->pool, sizeof(ngx_buf_t)); memcpy(ctx->response_ptr->buf, link->buf, sizeof(ngx_buf_t)); } #endif } if (link->buf->last_buf) { ib_log_debug_tx(ctx->tx, "ironbee_body_out: last_buf"); ctx->output_filter_done = 1; } } if (ctx->output_buffering == IOBUF_NOBUF) { /* Normal operation - pass it down the chain */ ib_log_debug_tx(ctx->tx, "ironbee_body_out: passing on"); ctx->start_response = 1; rv = ngx_http_next_body_filter(r, in); } else if (ctx->output_buffering == IOBUF_BUFFER) { ib_log_debug_tx(ctx->tx, "ironbee_body_out: buffering"); if (ctx->output_filter_done) { /* We can pass on the buffered data all at once */ ib_log_debug_tx(ctx->tx, "ironbee_body_out: passing buffer"); ctx->start_response = 1; rv = ngx_http_next_body_filter(r, ctx->response_buf); } } else if (ctx->output_buffering == IOBUF_DISCARD) { ib_log_debug_tx(ctx->tx, "ironbee_body_out: discarding"); if (ctx->output_filter_done) { /* Pass a last bucket with no data */ //ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, // "ironbee_body_out: passing NULL last-buffer"); //ctx->response_buf = ngx_pcalloc(r->pool, sizeof(ngx_chain_t)); //ctx->response_buf->buf = ngx_calloc_buf(r->pool); //ctx->response_buf->buf->last_buf = ctx->response_buf->buf->last_in_chain = 1; //rv = ngx_http_next_body_filter(r, ctx->response_buf); /* FIXME: Is setting rv enough to serve error page */ rv = ctx->status; } } if (ctx->output_filter_done) { ib_log_debug_tx(ctx->tx, "ironbee_body_out: notify_postprocess"); rc = ib_state_notify_postprocess(ctx->tx->ib, ctx->tx); if ((rv == NGX_OK) && (rc != IB_OK)) { rv = NGX_HTTP_INTERNAL_SERVER_ERROR; } rc = ib_state_notify_logging(ctx->tx->ib, ctx->tx); if ((rv == NGX_OK) && (rc != IB_OK)) { rv = NGX_HTTP_INTERNAL_SERVER_ERROR; } } cleanup_return rv; }
char * ngx_http_lua_shared_dict(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_lua_main_conf_t *lmcf = conf; ngx_str_t *value, name; ngx_shm_zone_t *zone; ngx_shm_zone_t **zp; ngx_http_lua_shdict_ctx_t *ctx; ssize_t size; if (lmcf->shdict_zones == NULL) { lmcf->shdict_zones = ngx_palloc(cf->pool, sizeof(ngx_array_t)); if (lmcf->shdict_zones == NULL) { return NGX_CONF_ERROR; } if (ngx_array_init(lmcf->shdict_zones, cf->pool, 2, sizeof(ngx_shm_zone_t *)) != NGX_OK) { return NGX_CONF_ERROR; } } value = cf->args->elts; ctx = NULL; if (value[1].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid lua shared dict name \"%V\"", &value[1]); return NGX_CONF_ERROR; } name = value[1]; size = ngx_parse_size(&value[2]); if (size <= 8191) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid lua shared dict size \"%V\"", &value[2]); return NGX_CONF_ERROR; } ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_lua_shdict_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } ctx->name = name; ctx->main_conf = lmcf; ctx->log = &cf->cycle->new_log; zone = ngx_http_lua_shared_memory_add(cf, &name, (size_t) size, &ngx_http_lua_module); if (zone == NULL) { return NGX_CONF_ERROR; } if (zone->data) { ctx = zone->data; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "lua_shared_dict \"%V\" is already defined as " "\"%V\"", &name, &ctx->name); return NGX_CONF_ERROR; } zone->init = ngx_http_lua_shdict_init_zone; zone->data = ctx; zp = ngx_array_push(lmcf->shdict_zones); if (zp == NULL) { return NGX_CONF_ERROR; } *zp = zone; lmcf->requires_shm = 1; return NGX_CONF_OK; }
void * passenger_create_loc_conf(ngx_conf_t *cf) { passenger_loc_conf_t *conf; conf = ngx_pcalloc(cf->pool, sizeof(passenger_loc_conf_t)); if (conf == NULL) { return NGX_CONF_ERROR; } /* * set by ngx_pcalloc(): * * conf->upstream_config.bufs.num = 0; * conf->upstream_config.next_upstream = 0; * conf->upstream_config.temp_path = NULL; * conf->upstream_config.hide_headers_hash = { NULL, 0 }; * conf->upstream_config.hide_headers = NULL; * conf->upstream_config.pass_headers = NULL; * conf->upstream_config.uri = { 0, NULL }; * conf->upstream_config.location = NULL; * conf->upstream_config.store_lengths = NULL; * conf->upstream_config.store_values = NULL; */ generated_set_conf_part(conf); /******************************/ /******************************/ conf->upstream_config.pass_headers = NGX_CONF_UNSET_PTR; conf->upstream_config.hide_headers = NGX_CONF_UNSET_PTR; conf->upstream_config.store = NGX_CONF_UNSET; conf->upstream_config.store_access = NGX_CONF_UNSET_UINT; #if NGINX_VERSION_NUM >= 1007005 conf->upstream_config.next_upstream_tries = NGX_CONF_UNSET_UINT; #endif conf->upstream_config.buffering = NGX_CONF_UNSET; conf->upstream_config.ignore_client_abort = NGX_CONF_UNSET; #if NGINX_VERSION_NUM >= 1007007 conf->upstream_config.force_ranges = NGX_CONF_UNSET; #endif conf->upstream_config.local = NGX_CONF_UNSET_PTR; conf->upstream_config.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream_config.send_timeout = NGX_CONF_UNSET_MSEC; conf->upstream_config.read_timeout = NGX_CONF_UNSET_MSEC; #if NGINX_VERSION_NUM >= 1007005 conf->upstream_config.next_upstream_timeout = NGX_CONF_UNSET_MSEC; #endif conf->upstream_config.send_lowat = NGX_CONF_UNSET_SIZE; conf->upstream_config.buffer_size = NGX_CONF_UNSET_SIZE; #if NGINX_VERSION_NUM >= 1007007 conf->upstream_config.limit_rate = NGX_CONF_UNSET_SIZE; #endif conf->upstream_config.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; conf->upstream_config.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; conf->upstream_config.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; conf->upstream_config.pass_request_headers = NGX_CONF_UNSET; conf->upstream_config.pass_request_body = NGX_CONF_UNSET; #if (NGX_HTTP_CACHE) #if NGINX_VERSION_NUM >= 1007009 conf->upstream_config.cache = NGX_CONF_UNSET; #else conf->upstream_config.cache = NGX_CONF_UNSET_PTR; #endif conf->upstream_config.cache_min_uses = NGX_CONF_UNSET_UINT; conf->upstream_config.cache_bypass = NGX_CONF_UNSET_PTR; conf->upstream_config.no_cache = NGX_CONF_UNSET_PTR; conf->upstream_config.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream_config.cache_lock = NGX_CONF_UNSET; conf->upstream_config.cache_lock_timeout = NGX_CONF_UNSET_MSEC; #if NGINX_VERSION_NUM >= 1007008 conf->upstream_config.cache_lock_age = NGX_CONF_UNSET_MSEC; #endif #if NGINX_VERSION_NUM >= 1006000 conf->upstream_config.cache_revalidate = NGX_CONF_UNSET; #endif #endif conf->upstream_config.intercept_errors = NGX_CONF_UNSET; conf->upstream_config.cyclic_temp_file = 0; conf->upstream_config.change_buffering = 1; ngx_str_set(&conf->upstream_config.module, "passenger"); conf->options_cache.data = NULL; conf->options_cache.len = 0; conf->env_vars_cache.data = NULL; conf->env_vars_cache.len = 0; return conf; }
static ngx_int_t ngx_rtmp_auto_push_init_process(ngx_cycle_t *cycle) { #if (NGX_HAVE_UNIX_DOMAIN) ngx_rtmp_auto_push_conf_t *apcf; ngx_listening_t *ls, *lss; struct sockaddr_un *sun; int reuseaddr; ngx_socket_t s; size_t n; ngx_file_info_t fi; if (ngx_process != NGX_PROCESS_WORKER) { return NGX_OK; } apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_rtmp_auto_push_module); if (apcf->auto_push == 0) { return NGX_OK; } next_publish = ngx_rtmp_publish; ngx_rtmp_publish = ngx_rtmp_auto_push_publish; next_delete_stream = ngx_rtmp_delete_stream; ngx_rtmp_delete_stream = ngx_rtmp_auto_push_delete_stream; reuseaddr = 1; s = (ngx_socket_t) -1; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, cycle->log, 0, "auto_push: creating sockets"); /*TODO: clone all RTMP listenings? */ ls = cycle->listening.elts; lss = NULL; for (n = 0; n < cycle->listening.nelts; ++n, ++ls) { if (ls->handler == ngx_rtmp_init_connection) { lss = ls; break; } } if (lss == NULL) { return NGX_OK; } ls = ngx_array_push(&cycle->listening); if (ls == NULL) { return NGX_ERROR; } *ls = *lss; /* Disable unix socket client address extraction * from accept call * Nginx generates bad addr_text with this enabled */ ls->addr_ntop = 0; ls->socklen = sizeof(struct sockaddr_un); sun = ngx_pcalloc(cycle->pool, ls->socklen); ls->sockaddr = (struct sockaddr *) sun; if (ls->sockaddr == NULL) { return NGX_ERROR; } sun->sun_family = AF_UNIX; *ngx_snprintf((u_char *) sun->sun_path, sizeof(sun->sun_path), "%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i", &apcf->socket_dir, ngx_process_slot) = 0; ngx_log_debug1(NGX_LOG_DEBUG_RTMP, cycle->log, 0, "auto_push: create socket '%s'", sun->sun_path); if (ngx_file_info(sun->sun_path, &fi) != ENOENT) { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, cycle->log, 0, "auto_push: delete existing socket '%s'", sun->sun_path); ngx_delete_file(sun->sun_path); } ngx_str_set(&ls->addr_text, "worker_socket"); s = ngx_socket(AF_UNIX, SOCK_STREAM, 0); if (s == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_socket_n " worker_socket failed"); return NGX_ERROR; } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuseaddr, sizeof(int)) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, "setsockopt(SO_REUSEADDR) worker_socket failed"); goto sock_error; } if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) { if (ngx_nonblocking(s) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_nonblocking_n " worker_socket failed"); return NGX_ERROR; } } if (bind(s, (struct sockaddr *) sun, sizeof(*sun)) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_nonblocking_n " worker_socket bind failed"); goto sock_error; } if (listen(s, NGX_LISTEN_BACKLOG) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, "listen() to worker_socket, backlog %d failed", NGX_LISTEN_BACKLOG); goto sock_error; } ls->fd = s; ls->listen = 1; return NGX_OK; sock_error: if (s != (ngx_socket_t) -1 && ngx_close_socket(s) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " worker_socket failed"); } ngx_delete_file(sun->sun_path); return NGX_ERROR; #else /* NGX_HAVE_UNIX_DOMAIN */ return NGX_OK; #endif /* NGX_HAVE_UNIX_DOMAIN */ }