static void 
ngx_tcp_websocket_init_session(ngx_tcp_session_t *s) 
{
    ngx_connection_t             *c;
    ngx_tcp_websocket_ctx_t      *wctx;
    ngx_tcp_core_srv_conf_t      *cscf;
    ngx_tcp_websocket_conf_t     *wcf;

    c = s->connection;

    ngx_log_debug0(NGX_LOG_DEBUG_TCP, c->log, 0, "tcp websocket init session");

    cscf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_core_module);

    wcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_websocket_module);

    wctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_tcp_websocket_ctx_t));
    if (wctx == NULL) {
        ngx_tcp_finalize_session(s);
        return;
    }
    ngx_tcp_set_ctx(s, wctx, ngx_tcp_websocket_module);

    s->out.len = 0;

    s->buffer = ngx_create_temp_buf(s->connection->pool, wcf->buffer_size);
    if (s->buffer == NULL) {
        ngx_tcp_finalize_session(s);
        return;
    }

    c->write->handler = ngx_tcp_websocket_dummy_write_handler;
    c->read->handler = ngx_tcp_websocket_init_protocol;

    ngx_add_timer(c->read, cscf->timeout);

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

#if (NGX_TCP_SSL)

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

#endif

    if (c->read->ready) {
        ngx_tcp_websocket_init_protocol(c->read);
    }

    return;
}
static  void
ngx_tcp_proxy_init_upstream(ngx_connection_t *c, ngx_tcp_session_t *s)
{
    ngx_tcp_upstream_t       *u;
    ngx_tcp_proxy_ctx_t      *p;
    ngx_tcp_proxy_conf_t     *pcf;

    s->connection->log->action = "ngx_tcp_proxy_init_upstream";

    pcf = ngx_tcp_get_module_srv_conf(s, ngx_tcp_proxy_module);
    if (pcf->upstream.upstream == NULL) {
        ngx_tcp_finalize_session(s);
        return;
    }

    p = ngx_pcalloc(s->connection->pool, sizeof(ngx_tcp_proxy_ctx_t));
    if (p == NULL) {
        ngx_tcp_finalize_session(s);
        return;
    }

    ngx_tcp_set_ctx(s, p, ngx_tcp_proxy_module);

    if (ngx_tcp_upstream_create(s) != NGX_OK) {
        ngx_tcp_finalize_session(s);
        return;
    }

    u = s->upstream;

    u->conf = &pcf->upstream;

    u->write_event_handler = ngx_tcp_upstream_init_proxy_handler;
    u->read_event_handler = ngx_tcp_upstream_init_proxy_handler;

    p->upstream = &u->peer;

    p->buffer = ngx_create_temp_buf(s->connection->pool, pcf->buffer_size);
    if (p->buffer == NULL) {
        ngx_tcp_finalize_session(s);
        return;
    }

    ngx_tcp_upstream_init(s);

    return;
}
ngx_int_t
ngx_tcp_lua_process_by_chunk(lua_State *L, ngx_tcp_session_t *s)
{
    int                      cc_ref;
    lua_State               *cc;
    ngx_tcp_lua_ctx_t      *ctx;
    ngx_tcp_cleanup_t      *cln;

    dd("content by chunk");

    ctx = ngx_tcp_get_module_ctx(s, ngx_tcp_lua_module);

    if (ctx == NULL) {
        ctx = ngx_pcalloc(s->pool, sizeof(ngx_tcp_lua_ctx_t));
        if (ctx == NULL) {
            return NGX_ERROR;
        }

        dd("setting new ctx, ctx = %p", ctx);

        ctx->cc_ref  = LUA_NOREF;
        ctx->ctx_ref = LUA_NOREF;
		ctx->exited  = 0;

        ngx_tcp_set_ctx(s, ctx, ngx_tcp_lua_module);

    } else {
        dd("reset ctx");
        ngx_tcp_lua_reset_ctx(s, L, ctx);
    }

    /*  {{{ new coroutine to handle request */
    cc = ngx_tcp_lua_new_thread(s, L, &cc_ref);

    if (cc == NULL) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                "(lua-content-by-chunk) failed to create new coroutine "
                "to handle request");

        return NGX_ERROR;
    }

    /*  move code closure to new coroutine */
    lua_xmove(L, cc, 1);

    /*  set closure's env table to new coroutine's globals table */
    lua_pushvalue(cc, LUA_GLOBALSINDEX);
    lua_setfenv(cc, -2);

    /*  save nginx request in coroutine globals table */
    lua_pushlightuserdata(cc, &ngx_tcp_lua_request_key);
    lua_pushlightuserdata(cc, s);
    lua_rawset(cc, LUA_GLOBALSINDEX);
    /*  }}} */

    ctx->co = cc;
    ctx->cc_ref = cc_ref;

    /*  {{{ register request cleanup hooks */
    if (ctx->cleanup == NULL) {
        cln = ngx_tcp_cleanup_add(s, 0);
        if (cln == NULL) {
            return NGX_ERROR;
        }

        cln->handler = ngx_tcp_lua_request_cleanup;
        cln->data = s;
        ctx->cleanup = &cln->handler;
    }
    /*  }}} */

    return ngx_tcp_lua_run_thread(L, s, ctx, 0);

}