// File: shaovie[P]reactor/src/acceptor.cpp
// Function: acceptor::tcp_open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, options const&)
int acceptor::tcp_open(const std::string &addr, const options &opt) {
    auto p = addr.find(":");
    if (p == addr.npos || (p > 0 && p < 7)) {
        fprintf(stderr, "reactor: accepor open fail! addr invalid\n");
        return -1;
    }
    std::string ip = addr.substr(0, p);
    int port = 0;
    try {
        port = std::stoi(addr.substr(p+1, addr.length() - p - 1)); // throw
    } catch(...) {
        fprintf(stderr, "reactor: accepor open fail! addr invalid\n");
        return -1;
    }
    if (port < 1 || port > 65535) {
        fprintf(stderr, "reactor: accepor open fail! port invalid\n");
        return -1;
    }

    int fd = ::socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
    if (fd == -1) {
        fprintf(stderr, "reactor: create listen socket fail! %s\n", strerror(errno));
        return -1;
    }
    // `sysctl -a | grep net.ipv4.tcp_rmem` 返回 min default max
    // 默认内核会在min,max之间动态调整, default是初始值, 如果设置了SO_RCVBUF, 
    // 缓冲区大小不变成固定值, 内核也不会进行动态调整了.
    //
    // 必须在listen/connect之前调用
    // must < `sysctl -a | grep net.core.rmem_max`
    if (opt.rcvbuf_size > 0 && socket::set_rcvbuf(fd, opt.rcvbuf_size) != 0) {
        socket::close(fd);
        fprintf(stderr, "reactor: set rcvbuf fail! %s\n", strerror(errno));
        return -1;
    }
    if (opt.reuse_addr && socket::reuseaddr(fd, 1) != 0) {
        socket::close(fd);
        fprintf(stderr, "reactor: set reuseaddr fail! %s\n", strerror(errno));
        return -1;
    }
    if (opt.reuse_port && socket::reuseport(fd, 1) != 0) {
        socket::close(fd);
        fprintf(stderr, "reactor: set reuseport fail! %s\n", strerror(errno));
        return -1;
    }
    struct sockaddr_in laddr;
    ::memset(reinterpret_cast<void *>(&laddr), 0, sizeof(laddr));
    inet_address iaddr(port, ip.c_str());
    laddr = *reinterpret_cast<sockaddr_in *>(iaddr.get_addr());
    return this->listen(fd,
        reinterpret_cast<sockaddr *>(&laddr), sizeof(laddr),
        opt.backlog);
}

// Assembly:
subq $0x118, %rsp            # imm = 0x118
movq %rdi, 0x108(%rsp)
movq %rsi, 0x100(%rsp)
movq %rdx, 0xf8(%rsp)
movq 0x108(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x100(%rsp), %rdi
leaq 0x52b5(%rip), %rsi      # 0x23210
xorl %eax, %eax
movl %eax, %edx
callq 0x16090
movq %rax, 0xf0(%rsp)
cmpq $-0x1, 0xf0(%rsp)
je 0x1df8d
cmpq $0x0, 0xf0(%rsp)
jbe 0x1dfb5
cmpq $0x7, 0xf0(%rsp)
jae 0x1dfb5
movq 0xc03c(%rip), %rax      # 0x29fd0
movq (%rax), %rdi
leaq 0x5274(%rip), %rsi      # 0x23212
movb $0x0, %al
callq 0x15860
movl $0xffffffff, 0x114(%rsp) # imm = 0xFFFFFFFF
jmp 0x1e40d
movq 0x100(%rsp), %rsi
movq 0xf0(%rsp), %rcx
xorl %eax, %eax
movl %eax, %edx
leaq 0xd0(%rsp), %rdi
callq 0x151d0
movl $0x0, 0xcc(%rsp)
movq 0x100(%rsp), %rdi
movq %rdi, 0x58(%rsp)
movq 0xf0(%rsp), %rax
incq %rax
movq %rax, 0x60(%rsp)
callq 0x15960
movq 0x58(%rsp), %rsi
movq 0x60(%rsp), %rdx
movq 0xf0(%rsp), %rcx
notq %rcx
addq %rax, %rcx
leaq 0xa8(%rsp), %rdi
callq 0x151d0
jmp 0x1e02a
xorl %eax, %eax
movl %eax, %esi
leaq 0xa8(%rsp), %rdi
movl $0xa, %edx
callq 0x15fb0
movl %eax, 0x54(%rsp)
jmp 0x1e046
movl 0x54(%rsp), %eax
movl %eax, 0xcc(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0x14ab0
jmp 0x1e107
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa0(%rsp)
movl %eax, 0x9c(%rsp)
jmp 0x1e09a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa0(%rsp)
movl %eax, 0x9c(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0x14ab0
movq 0xa0(%rsp), %rdi
callq 0x14610
movq 0xbf22(%rip), %rax      # 0x29fd0
movq (%rax), %rdi
leaq 0x515a(%rip), %rsi      # 0x23212
xorl %eax, %eax
callq 0x15860
movl $0xffffffff, 0x114(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x98(%rsp)
callq 0x15b20
jmp 0x1e0dc
jmp 0x1e400
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa0(%rsp)
movl %eax, 0x9c(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x14ab0
jmp 0x1e41c
cmpl $0x1, 0xcc(%rsp)
jl 0x1e11e
cmpl $0xffff, 0xcc(%rsp) # imm = 0xFFFF
jle 0x1e151
movq 0xbeab(%rip), %rax      # 0x29fd0
movq (%rax), %rdi
leaq 0x510d(%rip), %rsi      # 0x2323c
movb $0x0, %al
callq 0x15860
movl $0xffffffff, 0x114(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x98(%rsp)
jmp 0x1e400
movl $0x2, %edi
movl $0x80801, %esi          # imm = 0x80801
xorl %edx, %edx
callq 0x14340
movl %eax, 0x94(%rsp)
cmpl $-0x1, 0x94(%rsp)
jne 0x1e1bf
movq 0xbe56(%rip), %rax      # 0x29fd0
movq (%rax), %rax
movq %rax, 0x48(%rsp)
callq 0x140c0
movl (%rax), %edi
callq 0x144d0
movq 0x48(%rsp), %rdi
movq %rax, %rdx
leaq 0x50c9(%rip), %rsi      # 0x23266
movb $0x0, %al
callq 0x15860
movl $0xffffffff, 0x114(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x98(%rsp)
jmp 0x1e400
movq 0xf8(%rsp), %rax
cmpl $0x0, 0x1c(%rax)
jle 0x1e252
movl 0x94(%rsp), %edi
movq 0xf8(%rsp), %rax
movslq 0x1c(%rax), %rsi
callq 0x15670
movl %eax, 0x44(%rsp)
jmp 0x1e1ef
movl 0x44(%rsp), %eax
cmpl $0x0, %eax
je 0x1e252
movl 0x94(%rsp), %edi
callq 0x155b0
jmp 0x1e206
movq 0xbdc3(%rip), %rax      # 0x29fd0
movq (%rax), %rax
movq %rax, 0x38(%rsp)
callq 0x140c0
movl (%rax), %edi
callq 0x144d0
movq 0x38(%rsp), %rdi
movq %rax, %rdx
leaq 0x505e(%rip), %rsi      # 0x2328e
movb $0x0, %al
callq 0x15860
movl $0xffffffff, 0x114(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x98(%rsp)
jmp 0x1e400
movq 0xf8(%rsp), %rax
testb $0x1, 0x18(%rax)
je 0x1e2da
movl 0x94(%rsp), %edi
movl $0x1, %esi
callq 0x14950
movl %eax, 0x34(%rsp)
jmp 0x1e277
movl 0x34(%rsp), %eax
cmpl $0x0, %eax
je 0x1e2da
movl 0x94(%rsp), %edi
callq 0x155b0
jmp 0x1e28e
movq 0xbd3b(%rip), %rax      # 0x29fd0
movq (%rax), %rax
movq %rax, 0x28(%rsp)
callq 0x140c0
movl (%rax), %edi
callq 0x144d0
movq 0x28(%rsp), %rdi
movq %rax, %rdx
leaq 0x4ff4(%rip), %rsi      # 0x232ac
movb $0x0, %al
callq 0x15860
movl $0xffffffff, 0x114(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x98(%rsp)
jmp 0x1e400
movq 0xf8(%rsp), %rax
testb $0x1, 0x19(%rax)
je 0x1e362
movl 0x94(%rsp), %edi
movl $0x1, %esi
callq 0x15630
movl %eax, 0x24(%rsp)
jmp 0x1e2ff
movl 0x24(%rsp), %eax
cmpl $0x0, %eax
je 0x1e362
movl 0x94(%rsp), %edi
callq 0x155b0
jmp 0x1e316
movq 0xbcb3(%rip), %rax      # 0x29fd0
movq (%rax), %rax
movq %rax, 0x18(%rsp)
callq 0x140c0
movl (%rax), %edi
callq 0x144d0
movq 0x18(%rsp), %rdi
movq %rax, %rdx
leaq 0x4f8d(%rip), %rsi      # 0x232cd
movb $0x0, %al
callq 0x15860
movl $0xffffffff, 0x114(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x98(%rsp)
jmp 0x1e400
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movzwl 0xcc(%rsp), %eax
movl %eax, 0x14(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x14630
movl 0x14(%rsp), %esi
movq %rax, %rdx
leaq 0x70(%rsp), %rdi
callq 0x15370
jmp 0x1e399
leaq 0x70(%rsp), %rdi
callq 0x15580
movq %rax, 0x8(%rsp)
jmp 0x1e3aa
movq 0x68(%rsp), %rdi
movq 0x8(%rsp), %rax
movups (%rax), %xmm0
movaps %xmm0, 0x80(%rsp)
movl 0x94(%rsp), %esi
movq 0xf8(%rsp), %rax
movl 0x20(%rax), %r8d
leaq 0x80(%rsp), %rdx
movl $0x10, %ecx
callq 0x15f90
movl %eax, 0x4(%rsp)
jmp 0x1e3ea
movl 0x4(%rsp), %eax
movl %eax, 0x114(%rsp)
movl $0x1, 0x98(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x14ab0
movl 0x114(%rsp), %eax
addq $0x118, %rsp            # imm = 0x118
retq
movq 0xa0(%rsp), %rdi
callq 0x15ce0
nopl (%rax)