// File: hugosantos[P]dbeacon/dbeacon_posix.cpp
// Function: RecvMsg(int, address&, address&, unsigned char*, int, int&, unsigned long&)
int RecvMsg(int sock, address &from, address &to, uint8_t *buffer, int buflen, int &ttl, uint64_t &ts) {
	int len;
	struct msghdr msg;
	struct iovec iov;
	uint8_t ctlbuf[64];

	from.set_family(beaconUnicastAddr.family());

	msg.msg_name = (char *)from.saddr();
	msg.msg_namelen = from.addrlen();
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = (char *)ctlbuf;
	msg.msg_controllen = sizeof(ctlbuf);
	msg.msg_flags = 0;

	iov.iov_base = (char *)buffer;
	iov.iov_len = buflen;

	len = recvmsg(sock, &msg, 0);
	if (len < 0)
		return len;

	ts = 0;
	ttl = 127;

	to = beaconUnicastAddr;

	if (msg.msg_controllen > 0) {
		for (cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
			if (hdr->cmsg_level == IPPROTO_IPV6 && hdr->cmsg_type == IPV6_HOPLIMIT) {
				ttl = *(uint8_t *)CMSG_DATA(hdr);
#ifdef IPV6_PKTINFO
			} else if (hdr->cmsg_level == IPPROTO_IPV6 && hdr->cmsg_type == IPV6_PKTINFO) {
				if (hdr->cmsg_len == CMSG_LEN(sizeof(in6_pktinfo))) {
					in6_pktinfo *pktinfo = (in6_pktinfo *)CMSG_DATA(hdr);
					to.set_family(AF_INET6);
					to.v6()->sin6_addr = pktinfo->ipi6_addr;
				}
#endif
#ifdef IP_RECVTTL
			} else if (hdr->cmsg_level == IPPROTO_IP && hdr->cmsg_type == IP_RECVTTL) {
				ttl = *(uint8_t *)CMSG_DATA(hdr);
#endif
			} else if (hdr->cmsg_level == IPPROTO_IP && hdr->cmsg_type == IP_TTL) {
				ttl = *(uint8_t *)CMSG_DATA(hdr);
#ifdef SO_TIMESTAMP
			} else if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SO_TIMESTAMP) {
				timeval *tv = (timeval *)CMSG_DATA(hdr);
				ts = tv->tv_sec;
				ts *= 1000;
				ts += tv->tv_usec / 1000;
#endif
			}
		}
	}

	if (!ts) {
		ts = get_time_of_day();
	}

	return len;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq 0x10(%rbp), %rax
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movq %r9, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xe0(%rbp)
leaq 0x11f30(%rip), %rdi     # 0x29568
callq 0x170e0
movq -0xe0(%rbp), %rdi
movl %eax, %esi
callq 0x17900
movq -0x10(%rbp), %rdi
callq 0x17940
movq %rax, -0x70(%rbp)
movq -0x10(%rbp), %rdi
callq 0x17450
movl %eax, -0x68(%rbp)
leaq -0x80(%rbp), %rax
movq %rax, -0x60(%rbp)
movq $0x1, -0x58(%rbp)
leaq -0xc0(%rbp), %rax
movq %rax, -0x50(%rbp)
movq $0x40, -0x48(%rbp)
movl $0x0, -0x40(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x80(%rbp)
movslq -0x24(%rbp), %rax
movq %rax, -0x78(%rbp)
movl -0x8(%rbp), %edi
leaq -0x70(%rbp), %rsi
xorl %edx, %edx
callq 0x4150
movl %eax, -0x34(%rbp)
cmpl $0x0, -0x34(%rbp)
jge 0x176c0
movl -0x34(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x178ea
movq 0x10(%rbp), %rax
movq $0x0, (%rax)
movq -0x30(%rbp), %rax
movl $0x7f, (%rax)
movq -0x18(%rbp), %rdi
leaq 0x11e88(%rip), %rsi     # 0x29568
movl $0x80, %edx
callq 0x4390
cmpq $0x0, -0x48(%rbp)
jbe 0x178cb
cmpq $0x10, -0x48(%rbp)
jb 0x17709
movq -0x50(%rbp), %rax
movq %rax, -0xe8(%rbp)
jmp 0x17714
xorl %eax, %eax
movq %rax, -0xe8(%rbp)
jmp 0x17714
movq -0xe8(%rbp), %rax
movq %rax, -0xc8(%rbp)
cmpq $0x0, -0xc8(%rbp)
je 0x178c9
movq -0xc8(%rbp), %rax
cmpl $0x29, 0x8(%rax)
jne 0x17760
movq -0xc8(%rbp), %rax
cmpl $0x34, 0xc(%rax)
jne 0x17760
movq -0xc8(%rbp), %rax
movzbl 0x10(%rax), %ecx
movq -0x30(%rbp), %rax
movl %ecx, (%rax)
jmp 0x178ab
movq -0xc8(%rbp), %rax
cmpl $0x29, 0x8(%rax)
jne 0x177d9
movq -0xc8(%rbp), %rax
cmpl $0x32, 0xc(%rax)
jne 0x177d9
movq -0xc8(%rbp), %rax
cmpq $0x24, (%rax)
jne 0x177d4
movq -0xc8(%rbp), %rax
addq $0x10, %rax
movq %rax, -0xd0(%rbp)
movq -0x18(%rbp), %rdi
movl $0xa, %esi
callq 0x17900
movq -0xd0(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x18(%rbp), %rdi
callq 0x17950
movq -0xf0(%rbp), %rcx
movq (%rcx), %rdx
movq %rdx, 0x8(%rax)
movq 0x8(%rcx), %rcx
movq %rcx, 0x10(%rax)
jmp 0x178a9
movq -0xc8(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x17809
movq -0xc8(%rbp), %rax
cmpl $0xc, 0xc(%rax)
jne 0x17809
movq -0xc8(%rbp), %rax
movzbl 0x10(%rax), %ecx
movq -0x30(%rbp), %rax
movl %ecx, (%rax)
jmp 0x178a7
movq -0xc8(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x17836
movq -0xc8(%rbp), %rax
cmpl $0x2, 0xc(%rax)
jne 0x17836
movq -0xc8(%rbp), %rax
movzbl 0x10(%rax), %ecx
movq -0x30(%rbp), %rax
movl %ecx, (%rax)
jmp 0x178a5
movq -0xc8(%rbp), %rax
cmpl $0x1, 0x8(%rax)
jne 0x178a3
movq -0xc8(%rbp), %rax
cmpl $0x1d, 0xc(%rax)
jne 0x178a3
movq -0xc8(%rbp), %rax
addq $0x10, %rax
movq %rax, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
movq (%rax), %rcx
movq 0x10(%rbp), %rax
movq %rcx, (%rax)
movq 0x10(%rbp), %rax
imulq $0x3e8, (%rax), %rcx    # imm = 0x3E8
movq %rcx, (%rax)
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rax
movl $0x3e8, %ecx            # imm = 0x3E8
cqto
idivq %rcx
movq %rax, %rcx
movq 0x10(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
jmp 0x178a5
jmp 0x178a7
jmp 0x178a9
jmp 0x178ab
jmp 0x178ad
movq -0xc8(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0x40f0
movq %rax, -0xc8(%rbp)
jmp 0x17722
jmp 0x178cb
movq 0x10(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x178e4
callq 0x17960
movq %rax, %rcx
movq 0x10(%rbp), %rax
movq %rcx, (%rax)
movl -0x34(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xf0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)