// File: /workspace/github_cpp_makefile_star2_O2/davidgfnet[P]tadns/tadns.cc
// Function: DNSResolver::getNSipaddr(unsigned int, unsigned int, std::vector<dns_record, std::allocator<dns_record>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, void*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, dns_record_type, void (*)(dns_cb_data*))
std::string
DNSResolver::getNSipaddr(unsigned level, unsigned niter, std::vector<struct dns_record> recs,
                         std::string dom, void *ctx, std::string name,
                         enum dns_record_type qtype, dns_callback_t callback) {

    // Filter all the NS records
    std::vector<std::string> nsrecs;
    std::unordered_map<std::string, std::string> arecs;
    for (const auto & e: recs) {
        if (e.name == dom && e.rtype == DNS_NS_RECORD)
            nsrecs.push_back(e.addr);
        if (e.rtype == DNS_A_RECORD)
            arecs[e.name] = e.addr;
    }

    // If we have no NS servers, it gets a bit more interesting.
    // According to rfc7816 (Qname minimization) we should need to go one level up
    // trying the same server
    if (!nsrecs.size())
        return "-";   // Hack, shame on me

    // Get a random permutation to avoid banging the same server
    std::random_shuffle(nsrecs.begin(), nsrecs.end());

    // Now go and check whether we have the A adress for them (in response)
    for (const auto & e: nsrecs)
        if (arecs.count(e))
            return arecs.at(e);

    // Seems like we don't have it in the packet, check the query cache
    std::vector<std::string> ipaddrs;
    int totry = -1;
    //for (const auto & e: nsrecs) {
    for (unsigned i = 0; i < nsrecs.size(); i++) {
        struct cache_entry *nsentry = find_cached_query(DNS_A_RECORD, nsrecs[i]);
        if (nsentry != NULL) {
            // Get any valid IP address (random)
            for (const auto & aent: nsentry->replies)
                if (aent.name == nsrecs[i] && aent.rtype == DNS_A_RECORD)
                    ipaddrs.push_back(aent.addr);
        }
        else
            totry = i;
    }
    // Pick a random one if any, a bit biased here
    if (ipaddrs.size())
        return ipaddrs[std::rand() % ipaddrs.size()];

    // Now, packet was useless, cache too, issue a request for ips
    // Prefetch all of them for better balancing and stuff
    #ifdef DO_DNS_PREFETCH
    if (level <= DO_DNS_PREFETCH) {
        for (const auto & e: nsrecs)
            this->queue(niter, e, NULL, DNS_A_RECORD, NULL);
    }
    #endif

    if (totry >= 0) {
        Query * oq = createQuery(niter, ctx, name, qtype, callback);
        this->queue(niter, nsrecs[totry], oq, DNS_A_RECORD, NULL);
        return "";
    }
    else {
        // None of the NS servers are really up for this!
        call_user(this, name, qtype, NULL, callback, ctx, DNS_DOES_NOT_EXIST);
    }
    return "";
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x138, %rsp            # imm = 0x138
movq %r9, %r15
movl %ecx, 0x1c(%rsp)
movl %edx, 0x18(%rsp)
movq %rsi, 0x10(%rsp)
movq %rdi, 0x8(%rsp)
xorps %xmm0, %xmm0
leaq 0x20(%rsp), %r12
movaps %xmm0, (%r12)
andq $0x0, 0x10(%r12)
leaq 0xf0(%rsp), %rax
movq %rax, -0x30(%rax)
movq $0x1, -0x28(%rax)
movups %xmm0, -0x20(%rax)
movl $0x3f800000, -0x10(%rax) # imm = 0x3F800000
movups %xmm0, -0x8(%rax)
movq (%r8), %r14
movq 0x8(%r8), %rbp
leaq 0xc0(%rsp), %r13
cmpq %rbp, %r14
je 0x52d8
leaq 0x8(%r14), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x618f
movl (%r14), %ecx
cmpl $0x2, %ecx
sete %dl
andb %al, %dl
cmpb $0x1, %dl
jne 0x52b6
leaq 0x28(%r14), %rsi
movq %r12, %rdi
callq 0x60ea
movl (%r14), %ecx
cmpl $0x1, %ecx
jne 0x52d2
movq %r13, %rdi
movq %rbx, %rsi
callq 0x7da6
leaq 0x28(%r14), %rsi
movq %rax, %rdi
callq 0x3180
addq $0x50, %r14
jmp 0x5283
movq 0x20(%rsp), %rdi
movq 0x28(%rsp), %rsi
cmpq %rdi, %rsi
je 0x531d
callq 0x61f3
movq 0x20(%rsp), %rbx
movq 0x28(%rsp), %r14
leaq 0xc0(%rsp), %r15
cmpq %r14, %rbx
je 0x533b
movq %r15, %rdi
movq %rbx, %rsi
callq 0x81d0
testq %rax, %rax
jne 0x5450
addq $0x20, %rbx
jmp 0x52fe
leaq 0x4e16(%rip), %rsi      # 0xa13a
leaq 0x40(%rsp), %rdx
movq 0x8(%rsp), %r14
movq %r14, %rdi
callq 0x61b8
jmp 0x55e5
xorps %xmm0, %xmm0
leaq 0x40(%rsp), %r13
movaps %xmm0, (%r13)
andq $0x0, 0x10(%r13)
pushq $-0x1
popq %rax
movl %eax, 0x4(%rsp)
xorl %r12d, %r12d
leaq 0xf8(%rsp), %r15
movl %r12d, %r14d
movq 0x20(%rsp), %rbx
movq 0x28(%rsp), %rbp
movq %rbp, %rax
subq %rbx, %rax
sarq $0x5, %rax
cmpq %r14, %rax
jbe 0x540e
shlq $0x5, %r14
addq %r14, %rbx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3360
movq 0x10(%rsp), %rdi
pushq $0x1
popq %rsi
movq %r15, %rdx
callq 0x42e6
movq %rax, %rbp
movq %r15, %rdi
callq 0x3140
movl %r12d, %eax
testq %rbp, %rbp
je 0x5402
movq (%rbp), %rbx
movq 0x8(%rbp), %r15
cmpq %r15, %rbx
je 0x53f6
leaq 0x8(%rbx), %rbp
movq 0x20(%rsp), %rsi
addq %r14, %rsi
movq %rbp, %rdi
callq 0x618f
testb %al, %al
je 0x53ed
cmpl $0x1, (%rbx)
jne 0x53ed
addq $0x28, %rbx
movq %r13, %rdi
movq %rbx, %rsi
callq 0x60ea
addq $0x48, %rbp
movq %rbp, %rbx
jmp 0x53bc
movl 0x4(%rsp), %eax
leaq 0xf8(%rsp), %r15
incl %r12d
movl %eax, 0x4(%rsp)
jmp 0x535f
movq 0x48(%rsp), %rax
cmpq 0x40(%rsp), %rax
je 0x5475
callq 0x30d0
cltq
movq 0x40(%rsp), %rsi
movq 0x48(%rsp), %rcx
subq %rsi, %rcx
sarq $0x5, %rcx
xorl %edx, %edx
divq %rcx
shlq $0x5, %rdx
addq %rdx, %rsi
movq 0x8(%rsp), %r14
movq %r14, %rdi
callq 0x3360
jmp 0x55db
leaq 0xc0(%rsp), %rdi
movq %rbx, %rsi
callq 0x8212
movq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rax, %rsi
callq 0x3360
jmp 0x55e5
cmpl $0x2, 0x18(%rsp)
movq 0x8(%rsp), %r14
movl 0x1c(%rsp), %r13d
ja 0x54c8
leaq 0x118(%rsp), %r15
pushq $0x1
popq %r12
cmpq %rbp, %rbx
je 0x54c8
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3360
movq 0x10(%rsp), %rdi
movl %r13d, %esi
movq %r15, %rdx
xorl %ecx, %ecx
movl %r12d, %r8d
xorl %r9d, %r9d
callq 0x569a
movq %r15, %rdi
callq 0x3140
addq $0x20, %rbx
jmp 0x5492
cmpl $0x0, 0x4(%rsp)
js 0x5581
leaq 0xa0(%rsp), %rdi
movq 0x178(%rsp), %rsi
callq 0x3360
leaq 0xa0(%rsp), %rcx
movq 0x10(%rsp), %rdi
movl %r13d, %esi
movq 0x170(%rsp), %rdx
movl 0x180(%rsp), %r8d
movq 0x188(%rsp), %r9
callq 0x58b6
movq %rax, %rbx
leaq 0xa0(%rsp), %rdi
callq 0x3140
movl 0x4(%rsp), %esi
shlq $0x5, %rsi
addq 0x20(%rsp), %rsi
leaq 0x80(%rsp), %rdi
callq 0x3360
leaq 0x80(%rsp), %rdx
pushq $0x1
popq %r8
movq 0x10(%rsp), %rdi
movl %r13d, %esi
movq %rbx, %rcx
xorl %r9d, %r9d
callq 0x569a
leaq 0x80(%rsp), %rdi
callq 0x3140
leaq 0x4ac6(%rip), %rsi      # 0xa038
leaq 0x3(%rsp), %rdx
movq %r14, %rdi
callq 0x61b8
jmp 0x55db
leaq 0x60(%rsp), %rdi
movq 0x178(%rsp), %rsi
callq 0x3360
movl 0x180(%rsp), %eax
movzwl %ax, %esi
leaq 0x60(%rsp), %rdi
pushq $0x1
popq %r9
xorl %edx, %edx
movq 0x188(%rsp), %rcx
movq 0x170(%rsp), %r8
callq 0x4970
leaq 0x60(%rsp), %rdi
callq 0x3140
leaq 0x4a6a(%rip), %rsi      # 0xa038
leaq 0x3(%rsp), %rdx
movq %r14, %rdi
callq 0x61b8
leaq 0x40(%rsp), %rdi
callq 0x616e
leaq 0xc0(%rsp), %rdi
callq 0x6c2a
leaq 0x20(%rsp), %rdi
callq 0x616e
movq %r14, %rax
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x566d
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
jmp 0x565d
jmp 0x566d
movq %rax, %rbx
leaq 0x80(%rsp), %rdi
jmp 0x565d
movq %rax, %rbx
leaq 0xa0(%rsp), %rdi
jmp 0x565d
jmp 0x566d
jmp 0x566d
jmp 0x5668
jmp 0x5668
jmp 0x5668
jmp 0x566d
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
jmp 0x565d
movq %rax, %rbx
leaq 0xf8(%rsp), %rdi
callq 0x3140
jmp 0x5670
jmp 0x566d
jmp 0x5668
movq %rax, %rbx
jmp 0x567a
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x616e
leaq 0xc0(%rsp), %rdi
callq 0x6c2a
leaq 0x20(%rsp), %rdi
callq 0x616e
movq %rbx, %rdi
callq 0x33f0
nop