// File: cybozu[P]yrmcds/cybozu/tcp.cpp
// Function: cybozu::tcp_socket::tcp_socket(int, unsigned int)
tcp_socket::tcp_socket(int fd, unsigned int bufcnt):
    resource(fd) {
    if( bufcnt > MAX_BUFCNT )
        throw std::logic_error("tcp_socket: Too many buffers");
    m_free_buffers.reserve(bufcnt);
    m_pending.reserve(bufcnt);

    int v = 1;
    if( setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &v, sizeof(v)) == -1 )
        throw_unix_error(errno, "setsockopt(SO_KEEPALIVE)");

    v = 1;
    if( setsockopt(fd, IPPROTO_TCP, TCP_CORK, &v, sizeof(v)) == -1 )
        throw_unix_error(errno, "setsockopt(TCP_CORK)");

    v = KEEPALIVE_IDLE;
    if( setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &v, sizeof(v)) == -1 )
        throw_unix_error(errno, "setsockopt(TCP_KEEPIDLE)");

    v = KEEPALIVE_INTERVAL;
    if( setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &v, sizeof(v)) == -1 )
        throw_unix_error(errno, "setsockopt(TCP_KEEPINTVL)");

    for( unsigned int i = 0; i < bufcnt; ++i ) {
        char* p = (char*)MALLOC(SENDBUF_SIZE);
        if( p == NULL ) {
            for( char* p2: m_free_buffers )
                FREE(p2);
            m_free_buffers.clear();
            throw std::runtime_error("tcp_socket: failed to allocate buffers");
        }
        // reserved, hence no throw
        m_free_buffers.push_back(p);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x60(%rbp)
movl -0xc(%rbp), %esi
callq 0x2ac50
movq -0x60(%rbp), %rdi
leaq 0x59058(%rip), %rax     # 0xae7a8
addq $0x10, %rax
movq %rax, (%rdi)
addq $0x58, %rdi
movq %rdi, -0x78(%rbp)
callq 0x57840
movq -0x60(%rbp), %rdi
addq $0x70, %rdi
movq %rdi, -0x70(%rbp)
callq 0x57860
movq -0x60(%rbp), %rdi
addq $0x88, %rdi
movq %rdi, -0x68(%rbp)
callq 0x33ca0
movq -0x60(%rbp), %rdi
movb $0x0, 0xa0(%rdi)
addq $0xa8, %rdi
callq 0xb6f0
movq -0x60(%rbp), %rdi
addq $0xd0, %rdi
movq %rdi, -0x58(%rbp)
callq 0x8960
cmpl $0x10000, -0x10(%rbp)   # imm = 0x10000
jbe 0x55826
movl $0x10, %edi
callq 0x82f0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x80(%rbp)
leaq 0x27293(%rip), %rsi     # 0x7ca6b
callq 0x89a0
jmp 0x557df
movq -0x80(%rbp), %rdi
movq 0x597d6(%rip), %rsi     # 0xaefc0
movq 0x5978f(%rip), %rdx     # 0xaef80
callq 0x8b70
jmp 0x55a93
movq -0x80(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x8490
jmp 0x55a5d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
jmp 0x55a5d
movq -0x60(%rbp), %rdi
addq $0x58, %rdi
movl -0x10(%rbp), %eax
movl %eax, %esi
callq 0x57880
jmp 0x5583a
movq -0x60(%rbp), %rdi
addq $0x70, %rdi
movl -0x10(%rbp), %eax
movl %eax, %esi
callq 0x57980
jmp 0x5584e
movl $0x1, -0x20(%rbp)
movl -0xc(%rbp), %edi
movl $0x1, %esi
movl $0x9, %edx
leaq -0x20(%rbp), %rcx
movl $0x4, %r8d
callq 0x8bf0
cmpl $-0x1, %eax
jne 0x5588b
callq 0x8050
movl (%rax), %edi
leaq 0x27204(%rip), %rsi     # 0x7ca88
callq 0xa320
jmp 0x5588b
movl $0x1, -0x20(%rbp)
movl -0xc(%rbp), %edi
movl $0x6, %esi
movl $0x3, %edx
leaq -0x20(%rbp), %rcx
movl $0x4, %r8d
callq 0x8bf0
cmpl $-0x1, %eax
jne 0x558c8
callq 0x8050
movl (%rax), %edi
leaq 0x271e0(%rip), %rsi     # 0x7caa1
callq 0xa320
jmp 0x558c8
movl $0x12c, -0x20(%rbp)     # imm = 0x12C
movl -0xc(%rbp), %edi
movl $0x6, %esi
movl $0x4, %r8d
leaq -0x20(%rbp), %rcx
movl %r8d, %edx
callq 0x8bf0
cmpl $-0x1, %eax
jne 0x55903
callq 0x8050
movl (%rax), %edi
leaq 0x271ba(%rip), %rsi     # 0x7cab6
callq 0xa320
jmp 0x55903
movl $0x5, -0x20(%rbp)
movl -0xc(%rbp), %edi
movl $0x6, %esi
movl $0x5, %edx
leaq -0x20(%rbp), %rcx
movl $0x4, %r8d
callq 0x8bf0
cmpl $-0x1, %eax
jne 0x55940
callq 0x8050
movl (%rax), %edi
leaq 0x27196(%rip), %rsi     # 0x7cacf
callq 0xa320
jmp 0x55940
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
cmpl -0x10(%rbp), %eax
jae 0x55a54
movl $0x100000, %edi         # imm = 0x100000
callq 0x88c0
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x55a31
movq -0x60(%rbp), %rax
addq $0x58, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0x57a80
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
callq 0x57ab0
movq %rax, -0x48(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x57ae0
testb $0x1, %al
jne 0x559a5
jmp 0x559c9
leaq -0x40(%rbp), %rdi
callq 0x57b20
movq (%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
callq 0x8760
leaq -0x40(%rbp), %rdi
callq 0x57b40
jmp 0x55992
movq -0x60(%rbp), %rdi
addq $0x58, %rdi
callq 0x57b60
movl $0x10, %edi
callq 0x82f0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x88(%rbp)
leaq 0x270f5(%rip), %rsi     # 0x7cae9
callq 0x8220
jmp 0x559fb
movq -0x88(%rbp), %rdi
movq 0x595e7(%rip), %rsi     # 0xaeff0
movq 0x59560(%rip), %rdx     # 0xaef70
callq 0x8b70
jmp 0x55a93
movq -0x88(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x8490
jmp 0x55a5d
movq -0x60(%rbp), %rdi
addq $0x58, %rdi
leaq -0x30(%rbp), %rsi
callq 0x57b80
jmp 0x55a44
jmp 0x55a46
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x55947
addq $0x90, %rsp
popq %rbp
retq
movq -0x58(%rbp), %rdi
callq 0x8c30
movq -0x68(%rbp), %rdi
callq 0x2ed10
movq -0x70(%rbp), %rdi
callq 0x331c0
movq -0x78(%rbp), %rdi
callq 0x33220
movq -0x60(%rbp), %rdi
callq 0x2afb0
movq -0x18(%rbp), %rdi
callq 0x8bc0
nopw %cs:(%rax,%rax)