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);
}
Beispiel #2
0
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");
    }
}
Beispiel #3
0
__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);
}
Beispiel #6
0
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);
    }
}
Beispiel #9
0
__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);
}
Beispiel #10
0
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);
}
Beispiel #11
0
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);
}
Beispiel #15
0
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;
}
Beispiel #16
0
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);
}
Beispiel #23
0
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;
}
Beispiel #29
0
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);
    }
}
Beispiel #30
0
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;
}