// File: xocoder[P]m_kcptun/src/kcp_remote.cpp
// Function: remote_udpin_callback(chann_msg_t*)
static void
_remote_udpin_callback(chann_msg_t *e) {
   tun_remote_t *tun = (tun_remote_t*)e->opaque;   

   switch (e->event) {

      case CHANN_EVENT_RECV: {
         long ret = mnet_chann_recv(e->n, tun->buf, MKCP_BUF_SIZE);

         if (ret >= MKCP_OVERHEAD) {
            const int rs_offset = tun->rt ? sizeof(uint16_t) : 0;
            uint8_t *data = tun->buf + rs_offset;
            int data_len = tun->rt ? rskcp_dec_info(tun->rt, ret) : (ret - XOR64_CHECKSUM_SIZE);

            if ( tun->rt ) {
               ret = rskcp_decode(tun->rt, tun->buf, ret, &tun->buf[data_len]);
               data_len = *((uint16_t*)tun->buf); // restore data_len
            } else {
               ret = xor64_checksum_check(data, data_len, &tun->buf[data_len]);
            }

            if ( ret ) {
               if ( tun->conf->crypto ) {
                  data_len = rc4_decrypt((const char*)data, data_len,
                                         (char*)tun->buf, MKCP_BUF_SIZE,
                                         tun->ukey, (tun->ti>>20));
                  if (data_len < 0) {
                     return;
                  }
                  data = tun->buf;
               }

               if (data_len >= MKCP_OVERHEAD) {
                  proto_t pr;
                  const uint8_t *proto_data = &data[MKCP_OVERHEAD];

                  if (proto_probe(proto_data, data_len - MKCP_OVERHEAD, &pr) &&
                      pr.ptype == PROTO_TYPE_CTRL &&
                      pr.u.cmd == PROTO_CMD_RESET &&
                      tun->kcpconv != ikcp_getconv(data))
                  {
                     _remote_kcpin_reset(tun, ikcp_getconv(data));
                  }

                  ikcp_input(tun->kcpin, (const char*)data, data_len);
                  break;
               }
            }
         }

         chann_addr_t addr;
         mnet_chann_addr(e->n, &addr);
         cout << "invalid udp packet from "
              << addr.ip << ":" << addr.port
              << " ret: " << ret << endl;
         break;
      }

      case CHANN_EVENT_DISCONNECT:  {
         cout << "remote udp disconnect !" << endl;
         mnet_chann_close(e->n);
         break;
      }

      default: {
         break;
      }
   }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x68(%rbp)
subl $0x1, %eax
je 0xdafc
jmp 0xdaeb
movl -0x68(%rbp), %eax
subl $0x5, %eax
je 0xdd87
jmp 0xddb8
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x10(%rbp), %rsi
addq $0x98, %rsi
movl $0x10000, %edx          # imm = 0x10000
callq 0x7b60
cltq
movq %rax, -0x18(%rbp)
cmpq $0x18, -0x18(%rbp)
jl 0xdd11
movq -0x10(%rbp), %rax
movq 0x90(%rax), %rdx
xorl %eax, %eax
movl $0x2, %ecx
cmpq $0x0, %rdx
cmovneq %rcx, %rax
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
addq $0x98, %rax
movslq -0x1c(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x90(%rax)
je 0xdb88
movq -0x10(%rbp), %rax
movq 0x90(%rax), %rdi
movq -0x18(%rbp), %rax
movl %eax, %esi
callq 0xe830
cltq
movq %rax, -0x70(%rbp)
jmp 0xdb94
movq -0x18(%rbp), %rax
subq $0x8, %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x90(%rax)
je 0xdbf2
movq -0x10(%rbp), %rax
movq 0x90(%rax), %rdi
movq -0x10(%rbp), %rsi
addq $0x98, %rsi
movq -0x18(%rbp), %rax
movl %eax, %edx
movq -0x10(%rbp), %rcx
addq $0x98, %rcx
movslq -0x2c(%rbp), %rax
addq %rax, %rcx
callq 0xea10
cltq
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movzwl 0x98(%rax), %eax
movl %eax, -0x2c(%rbp)
jmp 0xdc16
movq -0x28(%rbp), %rdi
movl -0x2c(%rbp), %esi
movq -0x10(%rbp), %rdx
addq $0x98, %rdx
movslq -0x2c(%rbp), %rax
addq %rax, %rdx
callq 0x99d0
cltq
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0xdd0f
movq -0x10(%rbp), %rax
movq 0x78(%rax), %rax
cmpl $0x0, 0x148(%rax)
je 0xdc7e
movq -0x28(%rbp), %rdi
movl -0x2c(%rbp), %esi
movq -0x10(%rbp), %rdx
addq $0x98, %rdx
movq -0x10(%rbp), %rax
movq 0x60(%rax), %r8
movq -0x10(%rbp), %rax
movq 0x68(%rax), %r9
shrq $0x14, %r9
movl $0x10000, %ecx          # imm = 0x10000
callq 0x9640
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jge 0xdc70
jmp 0xddba
movq -0x10(%rbp), %rax
addq $0x98, %rax
movq %rax, -0x28(%rbp)
cmpl $0x18, -0x2c(%rbp)
jl 0xdd0d
movq -0x28(%rbp), %rax
addq $0x18, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
movl -0x2c(%rbp), %esi
subl $0x18, %esi
leaq -0x48(%rbp), %rdx
callq 0xbbf0
cmpl $0x0, %eax
je 0xdcf3
cmpl $0x1, -0x48(%rbp)
jne 0xdcf3
movzbl -0x40(%rbp), %eax
cmpl $0x4, %eax
jne 0xdcf3
movq -0x10(%rbp), %rax
movl 0x50(%rax), %eax
movl %eax, -0x74(%rbp)
movq -0x28(%rbp), %rdi
callq 0x6650
movl %eax, %ecx
movl -0x74(%rbp), %eax
cmpl %ecx, %eax
je 0xdcf3
movq -0x10(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x28(%rbp), %rdi
callq 0x6650
movq -0x80(%rbp), %rdi
movl %eax, %esi
callq 0xdf80
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rdi
movq -0x28(%rbp), %rsi
movslq -0x2c(%rbp), %rdx
callq 0x4af0
jmp 0xddba
jmp 0xdd0f
jmp 0xdd11
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
leaq -0x64(%rbp), %rsi
callq 0x8220
movq 0xb2a7(%rip), %rdi      # 0x18fd0
leaq 0x727c(%rip), %rsi      # 0x14fac
callq 0x32d0
movq %rax, %rdi
leaq -0x64(%rbp), %rsi
callq 0x32d0
movq %rax, %rdi
leaq 0x6dd1(%rip), %rsi      # 0x14b1c
callq 0x32d0
movq %rax, %rdi
movl -0x54(%rbp), %esi
callq 0x34d0
movq %rax, %rdi
leaq 0x7260(%rip), %rsi      # 0x14fc5
callq 0x32d0
movq %rax, %rdi
movq -0x18(%rbp), %rsi
callq 0x3530
movq %rax, %rdi
movq 0xb240(%rip), %rsi      # 0x18fc0
callq 0x3320
jmp 0xddba
movq 0xb242(%rip), %rdi      # 0x18fd0
leaq 0x7237(%rip), %rsi      # 0x14fcc
callq 0x32d0
movq %rax, %rdi
movq 0xb21c(%rip), %rsi      # 0x18fc0
callq 0x3320
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x7280
jmp 0xddba
jmp 0xddba
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)