// File: hugosantos[P]dbeacon/dbeacon_posix.cpp
// Function: SetupSocket(address const&, bool, bool)
int SetupSocket(const address &addr, bool shouldbind, bool ssm) {
	int af_family = addr.family();
	int level = addr.optlevel();

	int sock = socket(af_family, SOCK_DGRAM, 0);
	if (sock < 0) {
		perror("Failed to create multicast socket");
		return -1;
	}

	int on = 1;

	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) {
		perror("setsockopt");
		return -1;
	}

	if (shouldbind) {
		if (bind(sock, addr.saddr(), addr.addrlen()) != 0) {
			perror("Failed to bind multicast socket");
			return -1;
		}
	}

#ifdef SO_TIMESTAMP
	if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) != 0) {
		perror("setsockopt(SO_TIMESTAMP)");
		return -1;
	}
#endif

	int type = level == IPPROTO_IPV6 ?
#ifdef IPV6_RECVHOPLIMIT
				IPV6_RECVHOPLIMIT
#else
				IPV6_HOPLIMIT
#endif
				:
#ifdef IP_RECVTTL
				IP_RECVTTL;
#else
				IP_TTL;
#endif

	if (setsockopt(sock, level, type, &on, sizeof(on)) != 0) {
		perror("receiving hop limit/ttl setsockopt()");
		return -1;
	}

	if (!SetHops(sock, addr, defaultTTL)) {
		perror("SetHops");
		return -1;
	}

	if (!ssm && addr.is_multicast()) {
		if (MulticastListen(sock, addr) != 0) {
			perror("Failed to join multicast group");
			return -1;
		}
	}

	return sock;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movb %dl, %al
movb %sil, %cl
movq %rdi, -0x10(%rbp)
andb $0x1, %cl
movb %cl, -0x11(%rbp)
andb $0x1, %al
movb %al, -0x12(%rbp)
movq -0x10(%rbp), %rdi
callq 0x170e0
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
callq 0x17010
movl %eax, -0x1c(%rbp)
movl -0x18(%rbp), %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x4100
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jge 0x172b4
leaq 0x542e(%rip), %rdi      # 0x1c6d1
callq 0x43b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17435
movl $0x1, -0x24(%rbp)
movl -0x20(%rbp), %edi
movl $0x1, %esi
movl $0x2, %edx
leaq -0x24(%rbp), %rcx
movl $0x4, %r8d
callq 0x4730
cmpl $0x0, %eax
je 0x172f4
leaq 0x5410(%rip), %rdi      # 0x1c6f3
callq 0x43b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17435
testb $0x1, -0x11(%rbp)
je 0x17343
movl -0x20(%rbp), %eax
movl %eax, -0x34(%rbp)
movq -0x10(%rbp), %rdi
callq 0x17440
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rdi
callq 0x17450
movl -0x34(%rbp), %edi
movq -0x30(%rbp), %rsi
movl %eax, %edx
callq 0x40a0
cmpl $0x0, %eax
je 0x17341
leaq 0x53ce(%rip), %rdi      # 0x1c6fe
callq 0x43b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17435
jmp 0x17343
movl -0x20(%rbp), %edi
movl $0x1, %esi
movl $0x1d, %edx
leaq -0x24(%rbp), %rcx
movl $0x4, %r8d
callq 0x4730
cmpl $0x0, %eax
je 0x1737c
leaq 0x53b3(%rip), %rdi      # 0x1c71e
callq 0x43b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17435
movl -0x1c(%rbp), %edx
movl $0xc, %eax
movl $0x33, %ecx
cmpl $0x29, %edx
cmovel %ecx, %eax
movl %eax, -0x28(%rbp)
movl -0x20(%rbp), %edi
movl -0x1c(%rbp), %esi
movl -0x28(%rbp), %edx
leaq -0x24(%rbp), %rcx
movl $0x4, %r8d
callq 0x4730
cmpl $0x0, %eax
je 0x173c4
leaq 0x5381(%rip), %rdi      # 0x1c737
callq 0x43b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17435
movl -0x20(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x3e86(%rip), %rax      # 0x1b258
movl (%rax), %edx
callq 0x17480
testb $0x1, %al
jne 0x173f2
leaq 0x5378(%rip), %rdi      # 0x1c75c
callq 0x43b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17435
testb $0x1, -0x12(%rbp)
jne 0x1742f
movq -0x10(%rbp), %rdi
callq 0x17520
testb $0x1, %al
jne 0x17407
jmp 0x1742f
movl -0x20(%rbp), %edi
movq -0x10(%rbp), %rsi
callq 0x17120
cmpl $0x0, %eax
je 0x1742d
leaq 0x5345(%rip), %rdi      # 0x1c764
callq 0x43b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17435
jmp 0x1742f
movl -0x20(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nop