void ngx_pipe_do_rollback(ngx_cycle_t *cycle, ngx_pipe_rollback_conf_t *rbcf) { int fd; struct flock lock; int ret; ngx_int_t i; ngx_file_info_t sb; ngx_int_t need_do = 0; fd = ngx_open_file(rbcf->logname, NGX_FILE_RDWR, NGX_FILE_OPEN, 0); if (fd < 0) { //open lock file failed just no need rollback return; } lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; ret = fcntl(fd, F_SETLKW, &lock); if (ret < 0) { ngx_close_file(fd); //lock failed just no need rollback return; } //check time if (rbcf->interval >= 0) { if (ngx_file_info(rbcf->backup[0], &sb) == -1) { need_do = 1; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need rollback [%s]: cannot open backup", rbcf->logname); } else if (sb.st_ctime / rbcf->interval < ngx_time() / rbcf->interval) { need_do = 1; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need rollback [%s]: time on [%d] [%d]", rbcf->logname, sb.st_ctime, rbcf->time_now); } else { ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "no need rollback [%s]: time not on [%d] [%d]", rbcf->logname, sb.st_ctime, rbcf->time_now); } } else { ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "no need check rollback [%s] time: no interval", rbcf->logname); } //check size if (rbcf->log_max_size > 0) { if (ngx_file_info(rbcf->logname, &sb) == 0 && (sb.st_size >= rbcf->log_max_size)) { need_do = 1; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need rollback [%s]: size on [%d]", rbcf->logname, sb.st_size); } else { ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "no need rollback [%s]: size not on", rbcf->logname); } } else { ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "no need check rollback [%s] size: no max size", rbcf->logname); } if (need_do) { for (i = 1; i < rbcf->backup_num; i++) { ngx_rename_file(rbcf->backup[rbcf->backup_num - i - 1], rbcf->backup[rbcf->backup_num - i]); } if (ngx_rename_file(rbcf->logname, rbcf->backup[0]) < 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "rname %s to %s failed", rbcf->logname, rbcf->backup[0]); } else { ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "rollback [%s] success", rbcf->logname); } } ngx_close_file(fd); }
static ngx_int_t ngx_http_filetransfer_handler2(ngx_http_request_t *r) { //必须是GET或者HEAD方法,否则返回405 Not Allowed if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } //丢弃请求中的包体 ngx_int_t rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } ngx_str_t type = ngx_string("text/html"); //返回的包体内容 //设置返回状态码 r->headers_out.status = NGX_HTTP_OK; //响应包是有包体内容的,需要设置Content-Length长度 //设置Content-Type r->headers_out.content_type = type; //发送HTTP头部 rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } ngx_buf_t *b; b = ngx_palloc(r->pool, sizeof(ngx_buf_t)); b->in_file=1; u_char* filename = (u_char*)"/usr/local/nginx/html/Google.html"; b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); b->file->fd = ngx_open_file(filename, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0); b->file->log = r->connection->log; b->file->name.data = filename; b->file->name.len = sizeof(filename)-1; if (b->file->fd <= 0) { return NGX_HTTP_NOT_FOUND; } if (ngx_file_info(filename, &b->file->info) == NGX_FILE_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->headers_out.content_length_n = b->file->info.st_size; b->file_pos = 0; b->file_last = b->file->info.st_size; ngx_pool_cleanup_t* cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t)); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_pool_cleanup_file; ngx_pool_cleanup_file_t *clnclnf = cln->data; clnclnf->fd = b->file->fd; clnclnf->name = b->file->name.data; clnclnf->log = r->pool->log; //构造发送时的ngx_chain_t结构体 ngx_chain_t out; //赋值ngx_buf_t out.buf = b; //设置next为NULL out.next = NULL; return ngx_http_output_filter(r, &out); }
// 初始化日志 ngx_log_t * ngx_log_init(u_char *prefix) { u_char *p, *name; size_t nlen, plen; // 初始化为notice级别,即只有warn,error等才能记录日志 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_int_t ngx_log_open_default(ngx_cycle_t *cycle) { ngx_log_t *log; static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH); if (ngx_log_get_file_log(&cycle->new_log) != NULL) { return NGX_OK; } if (cycle->new_log.log_level != 0) { /* there are some error logs, but no files */ log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t)); if (log == NULL) { return NGX_ERROR; } } else { /* no error logs at all */ log = &cycle->new_log; } log->log_level = NGX_LOG_ERR; log->file = ngx_conf_open_file(cycle, &error_log); if (log->file == NULL) { return NGX_ERROR; } if (log != &cycle->new_log) { ngx_log_insert(&cycle->new_log, log); } return NGX_OK; }
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; 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; } if (file[i].flush) { file[i].flush(&file[i], cycle->log); } 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_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); continue; } #if !(NGX_WIN32) if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; if (ngx_file_info((const char *) file[i].name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (fi.st_uid != user) { if (chown((const char *) file[i].name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR); if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } } if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #endif if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } file[i].fd = fd; } (void) ngx_log_redirect_stderr(cycle); }
ngx_int_t ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf) { char *buf; off_t size; size_t len; ssize_t n; ngx_fd_t fd, nfd; ngx_int_t rc; ngx_file_info_t fi; rc = NGX_ERROR; buf = NULL; nfd = NGX_INVALID_FILE; fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno, ngx_open_file_n " \"%s\" failed", from); goto failed; } if (cf->size != -1) { size = cf->size; } else { if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", from); goto failed; } size = ngx_file_size(&fi); } len = cf->buf_size ? cf->buf_size : 65536; if ((off_t) len > size) { len = (size_t) size; } buf = ngx_alloc(len, cf->log); if (buf == NULL) { goto failed; } nfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, cf->access); if (nfd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno, ngx_open_file_n " \"%s\" failed", to); goto failed; } while (size > 0) { if ((off_t) len > size) { len = (size_t) size; } n = ngx_read_fd(fd, buf, len); if (n == -1) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_read_fd_n " \"%s\" failed", from); goto failed; } if ((size_t) n != len) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, ngx_read_fd_n " has read only %z of %O from %s", n, size, from); goto failed; } n = ngx_write_fd(nfd, buf, len); if (n == -1) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_write_fd_n " \"%s\" failed", to); goto failed; } if ((size_t) n != len) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, ngx_write_fd_n " has written only %z of %O to %s", n, size, to); goto failed; } size -= n; } if (cf->time != -1) { if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_set_file_time_n " \"%s\" failed", to); goto failed; } } rc = NGX_OK; failed: if (nfd != NGX_INVALID_FILE) { if (ngx_close_file(nfd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " \"%s\" failed", to); } } if (fd != NGX_INVALID_FILE) { if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " \"%s\" failed", from); } } if (buf) { ngx_free(buf); } return rc; }
ngx_int_t ngx_http_small_light_imlib2_process(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_imlib2_ctx_t *ictx; ngx_http_small_light_image_size_t sz; Imlib_Image image_org, image_dst, image_tmp; Imlib_Load_Error err; ngx_file_info_t fi; ngx_fd_t fd; char *filename, *sharpen, *blur, *of, *buf; void *data; int w, h, radius, orientation; double iw, ih, q; ngx_int_t type; const char *ext; ssize_t size; ictx = (ngx_http_small_light_imlib2_ctx_t *)ctx->ictx; filename = (char *)ictx->tf->file.name.data; /* adjust image size */ ngx_http_small_light_calc_image_size(r, ctx, &sz, 10000.0, 10000.0); if (sz.jpeghint_flg != 0 && sz.dw != NGX_HTTP_SMALL_LIGHT_COORD_INVALID_VALUE && sz.dh != NGX_HTTP_SMALL_LIGHT_COORD_INVALID_VALUE) { if (ngx_http_small_light_load_jpeg((void**)&data, &w, &h, r, filename, sz.dw, sz.dh) != NGX_OK) { image_org = imlib_load_image_immediately_without_cache(filename); if (image_org == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to load image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } } else { image_org = imlib_create_image_using_data(w, h, data); } } else { image_org = imlib_load_image_immediately_without_cache(filename); if (image_org == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to load image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } } /* rotate. */ if (sz.angle) { orientation = 0; switch (sz.angle) { case 90: orientation = 1; break; case 180: orientation = 2; break; case 270: orientation = 3; break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image not rotated. 'angle'(%ui) must be 90 or 180 or 270. %s:%d", sz.angle, __FUNCTION__, __LINE__); break; } imlib_context_set_image(image_org); imlib_image_orientate(orientation); } /* calc size. */ imlib_context_set_image(image_org); iw = (double)imlib_image_get_width(); ih = (double)imlib_image_get_height(); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); /* pass through. */ if (sz.pt_flg != 0) { ctx->of = ctx->inf; return NGX_OK; } /* adjust destination size */ if (sz.dw == NGX_HTTP_SMALL_LIGHT_COORD_INVALID_VALUE) { sz.dw = sz.sw; } if (sz.dh == NGX_HTTP_SMALL_LIGHT_COORD_INVALID_VALUE) { sz.dh = sz.sh; } /* crop, scale. */ if (sz.scale_flg != 0) { image_dst = imlib_create_cropped_scaled_image((int)sz.sx, (int)sz.sy, (int)sz.sw, (int)sz.sh, (int)sz.dw, (int)sz.dh); imlib_context_set_image(image_org); imlib_free_image(); } else { image_dst = image_org; } if (image_dst == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "imlib_create_cropped_scaled_image failed. %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } /* create canvas then draw image to the canvas. */ if (sz.cw > 0.0 && sz.ch > 0.0) { image_tmp = imlib_create_image(sz.cw, sz.ch); if (image_tmp == NULL) { imlib_context_set_image(image_dst); imlib_free_image(); return NGX_ERROR; } imlib_context_set_image(image_tmp); imlib_context_set_color(sz.cc.r, sz.cc.g, sz.cc.b, sz.cc.a); imlib_image_fill_rectangle(0, 0, sz.cw, sz.ch); ngx_http_small_light_adjust_canvas_image_offset(&sz); imlib_blend_image_onto_image(image_dst, 255, 0, 0, (int)sz.dw, (int)sz.dh, (int)sz.dx, (int)sz.dy, (int)sz.dw, (int)sz.dh); imlib_context_set_image(image_dst); imlib_free_image(); image_dst = image_tmp; } /* effects. */ sharpen = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "sharpen"); if (ngx_strlen(sharpen) > 0) { radius = ngx_http_small_light_parse_int(sharpen); if (radius > 0 && radius <= (int)ctx->radius_max) { imlib_context_set_image(image_dst); imlib_image_sharpen(radius); } else { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "As sharpen geometry is out of range, ignored. %s:%d", __FUNCTION__, __LINE__); } } blur = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "blur"); if (ngx_strlen(blur) > 0) { radius = ngx_http_small_light_parse_int(blur); if (radius > 0 && radius <= (int)ctx->radius_max) { imlib_context_set_image(image_dst); imlib_image_blur(radius); } else { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "As blur geometry is out of range, ignored. %s:%d", __FUNCTION__, __LINE__); } } /* border. */ if (sz.bw > 0.0 || sz.bh > 0.0) { imlib_context_set_color(sz.bc.r, sz.bc.g, sz.bc.b, sz.bc.a); imlib_context_set_image(image_dst); if (sz.cw > 0.0 && sz.ch > 0.0) { imlib_image_fill_rectangle(0, 0, sz.cw, sz.bh); imlib_image_fill_rectangle(0, 0, sz.bw, sz.ch); imlib_image_fill_rectangle(0, sz.ch - sz.bh, sz.cw, sz.bh); imlib_image_fill_rectangle(sz.cw - sz.bw, 0, sz.bw, sz.ch); } else { imlib_image_fill_rectangle(0, 0, sz.dw, sz.bh); imlib_image_fill_rectangle(0, 0, sz.bw, sz.ch); imlib_image_fill_rectangle(0, sz.dh - sz.bh, sz.dw, sz.bh); imlib_image_fill_rectangle(sz.dw - sz.bw, 0, sz.bw, sz.dh); } } /* set params. */ imlib_context_set_image(image_dst); q = ngx_http_small_light_parse_double(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "q")); if (q > 0.0) { imlib_image_attach_data_value("quality", NULL, q, NULL); } of = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "of"); if (ngx_strlen(of) > 0) { type = ngx_http_small_light_type(of); if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "of is invalid(%s) %s:%d", of, __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_WEBP) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "WebP is not supported %s:%d", __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else { ictx->type = type; } imlib_image_set_format(of); ctx->of = ngx_http_small_light_image_types[ictx->type - 1]; } else { ext = ngx_http_small_light_image_exts[ictx->type - 1]; imlib_image_set_format(ext); ctx->of = ctx->inf; } /* save image. */ imlib_save_image_with_error_return(filename, &err); imlib_free_image(); /* check error. */ if (err != IMLIB_LOAD_ERROR_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to imlib_save_error %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_file_info(filename, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_file_info %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } fd = ngx_open_file(filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to open fd %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_fd_info %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } buf = ngx_palloc(r->pool, ngx_file_size(&fi)); if (buf == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } size = ngx_read_fd(fd, buf, ngx_file_size(&fi)); if (size == -1) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to ngx_read_fd %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } if ((size_t)size > ctx->content_length) { ctx->content = ngx_palloc(r->pool, size); if (ctx->content == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); ngx_close_file(fd); return NGX_ERROR; } } ngx_memcpy(ctx->content, buf, size); ngx_close_file(fd); ctx->content_length = size; return NGX_OK; }
//http://blog.csdn.net/lengzijian/article/details/7575813 ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; char **senv, **env; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; ngx_conf_t conf; ngx_pool_t *pool; ngx_cycle_t *cycle, **old; ngx_shm_zone_t *shm_zone, *oshm_zone; ngx_list_part_t *part, *opart; ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday(); tp->sec = 0; ngx_time_update(); log = old_cycle->log; pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } pool->log = log; cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pool = pool; cycle->log = log; cycle->old_cycle = old_cycle; cycle->conf_prefix.len = old_cycle->conf_prefix.len; cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->prefix.len = old_cycle->prefix.len; cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_file.len = old_cycle->conf_file.len; cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); if (cycle->conf_file.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, old_cycle->conf_file.len + 1); cycle->conf_param.len = old_cycle->conf_param.len; cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); if (cycle->conf_param.data == NULL) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->paths.nelts = 0; cycle->paths.size = sizeof(ngx_path_t *); cycle->paths.nalloc = n; cycle->paths.pool = pool; if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } //ngx_list_init主要是初始链表的elts,并为其申请内存 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_connection_t 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); //调用全部NGX_CORE_MODULE的create_conf构建配置结构体。并保存在conf_ctx数组里面 for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { //event 和http 和core 三个module continue; } //上下文操作 //static ngx_core_module_t ngx_events_module_ctx = { //ngx_string("events"), //NULL, //ngx_event_init_conf //}; //static ngx_core_module_t ngx_http_module_ctx = { //ngx_string("http"), //NULL, //NULL //}; //static ngx_core_module_t ngx_core_module_ctx = { // ngx_string("core"), //ngx_core_module_create_conf, // ngx_core_module_init_conf //}; // module = ngx_modules[i]->ctx; //core module 模块只有create 和 init 两个回调函数 其他 if (module->create_conf) { // rv 返回ngx_core_conf_t rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ngx_modules[i]->index] = rv; //倒数第二级指针存放的是每个模块的create-conf 的指针 } } senv = environ; 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 //2.4从命令行和配置文件里把全部配置更新到cycle的conf_ctx中:首先调用ngx_conf_param把命令行中的指令(-g directives)转换为配置结构并把指针增加到cycle.conf_ctx中;接着调用ngx_conf_parse(..,filename)把配置文件里的指令转换为配置结构并把指针增加到cycle.conf_ctx中。 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); } //2.5调用全部核心模块的init函数初始化全部核心模块的配置结构体 for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) {//调用模块的init_conf初始化全部核心模块的配置结构体 if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle; } //2.6获得核心模块ngx_core_dodule的配置结构,然后调用ngx_create_pidfile创建pid文件 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 */ //2.8打开新文件,在第2步的时候提到cycle->open_files这个链表是空的。仅仅是给它预先分配了空间,并没有数据。这里之所以可能会有文件被打开,预计是前面读配置文件的时候,调用各个钩子的过程中,填充了这个链表,把ngx_open_file_t结构变量填充进来(结构体中包括要打开文件的路径信息),接着改动一下cycle的成员:cycle->log = &cycle->new_log;pool->log = &cycle->new_log; //2.9创建共享内存,和open_files类似,在第2步的时候cycle->share_memory也初始化为一个空的链表。也是预分配了空间,假设此时链表中已经被填充了ngx_shm_zone_t结构变量(当中包括须要共享内存的尺寸和标识等信息)。那么这里就会分配共享内存,而且调用合适的初始化钩子初始化分配的共享内存,每块共享内存都会有name标识。这里也会做一些排重,已经分配的就不会再去分配。从对open_files和share_memory的处理过程能够看出,nginx在资源管理上是集中分配的,请求资源的时候分配说明性的结构变量,然后在恰当的时机才去真正分配资源。 //2.10处理listening sockets,cycle->listening是ngx_listening_t结构的数组。把cycle->listening于old_cycle->listening进行比較。设置cycle->listening的一些状态信息。接着调用ngx_open_listening_sockets(cycle)启动cycle->listening中的全部监听socket,循环调用socket,bind,listen完毕服务端监听socket的启动。接着调用ngx_configure_listening_sockets(cycle)配置监听socket。会依据ngx_listening_t中的状态信息设置socket的读写缓存和TCP_DEFER_ACCEPT。 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) {//标识位为1表示跳过设置ngx_lisenting_t中的套接字。 continue; //为0表示正常初始化套接字 } 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 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 } } //在ngx_open_listening_sockets函数的代码中可以看到bind、 //listen等套接字函数的调用。最终创建完的监听套接字就在 //cycle结构体的listening域里 主程序中完成socket的基础设置,完成监听操作。 if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } if (!ngx_test_config) { ngx_configure_listening_sockets(cycle); } /* commit the new cycle configuration */ if (!ngx_use_stderr) { (void) ngx_log_redirect_stderr(cycle); } pool->log = cycle->log; for (i = 0; ngx_modules[i]; i++) {// 调用全部模块的init_module if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } /* close and delete stuff that lefts from an old cycle */ /* free the unnecessary shared memory */ opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (i = 0; /* void */ ; i++) { if (i >= opart->nelts) { if (opart->next == NULL) { goto old_shm_zone_done; } opart = opart->next; oshm_zone = opart->elts; i = 0; } part = &cycle->shared_memory.part; shm_zone = part->elts; for (n = 0; /* void */ ; n++) { if (n >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; n = 0; } if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len && ngx_strncmp(oshm_zone[i].shm.name.data, shm_zone[n].shm.name.data, oshm_zone[i].shm.name.len) == 0) { goto live_shm_zone; } } ngx_shm_free(&oshm_zone[i].shm); live_shm_zone: continue; } old_shm_zone_done: /* close the unnecessary listening sockets */ ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].remain || ls[i].fd == (ngx_socket_t) -1) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " listening socket on %V failed", &ls[i].addr_text); } #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX) { u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - 1; ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "deleting socket %s", name); if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } } #endif } /* close the unnecessary open files */ part = &old_cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } ngx_destroy_pool(conf.temp_pool); if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { /* * perl_destruct() frees environ, if it is not the same as it was at * perl_construct() time, therefore we save the previous cycle * environment before ngx_conf_parse() where it will be changed. */ env = environ; environ = senv; ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; environ = env; return cycle; } if (ngx_temp_pool == NULL) { ngx_temp_pool = ngx_create_pool(128, cycle->log); if (ngx_temp_pool == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "could not create ngx_temp_pool"); exit(1); } n = 10; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { exit(1); } ngx_old_cycles.nelts = 0; ngx_old_cycles.size = sizeof(ngx_cycle_t *); ngx_old_cycles.nalloc = n; ngx_old_cycles.pool = ngx_temp_pool; ngx_cleaner_event.handler = ngx_clean_old_cycles; ngx_cleaner_event.log = cycle->log; ngx_cleaner_event.data = &dumb; dumb.fd = (ngx_socket_t) -1; } ngx_temp_pool->log = cycle->log; old = ngx_array_push(&ngx_old_cycles); if (old == NULL) { exit(1); } *old = old_cycle; if (!ngx_cleaner_event.timer_set) { ngx_add_timer(&ngx_cleaner_event, 30000); ngx_cleaner_event.timer_set = 1; } return cycle; failed: if (!ngx_is_init_cycle(old_cycle)) { old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (old_ccf->environment) { environ = old_ccf->environment; } } /* rollback the new cycle configuration */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; } ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { if (ls[i].fd == (ngx_socket_t) -1 || !ls[i].open) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } } ngx_destroy_cycle_pools(&conf); return NULL; }
static char * ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_js_loc_conf_t *jlcf = conf; size_t size; u_char *start, *end; ssize_t n; ngx_fd_t fd; ngx_str_t *value, file; nxt_int_t rc; nxt_str_t text, ext, *export; nxt_lvlhsh_t externals; ngx_file_info_t fi; njs_vm_shared_t *shared; ngx_pool_cleanup_t *cln; nxt_mem_cache_pool_t *mcp; if (jlcf->vm) { return "is duplicate"; } value = cf->args->elts; file = value[1]; if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } fd = ngx_open_file(file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", file.data); return NGX_CONF_ERROR; } if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", file.data); (void) ngx_close_file(fd); return NGX_CONF_ERROR; } size = ngx_file_size(&fi); start = ngx_pnalloc(cf->pool, size); if (start == NULL) { (void) ngx_close_file(fd); return NGX_CONF_ERROR; } n = ngx_read_fd(fd, start, size); if (n == -1) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_read_fd_n " \"%s\" failed", file.data); (void) ngx_close_file(fd); return NGX_CONF_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, ngx_read_fd_n " has read only %z of %O from \"%s\"", n, size, file.data); (void) ngx_close_file(fd); return NGX_CONF_ERROR; } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " %s failed", file.data); } end = start + size; mcp = ngx_http_js_create_mem_cache_pool(); if (mcp == NULL) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NULL; } cln->handler = ngx_http_js_cleanup_mem_cache_pool; cln->data = mcp; shared = NULL; nxt_lvlhsh_init(&externals); if (njs_vm_external_add(&externals, mcp, 0, ngx_http_js_externals, nxt_nitems(ngx_http_js_externals)) != NJS_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "could not add js externals"); return NGX_CONF_ERROR; } jlcf->vm = njs_vm_create(mcp, &shared, &externals); if (jlcf->vm == NULL) { return NGX_CONF_ERROR; } rc = njs_vm_compile(jlcf->vm, &start, end, NULL, &export); if (rc != NJS_OK) { njs_vm_exception(jlcf->vm, &text); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%*s, included", text.length, text.start); return NGX_CONF_ERROR; } if (start != end) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "extra characters in js script: \"%*s\", included", end - start, start); return NGX_CONF_ERROR; } ext = nxt_string_value("$r"); if (njs_vm_external(jlcf->vm, NULL, &ext, &jlcf->args[0]) != NJS_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "js external \"%*s\" not found", ext.length, ext.start); return NGX_CONF_ERROR; } ext = nxt_string_value("response"); rc = njs_vm_external(jlcf->vm, &jlcf->args[0], &ext, &jlcf->args[1]); if (rc != NXT_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "js external \"$r.%*s\" not found", ext.length, ext.start); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
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_int_t ngx_log_open_default(ngx_cycle_t *cycle) { static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH); if (cycle->new_log.file == NULL) { cycle->new_log.file = ngx_conf_open_file(cycle, &error_log); if (cycle->new_log.file == NULL) { return NGX_ERROR; } cycle->new_log.log_level = NGX_LOG_ERR; } return NGX_OK; } ngx_int_t ngx_log_redirect_stderr(ngx_cycle_t *cycle) { ngx_fd_t fd; if (cycle->log_use_stderr) { return NGX_OK; } fd = cycle->log->file->fd; if (fd != ngx_stderr) { if (ngx_set_stderr(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_set_stderr_n " failed"); return NGX_ERROR; } } return NGX_OK; }
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ssize_t n, len; ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; 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;//如果还有,标记i = 0,重新来 file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } len = file[i].pos - file[i].buffer; if (file[i].buffer && len != 0) {//要写进去吗,确认? n = ngx_write_fd(file[i].fd, file[i].buffer, len); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_write_fd_n " to \"%s\" failed", file[i].name.data); } else if (n != len) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", file[i].name.data, n, len); } file[i].pos = file[i].buffer; } //再次打开以下这个文件 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_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); continue; } #if !(NGX_WIN32)//如果是unix系的操作系统,需要设置文件拥有者啥的 if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; //得到文件的信息 if (ngx_file_info((const char *) file[i].name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } //修改文件所有者 if (fi.st_uid != user) { if (chown((const char *) file[i].name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } //修改文件权限 if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR); if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } } if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #endif if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {//关闭掉老的文件句柄 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed",file[i].name.data); } //赋值为新的文件句柄。放心吧,没有别的地方使用这个fd的,就我一个进程,多线程版本不在此 file[i].fd = fd; } #if !(NGX_WIN32) if (cycle->log->file->fd != STDERR_FILENO) {//int dup2(int oldfd, int newfd); if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {//标准错误输出也设置为日志.那程序的fprint(stderr,)将输出到日志文件 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,"dup2(STDERR) failed"); } } #endif }
char * ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { char *rv; u_char *p; off_t size; ngx_fd_t fd; ngx_int_t rc; ngx_buf_t buf, *tbuf; ngx_conf_file_t *prev, conf_file; ngx_conf_dump_t *cd; enum { parse_file = 0, parse_block, parse_param } type; #if (NGX_SUPPRESS_WARN) fd = NGX_INVALID_FILE; prev = NULL; #endif if (filename) { /* open configuration file */ //打开配置文件 fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", filename->data); return NGX_CONF_ERROR; } prev = cf->conf_file; cf->conf_file = &conf_file; if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", filename->data); } cf->conf_file->buffer = &buf; buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log); if (buf.start == NULL) { goto failed; } buf.pos = buf.start; buf.last = buf.start; buf.end = buf.last + NGX_CONF_BUFFER; buf.temporary = 1; cf->conf_file->file.fd = fd; cf->conf_file->file.name.len = filename->len; cf->conf_file->file.name.data = filename->data; cf->conf_file->file.offset = 0; cf->conf_file->file.log = cf->log; cf->conf_file->line = 1; type = parse_file; if (ngx_dump_config #if (NGX_DEBUG) || 1 #endif ) { p = ngx_pstrdup(cf->cycle->pool, filename); if (p == NULL) { goto failed; } size = ngx_file_size(&cf->conf_file->file.info); tbuf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size); if (tbuf == NULL) { goto failed; } cd = ngx_array_push(&cf->cycle->config_dump); if (cd == NULL) { goto failed; } cd->name.len = filename->len; cd->name.data = p; cd->buffer = tbuf; cf->conf_file->dump = tbuf; } else { cf->conf_file->dump = NULL; } } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) { type = parse_block; } else { type = parse_param; } for ( ;; ) { rc = ngx_conf_read_token(cf); /* * ngx_conf_read_token() may return * * NGX_ERROR there is error * NGX_OK the token terminated by ";" was found * NGX_CONF_BLOCK_START the token terminated by "{" was found * NGX_CONF_BLOCK_DONE the "}" was found * NGX_CONF_FILE_DONE the configuration file is done */ if (rc == NGX_ERROR) { goto done; } if (rc == NGX_CONF_BLOCK_DONE) { if (type != parse_block) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\""); goto failed; } goto done; } if (rc == NGX_CONF_FILE_DONE) { if (type == parse_block) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected end of file, expecting \"}\""); goto failed; } goto done; } if (rc == NGX_CONF_BLOCK_START) { if (type == parse_param) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "block directives are not supported " "in -g option"); goto failed; } } /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */ if (cf->handler) { /* * the custom handler, i.e., that is used in the http's * "types { ... }" directive */ if (rc == NGX_CONF_BLOCK_START) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\""); goto failed; } rv = (*cf->handler)(cf, NULL, cf->handler_conf); if (rv == NGX_CONF_OK) { continue; } if (rv == NGX_CONF_ERROR) { goto failed; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv); goto failed; } rc = ngx_conf_handler(cf, rc); if (rc == NGX_ERROR) { goto failed; } } failed: rc = NGX_ERROR; done: if (filename) { if (cf->conf_file->buffer->start) { ngx_free(cf->conf_file->buffer->start); } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " %s failed", filename->data); rc = NGX_ERROR; } cf->conf_file = prev; } if (rc == NGX_ERROR) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
/* 加载配置文件,并回调create_conf,init_conf, init_module等; 初始化各个配置,并打开监听端口,设置优化选项; */ ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) {//整个程序的主要初始化,配置加载,解析,各个模块的初始化回调函数,指令的set回调函数调用,监听端口打开,共享内存申请等等都在这里. void *rv; char **senv, **env; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; ngx_conf_t conf; ngx_pool_t *pool; ngx_cycle_t *cycle, **old; ngx_shm_zone_t *shm_zone, *oshm_zone; ngx_list_part_t *part, *opart; ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday();//k : ngx_cached_time tp->sec = 0;//秒设置为0 ngx_time_update();//迫使当前的缓存时间更新。 log = old_cycle->log; pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } pool->log = log; cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));//下一个过程吗 if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pool = pool;//cycle也是包含在pool里面的! ,也就是,释放了cycle->pool后,cycle也释放了 cycle->log = log; cycle->new_log.log_level = NGX_LOG_ERR; cycle->old_cycle = old_cycle; //下面拷贝一下旧的配置路径什么的,参数等到新的cycle cycle->conf_prefix.len = old_cycle->conf_prefix.len; cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->prefix.len = old_cycle->prefix.len; cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_file.len = old_cycle->conf_file.len; cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); if (cycle->conf_file.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, old_cycle->conf_file.len + 1); cycle->conf_param.len = old_cycle->conf_param.len; cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); if (cycle->conf_param.data == NULL) { ngx_destroy_pool(pool); return NULL; } //干嘛的? n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10; cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->pathes.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pathes.nelts = 0; cycle->pathes.size = sizeof(ngx_path_t *); cycle->pathes.nalloc = n; cycle->pathes.pool = pool; if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } //拷贝共享内存 if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } //拷贝一下监听端口的信息; n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->listening.nelts = 0; cycle->listening.size = sizeof(ngx_listening_t); cycle->listening.nalloc = n; cycle->listening.pool = pool; //为每个模块分配一个配置上下文指针,用来保存每个模块设置的配置数据 cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); ngx_destroy_pool(pool); return NULL; } /* on Linux gethostname() silently truncates name that does not fit */ hostname[NGX_MAXHOSTNAMELEN - 1] = '\0'; cycle->hostname.len = ngx_strlen(hostname); cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len); if (cycle->hostname.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); //k:for core modules. for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } //对于核心模块 module = ngx_modules[i]->ctx; if (module->create_conf) {//如果核心模块设置了create_conf回调,则调用它们 rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ ngx_modules[i]->index ] = rv;//帮模块们保存create_conf返回的数据。后续可以方便取到 } } senv = environ;//保留老的environ,这个环境变量已经被我们拷贝到了新地址的 ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; } conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (conf.temp_pool == NULL) { ngx_destroy_pool(pool); return NULL; } //切换到新的配置 conf.ctx = cycle->conf_ctx; conf.cycle = cycle; conf.pool = pool; conf.log = log; conf.module_type = NGX_CORE_MODULE; conf.cmd_type = NGX_MAIN_CONF; #if 0 log->log_level = NGX_LOG_DEBUG_ALL; #endif if (ngx_conf_param(&conf) != NGX_CONF_OK) {//调用ngx_conf_parse解析全局指令,貌似是做参数准备的。 environ = senv;//还原老的environ,因为perl会改变它 ngx_destroy_cycle_pools(&conf); return NULL; } //解析配置文件,调用各个配置文件的set函数等。 if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_test_config && !ngx_quiet_mode) {//这就是经典的那个-t参数啦 ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } for (i = 0; ngx_modules[i]; i++) { //刚才各个配置指令已经调用了其set函数的。下面调用一下每个模块的init_conf,也就是每个模块的各个指令已经设置,现在开始模块本身了。 if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } //对于NGX_CORE_MODULE,调用它他们的init_conf回调 module = ngx_modules[i]->ctx;//得到模块初始化设置的数据,然后调用其init_conf if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])== NGX_CONF_ERROR){ //第二个参数是在create_conf回调返回的东西 environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle;//如果是加-s reload等启动的,这里可以返回了。服务需要重启啥的,不是全新启动。在这里设置的ngx_get_options } // 最核心的配置 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);//k conf_ctx[module.index] if (ngx_test_config) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_cycle)) {//第一次调用,old_cycle的配置相关的为空,第二次才是非空的。也就是下面的注释介绍的 /* * we do not create the pid file in the first ngx_init_cycle() call * because we need to write the demonized process pid */ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (ccf->pid.len != old_ccf->pid.len || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) { /* new pid file name */ if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } ngx_delete_pidfile(old_cycle);//删除旧的,这是啥原因,比如配置重新加载吗,文件变了啥的 } } //就打开文件,关闭,然后删除之 if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { goto failed; } //创建这些目录,并设置权限啥的 if (ngx_create_pathes(cycle, ccf->user) != NGX_OK) { goto failed; } if (cycle->new_log.file == NULL) {//找到"logs/error.log"的ngx_open_file_t*结构,不open打开 cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);//"logs/error.log" if (cycle->new_log.file == NULL) { goto failed; } } /* open the new files */ part = &cycle->open_files.part; file = part->elts; //一个个打开这些文件,APPEND模式打开 for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } //真正打开这些文件,append模式 file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d \"%s\"", &file[i], file[i].fd, file[i].name.data); if (file[i].fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); goto failed; } #if !(NGX_WIN32) // 这里设置为FD_CLOEXEC表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程。close-on-exec if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); goto failed; } #endif } cycle->log = &cycle->new_log; pool->log = &cycle->new_log; /* create shared memory */ part = &cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } if (shm_zone[i].shm.size == 0) { ngx_log_error(NGX_LOG_EMERG, log, 0, "zero size shared memory zone \"%V\"", &shm_zone[i].shm.name); goto failed; } if (shm_zone[i].init == NULL) { /* unused shared zone */ continue; } shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (n = 0; /* void */ ; n++) { if (n >= opart->nelts) { if (opart->next == NULL) { break; } opart = opart->next; oshm_zone = opart->elts; n = 0; } if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { continue; } if (ngx_strncmp(shm_zone[i].shm.name.data, oshm_zone[n].shm.name.data, shm_zone[i].shm.name.len) != 0) { continue; } if (shm_zone[i].shm.size == oshm_zone[n].shm.size) { shm_zone[i].shm.addr = oshm_zone[n].shm.addr; if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) != NGX_OK) { goto failed; } goto shm_zone_found; } ngx_shm_free(&oshm_zone[n].shm); break; } if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { goto failed; } if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { goto failed; } shm_zone_found: continue; } /* handle the listening sockets */ if (old_cycle->listening.nelts) {//如果设置了继承SOCK,就拷贝到cycle来 ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { ls[i].remain = 0;//标记为全都不需要了,后面会清除 } nls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].ignore) { continue; } if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) {//如果地址完全相同,那后面就不需要关闭,直接拷贝fd就行了 nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; ls[i].remain = 1; if (ls[n].backlog != nls[i].backlog) { nls[n].listen = 1; } #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /* * FreeBSD, except the most recent versions, * could not remove accept filter */ nls[n].deferred_accept = ls[i].deferred_accept; if (ls[i].accept_filter && nls[n].accept_filter) { if (ngx_strcmp(ls[i].accept_filter, nls[n].accept_filter) != 0) { nls[n].delete_deferred = 1; nls[n].add_deferred = 1; } } else if (ls[i].accept_filter) { nls[n].delete_deferred = 1; } else if (nls[n].accept_filter) { nls[n].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[n].deferred_accept && !nls[n].deferred_accept) { nls[n].delete_deferred = 1; } else if (ls[i].deferred_accept != nls[n].deferred_accept) { nls[n].add_deferred = 1; } #endif break; } } if (nls[n].fd == -1) { nls[n].open = 1; } } } else { ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { ls[i].open = 1; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) if (ls[i].accept_filter) { ls[i].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[i].deferred_accept) { ls[i].add_deferred = 1; } #endif } } //下面一个个打开cycle->listening的listen的端口,并设置为listening端口 //这些监听端口的可读事件是在ngx_event_core_module模块中设置的,其进程初始化函数为ngx_event_process_init里面会放入epoll里面 if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } if (!ngx_test_config) {//如果不是测试配置,设置一下各个优化选项,比如发送,接收缓冲区大小,TCP_DEFER_ACCEPT等 ngx_configure_listening_sockets(cycle); } /* commit the new cycle configuration */ if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_set_stderr_n " failed"); } } pool->log = cycle->log; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) {//对所有模块,调用其init_module回调 if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } /* close and delete stuff that lefts from an old cycle */ /* free the unnecessary shared memory */ opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (i = 0; /* void */ ; i++) { if (i >= opart->nelts) { if (opart->next == NULL) { goto old_shm_zone_done; } opart = opart->next; oshm_zone = opart->elts; i = 0; } part = &cycle->shared_memory.part; shm_zone = part->elts; for (n = 0; /* void */ ; n++) { if (n >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; n = 0; } if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len && ngx_strncmp(oshm_zone[i].shm.name.data, shm_zone[n].shm.name.data, oshm_zone[i].shm.name.len) == 0){ goto live_shm_zone; } } ngx_shm_free(&oshm_zone[i].shm); live_shm_zone: continue; } old_shm_zone_done: /* close the unnecessary listening sockets */ ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].remain || ls[i].fd == -1) { continue;//需要保留或者fd无效,不用删除,因为已经拷贝到cycle中了 } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,ngx_close_socket_n " listening socket on %V failed", &ls[i].addr_text); } #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX) { u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - 1; ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "deleting socket %s", name); if (ngx_delete_file(name) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } } #endif } /* close the unnecessary open files */ part = &old_cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } ngx_destroy_pool(conf.temp_pool); if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) {//ngx_is_init_cycle第一次调用false //这是怎么进来的? /* * perl_destruct() frees environ, if it is not the same as it was at * perl_construct() time, therefore we save the previous cycle * environment before ngx_conf_parse() where it will be changed. */ env = environ; environ = senv;//还原之前保存的环境变量地址 ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; environ = env; return cycle; } if (ngx_temp_pool == NULL) { ngx_temp_pool = ngx_create_pool(128, cycle->log); if (ngx_temp_pool == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "can not create ngx_temp_pool"); exit(1); } n = 10; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { exit(1); } ngx_old_cycles.nelts = 0; ngx_old_cycles.size = sizeof(ngx_cycle_t *); ngx_old_cycles.nalloc = n; ngx_old_cycles.pool = ngx_temp_pool; ngx_cleaner_event.handler = ngx_clean_old_cycles; ngx_cleaner_event.log = cycle->log; ngx_cleaner_event.data = &dumb; dumb.fd = (ngx_socket_t) -1; } ngx_temp_pool->log = cycle->log; old = ngx_array_push(&ngx_old_cycles); if (old == NULL) { exit(1); } *old = old_cycle; if (!ngx_cleaner_event.timer_set) {//如果还没有设置定时器,设置定时器,30秒后清除老的cycle? ngx_add_timer(&ngx_cleaner_event, 30000); ngx_cleaner_event.timer_set = 1;//标记此处已经设置过定时器了。 } return cycle; failed: if (!ngx_is_init_cycle(old_cycle)) { old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (old_ccf->environment) { environ = old_ccf->environment; } } /* rollback the new cycle configuration */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; } ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { if (ls[i].fd == -1 || !ls[i].open) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } } ngx_destroy_cycle_pools(&conf); return NULL; }
char * ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { //第二个数为保存的配置文件路径的字符串,如/usr/local/nginx/conf/nginx.conf_file char *rv; ngx_fd_t fd; ngx_int_t rc; ngx_buf_t buf; ngx_conf_file_t *prev, conf_file; enum { parse_file = 0, parse_block, parse_param } type; #if (NGX_SUPPRESS_WARN) fd = NGX_INVALID_FILE; prev = NULL; #endif if (filename) { //指向一个配置文件路径字符串,需要函数ngx_conf_parse打开该文件并获取相关的文件信息 /* open configuration file */ fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", filename->data); return NGX_CONF_ERROR; } prev = cf->conf_file; cf->conf_file = &conf_file; if (ngx_fd_info(fd, &cf->conf_file->file.info) == -1) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", filename->data); } cf->conf_file->buffer = &buf; buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log); //内存 if (buf.start == NULL) { goto failed; } buf.pos = buf.start; //初始值 buf.last = buf.start; buf.end = buf.last + NGX_CONF_BUFFER; //4K,到末尾 buf.temporary = 1; cf->conf_file->file.fd = fd; cf->conf_file->file.name.len = filename->len; cf->conf_file->file.name.data = filename->data; cf->conf_file->file.offset = 0; cf->conf_file->file.log = cf->log; cf->conf_file->line = 1; type = parse_file; //刚刚打开的新文件,包括include指令 } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) { //说明此时仅解析了部分解析,当遇到复杂配置项,比如events,http等,此时解析的内容还是来自当前文件 type = parse_block; } else { //正要开始解析命令行参数配置项值,在对用户通过命令行-g参数输入的配置信息进行解析,如nginx -g 'daemon on' type = parse_param; } for ( ;; ) { rc = ngx_conf_read_token(cf); //读取token,每次读取一个buffer /* * ngx_conf_read_token() may return * * NGX_ERROR there is error * NGX_OK the token terminated by ";" was found * NGX_CONF_BLOCK_START the token terminated by "{" was found * NGX_CONF_BLOCK_DONE the "}" was found * NGX_CONF_FILE_DONE the configuration file is done */ if (rc == NGX_ERROR) { goto done; } if (rc == NGX_CONF_BLOCK_DONE) { //解析正常 if (type != parse_block) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\""); goto failed; } goto done; } if (rc == NGX_CONF_FILE_DONE) { if (type == parse_block) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected end of file, expecting \"}\""); goto failed; } goto done; } if (rc == NGX_CONF_BLOCK_START) { if (type == parse_param) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "block directives are not supported " "in -g option"); goto failed; } } /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */ if (cf->handler) { //进行这些token转换为Nginx内控制变量的值,针对“text/html html htm shtml”等这样的配置项或geo模块里的“192.168.0.0/16 local”这样的不定配置项,进行特殊的处理 /* * the custom handler, i.e., that is used in the http's * "types { ... }" directive */ rv = (*cf->handler)(cf, NULL, cf->handler_conf); if (rv == NGX_CONF_OK) { continue; } if (rv == NGX_CONF_ERROR) { goto failed; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv); goto failed; } rc = ngx_conf_handler(cf, rc); //配置转换 if (rc == NGX_ERROR) { goto failed; } } failed: rc = NGX_ERROR; done: if (filename) { if (cf->conf_file->buffer->start) { ngx_free(cf->conf_file->buffer->start); } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " %s failed", filename->data); return NGX_CONF_ERROR; } cf->conf_file = prev; } if (rc == NGX_ERROR) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
ngx_int_t ngx_http_small_light_imagemagick_process(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_imagemagick_ctx_t *ictx; ngx_http_small_light_image_size_t sz; MagickBooleanType status; int rmprof_flg, progressive_flg, cmyk2rgb_flg; double iw, ih, q; char *unsharp, *sharpen, *blur, *of, *of_orig; MagickWand *trans_wand, *canvas_wand; DrawingWand *border_wand; PixelWand *bg_color, *canvas_color, *border_color; GeometryInfo geo; ngx_fd_t fd; MagickWand *icon_wand; u_char *p, *embedicon; size_t embedicon_path_len, embedicon_len, sled_image_size; ngx_int_t type; u_char jpeg_size_opt[32], crop_geo[128], size_geo[128], embedicon_path[256]; ColorspaceType color_space; #if MagickLibVersion >= 0x690 int autoorient_flg; #endif status = MagickFalse; ictx = (ngx_http_small_light_imagemagick_ctx_t *)ctx->ictx; /* adjust image size */ ngx_http_small_light_calc_image_size(r, ctx, &sz, 10000.0, 10000.0); /* prepare */ if (sz.jpeghint_flg != 0) { p = ngx_snprintf((u_char *)jpeg_size_opt, sizeof(jpeg_size_opt) - 1, "%dx%d", (ngx_int_t)sz.dw, (ngx_int_t)sz.dh); *p = '\0'; ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "jpeg_size_opt:%s", jpeg_size_opt); MagickSetOption(ictx->wand, "jpeg:size", (char *)jpeg_size_opt); } /* load image. */ status = MagickReadImageBlob(ictx->wand, (void *)ictx->image, ictx->image_len); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couldn't read image %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } MagickSetFirstIterator(ictx->wand); color_space = MagickGetImageColorspace(ictx->wand); /* remove all profiles */ rmprof_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "rmprof")); if (rmprof_flg != 0) { status = MagickProfileImage(ictx->wand, "*", NULL, 0); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "couldn't profiling image %s:%d", __FUNCTION__, __LINE__); } } of_orig = MagickGetImageFormat(ictx->wand); status = MagickTrue; #if MagickLibVersion >= 0x690 /* auto-orient */ autoorient_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "autoorient")); if (autoorient_flg != 0) { status = MagickAutoOrientImage(ictx->wand); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyString(of_orig); return NGX_ERROR; } } #endif /* rotate. */ if (sz.angle) { bg_color = NewPixelWand(); PixelSetRed(bg_color, sz.cc.r / 255.0); PixelSetGreen(bg_color, sz.cc.g / 255.0); PixelSetBlue(bg_color, sz.cc.b / 255.0); PixelSetAlpha(bg_color, sz.cc.a / 255.0); switch (sz.angle) { case 90: case 180: case 270: MagickRotateImage(ictx->wand, bg_color, sz.angle); break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image not rotated. 'angle'(%ui) must be 90 or 180 or 270. %s:%d", sz.angle, __FUNCTION__, __LINE__); break; } DestroyPixelWand(bg_color); } /* calc size. */ iw = (double)MagickGetImageWidth(ictx->wand); ih = (double)MagickGetImageHeight(ictx->wand); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); /* pass through. */ if (sz.pt_flg != 0) { ctx->of = ctx->inf; DestroyString(of_orig); return NGX_OK; } /* crop, scale. */ if (sz.scale_flg != 0) { p = ngx_snprintf(crop_geo, sizeof(crop_geo) - 1, "%f!x%f!+%f+%f", sz.sw, sz.sh, sz.sx, sz.sy); *p = '\0'; p = ngx_snprintf(size_geo, sizeof(size_geo) - 1, "%f!x%f!", sz.dw, sz.dh); *p = '\0'; ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "crop_geo:%s", crop_geo); ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "size_geo:%s", size_geo); MagickResetImagePage(ictx->wand, "+0+0"); trans_wand = MagickTransformImage(ictx->wand, (char *)crop_geo, (char *)size_geo); if (trans_wand == NULL || trans_wand == ictx->wand) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyString(of_orig); return NGX_ERROR; } DestroyMagickWand(ictx->wand); ictx->wand = trans_wand; } /* create canvas then draw image to the canvas. */ if (sz.cw > 0.0 && sz.ch > 0.0) { canvas_wand = NewMagickWand(); canvas_color = NewPixelWand(); PixelSetRed(canvas_color, sz.cc.r / 255.0); PixelSetGreen(canvas_color, sz.cc.g / 255.0); PixelSetBlue(canvas_color, sz.cc.b / 255.0); PixelSetAlpha(canvas_color, sz.cc.a / 255.0); status = MagickNewImage(canvas_wand, sz.cw, sz.ch, canvas_color); DestroyPixelWand(canvas_color); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyMagickWand(canvas_wand); DestroyString(of_orig); return NGX_ERROR; } status = MagickTransformImageColorspace(canvas_wand, color_space); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyMagickWand(canvas_wand); DestroyString(of_orig); return NGX_ERROR; } status = MagickCompositeImage(canvas_wand, ictx->wand, AtopCompositeOp, sz.dx, sz.dy); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyMagickWand(canvas_wand); DestroyString(of_orig); return NGX_ERROR; } DestroyMagickWand(ictx->wand); ictx->wand = canvas_wand; } /* CMYK to sRGB */ cmyk2rgb_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "cmyk2rgb")); if (cmyk2rgb_flg != 0 && color_space == CMYKColorspace) { status = MagickTransformImageColorspace(ictx->wand, sRGBColorspace); if (status == MagickFalse) { r->err_status = NGX_HTTP_INTERNAL_SERVER_ERROR; DestroyString(of_orig); return NGX_ERROR; } } /* effects. */ unsharp = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "unsharp"); if (ngx_strlen(unsharp) > 0) { ParseGeometry(unsharp, &geo); if (geo.rho > ctx->radius_max || geo.sigma > ctx->sigma_max) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "As unsharp geometry is too large, ignored. %s:%d", __FUNCTION__, __LINE__); } else { status = MagickUnsharpMaskImage(ictx->wand, geo.rho, geo.sigma, geo.xi, geo.psi); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unsharp failed %s:%d", __FUNCTION__, __LINE__); } } } sharpen = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "sharpen"); if (ngx_strlen(sharpen) > 0) { ParseGeometry(sharpen, &geo); if (geo.rho > ctx->radius_max || geo.sigma > ctx->sigma_max) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "As sharpen geometry is too large, ignored. %s:%d", __FUNCTION__, __LINE__); } else { status = MagickSharpenImage(ictx->wand, geo.rho, geo.sigma); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "sharpen failed %s:%d", __FUNCTION__, __LINE__); } } } blur = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "blur"); if (ngx_strlen(blur) > 0) { ParseGeometry(blur, &geo); if (geo.rho > ctx->radius_max || geo.sigma > ctx->sigma_max) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "As blur geometry is too large, ignored. %s:%d", __FUNCTION__, __LINE__); } else { status = MagickBlurImage(ictx->wand, geo.rho, geo.sigma); if (status == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "blur failed %s:%d", __FUNCTION__, __LINE__); } } } /* border. */ if (sz.bw > 0.0 || sz.bh > 0.0) { border_wand = NewDrawingWand(); border_color = NewPixelWand(); PixelSetRed(border_color, sz.bc.r / 255.0); PixelSetGreen(border_color, sz.bc.g / 255.0); PixelSetBlue(border_color, sz.bc.b / 255.0); PixelSetAlpha(border_color, sz.bc.a / 255.0); DrawSetFillColor(border_wand, border_color); DrawSetStrokeColor(border_wand, border_color); DrawSetStrokeWidth(border_wand, 1); if (sz.cw > 0.0 && sz.ch > 0.0) { DrawRectangle(border_wand, 0, 0, sz.cw - 1, sz.bh - 1); DrawRectangle(border_wand, 0, 0, sz.bw - 1, sz.ch - 1); DrawRectangle(border_wand, 0, sz.ch - sz.bh, sz.cw - 1, sz.ch - 1); DrawRectangle(border_wand, sz.cw - sz.bw, 0, sz.cw - 1, sz.ch - 1); } else { DrawRectangle(border_wand, 0, 0, sz.dw - 1, sz.bh - 1); DrawRectangle(border_wand, 0, 0, sz.bw - 1, sz.dh - 1); DrawRectangle(border_wand, 0, sz.dh - sz.bh, sz.dw - 1, sz.dh - 1); DrawRectangle(border_wand, sz.dw - sz.bw, 0, sz.dw - 1, sz.dh - 1); } MagickDrawImage(ictx->wand, border_wand); DestroyPixelWand(border_color); DestroyDrawingWand(border_wand); } /* embed icon */ embedicon = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "embedicon"); if (ctx->material_dir->len > 0 && ngx_strlen(embedicon) > 0) { if (ngx_strstrn((u_char *)embedicon, "/", 1 - 1)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid parameter 'embedicon':%s %s:%d", embedicon, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } embedicon_len = ngx_strlen(embedicon); embedicon_path_len = ctx->material_dir->len + ngx_strlen("/") + embedicon_len; if (embedicon_path_len > sizeof(embedicon_path) - 1) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "embedicon path is too long. maximun value is %z %s:%d", sizeof(embedicon_path) - 1, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } p = embedicon_path; p = ngx_cpystrn(p, ctx->material_dir->data, ctx->material_dir->len + 1); p = ngx_cpystrn(p, (u_char *)"/", 1 + 1); p = ngx_cpystrn(p, embedicon, embedicon_len + 1); if ((fd = ngx_open_file(embedicon_path, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0)) == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to open embeddedicon file:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to close:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } if (ngx_strstrn(embedicon_path, "..", 2 - 1)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid embeddedicon_path:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); DestroyString(of_orig); return NGX_ERROR; } icon_wand = NewMagickWand(); if (MagickReadImage(icon_wand, (char *)embedicon_path) == MagickFalse) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to read embed icon image file:%s %s:%d", embedicon_path, __FUNCTION__, __LINE__); DestroyMagickWand(icon_wand); DestroyString(of_orig); return NGX_ERROR; } MagickCompositeImageChannel(ictx->wand, AllChannels, icon_wand, OverCompositeOp, sz.ix, sz.iy); DestroyMagickWand(icon_wand); } /* set params. */ q = ngx_http_small_light_parse_double(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "q")); if (q > 0.0) { MagickSetImageCompressionQuality(ictx->wand, q); } progressive_flg = ngx_http_small_light_parse_flag(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "progressive")); if (progressive_flg != 0) { MagickSetInterlaceScheme(ictx->wand, LineInterlace); } of = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "of"); if (ngx_strlen(of) > 0) { type = ngx_http_small_light_type(of); if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "of is invalid(%s) %s:%d", of, __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; } else if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_WEBP) { #if defined(MAGICKCORE_WEBP_DELEGATE) ictx->type = type; #else ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "WebP is not supported %s:%d", __FUNCTION__, __LINE__); of = (char *)ngx_http_small_light_image_exts[ictx->type - 1]; #endif } else { ictx->type = type; } MagickSetFormat(ictx->wand, of); ctx->of = ngx_http_small_light_image_types[ictx->type - 1]; } else { MagickSetFormat(ictx->wand, of_orig); ctx->of = ctx->inf; } DestroyString(of_orig); ctx->content = MagickGetImageBlob(ictx->wand, &sled_image_size); ctx->content_length = sled_image_size; ngx_pfree(r->pool, ctx->content_orig); ictx->complete = 1; return NGX_OK; }
static ngx_int_t ngx_http_file_cache_add_file(ngx_tree_ctx_t *ctx, ngx_str_t *name) { u_char *p; ngx_fd_t fd; ngx_int_t n; ngx_uint_t i; ngx_file_info_t fi; ngx_http_cache_t c; ngx_http_file_cache_t *cache; ngx_http_file_cache_header_t h; if (name->len < 2 * NGX_HTTP_CACHE_KEY_LEN) { return NGX_ERROR; } ngx_memzero(&c, sizeof(ngx_http_cache_t)); fd = ngx_open_file(name->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, ngx_open_file_n " \"%s\" failed", name->data); return NGX_ERROR; } c.file.fd = fd; c.file.name = *name; c.file.log = ctx->log; n = ngx_read_file(&c.file, (u_char *) &h, sizeof(ngx_http_file_cache_header_t), 0); if (n == NGX_ERROR) { return NGX_ERROR; } if ((size_t) n < sizeof(ngx_http_file_cache_header_t)) { ngx_log_error(NGX_LOG_CRIT, ctx->log, 0, "cache file \"%s\" is too small", name->data); return NGX_ERROR; } cache = ctx->data; if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", name->data); } else { c.uniq = ngx_file_uniq(&fi); c.valid_sec = h.valid_sec; c.valid_msec = h.valid_msec; c.body_start = h.body_start; c.length = ngx_file_size(&fi); c.fs_size = (ngx_file_fs_size(&fi) + cache->bsize - 1) / cache->bsize; } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_close_file_n " \"%s\" failed", name->data); } if (c.body_start == 0) { return NGX_ERROR; } p = &name->data[name->len - 2 * NGX_HTTP_CACHE_KEY_LEN]; for (i = 0; i < NGX_HTTP_CACHE_KEY_LEN; i++) { n = ngx_hextoi(p, 2); if (n == NGX_ERROR) { return NGX_ERROR; } p += 2; c.key[i] = (u_char) n; } return ngx_http_file_cache_add(cache, &c); }
static int command_sendfile(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { ngx_buf_t *b; ngx_chain_t out; ngx_http_request_t *r = getrequest(clientData); ngx_file_info_t *fi; ngx_fd_t fd; const char *filename; int filename_len; int rc; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "file"); return TCL_ERROR; } filename = Tcl_GetStringFromObj(objv[1], &filename_len); fd = ngx_open_file(filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { Tcl_SetResult(interp, (char *) Tcl_PosixError(interp), TCL_VOLATILE); return TCL_ERROR; } b = ngx_calloc_buf(r->pool); if (b == NULL) { return TCL_ERROR; } b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); if (b->file == NULL) { return TCL_ERROR; } fi = &b->file->info; ngx_fd_info(fd, fi); if (!r->header_sent) { r->headers_out.content_length_n = ngx_file_size(fi); r->headers_out.last_modified_time = ngx_file_mtime(fi); if (ngx_http_set_etag(r) != NGX_OK) { return TCL_ERROR; } ngx_http_send_header(r); /* TODO: CHECK RETURN */ } r->allow_ranges = 1; b->file_pos = 0; b->file_last = ngx_file_size(fi); b->in_file = 1; b->last_buf = 1; b->last_in_chain = 1; b->file->fd = fd; b->file->name.data = (u_char*)filename; b->file->name.len = filename_len; b->file->log = r->connection->log; out.buf = b; out.next = NULL; rc = ngx_http_output_filter(r, &out); if (rc != NGX_OK) { ngx_tcl_set_error_code(interp, rc); return TCL_ERROR; } printf("ngx_http_output_filter returns %i\n", rc); fflush(stdout); return TCL_OK; }
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; static ngx_str_t nosfx; static u_char path[NGX_MAX_PATH]; 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->root.len == 0 && pacf->url == NULL)) { 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 */ 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->file.log = s->connection->log; 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) { name.data += pfx->len; name.len -= 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; ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "play %s: %V", pacf->url ? "remote" : "local", &ctx->fmt->name); sfx = &ctx->fmt->sfx; if (name.len >= sfx->len && ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len, sfx->len) == 0) { sfx = &nosfx; } /* remote? */ if (pacf->url) { ctx->name.data = ngx_palloc(s->connection->pool, name.len + sfx->len); if (ctx->name.data == NULL) { return NGX_ERROR; } p = ngx_sprintf(ctx->name.data, "%V%V", &name, sfx); *p = 0; ctx->name.len = p - ctx->name.data; return ngx_rtmp_play_open_remote(s, v); } /* open local */ p = ngx_snprintf(path, sizeof(path), "%V/%V%V", &pacf->root, &name, sfx); *p = 0; 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, ngx_errno, "play: error opening file '%s'", path); ngx_rtmp_send_status(s, "NetStream.Play.StreamNotFound", "error", "Video on demand stream not found"); return NGX_OK; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: opened local file '%s'", path); if (ngx_rtmp_play_open(s, v->start) != NGX_OK) { return NGX_ERROR; } next: return next_play(s, v); }
ngx_int_t ngx_http_cookie_conf_each_line_proc(ngx_http_cookie_clean_conf_t *conf, ngx_str_t *filename, each_line_proc proc, void * obj, void * p_data) { ngx_int_t rc = NGX_OK; ngx_file_t file; ngx_str_t full; ngx_fd_t fd; off_t file_size; ssize_t n; ngx_buf_t buf; u_char *s = NULL; ngx_log_t *log = conf->ctx->log; ngx_memzero(&file, sizeof(ngx_file_t)); ngx_memzero(&full, sizeof(ngx_str_t)); ngx_memzero(&buf, sizeof(ngx_buf_t)); fd = NGX_INVALID_FILE; if (filename->len == 0) { ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], file not set", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_http_cookie_full_name(conf->ctx, filename, &full) != NGX_OK) { ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], get full file name of \"%V\" failed.",__FUNCTION__, __LINE__, filename); goto failed; } ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], full file name:\"%V\".", __FUNCTION__, __LINE__, &full); fd = ngx_open_file(full.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], open file:\"%V\" failed.", __FUNCTION__, __LINE__, &full); goto failed; } if (ngx_fd_info(fd, &file.info) == NGX_FILE_ERROR) { ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], get file:\"%V\" info failed.", __FUNCTION__, __LINE__, &full); goto failed; } file.fd = fd; file.name.data = full.data; file.name.len = full.len; file.offset = 0; file.log = log; buf.start = ngx_alloc(NGX_HTTP_COOKIE_CLEAN_BUFFER, log); if (buf.start == NULL) { ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], alloc buffer failed.", __FUNCTION__, __LINE__); goto failed; } buf.pos = buf.start; buf.last = buf.start; buf.end = buf.last + NGX_HTTP_COOKIE_CLEAN_BUFFER; buf.temporary = 1; file_size = ngx_file_size(&file.info); while (1) { s = ngx_http_cookie_read_one_line(&file, &buf, file_size, &n); if (n == -1) { ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], read file:\"%V\" failed.", __FUNCTION__, __LINE__, &full); goto failed; } if (n == 0) { break; } if (proc(conf, obj, s, n, p_data) != 0) { ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], proc one line:\"%*s\" failed.", __FUNCTION__, __LINE__, n, s); goto failed; } ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], proc one line:\"%*s\" succeed.", __FUNCTION__, __LINE__, n, s); } ngx_log_debug(NGX_LOG_NOTICE, log, 0, "[%s:%d], proc file:\"%V\" succeed.", __FUNCTION__, __LINE__, &full); goto done; failed: rc = NGX_ERROR; done: if (full.data != NULL) { ngx_free(full.data); full.data = NULL; } if (fd != NGX_INVALID_FILE && ngx_close_file(fd) == NGX_FILE_ERROR) { rc = NGX_ERROR; } if (buf.start != NULL) { ngx_free(buf.start); buf.start = NULL; } return rc; }
static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx, ngx_str_t *path) { u_char *p, *dir; size_t len; ngx_http_dav_copy_ctx_t *copy; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "http copy dir time: \"%s\"", path->data); copy = ctx->data; len = copy->path.len + path->len; dir = ngx_alloc(len + 1, ctx->log); if (dir == NULL) { return NGX_ABORT; } p = ngx_cpymem(dir, copy->path.data, copy->path.len); (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "http copy dir time to: \"%s\"", dir); #if (NGX_WIN32) { ngx_fd_t fd; fd = ngx_open_file(dir, NGX_FILE_RDWR, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, dir); goto failed; } if (ngx_set_file_time(NULL, fd, ctx->mtime) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_set_file_time_n " \"%s\" failed", dir); } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_close_file_n " \"%s\" failed", dir); } } failed: #else if (ngx_set_file_time(dir, 0, ctx->mtime) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_set_file_time_n " \"%s\" failed", dir); } #endif ngx_free(dir); return NGX_OK; }
static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, u_char *to) { off_t size; ssize_t n; ngx_fd_t fd, cfd; ngx_int_t rc; u_char buf[NGX_HTTP_DAV_COPY_BLOCK]; fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, from); return NGX_ERROR; } cfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, ctx->access); rc = NGX_ERROR; if (cfd == NGX_INVALID_FILE) { (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, to); goto failed; } for (size = ctx->size; size > 0; size -= n) { n = ngx_read_fd(fd, buf, NGX_HTTP_DAV_COPY_BLOCK); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_read_fd_n " \"%s\" failed", from); goto failed; } if (ngx_write_fd(cfd, buf, n) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_write_fd_n " \"%s\" failed", to); goto failed; } } if (ngx_set_file_time(to, cfd, ctx->mtime) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_set_file_time_n " \"%s\" failed", to); goto failed; } if (ngx_close_file(cfd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_close_file_n " \"%s\" failed", to); goto failed; } rc = NGX_OK; failed: if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_close_file_n " \"%s\" failed", from); } return rc; }
void ngx_http_file_cache_update_header(ngx_http_request_t *r) { ssize_t n; ngx_err_t err; ngx_file_t file; ngx_file_info_t fi; ngx_http_cache_t *c; ngx_http_file_cache_header_t h; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache update header"); c = r->cache; ngx_memzero(&file, sizeof(ngx_file_t)); file.name = c->file.name; file.log = r->connection->log; file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR, NGX_FILE_OPEN, 0); if (file.fd == NGX_INVALID_FILE) { err = ngx_errno; /* cache file may have been deleted */ if (err == NGX_ENOENT) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache \"%s\" not found", file.name.data); return; } ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_open_file_n " \"%s\" failed", file.name.data); return; } /* * make sure cache file wasn't replaced; * if it was, do nothing */ if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", file.name.data); goto done; } if (c->uniq != ngx_file_uniq(&fi) || c->length != ngx_file_size(&fi)) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache \"%s\" changed", file.name.data); goto done; } n = ngx_read_file(&file, (u_char *) &h, sizeof(ngx_http_file_cache_header_t), 0); if (n == NGX_ERROR) { goto done; } if ((size_t) n != sizeof(ngx_http_file_cache_header_t)) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, ngx_read_file_n " read only %z of %z from \"%s\"", n, sizeof(ngx_http_file_cache_header_t), file.name.data); goto done; } if (h.last_modified != c->last_modified || h.crc32 != c->crc32 || h.header_start != c->header_start || h.body_start != c->body_start) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache \"%s\" content changed", file.name.data); goto done; } /* * update cache file header with new data, * notably h.valid_sec and h.date */ ngx_memzero(&h, sizeof(ngx_http_file_cache_header_t)); h.valid_sec = c->valid_sec; h.last_modified = c->last_modified; h.date = c->date; h.crc32 = c->crc32; h.valid_msec = (u_short) c->valid_msec; h.header_start = (u_short) c->header_start; h.body_start = (u_short) c->body_start; (void) ngx_write_file(&file, (u_char *) &h, sizeof(ngx_http_file_cache_header_t), 0); done: if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file.name.data); } }
char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { int m, rc, found, valid; char *rv; void *conf, **confp; ngx_fd_t fd; ngx_str_t *name; ngx_conf_file_t *prev; ngx_command_t *cmd; #if (NGX_SUPPRESS_WARN) fd = NGX_INVALID_FILE; prev = NULL; #endif if (filename) { /* open configuration file */ fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_open_file_n " %s failed", filename->data); return NGX_CONF_ERROR; } prev = cf->conf_file; if (!(cf->conf_file = ngx_palloc(cf->pool, sizeof(ngx_conf_file_t)))) { return NGX_CONF_ERROR; } if (ngx_fd_info(fd, &cf->conf_file->file.info) == -1) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_fd_info_n " %s failed", filename->data); } if (!(cf->conf_file->buffer = ngx_create_temp_buf(cf->pool, 1024))) { return NGX_CONF_ERROR; } cf->conf_file->file.fd = fd; cf->conf_file->file.name.len = filename->len; cf->conf_file->file.name.data = filename->data; cf->conf_file->file.offset = 0; cf->conf_file->file.log = cf->log;; cf->conf_file->line = 1; } for ( ;; ) { rc = ngx_conf_read_token(cf); /* * ngx_conf_read_token() returns NGX_OK, NGX_ERROR, * NGX_CONF_FILE_DONE or NGX_CONF_BLOCK_DONE */ #if 0 ngx_log_debug(cf->log, "token %d" _ rc); #endif if (rc == NGX_ERROR) { break; } if (rc != NGX_OK) { break; } if (cf->handler) { /* custom handler, i.e. used in http "types { ... }" directive */ rv = (*cf->handler)(cf, NULL, cf->handler_conf); if (rv == NGX_CONF_OK) { continue; } else if (rv == NGX_CONF_ERROR) { rc = NGX_ERROR; break; } else { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "%s in %s:%d", rv, cf->conf_file->file.name.data, cf->conf_file->line); rc = NGX_ERROR; break; } } name = (ngx_str_t *) cf->args->elts; found = 0; for (m = 0; rc != NGX_ERROR && !found && ngx_modules[m]; m++) { /* look up the directive in the appropriate modules */ if (ngx_modules[m]->type != NGX_CONF_MODULE && ngx_modules[m]->type != cf->module_type) { continue; } cmd = ngx_modules[m]->commands; if (cmd == NULL) { continue; } while (cmd->name.len) { if (name->len == cmd->name.len && ngx_strcmp(name->data, cmd->name.data) == 0) { found = 1; #if 0 ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data); #endif /* is the directive's location right ? */ if ((cmd->type & cf->cmd_type) == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "directive \"%s\" in %s:%d " "is not allowed here", name->data, cf->conf_file->file.name.data, cf->conf_file->line); rc = NGX_ERROR; break; } /* is the directive's argument count right ? */ if (cmd->type & NGX_CONF_ANY) { valid = 1; } else if (cmd->type & NGX_CONF_FLAG) { if (cf->args->nelts == 2) { valid = 1; } else { valid = 0; } } else if (cmd->type & NGX_CONF_1MORE) { if (cf->args->nelts > 1) { valid = 1; } else { valid = 0; } } else if (cmd->type & NGX_CONF_2MORE) { if (cf->args->nelts > 2) { valid = 1; } else { valid = 0; } } else if (cf->args->nelts <= 10 && (cmd->type & argument_number[cf->args->nelts - 1])) { valid = 1; } else { valid = 0; } if (!valid) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "invalid number arguments in " "directive \"%s\" in %s:%d", name->data, cf->conf_file->file.name.data, cf->conf_file->line); rc = NGX_ERROR; break; } /* set up the directive's configuration context */ conf = NULL; if (cmd->type & NGX_DIRECT_CONF) { conf = ((void **) cf->ctx)[ngx_modules[m]->index]; } else if (cmd->type & NGX_MAIN_CONF) { conf = &(((void **) cf->ctx)[ngx_modules[m]->index]); } else if (cf->ctx) { confp = *(void **) ((char *) cf->ctx + cmd->conf); if (confp) { conf = confp[ngx_modules[m]->ctx_index]; } } rv = cmd->set(cf, cmd, conf); #if 0 ngx_log_debug(cf->log, "rv: %d" _ rv); #endif if (rv == NGX_CONF_OK) { break; } else if (rv == NGX_CONF_ERROR) { rc = NGX_ERROR; break; } else { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "the \"%s\" directive %s in %s:%d", name->data, rv, cf->conf_file->file.name.data, cf->conf_file->line); rc = NGX_ERROR; break; } } cmd++; } } if (!found) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "unknown directive \"%s\" in %s:%d", name->data, cf->conf_file->file.name.data, cf->conf_file->line); rc = NGX_ERROR; break; } if (rc == NGX_ERROR) { break; } } if (filename) { cf->conf_file = prev; if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " %s failed", cf->conf_file->file.name.data); return NGX_CONF_ERROR; } } if (rc == NGX_ERROR) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; char **senv, **env; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; ngx_conf_t conf; ngx_pool_t *pool; ngx_cycle_t *cycle, **old; ngx_shm_zone_t *shm_zone, *oshm_zone; ngx_list_part_t *part, *opart; ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; /* 更新时区 */ ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday(); tp->sec = 0; /* 更新时间 */ ngx_time_update(); /* 创建内存池pool,并初始化 */ log = old_cycle->log; pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } pool->log = log; /* 创建ngx_cycle_t 结构体变量 */ cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } /* 初始化ngx_cycle_t 结构体变量 cycle */ cycle->pool = pool; cycle->log = log; cycle->old_cycle = old_cycle; cycle->conf_prefix.len = old_cycle->conf_prefix.len; cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->prefix.len = old_cycle->prefix.len; cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_file.len = old_cycle->conf_file.len; cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); if (cycle->conf_file.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, old_cycle->conf_file.len + 1); cycle->conf_param.len = old_cycle->conf_param.len; cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); if (cycle->conf_param.data == NULL) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->paths.nelts = 0; cycle->paths.size = sizeof(ngx_path_t *); cycle->paths.nalloc = n; cycle->paths.pool = pool; if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->listening.nelts = 0; cycle->listening.size = sizeof(ngx_listening_t); cycle->listening.nalloc = n; cycle->listening.pool = pool; ngx_queue_init(&cycle->reusable_connections_queue); cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); ngx_destroy_pool(pool); return NULL; } /* on Linux gethostname() silently truncates name that does not fit */ hostname[NGX_MAXHOSTNAMELEN - 1] = '\0'; cycle->hostname.len = ngx_strlen(hostname); cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len); if (cycle->hostname.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); /* 遍历所有core模块 */ for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; /* 若有core模块实现了create_conf(),则就调用它,并返回地址 */ if (module->create_conf) { rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ngx_modules[i]->index] = rv; } } senv = environ; ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; } conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (conf.temp_pool == NULL) { ngx_destroy_pool(pool); return NULL; } conf.ctx = cycle->conf_ctx; conf.cycle = cycle; conf.pool = pool; conf.log = log; conf.module_type = NGX_CORE_MODULE; conf.cmd_type = NGX_MAIN_CONF; #if 0 log->log_level = NGX_LOG_DEBUG_ALL; #endif /* 配置文件解析 */ if (ngx_conf_param(&conf) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_test_config && !ngx_quiet_mode) { ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } /* 遍历所有core模块,并调用core模块的init_conf()函数 */ for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle; } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_test_config) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_cycle)) { /* * we do not create the pid file in the first ngx_init_cycle() call * because we need to write the demonized process pid */ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (ccf->pid.len != old_ccf->pid.len || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) { /* new pid file name */ if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } ngx_delete_pidfile(old_cycle); } } if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { goto failed; } /* 初始化paths 数组 */ 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; /* 遍历open_file 链表中每一个文件,并打开该文件 */ for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d \"%s\"", &file[i], file[i].fd, file[i].name.data); if (file[i].fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); goto failed; } #if !(NGX_WIN32) if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); goto failed; } #endif } cycle->log = &cycle->new_log; pool->log = &cycle->new_log; /* 创建共享内存并初始化 */ /* create shared memory */ part = &cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } if (shm_zone[i].shm.size == 0) { ngx_log_error(NGX_LOG_EMERG, log, 0, "zero size shared memory zone \"%V\"", &shm_zone[i].shm.name); goto failed; } shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; /* * 新的共享内存与旧的共享内存链表进行比较, * 相同则保留,不同创建新的,旧的被释放 */ for (n = 0; /* void */ ; n++) { if (n >= opart->nelts) { if (opart->next == NULL) { break; } opart = opart->next; oshm_zone = opart->elts; n = 0; } if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { continue; } if (ngx_strncmp(shm_zone[i].shm.name.data, oshm_zone[n].shm.name.data, shm_zone[i].shm.name.len) != 0) { continue; } if (shm_zone[i].tag == oshm_zone[n].tag && shm_zone[i].shm.size == oshm_zone[n].shm.size) { shm_zone[i].shm.addr = oshm_zone[n].shm.addr; if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) != NGX_OK) { goto failed; } goto shm_zone_found; } ngx_shm_free(&oshm_zone[n].shm); break; } if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { goto failed; } if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { goto failed; } shm_zone_found: continue; } /* 遍历listening 数组,并打开所有监听 */ /* handle the listening sockets */ if (old_cycle->listening.nelts) { ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { ls[i].remain = 0; } nls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].ignore) { continue; } if (ngx_cmp_sockaddr(nls[n].sockaddr, 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 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); } /* 提交新的cycle配置,并调用所有模块的 init_module */ /* commit the new cycle configuration */ if (!ngx_use_stderr) { (void) ngx_log_redirect_stderr(cycle); } pool->log = cycle->log; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } /* 关闭或删除不被使用的old_cycle 资源 */ /* 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; }
/* * 函数功能:配置文件解析; * 支持三种不同的解析类型: * 1、解析配置文件; * 2、解析block块设置; * 3、解析命令行配置; */ char * ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { char *rv; ngx_fd_t fd; ngx_int_t rc; ngx_buf_t buf; ngx_conf_file_t *prev, conf_file; enum { parse_file = 0, parse_block, parse_param } type; #if (NGX_SUPPRESS_WARN) fd = NGX_INVALID_FILE; prev = NULL; #endif if (filename) {/* 若解析的是配置文件 */ /* open configuration file */ /* 打开配置文件 */ fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", filename->data); return NGX_CONF_ERROR; } prev = cf->conf_file; cf->conf_file = &conf_file; if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", filename->data); } cf->conf_file->buffer = &buf; buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log); if (buf.start == NULL) { goto failed; } buf.pos = buf.start; buf.last = buf.start; buf.end = buf.last + NGX_CONF_BUFFER; buf.temporary = 1; /* 复制文件属性及文件内容 */ cf->conf_file->file.fd = fd; cf->conf_file->file.name.len = filename->len; cf->conf_file->file.name.data = filename->data; cf->conf_file->file.offset = 0; cf->conf_file->file.log = cf->log; cf->conf_file->line = 1; type = parse_file; /* 解析的类型是配置文件 */ } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) { type = parse_block; /* 解析的类型是block块 */ } else { type = parse_param; /* 解析的类型是命令行配置 */ } for ( ;; ) { /* 语法分析函数 */ rc = ngx_conf_read_token(cf); /* * ngx_conf_read_token() may return * * NGX_ERROR there is error * NGX_OK the token terminated by ";" was found * NGX_CONF_BLOCK_START the token terminated by "{" was found * NGX_CONF_BLOCK_DONE the "}" was found * NGX_CONF_FILE_DONE the configuration file is done */ if (rc == NGX_ERROR) { goto done; } /* 解析block块设置 */ if (rc == NGX_CONF_BLOCK_DONE) { if (type != parse_block) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\""); goto failed; } goto done; } /* 解析配置文件 */ if (rc == NGX_CONF_FILE_DONE) { if (type == parse_block) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected end of file, expecting \"}\""); goto failed; } goto done; } if (rc == NGX_CONF_BLOCK_START) { if (type == parse_param) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "block directives are not supported " "in -g option"); goto failed; } } /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */ /* 自定义指令处理函数 */ if (cf->handler) { /* * the custom handler, i.e., that is used in the http's * "types { ... }" directive */ if (rc == NGX_CONF_BLOCK_START) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\""); goto failed; } /* 命令行配置处理函数 */ rv = (*cf->handler)(cf, NULL, cf->handler_conf); if (rv == NGX_CONF_OK) { continue; } if (rv == NGX_CONF_ERROR) { goto failed; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv); goto failed; } /* 若自定义指令处理函数handler为NULL,则调用Nginx内建的指令解析机制 */ rc = ngx_conf_handler(cf, rc); if (rc == NGX_ERROR) { goto failed; } } failed: rc = NGX_ERROR; done: if (filename) {/* 若是配置文件 */ if (cf->conf_file->buffer->start) { ngx_free(cf->conf_file->buffer->start); } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " %s failed", filename->data); return NGX_CONF_ERROR; } cf->conf_file = prev; } if (rc == NGX_ERROR) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static ngx_int_t ngx_rtmp_record_node_open(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx) { ngx_rtmp_record_app_conf_t *rracf; ngx_err_t err; ngx_str_t path; rracf = rctx->conf; if (rctx->file.fd != NGX_INVALID_FILE) { return NGX_AGAIN; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: %V opening", &rracf->id); ngx_memzero(rctx, sizeof(*rctx)); rctx->conf = rracf; rctx->last = *ngx_cached_time; rctx->timestamp = ngx_cached_time->sec; ngx_rtmp_record_make_path(s, rctx, &path); ngx_memzero(&rctx->file, sizeof(rctx->file)); rctx->file.offset = 0; rctx->file.log = s->connection->log; rctx->file.fd = ngx_open_file(path.data, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (rctx->file.fd == NGX_INVALID_FILE) { err = ngx_errno; if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_CRIT, s->connection->log, err, "record: %V failed to open file '%V'", &rracf->id, &path); } ngx_rtmp_record_notify_error(s, rctx); return NGX_OK; } if (rracf->lock_file) { err = ngx_lock_fd(rctx->file.fd); if (err) { ngx_log_error(NGX_LOG_CRIT, s->connection->log, err, "record: %V lock failed", &rracf->id); } } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: %V opened '%V'", &rracf->id, &path); if (rracf->notify) { ngx_rtmp_send_status(s, "NetStream.Record.Start", "status", rracf->id.data ? (char *) rracf->id.data : ""); } return NGX_OK; }
static ngx_int_t ngx_rtmp_play_next_entry(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) { ngx_rtmp_play_app_conf_t *pacf; ngx_rtmp_play_ctx_t *ctx; ngx_rtmp_play_entry_t *pe; u_char *p; static u_char path[NGX_MAX_PATH + 1]; pacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_play_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module); for ( ;; ) { if (ctx->file.fd != NGX_INVALID_FILE) { ngx_close_file(ctx->file.fd); ctx->file.fd = NGX_INVALID_FILE; } if (ctx->file_id) { ngx_rtmp_play_cleanup_local_file(s); } ctx->nentry = (ctx->nentry == NGX_CONF_UNSET_UINT ? 0 : ctx->nentry + 1); if (ctx->nentry >= pacf->entries.nelts) { ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: all entries failed"); ngx_rtmp_send_status(s, "NetStream.Play.StreamNotFound", "error", "Video on demand stream not found"); break; } pe = ngx_rtmp_play_get_current_entry(s); ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: trying %s entry %ui/%uz '%V'", pe->url ? "remote" : "local", ctx->nentry + 1, pacf->entries.nelts, pe->url ? &pe->url->url : pe->root); /* open remote */ if (pe->url) { return ngx_rtmp_play_open_remote(s, v); } /* open local */ p = ngx_snprintf(path, NGX_MAX_PATH, "%V/%s%V", pe->root, v->name + ctx->pfx_size, &ctx->sfx); *p = 0; 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_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, ngx_errno, "play: error opening file '%s'", path); continue; } ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: open local file '%s'", path); if (ngx_rtmp_play_open(s, v->start) != NGX_OK) { return NGX_ERROR; } break; } return next_play(s, v); }
static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log) { ngx_fd_t fd; ngx_file_info_t fi; of->fd = NGX_INVALID_FILE; if (of->test_dir) { if (ngx_file_info(name, &fi) == -1) { of->err = ngx_errno; return NGX_ERROR; } of->uniq = ngx_file_uniq(&fi); of->mtime = ngx_file_mtime(&fi); of->size = ngx_file_size(&fi); of->is_dir = ngx_is_dir(&fi); of->is_file = ngx_is_file(&fi); of->is_link = ngx_is_link(&fi); of->is_exec = ngx_is_exec(&fi); if (of->is_dir) { return NGX_OK; } } fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { of->err = ngx_errno; return NGX_ERROR; } if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, ngx_fd_info_n " \"%s\" failed", name); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name); } return NGX_ERROR; } if (ngx_is_dir(&fi)) { if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", name); } fd = NGX_INVALID_FILE; } of->fd = fd; of->uniq = ngx_file_uniq(&fi); of->mtime = ngx_file_mtime(&fi); of->size = ngx_file_size(&fi); of->is_dir = ngx_is_dir(&fi); of->is_file = ngx_is_file(&fi); of->is_link = ngx_is_link(&fi); of->is_exec = ngx_is_exec(&fi); return NGX_OK; }
/* The load_jpeg function is based on Imlib2 loader. */ ngx_int_t ngx_http_small_light_load_jpeg( void **dest_data, int *width, int *height, const ngx_http_request_t *r, const char *filename, int hint_w, int hint_h) { int w, h; struct jpeg_decompress_struct cinfo; struct ImLib_JPEG_error_mgr jerr; FILE *f; ngx_int_t fd; int denom; DATA8 *ptr, *line[16], *data; DATA32 *ptr2, *dest; int x, y, l, i, scans; *dest_data = NULL; *width = *height = 0; fd = ngx_open_file(filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); if (fd == NGX_INVALID_FILE) { return NGX_ERROR; } f = fdopen(fd, "rb"); cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (sigsetjmp(jerr.setjmp_buffer, 1)) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_start_decompress(&cinfo); w = cinfo.output_width; h = cinfo.output_height; denom = w / hint_w; if (denom > h / hint_h) { denom = h / hint_h; } denom = denom >= 1 ? denom : 1; denom = denom <= 8 ? denom : 8; jpeg_destroy_decompress(&cinfo); fseek(f, 0, SEEK_SET); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; cinfo.scale_denom = denom; jpeg_start_decompress(&cinfo); w = cinfo.output_width; h = cinfo.output_height; if ((cinfo.rec_outbuf_height > 16) || (cinfo.output_components <= 0) || !IMAGE_DIMENSIONS_OK(w, h)) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } data = ngx_palloc(r->pool, w * 16 * cinfo.output_components); if (!data) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } /* must set the im->data member before callign progress function */ ptr2 = dest = ngx_palloc(r->pool, w * h * sizeof(DATA32)); if (!dest) { jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); return NGX_ERROR; } if (cinfo.output_components > 1) { for (i = 0; i < cinfo.rec_outbuf_height; i++) { line[i] = data + (i * w * cinfo.output_components); } for (l = 0; l < h; l += cinfo.rec_outbuf_height) { jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); scans = cinfo.rec_outbuf_height; if ((h - l) < scans) { scans = h - l; } ptr = data; for (y = 0; y < scans; y++) { for (x = 0; x < w; x++) { *ptr2 = (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]); ptr += cinfo.output_components; ptr2++; } } } } else if (cinfo.output_components == 1) { for (i = 0; i < cinfo.rec_outbuf_height; i++) { line[i] = data + (i * w); } for (l = 0; l < h; l += cinfo.rec_outbuf_height) { jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); scans = cinfo.rec_outbuf_height; if ((h - l) < scans) { scans = h - l; } ptr = data; for (y = 0; y < scans; y++) { for (x = 0; x < w; x++) { *ptr2 = (0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]); ptr++; ptr2++; } } } } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); ngx_close_file(fd); fclose(f); *dest_data = dest; *width = w; *height = h; return NGX_OK; }
static ngx_int_t ngx_hls_handler(ngx_http_request_t *r) { //ngx_log_t *log = r->connection->log; if(!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))){ return NGX_HTTP_NOT_ALLOWED; } ngx_http_hls_loc_conf_t *elcf = ngx_http_get_module_loc_conf(r,ngx_http_hls_module); char* media_type = ngx_http_hls_convert_string(elcf->media_type); char* media_path = ngx_http_hls_convert_string(elcf->media_path); //char *media_type = (char*)elcf->media_type.data; //char *media_path = (char*)elcf->media_path.data; ngx_int_t rc = ngx_http_discard_request_body(r); if(rc != NGX_OK){ return rc; } if(strcmp(media_type,"live") == 0){ //TODO:Live media. } else{ ngx_str_t media_file; ngx_str_t media_start; ngx_str_t media_end; ngx_http_arg(r, (u_char *)"media", 5, &media_file); rc = ngx_http_arg(r,(u_char *)"start",5,&media_start); ngx_http_arg(r, (u_char *)"end", 3 , &media_end); if(rc == NGX_DECLINED || media_start.len == 0){ char filename[512]; bzero(filename,512); ngx_str_t type = ngx_string("application/x-mpegURL");//m3u8文件的content type ngx_snprintf((u_char*)filename,1024,"%s%V.m3u8",media_path,&media_file); //M3U8文件不存在,目前采用直接返回错误的方式,后期采用根据TS文件创建新的M3U8 if(access((char*)filename,F_OK) == -1){ ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"File[%s] is not exist!media_path = %s,media_file=%V",filename,media_path,&media_file); //r->headers_out.status = NGX_HTTP_NOT_FOUND; //rc = ngx_http_send_header(r); return NGX_HTTP_NOT_FOUND; } else{ ngx_chain_t *out = ngx_pcalloc(r->pool,sizeof(ngx_chain_t)); ngx_buf_t *b; //b = ngx_create_temp_buf(r->pool,sizeof(ngx_buf_t)); b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b == NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->in_file = 1; b->file = ngx_pcalloc(r->pool,sizeof(ngx_file_t)); b->file->fd = ngx_open_file(filename,NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0); if(b->file->fd == -1){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file->name.data = (u_char*)filename; b->file->name.len = sizeof(filename) -1; if(ngx_file_info(filename,&b->file->info) == NGX_FILE_ERROR){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->file->info.st_size; r->headers_out.content_type = type; b->file_pos = 0; b->file_last = b->file->info.st_size; b->last_in_chain = 1; b->file->log = r->connection->log; b->last_buf = 1; //清理文件句柄 /* ngx_pool_cleanup_t *cln = ngx_pool_cleanup_add(r->pool,sizeof(ngx_pool_cleanup_file_t)); if(cln == NULL){ return NGX_ERROR; } cln->handler = ngx_pool_cleanup_file; ngx_pool_cleanup_file_t *clnf = cln->data; clnf->fd = b->file->fd; clnf->name = b->file->name.data; clnf->log = r->pool->log; */ out->buf = b; out->next = NULL; rc = ngx_http_send_header(r); if(rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r,out); } } else{ ngx_str_t type = ngx_string("video/mp2t"); //ts文件的content type //ngx_str_t type = ngx_string("application/octet-stream"); char filename[512]; bzero(filename,512); ngx_snprintf((u_char*)filename,512,"%s%V.ts",media_path,&media_file); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"File[%s] is not exist!media_path = %s,media_file=%V",filename,media_path,&media_file); r->allow_ranges = 1; //开启range选项 char *start = ngx_http_hls_convert_string(media_start); char *end = ngx_http_hls_convert_string(media_end); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"start=%s;end=%s",start,end); ngx_chain_t *out = ngx_pcalloc(r->pool,sizeof(ngx_chain_t)); ngx_buf_t *b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b == NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->in_file = 1; b->file = ngx_pcalloc(r->pool,sizeof(ngx_file_t)); b->file->fd = ngx_open_file(filename,NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN,0); if(b->file->fd == -1){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file->name.data = (u_char*)filename; b->file->name.len = sizeof(filename)-1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = atol(end)-atol(start); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"%d",r->headers_out.content_length_n); r->headers_out.content_type = type; b->file_pos = atol(start); b->file_last= atol(end); b->last_in_chain = 1; b->file->log = r->connection->log; b->last_buf = 1; out->buf = b; out->next = NULL; rc = ngx_http_send_header(r); if(rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r,out); } } return NGX_OK; }
static void ngx_pipe_log(ngx_cycle_t *cycle, ngx_open_pipe_t *op) { ngx_int_t n_bytes_read; u_char *read_buf; size_t read_buf_len = 65536; ngx_fd_t log_fd = NGX_INVALID_FILE; #ifdef T_PIPE_NO_DISPLAY size_t title_len; #endif ngx_pipe_rollback_conf_t rbcf; ngx_file_info_t sb; size_t one_day = 24 * 60 * 60; ngx_pid = ngx_getpid(); rbcf.last_open_time = 0; rbcf.last_suit_time = 0; rbcf.log_size = 0; if (ngx_pipe_rollback_parse_args(cycle, op, &rbcf) != NGX_OK) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "log rollback parse error"); return; } read_buf = ngx_pcalloc(cycle->pool, read_buf_len); if (read_buf == NULL) { return; } //set title ngx_setproctitle((char *) op->cmd); #ifdef T_PIPE_NO_DISPLAY title_len = ngx_strlen(ngx_os_argv[0]); #if (NGX_SOLARIS) #else ngx_memset((u_char *) ngx_os_argv[0], NGX_SETPROCTITLE_PAD, title_len); ngx_cpystrn((u_char *) ngx_os_argv[0], op->cmd, title_len); #endif #endif for (;;) { if (ngx_terminate == 1) { return; } n_bytes_read = ngx_read_fd(0, read_buf, read_buf_len); if (n_bytes_read == 0) { return; } if (errno == EINTR) { continue; } else if (n_bytes_read < 0) { return; } rbcf.time_now = ngx_pipe_get_now_sec(); if (NULL != rbcf.suitpath) { if (rbcf.time_now / one_day > rbcf.last_suit_time / one_day) { ngx_pipe_create_suitpath(cycle, &rbcf); } } if (log_fd >= 0) { if (rbcf.interval > 0) { if (((rbcf.time_now - rbcf.adjust_time) / rbcf.interval) > (rbcf.last_open_time / rbcf.interval)) { //need check rollback ngx_close_file(log_fd); log_fd = NGX_INVALID_FILE; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need check rollback time [%s]", rbcf.logname); ngx_pipe_do_rollback(cycle, &rbcf); } } } if (log_fd >= 0 && rbcf.log_max_size > 0 && rbcf.log_size >= rbcf.log_max_size) { ngx_close_file(log_fd); log_fd = NGX_INVALID_FILE; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need check rollback size [%s] [%d]", rbcf.logname, rbcf.log_size); ngx_pipe_do_rollback(cycle, &rbcf); } /* If there is no log file open then open a new one. * */ if (log_fd < 0) { ngx_pipe_create_subdirs(rbcf.logname, cycle); if (rbcf.interval > 0 && rbcf.last_open_time == 0 && ((rbcf.time_now - rbcf.adjust_time_raw) / rbcf.interval < rbcf.time_now / rbcf.interval)) { /*just check when time is after interval and befor adjust_time_raw, fix when no backup file, do rollback */ //need check last rollback time, because other process may do rollback after when it adjust time more than this process ngx_pipe_get_last_rollback_time(&rbcf); } else { rbcf.last_open_time = ngx_pipe_get_now_sec(); } log_fd = ngx_open_file(rbcf.logname, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_PIPE_FILE_ACCESS); if (log_fd < 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "open [%s] failed", rbcf.logname); return; } if (0 == ngx_fd_info(log_fd, &sb)) { rbcf.log_size = sb.st_size; } } if (ngx_write_fd(log_fd, read_buf, n_bytes_read) != n_bytes_read) { if (errno != EINTR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "write to [%s] failed", rbcf.logname); return; } } rbcf.log_size += n_bytes_read; } }