コード例 #1
0
ファイル: worker.c プロジェクト: oneoo/merry-example
static int be_read(se_ptr_t *ptr)
{
    epdata_t *epd = ptr->data;

    int n = recv(epd->fd, &buf_4096, 4096, 0);

    if(n > 0) {
        update_timeout(epd->timeout_ptr, 1000);

        if(network_raw_send(epd->fd, (const char *)&buf_4096, n)) {
            if(buf_4096[n - 1] == '\n') {
                buf_4096[n - 1] = '\0';
            }

            LOGF(INFO, "%s", buf_4096);

        } else {
            LOGF(ERR, "send error!\n");

            se_delete(epd->se_ptr);

            if(epd->fd > -1) {
                close(epd->fd);
                epd->fd = -1;
            }

            free(epd);
        }

    } else if(n == 0 || (n < 0 && NOAGAIN)) { // close connection
        se_delete(epd->se_ptr);

        if(epd->fd > -1) {
            close(epd->fd);
            epd->fd = -1;
        }

        free(epd);

    } else {
        LOGF(ERR, "read error!\n");
    }

    return 1;
}
コード例 #2
0
static int lua_co_dup_setpeername(lua_State *L)
{
    if(!lua_isuserdata(L, 1) || !lua_isstring(L, 2)) {
        lua_pushnil(L);
        lua_pushstring(L, "Error params!");
        return 2;
    }

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

    if(c*k->fd > -1) {
        se_delete(c*k->ptr);
        c*k->ptr = NULL;
        close(c*k->fd);
    }

    if(lua_isnumber(L, 3)) {
        int fd = 0, slen = sizeof(c*k->addr);
        bzero(&c*k->addr, slen);
        c*k->addr.sin_family = AF_INET;
        c*k->addr.sin_port = htons(lua_tonumber(L, 3));
        const char *host = lua_tostring(L, 2);

        if(inet_aton(host, &c*k->addr.sin_addr) == 0) {
            struct hostent *hp = NULL;

            if((hp = gethostbyname(host)) == 0) {
                lua_pushnil(L);
                lua_pushstring(L, "Nslookup Error!");
                return 2;
            }

            memcpy(&c*k->addr.sin_addr.s_addr, hp->h_addr, hp->h_length);
        }

        if((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
            lua_pushnil(L);
            lua_pushstring(L, "Connect Error!");
            return 2;
        }

        if(!se_set_nonblocking(fd , 1)) {
            close(fd);
            lua_pushnil(L);
            lua_pushstring(L, "Connect Error!");
            return 2;
        }

        c*k->ptr = se_add(_loop_fd, fd, c*k);
        c*k->fd = fd;
        c*k->status = 2;
        lua_pushboolean(L, 1);
        return 1;
    }

    return 0;
}
コード例 #3
0
ファイル: worker.c プロジェクト: oneoo/merry-example
static void close_client(epdata_t *epd)
{
    se_delete(epd->se_ptr);
    delete_timeout(epd->timeout_ptr);

    close(epd->fd);

    smp_free(epd);
}
コード例 #4
0
static int cosocket_be_close(se_ptr_t *ptr)
{
    //printf("cosocket_be_close %d\n", ptr->fd);
    int fd = ptr->fd;

    cosocket_connection_pool_t *n = ptr->data;
    int k = n->pool_key % 64;

    if(n == connect_pool_p[0][k]) {
        connect_pool_p[0][k] = n->next;

        if(n->next) {
            ((cosocket_connection_pool_t *) n->next)->uper = NULL;
        }

    } else if(n == connect_pool_p[1][k]) {
        connect_pool_p[1][k] = n->next;

        if(n->next) {
            ((cosocket_connection_pool_t *) n->next)->uper = NULL;
        }

    } else {
        ((cosocket_connection_pool_t *) n->uper)->next = n->next;

        if(n->next) {
            ((cosocket_connection_pool_t *) n->next)->uper = n->uper;
        }
    }

    se_delete(n->ptr);
    n->ptr = NULL;

    if(n->ssl) {
        SSL_free(n->ssl);
        n->ssl = NULL;
        SSL_CTX_free(n->ctx);
        n->ctx = NULL;
    }

    connection_pool_counter_operate(n->pool_key, -1);
    close(fd);

    free(n);

    return 1;
}
コード例 #5
0
ファイル: worker.c プロジェクト: hopestar/alilua
void close_client(epdata_t *epd)
{
    if(!epd) {
        return;
    }

    if(epd->ssl && epd->fd > -1) {
        if(!SSL_shutdown(epd->ssl)) {
            shutdown(epd->fd, 1);
            SSL_shutdown(epd->ssl);
        }

        SSL_free(epd->ssl);
        epd->ssl = NULL;
    }

    if(epd->L) {
        if(epd->status == STEP_PROCESS) {
            LOGF(ERR, "at working!!!");
        }

        release_lua_thread(epd->L);
        epd->L = NULL;
    }

    if(epd->status == STEP_READ) {
        serv_status.reading_counts--;

    } else if(epd->status == STEP_SEND) {
        serv_status.sending_counts--;
    }

    se_delete(epd->se_ptr);
    delete_timeout(epd->timeout_ptr);
    epd->timeout_ptr = NULL;

    if(epd->fd > -1) {
        serv_status.active_counts--;
        close(epd->fd);
        epd->fd = -1;
    }

    free_epd(epd);
}
コード例 #6
0
ファイル: network.c プロジェクト: WinLinKer/alilua
void close_client ( epdata_t *epd )
{
    if ( !epd ) {
        return;
    }

    if ( epd->status == STEP_READ ) {
        serv_status.reading_counts--;

    } else if ( epd->status == STEP_SEND ) {
        serv_status.sending_counts--;
    }

    se_delete ( epd->se_ptr );
    delete_timeout ( epd->timeout_ptr );
    epd->timeout_ptr = NULL;

    if ( epd->fd > -1 ) {
        serv_status.active_counts--;
        close ( epd->fd );
        epd->fd = -1;
    }

    if ( epd->websocket ) {
        if ( epd->websocket->websocket_handles > 0 ) {
            luaL_unref ( epd->websocket->ML, LUA_REGISTRYINDEX,
                         epd->websocket->websocket_handles );
        }

        lua_resume ( epd->websocket->ML, 0 );
        free ( epd->websocket );
        epd->websocket = NULL;
    }

    free_epd ( epd );
}
コード例 #7
0
static int _lua_co_close(lua_State *L, cosocket_t *c*k)
{
    if(c*k->read_buf) {
        cosocket_link_buf_t *fr = c*k->read_buf;
        cosocket_link_buf_t *nb = NULL;

        while(fr) {
            nb = fr->next;
            free(fr->buf);
            free(fr);
            fr = nb;
        }

        c*k->read_buf = NULL;
    }

    if(c*k->send_buf_need_free) {
        free(c*k->send_buf_need_free);
        c*k->send_buf_need_free = NULL;
    }

    if(c*k->pool_wait) {
        delete_in_waiting_get_connection(c*k->pool_wait);
        c*k->pool_wait = NULL;
    }

    delete_timeout(c*k->timeout_ptr);
    c*k->timeout_ptr = NULL;

    c*k->status = 0;

    if(c*k->fd > -1) {
        ((se_ptr_t *) c*k->ptr)->fd = c*k->fd;

        if(c*k->pool_size < 1
           || add_connection_to_pool(_loop_fd, c*k->pool_key, c*k->pool_size, c*k->ptr, c*k->ssl,
                                     c*k->ctx, c*k->ssl_pw) == 0) {
            se_delete(c*k->ptr);
            c*k->ptr = NULL;

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

            if(c*k->ssl) {
                SSL_free(c*k->ssl);
                c*k->ssl = NULL;
            }

            if(c*k->ctx) {
                SSL_CTX_free(c*k->ctx);
                c*k->ctx = NULL;
            }

            if(c*k->ssl_pw) {
                free(c*k->ssl_pw);
                c*k->ssl_pw = NULL;
            }

        }

        c*k->ssl = NULL;
        c*k->ctx = NULL;
        c*k->ssl_pw = NULL;

        c*k->ptr = NULL;
        c*k->fd = -1;
    }
}
コード例 #8
0
static void timeout_handle(void *ptr)
{
    cosocket_t *c*k = ptr;
    delete_timeout(c*k->timeout_ptr);
    c*k->timeout_ptr = NULL;

    if(c*k->pool_wait) {
        delete_in_waiting_get_connection(c*k->pool_wait);
        c*k->pool_wait = NULL;
    }

    lua_pushnil(c*k->L);

    if(c*k->ptr) {
        if(c*k->status == 3) {
            lua_pushstring(c*k->L, "Connect error!(wait pool timeout)");

        } else if(((se_ptr_t *) c*k->ptr)->wfunc == cosocket_be_ssl_connected) {
            lua_pushstring(c*k->L, "SSL Connect timeout!");

        } else if(((se_ptr_t *) c*k->ptr)->wfunc == cosocket_be_write) {
            lua_pushstring(c*k->L, "Send timeout!");

        } else if(((se_ptr_t *) c*k->ptr)->rfunc == cosocket_be_read) {
            lua_pushstring(c*k->L, "Read timeout!");

        } else {
            lua_pushstring(c*k->L, "Timeout!");
        }

    } else {
        if(c*k->status == 3) {
            lua_pushstring(c*k->L, "Connect error!(wait pool timeout)");

        } else {
            lua_pushstring(c*k->L, "Timeout!");
        }
    }

    {
        se_delete(c*k->ptr);
        c*k->ptr = NULL;

        if(c*k->fd > -1) {
            connection_pool_counter_operate(c*k->pool_key, -1);
            close(c*k->fd);
            c*k->fd = -1;
        }

        c*k->status = 0;
    }

    if(c*k->ssl) {
        SSL_shutdown(c*k->ssl);
        SSL_free(c*k->ssl);
        c*k->ssl = NULL;
        SSL_CTX_free(c*k->ctx);
        c*k->ctx = NULL;
    }

    if(c*k->read_buf) {
        cosocket_link_buf_t *fr = c*k->read_buf;
        cosocket_link_buf_t *nb = NULL;

        while(fr) {
            nb = fr->next;
            free(fr->buf);
            free(fr);
            fr = nb;
        }

        c*k->read_buf = NULL;
    }

    if(c*k->send_buf_need_free) {
        free(c*k->send_buf_need_free);
        c*k->send_buf_need_free = NULL;
    }


    c*k->inuse = 0;

    lua_f_lua_uthread_resume_in_c(c*k->L, 2);
}
コード例 #9
0
int cosocket_be_read(se_ptr_t *ptr)
{
    cosocket_t *c*k = ptr->data;
    int n = 0, ret = 0;

init_read_buf:

    if(!c*k->read_buf
       || (c*k->last_buf->buf_len >= c*k->last_buf->buf_size)) {    /// init read buf
        cosocket_link_buf_t *nbuf = NULL;
        nbuf = malloc(sizeof(cosocket_link_buf_t));

        if(nbuf == NULL) {
            LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__);
            exit(1);
        }

        nbuf->buf = large_malloc(4096);

        if(!nbuf->buf) {
            LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__);
            exit(1);
        }

        nbuf->buf_size = 4096;
        nbuf->buf_len = 0;
        nbuf->next = NULL;

        if(c*k->read_buf) {
            c*k->last_buf->next = nbuf;

        } else {
            c*k->read_buf = nbuf;
        }

        c*k->last_buf = nbuf;
    }

    if(!c*k->ssl) {
        while((n = recv(c*k->fd, c*k->last_buf->buf + c*k->last_buf->buf_len,
                        c*k->last_buf->buf_size - c*k->last_buf->buf_len, 0)) > 0) {
            c*k->last_buf->buf_len += n;
            c*k->total_buf_len += n;

            if(c*k->last_buf->buf_len >= c*k->last_buf->buf_size) {
                goto init_read_buf;
            }
        }

    } else {
        while((n = SSL_read(c*k->ssl, c*k->last_buf->buf + c*k->last_buf->buf_len,
                            c*k->last_buf->buf_size - c*k->last_buf->buf_len)) > 0) {
            c*k->last_buf->buf_len += n;
            c*k->total_buf_len += n;

            if(c*k->last_buf->buf_len >= c*k->last_buf->buf_size) {
                goto init_read_buf;
            }
        }

    }

    if(n == 0 || (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) {
        int rfd = c*k->fd;
        /// socket closed
        delete_timeout(c*k->timeout_ptr);
        c*k->timeout_ptr = NULL;
        {
            c*k->status = 0;

            se_delete(c*k->ptr);
            c*k->ptr = NULL;
            connection_pool_counter_operate(c*k->pool_key, -1);
            close(c*k->fd);
            c*k->fd = -1;
            c*k->status = 0;
        }

        if(c*k->in_read_action == 1) {
            c*k->in_read_action = 0;
            int rt = lua_co_read_(c*k);
            c*k->inuse = 0;

            if(rt > 0) {
                ret = lua_f_lua_uthread_resume_in_c(c*k->L, rt);

            } else if(n == 0) {
                lua_pushnil(c*k->L);
                ret = lua_f_lua_uthread_resume_in_c(c*k->L, 1);
            }

            if(ret == LUA_ERRRUN) {
                se_delete(c*k->ptr);
                c*k->ptr = NULL;
                connection_pool_counter_operate(c*k->pool_key, -1);
                close(c*k->fd);
                c*k->fd = -1;
                c*k->status = 0;
            }
        }

    } else {
        if(c*k->in_read_action == 1) {
            int rt = lua_co_read_(c*k);

            if(rt > 0) {
                c*k->in_read_action = 0;
                delete_timeout(c*k->timeout_ptr);
                c*k->timeout_ptr = NULL;
                c*k->inuse = 0;

                ret = lua_f_lua_uthread_resume_in_c(c*k->L, rt);

                if(ret == LUA_ERRRUN) {
                    se_delete(c*k->ptr);
                    c*k->ptr = NULL;
                    connection_pool_counter_operate(c*k->pool_key, -1);
                    close(c*k->fd);
                    c*k->fd = -1;
                    c*k->status = 0;
                }
            }
        }
    }

    return 0;
}
コード例 #10
0
int cosocket_be_write(se_ptr_t *ptr)
{
    cosocket_t *c*k = ptr->data;
    int n = 0, ret = 0;
    c*k->in_read_action = 0;

    if(!c*k->ssl) {
        while((n = send(c*k->fd, c*k->send_buf + c*k->send_buf_ed, c*k->send_buf_len - c*k->send_buf_ed, MSG_DONTWAIT)) > 0) {
            c*k->send_buf_ed += n;
        }

    } else {
        while((n = SSL_write(c*k->ssl, c*k->send_buf + c*k->send_buf_ed, c*k->send_buf_len - c*k->send_buf_ed)) > 0) {
            c*k->send_buf_ed += n;
        }
    }

    if(c*k->send_buf_ed == c*k->send_buf_len || (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) {
        if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
            se_delete(c*k->ptr);
            c*k->ptr = NULL;
            connection_pool_counter_operate(c*k->pool_key, -1);
            close(c*k->fd);
            c*k->fd = -1;
            c*k->status = 0;
            c*k->send_buf_ed = 0;

        }

        /* else {
            se_be_pri(c*k->ptr, NULL);
        }*/

        if(c*k->send_buf_need_free) {
            free(c*k->send_buf_need_free);
            c*k->send_buf_need_free = NULL;
        }

        delete_timeout(c*k->timeout_ptr);
        c*k->timeout_ptr = NULL;

        int rc = 1;

        if(c*k->send_buf_ed >= c*k->send_buf_len) {
            lua_pushnumber(c*k->L, c*k->send_buf_ed);

        } else if(c*k->fd == -1) {
            lua_pushnil(c*k->L);
            lua_pushstring(c*k->L, "connection closed!");
            rc = 2;

        } else {
            lua_pushboolean(c*k->L, 0);
        }

        if(c*k->inuse == 1) {
            se_be_pri(c*k->ptr, NULL);
            c*k->inuse = 0;
            lua_f_lua_uthread_resume_in_c(c*k->L, rc);
            return 0;

        } else {
            return 0 - rc;
        }
    }

    return c*k->send_buf_len - c*k->send_buf_ed;
}
コード例 #11
0
static int _be_connect(cosocket_t *c*k, int fd, int yielded)
{
    int flag = 1;
    int ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));

    c*k->fd = fd;
    c*k->ptr = se_add(_loop_fd, fd, c*k);

    c*k->status = 2;
    c*k->in_read_action = 0;

    if(c*k->use_ssl) {
        if(c*k->ctx == NULL) {
            c*k->ctx = SSL_CTX_new(SSLv23_client_method());

            if(c*k->ctx == NULL) {
                connection_pool_counter_operate(c*k->pool_key, -1);
                se_delete(c*k->ptr);
                close(c*k->fd);

                c*k->ptr = NULL;
                c*k->fd = -1;
                c*k->status = 0;

                lua_pushnil(c*k->L);
                lua_pushstring(c*k->L, "SSL_CTX_new Error");
                return 2;
            }
        }

        c*k->ssl = SSL_new(c*k->ctx);

        if(c*k->ssl == NULL) {
            connection_pool_counter_operate(c*k->pool_key, -1);
            se_delete(c*k->ptr);
            close(c*k->fd);

            c*k->ptr = NULL;
            c*k->fd = -1;
            c*k->status = 0;

            SSL_CTX_free(c*k->ctx);
            c*k->ctx = NULL;

            lua_pushnil(c*k->L);
            lua_pushstring(c*k->L, "SSL_new Error");
            return 2;
        }

        SSL_set_fd(c*k->ssl, c*k->fd);
        se_be_read(c*k->ptr, cosocket_be_ssl_connected);

        if(SSL_connect(c*k->ssl) == 1) {
            se_be_pri(c*k->ptr, NULL);
            lua_pushboolean(c*k->L, 1);
            c*k->inuse = 0;
            return 1;
        }

        c*k->timeout_ptr = add_timeout(c*k, c*k->timeout, timeout_handle);

        return -2;
    }

    se_be_pri(c*k->ptr, NULL);
    lua_pushboolean(c*k->L, 1);
    c*k->inuse = 0;

    return 1;
}
コード例 #12
0
ファイル: lua-ext.c プロジェクト: cofyc/alilua
static int network_be_read_request_body(se_ptr_t *ptr)
{
    //printf("network_be_read_request_body\n");
    epdata_t *epd = ptr->data;

    if(!epd) {
        return 0;
    }

    int n = 0, readed = 0;
    char *buf = malloc(65536);
    int buf_size = 65536;

    if(!buf) {
        serv_status.active_counts--;

        se_delete(epd->se_ptr);
        epd->se_ptr = NULL;
        close(epd->fd);
        epd->fd = -1;

        if(epd->status == STEP_READ) {
            serv_status.reading_counts--;
            epd->status = STEP_PROCESS;
        }

        lua_pushnil(epd->L);
        lua_pushstring(epd->L, "memory error");
        LOGF(ERR, "memory error!");

        lua_f_lua_uthread_resume_in_c(epd->L, 2);

        return 0;
    }

    while((n = recv(epd->fd, buf + readed, buf_size - readed, 0)) >= 0) {
        if(n == 0) {
            serv_status.active_counts--;

            se_delete(epd->se_ptr);
            epd->se_ptr = NULL;
            close(epd->fd);
            epd->fd = -1;

            if(epd->status == STEP_READ) {
                serv_status.reading_counts--;
                epd->status = STEP_PROCESS;
            }

            break;
        }

        epd->data_len += n;
        readed += n;

        //printf("readed: %d\n", n);
        if(readed >= buf_size) {
            char *p = realloc(buf, buf_size + 65536);

            if(p) {
                buf = p;
                buf_size += 65536;

            } else {
                break;
            }
        }
    }

    if(readed > 0) {
        if(epd->status == STEP_READ) {
            serv_status.reading_counts--;
            epd->status = STEP_PROCESS;
        }

        se_be_pri(epd->se_ptr, NULL); // be wait
        lua_pushlstring(epd->L, buf, readed);
        free(buf);

        lua_f_lua_uthread_resume_in_c(epd->L, 1);

    } else if(n == 0) {
        n = -1;
        errno = 1;
    }

    if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
        serv_status.active_counts--;

        se_delete(epd->se_ptr);
        epd->se_ptr = NULL;
        close(epd->fd);
        epd->fd = -1;

        if(epd->status == STEP_READ) {
            serv_status.reading_counts--;
            epd->status = STEP_PROCESS;
        }

        lua_pushnil(epd->L);
        lua_pushstring(epd->L, "socket closed");

        lua_f_lua_uthread_resume_in_c(epd->L, 2);

        return 0;
    }
}
コード例 #13
0
se_ptr_t *get_connection_in_pool(int loop_fd, unsigned long pool_key, cosocket_t *c*k)
{
    int k = pool_key % 64;
    int p = (now / connect_pool_ttl) % 2;
    cosocket_connection_pool_t  *n = NULL,
                                 *m = NULL,
                                  *nn = NULL;
    se_ptr_t *ptr = NULL;

    /// clear old caches
    int q = (p + 1) % 2;
    int i = 0;

    for(i = 0; i < 64; i++) {
        n = connect_pool_p[q][i];

        while(n) {
            m = n;
            n = n->next;

            ptr = m->ptr;

            if(m->z == 0) {
                m->z = 1;
                nn = connect_pool_p[p][m->pool_key % 64];

                if(nn == NULL) {
                    connect_pool_p[p][m->pool_key % 64] = m;
                    m->next = NULL;
                    m->uper = NULL;

                } else {
                    m->uper = NULL;
                    m->next = nn;
                    nn->uper = m;
                    connect_pool_p[p][m->pool_key % 64] = m;
                }

            } else {
                int fd = ptr->fd;
                se_delete(ptr);
                connection_pool_counter_operate(m->pool_key, -1);
                close(fd);
                free(m);
            }
        }

        connect_pool_p[q][i] = NULL;
    }

    /// end
    if(pool_key == 0) {
        resume_in_waiting_get_connection(loop_fd);
        return NULL; /// only do clear job
    }

regetfd:
    n = connect_pool_p[p][k];

    while(n != NULL) {
        if(n->pool_key == pool_key) {
            break;
        }

        n = (cosocket_connection_pool_t *) n->next;
    }

    if(n) {
        if(n == connect_pool_p[p][k]) {    /// at top
            m = n->next;

            if(m) {
                m->uper = NULL;
                connect_pool_p[p][k] = m;

            } else {
                connect_pool_p[p][k] = NULL;
            }

        } else {
            ((cosocket_connection_pool_t *) n->uper)->next = n->next;

            if(n->next) {
                ((cosocket_connection_pool_t *) n->next)->uper = n->uper;
            }
        }

        ptr = n->ptr;

        if(c*k) {
            if(c*k->ctx) {
                SSL_CTX_free(c*k->ctx);
            }

            if(c*k->ssl_pw) {
                free(c*k->ssl_pw);
            }

            c*k->ctx = n->ctx;
            c*k->ssl = n->ssl;
            c*k->ssl_pw = n->ssl_pw;
        }

        free(n);
        //printf ( "get fd in pool%d %d key:%d\n", p, ptr->fd, k );
        return ptr;
    }

    if(p != q) {
        p = q;
        goto regetfd;
    }

    return NULL;
}
コード例 #14
0
static int lua_co_send(lua_State *L)
{
    cosocket_t *c*k = NULL;
    {
        if(lua_gettop(L) < 2) {
            return 0;
        }

        int t = lua_type(L, 2);

        if(!lua_isuserdata(L, 1) || (t != LUA_TSTRING && t != LUA_TTABLE)) {
            lua_pushboolean(L, 0);
            lua_pushstring(L, "Error params!");
            return 2;
        }

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

        if(c*k->status != 2 || c*k->fd == -1 || !c*k->ptr) {
            lua_pushboolean(L, 0);
            lua_pushstring(L, "Not connected!");
            return 2;
        }

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

        c*k->L = L;
        c*k->send_buf_ed = 0;

        if(t == LUA_TTABLE) {
            c*k->send_buf_len = lua_calc_strlen_in_table(L, 2, 2, 1 /* strict */);

            if(c*k->send_buf_len > 0) {
                if(c*k->send_buf_len < _SENDBUF_SIZE) {
                    c*k->send_buf_need_free = NULL;
                    lua_copy_str_in_table(L, 2, c*k->_send_buf);
                    c*k->send_buf = c*k->_send_buf;

                } else {
                    c*k->send_buf_need_free = large_malloc(c*k->send_buf_len);

                    if(!c*k->send_buf_need_free) {
                        LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__);
                        exit(1);
                    }

                    lua_copy_str_in_table(L, 2, c*k->send_buf_need_free);
                    c*k->send_buf = c*k->send_buf_need_free;
                }
            }

        } else {
            const char *p = lua_tolstring(L, 2, &c*k->send_buf_len);
            c*k->send_buf_need_free = NULL;

            if(c*k->send_buf_len < _SENDBUF_SIZE) {
                memcpy(c*k->_send_buf, p, c*k->send_buf_len);
                c*k->send_buf = c*k->_send_buf;

            } else {
                c*k->send_buf_need_free = large_malloc(c*k->send_buf_len);

                if(!c*k->send_buf_need_free) {
                    LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__);
                    exit(1);
                }

                memcpy(c*k->send_buf_need_free, p, c*k->send_buf_len);
                c*k->send_buf = c*k->send_buf_need_free;
            }
        }

        if(c*k->send_buf_len < 1) {
            lua_pushboolean(L, 0);
            lua_pushstring(L, "content empty!");
            return 2;
        }

        c*k->inuse = 0;
        int ret = cosocket_be_write(c*k->ptr);

        if(ret > 0) {
            if(
                se_be_write(c*k->ptr, cosocket_be_write) == -1) {
                se_delete(c*k->ptr);
                close(c*k->fd);
                c*k->ptr = NULL;
                c*k->fd = -1;
                c*k->status = 0;

                lua_pushnil(c*k->L);
                lua_pushstring(c*k->L, "Network Error");
                return 2;

            } else {

                c*k->timeout_ptr = add_timeout(c*k, c*k->timeout, timeout_handle);
                c*k->inuse = 1;
                return lua_yield(L, 0);
            }

        } else {
            return 0 - ret;
        }
    }
}