// File: /workspace/github_c_makefile_star2_O2/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 0x469b
testq %rax, %rax
je 0x38ed
movq %rax, %r14
movq %rbx, %rdi
callq 0x4ae2
leaq 0x98(%rbx), %rax
movq %rax, -0x40(%rbp)
leaq 0x2097(%rbx), %r12
movq %r14, -0x30(%rbp)
movq %r12, -0x48(%rbp)
movq 0x20a0(%rbx), %rsi
movq %r12, %rax
movl $0x190, %r15d           # imm = 0x190
subq %rsi, %rax
movq %rax, -0x38(%rbp)
je 0x39c9
movl (%rbx), %edi
leaq -0x38(%rbp), %rdx
callq 0x54e4
movq %rax, %r13
testq %rax, %rax
js 0x35af
movq %r13, %rax
jne 0x35ca
jmp 0x39d4
callq 0x2050
cmpl $0xb, (%rax)
jne 0x3966
movq -0x38(%rbp), %rax
testq %rax, %rax
je 0x3992
addq %rax, 0x20a0(%rbx)
movq %rbx, %rdi
callq *0x20f0(%rbx)
testl %eax, %eax
je 0x35f7
cmpl $-0x2, %eax
jne 0x39c9
testq %r13, %r13
jle 0x3575
cmpq -0x38(%rbp), %r13
jae 0x3575
jmp 0x39d4
movl 0x4c(%rbx), %eax
cmpl $0x4, %eax
je 0x3608
cmpl $0x2, %eax
jne 0x39c3
movl 0x54(%rbx), %eax
movzwl %ax, %ecx
shrl $0x10, %eax
imull $0x3e8, %eax, %eax      # imm = 0x3E8
addl %eax, %ecx
cmpl $0x3e9, %ecx            # imm = 0x3E9
ja 0x3916
movl $0x200, %edx            # imm = 0x200
leaq -0x2f0(%rbp), %r12
movq %r12, %rdi
xorl %esi, %esi
callq 0x21b0
cmpl $0x0, 0x50(%rbx)
jne 0x3688
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 -0x30(%rbp), %r14
callq 0x21c0
movq %r12, %rdi
leaq 0x301e(%rip), %rsi      # 0x6698
callq 0x2470
testq %rax, %rax
je 0x384e
movq %r12, %rdi
leaq -0xe8(%rbp), %rsi
callq 0x2270
testl %eax, %eax
jne 0x3921
movl -0xd0(%rbp), %eax
movl $0xf100, %ecx           # imm = 0xF100
andl %ecx, %eax
cmpl $0x8100, %eax           # imm = 0x8100
jne 0x392c
andl $0x0, (%r14)
movq -0x90(%rbp), %rax
movq %rax, 0x10(%r14)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x46e2
testl %eax, %eax
jne 0x3937
movl (%r14), %eax
movl %eax, %ecx
andl $0x30, %ecx
cmpl $0x20, %ecx
je 0x3956
testb $-0x40, %al
jne 0x395e
cmpl $0xff, %eax
ja 0x3701
orl $0xc800, %eax           # imm = 0xC800
movl %eax, (%r14)
movq -0xb8(%rbp), %r15
leaq -0x2f0(%rbp), %rdi
pushq $0x2e
popq %rsi
callq 0x2180
leaq 0x3141(%rip), %rdx      # 0x685f
testq %rax, %rax
je 0x3758
movq %rax, %r12
leaq 0x651b(%rip), %r14      # 0x9c48
movq -0x8(%r14), %rdi
testq %rdi, %rdi
je 0x3748
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
je 0x3751
addq $0x10, %r14
jmp 0x372d
leaq 0x3110(%rip), %rdx      # 0x685f
jmp 0x3754
movq (%r14), %rdx
movq -0x30(%rbp), %r14
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rcx
xorl %r8d, %r8d
callq 0x3b33
leaq -0x2f0(%rbp), %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x2380
cmpl $0x2, %eax
jg 0x37a6
pushq $0x4
popq %rdi
leaq 0x2def(%rip), %rsi      # 0x6579
leaq 0x2f10(%rip), %rdx      # 0x66a1
movl $0x1b6, %ecx            # imm = 0x1B6
leaq 0x2f11(%rip), %r8       # 0x66ae
xorl %eax, %eax
callq 0x4c60
jmp 0x381a
movl %eax, %r12d
xorl %edi, %edi
movq %r15, %rsi
pushq $0x1
popq %rdx
pushq $0x2
popq %rcx
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x2150
cmpq $-0x1, %rax
je 0x37ea
movq %rax, %r14
movl %r12d, %edi
callq 0x21d0
movl (%rbx), %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x5540
movq %r14, %rdi
movq %r15, %rsi
callq 0x2320
jmp 0x3816
pushq $0x4
popq %rdi
leaq 0x2d85(%rip), %rsi      # 0x6579
leaq 0x2ea6(%rip), %rdx      # 0x66a1
movl $0x1bc, %ecx            # imm = 0x1BC
leaq 0x2eb8(%rip), %r8       # 0x66bf
xorl %eax, %eax
callq 0x4c60
movl %r12d, %edi
callq 0x21d0
movq -0x30(%rbp), %r14
testb $0xf, (%r14)
movq -0x48(%rbp), %r12
je 0x39d4
testq %r13, %r13
jle 0x3837
cmpq -0x38(%rbp), %r13
jb 0x39d4
movq -0x40(%rbp), %rax
movq %rax, 0x2098(%rbx)
movq %rax, 0x20a0(%rbx)
jmp 0x3575
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 0x2e1d(%rip), %rsi      # 0x669d
callq 0x2230
testl %eax, %eax
je 0x3688
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
addq %rax, %r15
sarq $0x20, %r15
cmpb $0x2f, -0x2f0(%rbp,%r15)
jne 0x3688
movq 0x90(%rbx), %rsi
movq %r12, %rdi
testq %rsi, %rsi
je 0x38c6
callq 0x23c0
jmp 0x3688
callq 0x2130
movabsq $0x74682e7865646e69, %rcx # imm = 0x74682E7865646E69
movq %rcx, -0x2f0(%rbp,%rax)
movl $0x6c6d74, -0x2e9(%rbp,%rax) # imm = 0x6C6D74
jmp 0x3688
leaq 0x2c85(%rip), %rsi      # 0x6579
leaq 0x2d20(%rip), %rdx      # 0x661b
leaq 0x2d29(%rip), %r8       # 0x662b
pushq $0x4
popq %rdi
movl $0x93, %ecx
xorl %eax, %eax
callq 0x4c60
jmp 0x39e4
movl $0x1f9, %r15d           # imm = 0x1F9
jmp 0x39c9
movl $0x194, %r15d           # imm = 0x194
jmp 0x39c9
movl $0x193, %r15d           # imm = 0x193
jmp 0x39c9
leaq 0x2c3b(%rip), %rsi      # 0x6579
leaq 0x2cd6(%rip), %rdx      # 0x661b
leaq 0x2d0b(%rip), %r8       # 0x6657
pushq $0x4
popq %rdi
movl $0xf3, %ecx
jmp 0x3983
movl $0x130, %r15d           # imm = 0x130
jmp 0x39c9
movl $0x19c, %r15d           # imm = 0x19C
jmp 0x39c9
leaq 0x2c0c(%rip), %rsi      # 0x6579
leaq 0x2ca7(%rip), %rdx      # 0x661b
leaq 0x2cd0(%rip), %r8       # 0x664b
pushq $0x4
popq %rdi
movl $0xae, %ecx
xorl %eax, %eax
callq 0x4c60
movl $0x1f4, %r15d           # imm = 0x1F4
jmp 0x39c9
leaq -0x54(%rbp), %rdx
movq %rbx, 0x4(%rdx)
movl $0xc0000001, (%rdx)     # imm = 0xC0000001
movq 0x8(%rbx), %rdi
movl (%rbx), %esi
callq 0x3206
movq 0x20e8(%rbx), %rsi
leaq -0x5e0(%rip), %rdx      # 0x33d9
movq %rbx, %rdi
callq 0x49c3
jmp 0x39dc
movl $0x1f5, %r15d           # imm = 0x1F5
movq %rbx, %rdi
movl %r15d, %esi
callq 0x39f8
movq %rbx, %rdi
callq 0x33d9
movq %r14, %rdi
callq 0x47a7
xorl %eax, %eax
addq $0x2c8, %rsp            # imm = 0x2C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq