// File: /workspace/github_c_makefile_star2_O0/ttoobne[P]bohttpd/src/http/http.c
// Function: execute_request
void* execute_request(void* http_request) {
    http_request_t* rq;
    http_headers_out_t* out;
    struct epoll_event epev;
    char filename[MAXLINE] = {'\0'};
    struct stat statbuf;
    size_t remain;
    ssize_t size;
    int ret;

    rq = (http_request_t*)http_request;

    if ((out = http_headers_out_init()) == NULL) {
        log_error("http_headers_out_t init failed.");
        return NULL;
    }

    delete_timer((void*)rq);

    for ( ;; ) {
        remain = &(rq->buf[BUF_SIZE - 1]) - rq->bufed;

        if (remain <= 0) {
            serve_error(rq, HTTP_BAD_REQUEST);

            goto close;
        }

        size = rio_readn(rq->fd, rq->bufed, &remain);

        /* size 返回 -1 */
        /* 1. 读到 EAGAIN ，所读字节数作为值-结果参数返回 */
        /* 2. 其他 errno ，出错 */

        /* size 返回大于等于 0 */
        /* 3. 读到 EOF 返回不足值 */
        /* 4. 读到 EOF 返回 0 */
        /* 5. 没读到 EOF 返回所读的值，此时缓冲区已满 */
        if (size < 0) {
            if (errno != EAGAIN) {
                log_error("read error.");
                serve_error(rq, HTTP_INTERNAL_SERVER_ERROR);
                
                goto close;
            }
            
            if (remain == 0) {
                break;
            }

            rq->bufed += remain;
        } else if (size == 0) {
            goto close;
        } else {
            rq->bufed += size;
        }

        /* 解析请求头，直到出错或完成 */
        if ((ret = rq->handler(rq)) == REQUEST_AGAIN) {
            if (size > 0 && size < remain) {
                goto close;
            }

            continue;
        } else if (ret != REQUEST_OK) {
            serve_error(rq, HTTP_BAD_REQUEST);
            
            goto close;
        }

        /* TODO: CGI&POST */
        if (rq->method != HTTP_GET && rq->method != HTTP_HEAD) {
            serve_error(rq, HTTP_NOT_IMPLEMENTED);

            goto close;
        }

        /* http 版本号超过 1.1 则不支持 */
        if (rq->http_version_major * 1000 + rq->http_version_minor > 1001) {
            serve_error(rq, HTTP_VERSION_NOT_SUPPORTED);

            goto close;
        }

        memset(filename, 0, sizeof(filename));
        parse_uri(rq, filename);

        /* 没找到改文件，返回 404 */
        if (stat(filename, &statbuf) != 0) {
            serve_error(rq, HTTP_NOT_FOUND);

            goto close;
        }

        /* 权限不够，返回 403 */
        if (!S_ISREG(statbuf.st_mode) || !(statbuf.st_mode & S_IRUSR)) {
            serve_error(rq, HTTP_FORBIDDEN);

            goto close;
        }

        out->keep_alive = 0;
        out->if_modified = 0;
        out->if_unmodified = 0;
        out->status = 0;
        out->mtime = statbuf.st_mtime;

        /* 分析首部字段 */
        if (http_analyze_headers(rq, out) != 0) {
            log_error("analyze headers failed.");
            serve_error(rq, HTTP_INTERNAL_SERVER_ERROR);
            
            goto close;
        }

        if (out->if_modified == 2) {
            serve_error(rq, HTTP_NOT_MODIFIED);

            goto close;
        }

        if (out->if_unmodified) {
            serve_error(rq, HTTP_PRECONDITION_FAILED);

            goto close;
        }

        if (out->status == 0) {
            out->status = HTTP_OK;
        }

        /* 发送静态文件 */
        serve_static(rq, out, filename, statbuf.st_size);

        if (!out->keep_alive) {
            goto close;
        }

        if (size > 0 && size < remain) {
            goto close;
        }

        /* 长连接处理第二个请求， HTTP/1.1 请求不会并行执行 */
        rq->bufst = &(rq->buf[0]);
        rq->bufed = &(rq->buf[0]);
        
    }

    /* 当前读完，但是没有关闭连接（返回 EAGAIN） */
    /* 则需要再次设置 epoll 监听（边缘触发） */
    epev.data.ptr = (void*)rq;
    epev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
    epoll_modify_fd((epoll_t*)rq->epoll, rq->fd, &epev);

    /* 再次定时 */
    add_timer((void*)rq, rq->timeout, http_close_connection);
    
    http_headers_out_destroy(out);
    
    return NULL;

close:

    /* 关闭连接 */
    http_close_connection(rq);
    http_headers_out_destroy(out);

    return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2e0, %rsp            # imm = 0x2E0
movq %rdi, -0x10(%rbp)
leaq -0x230(%rbp), %rdi
xorl %esi, %esi
movl $0x200, %edx            # imm = 0x200
callq 0x21d0
movq -0x10(%rbp), %rax
movq %rax, -0x18(%rbp)
movb $0x0, %al
callq 0x5ac0
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x3e1e
movl $0x4, %edi
leaq 0x579d(%rip), %rsi      # 0x9594
leaq 0x5838(%rip), %rdx      # 0x9636
movl $0x93, %ecx
leaq 0x583c(%rip), %r8       # 0x9646
movb $0x0, %al
callq 0x6450
movq $0x0, -0x8(%rbp)
jmp 0x425d
movq -0x18(%rbp), %rdi
callq 0x6180
movq -0x18(%rbp), %rax
addq $0x98, %rax
addq $0x1fff, %rax           # imm = 0x1FFF
movq -0x18(%rbp), %rcx
movq 0x20a0(%rcx), %rcx
subq %rcx, %rax
movq %rax, -0x2c8(%rbp)
cmpq $0x0, -0x2c8(%rbp)
ja 0x3e69
movq -0x18(%rbp), %rdi
movl $0x190, %esi            # imm = 0x190
callq 0x4270
jmp 0x4243
movq -0x18(%rbp), %rax
movl (%rax), %edi
movq -0x18(%rbp), %rax
movq 0x20a0(%rax), %rsi
leaq -0x2c8(%rbp), %rdx
callq 0x75b0
movq %rax, -0x2d0(%rbp)
cmpq $0x0, -0x2d0(%rbp)
jge 0x3f04
callq 0x2050
cmpl $0xb, (%rax)
je 0x3eda
movl $0x4, %edi
leaq 0x56e7(%rip), %rsi      # 0x9594
leaq 0x5782(%rip), %rdx      # 0x9636
movl $0xae, %ecx
leaq 0x57a6(%rip), %r8       # 0x9666
movb $0x0, %al
callq 0x6450
movq -0x18(%rbp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
callq 0x4270
jmp 0x4243
cmpq $0x0, -0x2c8(%rbp)
jne 0x3ee9
jmp 0x41ef
movq -0x2c8(%rbp), %rcx
movq -0x18(%rbp), %rax
addq 0x20a0(%rax), %rcx
movq %rcx, 0x20a0(%rax)
jmp 0x3f2e
cmpq $0x0, -0x2d0(%rbp)
jne 0x3f13
jmp 0x4243
movq -0x2d0(%rbp), %rcx
movq -0x18(%rbp), %rax
addq 0x20a0(%rax), %rcx
movq %rcx, 0x20a0(%rax)
jmp 0x3f2e
movq -0x18(%rbp), %rax
movq 0x20f0(%rax), %rax
movq -0x18(%rbp), %rdi
callq *%rax
movl %eax, -0x2d4(%rbp)
cmpl $-0x2, %eax
jne 0x3f6e
cmpq $0x0, -0x2d0(%rbp)
jle 0x3f69
movq -0x2d0(%rbp), %rax
cmpq -0x2c8(%rbp), %rax
jae 0x3f69
jmp 0x4243
jmp 0x3e27
cmpl $0x0, -0x2d4(%rbp)
je 0x3f8a
movq -0x18(%rbp), %rdi
movl $0x190, %esi            # imm = 0x190
callq 0x4270
jmp 0x4243
jmp 0x3f8c
movq -0x18(%rbp), %rax
cmpl $0x2, 0x4c(%rax)
je 0x3fb3
movq -0x18(%rbp), %rax
cmpl $0x4, 0x4c(%rax)
je 0x3fb3
movq -0x18(%rbp), %rdi
movl $0x1f5, %esi            # imm = 0x1F5
callq 0x4270
jmp 0x4243
movq -0x18(%rbp), %rax
movl 0x54(%rax), %eax
shrl $0x10, %eax
imull $0x3e8, %eax, %eax      # imm = 0x3E8
movq -0x18(%rbp), %rcx
movl 0x54(%rcx), %ecx
andl $0xffff, %ecx           # imm = 0xFFFF
addl %ecx, %eax
cmpl $0x3e9, %eax            # imm = 0x3E9
jle 0x3fec
movq -0x18(%rbp), %rdi
movl $0x1f9, %esi            # imm = 0x1F9
callq 0x4270
jmp 0x4243
leaq -0x230(%rbp), %rdi
xorl %esi, %esi
movl $0x200, %edx            # imm = 0x200
callq 0x21d0
movq -0x18(%rbp), %rdi
leaq -0x230(%rbp), %rsi
callq 0x4440
leaq -0x230(%rbp), %rdi
leaq -0x2c0(%rbp), %rsi
callq 0x2290
cmpl $0x0, %eax
je 0x403a
movq -0x18(%rbp), %rdi
movl $0x194, %esi            # imm = 0x194
callq 0x4270
jmp 0x4243
movl -0x2a8(%rbp), %eax
andl $0xf000, %eax           # imm = 0xF000
cmpl $0x8000, %eax           # imm = 0x8000
jne 0x405c
movl -0x2a8(%rbp), %eax
andl $0x100, %eax            # imm = 0x100
cmpl $0x0, %eax
jne 0x406f
movq -0x18(%rbp), %rdi
movl $0x193, %esi            # imm = 0x193
callq 0x4270
jmp 0x4243
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $-0x10, %ecx
orl $0x0, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $-0x31, %ecx
orl $0x0, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $0xffffff3f, %ecx       # imm = 0xFFFFFF3F
orl $0x0, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $0xff, %ecx
orl $0x0, %ecx
movl %ecx, (%rax)
movq -0x268(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x5b60
cmpl $0x0, %eax
je 0x4107
movl $0x4, %edi
leaq 0x54ba(%rip), %rsi      # 0x9594
leaq 0x5555(%rip), %rdx      # 0x9636
movl $0xf3, %ecx
leaq 0x5585(%rip), %r8       # 0x9672
movb $0x0, %al
callq 0x6450
movq -0x18(%rbp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
callq 0x4270
jmp 0x4243
movq -0x20(%rbp), %rax
movl (%rax), %eax
shrl $0x4, %eax
andl $0x3, %eax
cmpl $0x2, %eax
jne 0x412b
movq -0x18(%rbp), %rdi
movl $0x130, %esi            # imm = 0x130
callq 0x4270
jmp 0x4243
movq -0x20(%rbp), %rax
movl (%rax), %eax
shrl $0x6, %eax
andl $0x3, %eax
cmpl $0x0, %eax
je 0x414f
movq -0x18(%rbp), %rdi
movl $0x19c, %esi            # imm = 0x19C
callq 0x4270
jmp 0x4243
movq -0x20(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
cmpl $0x0, %eax
jne 0x4171
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $0xff, %ecx
orl $0xc800, %ecx           # imm = 0xC800
movl %ecx, (%rax)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
leaq -0x230(%rbp), %rdx
movq -0x290(%rbp), %rcx
callq 0x4550
movq -0x20(%rbp), %rax
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x0, %eax
jne 0x419f
jmp 0x4243
cmpq $0x0, -0x2d0(%rbp)
jle 0x41be
movq -0x2d0(%rbp), %rax
cmpq -0x2c8(%rbp), %rax
jae 0x41be
jmp 0x4243
movq -0x18(%rbp), %rcx
addq $0x98, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x2098(%rax)
movq -0x18(%rbp), %rcx
addq $0x98, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x20a0(%rax)
jmp 0x3e27
movq -0x18(%rbp), %rax
movq %rax, -0x28(%rbp)
movl $0xc0000001, -0x2c(%rbp) # imm = 0xC0000001
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rax
movl (%rax), %esi
leaq -0x2c(%rbp), %rdx
callq 0x3910
movq -0x18(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x20e8(%rax), %rsi
leaq -0x64b(%rip), %rdx      # 0x3be0
callq 0x6000
movq -0x20(%rbp), %rdi
callq 0x5cd0
movq $0x0, -0x8(%rbp)
jmp 0x425d
movq -0x18(%rbp), %rdi
callq 0x3be0
movq -0x20(%rbp), %rdi
callq 0x5cd0
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x2e0, %rsp            # imm = 0x2E0
popq %rbp
retq
nopw (%rax,%rax)