// File: davidgfnet[P]tadns/tadns.cc
// Function: DNSResolver::resolveInt(unsigned int, void*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, dns_record_type, void (*)(dns_cb_data*))
void DNSResolver::resolveInt(unsigned niter, void *ctx, std::string name,
                          enum dns_record_type qtype, dns_callback_t callback) {

    std::transform(name.begin(), name.end(), name.begin(), ::tolower);

    if (niter >= DNS_QUERY_MAXITER) {
        call_user(this, name, qtype, NULL, callback, ctx, DNS_TIMEOUT);
        return;
    }

    /* Check cache right away */
    struct cache_entry *dentry = find_cached_query(qtype, name);
    if (dentry) {
        call_user(this, name, qtype, dentry, callback, ctx, DNS_OK);
        return;
    }

    /* Do recursive solving */
    unsigned level = 0;
    union {
        struct sockaddr_storage addrst;
        struct sockaddr_in6 ipv6addr;
        struct sockaddr_in ipv4addr;
    } addrunion;
    struct sockaddr * dnss = NULL;

    while (1) {
        std::string part; bool lastq;
        std::tie(part, lastq) = tokenizedom(name, level);
        enum dns_record_type iqtype = lastq ? qtype : DNS_NS_RECORD;

        /* Search the cache first */
        struct cache_entry *centry = find_cached_query(iqtype, part);
        if (centry != NULL) {
            if (lastq) {
                assert(iqtype == qtype);
                // This is the original request, all set, shoot!
                call_user(this, name, qtype, centry, callback, ctx, DNS_OK);
                return;
            }

            // We get here cause the current "part" has some NS responses
            // Sometimes the NS responses come with the A/AAAA records (optimization!)
            // Also we don't want to always use the same NS server, so round robin it
            std::string ipaddr = getNSipaddr(level, niter, centry->replies, part, ctx, name, qtype, callback);

            if (!ipaddr.size())
                return;

            if (ipaddr.size() == 4) {
                addrunion.ipv4addr.sin_family = AF_INET;
                addrunion.ipv4addr.sin_port = htons(53);
                memcpy(&addrunion.ipv4addr.sin_addr, ipaddr.c_str(), 4); // FIXME: Check addr sizes

                dnss = (struct sockaddr*)&addrunion;
            }
        } else {
            // We don't have the NS for that record, ask for it (cache miss)
            Query * oq = createQuery(niter, ctx, name, qtype, callback);
            this->queue(niter, part, oq, iqtype, dnss);
            return; // Will come back here eventually :D
        }

        level++;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x390, %rsp            # imm = 0x390
movq %rcx, -0x308(%rbp)
movq %rdi, %rax
movq -0x308(%rbp), %rdi
movq %rdi, -0x2f8(%rbp)
movq %rax, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movq %rdi, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movq %r9, -0x30(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x300(%rbp)
callq 0x32f0
movq -0x2f8(%rbp), %rdi
movq %rax, -0x38(%rbp)
callq 0x31d0
movq -0x2f8(%rbp), %rdi
movq %rax, -0x40(%rbp)
callq 0x32f0
movq %rax, -0x48(%rbp)
movq -0x38(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
movq 0x1ecf7(%rip), %rcx     # 0x25fd8
callq 0xadb0
movq %rax, -0x50(%rbp)
cmpl $0x10, -0xc(%rbp)
jb 0x735d
movq -0x2f8(%rbp), %rsi
leaq -0x70(%rbp), %rdi
movq %rdi, -0x310(%rbp)
callq 0x3160
movq -0x300(%rbp), %rdi
movq -0x310(%rbp), %rsi
movzwl -0x24(%rbp), %edx
movq -0x30(%rbp), %r8
movq -0x18(%rbp), %r9
movq %rsp, %rax
movl $0x2, (%rax)
xorl %eax, %eax
movl %eax, %ecx
callq 0x7190
jmp 0x7335
leaq -0x70(%rbp), %rdi
callq 0x3200
jmp 0x79a9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x3200
jmp 0x79b2
movq -0x2f8(%rbp), %rsi
movl -0x24(%rbp), %eax
movl %eax, -0x324(%rbp)
leaq -0xa8(%rbp), %rdi
movq %rdi, -0x320(%rbp)
callq 0x3160
movq -0x300(%rbp), %rdi
movl -0x324(%rbp), %esi
movq -0x320(%rbp), %rdx
callq 0x62a0
movq %rax, -0x318(%rbp)
jmp 0x73a2
leaq -0xa8(%rbp), %rdi
callq 0x3200
movq -0x318(%rbp), %rax
movq %rax, -0x88(%rbp)
cmpq $0x0, -0x88(%rbp)
je 0x7460
movq -0x2f8(%rbp), %rsi
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x330(%rbp)
callq 0x3160
movq -0x300(%rbp), %rdi
movq -0x330(%rbp), %rsi
movzwl -0x24(%rbp), %edx
movq -0x88(%rbp), %rcx
movq -0x30(%rbp), %r8
movq -0x18(%rbp), %r9
movq %rsp, %rax
movl $0x0, (%rax)
callq 0x7190
jmp 0x7415
leaq -0xc8(%rbp), %rdi
callq 0x3200
jmp 0x79a9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x3200
jmp 0x79b2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x3200
jmp 0x79b2
movl $0x0, -0xcc(%rbp)
movq $0x0, -0x158(%rbp)
leaq -0x178(%rbp), %rdi
callq 0x34a0
movq -0x2f8(%rbp), %rsi
leaq -0x1c8(%rbp), %rdi
callq 0x3160
jmp 0x7496
movl -0xcc(%rbp), %edx
leaq -0x1a8(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
callq 0x7d10
jmp 0x74b1
leaq -0x1d8(%rbp), %rdi
leaq -0x178(%rbp), %rsi
leaq -0x179(%rbp), %rdx
callq 0xae30
leaq -0x1d8(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0xae70
leaq -0x1a8(%rbp), %rdi
callq 0xaee0
leaq -0x1c8(%rbp), %rdi
callq 0x3200
testb $0x1, -0x179(%rbp)
je 0x750a
movl -0x24(%rbp), %eax
movl %eax, -0x334(%rbp)
jmp 0x7517
movl $0x2, %eax
movl %eax, -0x334(%rbp)
jmp 0x7517
movl -0x334(%rbp), %eax
movl %eax, -0x1dc(%rbp)
movl -0x1dc(%rbp), %eax
movl %eax, -0x338(%rbp)
leaq -0x208(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x3160
jmp 0x7544
movl -0x338(%rbp), %esi
movq -0x300(%rbp), %rdi
leaq -0x208(%rbp), %rdx
callq 0x62a0
movq %rax, -0x340(%rbp)
jmp 0x7566
leaq -0x208(%rbp), %rdi
callq 0x3200
movq -0x340(%rbp), %rax
movq %rax, -0x1e8(%rbp)
cmpq $0x0, -0x1e8(%rbp)
je 0x7855
testb $0x1, -0x179(%rbp)
je 0x7690
movl -0x1dc(%rbp), %eax
cmpl -0x24(%rbp), %eax
jne 0x75a8
jmp 0x7612
leaq 0x11b8d(%rip), %rdi     # 0x1913c
leaq 0x11af2(%rip), %rsi     # 0x190a8
movl $0x257, %edx            # imm = 0x257
leaq 0x11b8a(%rip), %rcx     # 0x1914c
callq 0x3210
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0x799b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x1c8(%rbp), %rdi
callq 0x3200
jmp 0x799b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x208(%rbp), %rdi
callq 0x3200
jmp 0x799b
movq -0x2f8(%rbp), %rsi
leaq -0x228(%rbp), %rdi
callq 0x3160
jmp 0x7627
movq -0x300(%rbp), %rdi
movzwl -0x24(%rbp), %edx
movq -0x1e8(%rbp), %rcx
movq -0x30(%rbp), %r8
movq -0x18(%rbp), %r9
movq %rsp, %rax
movl $0x0, (%rax)
leaq -0x228(%rbp), %rsi
callq 0x7190
jmp 0x7658
leaq -0x228(%rbp), %rdi
callq 0x3200
movl $0x1, -0x22c(%rbp)
jmp 0x797c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x228(%rbp), %rdi
callq 0x3200
jmp 0x799b
movl -0xcc(%rbp), %eax
movl %eax, -0x348(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x344(%rbp)
movq -0x1e8(%rbp), %rsi
leaq -0x268(%rbp), %rdi
callq 0xaf00
jmp 0x76ba
leaq -0x288(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x3160
jmp 0x76cf
movq -0x2f8(%rbp), %rsi
movq -0x18(%rbp), %rax
movq %rax, -0x350(%rbp)
leaq -0x2a8(%rbp), %rdi
callq 0x3160
jmp 0x76ef
movl -0x344(%rbp), %ecx
movl -0x348(%rbp), %edx
movq -0x300(%rbp), %rsi
movq -0x350(%rbp), %rdi
movl -0x24(%rbp), %r8d
movq -0x30(%rbp), %r9
movq %rsp, %rax
movq %r9, 0x18(%rax)
movl %r8d, 0x10(%rax)
leaq -0x2a8(%rbp), %r8
movq %r8, 0x8(%rax)
movq %rdi, (%rax)
leaq -0x250(%rbp), %rdi
leaq -0x268(%rbp), %r8
leaq -0x288(%rbp), %r9
callq 0x7fd0
jmp 0x7746
leaq -0x2a8(%rbp), %rdi
callq 0x3200
leaq -0x288(%rbp), %rdi
callq 0x3200
leaq -0x268(%rbp), %rdi
callq 0x4320
leaq -0x250(%rbp), %rdi
callq 0x3240
cmpq $0x0, %rax
jne 0x77dc
movl $0x1, -0x22c(%rbp)
jmp 0x7834
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0x77cb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
jmp 0x77bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x2a8(%rbp), %rdi
callq 0x3200
leaq -0x288(%rbp), %rdi
callq 0x3200
leaq -0x268(%rbp), %rdi
callq 0x4320
jmp 0x799b
leaq -0x250(%rbp), %rdi
callq 0x3240
cmpq $0x4, %rax
jne 0x782a
movw $0x2, -0x150(%rbp)
movl $0x35, %edi
callq 0x3070
movw %ax, -0x14e(%rbp)
leaq -0x250(%rbp), %rdi
callq 0x3150
movl (%rax), %eax
movl %eax, -0x14c(%rbp)
leaq -0x150(%rbp), %rax
movq %rax, -0x158(%rbp)
movl $0x0, -0x22c(%rbp)
leaq -0x250(%rbp), %rdi
callq 0x3200
movl -0x22c(%rbp), %eax
testl %eax, %eax
jne 0x797c
jmp 0x7850
jmp 0x7963
movq -0x2f8(%rbp), %rsi
movl -0xc(%rbp), %eax
movl %eax, -0x35c(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x358(%rbp)
leaq -0x2d0(%rbp), %rdi
callq 0x3160
jmp 0x787e
movq -0x358(%rbp), %rdx
movl -0x35c(%rbp), %esi
movq -0x300(%rbp), %rdi
movl -0x24(%rbp), %r8d
movq -0x30(%rbp), %r9
leaq -0x2d0(%rbp), %rcx
callq 0x8d20
movq %rax, -0x368(%rbp)
jmp 0x78af
leaq -0x2d0(%rbp), %rdi
callq 0x3200
movq -0x368(%rbp), %rax
movq %rax, -0x2b0(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x36c(%rbp)
leaq -0x2f0(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x3160
jmp 0x78e7
movl -0x36c(%rbp), %esi
movq -0x300(%rbp), %rdi
movq -0x2b0(%rbp), %rcx
movl -0x1dc(%rbp), %r8d
movq -0x158(%rbp), %r9
leaq -0x2f0(%rbp), %rdx
callq 0x8900
jmp 0x7917
leaq -0x2f0(%rbp), %rdi
callq 0x3200
movl $0x1, -0x22c(%rbp)
jmp 0x797c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x2d0(%rbp), %rdi
callq 0x3200
jmp 0x799b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x2f0(%rbp), %rdi
callq 0x3200
jmp 0x799b
movl -0xcc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xcc(%rbp)
movl $0x0, -0x22c(%rbp)
leaq -0x178(%rbp), %rdi
callq 0x3200
movl -0x22c(%rbp), %eax
testl %eax, %eax
je 0x7996
jmp 0x7994
jmp 0x79a9
jmp 0x7475
leaq -0x178(%rbp), %rdi
callq 0x3200
jmp 0x79b2
addq $0x390, %rsp            # imm = 0x390
popq %rbp
retq
movq -0x78(%rbp), %rdi
callq 0x3530
nopl (%rax,%rax)