// File: /workspace/github_c_makefile_star2_O0/ttoobne[P]bohttpd/src/core/bohttpd.c
// Function: main
int main(int argc, char* argv[]) {
    config_t*           config;
    char*               conf_path;
    struct sockaddr_in  cliaddr;
    socklen_t           cliadrlen;
    epoll_t*            epoll;
    struct epoll_event  epev;
    http_request_t*     event;
    threadpool_t*       threadpool;
    msec_t              timeout;
    int                 opt;
    int                 options_index;
    int                 listenfd;
    int                 connfd;
    int                 evnum;

    /* 配置文件默认路径 */
    conf_path = CONF_PATH;

    /* 解析参数 */
    while ((opt = getopt_long(argc, argv, "c:Vt?h", long_options, &options_index)) != EOF) {
        switch (opt) {
            case  0 : break;
            case 'c':
                conf_path = optarg;
                break;
            case 'V':
                fprintf(stderr, BOHTTPD_VER"\n");
                return 1;
            case 't':
                parse_configuration(conf_path);
                return 1;
            case ':':
            case '?':
            case 'h':
                usage();
                return 1;
            default:
                usage();
                return 1;
        }
    }

    /* 解析配置文件 */
    if ((config = parse_configuration(conf_path)) == NULL) {
        log_error("parse configuration failed.");
        return 1;
    }

    log_info("configuration file parsing is complete.");

    /* 初始化定时器 */
    if (init_timer() != 0) {
        log_error("init timer failed.");
        return 1;
    }

    log_info("timer initialization is complete.");

    /* 创建 epoll 文件描述符 */
    if ((epoll = epoll_create_fd(0)) == NULL) {
        log_error("create epoll fd failed.");
        return 1;
    }

    /* 创建监听描述符 */
    if ((listenfd = create_listenfd(config->port)) < 0) {
        log_error("create listenfd failed.");
        return 1;
    }

    /* 将监听描述符设置为非阻塞 */
    set_nonblocking(listenfd);

    /* 为了将 listenfd 放入 epoll 中，需要额外为 listenfd 初始化一个事件结构体  */
    if ((event = http_request_init(listenfd, epoll, NULL)) == NULL) {
        log_error("event_t init failed.");
        return 1;
    }

    /* epoll 监听 listenfd 上的 accept 事件，边缘触发 */
    epev.data.ptr = (void*)event;
    epev.events = EPOLLIN | EPOLLET;
    epoll_add_fd(epoll, listenfd, &epev);

    /* 创建线程池，大小从配置文件读取 */
    if ((threadpool = threadpool_create(config->threadpool, config->taskqueue)) == NULL) {
        log_error("thread poll create failed.");
        return 1;
    }

    cliadrlen = sizeof(cliaddr);    /* 必须初始化 */

    log_info("thread pool initialization is complete.");

    log_info("Bohttpd goes to work.");

    /* 主循环 */
    for ( ;; ) {
        timeout = find_timer();

        /* 根据超时时间最接近的事件确定 epoll wait 的阻塞时间 */
        if ((evnum = epoll_wait_event(epoll, MAX_EVENTS, timeout)) < 0) {
            log_error("epoll wait failed.");
            return 1;
        }

        /* 此时一定有超时事件，需要执行回调函数 */
        expire_timers();

        while(evnum -- ) {
            event = (http_request_t*)(epoll->events[evnum].data.ptr);
            if (event->fd == listenfd) {
                /* 边缘触发，所以必须处理完所有的连接请求 */
                for ( ;; ) {
                    //log_debug("ready to accept");
                    if ((connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cliadrlen)) < 0) {
                        if (errno != EAGAIN && errno != EWOULDBLOCK) {
                            log_error("accept error.");
                        }

                        break;
                    }

                    log_info("new connection arrive. client<%s:%u>", 
                            inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
                    
                    /* 初始化已连接描述符，加入定时器、epoll 监听可读事件 */
                    http_init_connection(connfd, epoll, config);
                }
                
            } else {
                if ((epoll->events[evnum].events & EPOLLERR) || 
                    (epoll->events[evnum].events & EPOLLHUP) || /* 对端关闭连接 */
                    !(epoll->events[evnum].events & EPOLLIN)) {

                    close(connfd);
                    continue;
                }

                event = epoll->events[evnum].data.ptr;

                /* 将执行任务添加至工作队列等待线程执行 */
                threadpool_add_task(threadpool, execute_request, (void*)event);

                //execute_request(event);
            }
        }
    }

    config_destroy(config);

    epoll_free(epoll);

    threadpool_destroy(threadpool);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq 0x6a14(%rip), %rax      # 0x9004
movq %rax, -0x20(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x6a11(%rip), %rdx      # 0x9013
leaq 0x9737(%rip), %rcx      # 0xbd40
leaq -0x70(%rbp), %r8
callq 0x2160
movl %eax, -0x6c(%rbp)
cmpl $-0x1, %eax
je 0x26d8
movl -0x6c(%rbp), %eax
movl %eax, -0x80(%rbp)
testl %eax, %eax
je 0x2666
jmp 0x262a
movl -0x80(%rbp), %eax
subl $0x3a, %eax
je 0x26b1
jmp 0x2634
movl -0x80(%rbp), %eax
subl $0x3f, %eax
je 0x26b1
jmp 0x263e
movl -0x80(%rbp), %eax
subl $0x56, %eax
je 0x2678
jmp 0x2648
movl -0x80(%rbp), %eax
subl $0x63, %eax
je 0x2668
jmp 0x2652
movl -0x80(%rbp), %eax
subl $0x68, %eax
je 0x26b1
jmp 0x265c
movl -0x80(%rbp), %eax
subl $0x74, %eax
je 0x269c
jmp 0x26c2
jmp 0x26d3
movq 0x9961(%rip), %rax      # 0xbfd0
movq (%rax), %rax
movq %rax, -0x20(%rbp)
jmp 0x26d3
movq 0x9971(%rip), %rax      # 0xbff0
movq (%rax), %rdi
leaq 0x6991(%rip), %rsi      # 0x901a
movb $0x0, %al
callq 0x2260
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
movq -0x20(%rbp), %rdi
callq 0x2b70
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
callq 0x2b50
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
callq 0x2b50
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
jmp 0x25f4
movq -0x20(%rbp), %rdi
callq 0x2b70
movq %rax, -0x18(%rbp)
cmpq $0x0, %rax
jne 0x271d
movl $0x4, %edi
leaq 0x6930(%rip), %rsi      # 0x9027
leaq 0x693c(%rip), %rdx      # 0x903a
movl $0x59, %ecx
leaq 0x6935(%rip), %r8       # 0x903f
movb $0x0, %al
callq 0x6450
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
movl $0x2, %edi
leaq 0x68fe(%rip), %rsi      # 0x9027
leaq 0x690a(%rip), %rdx      # 0x903a
movl $0x5d, %ecx
leaq 0x691f(%rip), %r8       # 0x905b
movb $0x0, %al
callq 0x6450
movb $0x0, %al
callq 0x5d40
cmpl $0x0, %eax
je 0x2781
movl $0x4, %edi
leaq 0x68cc(%rip), %rsi      # 0x9027
leaq 0x68d8(%rip), %rdx      # 0x903a
movl $0x61, %ecx
leaq 0x6915(%rip), %r8       # 0x9083
movb $0x0, %al
callq 0x6450
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
movl $0x2, %edi
leaq 0x689a(%rip), %rsi      # 0x9027
leaq 0x68a6(%rip), %rdx      # 0x903a
movl $0x65, %ecx
leaq 0x68f6(%rip), %r8       # 0x9096
movb $0x0, %al
callq 0x6450
xorl %edi, %edi
callq 0x36f0
movq %rax, -0x40(%rbp)
cmpq $0x0, %rax
jne 0x27ea
movl $0x4, %edi
leaq 0x6863(%rip), %rsi      # 0x9027
leaq 0x686f(%rip), %rdx      # 0x903a
movl $0x69, %ecx
leaq 0x68e1(%rip), %r8       # 0x90b8
movb $0x0, %al
callq 0x6450
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
movq -0x18(%rbp), %rax
movzwl 0x210(%rax), %edi
callq 0x3c40
movl %eax, -0x74(%rbp)
cmpl $0x0, %eax
jge 0x2834
movl $0x4, %edi
leaq 0x6819(%rip), %rsi      # 0x9027
leaq 0x6825(%rip), %rdx      # 0x903a
movl $0x6f, %ecx
leaq 0x68af(%rip), %r8       # 0x90d0
movb $0x0, %al
callq 0x6450
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
movl -0x74(%rbp), %edi
callq 0x8130
movl -0x74(%rbp), %edi
movq -0x40(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x5900
movq %rax, -0x58(%rbp)
cmpq $0x0, %rax
jne 0x2888
movl $0x4, %edi
leaq 0x67c5(%rip), %rsi      # 0x9027
leaq 0x67d1(%rip), %rdx      # 0x903a
movl $0x78, %ecx
leaq 0x6873(%rip), %r8       # 0x90e8
movb $0x0, %al
callq 0x6450
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
movq -0x58(%rbp), %rax
movq %rax, -0x48(%rbp)
movl $0x80000001, -0x4c(%rbp) # imm = 0x80000001
movq -0x40(%rbp), %rdi
movl -0x74(%rbp), %esi
leaq -0x4c(%rbp), %rdx
callq 0x3860
movq -0x18(%rbp), %rax
movl (%rax), %edi
movq -0x18(%rbp), %rax
movl 0x4(%rax), %esi
callq 0x79a0
movq %rax, -0x60(%rbp)
cmpq $0x0, %rax
jne 0x28f5
movl $0x4, %edi
leaq 0x6758(%rip), %rsi      # 0x9027
leaq 0x6764(%rip), %rdx      # 0x903a
movl $0x83, %ecx
leaq 0x681b(%rip), %r8       # 0x90fd
movb $0x0, %al
callq 0x6450
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
movl $0x10, -0x34(%rbp)
movl $0x2, %edi
leaq 0x671f(%rip), %rsi      # 0x9027
leaq 0x672b(%rip), %rdx      # 0x903a
movl $0x89, %ecx
leaq 0x67fd(%rip), %r8       # 0x9118
movb $0x0, %al
callq 0x6450
movl $0x2, %edi
leaq 0x66f9(%rip), %rsi      # 0x9027
leaq 0x6705(%rip), %rdx      # 0x903a
movl $0x8b, %ecx
leaq 0x67ff(%rip), %r8       # 0x9140
movb $0x0, %al
callq 0x6450
movb $0x0, %al
callq 0x5e30
movq %rax, -0x68(%rbp)
movq -0x40(%rbp), %rdi
movq -0x68(%rbp), %rax
movl %eax, %edx
movl $0x400, %esi            # imm = 0x400
callq 0x3a70
movl %eax, -0x7c(%rbp)
cmpl $0x0, %eax
jge 0x29a1
movl $0x4, %edi
leaq 0x66ac(%rip), %rsi      # 0x9027
leaq 0x66b8(%rip), %rdx      # 0x903a
movl $0x93, %ecx
leaq 0x67c8(%rip), %r8       # 0x9156
movb $0x0, %al
callq 0x6450
movl $0x1, -0x4(%rbp)
jmp 0x2b3e
movb $0x0, %al
callq 0x5ed0
movl -0x7c(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x7c(%rbp)
cmpl $0x0, %eax
je 0x2b39
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x7c(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq 0x4(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movl (%rax), %eax
cmpl -0x74(%rbp), %eax
jne 0x2aa1
jmp 0x29e8
movl -0x74(%rbp), %edi
leaq -0x30(%rbp), %rsi
leaq -0x34(%rbp), %rdx
callq 0x23e0
movl %eax, -0x78(%rbp)
cmpl $0x0, %eax
jge 0x2a3c
callq 0x2050
cmpl $0xb, (%rax)
je 0x2a3a
callq 0x2050
cmpl $0xb, (%rax)
je 0x2a3a
movl $0x4, %edi
leaq 0x6607(%rip), %rsi      # 0x9027
leaq 0x6613(%rip), %rdx      # 0x903a
movl $0xa2, %ecx
leaq 0x6736(%rip), %r8       # 0x9169
movb $0x0, %al
callq 0x6450
jmp 0x2a9c
movl -0x2c(%rbp), %edi
callq 0x2100
movq %rax, -0x88(%rbp)
movzwl -0x2e(%rbp), %edi
callq 0x2350
movq -0x88(%rbp), %r9
movzwl %ax, %eax
movl $0x2, %edi
leaq 0x65bd(%rip), %rsi      # 0x9027
leaq 0x65c9(%rip), %rdx      # 0x903a
movl $0xa9, %ecx
leaq 0x66fa(%rip), %r8       # 0x9177
movl %eax, (%rsp)
movb $0x0, %al
callq 0x6450
movl -0x78(%rbp), %edi
movq -0x40(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x3b30
jmp 0x29e8
jmp 0x2b34
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x7c(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
jne 0x2af8
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x7c(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
jne 0x2af8
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x7c(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x2b05
movl -0x78(%rbp), %edi
callq 0x21f0
jmp 0x29a8
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x7c(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq 0x4(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x60(%rbp), %rdi
movq -0x58(%rbp), %rdx
leaq 0x1281(%rip), %rsi      # 0x3db0
callq 0x7e20
jmp 0x29a8
jmp 0x2948
movl -0x4(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
nopw (%rax,%rax)