static ngx_int_t create_request(ngx_http_request_t *r) { u_char ch; u_char buf[sizeof("4294967296")]; size_t len, size, key_len, val_len, content_length; const u_char *app_type_string; size_t app_type_string_len; u_char framework_spawner_idle_time_string[12]; u_char app_spawner_idle_time_string[12]; u_char *end; ngx_uint_t i, n; ngx_buf_t *b; ngx_chain_t *cl, *body; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_http_script_code_pt code; ngx_http_script_engine_t e, le; passenger_loc_conf_t *slcf; passenger_main_conf_t *main_conf; passenger_context_t *context; ngx_http_script_len_code_pt lcode; #if (NGX_HTTP_SSL) ngx_http_ssl_srv_conf_t *ssl_conf; #endif slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module); main_conf = &passenger_main_conf; context = ngx_http_get_module_ctx(r, ngx_http_passenger_module); if (context == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } switch (context->app_type) { case AP_RAILS: app_type_string = (const u_char *) "rails"; app_type_string_len = sizeof("rails"); break; case AP_RACK: app_type_string = (const u_char *) "rack"; app_type_string_len = sizeof("rack"); break; case AP_WSGI: app_type_string = (const u_char *) "wsgi"; app_type_string_len = sizeof("wsgi"); break; default: app_type_string = (const u_char *) "rails"; app_type_string_len = sizeof("rails"); break; } /************************************************** * Determine the request header length. **************************************************/ /* Length of the Content-Length header. */ if (r->headers_in.content_length_n < 0) { content_length = 0; } else { content_length = r->headers_in.content_length_n; } uint_to_str(content_length, buf, sizeof(buf)); /* +1 for trailing null */ len = sizeof("CONTENT_LENGTH") + ngx_strlen(buf) + 1; /* DOCUMENT_ROOT, SCRIPT_NAME and base URI */ len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1; if (context->base_uri.len > 0) { len += sizeof("SCRIPT_NAME") + context->base_uri.len + 1; len += sizeof("RAILS_RELATIVE_URL_ROOT") + context->base_uri.len + 1; } else { len += sizeof("SCRIPT_NAME") + sizeof(""); } /* Various other HTTP headers. */ if (r->headers_in.content_type != NULL && r->headers_in.content_type->value.len > 0) { len += sizeof("CONTENT_TYPE") + r->headers_in.content_type->value.len + 1; } #if (NGX_HTTP_SSL) ssl_conf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (ssl_conf->enable) { len += sizeof("HTTPS") + sizeof("on"); } #endif /* Lengths of Passenger application pool options. */ if (slcf->use_global_queue) { len += sizeof("PASSENGER_USE_GLOBAL_QUEUE") + sizeof("true"); } else { len += sizeof("PASSENGER_USE_GLOBAL_QUEUE") + sizeof("false"); } len += sizeof("PASSENGER_ENVIRONMENT") + slcf->environment.len + 1; len += sizeof("PASSENGER_SPAWN_METHOD") + slcf->spawn_method.len + 1; len += sizeof("PASSENGER_APP_TYPE") + app_type_string_len; end = ngx_snprintf(framework_spawner_idle_time_string, sizeof(framework_spawner_idle_time_string) - 1, "%d", slcf->framework_spawner_idle_time); *end = '\0'; len += sizeof("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME") + ngx_strlen(framework_spawner_idle_time_string) + 1; end = ngx_snprintf(app_spawner_idle_time_string, sizeof(app_spawner_idle_time_string) - 1, "%d", slcf->app_spawner_idle_time); *end = '\0'; len += sizeof("PASSENGER_APP_SPAWNER_IDLE_TIME") + ngx_strlen(app_spawner_idle_time_string) + 1; /* Lengths of various CGI variables. */ if (slcf->vars_len) { ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); ngx_http_script_flush_no_cacheable_variables(r, slcf->flushes); le.flushed = 1; le.ip = slcf->vars_len->elts; le.request = r; while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; key_len = lcode(&le); for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; } le.ip += sizeof(uintptr_t); len += key_len + val_len; } } /* Lengths of HTTP headers. */ if (slcf->upstream.pass_request_headers) { part = &r->headers_in.headers.part; header = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } len += sizeof("HTTP_") - 1 + header[i].key.len + 1 + header[i].value.len + 1; } } /* Trailing dummy header. * * If the last header value is an empty string, then the buffer * will end with "\0\0". For example, if 'SSL_CLIENT_CERT' * is the last header and it has an empty value, then the SCGI header * will end with: * * "SSL_CLIENT_CERT\0\0" * * The data in the buffer will be processed by the AbstractRequestHandler class, * which is implemented in Ruby. But it uses Hash[*data.split("\0")] to * unserialize the data. Unfortunately String#split will not transform * the trailing "\0\0" into an empty string: * * "SSL_CLIENT_CERT\0\0".split("\0") * # => desired result: ["SSL_CLIENT_CERT", ""] * # => actual result: ["SSL_CLIENT_CERT"] * * When that happens, Hash[..] will raise an ArgumentError because * data.split("\0") does not return an array with a length that is a * multiple of 2. * * So here, we add a dummy header to prevent situations like that from * happening. */ len += sizeof("_") + sizeof("_"); /************************************************** * Build the request header data. **************************************************/ size = passenger_helper_server_password.len + /* netstring length + ":" + trailing "," */ /* note: 10 == sizeof("4294967296") - 1 */ len + 10 + 1 + 1; b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; /* Build SCGI header netstring length part. */ b->last = ngx_copy(b->last, passenger_helper_server_password.data, passenger_helper_server_password.len); b->last = ngx_snprintf(b->last, 10, "%ui", len); *b->last++ = (u_char) ':'; /* Build CONTENT_LENGTH header. This must always be sent, even if 0. */ b->last = ngx_copy(b->last, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")); b->last = ngx_snprintf(b->last, 10, "%ui", content_length); *b->last++ = (u_char) 0; /* Build DOCUMENT_ROOT, SCRIPT_NAME and base URI. */ b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")); b->last = ngx_copy(b->last, context->public_dir.data, context->public_dir.len + 1); if (context->base_uri.len > 0) { b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME")); b->last = ngx_copy(b->last, context->base_uri.data, context->base_uri.len + 1); b->last = ngx_copy(b->last, "RAILS_RELATIVE_URL_ROOT", sizeof("RAILS_RELATIVE_URL_ROOT")); b->last = ngx_copy(b->last, context->base_uri.data, context->base_uri.len + 1); } else { b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME")); b->last = ngx_copy(b->last, "", sizeof("")); } /* Various other HTTP headers. */ if (r->headers_in.content_type != NULL && r->headers_in.content_type->value.len > 0) { b->last = ngx_copy(b->last, "CONTENT_TYPE", sizeof("CONTENT_TYPE")); b->last = ngx_copy(b->last, r->headers_in.content_type->value.data, r->headers_in.content_type->value.len + 1); } #if (NGX_HTTP_SSL) ssl_conf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (ssl_conf->enable) { b->last = ngx_copy(b->last, "HTTPS", sizeof("HTTPS")); b->last = ngx_copy(b->last, "on", sizeof("on")); } #endif /* Build Passenger application pool option headers. */ b->last = ngx_copy(b->last, "PASSENGER_USE_GLOBAL_QUEUE", sizeof("PASSENGER_USE_GLOBAL_QUEUE")); if (slcf->use_global_queue) { b->last = ngx_copy(b->last, "true", sizeof("true")); } else { b->last = ngx_copy(b->last, "false", sizeof("false")); } b->last = ngx_copy(b->last, "PASSENGER_ENVIRONMENT", sizeof("PASSENGER_ENVIRONMENT")); b->last = ngx_copy(b->last, slcf->environment.data, slcf->environment.len + 1); b->last = ngx_copy(b->last, "PASSENGER_SPAWN_METHOD", sizeof("PASSENGER_SPAWN_METHOD")); b->last = ngx_copy(b->last, slcf->spawn_method.data, slcf->spawn_method.len + 1); b->last = ngx_copy(b->last, "PASSENGER_APP_TYPE", sizeof("PASSENGER_APP_TYPE")); b->last = ngx_copy(b->last, app_type_string, app_type_string_len); b->last = ngx_copy(b->last, "PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME", sizeof("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME")); b->last = ngx_copy(b->last, framework_spawner_idle_time_string, ngx_strlen(framework_spawner_idle_time_string) + 1); b->last = ngx_copy(b->last, "PASSENGER_APP_SPAWNER_IDLE_TIME", sizeof("PASSENGER_APP_SPAWNER_IDLE_TIME")); b->last = ngx_copy(b->last, app_spawner_idle_time_string, ngx_strlen(app_spawner_idle_time_string) + 1); if (slcf->vars_len) { ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); e.ip = slcf->vars->elts; e.pos = b->last; e.request = r; e.flushed = 1; le.ip = slcf->vars_len->elts; while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; (void) lcode(&le); for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; } le.ip += sizeof(uintptr_t); while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; code((ngx_http_script_engine_t *) &e); } e.ip += sizeof(uintptr_t); } b->last = e.pos; } if (slcf->upstream.pass_request_headers) { part = &r->headers_in.headers.part; header = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1); for (n = 0; n < header[i].key.len; n++) { ch = header[i].key.data[n]; if (ch >= 'a' && ch <= 'z') { ch &= ~0x20; } else if (ch == '-') { ch = '_'; } *b->last++ = ch; } *b->last++ = (u_char) 0; b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); *b->last++ = (u_char) 0; } } /* Trailing dummy header. See earlier comment for explanation. */ b->last = ngx_copy(b->last, "_\0_", sizeof("_\0_")); *b->last++ = (u_char) ','; if (slcf->upstream.pass_request_body) { body = r->upstream->request_bufs; r->upstream->request_bufs = cl; while (body) { b = ngx_alloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } ngx_memcpy(b, body->buf, sizeof(ngx_buf_t)); cl->next = ngx_alloc_chain_link(r->pool); if (cl->next == NULL) { return NGX_ERROR; } cl = cl->next; cl->buf = b; body = body->next; } b->flush = 1; } else { r->upstream->request_bufs = cl; } cl->next = NULL; return NGX_OK; }
static ngx_int_t process_header(ngx_http_request_t *r) { ngx_str_t *status_line; ngx_int_t rc, status; ngx_table_elt_t *h; ngx_http_upstream_t *u; ngx_http_upstream_header_t *hh; ngx_http_upstream_main_conf_t *umcf; ngx_http_core_loc_conf_t *clcf; passenger_loc_conf_t *slcf; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module); for ( ;; ) { rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1); if (rc == NGX_OK) { /* a header line has been parsed successfully */ h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_ERROR; } h->hash = r->header_hash; h->key.len = r->header_name_end - r->header_name_start; h->value.len = r->header_end - r->header_start; h->key.data = ngx_pnalloc(r->pool, h->key.len + 1 + h->value.len + 1 + h->key.len); if (h->key.data == NULL) { return NGX_ERROR; } h->value.data = h->key.data + h->key.len + 1; h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; ngx_memcpy(h->key.data, r->header_name_start, h->key.len); h->key.data[h->key.len] = '\0'; ngx_memcpy(h->value.data, r->header_start, h->value.len); h->value.data[h->value.len] = '\0'; if (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); } else { ngx_strlow(h->lowcase_key, h->key.data, h->key.len); } hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { return NGX_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http scgi header: \"%V: %V\"", &h->key, &h->value); continue; } if (rc == NGX_HTTP_PARSE_HEADER_DONE) { /* a whole header has been parsed successfully */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http scgi header done"); /* * if no "Server" and "Date" in header line, * then add the default headers */ if (r->upstream->headers_in.server == NULL) { h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash( ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r'); h->key.len = sizeof("Server") - 1; h->key.data = (u_char *) "Server"; if( slcf->show_version_in_header == 0 ) { if (clcf->server_tokens) { h->value.data = (u_char *) (NGINX_VER " + Phusion Passenger"); } else { h->value.data = (u_char *) ("nginx + Phusion Passenger"); } } else { if (clcf->server_tokens) { h->value.data = (u_char *) (NGINX_VER " + Phusion Passenger " PASSENGER_VERSION); } else { h->value.data = (u_char *) ("nginx + Phusion Passenger " PASSENGER_VERSION); } } h->value.len = ngx_strlen(h->value.data); h->lowcase_key = (u_char *) "server"; } if (r->upstream->headers_in.date == NULL) { h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e'); h->key.len = sizeof("Date") - 1; h->key.data = (u_char *) "Date"; h->value.len = 0; h->value.data = NULL; h->lowcase_key = (u_char *) "date"; } /* Process "Status" header. */ u = r->upstream; if (u->headers_in.status_n) { goto done; } if (u->headers_in.status) { status_line = &u->headers_in.status->value; status = ngx_atoi(status_line->data, 3); if (status == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent invalid status \"%V\"", status_line); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } u->headers_in.status_n = status; u->headers_in.status_line = *status_line; } else if (u->headers_in.location) { u->headers_in.status_n = 302; ngx_str_set(&u->headers_in.status_line, "302 Moved Temporarily"); } else { u->headers_in.status_n = 200; ngx_str_set(&u->headers_in.status_line, "200 OK"); } if (u->state) { u->state->status = u->headers_in.status_n; } done: /* Supported since Nginx 1.3.15. */ #ifdef NGX_HTTP_SWITCHING_PROTOCOLS if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS && r->headers_in.upgrade) { u->upgrade = 1; } #endif return NGX_OK; } if (rc == NGX_AGAIN) { return NGX_AGAIN; } /* there was error while a header line parsing */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent invalid header"); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } }
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 (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } 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); if (ngx_cycle_modules(cycle) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } for (i = 0; cycle->modules[i]; i++) { if (cycle->modules[i]->type != NGX_CORE_MODULE) { continue; } module = cycle->modules[i]->ctx; if (module->create_conf) { rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[cycle->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; cycle->modules[i]; i++) { if (cycle->modules[i]->type != NGX_CORE_MODULE) { continue; } module = cycle->modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[cycle->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].noreuse) { shm_zone[i].shm.addr = oshm_zone[n].shm.addr; #if (NGX_WIN32) shm_zone[i].shm.handle = oshm_zone[n].shm.handle; #endif 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 (ls[i].remain) { continue; } if (ls[i].type != nls[n].type) { continue; } if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) == NGX_OK) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; ls[i].remain = 1; if (ls[i].backlog != nls[n].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[i].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 #if (NGX_HAVE_REUSEPORT) if (nls[n].reuseport && !ls[i].reuseport) { nls[n].add_reuseport = 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; if (ngx_init_modules(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; }
void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n, sigio; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; //屏蔽一系列信号,防止被打扰 sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); size = sizeof(master_process); for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } title = ngx_pnalloc(cycle->pool, size); p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } ngx_setproctitle(title); //master进程获取core模块配置,ccf中有要创建多少个worker的设定 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); //启动worker,这时已经有了worker进程 ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); //创建有关cache的子进程 ngx_new_binary = 0; delay = 0; sigio = 0; live = 1; for ( ;; ) { //delay用来等待子进程退出的时间,由于我们接受到SIGINT信号后,我们需要先发送信号给子进程, //而子进程的退出需要一定的时间,超时时如果子进程已退出,我们父进程就直接退出, //否则发送sigkill信号给子进程(强制退出),然后再退出。 if (delay) { if (ngx_sigalrm) { sigio = 0; delay *= 2; ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; //设置定时器 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); //延时,等待信号 sigsuspend(&set); //调用这个将master进程挂起来 ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); //ngx_reap为1,说明有子进程已经退出 if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); //这个里面处理退出的子进程(有的worker异常退出,这时我们就需要重启这个worker ),如果所有子进程都退出则会返回0. live = ngx_reap_children(cycle); } //如果没有存活的子进程,并且收到了ngx_terminate或者ngx_quit信号,则master退出。 if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } //收到了sigint信号 if (ngx_terminate) { //设置延时 if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; if (delay > 1000) { //如果超时,则强制杀死worker ngx_signal_worker_processes(cycle, SIGKILL); } else { //负责发送sigint给worker,让它退出 ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } //收到quit信号 if (ngx_quit) { //发送给worker quit信号 ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } //收到需要reconfig的信号 if (ngx_reconfigure) { ngx_reconfigure = 0; //判断是否热代码替换后的新的代码还在运行中(也就是还没退出当前的master)。如果还在运行中,则不需要重新初始化config if (ngx_new_binary) { ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); //重新初始化config,并重新启动新的worker cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); live = 1; } //重新打开 if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } //热代码替换 if (ngx_change_binary) { ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); //进行热代码替换,这里是调用execve来执行新的代码 ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } //接受到停止accept连接,其实也就是worker退出(有区别的是,这里master不需要退出) if (ngx_noaccept) { ngx_noaccept = 0; ngx_noaccepting = 1; //给worker发送信号 ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } }
static ngx_int_t ngx_rtmp_play_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) { ngx_rtmp_play_main_conf_t *pmcf; ngx_rtmp_play_app_conf_t *pacf; ngx_rtmp_play_ctx_t *ctx; u_char *p; ngx_rtmp_play_fmt_t *fmt, **pfmt; ngx_str_t *pfx, *sfx; ngx_str_t name; ngx_uint_t n; pmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_play_module); pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module); if (pacf == NULL || pacf->entries.nelts == 0) { goto next; } ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "play: play name='%s' timestamp=%i", v->name, (ngx_int_t) v->start); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx && ctx->file.fd != NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: already playing"); goto next; } /* check for double-dot in v->name; * we should not move out of play directory */ for (p = v->name; *p; ++p) { if (ngx_path_separator(p[0]) && p[1] == '.' && p[2] == '.' && ngx_path_separator(p[3])) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: bad name '%s'", v->name); return NGX_ERROR; } } if (ctx == NULL) { ctx = ngx_palloc(s->connection->pool, sizeof(ngx_rtmp_play_ctx_t)); ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_play_module); } ngx_memzero(ctx, sizeof(*ctx)); ctx->session = s; ctx->aindex = ngx_rtmp_play_parse_index('a', v->args); ctx->vindex = ngx_rtmp_play_parse_index('v', v->args); ctx->file.log = s->connection->log; ngx_memcpy(ctx->name, v->name, NGX_RTMP_MAX_NAME); name.len = ngx_strlen(v->name); name.data = v->name; pfmt = pmcf->fmts.elts; for (n = 0; n < pmcf->fmts.nelts; ++n, ++pfmt) { fmt = *pfmt; pfx = &fmt->pfx; sfx = &fmt->sfx; if (pfx->len == 0 && ctx->fmt == NULL) { ctx->fmt = fmt; } if (pfx->len && name.len >= pfx->len && ngx_strncasecmp(pfx->data, name.data, pfx->len) == 0) { ctx->pfx_size = pfx->len; ctx->fmt = fmt; break; } if (name.len >= sfx->len && ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len, sfx->len) == 0) { ctx->fmt = fmt; } } if (ctx->fmt == NULL) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: fmt not found"); goto next; } ctx->file.fd = NGX_INVALID_FILE; ctx->nentry = NGX_CONF_UNSET_UINT; ctx->post_seek = NGX_CONF_UNSET_UINT; sfx = &ctx->fmt->sfx; if (name.len < sfx->len || ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len, sfx->len)) { ctx->sfx = *sfx; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: fmt=%V", &ctx->fmt->name); return ngx_rtmp_play_next_entry(s, v); next: return next_play(s, v); }
void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n, sigio; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); size = sizeof(master_process); for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } title = ngx_pnalloc(cycle->pool, size); p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } ngx_setproctitle(title); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_start_session_manager_processes(cycle, 0); ngx_start_ip_blacklist_manager_processes(cycle, 0); ngx_new_binary = 0; delay = 0; sigio = 0; live = 1; for ( ;; ) { if (delay) { if (ngx_sigalrm) { sigio = 0; delay *= 2; ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); sigsuspend(&set); ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); live = ngx_reap_children(cycle); } if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } if (ngx_terminate) { if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; if (delay > 1000) { ngx_signal_worker_processes(cycle, SIGKILL); } else { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } if (ngx_quit) { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } if (ngx_reconfigure) { ngx_reconfigure = 0; if (ngx_new_binary) { ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_start_session_manager_processes(cycle, 0); ngx_start_ip_blacklist_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); ngx_start_session_manager_processes(cycle, 1); ngx_start_ip_blacklist_manager_processes(cycle, 1); /* allow new processes to start */ ngx_msleep(100); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_start_session_manager_processes(cycle, 0); ngx_start_ip_blacklist_manager_processes(cycle, 0); live = 1; } if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } if (ngx_change_binary) { ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } if (ngx_noaccept) { ngx_noaccept = 0; ngx_noaccepting = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } }
static ngx_chain_t * ngx_rtmp_record_notify_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool) { ngx_rtmp_record_app_conf_t *racf; ngx_rtmp_record_ctx_t *ctx; ngx_chain_t *hl, *cl, *pl; ngx_buf_t *b; ngx_str_t *addr_text; size_t path_len, name_len, args_len; u_char *path; racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); if (ctx == NULL) { return NULL; } /* common variables */ cl = ngx_rtmp_netcall_http_format_session(s, pool); if (cl == NULL) { return NULL; } /* publish variables */ pl = ngx_alloc_chain_link(pool); if (pl == NULL) { return NULL; } path = ngx_rtmp_record_make_path(s); path_len = ngx_strlen(path); name_len = ngx_strlen(ctx->name); args_len = ngx_strlen(ctx->args); addr_text = &s->connection->addr_text; b = ngx_create_temp_buf(pool, sizeof("&call=record_done") + sizeof("&addr=") + addr_text->len + sizeof("&name=") + name_len * 3 + sizeof("&path=") + path_len * 3 + + 1 + args_len); if (b == NULL) { return NULL; } pl->buf = b; b->last = ngx_cpymem(b->last, (u_char*)"&call=record_done", sizeof("&call=record_done") - 1); b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1); b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data, addr_text->len, 0); b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1); b->last = (u_char*)ngx_escape_uri(b->last, ctx->name, name_len, 0); b->last = ngx_cpymem(b->last, (u_char*)"&path=", sizeof("&path=") - 1); b->last = (u_char*)ngx_escape_uri(b->last, path, path_len, 0); if (args_len) { *b->last++ = '&'; b->last = (u_char *)ngx_cpymem(b->last, ctx->args, args_len); } /* HTTP header */ hl = ngx_rtmp_netcall_http_format_header(racf->url, pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos), &ngx_rtmp_netcall_content_type_urlencoded); if (hl == NULL) { return NULL; } hl->next = cl; cl->next = pl; pl->next = NULL; return hl; }
ngx_int_t ngx_stream_upm_parse_resp_body(ngx_stream_session_t *s) { int port, fail_timeout, max_fail, weight, ta[1024]; char *upname, *host, *t; cJSON *jsroot, *service, *jinsts, *jinst, *tags; ngx_buf_t *b; ngx_uint_t i, j, p, st, sfound, ifound; ngx_conf_t cf; //ngx_pool_t *pool; ngx_array_t *servs, *upstreams; ngx_connection_t *pc; ngx_stream_upstream_t *u; ngx_stream_upm_ctx_t *ctx; ngx_stream_upm_service_t *ums; ngx_stream_upm_main_conf_t *ummcf; ngx_stream_upm_service_inst_t *umsi; ngx_stream_upstream_init_pt init; ngx_stream_upstream_server_t *us; ngx_stream_upstream_srv_conf_t *uscf; ngx_stream_upstream_main_conf_t *umcf; ctx = ngx_stream_get_module_ctx(s, ngx_stream_upm_module); ummcf = ngx_stream_get_module_srv_conf(s, ngx_stream_upm_module); umcf = ngx_stream_get_module_main_conf(s, ngx_stream_upstream_module); upstreams = &umcf->upstreams; b = ctx->resp_body; u = s->upstream; pc = u->peer.connection; /* start to parse the JSON body; */ jsroot = cJSON_Parse((char *)b->start); if (jsroot == NULL) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "upm json parse failed"); return ERR_JSON; } /* start to parse the JSON; */ service = jsroot->child; if (service == NULL) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "upm json with empty service list"); return ERR_JSON; } /*service array */ servs = ngx_array_create(ctx->pool, 16, sizeof(ngx_stream_upm_service_t)); if (servs == NULL) { return NGX_ERROR; } while( service != NULL ) { //Got the service name; upname = service->string; //Got the service related instance; jinsts = service->child; if (jinsts == NULL || jinsts->child == NULL) { ngx_log_error(NGX_LOG_ERR, pc->log, 0, "upm service: %s without any instance", upname); } ums = ngx_array_push(servs); if (ums == NULL) { return NGX_ERROR; } ums->service_name.len = ngx_strlen(upname); ums->service_name.data = ngx_pcalloc(ctx->pool, ums->service_name.len); ngx_memcpy(ums->service_name.data, upname, ums->service_name.len); ums->insts = ngx_array_create(ctx->pool, 16, sizeof(ngx_stream_upm_service_inst_t)); if (ums->insts == NULL) { return NGX_ERROR; } //travers all the instance jinst = jinsts; while (jinst != NULL) { //FIXME need check the Item isn't exists; host = cJSON_GetObjectItem(jinst, "Host")->valuestring; port = cJSON_GetObjectItem(jinst, "Port")->valueint; tags = cJSON_GetObjectItem(jinst, "Tags"); fail_timeout = cJSON_GetObjectItem(tags, "fail_timeout")->valueint; max_fail = cJSON_GetObjectItem(tags, "max_fails")->valueint; weight = cJSON_GetObjectItem(tags, "weight")->valueint; umsi = ngx_array_push(ums->insts); if (umsi == NULL) { return NGX_ERROR; } i = ngx_strlen(host); //Here, ip:port, Max port is 65535 umsi->name.data = ngx_pcalloc(ctx->pool, (i + 5) * sizeof(char)); t = (char *)ngx_snprintf(umsi->name.data, i + 5, "%s:%d", (char *)host, port); umsi->name.len = t - (char *)umsi->name.data; umsi->host.data = (u_char *)host; umsi->host.len = i; umsi->port = port; umsi->fail_timeout = fail_timeout; umsi->max_fail = max_fail; umsi->weight = weight; jinst = jinst->next; } service = service->next; } //Process the upstream msg, check wether we need to update the server; cf.name = "ngx_stream_upm_module"; //Here, we create a memory pool, Only use to the upstream init peer; cf.pool = ngx_create_pool(8192, pc->log); cf.module_type = NGX_STREAM_MODULE; cf.cmd_type = NGX_STREAM_SRV_CONF; cf.log = pc->log; if (ummcf->pool == NULL) { ummcf->pool = cf.pool; } else { //pool = cf.pool; ummcf->pool = cf.pool; } for (i = 0; i < servs->nelts; i++) { ums = &((ngx_stream_upm_service_t *)(servs->elts))[i]; sfound = 0; /*First: find the upstream name */ uscf = NULL; for (j = 0; j < upstreams->nelts; j++) { uscf = &((ngx_stream_upstream_srv_conf_t *)upstreams->elts)[j]; if (uscf->host.len == ums->service_name.len && ngx_strncmp(uscf->host.data, ums->service_name.data, uscf->host.len) == 0) { sfound = 1; } } if (sfound == 1) { //reset the temporary array to zero; //the elt == 1, Means update; //the elt == 2, Means create; //the elt == 0, Means need set this server to down; memset(ta, 0, sizeof(ta)); us = NULL; for (p = 0; p < ums->insts->nelts; p++) { umsi = &((ngx_stream_upm_service_inst_t *)ums->insts->elts)[p]; ifound = 0; for (st = 0; st < uscf->servers->nelts; st++) { us = &((ngx_stream_upstream_server_t *)uscf->servers->elts)[st]; if(us->name.len == umsi->name.len && ngx_strncmp(us->name.data, umsi->name.data, us->name.len ) == 0) { ifound = 1; } } //Means server already exists; if (ifound == 1) { us->weight = umsi->weight; us->max_fails = umsi->max_fail; us->fail_timeout = umsi->fail_timeout; us->backup = umsi->backup; us->down = umsi->down; ta[st] = 1; //insert the server; } else { us = ngx_array_push(uscf->servers); us->weight = umsi->weight; us->max_fails = umsi->max_fail; us->fail_timeout = umsi->fail_timeout; us->backup = umsi->backup; us->down = umsi->down; ta[st] = 2; } } for (st = 0; st < uscf->servers->nelts; st++) { us = &((ngx_stream_upstream_server_t *)uscf->servers->elts)[st]; if (ta[st] == 0) { //FIXME: Only set this server to down, // If the backend change very quikly, there are too many down server list; us->down = 1; } } /*Reinit the upstream servers*/ init = uscf->peer.init_upstream ? uscf->peer.init_upstream: ngx_stream_upstream_init_round_robin; if (init(&cf, uscf) != NGX_OK) { return NGX_ERROR; } } else { //TODO: doesn't support auto discovery the service name? //Need alloc the memory from the global; ngx_log_error(NGX_LOG_ERR, pc->log, 0, "config server return uninitilized usptreams: %V", &ums->service_name); } } /*Update the upstream weight*/ return NGX_OK; }
static ngx_int_t ngx_http_upstream_init_chash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { u_char hash_buf[256]; ngx_int_t j, weight; ngx_uint_t sid, id, hash_len; ngx_uint_t i, n, *number, rnindex; ngx_http_upstream_rr_peer_t *peer; ngx_http_upstream_rr_peers_t *peers; ngx_http_upstream_chash_server_t *server; ngx_http_upstream_chash_srv_conf_t *ucscf; if (ngx_http_upstream_init_round_robin(cf, us) == NGX_ERROR) { return NGX_ERROR; } ucscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_consistent_hash_module); if (ucscf == NULL) { return NGX_ERROR; } us->peer.init = ngx_http_upstream_init_chash_peer; peers = (ngx_http_upstream_rr_peers_t *) us->peer.data; if (peers == NULL) { return NGX_ERROR; } n = peers->number; ucscf->number = 0; ucscf->real_node = ngx_pcalloc(cf->pool, n * sizeof(ngx_http_upstream_chash_server_t**)); if (ucscf->real_node == NULL) { return NGX_ERROR; } for (i = 0; i < n; i++) { ucscf->number += peers->peer[i].weight * NGX_CHASH_VIRTUAL_NODE_NUMBER; ucscf->real_node[i] = ngx_pcalloc(cf->pool, (peers->peer[i].weight * NGX_CHASH_VIRTUAL_NODE_NUMBER + 1) * sizeof(ngx_http_upstream_chash_server_t*)); if (ucscf->real_node[i] == NULL) { return NGX_ERROR; } } ucscf->servers = ngx_pcalloc(cf->pool, (ucscf->number + 1) * sizeof(ngx_http_upstream_chash_server_t)); if (ucscf->servers == NULL) { return NGX_ERROR; } ucscf->d_servers = ngx_pcalloc(cf->pool, (ucscf->number + 1) * sizeof(ngx_http_upstream_chash_down_server_t)); if (ucscf->d_servers == NULL) { return NGX_ERROR; } ucscf->number = 0; for (i = 0; i < n; i++) { peer = &peers->peer[i]; sid = (ngx_uint_t) ngx_atoi(peer->id.data, peer->id.len); if (sid == (ngx_uint_t) NGX_ERROR || sid > 65535) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, "server id %d", sid); ngx_snprintf(hash_buf, 256, "%V%Z", &peer->name); hash_len = ngx_strlen(hash_buf); sid = ngx_murmur_hash2(hash_buf, hash_len); } weight = peer->weight * NGX_CHASH_VIRTUAL_NODE_NUMBER; if (weight >= 1 << 14) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "weigth[%d] is too large, is must be less than %d", weight / NGX_CHASH_VIRTUAL_NODE_NUMBER, (1 << 14) / NGX_CHASH_VIRTUAL_NODE_NUMBER); weight = 1 << 14; } for (j = 0; j < weight; j++) { server = &ucscf->servers[++ucscf->number]; server->peer = peer; server->rnindex = i; id = sid * 256 * 16 + j; server->hash = ngx_murmur_hash2((u_char *) (&id), 4); } } ngx_qsort(ucscf->servers + 1, ucscf->number, sizeof(ngx_http_upstream_chash_server_t), (const void *)ngx_http_upstream_chash_cmp); number = ngx_calloc(n * sizeof(ngx_uint_t), cf->log); if (number == NULL) { return NGX_ERROR; } for (i = 1; i <= ucscf->number; i++) { ucscf->servers[i].index = i; ucscf->d_servers[i].id = i; rnindex = ucscf->servers[i].rnindex; ucscf->real_node[rnindex][number[rnindex]] = &ucscf->servers[i]; number[rnindex]++; } ngx_free(number); ucscf->tree = ngx_pcalloc(cf->pool, sizeof(ngx_segment_tree_t)); if (ucscf->tree == NULL) { return NGX_ERROR; } ngx_segment_tree_init(ucscf->tree, ucscf->number, cf->pool); ucscf->tree->build(ucscf->tree, 1, 1, ucscf->number); ngx_queue_init(&ucscf->down_servers); return NGX_OK; }
static int log_wrapper(ngx_tcp_session_t *s, const char *ident, ngx_uint_t level, lua_State *L) { u_char *buf; u_char *p, *q; ngx_str_t name; int nargs, i; size_t size, len; size_t src_len = 0; int type; const char *msg; lua_Debug ar; ngx_buf_t *b; if (level > s->connection->log->log_level) { return 0; } dd("log level: %d", (int)level); #if 1 /* add debug info */ lua_getstack(L, 1, &ar); lua_getinfo(L, "Snl", &ar); /* get the basename of the Lua source file path, stored in q */ name.data = (u_char *) ar.short_src; if (name.data == NULL) { name.len = 0; } else { p = name.data; while (*p != '\0') { if (*p == '/' || *p == '\\') { name.data = p + 1; } p++; } name.len = p - name.data; } #endif nargs = lua_gettop(L); size = name.len + NGX_INT_T_LEN + sizeof(":: ") - 1; if (*ar.namewhat != '\0' && *ar.what == 'L') { src_len = ngx_strlen(ar.name); size += src_len + sizeof("(): ") - 1; } for (i = 1; i <= nargs; i++) { type = lua_type(L, i); switch (type) { case LUA_TNUMBER: case LUA_TSTRING: lua_tolstring(L, i, &len); size += len; break; case LUA_TNIL: size += sizeof("nil") - 1; break; case LUA_TBOOLEAN: if (lua_toboolean(L, i)) { size += sizeof("true") - 1; } else { size += sizeof("false") - 1; } break; case LUA_TLIGHTUSERDATA: if (lua_touserdata(L, i) == NULL) { size += sizeof("null") - 1; break; } continue; default: msg = lua_pushfstring(L, "string, number, boolean, or nil " "expected, got %s", lua_typename(L, type)); return luaL_argerror(L, i, msg); } } //buf = lua_newuserdata(L, size + 1); b = ngx_create_temp_buf(s->pool, size + 1); buf = (u_char*)b->pos; p = ngx_copy(buf, name.data, name.len); *p++ = ':'; p = ngx_snprintf(p, NGX_INT_T_LEN, "%d", ar.currentline ? ar.currentline : ar.linedefined); *p++ = ':'; *p++ = ' '; if (*ar.namewhat != '\0' && *ar.what == 'L') { p = ngx_copy(p, ar.name, src_len); *p++ = '('; *p++ = ')'; *p++ = ':'; *p++ = ' '; } for (i = 1; i <= nargs; i++) { type = lua_type(L, i); switch (type) { case LUA_TNUMBER: case LUA_TSTRING: q = (u_char *) lua_tolstring(L, i, &len); p = ngx_copy(p, q, len); break; case LUA_TNIL: *p++ = 'n'; *p++ = 'i'; *p++ = 'l'; break; case LUA_TBOOLEAN: if (lua_toboolean(L, i)) { *p++ = 't'; *p++ = 'r'; *p++ = 'u'; *p++ = 'e'; } else { *p++ = 'f'; *p++ = 'a'; *p++ = 'l'; *p++ = 's'; *p++ = 'e'; } break; case LUA_TLIGHTUSERDATA: *p++ = 'n'; *p++ = 'u'; *p++ = 'l'; *p++ = 'l'; break; default: return luaL_error(L, "impossible to reach here"); } } *p++ = '\0'; if (p - buf > (off_t) (size + 1)) { return luaL_error(L, "buffer error: %d > %d", (int) (p - buf), (int) (size + 1)); } ngx_log_error(level, s->connection->log, 0, "%s%s", ident, buf); return 0; }
static mrb_value ngx_http_mruby_variable_set_internal(mrb_state *mrb, mrb_value self, char *k, mrb_value o) { ngx_http_request_t *r; ngx_http_variable_t *v; ngx_http_variable_value_t *vv; ngx_http_core_main_conf_t *cmcf; ngx_str_t key; ngx_uint_t hash; u_char *val, *low; r = ngx_http_mruby_get_request(); val = (u_char *)RSTRING_PTR(o); key.data = (u_char *)k; key.len = ngx_strlen(k); if (key.len) { low = ngx_pnalloc(r->pool, key.len); if (low == NULL) { return mrb_nil_value(); } } else { return mrb_nil_value(); } hash = ngx_hash_strlow(low, key.data, key.len); cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); v = ngx_hash_find(&cmcf->variables_hash, hash, key.data, key.len); if (v) { if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "%s ERROR %s:%d: %s not changeable" , MODULE_NAME , __FUNCTION__ , __LINE__ , key.data ); return mrb_nil_value(); } if (v->set_handler) { vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); if (vv == NULL) { ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "%s ERROR %s:%d: memory allocate failed" , MODULE_NAME , __FUNCTION__ , __LINE__ ); return mrb_nil_value(); } vv->valid = 1; vv->not_found = 0; vv->no_cacheable = 0; vv->data = val; vv->len = RSTRING_LEN(o); v->set_handler(r, vv, v->data); return mrb_str_new_cstr(mrb, (char *)val); } if (v->flags & NGX_HTTP_VAR_INDEXED) { vv = &r->variables[v->index]; vv->valid = 1; vv->not_found = 0; vv->no_cacheable = 0; vv->data = val; vv->len = RSTRING_LEN(o); return mrb_str_new_cstr(mrb, (char *)val); } ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "%s ERROR %s:%d: %s is not assinged" , MODULE_NAME , __FUNCTION__ , __LINE__ , key.data ); return mrb_nil_value(); } ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "%s ERROR %s:%d: %s is not found" , MODULE_NAME , __FUNCTION__ , __LINE__ , key.data ); return mrb_nil_value(); }
static ngx_int_t ngx_rtmp_play_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) { ngx_rtmp_play_app_conf_t *pacf; ngx_rtmp_play_ctx_t *ctx; u_char *p; ngx_event_t *e; size_t len, slen; static u_char path[NGX_MAX_PATH]; pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module); if (pacf == NULL || pacf->root.len == 0) { goto next; } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: play name='%s' timestamp=%i", v->name, (ngx_int_t) v->start); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); if (ctx && ctx->file.fd != NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: already playing"); goto next; } /* check for double-dot in v->name; * we should not move out of play directory */ p = v->name; while (*p) { if (*p == '.' && *(p + 1) == '.') { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: bad name '%s'", v->name); return NGX_ERROR; } ++p; } if (ctx == NULL) { ctx = ngx_palloc(s->connection->pool, sizeof(ngx_rtmp_play_ctx_t)); ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_play_module); } ngx_memzero(ctx, sizeof(*ctx)); ctx->file.log = s->connection->log; /* make file path */ len = ngx_strlen(v->name); slen = sizeof(".flv") - 1; p = ngx_snprintf(path, sizeof(path), "%V/%s%s", &pacf->root, v->name, len > slen && ngx_strncasecmp((u_char *) ".flv", v->name + len - slen, slen) == 0 ? "" : ".flv"); *p = 0; /* open file */ ctx->file.fd = ngx_open_file(path, NGX_FILE_RDONLY, NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); if (ctx->file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "play: error opening file %s", path); goto next; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: opened file '%s'", path); e = &ctx->write_evt; e->data = s; e->handler = ngx_rtmp_play_send; e->log = s->connection->log; ngx_rtmp_send_user_recorded(s, 1); ngx_rtmp_play_start(s, v->start); next: return next_play(s, v); }
static void ngx_rtmp_auto_push_reconnect(ngx_event_t *ev) { ngx_rtmp_session_t *s = ev->data; ngx_rtmp_auto_push_conf_t *apcf; ngx_rtmp_auto_push_ctx_t *ctx; ngx_int_t *slot; ngx_int_t n; ngx_rtmp_relay_target_t at; u_char path[sizeof("unix:") + NGX_MAX_PATH]; u_char flash_ver[sizeof("APSH ,") + NGX_OFF_T_LEN * 2]; u_char play_path[NGX_RTMP_MAX_NAME]; ngx_str_t name; u_char *p; ngx_str_t *u; ngx_pid_t pid; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "auto_push: reconnect"); apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ngx_rtmp_auto_push_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_auto_push_module); if (ctx == NULL) { return; } name.data = ctx->name; name.len = ngx_strlen(name.data); ngx_memzero(&at, sizeof(at)); ngx_str_set(&at.page_url, "nginx-auto-push"); at.tag = &ngx_rtmp_auto_push_module; if (ctx->args[0]) { at.play_path.data = play_path; at.play_path.len = ngx_snprintf(play_path, sizeof(play_path), "%s?%s", ctx->name, ctx->args) - play_path; } slot = ctx->slots; for (n = 0; n < NGX_MAX_PROCESSES; ++n, ++slot) { if (n == ngx_process_slot) { continue; } pid = ngx_processes[n].pid; if (pid == 0 || pid == -1) { continue; } if (*slot) { continue; } at.data = &ngx_processes[n]; ngx_memzero(&at.url, sizeof(at.url)); u = &at.url.url; p = ngx_snprintf(path, sizeof(path) - 1, "unix:%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i", &apcf->socket_dir, n); *p = 0; u->data = path; u->len = p - path; if (ngx_parse_url(s->connection->pool, &at.url) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auto_push: auto-push parse_url failed " "url='%V' name='%s'", u, ctx->name); continue; } p = ngx_snprintf(flash_ver, sizeof(flash_ver) - 1, "APSH %i,%i", (ngx_int_t) ngx_process_slot, (ngx_int_t) ngx_pid); at.flash_ver.data = flash_ver; at.flash_ver.len = p - flash_ver; ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "auto_push: connect slot=%i pid=%i socket='%s' " "name='%s'", n, (ngx_int_t) pid, path, ctx->name); if (ngx_rtmp_relay_push(s, &name, &at) == NGX_OK) { *slot = 1; continue; } ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auto_push: connect failed: slot=%i pid=%i socket='%s'" "url='%V' name='%s'", n, (ngx_int_t) pid, path, u, ctx->name); if (!ctx->push_evt.timer_set) { ngx_add_timer(&ctx->push_evt, apcf->push_reconnect); } } }
static ngx_int_t process_header(ngx_http_request_t *r) { ngx_int_t rc; ngx_uint_t i; ngx_table_elt_t *h; ngx_http_upstream_header_t *hh; ngx_http_upstream_main_conf_t *umcf; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); for ( ;; ) { #if NGINX_VERSION_NUM >= 7000 rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1); #else rc = ngx_http_parse_header_line(r, &r->upstream->buffer); #endif if (rc == NGX_OK) { /* a header line has been parsed successfully */ h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = r->header_hash; h->key.len = r->header_name_end - r->header_name_start; h->value.len = r->header_end - r->header_start; h->key.data = ngx_palloc(r->pool, h->key.len + 1 + h->value.len + 1 + h->key.len); if (h->key.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->value.data = h->key.data + h->key.len + 1; h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); if (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); } else { for (i = 0; i < h->key.len; i++) { h->lowcase_key[i] = ngx_tolower(h->key.data[i]); } } hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http scgi header: \"%V: %V\"", &h->key, &h->value); continue; } if (rc == NGX_HTTP_PARSE_HEADER_DONE) { /* a whole header has been parsed successfully */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http scgi header done"); /* * if no "Server" and "Date" in header line, * then add the default headers */ if (r->upstream->headers_in.server == NULL) { h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash( ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r'); h->key.len = sizeof("Server") - 1; h->key.data = (u_char *) "Server"; h->value.data = (u_char *) (NGINX_VER " + Phusion Passenger " PASSENGER_VERSION " (mod_rails/mod_rack)"); h->value.len = ngx_strlen(h->value.data); h->lowcase_key = (u_char *) "server"; } if (r->upstream->headers_in.date == NULL) { h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e'); h->key.len = sizeof("Date") - 1; h->key.data = (u_char *) "Date"; h->value.len = 0; h->value.data = NULL; h->lowcase_key = (u_char *) "date"; } return NGX_OK; } if (rc == NGX_AGAIN) { return NGX_AGAIN; } /* there was error while a header line parsing */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent invalid header"); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } }
static ngx_chain_t * ngx_rtmp_notify_connect_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool) { ngx_rtmp_connect_t *v = arg; ngx_rtmp_notify_srv_conf_t *nscf; ngx_url_t *url; ngx_chain_t *al, *bl; ngx_buf_t *b; ngx_str_t *addr_text; size_t app_len, args_len, flashver_len, swf_url_len, tc_url_len, page_url_len; nscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_notify_module); al = ngx_alloc_chain_link(pool); if (al == NULL) { return NULL; } /* these values are still missing in session * so we have to construct the request from * connection struct */ app_len = ngx_strlen(v->app); args_len = ngx_strlen(v->args); flashver_len = ngx_strlen(v->flashver); swf_url_len = ngx_strlen(v->swf_url); tc_url_len = ngx_strlen(v->tc_url); page_url_len = ngx_strlen(v->page_url); addr_text = &s->connection->addr_text; b = ngx_create_temp_buf(pool, sizeof("call=connect") - 1 + sizeof("&app=") - 1 + app_len * 3 + sizeof("&flashver=") - 1 + flashver_len * 3 + sizeof("&swfurl=") - 1 + swf_url_len * 3 + sizeof("&tcurl=") - 1 + tc_url_len * 3 + sizeof("&pageurl=") - 1 + page_url_len * 3 + sizeof("&addr=") - 1 + addr_text->len * 3 + sizeof("&epoch=") - 1 + NGX_INT32_LEN + 1 + args_len ); if (b == NULL) { return NULL; } al->buf = b; al->next = NULL; b->last = ngx_cpymem(b->last, (u_char*) "app=", sizeof("app=") - 1); b->last = (u_char*) ngx_escape_uri(b->last, v->app, app_len, NGX_ESCAPE_ARGS); b->last = ngx_cpymem(b->last, (u_char*) "&flashver=", sizeof("&flashver=") - 1); b->last = (u_char*) ngx_escape_uri(b->last, v->flashver, flashver_len, NGX_ESCAPE_ARGS); b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=", sizeof("&swfurl=") - 1); b->last = (u_char*) ngx_escape_uri(b->last, v->swf_url, swf_url_len, NGX_ESCAPE_ARGS); b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=", sizeof("&tcurl=") - 1); b->last = (u_char*) ngx_escape_uri(b->last, v->tc_url, tc_url_len, NGX_ESCAPE_ARGS); b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=", sizeof("&pageurl=") - 1); b->last = (u_char*) ngx_escape_uri(b->last, v->page_url, page_url_len, NGX_ESCAPE_ARGS); b->last = ngx_cpymem(b->last, (u_char*) "&addr=", sizeof("&addr=") -1); b->last = (u_char*) ngx_escape_uri(b->last, addr_text->data, addr_text->len, NGX_ESCAPE_ARGS); b->last = ngx_cpymem(b->last, (u_char*) "&epoch=", sizeof("&epoch=") -1); b->last = ngx_sprintf(b->last, "%uD", (uint32_t) s->epoch); b->last = ngx_cpymem(b->last, (u_char*) "&call=connect", sizeof("&call=connect") - 1); if (args_len) { *b->last++ = '&'; b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len); } url = nscf->url[NGX_RTMP_NOTIFY_CONNECT]; bl = NULL; if (nscf->method == NGX_RTMP_NETCALL_HTTP_POST) { bl = al; al = NULL; } return ngx_rtmp_netcall_http_format_request(nscf->method, &url->host, &url->uri, al, bl, pool, &ngx_rtmp_notify_urlencoded); }
static ngx_int_t ngx_http_mycookie_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; ngx_http_mycookie_loc_conf_t *my_cf; u_char ngx_my_string[1024] = {0}; ngx_uint_t content_length = 0; ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_mycookie_handler is called!"); my_cf = ngx_http_get_module_loc_conf(r,ngx_http_mycookie_module); if (my_cf->cookieflag == NGX_CONF_UNSET ) { ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "cookieflag is UNSET!"); return NGX_DECLINED; } //从请求头读取cookies,使用的时候可以使用cookies[0]->value.data,cookies[0]->value.len ngx_table_elt_t ** cookies = NULL; cookies = r->headers_in.cookies.elts; ngx_table_elt_t * client_ip = NULL; client_ip = r->headers_in.user_agent; /* * supported formats: * %[0][width][x][X]O off_t * %[0][width]T time_t * %[0][width][u][x|X]z ssize_t/size_t * %[0][width][u][x|X]d int/u_int * %[0][width][u][x|X]l long * %[0][width|m][u][x|X]i ngx_int_t/ngx_uint_t * %[0][width][u][x|X]D int32_t/uint32_t * %[0][width][u][x|X]L int64_t/uint64_t * %[0][width|m][u][x|X]A ngx_atomic_int_t/ngx_atomic_uint_t * %[0][width][.width]f double, max valid number fits to %18.15f * %P ngx_pid_t * %M ngx_msec_t * %r rlim_t * %p void * * %V ngx_str_t * * %v ngx_variable_value_t * * %s null-terminated string * %*s length and string * %Z '\0' * %N '\n' * %c char * %% % * * reserved: * %t ptrdiff_t * %S null-terminated wchar string * %C wchar */ //u_char ipchar[client_ip->value.len+1]={0}; //u_char cookiechar[cookies[0]->value.len+1]={0}; //ngx_sprintf(ipchar, "%V\0",&client_ip->value); //ngx_sprintf(cookiechar, "%V\0",&cookies[0]->value); if ( cookies != NULL) //未定义cookie? { ngx_sprintf(ngx_my_string, "user_agent is %V, you have cookie", &client_ip->value); } else { ngx_sprintf(ngx_my_string, "user_agent is %V, you do not have cookie or cookie not match", &client_ip->value); //没有cookie,则给他cookie ngx_table_elt_t *set_cookie = ngx_list_push(&r->headers_out.headers); if (set_cookie == NULL) { return NGX_ERROR; } set_cookie->hash = 1; set_cookie->key.len = sizeof("Set-Cookie") - 1; set_cookie->key.data = (u_char *) "Set-Cookie"; set_cookie->value = client_ip->value; } content_length = ngx_strlen(ngx_my_string); /* we response to 'GET' and 'HEAD' requests only */ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } /* discard request body, since we don't need it here */ rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } /* set the 'Content-type' header */ /* *r->headers_out.content_type.len = sizeof("text/html") - 1; *r->headers_out.content_type.data = (u_char *)"text/html"; */ ngx_str_set(&r->headers_out.content_type, "text/html"); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; /* send the header only, if the request type is http 'HEAD' */ if (r->method == NGX_HTTP_HEAD) { return ngx_http_send_header(r); } /* allocate a buffer for your response body */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /*另一种方式 对于创建temporary字段为1的buf(就是其内容可以被后续的filter模块进行修改),可以直接使用函数ngx_create_temp_buf进行创建。 ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size); 该函数创建一个ngx_but_t类型的对象,并返回指向这个对象的指针,创建失败返回NULL。 对于创建的这个对象,它的start和end指向新分配内存开始和结束的地方。pos和last都指向这块新分配内存的开始处,这样,后续的操作可以在这块新分配的内存上存入数据。*/ /* adjust the pointers of the buffer */ b->pos = ngx_my_string; b->last = ngx_my_string + content_length; b->memory = 1; /* this buffer is in memory */ b->last_buf = 1; /* this is the last buffer in the buffer chain */ /* attach this buffer to the buffer chain */ out.buf = b; out.next = NULL; /* send the headers of your response */ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } /* send the buffer chain of your response */ return ngx_http_output_filter(r, &out); }
static ngx_chain_t * ngx_rtmp_notify_update_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool) { ngx_chain_t *pl; ngx_buf_t *b; size_t name_len, args_len; ngx_rtmp_notify_ctx_t *ctx; ngx_str_t sfx; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); pl = ngx_alloc_chain_link(pool); if (pl == NULL) { return NULL; } if (ctx->flags & NGX_RTMP_NOTIFY_PUBLISHING) { ngx_str_set(&sfx, "_publish"); } else if (ctx->flags & NGX_RTMP_NOTIFY_PLAYING) { ngx_str_set(&sfx, "_play"); } else { ngx_str_null(&sfx); } name_len = ctx ? ngx_strlen(ctx->name) : 0; args_len = ctx ? ngx_strlen(ctx->args) : 0; b = ngx_create_temp_buf(pool, sizeof("&call=update") + sfx.len + sizeof("&time=") + NGX_TIME_T_LEN + sizeof("×tamp=") + NGX_INT32_LEN + sizeof("&name=") + name_len * 3 + 1 + args_len); if (b == NULL) { return NULL; } pl->buf = b; pl->next = NULL; b->last = ngx_cpymem(b->last, (u_char*) "&call=update", sizeof("&call=update") - 1); b->last = ngx_cpymem(b->last, sfx.data, sfx.len); b->last = ngx_cpymem(b->last, (u_char *) "&time=", sizeof("&time=") - 1); b->last = ngx_sprintf(b->last, "%T", ngx_cached_time->sec - ctx->start); b->last = ngx_cpymem(b->last, (u_char *) "×tamp=", sizeof("×tamp=") - 1); b->last = ngx_sprintf(b->last, "%D", s->current_time); if (name_len) { b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1); b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len, NGX_ESCAPE_ARGS); } if (args_len) { *b->last++ = '&'; b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len); } return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_UPDATE, pl); }
static ngx_chain_t * ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool) { ngx_rtmp_play_t *v = arg; ngx_rtmp_notify_app_conf_t *nacf; ngx_chain_t *hl, *cl, *pl; ngx_buf_t *b; ngx_str_t *addr_text; ngx_url_t *url; size_t name_len, args_len; nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); /* common variables */ cl = ngx_rtmp_netcall_http_format_session(s, pool); if (cl == NULL) { return NULL; } /* play variables */ pl = ngx_alloc_chain_link(pool); if (pl == NULL) { return NULL; } name_len = ngx_strlen(v->name); args_len = ngx_strlen(v->args); addr_text = &s->connection->addr_text; b = ngx_create_temp_buf(pool, sizeof("&call=play") + sizeof("&addr=") + addr_text->len * 3 + sizeof("&name=") + name_len * 3 + sizeof("&start=&duration=&reset=") + NGX_OFF_T_LEN * 3 + 1 + args_len); if (b == NULL) { return NULL; } pl->buf = b; b->last = ngx_cpymem(b->last, (u_char*)"&call=play", sizeof("&call=play") - 1); b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1); b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data, addr_text->len, 0); b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1); b->last = (u_char*)ngx_escape_uri(b->last, v->name, name_len, 0); b->last = ngx_snprintf(b->last, b->end - b->last, "&start=%uD&duration=%uD&reset=%d", (uint32_t)v->start, (uint32_t)v->duration, v->reset & 1); if (args_len) { *b->last++ = '&'; b->last = (u_char *)ngx_cpymem(b->last, v->args, args_len); } /* HTTP header */ url = nacf->url[NGX_RTMP_NOTIFY_PLAY]; hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST, &url->uri, &url->host, pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos), &ngx_rtmp_notify_urlencoded); if (hl == NULL) { return NULL; } hl->next = cl; cl->next = pl; pl->next = NULL; return hl; }
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle) { u_char *p; size_t len; if (ngx_prefix) { len = ngx_strlen(ngx_prefix); p = ngx_prefix; if (!ngx_path_separator(*p)) { p = ngx_pnalloc(cycle->pool, len + 1); if (p == NULL) { return NGX_ERROR; } ngx_memcpy(p, ngx_prefix, len); p[len++] = '/'; } cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; } else { #ifndef NGX_PREFIX p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH); if (p == NULL) { return NGX_ERROR; } if (ngx_getcwd(p, NGX_MAX_PATH) == 0) { ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed"); return NGX_ERROR; } len = ngx_strlen(p); p[len++] = '/'; cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; #else #ifdef NGX_CONF_PREFIX ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX); #else ngx_str_set(&cycle->conf_prefix, NGX_PREFIX); #endif ngx_str_set(&cycle->prefix, NGX_PREFIX); #endif } if (ngx_conf_file) { cycle->conf_file.len = ngx_strlen(ngx_conf_file); cycle->conf_file.data = ngx_conf_file; } else { ngx_str_set(&cycle->conf_file, NGX_CONF_PATH); } if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) { return NGX_ERROR; } for (p = cycle->conf_file.data + cycle->conf_file.len - 1; p > cycle->conf_file.data; p--) { if (ngx_path_separator(*p)) { cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1; cycle->conf_prefix.data = ngx_cycle->conf_file.data; break; } } if (ngx_conf_params) { cycle->conf_param.len = ngx_strlen(ngx_conf_params); cycle->conf_param.data = ngx_conf_params; } if (ngx_test_config) { cycle->log->log_level = NGX_LOG_INFO; } return NGX_OK; }
static ngx_chain_t * ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool) { ngx_rtmp_notify_done_t *ds = arg; ngx_chain_t *hl, *cl, *pl; ngx_buf_t *b; size_t cbname_len, name_len, args_len; ngx_str_t *addr_text; ngx_rtmp_notify_ctx_t *ctx; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); /* common variables */ cl = ngx_rtmp_netcall_http_format_session(s, pool); if (cl == NULL) { return NULL; } pl = ngx_alloc_chain_link(pool); if (pl == NULL) { return NULL; } cbname_len = ngx_strlen(ds->cbname); name_len = ctx ? ngx_strlen(ctx->name) : 0; args_len = ctx ? ngx_strlen(ctx->args) : 0; addr_text = &s->connection->addr_text; b = ngx_create_temp_buf(pool, sizeof("&call=") + cbname_len + sizeof("&addr=") + addr_text->len * 3 + sizeof("&name=") + name_len * 3 + 1 + args_len); if (b == NULL) { return NULL; } pl->buf = b; b->last = ngx_cpymem(b->last, (u_char*)"&call=", sizeof("&call=") - 1); b->last = ngx_cpymem(b->last, ds->cbname, cbname_len); b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1); b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data, addr_text->len, 0); if (name_len) { b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1); b->last = (u_char*)ngx_escape_uri(b->last, ctx->name, name_len, 0); } if (args_len) { *b->last++ = '&'; b->last = (u_char *)ngx_cpymem(b->last, ctx->args, args_len); } /* HTTP header */ hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST, &ds->url->uri, &ds->url->host, pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos), &ngx_rtmp_notify_urlencoded); if (hl == NULL) { return NULL; } hl->next = cl; cl->next = pl; pl->next = NULL; return hl; }
static ngx_int_t ngx_dso_find_postion(ngx_dso_conf_ctx_t *ctx, ngx_str_t module_name) { size_t len1, len2, len3; ngx_int_t near; ngx_str_t *name; ngx_uint_t i, k; near = ctx->flag_postion; if (ctx->stubs == NULL || ctx->stubs->nelts == 0) { for (i = 1; ngx_all_module_names[i]; i++) { len1 = ngx_strlen(ngx_all_module_names[i]); if (len1 == module_name.len && ngx_strncmp(ngx_all_module_names[i], module_name.data, len1) == 0) { if (near <= ctx->flag_postion) { ctx->flag_postion++; } return near; } len2 = ngx_strlen(ngx_all_module_names[i - 1]); for (k = 0; ngx_module_names[k]; k++) { len3 = ngx_strlen(ngx_module_names[k]); if (len2 == len3 && ngx_strncmp(ngx_all_module_names[i - 1], ngx_module_names[k], len2) == 0) { near = k + 1; break; } } } if (ngx_all_module_names[i] == NULL) { return ctx->flag_postion++; } } name = ctx->stubs->elts; near = ctx->flag_postion; for (i = 1; i < ctx->stubs->nelts; i++) { if (name[i].len == module_name.len && ngx_strncmp(name[i].data, module_name.data, name[i].len) == 0) { if (near <= ctx->flag_postion) { ctx->flag_postion++; } return near; } for (k = 0; ngx_module_names[k]; k++) { len1 = ngx_strlen(ngx_module_names[k]); if (len1 == name[i - 1].len && ngx_strncmp(name[i - 1].data, ngx_module_names[k], name[i - 1].len) == 0) { near = k + 1; break; } } } return ctx->flag_postion++; }
static ngx_chain_t * ngx_rtmp_notify_record_done_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool) { ngx_rtmp_record_done_t *v = arg; ngx_rtmp_notify_app_conf_t *nacf; ngx_rtmp_notify_ctx_t *ctx; ngx_chain_t *hl, *cl, *pl; ngx_buf_t *b; ngx_str_t *addr_text; ngx_url_t *url; size_t name_len, args_len; nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); /* common variables */ cl = ngx_rtmp_netcall_http_format_session(s, pool); if (cl == NULL) { return NULL; } /* publish variables */ pl = ngx_alloc_chain_link(pool); if (pl == NULL) { return NULL; } name_len = ngx_strlen(ctx->name); args_len = ngx_strlen(ctx->args); addr_text = &s->connection->addr_text; b = ngx_create_temp_buf(pool, sizeof("&call=record_done") + sizeof("&recorder=") + v->recorder.len + sizeof("&addr=") + addr_text->len *3 + sizeof("&name=") + name_len * 3 + sizeof("&path=") + v->path.len * 3 + + 1 + args_len); if (b == NULL) { return NULL; } pl->buf = b; b->last = ngx_cpymem(b->last, (u_char*)"&call=record_done", sizeof("&call=record_done") - 1); b->last = ngx_cpymem(b->last, (u_char *)"&recorder=", sizeof("&recorder=") - 1); b->last = (u_char*)ngx_escape_uri(b->last, v->recorder.data, v->recorder.len, 0); b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1); b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data, addr_text->len, 0); b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1); b->last = (u_char*)ngx_escape_uri(b->last, ctx->name, name_len, 0); b->last = ngx_cpymem(b->last, (u_char*)"&path=", sizeof("&path=") - 1); b->last = (u_char*)ngx_escape_uri(b->last, v->path.data, v->path.len, 0); if (args_len) { *b->last++ = '&'; b->last = (u_char *)ngx_cpymem(b->last, ctx->args, args_len); } /* HTTP header */ url = nacf->url[NGX_RTMP_NOTIFY_RECORD_DONE]; hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST, &url->uri, &url->host, pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos), &ngx_rtmp_notify_urlencoded); if (hl == NULL) { return NULL; } hl->next = cl; cl->next = pl; pl->next = NULL; return hl; }
static ngx_int_t ngx_http_traffic_status_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; u_char ngx_traffic_status_string[1024] = {0}; ngx_uint_t i; ngx_http_traffic_status_rule_t *rucf = NULL; ngx_http_traffic_status_local_conf_t *local_conf = NULL; ngx_int_t offset = 0; ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_traffic_status_handler is called!"); /* we response to 'GET' and 'HEAD' requests only */ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rucf = ngx_http_get_module_srv_conf(r, ngx_http_traffic_status_module); if (NULL == rucf) { return NGX_ERROR; } local_conf = ngx_http_get_module_loc_conf(r, ngx_http_traffic_status_module); /* not enable */ if (!(local_conf->req_flag | local_conf->pkt_flag | local_conf->status_flag)) { return NGX_HTTP_NOT_ALLOWED; } /* request times calculate */ if (local_conf->req_flag) { ngx_sprintf(ngx_traffic_status_string + offset, "http request times: %d\n", rucf->request_cnt); offset += ngx_strlen(ngx_traffic_status_string); } if (local_conf->pkt_flag) { /* recevie bytes */ ngx_sprintf(ngx_traffic_status_string + offset, "recevie packet bytes: %d\n", rucf->recv_bytes); offset += ngx_strlen(ngx_traffic_status_string); /* send bytes */ ngx_sprintf(ngx_traffic_status_string + offset, "send packet bytes: %d\n", rucf->send_bytes); offset += ngx_strlen(ngx_traffic_status_string); } if (local_conf->status_flag) { ngx_sprintf(ngx_traffic_status_string + offset, "---- http status ----\n"); offset += ngx_strlen(ngx_traffic_status_string); ngx_sprintf(ngx_traffic_status_string + offset, "---------------------\n"); offset += ngx_strlen(ngx_traffic_status_string); for (i = 0; i < NGX_HTTP_STATUS_CODES_NUM; i++) { if (rucf->status_codes_cnt[i] > 0) { ngx_sprintf(ngx_traffic_status_string + offset, "%d: %d\n", i + NGX_HTTP_OK, rucf->status_codes_cnt[i]); offset += ngx_strlen(ngx_traffic_status_string); } } ngx_sprintf(ngx_traffic_status_string + offset, "---------------------\n"); offset += ngx_strlen(ngx_traffic_status_string); } /* discard request body, since we don't need it here */ rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } /* set the 'Content-type' header */ ngx_str_set(&r->headers_out.content_type, "text/html"); /* send the header only, if the request type is http 'HEAD' */ if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = offset; return ngx_http_send_header(r); } /* allocate a buffer for your response body */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* attach this buffer to the buffer chain */ out.buf = b; out.next = NULL; /* adjust the pointers of the buffer */ b->pos = ngx_traffic_status_string; b->last = ngx_traffic_status_string + offset; b->memory = 1; /* this buffer is in memory */ b->last_buf = 1; /* this is the last buffer in the buffer chain */ /* set the status line */ r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = offset; /* send the headers of your response */ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } /* send the buffer chain of your response */ return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_http_auth_mysql_authenticate(ngx_http_request_t *r, ngx_http_auth_mysql_ctx_t *ctx, ngx_str_t *passwd, void *conf) { ngx_http_auth_mysql_loc_conf_t *alcf = conf; ngx_auth_mysql_userinfo uinfo; size_t len; ngx_int_t auth_res; ngx_int_t found_in_allowed = 0; ngx_int_t using_groups = 0; u_char *uname_buf, *p, *next_username; ngx_str_t actual_password; u_char *query_buf; u_char *table; u_char *user_column; u_char *password_column; u_char *conditions; u_char *esc_user; MYSQL *conn, *mysql_result; MYSQL_RES *query_result; /** * Get username and password, note that r->headers_in.user contains the * string 'user:pass', so we need to copy the username **/ for (len = 0; len < r->headers_in.user.len; len++) { if (r->headers_in.user.data[len] == ':') { break; } } uname_buf = ngx_palloc(r->pool, len+1); if (uname_buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } p = ngx_cpymem(uname_buf, r->headers_in.user.data , len); *p ='\0'; uinfo.username.data = uname_buf; uinfo.username.len = len; uinfo.password.data = r->headers_in.passwd.data; uinfo.password.len = r->headers_in.passwd.len; /* Check if the user is among allowed users */ if (ngx_strcmp(alcf->allowed_users.data, "") != 0) { found_in_allowed = 0; char* allowed_users = (char*)ngx_http_auth_mysql_uchar(r->pool, &alcf->allowed_users); while ((next_username = (u_char*)strsep(&allowed_users, " \t")) != NULL) { if (ngx_strcmp(next_username, uinfo.username.data) == 0) { found_in_allowed = 1; break; } } } conn = mysql_init(NULL); if (conn == NULL) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "auth_mysql: Could not initialize MySQL connection"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } mysql_result = mysql_real_connect(conn, (char*)alcf->host.data, (char*)alcf->user.data, (char*)alcf->password.data, (char*)alcf->database.data, alcf->port, NULL, 0); if (mysql_result == NULL) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "auth_mysql: Could not connect to MySQL server: %s", mysql_error(conn)); mysql_close(conn); return NGX_HTTP_INTERNAL_SERVER_ERROR; } user_column = ngx_http_auth_mysql_uchar(r->pool, &alcf->user_column); esc_user = ngx_pnalloc(r->pool, 2*(uinfo.username.len + 1)); mysql_real_escape_string(conn, (char*)esc_user, (char*)uinfo.username.data, uinfo.username.len); conditions = ngx_pnalloc(r->pool, ngx_strlen(user_column) + ngx_strlen(esc_user) + 7); p = (u_char*)ngx_sprintf(conditions, "%s = '%s'", (char*)user_column, esc_user); *p = '\0'; if (ngx_strcmp(alcf->conditions.data, "") != 0) { u_char* username_condition = conditions; conditions = ngx_http_auth_mysql_append2(r->pool, username_condition, (u_char*)" AND ", ngx_http_auth_mysql_uchar(r->pool, &alcf->conditions)); ngx_pfree(r->pool, username_condition); } table = ngx_http_auth_mysql_uchar(r->pool, &alcf->table); if (!found_in_allowed && ngx_strcmp(alcf->allowed_groups.data, "") != 0) { if (ngx_strcmp(alcf->group_table.data, "") != 0) { using_groups = 1; u_char* user_table = table; table = ngx_http_auth_mysql_append2(r->pool, user_table, (u_char*)", ", ngx_http_auth_mysql_uchar(r->pool, &alcf->group_table)); ngx_pfree(r->pool, user_table); u_char* current_conditions = conditions; conditions = ngx_http_auth_mysql_append2(r->pool, current_conditions, (u_char*)" AND ", ngx_http_auth_mysql_uchar(r->pool, &alcf->group_conditions)); ngx_pfree(r->pool, current_conditions); // TODO: AND group_col IN (group_values) char* allowed_groups = (char*)ngx_http_auth_mysql_uchar(r->pool, &alcf->allowed_groups); u_char* next_group; current_conditions = conditions; conditions = ngx_http_auth_mysql_append3(r->pool, current_conditions, (u_char*)" AND ", ngx_http_auth_mysql_uchar(r->pool, &alcf->group_column), (u_char*)" IN ("); ngx_pfree(r->pool, current_conditions); u_char* in_group = (u_char*)""; while ((next_group = (u_char*)strsep(&allowed_groups, " \t")) != NULL) { u_char* current_in_group = in_group; u_char* esc_group = ngx_pnalloc(r->pool, 2*(ngx_strlen(next_group) + 1)); mysql_real_escape_string(conn, (char*)esc_group, (char*)next_group, ngx_strlen(next_group)); in_group = ngx_http_auth_mysql_append3(r->pool, current_in_group, (u_char*)"'", esc_group, (u_char*)"',"); if (ngx_strcmp(current_in_group, "") != 0) { ngx_pfree(r->pool, current_in_group); } } if (ngx_strcmp(in_group, "") != 0) { // remove trailing coma in_group[ngx_strlen(in_group)-1] = '\0'; } current_conditions = conditions; conditions = ngx_http_auth_mysql_append2(r->pool, current_conditions, in_group, (u_char*)")"); ngx_pfree(r->pool, current_conditions); } } password_column = ngx_http_auth_mysql_uchar(r->pool, &alcf->password_column); query_buf = ngx_pnalloc(r->pool, ngx_strlen(password_column) + ngx_strlen(table) + ngx_strlen(conditions) + 33); p = ngx_sprintf(query_buf, "SELECT %s FROM %s WHERE %s LIMIT 1", password_column, table, conditions); *p = '\0'; if (mysql_query(conn, (char*)query_buf) != 0) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "auth_mysql: Could not retrieve password: %s", mysql_error(conn)); mysql_close(conn); return NGX_HTTP_INTERNAL_SERVER_ERROR; } query_result = mysql_store_result(conn); if (query_result == NULL){ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "auth_mysql: Could not store result: %s", mysql_error(conn)); mysql_close(conn); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if ( ( ngx_strcmp(alcf->allowed_users.data, "") == 0 || found_in_allowed || using_groups ) && mysql_num_rows(query_result) >= 1 ) { MYSQL_ROW data = mysql_fetch_row(query_result); unsigned long *lengths = mysql_fetch_lengths(query_result); ngx_str_t volatile_actual_password = {lengths[0], (u_char*) data[0]}; actual_password.len = lengths[0]; actual_password.data = ngx_http_auth_mysql_uchar(r->pool, &volatile_actual_password); mysql_free_result(query_result); } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "auth_mysql: User '%s' doesn't exist or is in neither allowed users nor allowed groups", (char*)uinfo.username.data); mysql_free_result(query_result); mysql_close(conn); return ngx_http_auth_mysql_set_realm(r, &alcf->realm); } mysql_close(conn); auth_res = NGX_OK; auth_res = ngx_http_auth_mysql_enctypes[alcf->encryption_type].checker(r, uinfo.password, actual_password); if (NGX_DECLINED == auth_res) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "auth_mysql: Bad authentication for user '%s'.", (char*)uinfo.username.data); return ngx_http_auth_mysql_set_realm(r, &alcf->realm); } /* We expect that on error the checkers log it and then return NGX_ERR. That's why we don't log here, just return NGX_HTTP_INTERNAL_SERVER_ERROR */ return auth_res == NGX_OK? NGX_OK : NGX_HTTP_INTERNAL_SERVER_ERROR; }
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; ngx_http_hello_loc_conf_t* my_conf; u_char ngx_hello_string[1024] = {0}; ngx_uint_t content_length = 0; ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_hello_handler is called!"); my_conf = ngx_http_get_module_loc_conf(r, ngx_http_hello_module); if (my_conf->hello_string.len == 0 ) { ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "hello_string is empty!"); return NGX_DECLINED; } if (my_conf->hello_counter == NGX_CONF_UNSET || my_conf->hello_counter == 0) { ngx_sprintf(ngx_hello_string, "%s", my_conf->hello_string.data); } else { ngx_sprintf(ngx_hello_string, "%s Visited Times:%d", my_conf->hello_string.data, ++ngx_hello_visited_times); } ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "hello_string:%s", ngx_hello_string); content_length = ngx_strlen(ngx_hello_string); /* we response to 'GET' and 'HEAD' requests only */ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } /* discard request body, since we don't need it here */ rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } /* set the 'Content-type' header */ /* *r->headers_out.content_type.len = sizeof("text/html") - 1; *r->headers_out.content_type.data = (u_char *)"text/html"; */ ngx_str_set(&r->headers_out.content_type, "text/html"); /* send the header only, if the request type is http 'HEAD' */ if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; return ngx_http_send_header(r); } /* allocate a buffer for your response body */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* attach this buffer to the buffer chain */ out.buf = b; out.next = NULL; /* adjust the pointers of the buffer */ b->pos = ngx_hello_string; b->last = ngx_hello_string + content_length; b->memory = 1; /* this buffer is in memory */ b->last_buf = 1; /* this is the last buffer in the buffer chain */ /* set the status line */ r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; /* send the headers of your response */ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } /* send the buffer chain of your response */ return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_rtmp_cmd_connect_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) { size_t len; static ngx_rtmp_connect_t v; static ngx_rtmp_amf_elt_t in_cmd[] = { { NGX_RTMP_AMF_STRING, ngx_string("app"), v.app, sizeof(v.app) }, { NGX_RTMP_AMF_STRING, ngx_string("flashVer"), v.flashver, sizeof(v.flashver) }, { NGX_RTMP_AMF_STRING, ngx_string("swfUrl"), v.swf_url, sizeof(v.swf_url) }, { NGX_RTMP_AMF_STRING, ngx_string("tcUrl"), v.tc_url, sizeof(v.tc_url) }, { NGX_RTMP_AMF_NUMBER, ngx_string("audioCodecs"), &v.acodecs, sizeof(v.acodecs) }, { NGX_RTMP_AMF_NUMBER, ngx_string("videoCodecs"), &v.vcodecs, sizeof(v.vcodecs) }, { NGX_RTMP_AMF_STRING, ngx_string("pageUrl"), v.page_url, sizeof(v.page_url) }, { NGX_RTMP_AMF_NUMBER, ngx_string("objectEncoding"), &v.object_encoding, 0}, }; static ngx_rtmp_amf_elt_t in_elts[] = { { NGX_RTMP_AMF_NUMBER, ngx_null_string, &v.trans, 0 }, { NGX_RTMP_AMF_OBJECT, ngx_null_string, in_cmd, sizeof(in_cmd) }, }; ngx_memzero(&v, sizeof(v)); if (ngx_rtmp_receive_amf(s, in, in_elts, sizeof(in_elts) / sizeof(in_elts[0]))) { return NGX_ERROR; } len = ngx_strlen(v.app); if (len > 10 && !ngx_memcmp(v.app + len - 10, "/_definst_", 10)) { v.app[len - 10] = 0; } else if (len && v.app[len - 1] == '/') { v.app[len - 1] = 0; } ngx_rtmp_cmd_fill_args(v.app, v.args); ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "connect: app='%s' args='%s' flashver='%s' swf_url='%s' " "tc_url='%s' page_url='%s' acodecs=%uD vcodecs=%uD " "object_encoding=%ui", v.app, v.args, v.flashver, v.swf_url, v.tc_url, v.page_url, (uint32_t)v.acodecs, (uint32_t)v.vcodecs, (ngx_int_t)v.object_encoding); return ngx_rtmp_connect(s, &v); }
ngx_log_t * ngx_log_init(u_char *prefix) { u_char *p, *name; size_t nlen, plen; ngx_log.file = &ngx_log_file; ngx_log.log_level = NGX_LOG_NOTICE; name = (u_char *) NGX_ERROR_LOG_PATH; /* * we use ngx_strlen() here since BCC warns about * condition is always false and unreachable code */ nlen = ngx_strlen(name); if (nlen == 0) { ngx_log_file.fd = ngx_stderr; return &ngx_log; } p = NULL; #if (NGX_WIN32) if (name[1] != ':') { #else if (name[0] != '/') { #endif if (prefix) { plen = ngx_strlen(prefix); } else { #ifdef NGX_PREFIX prefix = (u_char *) NGX_PREFIX; plen = ngx_strlen(prefix); #else plen = 0; #endif } if (plen) { name = malloc(plen + nlen + 2); if (name == NULL) { return NULL; } p = ngx_cpymem(name, prefix, plen); if (!ngx_path_separator(*(p - 1))) { *p++ = '/'; } ngx_cpystrn(p, (u_char *) NGX_ERROR_LOG_PATH, nlen + 1); p = name; } } ngx_log_file.fd = ngx_open_file(name, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); if (ngx_log_file.fd == NGX_INVALID_FILE) { ngx_log_stderr(ngx_errno, "[alert] could not open error log file: " ngx_open_file_n " \"%s\" failed", name); #if (NGX_WIN32) ngx_event_log(ngx_errno, "could not open error log file: " ngx_open_file_n " \"%s\" failed", name); #endif ngx_log_file.fd = ngx_stderr; } if (p) { ngx_free(p); } return &ngx_log; } ngx_log_t * ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name) { ngx_log_t *log; log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t)); if (log == NULL) { return NULL; } log->file = ngx_conf_open_file(cycle, name); if (log->file == NULL) { return NULL; } return log; }
static ngx_int_t ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in) { ngx_rtmp_play_t *v = arg; ngx_int_t rc; ngx_str_t local_name; ngx_rtmp_relay_target_t target; ngx_url_t *u; ngx_rtmp_notify_app_conf_t *nacf; u_char name[NGX_RTMP_MAX_NAME]; static ngx_str_t location = ngx_string("location"); rc = ngx_rtmp_notify_parse_http_retcode(s, in); if (rc == NGX_ERROR) { ngx_rtmp_notify_clear_flag(s, NGX_RTMP_NOTIFY_PLAYING); return NGX_ERROR; } if (rc != NGX_AGAIN) { goto next; } /* HTTP 3xx */ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "notify: play redirect received"); rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name, sizeof(name) - 1); if (rc <= 0) { goto next; } if (ngx_strncasecmp(name, (u_char *) "rtmp://", 7)) { *ngx_cpymem(v->name, name, rc) = 0; ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "notify: play redirect to '%s'", v->name); goto next; } /* pull */ nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); if (nacf->relay_redirect) { ngx_rtmp_notify_set_name(v->name, NGX_RTMP_MAX_NAME, name, (size_t) rc); } ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "notify: pull '%s' from '%*s'", v->name, rc, name); local_name.data = v->name; local_name.len = ngx_strlen(v->name); ngx_memzero(&target, sizeof(target)); u = &target.url; u->url = local_name; u->url.data = name + 7; u->url.len = rc - 7; u->default_port = 1935; u->uri_part = 1; u->no_resolve = 1; /* want ip here */ if (ngx_parse_url(s->connection->pool, u) != NGX_OK) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "notify: pull failed '%V'", &local_name); return NGX_ERROR; } ngx_rtmp_relay_pull(s, &local_name, &target); next: return next_play(s, v); }
static ngx_buf_t * ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx) { int len, rc, doc_type; u_char *type, *encoding; ngx_buf_t *b; ngx_uint_t i; xmlChar *buf; xmlDocPtr doc, res; ngx_http_xslt_sheet_t *sheet; ngx_http_xslt_filter_loc_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); sheet = conf->sheets.elts; doc = ctx->doc; /* preallocate array for 4 params */ if (ngx_array_init(&ctx->params, r->pool, 4 * 2 + 1, sizeof(char *)) != NGX_OK) { xmlFreeDoc(doc); return NULL; } for (i = 0; i < conf->sheets.nelts; i++) { ctx->transform = xsltNewTransformContext(sheet[i].stylesheet, doc); if (ctx->transform == NULL) { xmlFreeDoc(doc); return NULL; } if (conf->params && ngx_http_xslt_params(r, ctx, conf->params, 0) != NGX_OK) { xsltFreeTransformContext(ctx->transform); xmlFreeDoc(doc); return NULL; } if (ngx_http_xslt_params(r, ctx, &sheet[i].params, 1) != NGX_OK) { xsltFreeTransformContext(ctx->transform); xmlFreeDoc(doc); return NULL; } res = xsltApplyStylesheetUser(sheet[i].stylesheet, doc, ctx->params.elts, NULL, NULL, ctx->transform); xsltFreeTransformContext(ctx->transform); xmlFreeDoc(doc); if (res == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xsltApplyStylesheet() failed"); return NULL; } doc = res; /* reset array elements */ ctx->params.nelts = 0; } /* there must be at least one stylesheet */ if (r == r->main) { type = ngx_http_xslt_content_type(sheet[i - 1].stylesheet); } else { type = NULL; } encoding = ngx_http_xslt_encoding(sheet[i - 1].stylesheet); doc_type = doc->type; ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xslt filter type: %d t:%s e:%s", doc_type, type ? type : (u_char *) "(null)", encoding ? encoding : (u_char *) "(null)"); rc = xsltSaveResultToString(&buf, &len, doc, sheet[i - 1].stylesheet); xmlFreeDoc(doc); if (rc != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xsltSaveResultToString() failed"); return NULL; } if (len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xsltSaveResultToString() returned zero-length result"); return NULL; } b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { ngx_free(buf); return NULL; } b->pos = buf; b->last = buf + len; b->memory = 1; if (encoding) { r->headers_out.charset.len = ngx_strlen(encoding); r->headers_out.charset.data = encoding; } if (r != r->main) { return b; } b->last_buf = 1; if (type) { len = ngx_strlen(type); r->headers_out.content_type_len = len; r->headers_out.content_type.len = len; r->headers_out.content_type.data = type; } else if (doc_type == XML_HTML_DOCUMENT_NODE) { r->headers_out.content_type_len = sizeof("text/html") - 1; ngx_str_set(&r->headers_out.content_type, "text/html"); } r->headers_out.content_type_lowcase = NULL; return b; }
ngx_int_t ngx_http_lua_cache_loadfile(lua_State *L, const u_char *script, const u_char *cache_key, char **err, unsigned enabled) { int rc; u_char *p; u_char buf[NGX_HTTP_LUA_FILE_KEY_LEN + 1]; /* calculate digest of script file path */ dd("code cache enabled: %d", (int) enabled); if (enabled) { if (cache_key == NULL) { dd("CACHE file key not pre-calculated...calculating"); p = ngx_copy(buf, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN); p = ngx_http_lua_digest_hex(p, script, ngx_strlen(script)); *p = '\0'; cache_key = buf; } else { dd("CACHE file key already pre-calculated"); } dd("XXX cache key for file: [%s]", cache_key); if (ngx_http_lua_cache_load_code(L, (char *) cache_key) == NGX_OK) { /* code chunk loaded from cache, sp++ */ dd("Code cache hit! cache key='%s', stack top=%d, file path='%s'", cache_key, lua_gettop(L), script); return NGX_OK; } dd("Code cache missed! cache key='%s', stack top=%d, file path='%s'", cache_key, lua_gettop(L), script); } /* load closure factory of script file to the top of lua stack, sp++ */ rc = ngx_http_lua_clfactory_loadfile(L, (char *) script); if (rc != 0) { /* Oops! error occured when loading Lua script */ if (rc == LUA_ERRMEM) { *err = "memory allocation error"; } else { if (lua_isstring(L, -1)) { *err = (char *) lua_tostring(L, -1); } else { *err = "unknown error"; } } return NGX_ERROR; } if (enabled) { /* store closure factory and gen new closure at the top of lua stack * to code cache */ rc = ngx_http_lua_cache_store_code(L, (char *) cache_key); if (rc != NGX_OK) { *err = "fail to generate new closure from the closure factory"; return NGX_ERROR; } } else { /* call closure factory to generate new closure */ rc = lua_pcall(L, 0, 1, 0); if (rc != 0) { dd("Error: failed to call closure factory!!"); return NGX_ERROR; } ngx_http_lua_clear_package_loaded(L); } return NGX_OK; }