// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movq %rdi, 0x10(%rsp)
cmpl $0x4, %r8d
jl 0xa6d0
movq %rcx, %r14
cmpw $0xacbe, (%rcx)         # imm = 0xACBE
jne 0xa6d0
cmpb $0x1, 0x2(%r14)
jne 0xa6d0
movl %r9d, %r13d
movl %r8d, %ebp
movl %edx, %r12d
movq %rsi, %rbx
callq 0x9f86
movq %rax, 0x8(%rsp)
movzbl 0x3(%r14), %eax
cmpl $0x1, %eax
je 0xa6cb
testl %eax, %eax
jne 0xa6d0
cmpl $0xc, %ebp
jne 0xa6d0
movl 0x4(%r14), %ebp
movl 0x8(%r14), %r14d
bswapl %ebp
bswapl %r14d
pushq $0x1
popq %r8
movq 0x10(%rsp), %rdi
xorl %esi, %esi
movq 0x8(%rsp), %r15
movq %r15, %rdx
movq %rbx, %rcx
callq 0x56f2
movzbl %r13b, %ecx
movl %ecx, (%rsp)
movzbl %r12b, %esi
movq %rax, %rdi
movl %ebp, %edx
movq %r14, %rcx
movq %r15, %r8
movq %rbx, %r9
callq 0x65ce
jmp 0xa6d0
cmpl $0x4, %ebp
jne 0xa6e2
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %r15d, %r15d
pushq $0x1
popq %r8
movq 0x10(%rsp), %rdi
xorl %esi, %esi
movq 0x8(%rsp), %rdx
movq %rbx, %rcx
callq 0x56f2
movq %rax, %r13
movzbl 0x4(%r14), %eax
movl %eax, 0x88(%r13)
addl $-0x5, %ebp
cmpl $0x2, %ebp
jb 0xa726
movzbl 0x6(%r14), %eax
addq $0x5, %r14
xorl %r15d, %r15d
cmpl %eax, %ebp
cmovaeq %r14, %r15
leaq 0x2d0(%r13), %rax
movq %rax, 0x28(%rsp)
leaq 0x328(%r13), %rax
movq %rax, 0x40(%rsp)
movq %r13, %rax
addq $0x2b0, %rax            # imm = 0x2B0
movq %rax, 0x30(%rsp)
movq %r13, 0x38(%rsp)
testq %r15, %r15
je 0xa6d0
movq %r15, %r12
leaq 0x7dd4(%rip), %rax      # 0x12538
cmpl $0x5, (%rax)
jge 0xa93a
movb (%r12), %al
movzbl %al, %ecx
leal -0x43(%rcx), %edx
cmpl $0xe, %edx
ja 0xa7e1
leaq 0x1fb5(%rip), %rsi      # 0xc738
movslq (%rsi,%rdx,4), %rcx
addq %rsi, %rcx
jmpq *%rcx
leaq 0x60(%rsp), %rax
movq %rax, 0x50(%rsp)
andq $0x0, 0x58(%rsp)
movb $0x0, 0x60(%rsp)
leaq 0x2(%r12), %rdi
movzbl 0x1(%r12), %esi
leaq 0x50(%rsp), %rdx
callq 0xabce
testb %al, %al
je 0xa833
movzbl (%r12), %eax
movl %eax, 0x1c(%rsp)
movq 0x40(%rsp), %rdi
leaq 0x1c(%rsp), %rsi
callq 0x7800
movq %rax, %rdi
leaq 0x50(%rsp), %rsi
callq 0x31e0
jmp 0xa833
cmpl $0x61, %ecx
je 0xa920
cmpl $0x69, %ecx
je 0xa873
cmpl $0x6e, %ecx
jne 0xa83d
leaq 0x60(%rsp), %rax
movq %rax, 0x50(%rsp)
andq $0x0, 0x58(%rsp)
movb $0x0, 0x60(%rsp)
leaq 0x2(%r12), %rdi
movzbl 0x1(%r12), %esi
leaq 0x50(%rsp), %rdx
callq 0xabce
testb %al, %al
je 0xa833
movq %r13, %rdi
leaq 0x50(%rsp), %rsi
callq 0x6012
leaq 0x50(%rsp), %rdi
callq 0x3688
movzbl 0x1(%r12), %eax
subl %eax, %ebp
addl $-0x2, %ebp
movl $0x0, %r15d
cmpl $0x2, %ebp
jl 0xa751
addq %r12, %rax
addq $0x2, %rax
movzbl 0x1(%rax), %ecx
cmpl %ecx, %ebp
movl $0x0, %r15d
cmovaeq %rax, %r15
jmp 0xa751
cmpb $0x49, %al
pushq $0x6
popq %r14
pushq $0x12
popq %rax
cmovel %eax, %r14d
movzbl 0x1(%r12), %eax
cmpl %eax, %r14d
ja 0xa83d
leaq 0x50(%rsp), %rdi
callq 0x9c00
leaq 0x2(%r12), %rax
cmpb $0x49, (%r12)
jne 0xa980
movw $0xa, 0x50(%rsp)
movups (%rax), %xmm0
leaq 0x60(%rsp), %rax
movups %xmm0, -0x8(%rax)
pushq $0x12
jmp 0xa98f
cmpb $0x2, 0x1(%r12)
jne 0xa83d
leaq 0x2(%r12), %rsi
leaq 0x60(%rsp), %rax
movq %rax, 0x50(%rsp)
leaq 0x4(%r12), %rdx
leaq 0x50(%rsp), %r14
movq %r14, %rdi
callq 0x9176
movq 0x28(%rsp), %rdi
movq %r14, %rsi
callq 0x3460
movq %r14, %rdi
jmp 0xa838
cmpb $0x4, 0x1(%r12)
jne 0xa83d
movl 0x2(%r12), %eax
bswapl %eax
movl %eax, 0x2f0(%r13)
jmp 0xa83d
leaq 0x2(%r12), %rdi
movzbl 0x1(%r12), %esi
movq 0x30(%rsp), %rdx
callq 0xabce
jmp 0xa83d
movq 0x10(%rsp), %rdi
leaq 0x50(%rsp), %r14
movq %r14, %rsi
pushq $0x40
popq %rdx
pushq $0x1
popq %rcx
callq 0x9e40
movq 0x7677(%rip), %rax      # 0x11fd0
movq (%rax), %rdi
movzbl (%r12), %edx
movzbl 0x1(%r12), %ecx
leaq 0x1e06(%rip), %rsi      # 0xc774
movq %r14, %r8
movl %ebp, %r9d
xorl %eax, %eax
callq 0x34f0
jmp 0xa76d
movw $0x2, 0x50(%rsp)
movl (%rax), %eax
movl %eax, 0x54(%rsp)
pushq $0x6
popq %rax
movzwl (%r12,%rax), %eax
movw %ax, 0x52(%rsp)
movq %r13, %rdi
leaq 0x50(%rsp), %rsi
movq 0x8(%rsp), %rdx
movq %rbx, %rcx
callq 0x6476
movq %rax, %r13
movzbl 0x1(%r12), %r15d
subl %r14d, %r15d
cmpl $0x2, %r15d
jge 0xa9c5
xorl %eax, %eax
jmp 0xa9e0
movl %r14d, %eax
leaq (%r12,%rax), %rcx
addq $0x2, %rcx
movzbl 0x1(%rcx), %eax
cmpl %eax, %r15d
movl $0x0, %eax
cmovaeq %rcx, %rax
leaq 0x88(%r13), %rcx
movq %rcx, 0x20(%rsp)
leaq 0x68(%r13), %rcx
movq %rcx, 0x48(%rsp)
testq %rax, %rax
je 0xab44
movq %rax, %r14
movzbl (%rax), %ecx
cmpl $0x41, %ecx
je 0xaa4a
cmpl $0x53, %ecx
je 0xaa4a
cmpl $0x61, %ecx
je 0xaafa
cmpl $0x6e, %ecx
jne 0xab0d
leaq 0x2(%r14), %rdi
movzbl 0x1(%r14), %esi
movq 0x48(%rsp), %rdx
callq 0xabce
testb %al, %al
je 0xab0d
cmpq $0x0, 0x70(%r13)
setne 0x60(%r13)
jmp 0xab0d
cmpb $0x14, 0x1(%r14)
jne 0xab44
leaq 0x38(%r13), %rax
leaq 0x10(%r13), %rdx
cmpb $0x41, %cl
cmoveq %rdx, %rax
movl 0x2(%r14), %ecx
bswapl %ecx
movq %rcx, (%rax)
movl 0x6(%r14), %ecx
bswapl %ecx
movl %ecx, 0x8(%r13)
movb 0xa(%r14), %cl
movb %cl, 0x25(%rax)
movl 0xb(%r14), %ecx
bswapl %ecx
movl %ecx, 0x10(%rax)
movl 0xf(%r14), %ecx
bswapl %ecx
movl %ecx, 0x14(%rax)
movzbl 0x13(%r14), %ecx
cvtsi2sd %ecx, %xmm0
divsd 0x1c8f(%rip), %xmm0     # 0xc730
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x18(%rax)
movzbl 0x14(%r14), %ecx
cvtsi2sd %ecx, %xmm0
divsd 0x1c6d(%rip), %xmm0     # 0xc728
movss 0x1c61(%rip), %xmm1     # 0xc724
cmpb $-0x1, %cl
je 0xaacc
cvtsd2ss %xmm0, %xmm1
movss %xmm1, 0x1c(%rax)
movzbl 0x15(%r14), %ecx
cvtsi2sd %ecx, %xmm0
divsd 0x1c4e(%rip), %xmm0     # 0xc730
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x20(%rax)
movb $0x1, 0x24(%rax)
movq 0x8(%rsp), %rcx
movq %rcx, 0x8(%rax)
jmp 0xab0d
leaq 0x2(%r14), %rdi
movzbl 0x1(%r14), %esi
movq 0x20(%rsp), %rdx
callq 0xabce
movzbl 0x1(%r14), %ecx
subl %ecx, %r15d
addl $-0x2, %r15d
movl $0x0, %eax
cmpl $0x2, %r15d
jl 0xa9f5
addq %r14, %rcx
addq $0x2, %rcx
movzbl 0x1(%rcx), %eax
cmpl %eax, %r15d
movl $0x0, %eax
cmovaeq %rcx, %rax
jmp 0xa9f5
leaq 0x50(%rsp), %rdi
leaq 0x7968(%rip), %rsi      # 0x124b8
callq 0x9f1c
testb %al, %al
jne 0xab9a
cmpb $0x0, 0x60(%r13)
je 0xab66
movq 0x68(%r13), %rsi
jmp 0xab68
xorl %esi, %esi
leaq 0x50(%rsp), %rdi
movq 0x8(%rsp), %rdx
movq %rbx, %rcx
xorl %r8d, %r8d
callq 0x56f2
cmpq $0x0, 0x2b8(%rax)
jne 0xab9a
addq $0x2b0, %rax            # imm = 0x2B0
movq %rax, %rdi
movq 0x20(%rsp), %rsi
callq 0x31e0
movq 0x38(%rsp), %r13
jmp 0xa83d
movq 0x10(%rsp), %rdi
xorl %esi, %esi
callq 0x602b
jmp 0xa6d0
jmp 0xabb9
jmp 0xabb9
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x3688
movq %rbx, %rdi
callq 0x35d0