int lua_co_setkeepalive(lua_State *L)
{
    if(!lua_isuserdata(L, 1) || !lua_isnumber(L, 2)) {
        lua_pushnil(L);
        lua_pushstring(L, "Error params!");
        return 2;
    }

    cosocket_t *c*k = (cosocket_t *) lua_touserdata(L, 1);
    c*k->pool_size = lua_tonumber(L, 2);

    if(c*k->pool_size < 0) {
        c*k->pool_size = 0;

    } else if(c*k->pool_size > 4096) {
        c*k->pool_size = 4096;
    }

    cosocket_connection_pool_counter_t *pool_counter = get_connection_pool_counter(c*k->pool_key);

    if(c*k->pool_size > pool_counter->size) {
        pool_counter->size = c*k->pool_size;
    }

    if(lua_gettop(L) == 3 && lua_isstring(L, 3)) {
        size_t len = 0;
        const char *key = lua_tolstring(L, 3, &len);
        c*k->pool_key = fnv1a_32(key, len);
    }

    _lua_co_close(L, c*k);

    lua_pushboolean(L, 1);
    return 1;
}
void connection_pool_counter_operate(unsigned long pool_key, int a)
{
    /// add: connection_pool_counter_operate(key, 1);
    /// remove: connection_pool_counter_operate(key, -1);
    if(pool_key < 1) {
        return;
    }

    cosocket_connection_pool_counter_t *pool_counter = get_connection_pool_counter(pool_key);
    pool_counter->count += a;
}
static int lua_co_connect(lua_State *L)
{
    cosocket_t *c*k = NULL;
    {
        if(!lua_isuserdata(L, 1) || !lua_isstring(L, 2)) {
            lua_pushnil(L);
            lua_pushstring(L, "Error params!");
            return 2;
        }

        c*k = (cosocket_t *) lua_touserdata(L, 1);

        if(c*k->status > 0) {
            lua_pushnil(L);
            lua_pushstring(L, "Aleady connected!");
            return 2;
        }

        if(c*k->inuse == 1) {
            lua_pushnil(L);
            lua_pushstring(L, "socket busy!");
            return 2;
        }

        //printf(" 0x%p connect to %s\n", L, lua_tostring(L, 2));
        size_t host_len = 0;
        const char *host = lua_tolstring(L, 2, &host_len);

        if(host_len > (host[0] == '/' ? 108 : 60)) {
            lua_pushnil(L);
            lua_pushstring(L, "hostname length must be <= 60!");
            return 2;
        }

        int port = 0;
        int pn = 3;

        if(host[0] != '/') {
            port = lua_tonumber(L, 3);

            if(port < 1) {
                lua_pushnil(L);
                lua_pushstring(L, "port must be > 0");
                return 2;
            }

            pn = 4;
        }

        if(lua_gettop(L) >= pn) { /// set keepalive options
            if(lua_isnumber(L, pn)) {
                c*k->pool_size = lua_tonumber(L, pn);

                if(c*k->pool_size < 0) {
                    c*k->pool_size = 0;

                } else if(c*k->pool_size > 4096) {
                    c*k->pool_size = 4096;
                }

                pn++;
            }

            if(c*k->pool_size > 0) {
                size_t len = 0;

                if(lua_gettop(L) == pn && lua_isstring(L, pn)) {
                    const char *key = lua_tolstring(L, pn, &len);
                    c*k->pool_key = fnv1a_32(key, len);
                }
            }
        }

        if(c*k->pool_key == 0) { /// create a normal key
            int len = snprintf(temp_buf, 4096, "%s%s:%d:%ld", port > 0 ? "tcp://" : "unix://", host, port, c*k->ssl_sign);
            c*k->pool_key = fnv1a_32(temp_buf, len);
        }

        c*k->status = 1;
        c*k->L = L;
        c*k->read_buf = NULL;
        c*k->last_buf = NULL;
        c*k->total_buf_len = 0;
        c*k->buf_read_len = 0;

        /// check pool count
        cosocket_connection_pool_counter_t *pool_counter = get_connection_pool_counter(c*k->pool_key);

        if(pool_counter->size > c*k->pool_size) {
            c*k->pool_size = pool_counter->size;
        }

        if(c*k->pool_size > 0) {
            c*k->ptr = get_connection_in_pool(_loop_fd, c*k->pool_key, c*k);

            if(c*k->ptr) {
                ((se_ptr_t *) c*k->ptr)->data = c*k;
                c*k->status = 2;
                c*k->reusedtimes = 1;
                c*k->fd = ((se_ptr_t *) c*k->ptr)->fd;
                //printf("reuse %d\n", c*k->fd);
                se_be_pri(c*k->ptr, NULL);
                lua_pushboolean(L, 1);

                return 1;
            }

            if(pool_counter->count > 0 && pool_counter->count >= c*k->pool_size / _process_count) {
                /// pool full
                if((c*k->pool_wait = add_waiting_get_connection(c*k))) {
                    c*k->status = 3;
                    c*k->timeout_ptr = add_timeout(c*k, c*k->timeout, timeout_handle);
                    //printf("wait %d\n", c*k->fd);
                    c*k->inuse = 1;
                    return lua_yield(L, 0);

                } else {
                    lua_pushnil(L);
                    lua_pushstring(L, "pool error");
                    return 2;
                }
            }
        }

        int fd = se_connect(_loop_fd, host, port, c*k->timeout > 0 ? c*k->timeout : 30000, be_connect, c*k);

        if(fd != -2) {
            if(fd > -1) {
                connection_pool_counter_operate(c*k->pool_key, 1);
                int ret = _be_connect(c*k, fd, 0);

                if(ret == -2) {
                    return lua_yield(L, 0);
                }

                return ret;

            } else {
                lua_pushnil(L);
                lua_pushstring(L, strerror(errno));
                return 2;
            }
        }

        connection_pool_counter_operate(c*k->pool_key, 1);
    }

    return lua_yield(L, 0);
}