Example #1
0
static void timeout_handle(void *ptr)
{
    epdata_t *epd = ptr;

    if(epd->status == STEP_READ) {
        epd->keepalive = 0;
        //LOGF(ERR, "Read Timeout!");
        network_send_error(epd, 400, "Timeout!");
        return;
        //serv_status.reading_counts--;

    } else if(epd->status == STEP_SEND) {
        //LOGF(ERR, "Send Timeout!");
        serv_status.sending_counts--;
    }

    if(epd->status == STEP_PROCESS && epd->L) {
        LOGF(ERR, "Process Timeout(continue)");
        update_timeout(epd->timeout_ptr, STEP_PROCESS_TIMEOUT);
        return;
    }

    epd->status = STEP_WAIT;

    close_client(epd);
}
Example #2
0
static int network_be_read ( se_ptr_t *ptr )
{
    epdata_t *epd = ptr->data;

    if ( !epd ) {
        return 0;
    }

    int n = 0;

    update_timeout ( epd->timeout_ptr, STEP_READ_TIMEOUT );

    if ( epd->headers == NULL ) {
        epd->headers = &epd->iov;
        epd->buf_size = sizeof ( epd->iov );

    } else if ( epd->data_len == epd->buf_size ) {
        if ( epd->headers == &epd->iov ) {
            epd->headers = malloc ( 4096 * 2 );
            memcpy ( epd->headers, &epd->iov, sizeof ( epd->iov ) );
            epd->buf_size = 4096 * 2;

        } else {
            char *_t = ( char * ) realloc ( epd->headers, epd->buf_size + 4096 );

            if ( _t != NULL ) {
                epd->headers = _t;

            } else {
                epd->iov[0].iov_base = NULL;
                epd->iov[0].iov_len = 0;
                epd->iov[1].iov_base = NULL;
                epd->iov[1].iov_len = 0;
                network_send_error ( epd, 503, "memory error!" );
                close_client ( epd );
                serv_status.reading_counts--;
                return 0;
            }

            epd->buf_size += 4096;
        }
    }

    while ( ( n = recv ( epd->fd, epd->headers + epd->data_len,
                         epd->buf_size - epd->data_len, 0 ) ) >= 0 ) {
        if ( n == 0 ) {
            close_client ( epd );
            epd = NULL;
            break;
        }

        if ( epd->data_len + n >= epd->buf_size ) {
            if ( epd->headers == &epd->iov ) {
                epd->headers = malloc ( 4096 * 2 );
                memcpy ( epd->headers, &epd->iov, sizeof ( epd->iov ) );
                epd->buf_size = 4096 * 2;

            } else {
                char *_t = ( char * ) realloc ( epd->headers, epd->buf_size + 4096 );

                if ( _t != NULL ) {
                    epd->headers = _t;

                } else {
                    epd->iov[0].iov_base = NULL;
                    epd->iov[0].iov_len = 0;
                    epd->iov[1].iov_base = NULL;
                    epd->iov[1].iov_len = 0;
                    network_send_error ( epd, 503, "memory error!" );
                    close_client ( epd );
                    serv_status.reading_counts--;
                    return 0;
                }

                epd->buf_size += 4096;
            }
        }

        if ( epd->status != STEP_READ ) {
            serv_status.reading_counts++;
            epd->status = STEP_READ;
            epd->data_len = n;
            epd->start_time = longtime();

        } else {
            epd->data_len += n;
        }

        if ( epd->_header_length < 1 && epd->data_len >= 4 && epd->headers ) {
            int _get_content_length = 0;

            if ( epd->headers[epd->data_len - 1] == '\n' &&
                 ( epd->headers[epd->data_len - 2] == '\n' ||
                   ( epd->headers[epd->data_len - 4] == '\r' &&
                     epd->headers[epd->data_len - 2] == '\r' ) ) ) {
                epd->_header_length = epd->data_len;

            } else {
                _get_content_length = 1;
                unsigned char *fp2 = stristr ( epd->headers, "\r\n\r\n", epd->data_len );

                if ( fp2 ) {
                    epd->_header_length = ( fp2 - epd->headers ) + 4;

                } else {
                    fp2 = stristr ( epd->headers, "\n\n", epd->data_len );

                    if ( fp2 ) {
                        epd->_header_length = ( fp2 - epd->headers ) + 2;
                    }
                }
            }

            if ( epd->_header_length > 0 && epd->content_length < 0 ) {
                /// not POST or PUT request
                if ( _get_content_length == 0 && epd->headers[0] != 'P' && epd->headers[0] != 'p' ) {
                    epd->content_length = 0;

                } else {
                    int flag = 0;

                    unsigned char *fp = stristr ( epd->headers, "\ncontent-length:", epd->data_len );

                    if ( fp ) {
                        int fp_at = fp - epd->headers + 16;
                        int i = 0, _oc;

                        for ( i = fp_at; i < epd->data_len; i++ ) {
                            if ( epd->headers[i] == '\r' || epd->headers[i] == '\n' ) {
                                flag = 1;
                                fp = epd->headers + fp_at;
                                _oc = epd->headers[i];
                                epd->headers[i] = '\0';
                                break;
                            }
                        }

                        if ( flag ) {
                            epd->content_length = atoi ( fp );
                            epd->headers[i] = _oc;
                        }

                        if ( stristr ( epd->headers + ( epd->_header_length - 60 ), "100-continue",
                                       epd->_header_length ) ) {
                            network_raw_send ( epd->fd, "HTTP/1.1 100 Continue\r\n\r\n", 25 );
                        }
                    }
                }
            }

            if ( epd->_header_length > 0
                 && epd->_header_length < epd->data_len
                 && epd->content_length < 1 ) {
                epd->iov[0].iov_base = NULL;
                epd->iov[0].iov_len = 0;
                epd->iov[1].iov_base = NULL;
                epd->iov[1].iov_len = 0;
                network_send_error ( epd, 411, "" );
                close_client ( epd );
                epd = NULL;
                serv_status.reading_counts--;

                break;
            }
        }

        //printf("data_len = %d header_length = %d content_length = %d\n", epd->data_len, epd->_header_length, epd->content_length);

        if ( epd->_header_length > 0 && ( ( epd->content_length < 1
                                            && epd->_header_length > 0 ) ||
                                          epd->content_length <= epd->data_len - epd->_header_length ) ) {


            /// start job
            epd->header_len = epd->_header_length;
            epd->headers[epd->data_len] = '\0';
            epd->header_len -= 1;
            epd->headers[epd->header_len] = '\0';

            if ( epd->header_len + 1 < epd->data_len ) {
                epd->contents = epd->headers + epd->header_len + 1;

            } else {
                epd->content_length = 0;
            }


            if ( USE_KEEPALIVE == 1 && ( epd->keepalive == 1 ||
                                         ( stristr ( epd->headers, "keep-alive", epd->header_len ) ) )
               ) {
                epd->keepalive = 1;
            }

            epd->response_header_length = 0;
            epd->iov_buf_count = 0;
            epd->response_content_length = 0;

            epd->response_sendfile_fd = -1;

            /// output server status !!!!!!!!!!
            {
                int i, len;
                char *uri = NULL;
                uri = epd->headers;

                for ( i = 0; i < epd->header_len; i++ )
                    if ( uri[i] == ' ' ) {
                        break;
                    }

                for ( ; i < epd->header_len; i++ )
                    if ( uri[i] != ' ' ) {
                        break;
                    }

                uri = epd->headers + i;
                len = strlen ( uri );

                for ( i = 0; i < len; i++ ) {
                    if ( uri[i] == '\r' || uri[i] == '\n' || uri[i] == ' ' ) {
                        break;
                    }
                }

                if ( i > 11 && strncmp ( "/serv-status", uri, i ) == 0 ) {
                    epd->process_timeout = 0;

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

                    network_send_status ( epd );
                    serv_status.reading_counts--;
                    break;
                }
            }
            /// end.

            se_be_pri ( epd->se_ptr, NULL ); // be wait

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

                serv_status.sec_process_counts[ ( now ) % 5]++;
                serv_status.process_counts++;
                epd->method = NULL;
                epd->uri = NULL;
                epd->host = NULL;
                epd->query = NULL;
                epd->http_ver = NULL;
                epd->referer = NULL;
                epd->user_agent = NULL;

                if ( process_func ( epd, 0 ) != 0 ) {
                    close_client ( epd );
                    epd = NULL;
                }
            }

            break;
        }
    }

    if ( epd && n < 0 && errno != EAGAIN && errno != EWOULDBLOCK ) {
        //printf("error fd %d (%d) %s\n", epd->fd, errno, strerror(errno));
        close_client ( epd );
        epd = NULL;
        return 0;
    }

    return 1;
}
Example #3
0
void network_be_end ( epdata_t *epd )  // for lua function die
{
    if ( epd->process_timeout == 1 && epd->keepalive != -1 ) {
        epd->process_timeout = 0;
        free_epd ( epd );
        return;
    }

    //printf ( "network_be_end %d\n" , ((se_ptr_t*)epd->se_ptr)->fd );
    update_timeout ( epd->timeout_ptr, STEP_SEND_TIMEOUT );
    se_be_write ( epd->se_ptr, network_be_write );
    serv_status.success_counts++;
    epd->status = STEP_SEND;
    serv_status.sending_counts++;

    if ( epd->iov[0].iov_base == NULL && epd->iov[1].iov_base == NULL
         && epd->response_sendfile_fd == -1 ) {
        serv_status.sending_counts--;
        network_send_error ( epd, 417, "" );

    } else if ( epd->response_sendfile_fd == -2 ) {
        epd->response_sendfile_fd = -1;
        serv_status.sending_counts--;
        network_send_error ( epd, 404, "File Not Found!" );

    } else {
        int gzip_data = 0;

        //printf("%d %s\n", epd->response_content_length, epd->iov[1].iov_base);
        if ( epd->response_content_length > 1024 && epd->iov[1].iov_base &&
             !is_binary ( epd->iov[1].iov_base, epd->iov[1].iov_len )
           ) {
            char *p = NULL;

            if ( epd->headers ) {
                p = stristr ( epd->headers, "Accept-Encoding", epd->header_len );
            }

            if ( p ) {
                p += 16;
                int i = 0, m = strlen ( p );

                for ( ; i < 20 && i < m; i++ ) {
                    if ( p[i] == '\n' ) {
                        break;
                    }
                }

                p[i] = '\0';

                if ( strstr ( p, "deflate" ) ) {
                    gzip_data = 2;

                } else if ( strstr ( p, "gzip" ) ) {
                    gzip_data = 1;
                }

                p[i] = '\n';
            }
        }

        if ( gzip_data > 0 )
            epd->response_content_length = gzip_iov ( gzip_data,
                                           ( struct iovec * ) &epd->iov,
                                           epd->iov_buf_count,
                                           &epd->iov_buf_count );

        int len = 0;

        if ( epd->iov[0].iov_base == NULL ) {
            len = sprintf ( temp_buf,
                            "HTTP/1.1 200 OK\r\nServer: aLiLua/%s (%s)\r\nContent-Type: text/html; charset=UTF-8\r\nConnection: %s\r\n%sContent-Length: %d\r\n\r\n",
                            version, hostname, ( epd->keepalive == 1 ? "keep-alive" : "close" ),
                            ( gzip_data == 1 ? "Content-Encoding: gzip\r\n" : ( gzip_data == 2 ?
                                    "Content-Encoding: deflate\r\n" : "" ) ),
                            epd->response_content_length + ( gzip_data == 1 ? 10 : 0 ) );
            epd->response_header_length = len;

        } else {
            //( ( char * ) ( epd->iov[0].iov_base ) ) [epd->response_header_length] = '\0';
            memcpy ( temp_buf, epd->iov[0].iov_base, epd->response_header_length );
            len = epd->response_header_length + sprintf ( temp_buf + epd->response_header_length,
                    "Server: aLiLua/%s (%s)\r\nConnection: %s\r\nDate: %s\r\n%sContent-Length: %d\r\n\r\n",
                    version, hostname, ( epd->keepalive == 1 ? "keep-alive" : "close" ), now_date,
                    ( gzip_data == 1 ? "Content-Encoding: gzip\r\n" : ( gzip_data == 2 ?
                            "Content-Encoding: deflate\r\n" : "" ) ),
                    epd->response_content_length + ( gzip_data == 1 ? 10 : 0 ) );
            epd->response_header_length += len;
        }

        if ( len < 4086 && epd->response_sendfile_fd <= -1 && epd->iov[1].iov_base
             && epd->iov[1].iov_len > 0 ) {
            if ( epd->iov[0].iov_base == NULL ) {
                epd->iov[0].iov_base = malloc ( EP_D_BUF_SIZE );
            }

            if ( epd->iov[0].iov_base == NULL ) {
                epd->keepalive = 0;
                network_end_process ( epd );
                serv_status.sending_counts--;
                return;
            }

            memcpy ( epd->iov[0].iov_base, temp_buf, len );
            epd->iov[0].iov_len = len;
            epd->response_content_length += len;

            if ( gzip_data == 1 ) {
                memcpy ( epd->iov[0].iov_base + len, gzip_header, 10 );
                epd->iov[0].iov_len += 10;
                epd->response_content_length += 10;
            }

            epd->iov_buf_count += 1;

        } else {
            network_raw_send ( epd->fd, temp_buf, len );

            if ( gzip_data == 1 ) {
                network_raw_send ( epd->fd, gzip_header, 10 );
            }

            free ( epd->iov[0].iov_base );
            epd->iov[0].iov_base = NULL;
            int i = 0;

            for ( i = 0; i < epd->iov_buf_count; i++ ) {
                epd->iov[i] = epd->iov[i + 1];
                epd->iov[i + 1].iov_base = NULL;
                epd->iov[i + 1].iov_len = 0;
            }
        }

        //epd->response_header_length = 0;
        //printf("%d\n", epd->response_header_length);

        if ( epd->response_content_length == 0 ) {
            network_end_process ( epd );
            serv_status.sending_counts--;

        } else {
            epd->response_buf_sended = 0;

        }
    }
}
Example #4
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 !!!");
            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;
    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) {
                return 1;

            } else {
                if(init_tables == 0) {
                    lua_newtable(L); //headers
                }
            }

            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);
                }
            }
        }
    }

    char *client_ip = inet_ntoa(epd->client_addr);
    lua_pushstring(L, client_ip);
    lua_setfield(L, -2, "remote-addr");
    int l = sizeof(struct sockaddr);
    struct sockaddr_in addr;
    getsockname(epd->fd, (struct sockaddr *) &addr, &l);
    lua_pushstring(L, inet_ntoa(addr.sin_addr));
    lua_setfield(L, -2, "server-addr");

    lua_setglobal(L, "headers");

    lua_newtable(L); /// _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);
        char kk[256] = {0};

        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;
                u_char *p;
                u_char *src, *dst;

                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_newtable(L); /// _COOKIE

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

            if(t2 && t3 && strlen(t2) > 0 && strlen(t3) > 0) {
                size_t len, dlen;
                u_char *p;
                u_char *src, *dst;
                len = strlen(t3);
                p = malloc(len);
                p[0] = '\0';
                dst = p;
                dlen = urldecode(&dst, (u_char **)&t3, len, RAW_UNESCAPE_URL);
                lua_pushlstring(L, (char *) p, dlen);

                len = strlen(t2);

                if(len > 4096) {
                    free(p);
                    p = malloc(len);
                }

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

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

    lua_setglobal(L, "_COOKIE");

    lua_pushnil(L);
    lua_setglobal(L, "__body_buf");

    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;", process_chdir);

    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_resume(L, 1) == LUA_ERRRUN && lua_isstring(L, -1)) {
        LOGF(ERR, "Lua:error %s", lua_tostring(L, -1));
        network_send_error(epd, 503, lua_tostring(L, -1));
        lua_pop(L, 1);
    }

    return 0;
}
Example #5
0
int worker_process ( epdata_t *epd, int thread_at )
{
    //printf("worker_process\n");
    working_at_fd = epd->fd;
    long start_time = longtime();
    //network_send_error(epd, 503, "Lua Error: main function not found !!!");return 0;
    //network_send(epd, "aaa", 3);network_be_end(epd);return 0;
    add_io_counts();
    lua_State *L = ( _L ); //lua_newthread

    if ( main_handle_ref != 0 ) {
        lua_rawgeti ( L, LUA_REGISTRYINDEX, main_handle_ref );

    } else {
        lua_getglobal ( L, "main" );
    }

    /*if(!lua_isfunction(L,-1))
    {
        lua_pop(L,1);
        printf("no function\n");
    }else*/{
        int init_tables = 0;
        char *pt1 = NULL, *pt2 = NULL, *t1 = NULL, *t2 = NULL, *t3 = NULL, *query = NULL;

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

        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 ) {
                    return 1;

                } else {
                    if ( init_tables == 0 ) {
                        lua_pushlightuserdata ( L, epd );
                        //lua_pushstring(L, epd->headers);
                        lua_newtable ( L );
                    }
                }

                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;
                        query = t2;
                        lua_pushstring ( L, t2 );
                        lua_setfield ( L, -2, "query" );
                    }
                }

                continue;
            }

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

            if ( t2 ) {
                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';
                    }

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

                    /// check content-type
                    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 ) ) {
                            boundary_post = stristr ( t3, "boundary=", len - 2 );
                        }

                    } 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 );
                    }
                }
            }
        }

        char *client_ip = inet_ntoa ( epd->client_addr );
        lua_pushstring ( L, client_ip );
        lua_setfield ( L, -2, "remote-addr" );

        lua_newtable ( L ); /// _GET

        if ( query ) { /// parse query string /?a=1&b=2
            while ( t1 = strtok_r ( query, "&", &query ) ) {
                t2 = strtok_r ( t1, "=", &t1 );
                t3 = strtok_r ( t1, "=", &t1 );

                if ( t2 && t3 && strlen ( t2 ) > 0 && strlen ( t3 ) > 0 ) {
                    size_t len, dlen;
                    u_char *p;
                    u_char *src, *dst;
                    len = strlen ( t3 );
                    p = large_malloc ( len );
                    p[0] = '\0';
                    dst = p;
                    ngx_http_lua_unescape_uri ( &dst, &t3, len, 0 );
                    lua_pushlstring ( L, ( char * ) p, dst - p );

                    len = strlen ( t2 );

                    if ( len > 4096 ) {
                        free ( p );
                        p = large_malloc ( len );
                    }

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

                    ngx_http_lua_unescape_uri ( &dst, &t2, len, 0 );
                    p[dst - p] = '\0';
                    lua_setfield ( L, -2, p );
                    free ( p );
                }
            }
        }

        lua_newtable ( L ); /// _COOKIE

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

                if ( t2 && t3 && strlen ( t2 ) > 0 && strlen ( t3 ) > 0 ) {
                    size_t len, dlen;
                    u_char *p;
                    u_char *src, *dst;
                    len = strlen ( t3 );
                    p = large_malloc ( len );
                    p[0] = '\0';
                    dst = p;
                    ngx_http_lua_unescape_uri ( &dst, &t3, len, 0 );
                    lua_pushlstring ( L, ( char * ) p, dst - p );

                    len = strlen ( t2 );

                    if ( len > 4096 ) {
                        free ( p );
                        p = large_malloc ( len );
                    }

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

                    ngx_http_lua_unescape_uri ( &dst, &t2, len, 0 );
                    p[dst - p] = '\0';
                    lua_setfield ( L, -2, p + ( p[0] == ' ' ? 1 : 0 ) );
                    free ( p );
                }
            }
        }

        lua_newtable ( L ); /// _POST

        if ( is_form_post == 1
             && epd->contents ) { /// parse post conents text=aa+bb&text2=%E4%B8%AD%E6%96%87+aa
            pt1 = epd->contents;

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

                if ( t2 && t3 && strlen ( t2 ) > 0 && strlen ( t3 ) > 0 ) {
                    size_t len, dlen;
                    u_char *p;
                    u_char *src, *dst;
                    len = strlen ( t3 );
                    p = large_malloc ( len );
                    p[0] = '\0';
                    dst = p;
                    ngx_http_lua_unescape_uri ( &dst, &t3, len, 0 );
                    lua_pushlstring ( L, ( char * ) p, dst - p );
                    free ( p );
                    //lua_pushstring(L, t3);
                    lua_setfield ( L, -2, t2 );
                }
            }

        } else if ( boundary_post ) { /// parse boundary body
            boundary_post += 9;
            int blen = strlen ( boundary_post );
            int len = 0;
            char *start = epd->contents, *p2 = NULL, *p1 = NULL, *pp = NULL, *value = NULL;
            int i = 0;

            do {
                p2 = strstr ( start, boundary_post );

                if ( p2 ) {
                    start = p2 + blen;
                }

                if ( p1 ) {
                    p1 += blen;

                    if ( p2 ) {
                        * ( p2 - 4 ) = '\0';

                    } else {
                        break;
                    }

                    len = p2 - p1;
                    value = stristr ( p1, "\r\n\r\n", len );

                    if ( value && value[4] != '\0' ) {
                        value[0] = '\0';
                        value += 4;
                        char *keyname = strstr ( p1, "name=\"" );
                        char *filename = NULL;
                        char *content_type = NULL;

                        if ( keyname ) {
                            keyname += 6;

                            for ( pp = keyname; *pp != '\0'; pp++ ) {
                                if ( *pp == '"' ) {
                                    *pp = '\0';
                                    p1 = pp + 2;
                                    break;
                                }
                            }

                            filename = strstr ( p1, "filename=\"" );

                            if ( filename ) { /// is file filed
                                filename += 10;

                                for ( pp = filename; *pp != '\0'; pp++ ) {
                                    if ( *pp == '"' ) {
                                        *pp = '\0';
                                        p1 = pp + 2;
                                        break;
                                    }
                                }

                                content_type = strstr ( p1, "Content-Type:" );

                                if ( content_type ) {
                                    content_type += 13;

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

                                lua_newtable ( L );
                                lua_pushstring ( L, filename );
                                lua_setfield ( L, -2, "filename" );
                                lua_pushstring ( L, content_type );
                                lua_setfield ( L, -2, "type" );
                                lua_pushnumber ( L, p2 - value - 4 );
                                lua_setfield ( L, -2, "size" );
                                lua_pushlstring ( L, value, p2 - value - 4 );
                                lua_setfield ( L, -2, "data" );

                                lua_setfield ( L, -2, keyname );

                            } else {
                                lua_pushstring ( L, value );
                                lua_setfield ( L, -2, keyname );
                            }
                        }
                    }
                }

                p1 = p2 + 2;
            } while ( p2 );
        }

        if ( epd->headers != &epd->iov ) {
            free ( epd->headers );
        }

        epd->headers = NULL;
        epd->header_len = 0;
        epd->contents = NULL;
        epd->content_length = 0;
        epd->iov[0].iov_base = NULL;
        epd->iov[0].iov_len = 0;
        epd->iov[1].iov_base = NULL;
        epd->iov[1].iov_len = 0;

        if ( lua_pcall ( L, 5, 0, 0 ) ) {
            if ( lua_isstring ( L, -1 ) ) {
                printf ( "Lua:error %s\n", lua_tostring ( L, -1 ) );
                const char *data = lua_tostring ( L, -1 );
                network_send_error ( epd, 503, data );
                lua_pop ( L, 1 );
                //network_be_end(epd);
            }
        }

        return 0;
    }

    network_send_error ( epd, 503, "Lua Error: main function not found !!!" );

    return 0;
}