// File: /workspace/github_c_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2c8, %rsp            # imm = 0x2C8
movq %rdi, %rbx
leaq -0x2f0(%rbp), %rdi
movl $0x200, %edx            # imm = 0x200
xorl %esi, %esi
callq 0x21b0
xorl %eax, %eax
callq 0x4a3b
testq %rax, %rax
je 0x3bfb
movq %rax, %r14
movq %rbx, %rdi
callq 0x4ed8
leaq 0x2097(%rbx), %r12
movq 0x20a0(%rbx), %rsi
movq %r12, %rax
subq %rsi, %rax
movq %rax, -0x30(%rbp)
je 0x3c23
leaq 0x98(%rbx), %rax
movq %rax, -0x40(%rbp)
leaq -0x30(%rbp), %r15
movq %r14, -0x38(%rbp)
movq %r12, -0x48(%rbp)
movl (%rbx), %edi
movq %r15, %rdx
callq 0x5814
movq %rax, %r13
testq %rax, %rax
js 0x3881
movq %r13, %rax
jne 0x389c
jmp 0x3c30
callq 0x2050
cmpl $0xb, (%rax)
jne 0x3ca7
movq -0x30(%rbp), %rax
testq %rax, %rax
je 0x3cda
addq %rax, 0x20a0(%rbx)
movq %rbx, %rdi
callq *0x20f0(%rbx)
testl %eax, %eax
je 0x38d1
cmpl $-0x2, %eax
jne 0x3c23
testq %r13, %r13
jle 0x3b39
cmpq -0x30(%rbp), %r13
jae 0x3b39
jmp 0x3c30
movl 0x4c(%rbx), %eax
cmpl $0x2, %eax
leaq -0x2f0(%rbp), %rdi
je 0x38e9
cmpl $0x4, %eax
jne 0x3d0e
movl 0x54(%rbx), %eax
movzwl %ax, %ecx
shrl $0x10, %eax
imull $0x3e8, %eax, %eax      # imm = 0x3E8
addl %eax, %ecx
cmpl $0x3ea, %ecx            # imm = 0x3EA
jae 0x3c54
movl $0x200, %edx            # imm = 0x200
movq %rdi, %r12
xorl %esi, %esi
callq 0x21b0
cmpl $0x0, 0x50(%rbx)
jne 0x3962
movl 0x40(%rbx), %r15d
movq 0x30(%rbx), %r14
subl %r14d, %r15d
movq 0x88(%rbx), %rsi
movq %r12, %rdi
callq 0x2090
incl %r15d
movslq %r15d, %rdx
movq %r12, %rdi
movq %r14, %rsi
movq -0x38(%rbp), %r14
callq 0x21c0
movq %r12, %rdi
leaq 0x3d44(%rip), %rsi      # 0x7698
callq 0x2470
testq %rax, %rax
je 0x3b55
movq %r12, %rdi
leaq -0xe8(%rbp), %rsi
callq 0x2270
testl %eax, %eax
jne 0x3c5e
movl -0xd0(%rbp), %eax
movl $0xf100, %ecx           # imm = 0xF100
andl %ecx, %eax
cmpl $0x8100, %eax           # imm = 0x8100
jne 0x3c68
movl $0x0, (%r14)
movq -0x90(%rbp), %rax
movq %rax, 0x10(%r14)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4a8d
testl %eax, %eax
jne 0x3c72
movl (%r14), %eax
movl %eax, %ecx
andl $0x30, %ecx
cmpl $0x20, %ecx
je 0x3c93
testb $-0x40, %al
jne 0x3c9d
cmpl $0xff, %eax
ja 0x39de
orl $0xc800, %eax           # imm = 0xC800
movl %eax, (%r14)
movq -0xb8(%rbp), %r15
leaq -0x2f0(%rbp), %rdi
movl $0x2e, %esi
callq 0x2180
leaq 0x3e62(%rip), %rdx      # 0x785f
testq %rax, %rax
je 0x3a3c
movq %rax, %r12
leaq 0x7244(%rip), %r14      # 0xac50
leaq 0x3928(%rip), %rdi      # 0x733b
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
je 0x3a34
movq (%r14), %rdi
addq $0x10, %r14
testq %rdi, %rdi
jne 0x3a13
leaq 0x3e2d(%rip), %rdx      # 0x785f
jmp 0x3a38
movq -0x8(%r14), %rdx
movq -0x38(%rbp), %r14
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rcx
xorl %r8d, %r8d
callq 0x3e58
leaq -0x2f0(%rbp), %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x2380
cmpl $0x2, %eax
jg 0x3a8c
movl $0x4, %edi
leaq 0x3b09(%rip), %rsi      # 0x7579
leaq 0x3c2a(%rip), %rdx      # 0x76a1
movl $0x1b6, %ecx            # imm = 0x1B6
leaq 0x3c2b(%rip), %r8       # 0x76ae
xorl %eax, %eax
callq 0x252a
jmp 0x3b06
movl %eax, %r12d
xorl %edi, %edi
movq %r15, %rsi
movl $0x1, %edx
movl $0x2, %ecx
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x2150
cmpq $-0x1, %rax
je 0x3ad4
movq %rax, %r14
movl %r12d, %edi
callq 0x21d0
movl (%rbx), %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x5877
movq %r14, %rdi
movq %r15, %rsi
callq 0x2320
jmp 0x3b02
movl $0x4, %edi
leaq 0x3a99(%rip), %rsi      # 0x7579
leaq 0x3bba(%rip), %rdx      # 0x76a1
movl $0x1bc, %ecx            # imm = 0x1BC
leaq 0x3bcc(%rip), %r8       # 0x76bf
xorl %eax, %eax
callq 0x252a
movl %r12d, %edi
callq 0x21d0
movq -0x38(%rbp), %r14
testb $0xf, (%r14)
movq -0x48(%rbp), %r12
leaq -0x30(%rbp), %r15
je 0x3c30
testq %r13, %r13
jle 0x3b27
cmpq -0x30(%rbp), %r13
jb 0x3c30
movq -0x40(%rbp), %rax
movq %rax, 0x2098(%rbx)
movq %rax, 0x20a0(%rbx)
movq 0x20a0(%rbx), %rsi
movq %r12, %rax
subq %rsi, %rax
movq %rax, -0x30(%rbp)
jne 0x3865
jmp 0x3c23
movq %r12, %rdi
callq 0x2130
movq %rax, %r15
shlq $0x20, %r15
movabsq $-0x300000000, %rax     # imm = 0xFFFFFFFD00000000
addq %r15, %rax
sarq $0x20, %rax
leaq (%rax,%rbp), %rdi
addq $-0x2f0, %rdi           # imm = 0xFD10
leaq 0x3b16(%rip), %rsi      # 0x769d
callq 0x2230
testl %eax, %eax
je 0x3962
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
addq %rax, %r15
sarq $0x20, %r15
cmpb $0x2f, -0x2f0(%rbp,%r15)
jne 0x3962
movq 0x90(%rbx), %rsi
leaq -0x2f0(%rbp), %r12
movq %r12, %rdi
testq %rsi, %rsi
je 0x3bd4
callq 0x23c0
jmp 0x3962
callq 0x2130
movabsq $0x74682e7865646e69, %rcx # imm = 0x74682E7865646E69
movq %rcx, -0x2f0(%rbp,%rax)
movl $0x6c6d74, -0x2e9(%rbp,%rax) # imm = 0x6C6D74
jmp 0x3962
leaq 0x3977(%rip), %rsi      # 0x7579
leaq 0x3a12(%rip), %rdx      # 0x761b
leaq 0x3a1b(%rip), %r8       # 0x762b
movl $0x4, %edi
movl $0x93, %ecx
xorl %eax, %eax
callq 0x252a
jmp 0x3c40
movq %rbx, %rdi
movl $0x190, %esi            # imm = 0x190
callq 0x3d1b
movq %rbx, %rdi
callq 0x367b
movq %r14, %rdi
callq 0x4b60
xorl %eax, %eax
addq $0x2c8, %rsp            # imm = 0x2C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
movl $0x1f9, %esi            # imm = 0x1F9
jmp 0x3c2b
movq %rbx, %rdi
movl $0x194, %esi            # imm = 0x194
jmp 0x3c2b
movq %rbx, %rdi
movl $0x193, %esi            # imm = 0x193
jmp 0x3c2b
leaq 0x3900(%rip), %rsi      # 0x7579
leaq 0x399b(%rip), %rdx      # 0x761b
leaq 0x39d0(%rip), %r8       # 0x7657
movl $0x4, %edi
movl $0xf3, %ecx
jmp 0x3cc6
movq %rbx, %rdi
movl $0x130, %esi            # imm = 0x130
jmp 0x3c2b
movq %rbx, %rdi
movl $0x19c, %esi            # imm = 0x19C
jmp 0x3c2b
leaq 0x38cb(%rip), %rsi      # 0x7579
leaq 0x3966(%rip), %rdx      # 0x761b
leaq 0x398f(%rip), %r8       # 0x764b
movl $0x4, %edi
movl $0xae, %ecx
xorl %eax, %eax
callq 0x252a
movq %rbx, %rdi
movl $0x1f4, %esi            # imm = 0x1F4
jmp 0x3c2b
leaq -0x54(%rbp), %rdx
movq %rbx, 0x4(%rdx)
movl $0xc0000001, (%rdx)     # imm = 0xC0000001
movq 0x8(%rbx), %rdi
movl (%rbx), %esi
callq 0x347b
movq 0x20e8(%rbx), %rsi
leaq -0x686(%rip), %rdx      # 0x367b
movq %rbx, %rdi
callq 0x4db2
jmp 0x3c38
movq %rbx, %rdi
movl $0x1f5, %esi            # imm = 0x1F5
jmp 0x3c2b