Пример #1
0
static void be_connect(void *data, int fd)
{
    cosocket_t *c*k = data;

    if(fd < 0) {
        connection_pool_counter_operate(c*k->pool_key, -1);

        lua_pushnil(c*k->L);

        if(se_errno == SE_DNS_QUERY_TIMEOUT) {
            lua_pushstring(c*k->L, "Connect error!(dns query timeout)");

        } else if(se_errno == SE_CONNECT_TIMEOUT) {
            lua_pushstring(c*k->L, "Connect error!(timeout)");

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

        c*k->status = 0;
        c*k->inuse = 0;

        lua_f_lua_uthread_resume_in_c(c*k->L, 2);
        return;
    }

    int ret = _be_connect(c*k, fd, 1);

    if(ret == -2) {
        return;
    }

    lua_f_lua_uthread_resume_in_c(c*k->L, ret);
}
Пример #2
0
int coevnet_module_do_other_jobs()
{
    swop_counter = swop_counter / 2;

    get_connection_in_pool(_loop_fd, 0, NULL);
    check_lua_sleep_timeouts();

    /// resume swops
    cosocket_swop_t *swop = NULL;

    if(swop_top->next != NULL) {
        swop = swop_top->next;
        swop_top->next = swop->next;

        if(swop_top->next == NULL) {
            swop_lat = NULL;
        }

        lua_State *L = swop->L;
        free(swop);
        swop = NULL;

        if(lua_status(L) == LUA_YIELD) {
            //lua_pushboolean ( L, 1 );
            lua_f_lua_uthread_resume_in_c(L, 0);
        }
    }
}
void resume_in_waiting_get_connection(int loop_fd)
{
    int k = 0;

    for(k = 0; k < 64; k++) {
        if(waiting_get_connections[k]) {
            cosocket_t *c*k = ((cosocket_waiting_get_connection_t *)waiting_get_connections[k])->c*k;

            c*k->ptr = get_connection_in_pool(loop_fd, c*k->pool_key, c*k);

            if(c*k->ptr) {
                c*k->pool_wait = NULL;
                delete_in_waiting_get_connection(waiting_get_connections[k]);
                ((se_ptr_t *) c*k->ptr)->data = c*k;
                c*k->status = 2;
                c*k->inuse = 0;
                c*k->reusedtimes = 1;
                c*k->in_read_action = 0;
                c*k->fd = ((se_ptr_t *) c*k->ptr)->fd;
                //printf("reuse %d\n", c*k->fd);
                delete_timeout(c*k->timeout_ptr);
                c*k->timeout_ptr = NULL;
                se_be_pri(c*k->ptr, NULL);
                lua_pushboolean(c*k->L, 1);

                lua_f_lua_uthread_resume_in_c(c*k->L, 1);

                return;
            }

        }
    }
}
Пример #4
0
int check_lua_sleep_timeouts()
{
    l_now = longtime() / 10;

    if(now_4sleep == 0) {
        now_4sleep = l_now - 5;
    }

    do {
        int k = now_4sleep % TIME_BUCKET_SIZE;

        sleep_timeout_t *m = timeout_links[k], *n = NULL;
        lua_State *L = NULL;

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

            if(l_now >= n->timeout) { // timeout
                {
                    if(n->uper) {
                        ((sleep_timeout_t *) n->uper)->next = n->next;

                    } else {
                        timeout_links[k] = n->next;
                    }

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

                    } else {
                        timeout_link_ends[k] = n->uper;
                    }

                    L = n->L;
                    free(n);
                }

                if(L) {
                    lua_f_lua_uthread_resume_in_c(L, 0);
                    l_now = longtime() / 10;
                }

                L = NULL;
            }
        }

        if(now_4sleep < l_now) {
            now_4sleep++;
            continue;
        }
    } while(now_4sleep < l_now);

    return 1;
}
Пример #5
0
int cosocket_be_ssl_connected(se_ptr_t *ptr)
{
    cosocket_t *c*k = ptr->data;

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

    return 0;
}
Пример #6
0
static int send_then_send(se_ptr_t *ptr)
{
    epdata_t *epd = ptr->data;
    epd->next_proc = NULL;

    char *buf = epd->next_out;
    int len = epd->next_out_len;
    epd->next_out_len = 0;

    int have = network_send(epd, buf, len);

    if(have > 0) {
        epd->next_out = malloc(have);

        if(epd->next_out) {
            memcpy(epd->next_out, buf + (len - have), have);
            free(buf);

            if(network_flush(epd) == 1) {
                epd->next_proc = send_then_send;
                epd->next_out_len = have;
                return have;

            } else {
                LOGF(ERR, "flush error");
                free(epd->next_out);
                epd->next_out = NULL;
                return 0;
            }

            return 0;
        }
    }

    free(buf);

    lua_f_lua_uthread_resume_in_c(epd->L, 0);

    return 0;
}
Пример #7
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);
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
0
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;
    }
}
Пример #11
0
int worker_process(epdata_t *epd, int thread_at)
{
    //printf("worker_process\n");
    working_at_fd = epd->fd;
    //network_send_error(epd, 503, "Lua Error: main function not found !!!");return 0;
    //network_send(epd, "aaa", 3);network_be_end(epd);return 0;

    if(epd->ssl && !epd->ssl_verify) {
        network_send_error(epd, 400, "No required SSL certificate was send");
        return 0;
    }

    lua_State *L = epd->L;

    if(!L) {
        epd->L = new_lua_thread(_L);

        if(!epd->L) {
            network_send_error(epd, 503, "Lua Error: Thread pool full !!!");
            LOGF(ERR, "Lua Error: Thread pool full !!!");
            return 0;
        }

        lua_pushlightuserdata(epd->L, epd);
        lua_setglobal(epd->L, "__epd__");

        L = epd->L;
    }

    lua_getglobal(L, "process");

    update_timeout(epd->timeout_ptr, STEP_PROCESS_TIMEOUT + 100);

    int init_tables = 0;
    char *pt1 = NULL, *pt2 = NULL, *t1 = NULL, *t2 = NULL, *t3 = NULL;

    int is_form_post = 0;
    char *cookies = NULL;
    pt1 = epd->headers;

    if(pt1[0] == '\0') {
        pt1 = pt1 + 1;
    }

    int i = 0;

    epd->uri = NULL;
    epd->host = NULL;
    epd->query = NULL;
    epd->http_ver = NULL;
    epd->referer = NULL;
    epd->user_agent = NULL;
    epd->if_modified_since = NULL;

    //epd->start_time = longtime();

    while(t1 = strtok_r(pt1, "\n", &pt1)) {
        if(++i == 1) { /// first line
            t2 = strtok_r(t1, " ", &t1);
            t3 = strtok_r(t1, " ", &t1);
            epd->http_ver = strtok_r(t1, " ", &t1);

            if(!epd->http_ver) {
                network_send_error(epd, 400, "Bad Request");
                return 0;

            } else {
                if(init_tables == 0) {
                    lua_createtable(L, 0, 20); //headers
                    init_tables = 1;
                }
            }

            int len = strlen(epd->http_ver);

            if(epd->http_ver[len - 1] == 13) { // CR == 13
                epd->http_ver[len - 1] = '\0';
            }

            if(t2 && t3) {
                for(t1 = t2 ; *t1 ; *t1 = toupper(*t1), t1++);

                epd->method = t2;
                lua_pushstring(L, t2);
                lua_setfield(L, -2, "method");
                t1 = strtok_r(t3, "?", &t3);
                t2 = strtok_r(t3, "?", &t3);
                epd->uri = t1;
                lua_pushstring(L, t1);
                lua_setfield(L, -2, "uri");

                if(t2) {
                    epd->query = (t2 - 1);
                    epd->query[0] = '?';
                    lua_pushstring(L, epd->query);
                    lua_setfield(L, -2, "query");
                }
            }

            continue;
        }

        t2 = strtok_r(t1, ":", &t1);

        if(t2) {
            if(t2[0] == '\r') {
                break;
            }

            for(t3 = t2; *t3; ++t3) {
                *t3 = *t3 >= 'A' && *t3 <= 'Z' ? *t3 | 0x60 : *t3;
            }

            t3 = t2 + strlen(t2) + 1; //strtok_r ( t1, ":", &t1 )

            if(t3) {
                int len = strlen(t3);

                if(t3[len - 1] == 13) { /// 13 == CR
                    t3[len - 1] = '\0';
                    len -= 1;
                }

                if(len < 1) {
                    break;
                }

                lua_pushstring(L, t3 + (t3[0] == ' ' ? 1 : 0));
                lua_setfield(L, -2, t2);

                /// check content-type
                if(t2[0] == 'h' && epd->host == NULL && strcmp(t2, "host") == 0) {
                    char *_t = strstr(t3, ":");

                    if(_t) {
                        _t[0] = '\0';
                    }

                    epd->host = t3 + (t3[0] == ' ' ? 1 : 0);

                } else if(t2[1] == 'o' && strcmp(t2, "content-type") == 0) {
                    if(stristr(t3, "x-www-form-urlencoded", len)) {
                        is_form_post = 1;

                    } else if(stristr(t3, "multipart/form-data", len)) {
                        epd->boundary = (char *)stristr(t3, "boundary=", len - 2);

                        if(epd->boundary) {
                            epd->boundary += 9;
                        }
                    }

                } else if(!cookies && t2[1] == 'o' && strcmp(t2, "cookie") == 0) {
                    cookies = t3 + (t3[0] == ' ' ? 1 : 0);

                } else if(!epd->user_agent && t2[1] == 's' && strcmp(t2, "user-agent") == 0) {
                    epd->user_agent = t3 + (t3[0] == ' ' ? 1 : 0);

                } else if(!epd->referer && t2[1] == 'e' && strcmp(t2, "referer") == 0) {
                    epd->referer = t3 + (t3[0] == ' ' ? 1 : 0);

                } else if(!epd->if_modified_since && t2[1] == 'f' && strcmp(t2, "if-modified-since") == 0) {
                    epd->if_modified_since = t3 + (t3[0] == ' ' ? 1 : 0);
                }
            }
        }
    }

    if(init_tables == 0) {
        network_send_error(epd, 400, "Bad Request");
        return 0;
    }

    const char *client_ip = cached_ntoa(epd->client_addr);
    lua_pushstring(L, client_ip);
    lua_setfield(L, -2, "remote-addr");
    lua_pushstring(L, cached_ntoa(epd->server_addr));
    lua_setfield(L, -2, "server-addr");

    lua_setglobal(L, "headers");

    lua_createtable(L, 0, 20); /// _GET

    if(epd->query) { /// parse query string /?a=1&b=2
        char *last = NULL;
        int plen = 0;
        int qlen = strlen(epd->query) - 1;

        t1 = (char *)strsplit(epd->query + 1, qlen, "&", &last, &plen);

        while(t1) {
            char *last2 = NULL;
            int plen2 = 0;
            int plen3 = 0;

            t2 = (char *)strsplit(t1, plen, "=", &last2, &plen2);
            t3 = (char *)strsplit(t1, plen, "=", &last2, &plen3);

            if(t2 && plen2 > 0 && plen3 > 0 && plen2 <= 4096 && plen3 <= 4096) {
                size_t dlen = 0;
                u_char *p = 0;
                u_char *src = NULL, *dst = NULL;

                p = (u_char *)&buf_4096;
                p[0] = '\0';
                dst = p;
                dlen = urldecode(&p, (u_char **)&t3, plen3, RAW_UNESCAPE_URL);
                lua_pushlstring(L, (char *) p, dlen);

                p[0] = '\0';
                dst = p;

                dlen = urldecode(&dst, (u_char **)&t2, plen2, RAW_UNESCAPE_URL);
                p[dlen] = '\0';
                lua_setfield(L, -2, p);
            }

            t1 = (char *)strsplit(epd->query + 1, qlen, "&", &last, &plen);
        }
    }

    lua_setglobal(L, "_GET");

    lua_createtable(L, 0, 20); /// _COOKIE

    if(cookies) {
        while(t1 = strtok_r(cookies, ";", &cookies)) {
            t2 = strtok_r(t1, "=", &t1);
            t3 = strtok_r(t1, "=", &t1);

            if(t2 && t3) {
                size_t t2_len = strlen(t2), t3_len = strlen(t3);

                if(t2_len > 0 && t3_len > 0) {
                    size_t dlen = 0, mlen = (t3_len > t2_len ? t3_len : t2_len);
                    u_char *p = (u_char *)&buf_4096;
                    u_char *src = NULL, *dst = NULL;

                    if(mlen > 4096) {
                        p = malloc(mlen);
                    }

                    p[0] = '\0';
                    dst = p;
                    dlen = urldecode(&dst, (u_char **)&t3, t3_len, RAW_UNESCAPE_URL);
                    lua_pushlstring(L, (char *) p, dlen);

                    p[0] = '\0';
                    dst = p;

                    dlen = urldecode(&dst, (u_char **)&t2, t2_len, RAW_UNESCAPE_URL);
                    p[dlen] = '\0';
                    lua_setfield(L, -2, p + (p[0] == ' ' ? 1 : 0));

                    if(mlen > 4096) {
                        free(p);
                    }
                }
            }
        }
    }

    lua_setglobal(L, "_COOKIE");

    epd->vhost_root = get_vhost_root(epd->host, &epd->vhost_root_len);

    memcpy(buf_4096, epd->vhost_root, epd->vhost_root_len + 1);
    sprintf(buf_4096 + epd->vhost_root_len + 1, "?.lua;%s/lua-libs/?.lua;%s", process_chdir, lua_path);

    lua_pushstring(L, buf_4096);
    lua_getglobal(L, "package");
    lua_insert(L, -2); //-1 bufres -2 package
    lua_setfield(L, -2, "path"); //-1: path -2: package
    lua_pop(L, 1); //void

    lua_pushlstring(L, epd->vhost_root, epd->vhost_root_len); /// host root

    lua_setglobal(L, "__root");

    lua_pushstring(L, epd->vhost_root + epd->vhost_root_len); /// index-route.lua file

    epd->iov[0].iov_base = NULL;
    epd->iov[0].iov_len = 0;
    epd->iov[1].iov_base = NULL;
    epd->iov[1].iov_len = 0;

    lua_routed = 0;

    if(lua_f_lua_uthread_resume_in_c(L, 1) == LUA_ERRRUN) {
        if(lua_isstring(L, -1)) {
            LOGF(ERR, "Lua:error %s", lua_tostring(L, -1));
            network_send_error(epd, 503, lua_tostring(L, -1));

        } else {
            network_send_error(epd, 503, "UNKNOW!");
        }

        lua_pop(L, 1);
    }

    return 0;
}