// File: 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
subq $0xf0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xb8(%rbp)
leaq -0x18(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0xa470
movw $0x2, -0x18(%rbp)
xorl %edi, %edi
callq 0xa670
movl %eax, -0x14(%rbp)
xorl %edi, %edi
callq 0xa0a0
movw %ax, %cx
movq -0xb8(%rbp), %rax
movw %cx, -0x16(%rbp)
movl $0x0, 0x8(%rax)
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0xa1e0
movl %eax, %ecx
movq -0xb8(%rbp), %rax
movl %ecx, 0xc(%rax)
cmpl $0x0, 0xc(%rax)
jge 0x102d8
leaq 0x2ece(%rip), %rdi      # 0x1318e
callq 0xa720
movq -0xb8(%rbp), %rax
movl $0xffffffff, 0x8(%rax)  # imm = 0xFFFFFFFF
jmp 0x10574
movq -0xb8(%rbp), %rax
movl 0xc(%rax), %edi
leaq -0x18(%rbp), %rsi
movl $0x10, %edx
callq 0xa0e0
cmpl $0x0, %eax
jge 0x10314
leaq 0x2ea7(%rip), %rdi      # 0x131a3
callq 0xa720
movq -0xb8(%rbp), %rax
movl $0xffffffff, 0x8(%rax)  # imm = 0xFFFFFFFF
jmp 0x10572
movq -0xb8(%rbp), %rdi
movl $0x1, %esi
callq 0xaf80
cmpl $0x2, %eax
je 0x10349
leaq 0x2fd4(%rip), %rdi      # 0x13305
callq 0xa720
movq -0xb8(%rbp), %rax
movl $0xffffffff, 0x8(%rax)  # imm = 0xFFFFFFFF
jmp 0x10570
movb $0x0, -0x19(%rbp)
movb $0x1, -0x1a(%rbp)
movl $0x0, -0x20(%rbp)
leaq -0x30(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0xa470
movq -0xb8(%rbp), %rdi
movw $0x2, -0x30(%rbp)
addq $0x18, %rdi
callq 0xa350
movq %rax, %rsi
leaq -0x30(%rbp), %rdx
addq $0x4, %rdx
movl $0x2, %edi
callq 0xafc0
movq -0xb8(%rbp), %rax
movzwl 0x38(%rax), %edi
callq 0xa0a0
movw %ax, %cx
movq -0xb8(%rbp), %rax
movw %cx, -0x2e(%rbp)
movl $0xffffffff, 0x8(%rax)  # imm = 0xFFFFFFFF
movb -0x19(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x103c6
jmp 0x1056e
movq -0xb8(%rbp), %rax
movl 0xc(%rax), %edi
leaq -0x30(%rbp), %rsi
movl $0x10, %edx
callq 0xa710
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jge 0x10557
callq 0xa060
cmpl $0x73, (%rax)
je 0x10403
callq 0xa060
cmpl $0x72, (%rax)
jne 0x104c8
testb $0x1, -0x1a(%rbp)
je 0x10423
callq 0xa060
cmpl $0x73, (%rax)
jne 0x10423
movb $0x0, -0x1a(%rbp)
movl $0xc350, %edi           # imm = 0xC350
callq 0xabb0
jmp 0x103b8
movl $0xf4240, %edi          # imm = 0xF4240
callq 0xabb0
movq -0xb8(%rbp), %rax
movb 0x10(%rax), %cl
addb $0x1, %cl
movb %cl, 0x10(%rax)
movsbl 0x10(%rax), %eax
cmpl $0x5, %eax
jne 0x104c3
movq -0xb8(%rbp), %rdi
leaq -0x70(%rbp), %rax
movq %rax, -0xd0(%rbp)
addq $0x18, %rdi
callq 0xa350
movq %rax, %rcx
movq -0xb8(%rbp), %rax
movq %rcx, -0xc8(%rbp)
movzwl 0x38(%rax), %eax
movl %eax, -0xbc(%rbp)
callq 0xa060
movl (%rax), %edi
callq 0xa2b0
movq -0xd0(%rbp), %rdi
movq -0xc8(%rbp), %rcx
movl -0xbc(%rbp), %r8d
movq %rax, %r9
leaq 0x2d0f(%rip), %rsi      # 0x131b6
leaq 0x2d4e(%rip), %rdx      # 0x131fc
movb $0x0, %al
callq 0xa100
leaq -0x70(%rbp), %rdi
callq 0xa720
jmp 0x1056e
jmp 0x103b8
movq -0xb8(%rbp), %rdi
leaq -0xb0(%rbp), %rax
movq %rax, -0xe8(%rbp)
addq $0x18, %rdi
callq 0xa350
movq %rax, %rcx
movq -0xb8(%rbp), %rax
movq %rcx, -0xe0(%rbp)
movzwl 0x38(%rax), %eax
movl %eax, -0xd4(%rbp)
callq 0xa060
movl (%rax), %edi
callq 0xa2b0
movq -0xe8(%rbp), %rdi
movq -0xe0(%rbp), %rcx
movl -0xd4(%rbp), %r8d
movq %rax, %r9
leaq 0x2cd8(%rip), %rsi      # 0x13204
leaq 0x2cc9(%rip), %rdx      # 0x131fc
movb $0x0, %al
callq 0xa100
leaq -0xb0(%rbp), %rdi
callq 0xa720
movq -0xb8(%rbp), %rax
movl 0xc(%rax), %edi
callq 0xb030
jmp 0x1056e
movq -0xb8(%rbp), %rax
movb $0x1, -0x19(%rbp)
movl $0x1, 0x8(%rax)
jmp 0x103b8
jmp 0x10570
jmp 0x10572
jmp 0x10574
movq -0xb8(%rbp), %rax
movl 0x8(%rax), %eax
addq $0xf0, %rsp
popq %rbp
retq
nopw (%rax,%rax)