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); }
static void ngx_stream_return_handler(ngx_stream_session_t *s) { ngx_str_t text; 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_close_connection(c); return; } ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream return text: \"%V\"", &text); if (text.len == 0) { ngx_stream_close_connection(c); return; } ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_return_ctx_t)); if (ctx == NULL) { ngx_stream_close_connection(c); return; } ngx_stream_set_ctx(s, ctx, ngx_stream_return_module); ctx->buf.pos = text.data; ctx->buf.last = text.data + text.len; c->write->handler = ngx_stream_return_write_handler; ngx_stream_return_write_handler(c->write); }
static ngx_int_t ngx_stream_write_filter(ngx_stream_session_t *s, ngx_chain_t *in, ngx_uint_t from_upstream) { off_t size; ngx_uint_t last, flush, sync; ngx_chain_t *cl, *ln, **ll, **out, *chain; ngx_connection_t *c; ngx_stream_write_filter_ctx_t *ctx; ctx = ngx_stream_get_module_ctx(s, ngx_stream_write_filter_module); if (ctx == NULL) { ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_stream_write_filter_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_stream_set_ctx(s, ctx, ngx_stream_write_filter_module); } if (from_upstream) { c = s->connection; out = &ctx->from_upstream; } else { c = s->upstream->peer.connection; out = &ctx->from_downstream; } if (c->error) { return NGX_ERROR; } size = 0; flush = 0; sync = 0; last = 0; ll = out; /* find the size, the flush point and the last link of the saved chain */ for (cl = *out; cl; cl = cl->next) { ll = &cl->next; ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, "write old buf t:%d f:%d %p, pos %p, size: %z " "file: %O, size: %O", cl->buf->temporary, cl->buf->in_file, cl->buf->start, cl->buf->pos, cl->buf->last - cl->buf->pos, cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); #if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " "t:%d r:%d f:%d %p %p-%p %p %O-%O", cl->buf->temporary, cl->buf->recycled, cl->buf->in_file, cl->buf->start, cl->buf->pos, cl->buf->last, cl->buf->file, cl->buf->file_pos, cl->buf->file_last); ngx_debug_point(); return NGX_ERROR; } #endif size += ngx_buf_size(cl->buf); if (cl->buf->flush || cl->buf->recycled) { flush = 1; } if (cl->buf->sync) { sync = 1; } if (cl->buf->last_buf) { last = 1; } } /* add the new chain to the existent one */ for (ln = in; ln; ln = ln->next) { cl = ngx_alloc_chain_link(c->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = ln->buf; *ll = cl; ll = &cl->next; ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, "write new buf t:%d f:%d %p, pos %p, size: %z " "file: %O, size: %O", cl->buf->temporary, cl->buf->in_file, cl->buf->start, cl->buf->pos, cl->buf->last - cl->buf->pos, cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); #if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " "t:%d r:%d f:%d %p %p-%p %p %O-%O", cl->buf->temporary, cl->buf->recycled, cl->buf->in_file, cl->buf->start, cl->buf->pos, cl->buf->last, cl->buf->file, cl->buf->file_pos, cl->buf->file_last); ngx_debug_point(); return NGX_ERROR; } #endif size += ngx_buf_size(cl->buf); if (cl->buf->flush || cl->buf->recycled) { flush = 1; } if (cl->buf->sync) { sync = 1; } if (cl->buf->last_buf) { last = 1; } } *ll = NULL; ngx_log_debug3(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream write filter: l:%ui f:%ui s:%O", last, flush, size); if (size == 0 && !(c->buffered & NGX_LOWLEVEL_BUFFERED) && !(last && c->need_last_buf)) { if (last || flush || sync) { for (cl = *out; cl; /* void */) { ln = cl; cl = cl->next; ngx_free_chain(c->pool, ln); } *out = NULL; c->buffered &= ~NGX_STREAM_WRITE_BUFFERED; return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, c->log, 0, "the stream output chain is empty"); ngx_debug_point(); return NGX_ERROR; } chain = c->send_chain(c, *out, 0); ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream write filter %p", chain); if (chain == NGX_CHAIN_ERROR) { c->error = 1; return NGX_ERROR; } for (cl = *out; cl && cl != chain; /* void */) { ln = cl; cl = cl->next; ngx_free_chain(c->pool, ln); } *out = chain; if (chain) { if (c->shared) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "shared connection is busy"); return NGX_ERROR; } c->buffered |= NGX_STREAM_WRITE_BUFFERED; return NGX_AGAIN; } c->buffered &= ~NGX_STREAM_WRITE_BUFFERED; if (c->buffered & NGX_LOWLEVEL_BUFFERED) { return NGX_AGAIN; } return NGX_OK; }
ngx_int_t ngx_stream_upm_init_worker(ngx_cycle_t * cycle) { u_char *p; //ngx_int_t rc; ngx_connection_t *c; //ngx_connection_t *pc; ngx_stream_upm_ctx_t *ctx; ngx_stream_session_t *fake_session; ngx_stream_upstream_t *u; //ngx_peer_connection_t *peer; ngx_stream_upm_main_conf_t *ummcf; ngx_stream_upstream_srv_conf_t *uscf; //Fake a client session ummcf = ngx_stream_cycle_get_module_main_conf(cycle, ngx_stream_upm_module); ummcf->fake_session = ngx_pcalloc(cycle->pool, sizeof(ngx_stream_session_t)); if (ummcf->fake_session == NULL) { return NGX_ERROR; } fake_session = ummcf->fake_session; //Fake the client fd as 254 c = ngx_get_connection(254, cycle->log); if (c == NULL) { return NGX_ERROR; } //Set the fake conn's base items c->pool = cycle->pool; c->log = cycle->log; fake_session->signature = NGX_STREAM_MODULE; fake_session->main_conf = ((ngx_stream_conf_ctx_t *)cycle->conf_ctx)->main_conf; fake_session->srv_conf = ((ngx_stream_conf_ctx_t *)cycle->conf_ctx)->srv_conf; fake_session->connection = c; c->data = fake_session; u = ngx_pcalloc(c->pool, sizeof(ngx_stream_upstream_t)); if (u == NULL) { return NGX_ERROR; } fake_session->upstream = u; //Init the upm ctx; fake_session->ctx = ngx_pcalloc(cycle->pool, sizeof(void *) * ngx_stream_max_module); if (fake_session->ctx == NULL) { return NGX_ERROR; } ctx = ngx_pcalloc(cycle->pool, sizeof(ngx_stream_upm_ctx_t)); ngx_stream_set_ctx(fake_session, ctx, ngx_stream_upm_module); ctx->state = CONNECT; ctx->connect = ngx_stream_upm_connect; ctx->create_request = ngx_stream_upm_create_request; ctx->send_request = ngx_stream_upm_send_request; ctx->read_and_parse_response = ngx_stream_upm_read_and_parse_response; //ctx->process_response = ngx_stream_upm_process_response; u->peer.log = cycle->log; u->peer.log_error = NGX_ERROR_ERR; //whitout need set the local u->peer.local = NULL; uscf = ummcf->upstream; if (uscf->peer.init(fake_session, uscf) != NGX_OK) { return NGX_ERROR; } u->peer.start_time = ngx_current_msec; if (ummcf->next_upstream_tries && u->peer.tries > ummcf->next_upstream_tries) { u->peer.tries = ummcf->next_upstream_tries; } u->start_sec = ngx_time(); //May without need alloc the downstream_buf p = ngx_pnalloc(c->pool, ummcf->buffer_size); if (p == NULL) { return NGX_ERROR; } //web use the downstream_buf to buffer the request; u->downstream_buf.start = p; u->downstream_buf.end = p + ummcf->buffer_size; u->downstream_buf.pos = p; u->downstream_buf.last = p; c->write->handler = ngx_stream_upm_empty_handler; c->read->handler = ngx_stream_upm_empty_handler; return ngx_stream_upm_connect(fake_session); }
/* static void ngx_app_empty_handler(ngx_event_t *wev) { } */ static void ngx_app_wait_request_handler(ngx_event_t *ev) { ngx_connection_t *c; ngx_stream_session_t *s; ngx_stream_app_main_conf_t *cscf; ngx_stream_app_srv_conf_t *ascf; ngx_stream_app_ctx_t *s_ctx; ngx_app_task_t *t; ngx_buf_t *b; ngx_str_t log_buf; ssize_t n; size_t size; u_char *tmp; c = ev->data; s = c->data; if (ev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); ngx_stream_close_connection(c); return; } if (c->close) { ngx_stream_close_connection(c); return; } cscf = ngx_stream_get_module_main_conf(s, ngx_stream_app_module); ascf = ngx_stream_get_module_srv_conf(s, ngx_stream_app_module); s_ctx = ngx_stream_get_module_ctx(s,ngx_stream_app_module); if(s_ctx == NULL){ s_ctx = ngx_palloc(c->pool, sizeof(ngx_stream_app_ctx_t)); if(s_ctx == NULL) return; s_ctx->header = 0; ngx_stream_set_ctx(s,s_ctx,ngx_stream_app_module); } b = c->buffer; if (b == NULL) { size = ascf->header_len; b = ngx_create_temp_buf(c->pool, size); if (b == NULL) { ngx_stream_close_connection(c); return; } c->buffer = b; } else if (b->start == NULL) { size = s_ctx->header == 0?ascf->header_len:s_ctx->body_len; b->start = ngx_palloc(c->pool, size); if (b->start == NULL) { ngx_stream_close_connection(c); return; } b->pos = b->start; b->last = b->start; b->end = b->last + size; } else { size = ascf->header_len + s_ctx->body_len - s->received; // size = b->end - b->last; } n = c->recv(c, b->last, size); if (n == NGX_AGAIN) { if (!c->read->timer_set) { ngx_add_timer(c->read, ascf->client_timeout); } if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_stream_close_connection(c); return; } return; } if (n == NGX_ERROR) { ngx_stream_close_connection(c); return; } if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection"); ngx_stream_close_connection(c); return; } b->last += n; s->received +=n; c->log->action = "reading client request line"; log_buf.len = s->received; log_buf.data = b->start; ngx_log_error(NGX_LOG_ALERT, c->log, 0, "%d recved [%V],[%d:%d]",n,&log_buf,b->end,b->last); if(b->end != b->last){ if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_stream_close_connection(c); return; } } else { if(s_ctx->header == 0){ s_ctx->body_len = ngx_atoi(b->start,ascf->header_len); s_ctx->header = 1; if(s_ctx->body_len > 0 ){ tmp = ngx_pcalloc(c->pool, ascf->header_len + s_ctx->body_len); if (tmp == NULL) { ngx_stream_close_connection(c); return; } ngx_memcpy(tmp,b->start,ascf->header_len); ngx_pfree(c->pool, b->start); b->start = tmp; b->pos = b->start + ascf->header_len; b->last = b->pos; b->end = b->last + s_ctx->body_len; ngx_app_wait_request_handler(ev); } else{ ngx_log_error(NGX_LOG_INFO, c->log, 0, "empty request body"); ngx_stream_close_connection(c); return; } ngx_log_error(NGX_LOG_ALERT, c->log, 0, "recv header,len[%d]",s_ctx->body_len); } else{ // c->read->handler = ngx_app_empty_handler; t = (ngx_app_task_t *)ngx_thread_task_alloc(c->pool, sizeof(ngx_app_task_t) - sizeof(ngx_thread_task_t)); if(t == NULL){ ngx_log_error(NGX_LOG_ERR, c->log, 0, "create thread task failed"); ngx_stream_close_connection(c); } t->data = s; t->task.handler = ngx_stream_app_process; t->task.event.handler = ngx_stream_app_finalize; t->task.event.data= c; ngx_log_error(NGX_LOG_ALERT, c->log, 0, "t->data[%d]=[%d][%d]",t->data,t->task.ctx,t); if(ngx_thread_task_post(cscf->tp,(ngx_thread_task_t *)t) != NGX_OK){ ngx_log_error(NGX_LOG_ERR, c->log, 0, "post task to thread pool failed"); ngx_stream_close_connection(c); return; } ngx_log_error(NGX_LOG_ALERT, c->log, 0, "after post task"); } } return; }
static ngx_int_t ngx_stream_ssl_preread_handler(ngx_stream_session_t *s) { u_char *last, *p; size_t len; ngx_int_t rc; ngx_connection_t *c; ngx_stream_ssl_preread_ctx_t *ctx; ngx_stream_ssl_preread_srv_conf_t *sscf; c = s->connection; ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "ssl preread handler"); sscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_preread_module); if (!sscf->enabled) { return NGX_DECLINED; } if (c->type != SOCK_STREAM) { return NGX_DECLINED; } if (c->buffer == NULL) { return NGX_AGAIN; } ctx = ngx_stream_get_module_ctx(s, ngx_stream_ssl_preread_module); if (ctx == NULL) { ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_ssl_preread_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_stream_set_ctx(s, ctx, ngx_stream_ssl_preread_module); ctx->pool = c->pool; ctx->log = c->log; ctx->pos = c->buffer->pos; } p = ctx->pos; last = c->buffer->last; while (last - p >= 5) { if (p[0] != 0x16) { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, "ssl preread: not a handshake"); return NGX_DECLINED; } if (p[1] != 3) { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, "ssl preread: unsupported SSL version"); return NGX_DECLINED; } len = (p[3] << 8) + p[4]; /* read the whole record before parsing */ if ((size_t) (last - p) < len + 5) { break; } p += 5; rc = ngx_stream_ssl_preread_parse_record(ctx, p, p + len); if (rc != NGX_AGAIN) { return rc; } p += len; } ctx->pos = p; return NGX_AGAIN; }