// File: /workspace/github_c_makefile_star2_O3/sharpyfox[P]citrusleaf-client/src/cl_lookup.c
// Function: cl_lookup
int
cl_lookup(cl_cluster *asc, char *hostname, short port, cf_vector *sockaddr_in_v)
{
	// do the gethostbyname to find the IP address
	size_t hstbuflen = 1024;
	uint8_t	stack_hstbuf[hstbuflen];
	void *tmphstbuf = stack_hstbuf;
	int rv, herr, addrmapsz;
	struct hostent hostbuf, *hp;
	cl_addrmap *map;
	int retry = 0;
	//Find if there is an alternate address that should be used for this hostname.
	if (asc && (asc->host_addr_map_v.len > 0)) {
		addrmapsz = asc->host_addr_map_v.len;
		for (int i=0; i<addrmapsz; i++) {
			map = cf_vector_pointer_get(&asc->host_addr_map_v, i);
			if (map && strcmp(map->orig, hostname) == 0) {
				//found a mapping for this address. Use the alternate one.
				cf_debug("Using %s instead of %s", map->alt, hostname);
				hostname = map->alt;
				break;
			}
		}
	}

	do {
#ifdef OSX // on OSX, gethostbyname is thread safe and there is no '_r' version 
		hp = gethostbyname2(hostname, AF_INET);
		rv = 0;
		if(hp == NULL){
			herr = h_errno; // I'm hoping this is thread-safe too, in the Mac world...
		}
#else
		rv = gethostbyname2_r(hostname, AF_INET, &hostbuf, tmphstbuf, hstbuflen,
				&hp, &herr);
#endif
		/* TRY_AGAIN for a maximun of 3 times, after which throw an error */
		if(retry > 2) {
			cf_error("gethostbyname of %s - maxmimum retries failed", hostname);
			retry = 0;
			return -1;
		}
		if (hp == NULL) {
			hostname = hostname ? hostname : "NONAME";
			switch(herr) {
				case HOST_NOT_FOUND:
					cf_error("gethostbyname says no host at %s", hostname);
					break;
				case NO_ADDRESS:
					cf_error("gethostbyname of %s says invalid address (errno %d)", hostname, herr);
					break;
				case NO_RECOVERY:
					cf_error("gethostbyname of %s says form error (errno %d)", hostname, herr);
					break;
				case TRY_AGAIN:
					cf_error("gethostbyname of %s returned TRY_AGAIN, try again (rv=%d)", hostname, rv);
					retry++;
					continue;
				default:
					cf_error("gethostbyname of %s returned an unknown error (errno %d)", hostname, herr);
					break;
			}
			if (tmphstbuf != stack_hstbuf)		free(tmphstbuf);
			return(-1);
		}
		else if (rv != 0) {
			if (rv == ERANGE) {
				hstbuflen *= 2;
				if (tmphstbuf == stack_hstbuf)
					tmphstbuf = malloc(hstbuflen);
				else
					tmphstbuf = realloc (tmphstbuf, hstbuflen);
				if (!tmphstbuf) {
					cf_error("malloc fail");
					return(-1);
				}
			}
			else if (rv == EAGAIN || herr == TRY_AGAIN) {
				cf_error("gethostbyname returned EAGAIN, try again");
				retry++;
			}
			else if (rv == ETIMEDOUT) {
				cf_error("gethostbyname for %s timed out", hostname ? (hostname): "NONAME");
				if (tmphstbuf != stack_hstbuf)		free(tmphstbuf);
				return(-1);
			}
			else {
				cf_error("gethostbyname returned an unknown error %d %d (errno %d)",rv,herr, errno);
				if (tmphstbuf != stack_hstbuf)		free(tmphstbuf);
				return(-1);
			}
		}
	} while ((rv != 0) || (hp == NULL));

#ifdef DEBUG
	cf_debug("host lookup: %s canonical: %s addrtype %d length: %d",
		hostname, hp->h_name, hp->h_addrtype, hp->h_length);

	for (int i=0;hp->h_aliases[i];i++) {
		cf_debug("  alias %d: %s",i, hp->h_aliases[i]);
	}
	for (int i=0;hp->h_addr_list[i];i++) {
		// todo: print something about the actual address
		cf_debug("  address %d: %x",i,*(uint32_t *) hp->h_addr_list[i]);
	}
#endif

	if (hp->h_addrtype != AF_INET) {
		cf_error("unknown address type %d", hp->h_addrtype);
		if (tmphstbuf != stack_hstbuf)		free(tmphstbuf);
		return(-1);
	}
	
	// sockaddr_in_v is passed as NULL from caller which needs
	// to only check if lookup succeeds. If reach here it is 
	// a successful lookup. 
	if (sockaddr_in_v == NULL) {
		goto ret_success;
	}
	
	// Move into vector
	for (int i=0;hp->h_addr_list[i];i++) {
		struct sockaddr_in 	addr;
		memset(&addr,0,sizeof(addr));
		addr.sin_family = hp->h_addrtype;
		addr.sin_addr.s_addr = *(uint32_t *) hp->h_addr_list[i];
		addr.sin_port = htons(port);
		
		cf_vector_append_unique(sockaddr_in_v, &addr);
	}

ret_success:
	if (tmphstbuf != stack_hstbuf)		free(tmphstbuf);
	
	return(0);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x478, %rsp            # imm = 0x478
movq %rsi, %r14
testq %rdi, %rdi
movq %rcx, 0x48(%rsp)
movl %edx, 0x2c(%rsp)
je 0x8ca3
movl 0xb4(%rdi), %r12d
movq %rdi, %rbx
testl %r12d, %r12d
jle 0x8ca3
addq $0xa8, %rbx
xorl %ebp, %ebp
leaq 0x50(%rsp), %r15
movq %rbx, %rdi
movl %ebp, %esi
movq %r15, %rdx
callq 0xe7d4
movq 0x50(%rsp), %r13
testq %r13, %r13
je 0x8c66
movq (%r13), %rdi
movq %r14, %rsi
callq 0x2350
testl %eax, %eax
je 0x8c6f
incl %ebp
cmpl %ebp, %r12d
jne 0x8c3f
jmp 0x8ca3
leaq 0xd652(%rip), %rax      # 0x162c8
movl (%rax), %eax
cmpl $0x3, %eax
jl 0x8c9f
leaq 0xd64c(%rip), %rax      # 0x162d0
leaq 0x6fa5(%rip), %rsi      # 0xfc30
movl $0x3, %edi
movq %r14, %rcx
movq (%rax), %r8
movq 0x8(%r13), %rdx
xorl %eax, %eax
callq *%r8
movq 0x8(%r13), %r14
movl $0x400, %r13d           # imm = 0x400
leaq 0x70(%rsp), %rbx
leaq 0x6fc0(%rip), %rbp      # 0xfc75
xorl %r15d, %r15d
leaq 0x14(%rsp), %rax
movq %r14, %rdi
movl $0x2, %esi
leaq 0x50(%rsp), %rdx
movq %rbx, %rcx
movq %r13, %r8
leaq 0x20(%rsp), %r9
movq %rax, (%rsp)
callq 0x23e0
cmpl $0x3, %r15d
jge 0x8ea3
cmpq $0x0, 0x20(%rsp)
movl %eax, %r12d
je 0x8d23
testl %r12d, %r12d
je 0x8dcc
cmpl $0x22, %r12d
jne 0x8d64
leaq 0x70(%rsp), %rax
addq %r13, %r13
cmpq %rax, %rbx
je 0x8db8
movq %rbx, %rdi
movq %r13, %rsi
callq 0x2470
jmp 0x8dc0
leaq 0xd59e(%rip), %rax      # 0x162c8
movl 0x14(%rsp), %ecx
testq %r14, %r14
cmoveq %rbp, %r14
movl (%rax), %eax
cmpl $0x2, %ecx
jne 0x8e61
testl %eax, %eax
js 0x8db3
leaq 0xd585(%rip), %rax      # 0x162d0
xorl %edi, %edi
leaq 0x6fac(%rip), %rsi      # 0xfd00
movq %r14, %rdx
movl %r12d, %ecx
movq (%rax), %r8
xorl %eax, %eax
callq *%r8
jmp 0x8db3
movq %rbx, 0x18(%rsp)
movq %rbp, %rbx
movl 0x14(%rsp), %ebp
cmpl $0xb, %r12d
sete %al
cmpl $0x2, %ebp
sete %cl
orb %al, %cl
cmpb $0x1, %cl
jne 0x8f82
leaq 0xd539(%rip), %rax      # 0x162c8
cmpl $0x0, (%rax)
js 0x8dab
leaq 0xd535(%rip), %rax      # 0x162d0
xorl %edi, %edi
leaq 0x6fdb(%rip), %rsi      # 0xfd7f
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
movq %rbx, %rbp
movq 0x18(%rsp), %rbx
incl %r15d
jmp 0x8dcc
movq %r13, %rdi
callq 0x22e0
movq %rax, %rbx
testq %rax, %rax
je 0x8fb8
movq 0x20(%rsp), %rax
testl %r12d, %r12d
setne %cl
testq %rax, %rax
sete %dl
orb %cl, %dl
jne 0x8cb8
movl 0x10(%rax), %edx
movl 0x2c(%rsp), %ebp
cmpl $0x2, %edx
jne 0x8ed7
movq 0x48(%rsp), %r12
testq %r12, %r12
je 0x8e5a
movq 0x18(%rax), %rcx
cmpq $0x0, (%rcx)
je 0x8e5a
rolw $0x8, %bp
movl $0x8, %r15d
leaq 0x30(%rsp), %r14
xorps %xmm0, %xmm0
movq %r12, %rdi
movq %r14, %rsi
movaps %xmm0, 0x30(%rsp)
movzwl 0x10(%rax), %eax
movw %ax, 0x30(%rsp)
movq (%rcx), %rax
movl (%rax), %eax
movl %eax, 0x34(%rsp)
movw %bp, 0x32(%rsp)
callq 0xe762
movq 0x20(%rsp), %rax
movq 0x18(%rax), %rdx
cmpq $0x0, (%rdx,%r15)
leaq (%rdx,%r15), %rcx
leaq 0x8(%r15), %r15
jne 0x8e18
xorl %ebp, %ebp
jmp 0x8f5c
cmpl $0x4, %ecx
je 0x8efc
cmpl $0x3, %ecx
je 0x8f1a
cmpl $0x1, %ecx
jne 0x8f38
testl %eax, %eax
js 0x8f57
leaq 0xd445(%rip), %rax      # 0x162d0
leaq 0x6dea(%rip), %rsi      # 0xfc7c
xorl %edi, %edi
movq %r14, %rdx
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x8f57
leaq 0xd41e(%rip), %rax      # 0x162c8
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
cmpl $0x0, (%rax)
js 0x8f6e
leaq 0xd411(%rip), %rax      # 0x162d0
leaq 0x6d81(%rip), %rsi      # 0xfc47
xorl %edi, %edi
movq %r14, %rdx
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x8f6e
leaq 0xd3ea(%rip), %rax      # 0x162c8
cmpl $0x0, (%rax)
js 0x8f57
leaq 0xd3e6(%rip), %rax      # 0x162d0
leaq 0x6f0f(%rip), %rsi      # 0xfe00
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x8f57
testl %eax, %eax
js 0x8f57
leaq 0xd3c9(%rip), %rax      # 0x162d0
leaq 0x6d8f(%rip), %rsi      # 0xfc9d
xorl %edi, %edi
movq %r14, %rdx
movl $0x4, %ecx
jmp 0x8f4f
testl %eax, %eax
js 0x8f57
leaq 0xd3ab(%rip), %rax      # 0x162d0
leaq 0x6da5(%rip), %rsi      # 0xfcd1
xorl %edi, %edi
movq %r14, %rdx
movl $0x3, %ecx
jmp 0x8f4f
testl %eax, %eax
js 0x8f57
leaq 0xd38d(%rip), %rax      # 0x162d0
leaq 0x6df0(%rip), %rsi      # 0xfd3a
xorl %edi, %edi
movq %r14, %rdx
movq (%rax), %r8
xorl %eax, %eax
callq *%r8
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
leaq 0x70(%rsp), %rax
cmpq %rax, %rbx
je 0x8f6e
movq %rbx, %rdi
callq 0x22c0
movl %ebp, %eax
addq $0x478, %rsp            # imm = 0x478
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xd33f(%rip), %rax      # 0x162c8
cmpl $0x6e, %r12d
movl (%rax), %eax
jne 0x8fe2
testl %eax, %eax
js 0x900b
leaq 0xd334(%rip), %rax      # 0x162d0
testq %r14, %r14
leaq 0x6e02(%rip), %rsi      # 0xfda8
cmovneq %r14, %rbx
xorl %edi, %edi
movq %rbx, %rdx
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x900b
leaq 0xd309(%rip), %rax      # 0x162c8
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
cmpl $0x0, (%rax)
js 0x8f6e
leaq 0xd300(%rip), %rax      # 0x162d0
leaq 0x6d9c(%rip), %rsi      # 0xfd73
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x8f6e
testl %eax, %eax
js 0x900b
leaq 0xd2e3(%rip), %rax      # 0x162d0
movq (%rax), %r14
callq 0x2040
movl (%rax), %r8d
leaq 0x6dc8(%rip), %rsi      # 0xfdc7
xorl %edi, %edi
movl %r12d, %edx
movl %ebp, %ecx
xorl %eax, %eax
callq *%r14
movq 0x18(%rsp), %rdi
leaq 0x70(%rsp), %rax
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
cmpq %rax, %rdi
jne 0x8f69
jmp 0x8f6e