// File: /workspace/github_cpp_makefile_star2_O2/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 %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdi, %rbx
andq $0x0, -0x34(%rbp)
movq $0x2, -0x3c(%rbp)
andl $0x0, 0x8(%rdi)
pushq $0x2
popq %rdi
pushq $0x1
popq %rsi
xorl %edx, %edx
callq 0x6120
movl %eax, 0xc(%rbx)
testl %eax, %eax
js 0x9100
leaq -0x3c(%rbp), %rsi
pushq $0x10
popq %rdx
movl %eax, %edi
callq 0x6090
testl %eax, %eax
js 0x9109
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x67a0
cmpl $0x2, %eax
jne 0x9112
xorps %xmm0, %xmm0
leaq -0x4c(%rbp), %r14
movaps %xmm0, -0x4(%r14)
movw $0x2, -0x4(%r14)
movq 0x18(%rbx), %rsi
pushq $0x2
popq %rdi
movq %r14, %rdx
callq 0x67d0
movzwl 0x38(%rbx), %eax
rolw $0x8, %ax
movw %ax, -0x2(%r14)
orl $-0x1, 0x8(%rbx)
movb $0x1, %cl
xorl %eax, %eax
leaq -0x50(%rbp), %r14
pushq $0x10
popq %r15
testb $0x1, %al
jne 0x90ee
movl %ecx, -0x2c(%rbp)
movl %ecx, %r13d
notb %r13b
movl 0xc(%rbx), %edi
movq %r14, %rsi
movl %r15d, %edx
callq 0x63b0
testl %eax, %eax
jns 0x9056
callq 0x6040
movq %rax, %r12
movl (%rax), %edi
movl %edi, %eax
andl $-0x2, %eax
cmpl $0x72, %eax
jne 0x9064
cmpl $0x73, %edi
setne %al
orb %r13b, %al
testb $0x1, %al
je 0x9048
movl $0xf4240, %edi          # imm = 0xF4240
callq 0x65e0
movb 0x10(%rbx), %al
incb %al
movb %al, 0x10(%rbx)
cmpb $0x5, %al
jne 0x8ffd
jmp 0x90ac
movl $0xc350, %edi           # imm = 0xC350
callq 0x65e0
xorl %ecx, %ecx
jmp 0x8ff4
movl $0x1, 0x8(%rbx)
movb $0x1, %al
movl -0x2c(%rbp), %ecx
jmp 0x8fec
movq 0x18(%rbx), %r14
movzwl 0x38(%rbx), %r15d
callq 0x6180
leaq 0x11b9(%rip), %rsi      # 0xa232
leaq 0x11aa(%rip), %rdx      # 0xa22a
leaq -0x90(%rbp), %r12
movq %r12, %rdi
movq %r14, %rcx
movl %r15d, %r8d
movq %rax, %r9
xorl %eax, %eax
callq 0x60a0
movq %r12, %rdi
callq 0x63c0
movl 0xc(%rbx), %edi
callq 0x6810
jmp 0x90ee
movq 0x18(%rbx), %r14
movzwl 0x38(%rbx), %r15d
movl (%r12), %edi
callq 0x6180
leaq 0x111f(%rip), %rsi      # 0xa1e4
leaq 0x115e(%rip), %rdx      # 0xa22a
leaq -0x90(%rbp), %r12
movq %r12, %rdi
movq %r14, %rcx
movl %r15d, %r8d
movq %rax, %r9
xorl %eax, %eax
callq 0x60a0
movq %r12, %rdi
callq 0x63c0
movl 0x8(%rbx), %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x10b5(%rip), %rdi      # 0xa1bc
jmp 0x9119
leaq 0x10c1(%rip), %rdi      # 0xa1d1
jmp 0x9119
leaq 0x121a(%rip), %rdi      # 0xa333
callq 0x63c0
orl $-0x1, 0x8(%rbx)
pushq $-0x1
popq %rax
jmp 0x90f1
nop