// File: /workspace/github_cpp_makefile_star2_O1/lszp[P]SmallWebServer/webserver.cpp
// Function: WebServer::eventListen()
void WebServer::eventListen()
{
    //网络编程基础步骤
    m_listenfd = socket(PF_INET, SOCK_STREAM, 0); // IPv4, TCP
    assert(m_listenfd >= 0);

    //优雅关闭连接
    if (0 == m_OPT_LINGER)
    {
        struct linger tmp = {0, 1};  // struct linger{int l_onoff, int l_linger}，l_onoff=0, l_linger忽略，调用closesocker断开TCP连接时，低层将未发送完的数据发送完再释放资源。
        setsockopt(m_listenfd, SOL_SOCKET, SO_LINGER, &tmp, sizeof(tmp));  //处于连接状态的socket调用closesocker后强制关闭，不经历TIME_WAIT过程
    }
    else if (1 == m_OPT_LINGER)
    {
        struct linger tmp = {1, 1}; // l_onoff非零，l_linger>0，调用closesocker不会立即返回，内核延迟一段时间，时间由l_linger决定，
                                    // 如果超时时间到达之前，发送完未发送的数据（包括FIN包）并得到另一端的确认，closesocket返回正确，socket描述符优雅退出，否则closesocket返回错误，
                                    // 未发送数据流失，socket描述符被强制退出。注意，如果socket描述符设置为非堵塞型，closesocket直接返回值。
        setsockopt(m_listenfd, SOL_SOCKET, SO_LINGER, &tmp, sizeof(tmp));
    }

    int ret = 0;
    struct sockaddr_in address;
    bzero(&address, sizeof(address));  // 初始化address结构体变量中sin_zero字符数组全部置为0
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = htonl(INADDR_ANY);  // htonl()将主机的无符号长整型数转换为网络字节顺序
    address.sin_port = htons(m_port);  // htons将主机无符号短整型数转换为网络字节顺序

    int flag = 1;
    setsockopt(m_listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));  // 一般不会立即关闭而经历TIME_WAIT过程，后续想重用socket
    ret = bind(m_listenfd, (struct sockaddr *)&address, sizeof(address));
    assert(ret >= 0);
    ret = listen(m_listenfd, 5);
    assert(ret >= 0);

    //工具类,信号和描述符基础操作
    Utils::u_pipefd = m_pipefd;
    Utils::u_epollfd = m_epollfd;

    utils.init(timer_lst, TIMESLOT);

    //epoll创建内核事件表
    epoll_event events[MAX_EVENT_NUMBER];
    m_epollfd = epoll_create(5);  // 生成epoll专用的文件描述符，其实是在内核申请空间，用来存放你想关注的socket fd上是否发生以及发生了什么事，size就是在epoll fd上能关注的最大socket fd数
    assert(m_epollfd != -1);

    utils.addfd(m_epollfd, m_listenfd, false, m_TRIGMode);
    http_conn::m_epollfd = m_epollfd;

    ret = socketpair(PF_UNIX, SOCK_STREAM, 0, m_pipefd);  // 创建一对套接字进行进程间通信（IPC），参数（协议族，协议，类型，套接字柄对）SOCK_STREAM基于TCP。套接字柄对作用相同，可进行读写双向操作。
    assert(ret != -1);
    utils.setnonblocking(m_pipefd[1]);
    utils.addfd(m_epollfd, m_pipefd[0], false, m_TRIGMode);

    utils.addsig(SIGPIPE, SIG_IGN);  // SIGPIPE 终止进程
    utils.addsig(SIGALRM, utils.sig_handler, false);  // SIGALRM 当进程的计时器到期时，SIGALRM信号交付给进程。
    utils.addsig(SIGTERM, utils.sig_handler, false);

    alarm(TIMESLOT);  // alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x30, %rsp
movq %rdi, %rbx
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x30c0
movl %eax, 0x1d56c(%rbx)
testl %eax, %eax
js 0x829a
movl 0x1d570(%rbx), %ecx
cmpl $0x1, %ecx
je 0x80d8
testl %ecx, %ecx
jne 0x8104
movabsq $0x100000000, %rdx      # imm = 0x100000000
jmp 0x80e5
movabsq $0x100000000, %rdx      # imm = 0x100000000
incq %rdx
leaq 0x20(%rsp), %rcx
movq %rdx, (%rcx)
movl %eax, %edi
movl $0x1, %esi
movl $0xd, %edx
movl $0x8, %r8d
callq 0x3710
xorps %xmm0, %xmm0
leaq 0x20(%rsp), %r14
movaps %xmm0, (%r14)
movw $0x2, (%r14)
movl $0x0, 0x4(%r14)
movzwl (%rbx), %eax
rolw $0x8, %ax
movw %ax, 0x2(%r14)
leaq 0xc(%rsp), %rcx
movl $0x1, (%rcx)
movl 0x1d56c(%rbx), %edi
movl $0x1, %esi
movl $0x2, %edx
movl $0x4, %r8d
callq 0x3710
movl 0x1d56c(%rbx), %edi
movq %r14, %rsi
movl $0x10, %edx
callq 0x3090
testl %eax, %eax
js 0x82b9
movl 0x1d56c(%rbx), %edi
movl $0x5, %esi
callq 0x34b0
testl %eax, %eax
js 0x82d8
leaq 0x1c(%rbx), %r15
leaq 0x62ca(%rip), %rax      # 0xe458
movq %r15, (%rax)
movl 0x24(%rbx), %eax
leaq 0x62c5(%rip), %rcx      # 0xe460
movl %eax, (%rcx)
leaq 0x1d590(%rbx), %r14
movups 0x1d578(%rbx), %xmm0
leaq 0x10(%rsp), %rsi
movaps %xmm0, (%rsi)
movq %r14, %rdi
movl $0x5, %edx
callq 0x4160
leaq 0x10(%rsp), %rdi
callq 0x3f18
movl $0x5, %edi
callq 0x3760
movl %eax, 0x24(%rbx)
cmpl $-0x1, %eax
je 0x82f7
movl 0x1d56c(%rbx), %edx
movl 0x1d574(%rbx), %r8d
movq %r14, %rdi
movl %eax, %esi
xorl %ecx, %ecx
callq 0x419e
movl 0x24(%rbx), %eax
leaq 0x623d(%rip), %rcx      # 0xe440
movl %eax, (%rcx)
movl $0x1, %edi
movl $0x1, %esi
xorl %edx, %edx
movq %r15, %rcx
callq 0x33a0
cmpl $-0x1, %eax
je 0x8316
movl 0x20(%rbx), %esi
movq %r14, %rdi
callq 0x416a
movl 0x1c(%rbx), %edx
movl 0x24(%rbx), %esi
movl 0x1d574(%rbx), %r8d
movq %r14, %rdi
xorl %ecx, %ecx
callq 0x419e
movl $0x1, %edx
movq %r14, %rdi
movl $0xd, %esi
movl $0x1, %ecx
callq 0x423e
leaq -0x4062(%rip), %rbx     # 0x4200
movq %r14, %rdi
movl $0xe, %esi
movq %rbx, %rdx
xorl %ecx, %ecx
callq 0x423e
movq %r14, %rdi
movl $0xf, %esi
movq %rbx, %rdx
xorl %ecx, %ecx
callq 0x423e
movl $0x5, %edi
callq 0x3770
addq $0x30, %rsp
popq %rbx
popq %r14
popq %r15
retq
leaq 0x226e(%rip), %rdi      # 0xa50f
leaq 0x2277(%rip), %rsi      # 0xa51f
leaq 0x227e(%rip), %rcx      # 0xa52d
movl $0x53, %edx
callq 0x32d0
leaq 0x228b(%rip), %rdi      # 0xa54b
leaq 0x2258(%rip), %rsi      # 0xa51f
leaq 0x225f(%rip), %rcx      # 0xa52d
movl $0x6d, %edx
callq 0x32d0
leaq 0x226c(%rip), %rdi      # 0xa54b
leaq 0x2239(%rip), %rsi      # 0xa51f
leaq 0x2240(%rip), %rcx      # 0xa52d
movl $0x6f, %edx
callq 0x32d0
leaq 0x2256(%rip), %rdi      # 0xa554
leaq 0x221a(%rip), %rsi      # 0xa51f
leaq 0x2221(%rip), %rcx      # 0xa52d
movl $0x7a, %edx
callq 0x32d0
leaq 0x2247(%rip), %rdi      # 0xa564
leaq 0x21fb(%rip), %rsi      # 0xa51f
leaq 0x2202(%rip), %rcx      # 0xa52d
movl $0x80, %edx
callq 0x32d0
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x3f18
movq %rbx, %rdi
callq 0x36e0