// File: 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:
subq $0x818, %rsp            # imm = 0x818
movq %rdi, 0xd8(%rsp)
movq %rdi, %rax
movq %rax, 0xd0(%rsp)
movq %rdi, 0x810(%rsp)
movq %rsi, 0x808(%rsp)
movq %rdx, 0x800(%rsp)
movb $0x0, 0x7ff(%rsp)
callq 0x73670
movq 0xd8(%rsp), %rdi
movq 0x808(%rsp), %rsi
callq 0x71b60
jmp 0xd4876
leaq 0x7b8(%rsp), %rdi
callq 0x71300
jmp 0xd4885
leaq 0x778(%rsp), %rdi
callq 0x7aae0
jmp 0xd4894
movq 0x808(%rsp), %rsi
leaq 0x778(%rsp), %rdi
callq 0x7afd0
jmp 0xd48ab
leaq 0x778(%rsp), %rdi
callq 0x72f60
movb %al, 0xcf(%rsp)
jmp 0xd48c1
movb 0xcf(%rsp), %al
testb $0x1, %al
jne 0xd48d1
jmp 0xd4d14
movq 0x800(%rsp), %rdi
callq 0x73020
movq %rax, 0xc0(%rsp)
jmp 0xd48e8
movq 0xc0(%rsp), %rdi
callq 0x7a180
movw %ax, 0x776(%rsp)
movq $0x0, 0x738(%rsp)
movl $0x0, 0x734(%rsp)
leaq 0x778(%rsp), %rdi
callq 0x7ba20
movl %eax, 0xbc(%rsp)
jmp 0xd492a
movl 0xbc(%rsp), %eax
cmpl $0x0, %eax
jne 0xd49f8
leaq 0x760(%rsp), %rax
movq %rax, 0x738(%rsp)
movl $0x10, 0x734(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x760(%rsp)
movw $0x2, 0x760(%rsp)
leaq 0x778(%rsp), %rdi
callq 0x7aef0
movl %eax, 0xb8(%rsp)
jmp 0xd4980
movl 0xb8(%rsp), %edi
callq 0x75020
movl %eax, 0x764(%rsp)
movzwl 0x776(%rsp), %edi
callq 0x71380
movw %ax, 0x762(%rsp)
jmp 0xd4ae6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
jmp 0xd5370
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
jmp 0xd5342
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
jmp 0xd5325
leaq 0x778(%rsp), %rdi
callq 0x7ba20
movl %eax, 0xb4(%rsp)
jmp 0xd4a0e
movl 0xb4(%rsp), %eax
cmpl $0x0, %eax
jne 0xd4adb
leaq 0x740(%rsp), %rax
movq %rax, 0x738(%rsp)
movl $0x1c, 0x734(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x74c(%rsp)
movaps %xmm0, 0x740(%rsp)
movw $0xa, 0x740(%rsp)
leaq 0x748(%rsp), %rax
movq %rax, 0x98(%rsp)
leaq 0x778(%rsp), %rdi
callq 0x7b060
movq %rdx, 0xa0(%rsp)
movq %rax, 0xa8(%rsp)
jmp 0xd4a85
movq 0x98(%rsp), %rax
movq 0xa0(%rsp), %rcx
movq 0xa8(%rsp), %rdx
movq %rdx, 0x724(%rsp)
movq %rcx, 0x72c(%rsp)
movq 0x724(%rsp), %rcx
movq %rcx, (%rax)
movq 0x72c(%rsp), %rcx
movq %rcx, 0x8(%rax)
movzwl 0x776(%rsp), %edi
callq 0x71380
movw %ax, 0x742(%rsp)
jmp 0xd4ae4
callq 0x761a0
jmp 0xd4ae2
jmp 0xd4ae4
jmp 0xd4ae6
cmpq $0x0, 0x738(%rsp)
je 0xd4bfc
movq 0x738(%rsp), %rdi
movl 0x734(%rsp), %esi
movq %rsp, %rax
movl $0x0, (%rax)
leaq 0x320(%rsp), %rdx
movl $0x401, %ecx            # imm = 0x401
leaq 0x300(%rsp), %r8
movl $0x20, %r9d
callq 0x745d0
movl %eax, 0x94(%rsp)
jmp 0xd4b36
movl 0x94(%rsp), %eax
cmpl $0x0, %eax
jne 0xd4bfc
leaq 0x2df(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x7b5f0
movq 0x88(%rsp), %rdx
leaq 0x2e0(%rsp), %rdi
leaq 0x320(%rsp), %rsi
callq 0x78e70
jmp 0xd4b7a
movq 0xd8(%rsp), %rdi
leaq 0x2e0(%rsp), %rsi
callq 0x71b60
jmp 0xd4b91
leaq 0x2e0(%rsp), %rdi
callq 0x7cce8
jmp 0xd4ba0
leaq 0x2df(%rsp), %rdi
callq 0x76f80
jmp 0xd4bfc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
jmp 0xd4bea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0x2e0(%rsp), %rdi
callq 0x7cce8
jmp 0xd4be8
jmp 0xd4bea
leaq 0x2df(%rsp), %rdi
callq 0x76f80
jmp 0xd5325
movq 0xd8(%rsp), %rsi
leaq 0x2b8(%rsp), %rdi
callq 0x715f0
jmp 0xd4c13
leaq 0x2b8(%rsp), %rdi
callq 0x7aba0
movb %al, 0x87(%rsp)
jmp 0xd4c29
leaq 0x2b8(%rsp), %rdi
callq 0x7cce8
jmp 0xd4c38
movb 0x87(%rsp), %al
testb $0x1, %al
jne 0xd4c48
jmp 0xd4cd7
leaq 0x298(%rsp), %rdi
leaq 0x778(%rsp), %rsi
callq 0x79c70
jmp 0xd4c5f
movq 0xd8(%rsp), %rdi
leaq 0x298(%rsp), %rsi
callq 0x71b60
jmp 0xd4c76
leaq 0x298(%rsp), %rdi
callq 0x7cce8
jmp 0xd4c85
jmp 0xd4cd7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0x2b8(%rsp), %rdi
callq 0x7cce8
jmp 0xd4caa
jmp 0xd5325
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0x298(%rsp), %rdi
callq 0x7cce8
jmp 0xd4cd2
jmp 0xd5325
leaq 0x7b8(%rsp), %rdi
leaq 0x778(%rsp), %rsi
callq 0x77b30
movb %dl, 0x77(%rsp)
movq %rax, 0x78(%rsp)
jmp 0xd4cf7
movb 0x77(%rsp), %al
movq 0x78(%rsp), %rcx
movq %rcx, 0x288(%rsp)
movb %al, 0x290(%rsp)
jmp 0xd520a
xorps %xmm0, %xmm0
movaps %xmm0, 0x270(%rsp)
movaps %xmm0, 0x260(%rsp)
movaps %xmm0, 0x250(%rsp)
movl $0x0, 0x254(%rsp)
movl $0x1, 0x258(%rsp)
movl $0x6, 0x25c(%rsp)
movq 0x808(%rsp), %rdi
callq 0x73020
movq %rax, 0x68(%rsp)
jmp 0xd4d64
movq 0x800(%rsp), %rdi
callq 0x73020
movq %rax, 0x60(%rsp)
jmp 0xd4d78
movq 0x60(%rsp), %rsi
movq 0x68(%rsp), %rdi
leaq 0x250(%rsp), %rdx
leaq 0x248(%rsp), %rcx
callq 0x78310
movl %eax, 0x5c(%rsp)
jmp 0xd4d9d
movl 0x5c(%rsp), %eax
movl %eax, 0x244(%rsp)
cmpl $0x0, 0x244(%rsp)
jne 0xd5054
movq 0x248(%rsp), %rax
movq %rax, 0x238(%rsp)
cmpq $0x0, 0x238(%rsp)
je 0xd4f5f
movq 0x238(%rsp), %rax
cmpl $0x2, 0x4(%rax)
jne 0xd4e90
movq 0x238(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x230(%rsp)
movq 0x230(%rsp), %rax
movl 0x4(%rax), %edi
callq 0x784a0
movl %eax, %esi
leaq 0x1f0(%rsp), %rdi
callq 0x75450
jmp 0xd4e1c
leaq 0x7b8(%rsp), %rdi
leaq 0x1f0(%rsp), %rsi
callq 0x77b30
movb %dl, 0x4f(%rsp)
movq %rax, 0x50(%rsp)
jmp 0xd4e3c
movb 0x4f(%rsp), %al
movq 0x50(%rsp), %rcx
movq %rcx, 0x1e0(%rsp)
movb %al, 0x1e8(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x72a20
jmp 0xd4e63
jmp 0xd4f44
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x72a20
jmp 0xd4e8b
jmp 0xd5325
movq 0x238(%rsp), %rax
cmpl $0xa, 0x4(%rax)
jne 0xd4f42
movq 0x238(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x1d8(%rsp)
movq 0x1d8(%rsp), %rsi
addq $0x8, %rsi
leaq 0x198(%rsp), %rdi
callq 0x73980
jmp 0xd4ed1
leaq 0x7b8(%rsp), %rdi
leaq 0x198(%rsp), %rsi
callq 0x77b30
movb %dl, 0x3f(%rsp)
movq %rax, 0x40(%rsp)
jmp 0xd4ef1
movb 0x3f(%rsp), %al
movq 0x40(%rsp), %rcx
movq %rcx, 0x188(%rsp)
movb %al, 0x190(%rsp)
leaq 0x198(%rsp), %rdi
callq 0x72a20
jmp 0xd4f18
jmp 0xd4f42
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0x198(%rsp), %rdi
callq 0x72a20
jmp 0xd4f3d
jmp 0xd5325
jmp 0xd4f44
jmp 0xd4f46
movq 0x238(%rsp), %rax
movq 0x28(%rax), %rax
movq %rax, 0x238(%rsp)
jmp 0xd4dc6
leaq 0x7b8(%rsp), %rdi
callq 0x75010
movb %al, 0x3e(%rsp)
jmp 0xd4f72
movb 0x3e(%rsp), %al
testb $0x1, %al
jne 0xd4f7f
jmp 0xd504f
cmpq $0x0, 0x238(%rsp)
jne 0xd504f
movq 0xd8(%rsp), %rdi
movl $0x2, %esi
callq 0x746e0
leaq 0x167(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x7b5f0
movq 0x30(%rsp), %rdx
leaq 0x17200(%rip), %rsi     # 0xec1be
leaq 0x168(%rsp), %rdi
callq 0x78e70
jmp 0xd4fcd
movq 0xd8(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0x78690
jmp 0xd4fe4
leaq 0x168(%rsp), %rdi
callq 0x7cce8
jmp 0xd4ff3
leaq 0x167(%rsp), %rdi
callq 0x76f80
jmp 0xd504f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
jmp 0xd503d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0x168(%rsp), %rdi
callq 0x7cce8
jmp 0xd503b
jmp 0xd503d
leaq 0x167(%rsp), %rdi
callq 0x76f80
jmp 0xd5325
jmp 0xd51fd
cmpl $-0x2, 0x244(%rsp)
je 0xd5076
cmpl $-0x4, 0x244(%rsp)
je 0xd5076
cmpl $-0x5, 0x244(%rsp)
jne 0xd513a
movq 0xd8(%rsp), %rdi
movl $0x1, %esi
callq 0x746e0
leaq 0x13f(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x7b5f0
movq 0x28(%rsp), %rdx
leaq 0x1713e(%rip), %rsi     # 0xec1e4
leaq 0x140(%rsp), %rdi
callq 0x78e70
jmp 0xd50b5
movq 0xd8(%rsp), %rdi
leaq 0x140(%rsp), %rsi
callq 0x78690
jmp 0xd50cc
leaq 0x140(%rsp), %rdi
callq 0x7cce8
jmp 0xd50db
leaq 0x13f(%rsp), %rdi
callq 0x76f80
jmp 0xd51fb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
jmp 0xd5128
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0x140(%rsp), %rdi
callq 0x7cce8
jmp 0xd5126
jmp 0xd5128
leaq 0x13f(%rsp), %rdi
callq 0x76f80
jmp 0xd5325
movq 0xd8(%rsp), %rdi
movl $0x2, %esi
callq 0x746e0
leaq 0x117(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x7b5f0
movq 0x20(%rsp), %rdx
leaq 0x17093(%rip), %rsi     # 0xec1fd
leaq 0x118(%rsp), %rdi
callq 0x78e70
jmp 0xd5179
movq 0xd8(%rsp), %rdi
leaq 0x118(%rsp), %rsi
callq 0x78690
jmp 0xd5190
leaq 0x118(%rsp), %rdi
callq 0x7cce8
jmp 0xd519f
leaq 0x117(%rsp), %rdi
callq 0x76f80
jmp 0xd51fb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
jmp 0xd51e9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0x118(%rsp), %rdi
callq 0x7cce8
jmp 0xd51e7
jmp 0xd51e9
leaq 0x117(%rsp), %rdi
callq 0x76f80
jmp 0xd5325
jmp 0xd51fd
movq 0x248(%rsp), %rdi
callq 0x78720
leaq 0x7b8(%rsp), %rdi
callq 0x7a840
movq %rax, 0x18(%rsp)
jmp 0xd521e
movq 0x18(%rsp), %rax
movq %rax, 0xf0(%rsp)
leaq 0x7b8(%rsp), %rdi
callq 0x78b90
movq %rax, 0x10(%rsp)
jmp 0xd523f
movq 0x10(%rsp), %rax
movq %rax, 0xe8(%rsp)
leaq 0xe7(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x7c6c0
movq 0x8(%rsp), %rcx
movq 0xf0(%rsp), %rsi
movq 0xe8(%rsp), %rdx
leaq 0xf8(%rsp), %rdi
callq 0x733b0
jmp 0xd5282
movq 0xd8(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x7ca00
jmp 0xd5299
leaq 0xf8(%rsp), %rdi
callq 0x797f0
jmp 0xd52a8
leaq 0xe7(%rsp), %rdi
callq 0x77470
movb $0x1, 0x7ff(%rsp)
leaq 0x778(%rsp), %rdi
callq 0x72a20
jmp 0xd5316
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
jmp 0xd5307
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x7f0(%rsp)
movl %eax, 0x7ec(%rsp)
leaq 0xf8(%rsp), %rdi
callq 0x797f0
jmp 0xd5305
jmp 0xd5307
leaq 0xe7(%rsp), %rdi
callq 0x77470
jmp 0xd5325
leaq 0x7b8(%rsp), %rdi
callq 0x7a9e0
jmp 0xd5336
leaq 0x778(%rsp), %rdi
callq 0x72a20
jmp 0xd5334
jmp 0xd5342
testb $0x1, 0x7ff(%rsp)
jne 0xd5360
jmp 0xd5353
leaq 0x7b8(%rsp), %rdi
callq 0x7a9e0
jmp 0xd5351
jmp 0xd5370
movq 0xd8(%rsp), %rdi
callq 0x7b1e0
movq 0xd0(%rsp), %rax
addq $0x818, %rsp            # imm = 0x818
retq
movq 0xd8(%rsp), %rdi
callq 0x7b1e0
jmp 0xd537f
jmp 0xd5381
movq 0x7f0(%rsp), %rdi
callq 0x7b550
movq %rax, %rdi
callq 0x88ef0
nopw %cs:(%rax,%rax)