ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size) { ngx_buf_t *b; if (!(b = ngx_calloc_buf(pool))) { return NULL; } if (!(b->start = ngx_palloc(pool, size))) { return NULL; } b->pos = b->start; b->last = b->start; b->end = b->last + size; b->temporary = 1; /* b->file_pos = 0; b->file_last = 0; b->file = NULL; b->shadow = NULL; b->tag = 0; */ return b; }
ngx_buf_t * ngx_create_temp_buf(ngx_pool_t *pool, size_t size) { ngx_buf_t *b; b = ngx_calloc_buf(pool); if (b == NULL) { return NULL; } b->start = ngx_palloc(pool, size); if (b->start == NULL) { return NULL; } /* * set by ngx_calloc_buf(): * * b->file_pos = 0; * b->file_last = 0; * b->file = NULL; * b->shadow = NULL; * b->tag = 0; * and flags */ b->pos = b->start; b->last = b->start; b->end = b->last + size; b->temporary = 1; return b; }
static int command_sendcontent(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { ngx_buf_t *b; ngx_chain_t out; Tcl_Obj *content; int rc; int len; ngx_http_request_t *r = getrequest(clientData); if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "content"); return TCL_ERROR; } content = objv[1]; b = ngx_calloc_buf(r->pool); if (b == NULL) { return TCL_ERROR; } out.buf = b; out.next = NULL; b->start = (u_char*)Tcl_GetByteArrayFromObj(content, &len); b->pos = b->start; b->end = b->last = b->start + len; b->memory = 1; b->last_buf = 1; b->last_in_chain = 1; rc = ngx_tcl_cleanup_add_Tcl_Obj(r->pool, content); if (rc != TCL_OK) { return rc; } if (!r->header_sent) { r->headers_out.content_length_n = len; if (r->headers_out.status == 0) { r->headers_out.status = 200; } ngx_http_send_header(r); /* TODO: CHECK RETURN */ } 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 void ngx_stream_return_handler(ngx_stream_session_t *s) { ngx_str_t text; ngx_buf_t *b; ngx_connection_t *c; ngx_stream_return_ctx_t *ctx; ngx_stream_return_srv_conf_t *rscf; c = s->connection; c->log->action = "returning text"; rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_return_module); if (ngx_stream_complex_value(s, &rscf->text, &text) != NGX_OK) { ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream return text: \"%V\"", &text); if (text.len == 0) { ngx_stream_finalize_session(s, NGX_STREAM_OK); return; } ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_return_ctx_t)); if (ctx == NULL) { ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } ngx_stream_set_ctx(s, ctx, ngx_stream_return_module); b = ngx_calloc_buf(c->pool); if (b == NULL) { ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } b->memory = 1; b->pos = text.data; b->last = text.data + text.len; b->last_buf = 1; ctx->out = ngx_alloc_chain_link(c->pool); if (ctx->out == NULL) { ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } ctx->out->buf = b; ctx->out->next = NULL; c->write->handler = ngx_stream_return_write_handler; ngx_stream_return_write_handler(c->write); }
// 先看free里是否有空闲节点,有则直接使用 // 如果没有,就从内存池的空闲链表里获取 ngx_chain_t * ngx_chain_get_free_buf(ngx_pool_t *p, ngx_chain_t **free) { ngx_chain_t *cl; if (*free) { cl = *free; *free = cl->next; cl->next = NULL; return cl; } cl = ngx_alloc_chain_link(p); if (cl == NULL) { return NULL; } cl->buf = ngx_calloc_buf(p); if (cl->buf == NULL) { return NULL; } cl->next = NULL; return cl; }
/*获取一个空的buff*/ ngx_chain_t * ngx_chain_get_free_buf(ngx_pool_t *p, ngx_chain_t **free) { ngx_chain_t *cl; /*如果本身存在free*/ if (*free) { cl = *free; *free = cl->next; /*调整指针*/ cl->next = NULL; return cl; } /*否者进行重新的生成*/ cl = ngx_alloc_chain_link(p); if (cl == NULL) { return NULL; } cl->buf = ngx_calloc_buf(p); if (cl->buf == NULL) { return NULL; } cl->next = NULL; return cl; }
/*创建一个临时缓冲区*/ ngx_buf_t * ngx_create_temp_buf(ngx_pool_t *pool, size_t size) { ngx_buf_t *b; /*创建的临时缓冲区都是归于pool系统中的这个句柄进行管理*/ b = ngx_calloc_buf(pool); if (b == NULL) { return NULL; } b->start = ngx_palloc(pool, size); /*buffer的开始地址,申请的大小是size*/ if (b->start == NULL) { return NULL; } /* * set by ngx_calloc_buf(): * * b->file_pos = 0; * b->file_last = 0; * b->file = NULL; * b->shadow = NULL; * b->tag = 0; * and flags */ b->pos = b->start; b->last = b->start; b->end = b->last + size; b->temporary = 1; /*标志为临时缓冲区,可以被改变*/ return b; }
static ngx_int_t ngx_http_breach_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"BREACH BODY FILTER: start!."); ngx_chain_t *chain_link; int chain_contains_last_buffer = 0; for (chain_link = in; chain_link; chain_link = chain_link->next) { if(chain_link->buf->last_buf) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"BREACH BODY FILTER: it's last buffer of chain!."); chain_contains_last_buffer = 1; } if(chain_link->next == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"BREACH BODY FILTER: no more chain!."); break; } } if(!chain_contains_last_buffer) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"BREACH BODY FILTER: it doesn't have last buffer!."); return ngx_http_next_body_filter(r, in); } ngx_buf_t *b; b = ngx_calloc_buf(r->pool); if(b==NULL){ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"BREACH BODY FILTER: can't allocate buffer!."); return NGX_ERROR; } u_char *breach_string = ngx_palloc(r->pool,sizeof(u_char)*30); breach_string = ngx_http_breach_string(r, breach_string); b->start = b->pos = (u_char *)breach_string; b->last = b->end = b->pos + sizeof(u_char)*ngx_strlen(breach_string); b->memory = 1; ngx_chain_t *added_link; added_link = ngx_alloc_chain_link(r->pool); if(added_link==NULL){ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"BREACH BODY FILTER: can't allocate chain link!."); return NGX_ERROR; } added_link->buf = b; added_link->next = NULL; added_link->buf->last_buf = 1; chain_link->buf->last_buf = 0; chain_link->next = added_link; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"BREACH BODY FILTER: end!."); return ngx_http_next_body_filter(r, in); }
ngx_int_t ngx_http_proxy_connect_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_http_proxy_connect_ctx_t *ctx; ngx_http_proxy_connect_loc_conf_t *pccf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_connect_module); if (!(r->method & (NGX_HTTP_CONNECT)) \ || ngx_http_proxy_connect_test_block_ports(r)) { return NGX_HTTP_NOT_ALLOWED; } if (pccf->black_hosts != NGX_CONF_UNSET_PTR) { if (NGX_OK == ngx_http_proxy_connect_test_black_hosts(r)) { return NGX_HTTP_NOT_ALLOWED; } } ngx_http_proxy_connect_buf.pos = ngx_http_proxy_connect_success.data; ngx_http_proxy_connect_buf.last = ngx_http_proxy_connect_success.data \ + ngx_http_proxy_connect_success.len; ngx_http_proxy_connect_buf.start = ngx_http_proxy_connect_success.data; ngx_http_proxy_connect_buf.end = ngx_http_proxy_connect_success.data \ + ngx_http_proxy_connect_success.len; ngx_http_proxy_connect_buf.last_buf = 1; ngx_http_proxy_connect_buf.memory = 1; rc = ngx_http_output_filter(r, &ngx_http_proxy_connect_chain); if (rc != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx = ngx_palloc(r->pool, sizeof(ngx_http_proxy_connect_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_proxy_connect_module); b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->start = ngx_palloc(r->pool, 4096); if (b->start == NULL) { return NGX_ERROR; } b->end = b->start + 4096; b->pos = b->start; b->last = b->pos; b->last_buf = 1; b->memory = 1; ctx->client_hello = b; r->main->count ++; r->read_event_handler = ngx_http_proxy_connect_read_hello_data; ngx_http_proxy_connect_read_hello_data(r); return NGX_DONE; }
/** * Output response body * */ int ngx_http_lua_ngx_echo(lua_State *l) { ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; lua_getglobal(l, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(l, -1); lua_pop(l, 1); if(r) { ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if(ctx != NULL && ctx->eof == 0) { const char *data; size_t len; ngx_buf_t *buf; ngx_chain_t *cl; // concatenate all args into single string // XXX: easy way to support multiple args, any serious performance penalties? lua_concat(l, lua_gettop(l)); data = lua_tolstring(l, -1, &len); if(data) { buf = ngx_calloc_buf(r->pool); if(buf == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-ngx-echo) can't allocate memory for output buffer!"); } else { // FIXME: is there any need to copy the content first? as // lua string will be invalid when it's poped out from // stack buf->start = buf->pos = (u_char*)data; buf->last = buf->end = (u_char*)(data + len); buf->memory = 1; cl = ngx_alloc_chain_link(r->pool); if(cl == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-ngx-echo) can't allocate memory for output chain-link!"); } else { cl->next = NULL; cl->buf = buf; ngx_http_lua_send_chain_link(r, ctx, cl); } } } // clear args lua_settop(l, 0); } } else { dd("(lua-ngx-echo) can't find nginx request object!"); } return 0; }
ngx_chain_t * ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs) { u_char *p; ngx_int_t i; ngx_buf_t *b; ngx_chain_t *chain, *cl, **ll; p = ngx_palloc(pool, bufs->num * bufs->size); if (p == NULL) { return NULL; } ll = &chain; // 创建 bufs->num 个大小为 bufs->size 的 buffer for (i = 0; i < bufs->num; i++) { b = ngx_calloc_buf(pool); if (b == NULL) { return NULL; } /* * set by ngx_calloc_buf(): * * b->file_pos = 0; * b->file_last = 0; * b->file = NULL; * b->shadow = NULL; * b->tag = 0; * and flags * */ b->pos = p; b->last = p; b->temporary = 1; b->start = p; p += bufs->size; b->end = p; cl = ngx_alloc_chain_link(pool); if (cl == NULL) { return NULL; } cl->buf = b; *ll = cl; ll = &cl->next; } *ll = NULL; return chain; }
static ngx_int_t ngx_http_foo_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_uint_t last; ngx_chain_t *cl, *nl; ngx_buf_t *buf; if(in == NULL || r->header_only) { return ngx_http_next_body_filter(r, in); } last = 0; for (cl = in; cl; cl = cl->next) { if(cl->buf->last_buf) { last = 1; cl->buf->last_in_chain = 1; cl->buf->last_buf = 0; cl->buf->sync = 1; break; } } if(!last) { return ngx_http_next_body_filter(r, in); } buf = ngx_calloc_buf(r->pool); if(buf == NULL) { return NGX_ERROR; } buf->pos = footer.data; buf->last = buf->pos + footer.len; buf->start = buf->pos; buf->end = buf->last; buf->last_buf = 1; buf->memory = 1; if(ngx_buf_size(cl->buf) == 0) { cl->buf = buf; } else { nl = ngx_alloc_chain_link(r->pool); if(nl == NULL) { return NGX_ERROR; } nl->buf = buf; nl->next = NULL; cl->next = nl; cl->buf->last_buf = 0; } return ngx_http_next_body_filter(r, in); }
static mrb_value ngx_http_mruby_rputs(mrb_state *mrb, mrb_value self) { mrb_value argv; ngx_buf_t *b; ngx_http_mruby_rputs_chain_list_t *chain; u_char *str; ngx_str_t ns; ngx_http_request_t *r; ngx_http_mruby_ctx_t *ctx; r = ngx_http_mruby_get_request(); ctx = ngx_http_get_module_ctx(r, ngx_http_mruby_module); mrb_get_args(mrb, "o", &argv); argv = mrb_obj_as_string(mrb, argv); ns.data = (u_char *)RSTRING_PTR(argv); ns.len = RSTRING_LEN(argv); if (ns.len == 0) { return self; } if (ctx->rputs_chain == NULL) { chain = ngx_pcalloc(r->pool, sizeof(ngx_http_mruby_rputs_chain_list_t)); chain->out = ngx_alloc_chain_link(r->pool); chain->last = &chain->out; } else { chain = ctx->rputs_chain; (*chain->last)->next = ngx_alloc_chain_link(r->pool); chain->last = &(*chain->last)->next; } b = ngx_calloc_buf(r->pool); (*chain->last)->buf = b; (*chain->last)->next = NULL; if ((str = ngx_pnalloc(r->pool, ns.len + 1)) == NULL) { return self; } ngx_memcpy(str, ns.data, ns.len); str[ns.len] = '\0'; (*chain->last)->buf->pos = str; (*chain->last)->buf->last = str + ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; if (r->headers_out.content_length_n == -1) { r->headers_out.content_length_n += ns.len + 1; } else { r->headers_out.content_length_n += ns.len; } return self; }
/** * Force flush out response content * */ static int ngx_http_lua_ngx_flush(lua_State *L) { ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_buf_t *buf; ngx_chain_t *cl; ngx_int_t rc; lua_getglobal(L, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(L, -1); lua_pop(L, 1); if (r == NULL) { return luaL_error(L, "no request object found"); } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { return luaL_error(L, "no request ctx found"); } if ((r->method & NGX_HTTP_HEAD) || r->header_only) { return 0; } if (ctx->eof) { return luaL_error(L, "already seen eof"); } buf = ngx_calloc_buf(r->pool); if (buf == NULL) { return luaL_error(L, "memory allocation error"); } buf->flush = 1; cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return luaL_error(L, "out of memory"); } cl->next = NULL; cl->buf = buf; rc = ngx_http_lua_send_chain_link(r, ctx, cl); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return luaL_error(L, "failed to send chain link: %d", (int) rc); } return 0; }
ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs) { u_char *p; ngx_int_t i; ngx_buf_t *b; ngx_chain_t *chain, *cl, **ll; if (!(p = ngx_palloc(pool, bufs->num * bufs->size))) { return NULL; } ll = &chain; for (i = 0; i < bufs->num; i++) { if (!(b = ngx_calloc_buf(pool))) { return NULL; } b->pos = p; b->last = p; b->temporary = 1; b->start = p; p += bufs->size; b->end = p; /* b->file_pos = 0; b->file_last = 0; b->file = NULL; b->shadow = NULL; b->tag = 0; */ if (!(cl = ngx_alloc_chain_link(pool))) { return NULL; } cl->buf = b; *ll = cl; ll = &cl->next; } *ll = NULL; return chain; }
static mrb_value ngx_mrb_rputs(mrb_state *mrb, mrb_value self) { mrb_value argv; ngx_buf_t *b; ngx_mrb_rputs_chain_list_t *chain; u_char *str; ngx_str_t ns; ngx_http_request_t *r = ngx_mrb_get_request(); ngx_http_mruby_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_mruby_module); mrb_get_args(mrb, "o", &argv); if (mrb_type(argv) != MRB_TT_STRING) { argv = mrb_funcall(mrb, argv, "to_s", 0, NULL); } ns.data = (u_char *)RSTRING_PTR(argv); ns.len = ngx_strlen(ns.data); if (ns.len == 0) { return self; } if (ctx->rputs_chain == NULL) { chain = ngx_pcalloc(r->pool, sizeof(ngx_mrb_rputs_chain_list_t)); chain->out = ngx_alloc_chain_link(r->pool); chain->last = &chain->out; } else { chain = ctx->rputs_chain; (*chain->last)->next = ngx_alloc_chain_link(r->pool); chain->last = &(*chain->last)->next; } b = ngx_calloc_buf(r->pool); (*chain->last)->buf = b; (*chain->last)->next = NULL; str = ngx_pstrdup(r->pool, &ns); str[ns.len] = '\0'; (*chain->last)->buf->pos = str; (*chain->last)->buf->last = str + ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; ngx_http_set_ctx(r, ctx, ngx_http_mruby_module); if (r->headers_out.content_length_n == -1) { r->headers_out.content_length_n += ns.len + 1; } else { r->headers_out.content_length_n += ns.len; } return self; }
static ngx_int_t ngx_http_minify_buf_in_memory(ngx_buf_t *buf,ngx_http_request_t *r) { ngx_buf_t *b = NULL, *dst = NULL, *min_dst = NULL; ngx_int_t size; size = buf->end - buf->start; dst = buf; dst->end[0] = 0; b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->start = ngx_palloc(r->pool, size); b->pos = b->start; b->last = b->start; b->end = b->last + size; b->temporary = 1; min_dst = b; if (ngx_strcmp(r->headers_out.content_type.data, ngx_http_minify_default_types[0].data) == 0) { jsmin(dst,min_dst); } else if (ngx_strcmp(r->headers_out.content_type.data, ngx_http_minify_default_types[1].data) == 0) { cssmin(dst,min_dst); } else { return NGX_HTTP_INTERNAL_SERVER_ERROR; } buf->start = min_dst->start; buf->pos = min_dst->pos; buf->last = min_dst->last; buf->end = min_dst->end; buf->memory = 1; buf->in_file = 0; return NGX_OK; }
static void ngx_http_dav_ext_output(ngx_http_request_t *r, ngx_chain_t **ll, ngx_int_t flags, u_char *data, ngx_uint_t len) { ngx_chain_t *cl; ngx_uint_t len_int; ngx_buf_t *b, *b_int /* internal buffer */; if (!len) { return; } if (flags & NGX_HTTP_DAV_EXT_ESCAPE) { len_int = len + ngx_escape_html(NULL, data, len); b_int = ngx_create_temp_buf(r->pool, len_int); b_int->last = (u_char*)ngx_escape_html(b_int->pos, data, len); len = len_int + ngx_http_dav_ext_escape_html(NULL, b_int->pos, len_int); b = ngx_create_temp_buf(r->pool, len); b->last = (u_char*)ngx_http_dav_ext_escape_html(b->pos, b_int->pos, len_int); ngx_pfree(r->pool, b_int); } else if (flags & NGX_HTTP_DAV_EXT_COPY) { b = ngx_create_temp_buf(r->pool, len); b->last = ngx_cpymem(b->pos, data, len); } else { b = ngx_calloc_buf(r->pool); b->memory = 1; b->pos = data; b->start = data; b->last = b->pos + len; b->end = b->last; } cl = ngx_alloc_chain_link(r->pool); cl->buf = b; cl->next = NULL; if (*ll != NULL) { cl->next = (*ll)->next; (*ll)->next = cl; *ll = cl; } else { *ll = cl; cl->next = cl; } }
static ngx_int_t ngx_http_echo_body_filter(ngx_http_request_t* r, ngx_chain_t* in) { /* 获取echo_times和current_echo_times */ ngx_http_echov4_loc_conf_t* echo_conf; ngx_chain_t* chain_link; ngx_chain_t* new_link; ngx_buf_t* new_buf; ngx_http_echov4_request_ctx_t* echo_ctx; int i; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ngx_echo_body_filter called - [rainx]"); echo_conf = ngx_http_get_module_loc_conf(r, ngx_http_echov4_module); // 我们模块运行时的上下文,如果没有的话,我们将不进行处理 echo_ctx = (ngx_http_echov4_request_ctx_t*) ngx_http_get_module_ctx(r, ngx_http_echov4_module); if (!echo_ctx || echo_ctx->current_echo_times >= echo_conf->echo_times){ return ngx_http_next_body_filter(r, in); } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ngx_http_echo_handler called[v2] - [rainx]\n" "Dump of ngx_http_echov4_loc_ctx_t current_echo_times=[%d]\n" "Dump of ngx_http_echov4_loc_conf_t echo_times=[%d]", echo_ctx->current_echo_times, echo_conf->echo_times ); chain_link = in; for ( i = 0 ; i < echo_conf->echo_times - echo_ctx->current_echo_times; i++) { new_link = ngx_alloc_chain_link(r->pool); new_buf = ngx_calloc_buf(r->pool); // 创建buffer并赋值 new_buf->pos = echo_ctx->post_content->data; new_buf->last = echo_ctx->post_content->data + echo_ctx->post_content->len; new_buf->memory = 1; new_buf->last_buf = 1; new_link->buf = new_buf; // 修改chain_link,将,新增的chain放到chain link的最前面 new_link->next = chain_link; chain_link = new_link; } echo_ctx->current_echo_times = echo_conf->echo_times; return ngx_http_next_body_filter(r, chain_link); }
size_t ngx_http_php_code_ub_write(const char *str, size_t str_length TSRMLS_DC) { ngx_buf_t *b; ngx_http_php_rputs_chain_list_t *chain; ngx_http_php_ctx_t *ctx; ngx_http_request_t *r; u_char *u_str; ngx_str_t ns; r = ngx_php_request; ctx = ngx_http_get_module_ctx(r, ngx_http_php_module); if (ctx->output_type & OUTPUT_CONTENT){ ns.data = (u_char *)str; ns.len = str_length; if (ctx->rputs_chain == NULL){ chain = ngx_pcalloc(r->pool, sizeof(ngx_http_php_rputs_chain_list_t)); chain->out = ngx_alloc_chain_link(r->pool); chain->last = &chain->out; }else { chain = ctx->rputs_chain; (*chain->last)->next = ngx_alloc_chain_link(r->pool); chain->last = &(*chain->last)->next; } b = ngx_calloc_buf(r->pool); (*chain->last)->buf = b; (*chain->last)->next = NULL; u_str = ngx_pstrdup(r->pool, &ns); //u_str[ns.len] = '\0'; (*chain->last)->buf->pos = u_str; (*chain->last)->buf->last = u_str + ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; ngx_http_set_ctx(r, ctx, ngx_http_php_module); if (r->headers_out.content_length_n == -1){ r->headers_out.content_length_n += ns.len + 1; }else { r->headers_out.content_length_n += ns.len; } } return r->headers_out.content_length_n; }
static ngx_int_t ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r, ngx_http_gunzip_ctx_t *ctx) { int rc; ngx_buf_t *b; ngx_chain_t *cl; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "gunzip inflate end"); rc = inflateEnd(&ctx->zstream); if (rc != Z_OK) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "inflateEnd() failed: %d", rc); return NGX_ERROR; } b = ctx->out_buf; if (ngx_buf_size(b) == 0) { b = ngx_calloc_buf(ctx->request->pool); if (b == NULL) { return NGX_ERROR; } } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; *ctx->last_out = cl; ctx->last_out = &cl->next; b->last_buf = (r == r->main) ? 1 : 0; b->last_in_chain = 1; b->sync = 1; ctx->done = 1; return NGX_OK; }
/** * Send last_buf, terminate output stream * */ int ngx_http_lua_ngx_eof(lua_State *l) { ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_buf_t *buf; ngx_chain_t *cl; lua_getglobal(l, GLOBALS_SYMBOL_REQUEST); r = lua_touserdata(l, -1); lua_pop(l, 1); if(r) { ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if(ctx != NULL && ctx->eof == 0) { ctx->eof = 1; // set eof flag to prevent further output buf = ngx_calloc_buf(r->pool); if(buf == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-ngx-eof) can't allocate memory for output buffer!"); } else { buf->last_buf = 1; cl = ngx_alloc_chain_link(r->pool); if(cl == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-ngx-eof) can't allocate memory for output chain-link!"); } else { cl->next = NULL; cl->buf = buf; ngx_http_lua_send_chain_link(r, ctx, cl); } } } } else { dd("(lua-ngx-eof) can't find nginx request object!"); } return 0; }
// make buffer with 32/64 bit Data Descriptor chunk, this follows files with incomplete headers ngx_chain_t* ngx_http_zip_data_descriptor_chain_link(ngx_http_request_t *r, ngx_http_zip_piece_t *piece, ngx_http_zip_range_t *range) { ngx_chain_t *link; ngx_buf_t *b; ngx_http_zip_file_t *file = piece->file; size_t struct_size = file->need_zip64? sizeof(ngx_zip_data_descriptor_zip64_t) : sizeof(ngx_zip_data_descriptor_t); union { ngx_zip_data_descriptor_t descriptor; ngx_zip_data_descriptor_zip64_t descriptor64; } data; if ((link = ngx_alloc_chain_link(r->pool)) == NULL || (b = ngx_calloc_buf(r->pool)) == NULL || (b->pos = ngx_palloc(r->pool, struct_size)) == NULL) return NULL; b->memory = 1; b->last = b->pos + struct_size; if (!file->need_zip64) { data.descriptor = ngx_zip_data_descriptor_template; data.descriptor.signature = htole32(data.descriptor.signature); data.descriptor.crc32 = htole32(file->crc32); data.descriptor.compressed_size = data.descriptor.uncompressed_size = htole32(file->size); } else { data.descriptor64 = ngx_zip_data_descriptor_zip64_template; data.descriptor64.signature = htole32(data.descriptor64.signature); data.descriptor64.crc32 = htole32(file->crc32); data.descriptor64.compressed_size = data.descriptor64.uncompressed_size = htole64(file->size); } ngx_memcpy(b->pos, &data, struct_size); ngx_http_zip_truncate_buffer(b, &piece->range, range); link->buf = b; link->next = NULL; return link; }
static ngx_int_t ngx_xlog_redis_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { if (r != r->main) { return ngx_http_next_body_filter(r, in); } ngx_chain_t *chain_link; int chain_contains_last_buffer = 0; for ( chain_link = in; chain_link != NULL; chain_link = chain_link->next ) { if (chain_link->buf->last_buf) { chain_contains_last_buffer = 1; break; } } if (!chain_contains_last_buffer) return ngx_http_next_body_filter(r, in); ngx_buf_t *b; b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->pos = (u_char *) "Nginx-HelightXu\n"; b->last = b->pos + sizeof("Nginx-HelightXu\n") - 1; b->memory = 1; b->last_buf = 1; ngx_chain_t *added_link; added_link = ngx_alloc_chain_link(r->pool); if (added_link == NULL) return NGX_ERROR; added_link->buf = b; added_link->next = NULL; chain_link->next = added_link; chain_link->buf->last_buf = 0; added_link->buf->last_buf = 1; return ngx_http_next_body_filter(r, in); }
ngx_int_t ngx_http_echo_exec_echo_sync(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx) { ngx_buf_t *buf; ngx_chain_t *cl = NULL; /* the head of the chain link */ buf = ngx_calloc_buf(r->pool); if (buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } buf->sync = 1; cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->buf = buf; cl->next = NULL; return ngx_http_echo_send_chain_link(r, ctx, cl); }
static ngx_int_t ngx_http_zip_send_boundary(ngx_http_request_t *r, ngx_http_zip_ctx_t *ctx, ngx_http_zip_range_t *range) { ngx_chain_t *link; ngx_buf_t *b; if (range->boundary_sent) return NGX_OK; if ((link = ngx_alloc_chain_link(r->pool)) == NULL || (b = ngx_calloc_buf(r->pool)) == NULL) return NGX_ERROR; b->memory = 1; b->pos = range->boundary_header.data; b->last = b->pos + range->boundary_header.len; link->buf = b; link->next = NULL; range->boundary_sent = 1; return ngx_http_next_body_filter(r, link); }
static ngx_int_t ngx_http_zip_send_final_boundary(ngx_http_request_t *r, ngx_http_zip_ctx_t *ctx) { size_t len; ngx_chain_t *link; ngx_buf_t *b; if ((link = ngx_alloc_chain_link(r->pool)) == NULL || (b = ngx_calloc_buf(r->pool)) == NULL) return NGX_ERROR; len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + sizeof("--" CRLF) - 1; b->memory = 1; if ((b->pos = ngx_palloc(r->pool, len)) == NULL) return NGX_ERROR; b->last = ngx_sprintf(b->pos, CRLF "--%0muA--" CRLF, ctx->boundary); link->buf = b; link->next = NULL; return ngx_http_next_body_filter(r, link); }
static ngx_int_t ngx_http_subs_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_log_t *log; ngx_chain_t *cl, *temp; ngx_http_subs_ctx_t *ctx; ngx_http_subs_loc_conf_t *slcf; log = r->connection->log; slcf = ngx_http_get_module_loc_conf(r, ngx_http_subs_filter_module); if (slcf == NULL) { return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_subs_filter_module); if (ctx == NULL) { return ngx_http_next_body_filter(r, in); } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http subs filter \"%V\"", &r->uri); if (in == NULL && ctx->busy == NULL) { return ngx_http_next_body_filter(r, in); } if (ngx_http_subs_body_filter_init_context(r, in) != NGX_OK){ goto failed; } for (cl = ctx->in; cl; cl = cl->next) { if (cl->buf->last_buf || cl->buf->last_in_chain){ ctx->last = 1; } /* TODO: check the flush flag */ rc = ngx_http_subs_body_filter_process_buffer(r, cl->buf); if (rc == NGX_DECLINED) { continue; } else if (rc == NGX_ERROR) { goto failed; } if (cl->next != NULL) { continue; } if (ctx->last) { /* copy line_in to ctx->out. */ if (ngx_buf_size(ctx->line_in) > 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "[subs_filter] Lost last linefeed, output anyway."); if (ngx_http_subs_out_chain_append(r, ctx, ctx->line_in) != NGX_OK) { goto failed; } } if (ctx->out_buf == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "[subs_filter] The last buffer is zero size."); /* * This is a zero buffer, it should not be set the temporary * or memory flag * */ ctx->out_buf = ngx_calloc_buf(r->pool); if (ctx->out_buf == NULL) { goto failed; } ctx->out_buf->sync = 1; temp = ngx_alloc_chain_link(r->pool); if (temp == NULL) { goto failed; } temp->buf = ctx->out_buf; temp->next = NULL; *ctx->last_out = temp; ctx->last_out = &temp->next; } ctx->out_buf->last_buf = (r == r->main) ? 1 : 0; ctx->out_buf->last_in_chain = cl->buf->last_in_chain; break; } } /* It doesn't output anything, return */ if ((ctx->out == NULL) && (ctx->busy == NULL)) { return NGX_OK; } return ngx_http_subs_output(r, ctx, in); failed: ngx_log_error(NGX_LOG_ERR, log, 0, "[subs_filter] ngx_http_subs_body_filter error."); return NGX_ERROR; }
static ngx_int_t ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { u_char *chunk; off_t size; ngx_buf_t *b; ngx_chain_t out, tail, *cl, *tl, **ll; if (in == NULL || !r->chunked || r->header_only) { return ngx_http_next_body_filter(r, in); } out.buf = NULL; ll = &out.next; size = 0; cl = in; for ( ;; ) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http chunk: %d", ngx_buf_size(cl->buf)); size += ngx_buf_size(cl->buf); if (cl->buf->flush || cl->buf->sync || ngx_buf_in_memory(cl->buf) || cl->buf->in_file) { tl = ngx_alloc_chain_link(r->pool); if (tl == NULL) { return NGX_ERROR; } tl->buf = cl->buf; *ll = tl; ll = &tl->next; } if (cl->next == NULL) { break; } cl = cl->next; } if (size) { b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } /* the "0000000000000000" is 64-bit hexadimal string */ chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1); if (chunk == NULL) { return NGX_ERROR; } b->temporary = 1; b->pos = chunk; b->last = ngx_sprintf(chunk, "%xO" CRLF, size); out.buf = b; } if (cl->buf->last_buf) { b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->memory = 1; b->last_buf = 1; b->pos = (u_char *) CRLF "0" CRLF CRLF; b->last = b->pos + 7; cl->buf->last_buf = 0; if (size == 0) { b->pos += 2; out.buf = b; out.next = NULL; return ngx_http_next_body_filter(r, &out); } } else { if (size == 0) { *ll = NULL; return ngx_http_next_body_filter(r, out.next); } b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->memory = 1; b->pos = (u_char *) CRLF; b->last = b->pos + 2; } tail.buf = b; tail.next = NULL; *ll = &tail; return ngx_http_next_body_filter(r, &out); }
static ngx_int_t ngx_http_range_multipart_body(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in) { ngx_buf_t *b, *buf; ngx_uint_t i; ngx_chain_t *out, *hcl, *rcl, *dcl, **ll; ngx_http_range_t *range; ll = &out; buf = in->buf; range = ctx->ranges.elts; for (i = 0; i < ctx->ranges.nelts; i++) { /* * The boundary header of the range: * CRLF * "--0123456789" CRLF * "Content-Type: image/jpeg" CRLF * "Content-Range: bytes " */ b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->memory = 1; b->pos = ctx->boundary_header.data; b->last = ctx->boundary_header.data + ctx->boundary_header.len; hcl = ngx_alloc_chain_link(r->pool); if (hcl == NULL) { return NGX_ERROR; } hcl->buf = b; /* "SSSS-EEEE/TTTT" CRLF CRLF */ b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->temporary = 1; b->pos = range[i].content_range.data; b->last = range[i].content_range.data + range[i].content_range.len; rcl = ngx_alloc_chain_link(r->pool); if (rcl == NULL) { return NGX_ERROR; } rcl->buf = b; /* the range data */ b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->in_file = buf->in_file; b->temporary = buf->temporary; b->memory = buf->memory; b->mmap = buf->mmap; b->file = buf->file; if (buf->in_file) { b->file_pos = buf->file_pos + range[i].start; b->file_last = buf->file_pos + range[i].end; } if (ngx_buf_in_memory(buf)) { b->pos = buf->pos + (size_t) range[i].start; b->last = buf->pos + (size_t) range[i].end; } dcl = ngx_alloc_chain_link(r->pool); if (dcl == NULL) { return NGX_ERROR; } dcl->buf = b; *ll = hcl; hcl->next = rcl; rcl->next = dcl; ll = &dcl->next; } /* the last boundary CRLF "--0123456789--" CRLF */ b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->temporary = 1; b->last_buf = 1; b->pos = ngx_pnalloc(r->pool, sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + sizeof("--" CRLF) - 1); if (b->pos == NULL) { return NGX_ERROR; } b->last = ngx_cpymem(b->pos, ctx->boundary_header.data, sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN); *b->last++ = '-'; *b->last++ = '-'; *b->last++ = CR; *b->last++ = LF; hcl = ngx_alloc_chain_link(r->pool); if (hcl == NULL) { return NGX_ERROR; } hcl->buf = b; hcl->next = NULL; *ll = hcl; return ngx_http_next_body_filter(r, out); }