static void 
ngx_tcp_upstream_init_proxy_handler(ngx_tcp_session_t *s, ngx_tcp_upstream_t *u)
{
    ngx_connection_t         *c;
    ngx_tcp_proxy_ctx_t      *pctx;
    ngx_tcp_proxy_conf_t     *pcf;

    c = s->connection;
    c->log->action = "ngx_tcp_upstream_init_proxy_handler";

    ngx_log_debug0(NGX_LOG_DEBUG_TCP, s->connection->log, 0,
                   "tcp proxy upstream init proxy");

    pcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_proxy_module);

    pctx = ngx_tcp_get_module_ctx(s, ngx_tcp_proxy_module);

    if (pcf == NULL || pctx == NULL) {
        ngx_tcp_finalize_session(s);
        return;
    }

    pctx->upstream = &s->upstream->peer;

    c = pctx->upstream->connection;
    if (c->read->timedout || c->write->timedout) {
        ngx_tcp_upstream_next(s, u, NGX_TCP_UPSTREAM_FT_TIMEOUT);
        return;
    }

    if (ngx_tcp_upstream_check_broken_connection(s) != NGX_OK){
        ngx_tcp_upstream_next(s, u, NGX_TCP_UPSTREAM_FT_ERROR);
        return;
    }

    s->connection->read->handler = ngx_tcp_proxy_handler;
    s->connection->write->handler = ngx_tcp_proxy_handler;

    c->read->handler = ngx_tcp_proxy_handler;
    c->write->handler = ngx_tcp_proxy_handler;

    ngx_add_timer(c->read, pcf->upstream.read_timeout);
    ngx_add_timer(c->write, pcf->upstream.send_timeout);

    if (ngx_handle_read_event(s->connection->read, 0) != NGX_OK) {
        ngx_tcp_finalize_session(s);
        return;
    }

#if (NGX_TCP_SSL)

    /* 
     * The ssl connection with client may not trigger the read event again,
     * So I trigger it in this function.
     * */
    if (s->connection->ssl) {
        ngx_tcp_proxy_handler(s->connection->read); 
    }

#endif

    return;
}
static void 
ngx_tcp_upstream_websocket_proxy_init_handler(ngx_tcp_session_t *s,
    ngx_tcp_upstream_t *u)
{
    ngx_connection_t             *c;
    ngx_tcp_websocket_ctx_t      *wctx;
    ngx_tcp_websocket_conf_t     *wcf;

    c = s->connection;
    c->log->action = "ngx_tcp_upstream_websocket_proxy_init_handler";

    ngx_log_debug0(NGX_LOG_DEBUG_TCP, s->connection->log, 
                   0, "tcp upstream websocket proxy init handler");

    wcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_websocket_module);

    wctx = ngx_tcp_get_module_ctx(s, ngx_tcp_websocket_module);

    if (wcf == NULL || wctx == NULL) {
        ngx_tcp_finalize_session(s);
        return;
    }

    wctx->upstream = &s->upstream->peer;

    c = wctx->upstream->connection;
    if (c->read->timedout || c->write->timedout) {
        ngx_tcp_upstream_next(s, u, NGX_TCP_UPSTREAM_FT_TIMEOUT);
        return;
    }

    if (ngx_tcp_upstream_check_broken_connection(s) != NGX_OK){
        ngx_tcp_upstream_next(s, u, NGX_TCP_UPSTREAM_FT_ERROR);
        return;
    }

    s->connection->read->handler = ngx_tcp_websocket_proxy_handler;
    s->connection->write->handler = ngx_tcp_websocket_proxy_handler;

    c->read->handler = ngx_tcp_websocket_proxy_handler;
    c->write->handler = ngx_tcp_websocket_proxy_handler;

    ngx_add_timer(c->read, wcf->upstream.read_timeout);
    ngx_add_timer(c->write, wcf->upstream.send_timeout);

#if (NGX_TCP_SSL)

    if (s->connection->ssl) {
        ngx_tcp_websocket_proxy_handler(s->connection->read); 
        return;
    }

#endif

    if (ngx_handle_read_event(s->connection->read, 0) != NGX_OK) {
        ngx_tcp_finalize_session(s);
        return;
    }

    ngx_tcp_websocket_proxy_handler(s->connection->read);

    return;
}