void ngx_rtmp_client_handshake(ngx_rtmp_session_t *s, unsigned async) { ngx_connection_t *c; c = s->connection; c->read->handler = ngx_rtmp_handshake_recv; c->write->handler = ngx_rtmp_handshake_send; ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "handshake: start client handshake"); s->hs_buf = ngx_rtmp_alloc_handshake_buffer(s); s->hs_stage = NGX_RTMP_HANDSHAKE_CLIENT_SEND_CHALLENGE; if (ngx_rtmp_handshake_create_challenge(s, ngx_rtmp_client_version, &ngx_rtmp_client_partial_key) != NGX_OK) { ngx_rtmp_finalize_session(s); return; } if (async) { ngx_add_timer(c->write, s->timeout); if (ngx_handle_write_event(c->write, 0) != NGX_OK) { ngx_rtmp_finalize_session(s); } return; } ngx_rtmp_handshake_send(c->write); }
void ss_ftp_cmd_link_add_chain(ss_ftp_request *r, ngx_chain_t *chain) { assert(r != NULL); ngx_event_t *send; ngx_connection_t *conn; ngx_int_t rc; conn = (ngx_connection_t *) r->connection; rc = ss_ftp_write(conn, r->cmd_link_write, chain); assert(rc == NGX_AGAIN || rc == NGX_OK || rc == NGX_ERROR); if (NGX_AGAIN == rc) { send = conn->write; ngx_handle_write_event(send, 0); /* Data transmited ok. */ } else if (NGX_OK == rc) { /* TODO */ //ngx_del_event(); } else { assert(rc == NGX_ERROR); /* TODO : error handling, such as peer shut down */ ngx_log_debug0(NGX_LOG_DEBUG_FTP, conn->log, 0, "ftp:write error"); } }
__attribute__((unused)) static void transfer_to_game_srv(conn_node_data *conn_node) { move_chain(&conn_node->recv, &game_srv_session->send); ngx_connection_t *c = game_srv_session->session->connection; if (ngx_handle_write_event(c->write, 0) != NGX_OK) conn_srv_close_connection(c); }
static void ngx_http_gettoken_connect_handler(ngx_event_t *wev) { ngx_connection_t *conn; ngx_http_gettoken_connection_t *c; int keepalive; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http_gettoken: Connect handler"); conn = wev->data; c = conn->data; if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_http_gettoken_close_connection(c); return; } keepalive = 1; if (setsockopt(conn->fd, SOL_SOCKET, SO_KEEPALIVE, (const void *) &keepalive, sizeof(int)) == -1) { ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, "http_gettoken: setsockopt(SO_KEEPALIVE) failed"); } ngx_http_gettoken_connection_established(c); }
static void ngx_http_limit_req_delay(ngx_http_request_t *r) { ngx_event_t *wev; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "limit_req delay"); wev = r->connection->write; if (!wev->timedout) { if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); } return; } wev->timedout = 0; if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } r->read_event_handler = ngx_http_block_reading; r->write_event_handler = ngx_http_core_run_phases; ngx_http_core_run_phases(r); }
static void transfer_to_login_srv(conn_node_data *conn_node) { move_chain(&conn_node->recv, &login_srv_session->send); ngx_connection_t *c = login_srv_session->session->connection; if (ngx_handle_write_event(c->write, 0) != NGX_OK) conn_srv_close_connection(c); }
void ngx_tcp_send(ngx_event_t *wev) { ngx_int_t rc; ngx_connection_t *c; ngx_tcp_session_t *s; ngx_tcp_core_srv_conf_t *cscf; c = wev->data; s = c->data; if (wev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "%s|%d|%s|client timed out",__FILE__, __LINE__, __FUNCTION__); c->timedout = 1; ngx_tcp_close_connection(c); return; } if (s->output_buffer_chain == NULL) { return; } // rc = s->output_ctx->output_filter(s->output_ctx->filter_ctx, //s->output_buffer_chain); rc = s->output_ctx->output_filter(s); ngx_chain_update_chains(s->output_ctx->pool, &s->output_ctx->free, &s->output_ctx->busy, &s->output_buffer_chain, s->output_ctx->tag); s->output_buffer_chain = NULL; if (rc == NGX_OK || rc == NGX_DONE) { if (wev->timer_set) { ngx_del_timer(wev); } return; } if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "ngx_tcp_send|client=%V\n", &c->addr_text); ngx_tcp_close_connection(c); return; } /* rc == NGX_AGAIN */ /* ngx_log_error(NGX_LOG_INFO, c->log, 0, "ngx_tcp_send|NGX_AGAIN|client=%V\n", &c->addr_text); */ cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); ngx_add_timer(c->write, cscf->timeout); if (ngx_handle_write_event(c->write, 0) != NGX_OK) { ngx_tcp_close_connection(c); return; } }
/* static void ngx_http_gettoken_reply_connection(ngx_http_gettoken_connection_t *c, int error_code, char* error_msg) { ngx_http_gettoken_ctx_t *ctx = c->rctx; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_gettoken: LDAP request to \"%V\" has finished", &c->server->alias); ctx->replied = 1; ctx->error_code = error_code; if (error_msg) { ctx->error_msg.len = ngx_strlen(error_msg); ctx->error_msg.data = ngx_palloc(ctx->r->pool, ctx->error_msg.len); ngx_memcpy(ctx->error_msg.data, error_msg, ctx->error_msg.len); } else { ctx->error_msg.len = 0; ctx->error_msg.data = NULL; } ngx_http_gettoken_wake_request(ctx->r); } */ static void ngx_http_gettoken_dummy_write_handler(ngx_event_t *wev) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http_gettoken: Dummy write handler"); if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_http_gettoken_close_connection(((ngx_connection_t *) wev->data)->data); } }
__attribute__((unused)) static void transfer_to_player(conn_node_data *conn_node, uint64_t player_id) { conn_node_data *client = get_client_by_playerid(player_id); if (!client || client->session) return; move_chain(&conn_node->recv, &client->send); ngx_connection_t *c = client->session->connection; if (ngx_handle_write_event(c->write, 0) != NGX_OK) conn_srv_close_connection(c); }
static void transfer_to_client_fd(conn_node_data *conn_node, uint32_t fd) { assert(fd <= UINT16_MAX); conn_node_data *client = &client_session[fd]; if (client->session) return; move_chain(&conn_node->recv, &client->send); ngx_connection_t *c = client->session->connection; if (ngx_handle_write_event(c->write, 0) != NGX_OK) conn_srv_close_connection(c); }
static ngx_int_t nchan_output_filter_generic(ngx_http_request_t *r, nchan_msg_t *msg, ngx_chain_t *in) { /* from push stream module, written by * Wandenberg Peixoto <*****@*****.**>, Rogério Carvalho Schneider <*****@*****.**> * thanks, guys! * modified to fit the needs of websockets and eventsources and multipartses and so on */ ngx_http_core_loc_conf_t *clcf; ngx_int_t rc; ngx_event_t *wev; ngx_connection_t *c; nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_nchan_module); c = r->connection; wev = c->write; if(ctx->bcp) { nchan_bufchain_pool_refresh_files(ctx->bcp); } rc = ngx_http_output_filter(r, in); //ERR("outpuit filter plz"); if (c->buffered & NGX_HTTP_LOWLEVEL_BUFFERED) { //ERR("what's the deal with this NGX_HTTP_LOWLEVEL_BUFFERED thing?"); clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); r->write_event_handler = nchan_flush_pending_output; if(msg) { nchan_output_reserve_message_queue(r, msg); } if (!wev->delayed) { //ERR("delay output by %ims", clcf->send_timeout); ngx_add_timer(wev, clcf->send_timeout); } if ((ngx_handle_write_event(wev, clcf->send_lowat)) != NGX_OK) { flush_all_the_reserved_things(ctx); return NGX_ERROR; } return NGX_OK; } else { if (wev->timer_set) { //ERR("nevermind timer"); ngx_del_timer(wev); } } if(r->out == NULL) { flush_all_the_reserved_things(ctx); } return rc; }
static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev) { ssize_t n, size; ngx_connection_t *c; ngx_ssl_ocsp_ctx_t *ctx; c = wev->data; ctx = c->data; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0, "ssl ocsp write handler"); if (wev->timedout) { ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT, "OCSP responder timed out"); ngx_ssl_ocsp_error(ctx); return; } size = ctx->request->last - ctx->request->pos; n = ngx_send(c, ctx->request->pos, size); if (n == NGX_ERROR) { ngx_ssl_ocsp_error(ctx); return; } if (n > 0) { ctx->request->pos += n; if (n == size) { wev->handler = ngx_ssl_ocsp_dummy_handler; if (wev->timer_set) { ngx_del_timer(wev); } if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_ssl_ocsp_error(ctx); } return; } } if (!wev->timer_set) { ngx_add_timer(wev, ctx->timeout); } }
static void ngx_http_clojure_socket_upstream_handler(ngx_event_t *ev) { ngx_connection_t *c; ngx_http_clojure_socket_upstream_t *u; c = ev->data; u = c->data; if (c->fd == -1) { ngx_log_error(NGX_LOG_ERR, ngx_http_clojure_global_cycle->log, 0, "ngx clojure maybe meet nginx bug: event on closed socket u=%p, c=%p", u, c); return; } if (!u->connect_event_sent) { if (ev->timedout) { ngx_http_clojure_socket_upstream_connect_handler(u, NGX_HTTP_CLOJURE_SOCKET_ERR_CONNECT_TIMEOUT); return; } if (c->write->timer_set) { ngx_del_timer(c->write); } if (ngx_http_clojure_socket_upstream_test_connect(c) == NGX_OK) { ngx_http_clojure_socket_upstream_connect_handler(u, NGX_HTTP_CLOJURE_SOCKET_OK); /*connection may be closed by above code*/ if (c->fd == -1) { return; } /*when ev->ready is true, we'll give a chance to writing after immediately successful connecting */ if (!ev->ready) { return; } }else { ngx_http_clojure_socket_upstream_connect_handler(u, NGX_HTTP_CLOJURE_SOCKET_ERR_CONNECT); return; } } if (ev->write) { ngx_http_clojure_socket_upstream_write_handler(ev); /*If the write handler didn't do any writing, we need to delete this event for level/select/poll event to avoid * foolish repeated write event notification*/ if (ev->ready) { (void)ngx_handle_write_event(ev, 0); } } else { ngx_http_clojure_socket_upstream_read_handler(ev); } }
static void ngx_rtmp_netcall_send(ngx_event_t *wev) { ngx_rtmp_netcall_session_t *cs; ngx_connection_t *cc; ngx_chain_t *cl; cc = wev->data; cs = cc->data; if (cc->destroyed) { return; } if (wev->timedout) { ngx_log_error(NGX_LOG_INFO, cc->log, NGX_ETIMEDOUT, "netcall: client send timed out"); cc->timedout = 1; ngx_rtmp_netcall_close(cc); return; } if (wev->timer_set) { ngx_del_timer(wev); } cl = cc->send_chain(cc, cs->out, 0); if (cl == NGX_CHAIN_ERROR) { ngx_rtmp_netcall_close(cc); return; } cs->out = cl; /* more data to send? */ if (cl) { ngx_add_timer(wev, cs->timeout); if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_rtmp_netcall_close(cc); } return; } /* we've sent everything we had. * now receive reply */ ngx_del_event(wev, NGX_WRITE_EVENT, 0); ngx_rtmp_netcall_recv(cc->read); }
ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) { int sslerr; if (c->timedout || c->ssl->no_send_shutdown || c->ssl->no_wait_shutdown) { ssl_free(c->ssl->connection); c->ssl = NULL; return NGX_OK; } sslerr = ssl_close_notify(c->ssl->connection); if (sslerr == 0 || sslerr == MBEDTLS_ERR_SSL_CONN_EOF) { ssl_free(c->ssl->connection); c->ssl = NULL; return NGX_OK; } if (sslerr == MBEDTLS_ERR_NET_WANT_READ || sslerr == MBEDTLS_ERR_NET_WANT_WRITE) { c->read->handler = ngx_ssl_shutdown_handler; c->write->handler = ngx_ssl_shutdown_handler; if (ngx_handle_read_event(c->read, 0) != NGX_OK) { return NGX_ERROR; } if (ngx_handle_write_event(c->write, 0) != NGX_OK) { return NGX_ERROR; } if (sslerr == MBEDTLS_ERR_NET_WANT_READ) { ngx_add_timer(c->read, 300000); } return NGX_AGAIN; } ngx_mbedtls_error(NGX_LOG_ERR, c->log, 0, sslerr, "ssl_close_notify() failed"); ssl_free(c->ssl->connection); c->ssl = NULL; return NGX_ERROR; }
static void ngx_mail_proxy_dummy_handler(ngx_event_t *wev) { ngx_connection_t *c; ngx_mail_session_t *s; ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy dummy handler"); if (ngx_handle_write_event(wev, 0) != NGX_OK) { c = wev->data; s = c->data; ngx_mail_proxy_close_session(s); } }
static void ngx_tcp_lua_dummy_write_handler(ngx_tcp_session_t *s) { ngx_connection_t *c; ngx_event_t *wev; c = s->connection; wev = c->write; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, wev->log, 0, "tcp lua dummy write handler: %d", c->fd); if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_tcp_finalize_session(s); } }
static void ngx_tcp_proxy_dummy_write_handler(ngx_event_t *wev) { ngx_connection_t *c; ngx_tcp_session_t *s; c = wev->data; s = c->data; ngx_log_debug1(NGX_LOG_DEBUG_TCP, wev->log, 0, "tcp proxy dummy write handler: %d", c->fd); if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_tcp_finalize_session(s); } }
static void ngx_stream_return_write_handler(ngx_event_t *ev) { ssize_t n; ngx_buf_t *b; ngx_connection_t *c; ngx_stream_session_t *s; ngx_stream_return_ctx_t *ctx; c = ev->data; s = c->data; if (ev->timedout) { ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); ngx_stream_close_connection(c); return; } if (ev->ready) { ctx = ngx_stream_get_module_ctx(s, ngx_stream_return_module); b = &ctx->buf; n = c->send(c, b->pos, b->last - b->pos); if (n == NGX_ERROR) { ngx_stream_close_connection(c); return; } if (n > 0) { b->pos += n; if (b->pos == b->last) { ngx_stream_close_connection(c); return; } } } if (ngx_handle_write_event(ev, 0) != NGX_OK) { ngx_stream_close_connection(c); return; } ngx_add_timer(ev, 5000); }
void ngx_http_perl_sleep_handler(ngx_http_request_t *r) { ngx_event_t *wev; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl sleep handler"); wev = r->connection->write; if (wev->timedout) { wev->timedout = 0; ngx_http_perl_handle_request(r); return; } if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); } }
int ngx_http_clojure_socket_upstream_write(ngx_http_clojure_socket_upstream_t *u, void *buf, size_t size) { ngx_connection_t *c = u->peer.connection; ngx_int_t rc = ngx_send(c, buf, size); if (rc == 0 || rc == NGX_AGAIN) { /*Because if connected immediately successfully or we have deleted this event in * ngx_http_clojure_socket_upstream_handler the write event was not registered * so we need register it here.*/ if (!c->write->active) { (void)ngx_handle_write_event(c->write, 0); } if (u->write_timeout > 0) { ngx_add_timer(c->write, u->write_timeout); } rc = NGX_HTTP_CLOJURE_SOCKET_ERR_AGAIN; }else if (rc < 0) { rc = NGX_HTTP_CLOJURE_SOCKET_ERR_WRITE; } return rc; }
static void ngx_stream_return_write_handler(ngx_event_t *ev) { ngx_connection_t *c; ngx_stream_session_t *s; ngx_stream_return_ctx_t *ctx; c = ev->data; s = c->data; if (ev->timedout) { ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); ngx_stream_finalize_session(s, NGX_STREAM_OK); return; } ctx = ngx_stream_get_module_ctx(s, ngx_stream_return_module); if (ngx_stream_top_filter(s, ctx->out, 1) == NGX_ERROR) { ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } ctx->out = NULL; if (!c->buffered) { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream return done sending"); ngx_stream_finalize_session(s, NGX_STREAM_OK); return; } if (ngx_handle_write_event(ev, 0) != NGX_OK) { ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } ngx_add_timer(ev, 5000); }
void ss_ftp_cmd_link_write(ngx_event_t *send) { ngx_connection_t *c; ss_ftp_request *r; ngx_int_t rc; c = (ngx_connection_t *) send->data; assert(c != NULL); r = (ss_ftp_request *) c->data; assert(r != NULL); rc = ss_ftp_write(c, r->cmd_link_write, NULL); assert(rc == NGX_AGAIN || rc == NGX_OK); if (NGX_AGAIN == rc) { ngx_handle_write_event(send, 0); /* Data transmited ok. */ } else { /* TODO */ // ngx_del_event(); } }
static void ngx_limit_tcp_delay(ngx_event_t *ev) { ngx_limit_tcp_delay_ctx_t *dctx = ev->data; ngx_connection_t *c; c = dctx->connection; ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "limit_tcp delay"); c->read->data = dctx->rdata; c->write->data = dctx->wdata; c->read->handler = dctx->rhandler; c->write->handler = dctx->whandler; if (!c->write->timedout) { if (ngx_handle_write_event(c->write, 0) != NGX_OK) { ngx_close_accepted_connection(c); } return; } c->write->timedout = 0; if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_close_accepted_connection(c); return; } c->read->ready = 1; c->write->ready = 1; dctx->handler(c); }
void ngx_mail_send(ngx_event_t *wev) { ngx_int_t n; ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_core_srv_conf_t *cscf; c = wev->data; s = c->data; if (wev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); c->timedout = 1; ngx_mail_close_connection(c); return; } if (s->out.len == 0) { if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { ngx_mail_close_connection(c); } return; } n = c->send(c, s->out.data, s->out.len); if (n > 0) { s->out.len -= n; if (wev->timer_set) { ngx_del_timer(wev); } if (s->quit) { ngx_mail_close_connection(c); return; } if (s->blocked) { c->read->handler(c->read); } return; } if (n == NGX_ERROR) { ngx_mail_close_connection(c); return; } /* n == NGX_AGAIN */ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); ngx_add_timer(c->write, cscf->timeout); if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { ngx_mail_close_connection(c); return; } }
static void ngx_mail_auth_http_write_handler(ngx_event_t *wev) { ssize_t n, size; ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_auth_http_ctx_t *ctx; ngx_mail_auth_http_conf_t *ahcf; c = wev->data; s = c->data; ctx = ngx_mail_get_module_ctx(s, ngx_mail_auth_http_module); ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail auth http write handler"); if (wev->timedout) { ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT, "auth http server %V timed out", ctx->peer.name); ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } size = ctx->request->last - ctx->request->pos; n = ngx_send(c, ctx->request->pos, size); if (n == NGX_ERROR) { ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } if (n > 0) { ctx->request->pos += n; if (n == size) { wev->handler = ngx_mail_auth_http_dummy_handler; if (wev->timer_set) { ngx_del_timer(wev); } if (ngx_handle_write_event(wev, 0) == NGX_ERROR) { ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); } return; } } if (!wev->timer_set) { ahcf = ngx_mail_get_module_srv_conf(s, ngx_mail_auth_http_module); ngx_add_timer(wev, ahcf->timeout); } }
/** * Force flush out response content * */ static int ngx_stream_lua_ngx_flush(lua_State *L) { #if 0 /* TODO */ ngx_stream_session_t *s; ngx_stream_lua_ctx_t *ctx; ngx_chain_t *cl; ngx_int_t rc; int n; unsigned wait = 0; ngx_event_t *wev; ngx_stream_core_loc_conf_t *clcf; ngx_stream_lua_co_ctx_t *coctx; n = lua_gettop(L); if (n > 1) { return luaL_error(L, "attempt to pass %d arguments, but accepted 0 " "or 1", n); } s = ngx_stream_lua_get_session(L); if (n == 1 && s == s->main) { luaL_checktype(L, 1, LUA_TBOOLEAN); wait = lua_toboolean(L, 1); } ctx = ngx_stream_get_module_ctx(s, ngx_stream_lua_module); if (ctx == NULL) { return luaL_error(L, "no session ctx found"); } ngx_stream_lua_check_context(L, ctx, NGX_STREAM_LUA_CONTEXT_REWRITE | NGX_STREAM_LUA_CONTEXT_ACCESS | NGX_STREAM_LUA_CONTEXT_CONTENT); if (ctx->acquired_raw_req_socket) { lua_pushnil(L); lua_pushliteral(L, "raw session socket acquired"); return 2; } coctx = ctx->cur_co_ctx; if (coctx == NULL) { return luaL_error(L, "no co ctx found"); } if (ctx->eof) { lua_pushnil(L); lua_pushliteral(L, "seen eof"); return 2; } #if 1 if (!s->header_sent && !ctx->header_sent) { lua_pushnil(L); lua_pushliteral(L, "nothing to flush"); return 2; } #endif cl = ngx_stream_lua_get_flush_chain(s, ctx); if (cl == NULL) { return luaL_error(L, "no memory"); } rc = ngx_stream_lua_send_chain_link(s, ctx, cl); dd("send chain: %d", (int) rc); if (rc == NGX_ERROR || rc >= NGX_STREAM_SPECIAL_RESPONSE) { lua_pushnil(L); lua_pushliteral(L, "nginx output filter error"); return 2; } dd("wait:%d, rc:%d, buffered:0x%x", wait, (int) rc, s->connection->buffered); wev = s->connection->write; if (wait && (s->connection->buffered & NGX_STREAM_LOWLEVEL_BUFFERED || wev->delayed)) { ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream lua flush requires waiting: buffered 0x%uxd, " "delayed:%d", (unsigned) s->connection->buffered, wev->delayed); coctx->flushing = 1; ctx->flushing_coros++; if (ctx->entered_content_phase) { /* mimic ngx_stream_set_write_handler */ s->write_event_handler = ngx_stream_lua_content_wev_handler; } else { s->write_event_handler = ngx_stream_core_run_phases; } clcf = ngx_stream_get_module_loc_conf(s, ngx_stream_core_module); if (!wev->delayed) { ngx_add_timer(wev, clcf->send_timeout); } if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { if (wev->timer_set) { wev->delayed = 0; ngx_del_timer(wev); } lua_pushnil(L); lua_pushliteral(L, "connection broken"); return 2; } ngx_stream_lua_cleanup_pending_operation(ctx->cur_co_ctx); coctx->cleanup = ngx_stream_lua_flush_cleanup; coctx->data = s; return lua_yield(L, 0); } ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream lua flush asynchronously"); #endif lua_pushinteger(L, 1); return 1; }
static void ngx_tcp_proxy_handler(ngx_event_t *ev) { char *action, *recv_action, *send_action; off_t *read_bytes, *write_bytes; size_t size; ssize_t n; ngx_buf_t *b; ngx_err_t err; ngx_uint_t do_write, first_read; ngx_connection_t *c, *src, *dst; ngx_tcp_session_t *s; ngx_tcp_proxy_conf_t *pcf; ngx_tcp_proxy_ctx_t *pctx; ngx_tcp_core_srv_conf_t *cscf; c = ev->data; s = c->data; cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module); if (ev->timedout) { c->log->action = "proxying"; ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "proxy timed out"); c->timedout = 1; ngx_tcp_finalize_session(s); return; } pctx = ngx_tcp_get_module_ctx(s, ngx_tcp_proxy_module); if (pctx == NULL) { ngx_tcp_finalize_session(s); return; } read_bytes = NULL; write_bytes = NULL; if (c == s->connection) { if (ev->write) { recv_action = "client write: proxying and reading from upstream"; send_action = "client write: proxying and sending to client"; src = pctx->upstream->connection; dst = c; b = pctx->buffer; write_bytes = &s->bytes_write; } else { recv_action = "client read: proxying and reading from client"; send_action = "client read: proxying and sending to upstream"; src = c; dst = pctx->upstream->connection; b = s->buffer; read_bytes = &s->bytes_read; } } else { if (ev->write) { recv_action = "upstream write: proxying and reading from client"; send_action = "upstream write: proxying and sending to upstream"; src = s->connection; dst = c; b = s->buffer; read_bytes = &s->bytes_read; } else { recv_action = "upstream read: proxying and reading from upstream"; send_action = "upstream read: proxying and sending to client"; src = c; dst = s->connection; b = pctx->buffer; write_bytes = &s->bytes_write; } } do_write = ev->write ? 1 : 0; #if (NGX_TCP_SSL) /* SSL Need this */ if (s->connection->ssl) { first_read = 1; } #else first_read = 0; #endif ngx_log_debug4(NGX_LOG_DEBUG_TCP, ev->log, 0, "tcp proxy handler: %d, #%d > #%d, time:%ui", do_write, src->fd, dst->fd, ngx_current_msec); for ( ;; ) { if (do_write) { size = b->last - b->pos; if (size && dst->write->ready) { c->log->action = send_action; n = dst->send(dst, b->pos, size); err = ngx_socket_errno; ngx_log_debug1(NGX_LOG_DEBUG_TCP, ev->log, 0, "tcp proxy handler send:%d", n); if (n == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, c->log, err, "proxy send error"); ngx_tcp_finalize_session(s); return; } if (n > 0) { b->pos += n; if (write_bytes) { *write_bytes += n; } if (b->pos == b->last) { b->pos = b->start; b->last = b->start; } } } } size = b->end - b->last; if (size) { if (src->read->ready || first_read) { first_read = 0; c->log->action = recv_action; n = src->recv(src, b->last, size); err = ngx_socket_errno; ngx_log_debug1(NGX_LOG_DEBUG_TCP, ev->log, 0, "tcp proxy handler recv:%d", n); if (n == NGX_AGAIN || n == 0) { break; } if (n > 0) { do_write = 1; b->last += n; if (read_bytes) { *read_bytes += n; } continue; } if (n == NGX_ERROR) { src->read->eof = 1; } } } break; } c->log->action = "nginx tcp proxying"; if ((s->connection->read->eof && s->buffer->pos == s->buffer->last) || (pctx->upstream->connection->read->eof && pctx->buffer->pos == pctx->buffer->last) || (s->connection->read->eof && pctx->upstream->connection->read->eof)) { action = c->log->action; c->log->action = NULL; ngx_log_error(NGX_LOG_DEBUG, c->log, 0, "proxied session done"); c->log->action = action; ngx_tcp_finalize_session(s); return; } if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } if (ngx_handle_read_event(dst->read, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } if (ngx_handle_write_event(src->write, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } if (ngx_handle_read_event(src->read, 0) != NGX_OK) { ngx_tcp_finalize_session(s); return; } pcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_proxy_module); if (c == s->connection) { ngx_add_timer(c->read, cscf->timeout); } if (c == pctx->upstream->connection) { if (ev->write) { ngx_add_timer(c->write, pcf->upstream.send_timeout); } else { ngx_add_timer(c->read, pcf->upstream.read_timeout); } } return; }
static void ngx_mail_proxy_handler(ngx_event_t *ev) { char *action, *recv_action, *send_action; size_t size; ssize_t n; ngx_buf_t *b; ngx_uint_t do_write; ngx_connection_t *c, *src, *dst; ngx_mail_session_t *s; ngx_mail_proxy_conf_t *pcf; c = ev->data; s = c->data; if (ev->timedout) { c->log->action = "proxying"; if (c == s->connection) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); c->timedout = 1; } else { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "upstream timed out"); } ngx_mail_proxy_close_session(s); return; } if (c == s->connection) { if (ev->write) { recv_action = "proxying and reading from upstream"; send_action = "proxying and sending to client"; src = s->proxy->upstream.connection; dst = c; b = s->proxy->buffer; } else { recv_action = "proxying and reading from client"; send_action = "proxying and sending to upstream"; src = c; dst = s->proxy->upstream.connection; b = s->buffer; } } else { if (ev->write) { recv_action = "proxying and reading from client"; send_action = "proxying and sending to upstream"; src = s->connection; dst = c; b = s->buffer; } else { recv_action = "proxying and reading from upstream"; send_action = "proxying and sending to client"; src = c; dst = s->connection; b = s->proxy->buffer; } } do_write = ev->write ? 1 : 0; ngx_log_debug3(NGX_LOG_DEBUG_MAIL, ev->log, 0, "mail proxy handler: %d, #%d > #%d", do_write, src->fd, dst->fd); for ( ;; ) { if (do_write) { size = b->last - b->pos; if (size && dst->write->ready) { c->log->action = send_action; n = dst->send(dst, b->pos, size); if (n == NGX_ERROR) { ngx_mail_proxy_close_session(s); return; } if (n > 0) { b->pos += n; if (b->pos == b->last) { b->pos = b->start; b->last = b->start; } } } } size = b->end - b->last; if (size && src->read->ready) { c->log->action = recv_action; n = src->recv(src, b->last, size); if (n == NGX_AGAIN || n == 0) { break; } if (n > 0) { do_write = 1; b->last += n; continue; } if (n == NGX_ERROR) { src->read->eof = 1; } } break; } c->log->action = "proxying"; if ((s->connection->read->eof && s->buffer->pos == s->buffer->last) || (s->proxy->upstream.connection->read->eof && s->proxy->buffer->pos == s->proxy->buffer->last) || (s->connection->read->eof && s->proxy->upstream.connection->read->eof)) { action = c->log->action; c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxied session done"); c->log->action = action; ngx_mail_proxy_close_session(s); return; } if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { ngx_mail_proxy_close_session(s); return; } if (ngx_handle_read_event(dst->read, 0) != NGX_OK) { ngx_mail_proxy_close_session(s); return; } if (ngx_handle_write_event(src->write, 0) != NGX_OK) { ngx_mail_proxy_close_session(s); return; } if (ngx_handle_read_event(src->read, 0) != NGX_OK) { ngx_mail_proxy_close_session(s); return; } if (c == s->connection) { pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); ngx_add_timer(c->read, pcf->timeout); } }
static ngx_int_t ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s) { u_char *p; ssize_t n, size; ngx_connection_t *c, *pc; ngx_stream_upstream_t *u; ngx_stream_proxy_srv_conf_t *pscf; u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; c = s->connection; ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream proxy send PROXY protocol header"); p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER); if (p == NULL) { ngx_stream_proxy_finalize(s, NGX_ERROR); return NGX_ERROR; } u = s->upstream; pc = u->peer.connection; size = p - buf; n = pc->send(pc, buf, size); if (n == NGX_AGAIN) { if (ngx_handle_write_event(pc->write, 0) != NGX_OK) { ngx_stream_proxy_finalize(s, NGX_ERROR); return NGX_ERROR; } pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); ngx_add_timer(pc->write, pscf->timeout); pc->write->handler = ngx_stream_proxy_connect_handler; return NGX_AGAIN; } if (n == NGX_ERROR) { ngx_stream_proxy_finalize(s, NGX_DECLINED); return NGX_ERROR; } if (n != size) { /* * PROXY protocol specification: * The sender must always ensure that the header * is sent at once, so that the transport layer * maintains atomicity along the path to the receiver. */ ngx_log_error(NGX_LOG_ERR, c->log, 0, "could not send PROXY protocol header at once"); ngx_stream_proxy_finalize(s, NGX_DECLINED); return NGX_ERROR; } return NGX_OK; }