// File: /workspace/github_cpp_makefile_star2_O3/zeeev[P]DASVC/bamtools/src/api/internal/io/HostInfo_p.cpp
// Function: BamTools::Internal::HostInfo::Lookup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
HostInfo HostInfo::Lookup(const string& hostname, const string& port) {

    HostInfo result;
    result.SetHostName(hostname);
    set<HostAddress> uniqueAddresses;

#ifdef _WIN32
    WindowsSockInit init;
#endif

    HostAddress address;
    address.SetAddress(hostname);

    // if hostname is an IP string ('0.0.0.0' or IPv6 format)
    // do reverse lookup for host domain name
    //
    // TODO: might just remove this... not sure if proper 'hostname' from IP string is needed
    //
    //       so far, haven't been able to successfully fetch a domain name with reverse DNS
    //       getnameinfo() on test sites just returns original IP string. BUT this is likely a rare
    //       case that client code tries to use an IP string and the connection should work fine
    //       anyway. GetHostName() just won't quite show what I was hoping for. :(
    if ( address.HasIPAddress() ) {

        const uint16_t portNum = static_cast<uint16_t>( atoi(port.c_str()) );

        sockaddr_in  sa4;
        sockaddr_in6 sa6;
        sockaddr* sa = 0;
        BT_SOCKLEN_T saSize = 0;

        // IPv4
        if ( address.GetProtocol() == HostAddress::IPv4Protocol ) {
            sa = (sockaddr*)&sa4;
            saSize = sizeof(sa4);
            memset(&sa4, 0, sizeof(sa4));
            sa4.sin_family = AF_INET;
            sa4.sin_addr.s_addr = htonl(address.GetIPv4Address());
            sa4.sin_port = htons(portNum);
        }

        // IPv6
        else if ( address.GetProtocol() == HostAddress::IPv4Protocol ){
            sa = (sockaddr*)&sa6;
            saSize = sizeof(sa6);
            memset(&sa6, 0, sizeof(sa6));
            sa6.sin6_family = AF_INET6;
            memcpy(sa6.sin6_addr.s6_addr, address.GetIPv6Address().data, sizeof(sa6.sin6_addr.s6_addr));
            sa6.sin6_port = htons(portNum);
        }

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

        // lookup name for IP
        char hbuf[NI_MAXHOST];
        char serv[NI_MAXSERV];
        if ( sa && (getnameinfo(sa, saSize, hbuf, sizeof(hbuf), serv, sizeof(serv), 0) == 0) )
            result.SetHostName(string(hbuf));

        // if no domain name found, just use the original address's IP string
        if ( result.HostName().empty() )
            result.SetHostName(address.GetIPString());

        // store address in HostInfo
        uniqueAddresses.insert(address);
    }

    // otherwise, hostname is a domain name ('www.foo.bar')
    // do 'normal' lookup
    else {

        // setup address lookup 'hints'
        addrinfo hints;
        memset(&hints, 0, sizeof(hints));
        hints.ai_family   = AF_UNSPEC;   // allow either IPv4 or IPv6
        hints.ai_socktype = SOCK_STREAM; // for TCP
        hints.ai_protocol = IPPROTO_TCP;

        // fetch addresses for requested hostname/port
        addrinfo* res;
        int status = getaddrinfo(hostname.c_str(), port.c_str(), &hints, &res );

        // if everything OK
        if ( status == 0 ) {

            // iterate over all IP addresses found
            addrinfo* p = res;
            for ( ; p != NULL; p = p->ai_next ) {

                // IPv4
                if ( p->ai_family == AF_INET ) {
                    sockaddr_in* ipv4 = (sockaddr_in*)p->ai_addr;
                    HostAddress a( ntohl(ipv4->sin_addr.s_addr) );
                    uniqueAddresses.insert(a);
                }

                // IPv6
                else if ( p->ai_family == AF_INET6 ) {
                    sockaddr_in6* ipv6 = (sockaddr_in6*)p->ai_addr;
                    HostAddress a(ipv6->sin6_addr.s6_addr);
                    uniqueAddresses.insert(a);
                }
            }

            // if we iterated, but no addresses were stored
            if ( uniqueAddresses.empty() && (p == NULL) ) {
                result.SetError(HostInfo::UnknownError);
                result.SetErrorString("HostInfo: unknown address types found");
            }
        }

        // handle error cases
        else if (
#ifndef _WIN32
                     status == EAI_NONAME
                  || status == EAI_FAIL
#  ifdef EAI_NODATA
                  || status == EAI_NODATA  // officially deprecated, but just in case we happen to hit it
#  endif // EAI_NODATA

#else  // _WIN32
                     WSAGetLastError() == WSAHOST_NOT_FOUND
                  || WSAGetLastError() == WSANO_DATA
                  || WSAGetLastError() == WSANO_RECOVERY
#endif // _WIN32
                )
        {
            result.SetError(HostInfo::HostNotFound);
            result.SetErrorString("HostInfo: host not found");
        }
        else {
            result.SetError(HostInfo::UnknownError);
            result.SetErrorString("HostInfo: unknown error encountered");
        }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x508, %rsp            # imm = 0x508
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
callq 0x26970
movq %rbx, %rdi
movq %r12, %rsi
callq 0x26b80
leaq 0x88(%rsp), %r14
movl $0x0, (%r14)
xorl %eax, %eax
movq %rax, 0x8(%r14)
movq %r14, 0x10(%r14)
movq %r14, 0x18(%r14)
movq %rax, 0x20(%r14)
leaq 0x40(%rsp), %rdi
callq 0x28880
leaq 0x40(%rsp), %rdi
movq %r12, %rsi
callq 0x289f0
leaq 0x40(%rsp), %rdi
callq 0x267b0
testb %al, %al
je 0x4b7eb
movq (%r15), %rdi
callq 0x28640
movl %eax, %ebp
leaq 0x40(%rsp), %rdi
callq 0x28d60
testl %eax, %eax
je 0x4b94e
leaq 0x40(%rsp), %rdi
callq 0x28d60
testl %eax, %eax
jne 0x4b9f7
xorps %xmm0, %xmm0
movaps %xmm0, 0xb0(%rsp)
movups %xmm0, 0xbc(%rsp)
movw $0xa, 0xb0(%rsp)
leaq 0x40(%rsp), %rdi
callq 0x28a40
leaq 0xb0(%rsp), %rdi
movq %rax, 0x8(%rdi)
movq %rdx, 0x10(%rdi)
movl $0x1c, %esi
jmp 0x4b976
xorps %xmm0, %xmm0
leaq 0xd0(%rsp), %rdx
movaps %xmm0, (%rdx)
movaps %xmm0, 0x20(%rdx)
movaps %xmm0, 0x10(%rdx)
movabsq $0x600000001, %rax      # imm = 0x600000001
movq %rax, 0x8(%rdx)
movq (%r12), %rdi
movq (%r15), %rsi
leaq 0x10(%rsp), %rcx
callq 0x27d50
leal 0x5(%rax), %ecx
cmpl $0x2, %ecx
jb 0x4b90a
cmpl $-0x2, %eax
je 0x4b90a
testl %eax, %eax
jne 0x4ba6c
movq 0x10(%rsp), %r13
testq %r13, %r13
je 0x4b8b7
leaq 0x100(%rsp), %r15
leaq 0x80(%rsp), %r12
movl 0x4(%r13), %eax
cmpl $0xa, %eax
je 0x4b88b
cmpl $0x2, %eax
jne 0x4b8ae
movq 0x18(%r13), %rax
movl 0x4(%rax), %esi
bswapl %esi
movq %r15, %rdi
callq 0x27190
movq %r12, %rdi
movq %r15, %rsi
callq 0x27a90
movq %r15, %rdi
callq 0x26640
jmp 0x4b8ae
movq 0x18(%r13), %rsi
addq $0x8, %rsi
movq %r15, %rdi
callq 0x26a60
movq %r12, %rdi
movq %r15, %rsi
callq 0x27a90
movq %r15, %rdi
callq 0x26640
movq 0x28(%r13), %r13
testq %r13, %r13
jne 0x4b857
cmpq $0x0, 0xa8(%rsp)
jne 0x4babd
movl $0x2, 0x38(%rbx)
leaq 0x110(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0xb64e(%rip), %rsi      # 0x56f2e
leaq 0xb66c(%rip), %rdx      # 0x56f53
leaq 0x100(%rsp), %rdi
callq 0x26750
leaq 0x40(%rbx), %rdi
leaq 0x100(%rsp), %rsi
callq 0x26b80
jmp 0x4baab
movl $0x1, 0x38(%rbx)
leaq 0x110(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0xb630(%rip), %rsi      # 0x56f54
leaq 0xb641(%rip), %rdx      # 0x56f6c
leaq 0x100(%rsp), %rdi
callq 0x26750
leaq 0x40(%rbx), %rdi
leaq 0x100(%rsp), %rsi
callq 0x26b80
jmp 0x4baab
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
movw $0x2, 0x30(%rsp)
leaq 0x40(%rsp), %rdi
callq 0x289b0
bswapl %eax
leaq 0x30(%rsp), %rdi
movl %eax, 0x4(%rdi)
movl $0x10, %esi
rolw $0x8, %bp
movw %bp, 0x2(%rdi)
movl $0x0, (%rsp)
leaq 0x100(%rsp), %rdx
leaq 0xd0(%rsp), %r8
movl $0x401, %ecx            # imm = 0x401
movl $0x20, %r9d
callq 0x26df0
testl %eax, %eax
jne 0x4b9f7
leaq 0x20(%rsp), %r12
movq %r12, -0x10(%r12)
leaq 0x100(%rsp), %r15
movq %r15, %rdi
callq 0x268a0
leaq (%rsp,%rax), %rdx
addq $0x100, %rdx            # imm = 0x100
leaq 0x10(%rsp), %rdi
movq %r15, %rsi
callq 0x26750
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x26b80
movq 0x10(%rsp), %rdi
cmpq %r12, %rdi
je 0x4b9f7
callq 0x27560
leaq 0x20(%rsp), %r15
movq %r15, -0x10(%r15)
movq (%rbx), %rsi
movq 0x8(%rbx), %rdx
addq %rsi, %rdx
leaq 0x10(%rsp), %rdi
callq 0x267c0
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %r12
cmpq %r15, %rdi
je 0x4ba28
callq 0x27560
testq %r12, %r12
jne 0x4ba58
leaq 0x10(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x28460
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x26b80
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x4ba58
callq 0x27560
leaq 0x80(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x27a90
jmp 0x4bac7
movl $0x2, 0x38(%rbx)
leaq 0x110(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0xb4e7(%rip), %rsi      # 0x56f6d
leaq 0xb503(%rip), %rdx      # 0x56f90
leaq 0x100(%rsp), %rdi
callq 0x26750
leaq 0x40(%rbx), %rdi
leaq 0x100(%rsp), %rsi
callq 0x26b80
movq 0x100(%rsp), %rdi
cmpq %r15, %rdi
je 0x4babd
callq 0x27560
movq 0x10(%rsp), %rdi
callq 0x27ea0
movq 0x98(%rsp), %rsi
leaq 0x100(%rsp), %rdi
leaq 0xd0(%rsp), %rcx
movq %r14, %rdx
callq 0x268b0
leaq 0x20(%rbx), %rdi
leaq 0x100(%rsp), %rsi
callq 0x261c0
leaq 0x100(%rsp), %rdi
callq 0x282f0
leaq 0x40(%rsp), %rdi
callq 0x26640
leaq 0x80(%rsp), %rdi
movq 0x10(%rdi), %rsi
callq 0x28010
movq %rbx, %rax
addq $0x508, %rsp            # imm = 0x508
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x4bb62
jmp 0x4bbcb
jmp 0x4bb62
jmp 0x4bbcb
movq %rax, %r14
movq 0x10(%rsp), %rdi
cmpq %r12, %rdi
jne 0x4bb72
jmp 0x4bbce
jmp 0x4bbcb
jmp 0x4bbcb
movq %rax, %r14
movq 0x10(%rsp), %rdi
jmp 0x4bb6d
jmp 0x4bbcb
movq %rax, %r14
movq 0x100(%rsp), %rdi
cmpq %r15, %rdi
je 0x4bbce
callq 0x27560
jmp 0x4bbce
jmp 0x4bbcb
jmp 0x4bbcb
jmp 0x4bbcb
movq %rax, %r14
leaq 0x100(%rsp), %rdi
callq 0x26640
jmp 0x4bbce
movq %rax, %r14
leaq 0x100(%rsp), %rdi
callq 0x26640
jmp 0x4bbce
jmp 0x4bbcb
jmp 0x4bbbb
movq %rax, %r14
leaq 0x100(%rsp), %rdi
callq 0x282f0
jmp 0x4bbce
jmp 0x4bbcb
movq %rax, %r14
jmp 0x4bbe9
jmp 0x4bbcb
jmp 0x4bbcb
jmp 0x4bbcb
movq %rax, %r14
jmp 0x4bbd8
movq %rax, %r14
leaq 0x40(%rsp), %rdi
callq 0x26640
leaq 0x80(%rsp), %rdi
movq 0x10(%rdi), %rsi
callq 0x28010
movq %rbx, %rdi
callq 0x28b00
movq %r14, %rdi
callq 0x28c10
movq %rax, %rdi
callq 0x2f047
nop