// File: hugosantos[P]dbeacon/protocol.cpp
// Function: handle_nmsg(address const&, unsigned long, int, unsigned char*, int, bool)
void handle_nmsg(const address &from, uint64_t recvdts, int ttl, uint8_t *buff, int len, bool ssm) {
	if (len < 4)
		return;

	if (ntohs(*((uint16_t *)buff)) != 0xbeac)
		return;

	if (buff[2] != PROTO_VER)
		return;

	uint64_t now = get_timestamp();

	if (buff[3] == 0) {
		if (len == 12) {
			uint32_t seq = read_u32(buff + 4);
			uint32_t ts = read_u32(buff + 8);
			getSource(from, 0, now, recvdts, true).update(ttl, seq, ts, now, recvdts, ssm);
		}
		return;
	} else if (buff[3] == 1) {
		if (len < 5)
			return;

		beaconSource &src = getSource(from, 0, now, recvdts, true);

		src.sttl = buff[4];

		len -= 5;

		for (uint8_t *hd = tlv_begin(buff + 5, len); hd; hd = tlv_next(hd, len)) {
			if (verbose > 4) {
				char tmp[64];
				from.to_string(tmp, sizeof(tmp));
				fprintf(stderr, "Parsing TLV (%i, %i) for %s [len is now %i]\n", (int)hd[0], (int)hd[1], tmp, len);
			}

			if (hd[0] == T_BEAC_NAME) {
				string name;
				if (check_string((char *)hd + 2, hd[1], name))
					src.setName(name);
			} else if (hd[0] == T_ADMIN_CONTACT) {
				check_string((char *)hd + 2, hd[1], src.adminContact);
			} else if (hd[0] == T_SOURCE_INFO || hd[0] == T_SOURCE_INFO_IPv4) {
				int blen = hd[0] == T_SOURCE_INFO ? 18 : 6;

				if (hd[1] < blen)
					continue;

				address addr;

				if (hd[0] == T_SOURCE_INFO) {
					sockaddr_in6 *a6 = (sockaddr_in6 *)&addr;

					a6->sin6_family = AF_INET6;

					memcpy(&a6->sin6_addr, hd + 2, sizeof(in6_addr));
					memcpy(&a6->sin6_port, hd + 18, sizeof(uint16_t));
				} else {
					sockaddr_in *a4 = (sockaddr_in *)&addr;

					a4->sin_family = AF_INET;

					memcpy(&a4->sin_addr, hd + 2, sizeof(in_addr));
					memcpy(&a4->sin_port, hd + 6, sizeof(uint16_t));
				}

				beaconExternalStats &stats = src.getExternal(addr, now, recvdts);

				int plen = hd[1] - blen;
				for (uint8_t *pd = tlv_begin(hd + 2 + blen, plen); pd; pd = tlv_next(pd, plen)) {
					if (pd[0] == T_BEAC_NAME) {
						if (check_string((char *)pd + 2, pd[1], stats.name)) {
							stats.identified = !stats.name.empty();
						}
					} else if (pd[0] == T_ADMIN_CONTACT) {
						check_string((char *)pd + 2, pd[1], stats.contact);
					} else if (pd[0] == T_ASM_STATS || pd[0] == T_SSM_STATS) {
						Stats *st = (pd[0] == T_ASM_STATS ? &stats.ASM : &stats.SSM);

						if (!read_tlv_stats(pd, stats, *st))
							break;
						st->lastupdate = now;
					}
				}

				// trigger local SSM join
				if (!addr.is_equal(beaconUnicastAddr)) {
					beaconSource &t = getSource(addr, stats.identified ? stats.name.c_str() : 0, now, recvdts, false);
					if (t.adminContact.empty())
						t.adminContact = stats.contact;
				}
			} else if (hd[0] == T_WEBSITE_GENERIC || hd[0] == T_WEBSITE_LG || hd[0] == T_WEBSITE_MATRIX) {
				string url;
				if (check_string((char *)hd + 2, hd[1], url)) {
					src.webSites[hd[0]] = url;
				}
			} else if (hd[0] == T_CC) {
				if (hd[1] == 2) {
					src.CC = string((char *)hd + 2, 2);
				}
			} else if (hd[0] == T_SOURCE_FLAGS) {
				if (hd[1] == 4)
					src.Flags = read_u32(hd + 2);
			} else if (hd[0] == T_LEAVE) {
				removeSource(from, false);
				break;
			}
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x210, %rsp            # imm = 0x210
movb %r9b, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
andb $0x1, %al
movb %al, -0x25(%rbp)
cmpl $0x4, -0x24(%rbp)
jge 0x192e1
jmp 0x19a9b
movq -0x20(%rbp), %rax
movzwl (%rax), %edi
callq 0x4760
movzwl %ax, %eax
cmpl $0xbeac, %eax           # imm = 0xBEAC
je 0x192fc
jmp 0x19a9b
movq -0x20(%rbp), %rax
movzbl 0x2(%rax), %eax
cmpl $0x1, %eax
je 0x1930e
jmp 0x19a9b
callq 0x184e0
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x3(%rax), %eax
cmpl $0x0, %eax
jne 0x19397
cmpl $0xc, -0x24(%rbp)
jne 0x19392
movq -0x20(%rbp), %rdi
addq $0x4, %rdi
callq 0x19ab0
movl %eax, -0x34(%rbp)
movq -0x20(%rbp), %rdi
addq $0x8, %rdi
callq 0x19ab0
movl %eax, -0x38(%rbp)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rdx
movq -0x10(%rbp), %rcx
xorl %eax, %eax
movl %eax, %esi
movl $0x1, %r8d
callq 0x6140
movq %rax, %rdi
movl -0x14(%rbp), %eax
movb %al, %sil
movl -0x34(%rbp), %edx
movl -0x38(%rbp), %eax
movl %eax, %ecx
movq -0x30(%rbp), %r8
movq -0x10(%rbp), %r9
movb -0x25(%rbp), %al
andb $0x1, %al
movzbl %sil, %esi
movzbl %al, %eax
movl %eax, (%rsp)
callq 0x7b20
jmp 0x19a9b
movq -0x20(%rbp), %rax
movzbl 0x3(%rax), %eax
cmpl $0x1, %eax
jne 0x19a99
cmpl $0x5, -0x24(%rbp)
jge 0x193b3
jmp 0x19a9b
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rdx
movq -0x10(%rbp), %rcx
xorl %eax, %eax
movl %eax, %esi
movl $0x1, %r8d
callq 0x6140
movq %rax, -0x40(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x4(%rax), %ecx
movq -0x40(%rbp), %rax
movl %ecx, 0x88(%rax)
movl -0x24(%rbp), %eax
subl $0x5, %eax
movl %eax, -0x24(%rbp)
movq -0x20(%rbp), %rdi
addq $0x5, %rdi
leaq -0x24(%rbp), %rsi
callq 0x19ae0
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0x19a97
leaq 0x101d4(%rip), %rax     # 0x295e8
cmpl $0x4, (%rax)
jle 0x19465
movq -0x8(%rbp), %rdi
leaq -0x90(%rbp), %rsi
movl $0x40, %edx
movl $0x1, %ecx
callq 0x18100
movq 0xfb96(%rip), %rax      # 0x28fd0
movq (%rax), %rdi
movq -0x48(%rbp), %rax
movzbl (%rax), %edx
movq -0x48(%rbp), %rax
movzbl 0x1(%rax), %ecx
leaq -0x90(%rbp), %r8
movl -0x24(%rbp), %r9d
leaq 0x33fe(%rip), %rsi      # 0x1c85c
movb $0x0, %al
callq 0x4600
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x6e, %eax
jne 0x194ff
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x1d0(%rbp)
callq 0x45d0
movq -0x1d0(%rbp), %rdx
movq -0x48(%rbp), %rax
movq %rax, %rdi
addq $0x2, %rdi
movzbl 0x1(%rax), %esi
callq 0x19b20
movb %al, -0x1c2(%rbp)
jmp 0x194ab
movb -0x1c2(%rbp), %al
testb $0x1, %al
jne 0x194b7
jmp 0x194ee
movq -0x40(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x6d90
jmp 0x194c9
jmp 0x194ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x47a8
jmp 0x19aa4
leaq -0xb0(%rbp), %rdi
callq 0x47a8
jmp 0x19a7f
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x61, %eax
jne 0x19530
movq -0x48(%rbp), %rdi
addq $0x2, %rdi
movq -0x48(%rbp), %rax
movzbl 0x1(%rax), %esi
movq -0x40(%rbp), %rdx
addq $0x2b0, %rdx            # imm = 0x2B0
callq 0x19b20
jmp 0x19a7d
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x49, %eax
je 0x1954c
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x69, %eax
jne 0x1988a
movq -0x48(%rbp), %rax
movzbl (%rax), %edx
movl $0x6, %eax
movl $0x12, %ecx
cmpl $0x49, %edx
cmovel %ecx, %eax
movl %eax, -0xc0(%rbp)
movq -0x48(%rbp), %rax
movzbl 0x1(%rax), %eax
cmpl -0xc0(%rbp), %eax
jge 0x1957e
jmp 0x19a81
leaq -0x140(%rbp), %rdi
callq 0x17b40
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x49, %eax
jne 0x195e0
leaq -0x140(%rbp), %rax
movq %rax, -0x148(%rbp)
movq -0x148(%rbp), %rax
movw $0xa, (%rax)
movq -0x148(%rbp), %rax
movq -0x48(%rbp), %rcx
movq 0x2(%rcx), %rdx
movq %rdx, 0x8(%rax)
movq 0xa(%rcx), %rcx
movq %rcx, 0x10(%rax)
movq -0x148(%rbp), %rax
movq -0x48(%rbp), %rcx
movw 0x12(%rcx), %cx
movw %cx, 0x2(%rax)
jmp 0x1961e
leaq -0x140(%rbp), %rax
movq %rax, -0x150(%rbp)
movq -0x150(%rbp), %rax
movw $0x2, (%rax)
movq -0x150(%rbp), %rax
movq -0x48(%rbp), %rcx
movl 0x2(%rcx), %ecx
movl %ecx, 0x4(%rax)
movq -0x150(%rbp), %rax
movq -0x48(%rbp), %rcx
movw 0x6(%rcx), %cx
movw %cx, 0x2(%rax)
movq -0x40(%rbp), %rdi
movq -0x30(%rbp), %rdx
movq -0x10(%rbp), %rcx
leaq -0x140(%rbp), %rsi
callq 0x78f0
movq %rax, -0x158(%rbp)
movq -0x48(%rbp), %rax
movzbl 0x1(%rax), %eax
subl -0xc0(%rbp), %eax
movl %eax, -0x15c(%rbp)
movq -0x48(%rbp), %rdi
addq $0x2, %rdi
movslq -0xc0(%rbp), %rax
addq %rax, %rdi
leaq -0x15c(%rbp), %rsi
callq 0x19ae0
movq %rax, -0x168(%rbp)
cmpq $0x0, -0x168(%rbp)
je 0x197d8
movq -0x168(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x6e, %eax
jne 0x196e6
movq -0x168(%rbp), %rdi
addq $0x2, %rdi
movq -0x168(%rbp), %rax
movzbl 0x1(%rax), %esi
movq -0x158(%rbp), %rdx
addq $0x68, %rdx
callq 0x19b20
testb $0x1, %al
jne 0x196bf
jmp 0x196e1
movq -0x158(%rbp), %rdi
addq $0x68, %rdi
callq 0x46e0
movb %al, %cl
xorb $-0x1, %cl
movq -0x158(%rbp), %rax
andb $0x1, %cl
movb %cl, 0x60(%rax)
jmp 0x197b7
movq -0x168(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x61, %eax
jne 0x19723
movq -0x168(%rbp), %rdi
addq $0x2, %rdi
movq -0x168(%rbp), %rax
movzbl 0x1(%rax), %esi
movq -0x158(%rbp), %rdx
addq $0x88, %rdx
callq 0x19b20
jmp 0x197b5
movq -0x168(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x41, %eax
je 0x19741
movq -0x168(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x53, %eax
jne 0x197b3
movq -0x168(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x41, %eax
jne 0x19764
movq -0x158(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x1d8(%rbp)
jmp 0x19776
movq -0x158(%rbp), %rax
addq $0x38, %rax
movq %rax, -0x1d8(%rbp)
movq -0x1d8(%rbp), %rax
movq %rax, -0x170(%rbp)
movq -0x168(%rbp), %rdi
movq -0x158(%rbp), %rsi
movq -0x170(%rbp), %rdx
callq 0x19c00
testb $0x1, %al
jne 0x197a4
jmp 0x197d8
movq -0x30(%rbp), %rcx
movq -0x170(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x197b5
jmp 0x197b7
jmp 0x197b9
movq -0x168(%rbp), %rdi
leaq -0x15c(%rbp), %rsi
callq 0x19d40
movq %rax, -0x168(%rbp)
jmp 0x19676
leaq -0x140(%rbp), %rdi
leaq 0xfd82(%rip), %rsi      # 0x29568
callq 0x18340
testb $0x1, %al
jne 0x19885
movq -0x158(%rbp), %rax
testb $0x1, 0x60(%rax)
je 0x19819
movq -0x158(%rbp), %rdi
addq $0x68, %rdi
callq 0x41b0
movq %rax, -0x1e0(%rbp)
jmp 0x19824
xorl %eax, %eax
movq %rax, -0x1e0(%rbp)
jmp 0x19824
movq -0x1e0(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x10(%rbp), %rcx
leaq -0x140(%rbp), %rdi
xorl %r8d, %r8d
callq 0x6140
movq %rax, -0x178(%rbp)
movq -0x178(%rbp), %rdi
addq $0x2b0, %rdi            # imm = 0x2B0
callq 0x46e0
testb $0x1, %al
jne 0x19862
jmp 0x19883
movq -0x158(%rbp), %rsi
addq $0x88, %rsi
movq -0x178(%rbp), %rdi
addq $0x2b0, %rdi            # imm = 0x2B0
callq 0x4030
jmp 0x19885
jmp 0x19a7b
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x47, %eax
je 0x198b2
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x4c, %eax
je 0x198b2
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x4d, %eax
jne 0x1996c
leaq -0x198(%rbp), %rdi
movq %rdi, -0x1f0(%rbp)
callq 0x45d0
movq -0x1f0(%rbp), %rdx
movq -0x48(%rbp), %rax
movq %rax, %rdi
addq $0x2, %rdi
movzbl 0x1(%rax), %esi
callq 0x19b20
movb %al, -0x1e1(%rbp)
jmp 0x198e8
movb -0x1e1(%rbp), %al
testb $0x1, %al
jne 0x198f4
jmp 0x1995b
movq -0x40(%rbp), %rdi
addq $0x328, %rdi            # imm = 0x328
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x19c(%rbp)
leaq -0x19c(%rbp), %rsi
callq 0xde40
movq %rax, -0x1f8(%rbp)
jmp 0x19921
movq -0x1f8(%rbp), %rdi
leaq -0x198(%rbp), %rsi
callq 0x4030
jmp 0x19936
jmp 0x1995b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x47a8
jmp 0x19aa4
leaq -0x198(%rbp), %rdi
callq 0x47a8
jmp 0x19a79
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x43, %eax
jne 0x19a26
movq -0x48(%rbp), %rax
movzbl 0x1(%rax), %eax
cmpl $0x2, %eax
jne 0x19a24
movq -0x48(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x208(%rbp)
leaq -0x1c1(%rbp), %rdi
movq %rdi, -0x200(%rbp)
callq 0x4710
movq -0x208(%rbp), %rsi
movq -0x200(%rbp), %rcx
leaq -0x1c0(%rbp), %rdi
movl $0x2, %edx
callq 0x4510
jmp 0x199d0
movq -0x40(%rbp), %rdi
addq $0x2d0, %rdi            # imm = 0x2D0
leaq -0x1c0(%rbp), %rsi
callq 0x4560
leaq -0x1c0(%rbp), %rdi
callq 0x47a8
leaq -0x1c1(%rbp), %rdi
callq 0x44c0
jmp 0x19a24
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x1c1(%rbp), %rdi
callq 0x44c0
jmp 0x19aa4
jmp 0x19a77
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x46, %eax
jne 0x19a5a
movq -0x48(%rbp), %rax
movzbl 0x1(%rax), %eax
cmpl $0x4, %eax
jne 0x19a58
movq -0x48(%rbp), %rdi
addq $0x2, %rdi
callq 0x19ab0
movl %eax, %ecx
movq -0x40(%rbp), %rax
movl %ecx, 0x2f0(%rax)
jmp 0x19a75
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x51, %eax
jne 0x19a73
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x7310
jmp 0x19a97
jmp 0x19a75
jmp 0x19a77
jmp 0x19a79
jmp 0x19a7b
jmp 0x19a7d
jmp 0x19a7f
jmp 0x19a81
movq -0x48(%rbp), %rdi
leaq -0x24(%rbp), %rsi
callq 0x19d40
movq %rax, -0x48(%rbp)
jmp 0x19402
jmp 0x19a99
jmp 0x19a9b
addq $0x210, %rsp            # imm = 0x210
popq %rbp
retq
movq -0xb8(%rbp), %rdi
callq 0x46f0