// File: /workspace/github_c_makefile_star2_O2/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 0x8550
movl 0xb4(%rdi), %r12d
movq %rdi, %rbx
testl %r12d, %r12d
je 0x8550
addq $0xa8, %rbx
xorl %ebp, %ebp
testl %r12d, %r12d
leaq 0x50(%rsp), %r15
cmovlel %ebp, %r12d
cmpl %ebp, %r12d
je 0x8550
movq %rbx, %rdi
movl %ebp, %esi
movq %r15, %rdx
callq 0xd967
movq 0x50(%rsp), %r13
testq %r13, %r13
je 0x851a
movq (%r13), %rdi
movq %r14, %rsi
callq 0x2350
testl %eax, %eax
je 0x851e
incl %ebp
jmp 0x84ee
leaq 0xcda3(%rip), %rax      # 0x152c8
movl (%rax), %eax
cmpl $0x3, %eax
jl 0x854c
leaq 0xcd9d(%rip), %rax      # 0x152d0
leaq 0x6706(%rip), %rsi      # 0xec40
movq (%rax), %r8
movq 0x8(%r13), %rdx
pushq $0x3
popq %rdi
movq %r14, %rcx
xorl %eax, %eax
callq *%r8
movq 0x8(%r13), %r14
movl $0x400, %r13d           # imm = 0x400
leaq 0x70(%rsp), %rbx
leaq 0x6723(%rip), %rbp      # 0xec85
xorl %r12d, %r12d
leaq 0x14(%rsp), %rax
movq %r14, %rdi
movq %rax, (%rsp)
pushq $0x2
popq %rsi
leaq 0x50(%rsp), %rdx
movq %rbx, %rcx
movq %r13, %r8
leaq 0x20(%rsp), %r9
callq 0x23e0
cmpl $0x3, %r12d
jge 0x8712
cmpq $0x0, 0x20(%rsp)
movl %eax, %r15d
je 0x85ce
testl %r15d, %r15d
je 0x868a
cmpl $0x22, %r15d
jne 0x8622
leaq 0x70(%rsp), %rax
addq %r13, %r13
cmpq %rax, %rbx
je 0x8676
movq %rbx, %rdi
movq %r13, %rsi
callq 0x2470
jmp 0x867e
leaq 0xccf3(%rip), %rax      # 0x152c8
movl 0x14(%rsp), %ecx
testq %r14, %r14
cmoveq %rbp, %r14
movl (%rax), %eax
leal -0x1(%rcx), %edx
cmpl $0x3, %edx
ja 0x87c9
leaq 0x663b(%rip), %rsi      # 0xec30
movslq (%rsi,%rdx,4), %rcx
addq %rsi, %rcx
jmpq *%rcx
testl %eax, %eax
js 0x8671
leaq 0xccc7(%rip), %rax      # 0x152d0
xorl %edi, %edi
leaq 0x66fe(%rip), %rsi      # 0xed10
movq %r14, %rdx
movl %r15d, %ecx
movq (%rax), %r8
xorl %eax, %eax
callq *%r8
jmp 0x8671
movq %rbx, 0x18(%rsp)
movq %rbp, %rbx
movl 0x14(%rsp), %ebp
cmpl $0xb, %r15d
sete %al
cmpl $0x2, %ebp
sete %cl
orb %al, %cl
cmpb $0x1, %cl
jne 0x8811
leaq 0xcc7b(%rip), %rax      # 0x152c8
cmpl $0x0, (%rax)
js 0x8669
leaq 0xcc77(%rip), %rax      # 0x152d0
xorl %edi, %edi
leaq 0x672d(%rip), %rsi      # 0xed8f
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
movq %rbx, %rbp
movq 0x18(%rsp), %rbx
incl %r12d
jmp 0x868a
movq %r13, %rdi
callq 0x22e0
movq %rax, %rbx
testq %rax, %rax
je 0x8847
movq 0x20(%rsp), %rax
testl %r15d, %r15d
setne %cl
testq %rax, %rax
sete %dl
orb %cl, %dl
jne 0x8565
movl 0x10(%rax), %edx
movl 0x2c(%rsp), %ebp
cmpl $0x2, %edx
jne 0x8744
movq 0x48(%rsp), %r12
testq %r12, %r12
je 0x876d
rolw $0x8, %bp
xorl %r15d, %r15d
leaq 0x30(%rsp), %r14
movq 0x18(%rax), %rcx
cmpq $0x0, (%rcx,%r15)
je 0x876d
xorps %xmm0, %xmm0
movq %r12, %rdi
movq %r14, %rsi
movaps %xmm0, 0x30(%rsp)
movzwl 0x10(%rax), %eax
movw %ax, 0x30(%rsp)
movq (%rcx,%r15), %rax
movl (%rax), %eax
movl %eax, 0x34(%rsp)
movw %bp, 0x32(%rsp)
callq 0xd8f6
movq 0x20(%rsp), %rax
addq $0x8, %r15
jmp 0x86cd
pushq $-0x1
popq %rbp
leaq 0xcbac(%rip), %rax      # 0x152c8
cmpl $0x0, (%rax)
js 0x87fd
leaq 0xcba4(%rip), %rax      # 0x152d0
leaq 0x6524(%rip), %rsi      # 0xec57
xorl %edi, %edi
movq %r14, %rdx
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x87fd
leaq 0xcb7d(%rip), %rax      # 0x152c8
cmpl $0x0, (%rax)
js 0x87e8
leaq 0xcb75(%rip), %rax      # 0x152d0
leaq 0x66ae(%rip), %rsi      # 0xee10
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x87e8
xorl %ebp, %ebp
jmp 0x87eb
testl %eax, %eax
js 0x87e8
leaq 0xcb54(%rip), %rax      # 0x152d0
leaq 0x652a(%rip), %rsi      # 0xecad
movq (%rax), %r8
pushq $0x4
jmp 0x87c1
testl %eax, %eax
js 0x87e8
leaq 0xcb3b(%rip), %rax      # 0x152d0
leaq 0x64f0(%rip), %rsi      # 0xec8c
xorl %edi, %edi
movq %r14, %rdx
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x87e8
testl %eax, %eax
js 0x87e8
leaq 0xcb1b(%rip), %rax      # 0x152d0
leaq 0x6525(%rip), %rsi      # 0xece1
movq (%rax), %r8
pushq $0x3
popq %rcx
xorl %edi, %edi
movq %r14, %rdx
jmp 0x87e3
testl %eax, %eax
js 0x87e8
leaq 0xcafc(%rip), %rax      # 0x152d0
leaq 0x656f(%rip), %rsi      # 0xed4a
xorl %edi, %edi
movq %r14, %rdx
movq (%rax), %r8
xorl %eax, %eax
callq *%r8
pushq $-0x1
popq %rbp
leaq 0x70(%rsp), %rax
cmpq %rax, %rbx
je 0x87fd
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 0xcab0(%rip), %rax      # 0x152c8
cmpl $0x6e, %r15d
movl (%rax), %eax
jne 0x886f
testl %eax, %eax
js 0x8898
leaq 0xcaa5(%rip), %rax      # 0x152d0
testq %r14, %r14
leaq 0x6583(%rip), %rsi      # 0xedb8
cmovneq %r14, %rbx
xorl %edi, %edi
movq %rbx, %rdx
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x8898
pushq $-0x1
popq %rbp
leaq 0xca77(%rip), %rax      # 0x152c8
cmpl $0x0, (%rax)
js 0x87fd
leaq 0xca73(%rip), %rax      # 0x152d0
leaq 0x651f(%rip), %rsi      # 0xed83
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0x87fd
testl %eax, %eax
js 0x8898
leaq 0xca56(%rip), %rax      # 0x152d0
movq (%rax), %r14
callq 0x2040
movl (%rax), %r8d
leaq 0x654b(%rip), %rsi      # 0xedd7
xorl %edi, %edi
movl %r15d, %edx
movl %ebp, %ecx
xorl %eax, %eax
callq *%r14
pushq $-0x1
popq %rbp
movq 0x18(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
jne 0x87f8
jmp 0x87fd
nop