// File: /workspace/github_cpp_makefile_star2_O1/Neuromancer2701[P]OpenTool/lib/sockets/Client.cpp
// Function: Client::Connect()
Connection_Status Client::Connect()
{

	struct sockaddr_in local_address;
	memset((char *)&local_address, 0, sizeof(local_address));
	local_address.sin_family = AF_INET;
	local_address.sin_addr.s_addr = htonl(INADDR_ANY);
	local_address.sin_port = htons(0);

	status = Connection_Status::UNKNOWN;
	client_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (client_fd < 0 )
	{
		perror("cannot create socket");
		status = Connection_Status::DISCONNECTED;
	}
	else
	{
		if(bind(client_fd, (struct sockaddr *)&local_address, sizeof(local_address)) < 0)
		{
			perror("cannot bind socket");
			status = Connection_Status::DISCONNECTED;
		}
		else
		{
			if(setBlockingMode(Blocking_Mode::NonBlock) != Error::NONE)
			{
				perror("Nonblock failed.");
				status = Connection_Status::DISCONNECTED;
			}
			else
			{
				bool connected = false;
				bool first = true;
				int result = 0;
				struct sockaddr_in remote_address;
				memset((char *)&remote_address, 0, sizeof(remote_address));
				remote_address.sin_family = AF_INET;
				inet_pton(AF_INET, ip_address.c_str(), &(remote_address.sin_addr));
				remote_address.sin_port = htons(port);

				status = Connection_Status::DISCONNECTED;
				while(!connected)
				{
				    result = connect(client_fd, (struct sockaddr *)&remote_address, sizeof(remote_address));
			        if (result < 0)
			        {
			            if (errno == EINPROGRESS || errno == EALREADY)
			            {
			                if (first && errno == EINPROGRESS)
			                {
			                    first = false;
			                    usleep(50000);  // 50 ms
			                    continue;
			                }

			                usleep(1000000);    // 1 second
			                retries++;
			                if (retries == max_retries)
			                {
				            	char error_buffer[64];
				            	sprintf(error_buffer,"%s: Unable to connect to service(reached max retries) at '%s:%d': %s\n", __FUNCTION__, ip_address.c_str(), port, strerror(errno));
				            	perror(error_buffer);
				            	break;
			                }
			                continue;
			            }
			            else
			            {
			            	char error_buffer[64];
			            	sprintf(error_buffer,"%s: Unable to connect to service at '%s:%d': %s\n", __FUNCTION__, ip_address.c_str(), port, strerror(errno));
			            	perror(error_buffer);
			                close(client_fd);
			                break;
			            }
			        }
			        else
			        {
			        	connected = true;
			        	status = Connection_Status::CONNECTED;
			        }
				}
			}
		}
	}
	return status;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x60, %rsp
movq %rdi, %rbx
xorps %xmm0, %xmm0
movaps %xmm0, -0x30(%rbp)
movq $0x2, -0x30(%rbp)
movl $0x0, 0x8(%rdi)
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x60f0
movl %eax, 0xc(%rbx)
testl %eax, %eax
js 0x9896
leaq -0x30(%rbp), %rsi
movl %eax, %edi
movl $0x10, %edx
callq 0x6090
testl %eax, %eax
js 0x989f
movq %rbx, %rdi
movl $0x1, %esi
callq 0x66e0
cmpl $0x2, %eax
jne 0x98a8
xorps %xmm0, %xmm0
leaq -0x3c(%rbp), %r14
movaps %xmm0, -0x4(%r14)
movw $0x2, -0x4(%r14)
movq 0x18(%rbx), %rsi
movl $0x2, %edi
movq %r14, %rdx
callq 0x6700
movzwl 0x38(%rbx), %eax
rolw $0x8, %ax
movw %ax, -0x2(%r14)
movl $0xffffffff, 0x8(%rbx)  # imm = 0xFFFFFFFF
movb $0x1, %r12b
leaq -0x40(%rbp), %r14
notb %r12b
movl 0xc(%rbx), %edi
movq %r14, %rsi
movl $0x10, %edx
callq 0x6360
testl %eax, %eax
jns 0x987f
callq 0x6050
movq %rax, %r15
movl (%rax), %edi
movl %edi, %eax
andl $-0x2, %eax
cmpl $0x72, %eax
jne 0x98bd
cmpl $0x73, %edi
setne %al
orb %r12b, %al
testb $0x1, %al
je 0x9870
movl $0xf4240, %edi          # imm = 0xF4240
callq 0x6540
movb 0x10(%rbx), %al
incb %al
movb %al, 0x10(%rbx)
cmpb $0x5, %al
jne 0x9820
jmp 0x9902
movl $0xc350, %edi           # imm = 0xC350
callq 0x6540
xorl %r12d, %r12d
jmp 0x981d
movl $0x1, 0x8(%rbx)
movl 0x8(%rbx), %eax
addq $0x60, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1949(%rip), %rdi      # 0xb1e6
jmp 0x98af
leaq 0x1955(%rip), %rdi      # 0xb1fb
jmp 0x98af
leaq 0x1aae(%rip), %rdi      # 0xb35d
callq 0x6370
movl $0xffffffff, 0x8(%rbx)  # imm = 0xFFFFFFFF
jmp 0x9886
movq 0x18(%rbx), %r14
movzwl 0x38(%rbx), %r15d
callq 0x6150
leaq 0x198a(%rip), %rsi      # 0xb25c
leaq 0x197b(%rip), %rdx      # 0xb254
leaq -0x80(%rbp), %r12
movq %r12, %rdi
movq %r14, %rcx
movl %r15d, %r8d
movq %rax, %r9
xorl %eax, %eax
callq 0x60a0
movq %r12, %rdi
callq 0x6370
movl 0xc(%rbx), %edi
callq 0x6720
jmp 0x9886
movq 0x18(%rbx), %r14
movzwl 0x38(%rbx), %r12d
movl (%r15), %edi
callq 0x6150
leaq 0x18f4(%rip), %rsi      # 0xb20e
leaq 0x1933(%rip), %rdx      # 0xb254
leaq -0x80(%rbp), %r15
movq %r15, %rdi
movq %r14, %rcx
movl %r12d, %r8d
movq %rax, %r9
xorl %eax, %eax
callq 0x60a0
movq %r15, %rdi
callq 0x6370
jmp 0x9886
nop