// File: /workspace/github_cpp_makefile_star2_O2/zeeev[P]DASVC/bamtools/src/api/internal/io/TcpSocketEngine_unix_p.cpp
// Function: BamTools::Internal::TcpSocketEngine::nativeConnect(BamTools::Internal::HostAddress const&, unsigned short)
bool TcpSocketEngine::nativeConnect(const HostAddress& address, const uint16_t port) {

    // setup connection parameters from address/port
    sockaddr_in  sockAddrIPv4;
    sockaddr_in6 sockAddrIPv6;
    sockaddr*    sockAddrPtr  = 0;
    BT_SOCKLEN_T sockAddrSize = 0;

    // IPv6
    if ( address.GetProtocol() == HostAddress::IPv6Protocol ) {

        memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
        sockAddrIPv6.sin6_family = AF_INET6;
        sockAddrIPv6.sin6_port   = htons(port);

        IPv6Address ip6 = address.GetIPv6Address();
        memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));

        sockAddrSize = sizeof(sockAddrIPv6);
        sockAddrPtr  = (sockaddr*)&sockAddrIPv6;
    }

    // IPv4
    else if ( address.GetProtocol() == HostAddress::IPv4Protocol ) {

        memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
        sockAddrIPv4.sin_family      = AF_INET;
        sockAddrIPv4.sin_port        = htons(port);
        sockAddrIPv4.sin_addr.s_addr = htonl(address.GetIPv4Address());

        sockAddrSize = sizeof(sockAddrIPv4);
        sockAddrPtr  = (sockaddr*)&sockAddrIPv4;
    }

    // unknown (should be unreachable)
    else BT_ASSERT_X(false, "TcpSocketEngine::nativeConnect() : unknown network protocol");

    // attempt connection
    int connectResult = connect(m_socketDescriptor, sockAddrPtr, sockAddrSize);

    // if failed, handle error
    if ( connectResult == -1 ) {

        // ensure state is set before checking errno
        m_socketState = TcpSocket::UnconnectedState;

        // set error type/message depending on errno
        switch ( errno ) { // <-- potential thread issues later? but can't get error type from connectResult

            case EISCONN:
                m_socketState = TcpSocket::ConnectedState; // socket was already connected
                break;
            case ECONNREFUSED:
            case EINVAL:
                m_socketError = TcpSocket::ConnectionRefusedError;
                m_errorString = "connection refused";
                break;
            case ETIMEDOUT:
                m_socketError = TcpSocket::NetworkError;
                m_errorString = "connection timed out";
                break;
            case EHOSTUNREACH:
                m_socketError = TcpSocket::NetworkError;
                m_errorString = "host unreachable";
                break;
            case ENETUNREACH:
                m_socketError = TcpSocket::NetworkError;
                m_errorString = "network unreachable";
                break;
            case EADDRINUSE:
                m_socketError = TcpSocket::SocketResourceError;
                m_errorString = "address already in use";
                break;
            case EACCES:
            case EPERM:
                m_socketError = TcpSocket::SocketAccessError;
                m_errorString = "permission denied";
                break;
            default:
                break;
        }

        // double check that we're not in 'connected' state; if so, return failure
        if ( m_socketState != TcpSocket::ConnectedState )
            return false;
    }

    // otherwise, we should be good
    // update state & return success
    m_socketState = TcpSocket::ConnectedState;
    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x28, %rsp
movl %edx, %ebp
movq %rsi, %r15
movq %rdi, %rbx
movq %rsi, %rdi
callq 0x35070
cmpl $0x1, %eax
jne 0x572ac
xorps %xmm0, %xmm0
leaq 0xc(%rsp), %r14
movups %xmm0, 0x4(%r14)
andq $0x0, 0x14(%r14)
movw $0xa, (%r14)
rolw $0x8, %bp
movw %bp, 0x2(%r14)
movq %r15, %rdi
callq 0x34cb0
movq %rax, 0x8(%r14)
movq %rdx, 0x10(%r14)
pushq $0x1c
jmp 0x572e8
movq %r15, %rdi
callq 0x35070
testl %eax, %eax
je 0x572bf
xorl %edx, %edx
xorl %r14d, %r14d
jmp 0x572e9
leaq 0xc(%rsp), %r14
andq $0x0, 0x8(%r14)
movw $0x2, (%r14)
rolw $0x8, %bp
movw %bp, 0x2(%r14)
movq %r15, %rdi
callq 0x34c00
bswapl %eax
movl %eax, 0x4(%r14)
pushq $0x10
popq %rdx
movl (%rbx), %edi
movq %r14, %rsi
callq 0x32b80
cmpl $-0x1, %eax
je 0x5730c
movl $0x1, 0x50(%rbx)
movb $0x1, %al
addq $0x28, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
andl $0x0, 0x50(%rbx)
callq 0x31160
movl (%rax), %ecx
leaq 0x6012(%rip), %rsi      # 0x5d330
xorl %eax, %eax
leal -0x6a(%rcx), %edx
cmpl $0x7, %edx
jbe 0x5734a
cmpl $0x1, %ecx
je 0x57363
cmpl $0xd, %ecx
je 0x57363
cmpl $0x16, %ecx
je 0x57383
cmpl $0x62, %ecx
je 0x57379
cmpl $0x65, %ecx
jne 0x57301
leaq 0x6021(%rip), %rsi      # 0x5d369
jmp 0x57375
leaq 0x5fbf(%rip), %rcx      # 0x5d310
movslq (%rcx,%rdx,4), %rdx
addq %rcx, %rdx
jmpq *%rdx
leaq 0x5fe2(%rip), %rsi      # 0x5d343
jmp 0x57375
leaq 0x602a(%rip), %rsi      # 0x5d394
pushq $0x3
jmp 0x57382
leaq 0x5fe3(%rip), %rsi      # 0x5d358
pushq $0x6
jmp 0x57382
leaq 0x5ffd(%rip), %rsi      # 0x5d37d
pushq $0x4
popq %rax
movl %eax, 0x4c(%rbx)
leaq 0x58(%rbx), %rdi
callq 0x35550
cmpl $0x1, 0x50(%rbx)
je 0x572f8
xorl %eax, %eax
jmp 0x57301