// File: xocoder[P]m_kcptun/vendor/m_net/src/mnet_core.c
// Function: evt_poll(int)
static int
_evt_poll(int microseconds) {
   int nfd = 0;
   mnet_t *ss = _gmnet();
   struct s_event *evt = &ss->evt;
   struct s_event *chg = &ss->chg;

#if (MNET_OS_MACOX || MNET_OS_FreeBSD)
   struct timespec tsp;
   if (microseconds > 0) {
      tsp.tv_sec = microseconds / MNET_SECOND_MS;
      tsp.tv_nsec = (uint64_t)(microseconds - tsp.tv_sec * MNET_SECOND_MS) * 1000;
   }
   nfd = kevent(ss->kq, NULL, 0, evt->array, evt->size, microseconds<=0 ? NULL : &tsp);
#else  /* LINUX */
   nfd = epoll_wait(ss->kq, evt->array, evt->size, microseconds);
#endif

   if (nfd<0 && errno!=EINTR) {
      mm_log(NULL, MNET_LOG_ERR, "kevent return %d, errno %d:%s\n", nfd, errno, strerror(errno));
      return -1;
   } else {
      chg->count = 0;

      for (int i=0; i<nfd; i++) {
         mevent_t *kev = &evt->array[i];
         chann_t *n = (chann_t*)_kev_opaque(kev);

         mm_log(n, MNET_LOG_VERBOSE, "fd:%d,flags:%x,events:%x,state:%d (E:%x,H:%x,R:%x,W:%x)\n",
                n->fd, _kev_get_flags(kev), _kev_get_events(kev), n->state,
                _KEV_FLAG_ERROR, _KEV_FLAG_HUP, _KEV_EVENT_READ, _KEV_EVENT_WRITE);

         /* check error first */
         if ( _kev_flags(kev, (_KEV_FLAG_ERROR | _KEV_FLAG_HUP)) ) {
            if (_kev_flags(kev, _KEV_FLAG_ERROR)) {
               int err = _chann_get_err(n);
               mm_log(n, MNET_LOG_ERR, "chann got error: %d:%s\n", err, strerror(err));
               _chann_disconnect_socket(ss, n);
               _chann_msg(n, CHANN_EVENT_DISCONNECT, NULL, err);
            } else {
               int err = _kev_errno(kev);
               mm_log(n, MNET_LOG_VERBOSE, "chann got eof: %d:%s\n", err, strerror(err));
               _chann_disconnect_socket(ss, n);
               _chann_msg(n, CHANN_EVENT_DISCONNECT, NULL, err);
            }
            continue;           /* error state handle down, continue to next */
         }

         switch ( n->state ) {
            case CHANN_STATE_LISTENING: {
               if (n->type == CHANN_TYPE_STREAM) {
                  chann_t *c = _chann_accept(ss, n);
                  if (c) {
                     _chann_msg(n, CHANN_EVENT_ACCEPT, c, 0);
                     _evt_add(c, MNET_SET_READ);
                  }
               } else {
                  _chann_msg(n, CHANN_EVENT_RECV, NULL, 0);
               }
               break;
            }
               
            case CHANN_STATE_CONNECTING: {
               int opt=0; socklen_t opt_len=sizeof(opt);
               getsockopt(n->fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
               if (opt == 0) {
                  _evt_del(n, MNET_SET_WRITE);
                  _evt_add(n, MNET_SET_READ);
                  n->state = CHANN_STATE_CONNECTED;
                  _chann_msg(n, CHANN_EVENT_CONNECTED, NULL, 0);
               } else {
                  mm_log(n, MNET_LOG_ERR, "chann fd:%d getsockopt %d:%s\n", n->fd, opt, strerror(opt));
                  _chann_disconnect_socket(ss, n);
                  _chann_msg(n, CHANN_EVENT_DISCONNECT, NULL, opt);
               }
               break;
            }

            case CHANN_STATE_CONNECTED: {
               if ( _kev_events(kev, _KEV_EVENT_READ) ) {
                  _chann_msg(n, CHANN_EVENT_RECV, NULL, 0);
               }
               if ( _kev_events(kev, _KEV_EVENT_WRITE) ) {
                  rwb_head_t *prh = &n->rwb_send;
                  if (_rwb_count(prh) > 0) {
                     int ret=0, len=0;
                     do {
                        unsigned char *buf = _rwb_drain_param(prh, &len);
                        ret = _chann_send(n, buf, len);
                        _rwb_drain(prh, ret);
                     } while (ret>=len && _rwb_count(prh)>0);
                  } else if ( n->active_send_event ) {
                     _chann_msg(n, CHANN_EVENT_SEND, NULL, 0);
                  } else {
                     _evt_del(n, MNET_SET_WRITE);
                  }
               }
               break;
            }

            default:
               break;
         }
      }
   }

   chann_t *n = ss->del_channs;
   while (n) {
      chann_t *next = n->del_next;
      _chann_destroy(ss, n);
      n = next;
   }
   ss->del_channs = NULL;

   return ss->chann_count;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movl %edi, -0x8(%rbp)
movl $0x0, -0xc(%rbp)
callq 0x67b0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
addq $0x28, %rax
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
addq $0x18, %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movl 0x10(%rax), %edi
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x20(%rbp), %rax
movl (%rax), %edx
movl -0x8(%rbp), %ecx
callq 0x3190
movl %eax, -0xc(%rbp)
cmpl $0x0, -0xc(%rbp)
jge 0x83cb
callq 0x3040
cmpl $0x4, (%rax)
je 0x83cb
movl -0xc(%rbp), %eax
movl %eax, -0x88(%rbp)
callq 0x3040
movl (%rax), %eax
movl %eax, -0x84(%rbp)
callq 0x3040
movl (%rax), %edi
callq 0x3110
movl -0x88(%rbp), %ecx
movl -0x84(%rbp), %r8d
movq %rax, %r9
xorl %eax, %eax
movl %eax, %edi
movl $0x1, %esi
leaq 0xb134(%rip), %rdx      # 0x134ec
movb $0x0, %al
callq 0x6c30
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x8873
movq -0x28(%rbp), %rax
movl $0x0, 0x4(%rax)
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0xc(%rbp), %eax
jge 0x8822
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x2c(%rbp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0x8e90
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x40(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x90(%rbp)
movq -0x38(%rbp), %rdi
callq 0x6b30
movl %eax, -0x8c(%rbp)
movq -0x38(%rbp), %rdi
callq 0x6b60
movq -0x98(%rbp), %rdi
movl -0x90(%rbp), %ecx
movl -0x8c(%rbp), %r8d
movl %eax, %r9d
movq -0x40(%rbp), %rax
movl 0x10(%rax), %eax
movl $0x3, %esi
leaq 0xb0a5(%rip), %rdx      # 0x1350b
movl %eax, (%rsp)
movl $0x8, 0x8(%rsp)
movl $0x2010, 0x10(%rsp)     # imm = 0x2010
movl $0x1, 0x18(%rsp)
movl $0x4, 0x20(%rsp)
movb $0x0, %al
callq 0x6c30
movq -0x38(%rbp), %rdi
movl $0x2018, %esi           # imm = 0x2018
callq 0x8eb0
cmpl $0x0, %eax
je 0x859b
movq -0x38(%rbp), %rdi
movl $0x8, %esi
callq 0x8eb0
cmpl $0x0, %eax
je 0x8529
movq -0x40(%rbp), %rdi
callq 0x8ed0
movl %eax, -0x44(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0xa8(%rbp)
movl -0x44(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x44(%rbp), %edi
callq 0x3110
movq -0xa8(%rbp), %rdi
movl -0x9c(%rbp), %ecx
movq %rax, %r8
movl $0x1, %esi
leaq 0xb046(%rip), %rdx      # 0x13544
movb $0x0, %al
callq 0x6c30
movq -0x18(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x6940
movq -0x40(%rbp), %rdi
movl -0x44(%rbp), %ecx
movl $0x5, %esi
xorl %eax, %eax
movl %eax, %edx
callq 0x7cf0
jmp 0x8596
movq -0x38(%rbp), %rdi
callq 0x8f30
movl %eax, -0x48(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0xb8(%rbp)
movl -0x48(%rbp), %eax
movl %eax, -0xac(%rbp)
movl -0x48(%rbp), %edi
callq 0x3110
movq -0xb8(%rbp), %rdi
movl -0xac(%rbp), %ecx
movq %rax, %r8
movl $0x3, %esi
leaq 0xafef(%rip), %rdx      # 0x1355c
movb $0x0, %al
callq 0x6c30
movq -0x18(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x6940
movq -0x40(%rbp), %rdi
movl -0x48(%rbp), %ecx
movl $0x5, %esi
xorl %eax, %eax
movl %eax, %edx
callq 0x7cf0
jmp 0x8814
movq -0x40(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0xbc(%rbp)
subl $0x2, %eax
je 0x8631
jmp 0x85b3
movl -0xbc(%rbp), %eax
subl $0x3, %eax
je 0x8715
jmp 0x85c4
movl -0xbc(%rbp), %eax
subl $0x4, %eax
jne 0x8810
jmp 0x85d5
movq -0x40(%rbp), %rax
cmpl $0x1, 0x14(%rax)
jne 0x8618
movq -0x18(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x8f40
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x8616
movq -0x40(%rbp), %rdi
movq -0x50(%rbp), %rdx
movl $0x3, %esi
xorl %ecx, %ecx
callq 0x7cf0
movq -0x50(%rbp), %rdi
xorl %esi, %esi
callq 0x76d0
jmp 0x862c
movq -0x40(%rbp), %rdi
movl $0x1, %esi
xorl %eax, %eax
movl %eax, %edx
xorl %ecx, %ecx
callq 0x7cf0
jmp 0x8812
movl $0x0, -0x54(%rbp)
movl $0x4, -0x58(%rbp)
movq -0x40(%rbp), %rax
movl (%rax), %edi
movl $0x1, %esi
movl $0x4, %edx
leaq -0x54(%rbp), %rcx
leaq -0x58(%rbp), %r8
callq 0x3240
cmpl $0x0, -0x54(%rbp)
jne 0x869c
movq -0x40(%rbp), %rdi
movl $0x1, %esi
callq 0x79f0
movq -0x40(%rbp), %rdi
xorl %esi, %esi
callq 0x76d0
movq -0x40(%rbp), %rax
movl $0x3, 0x10(%rax)
movq -0x40(%rbp), %rdi
movl $0x4, %esi
xorl %eax, %eax
movl %eax, %edx
xorl %ecx, %ecx
callq 0x7cf0
jmp 0x8710
movq -0x40(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0x40(%rbp), %rax
movl (%rax), %eax
movl %eax, -0xc4(%rbp)
movl -0x54(%rbp), %eax
movl %eax, -0xc0(%rbp)
movl -0x54(%rbp), %edi
callq 0x3110
movq -0xd0(%rbp), %rdi
movl -0xc4(%rbp), %ecx
movl -0xc0(%rbp), %r8d
movq %rax, %r9
movl $0x1, %esi
leaq 0xae8b(%rip), %rdx      # 0x13572
movb $0x0, %al
callq 0x6c30
movq -0x18(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x6940
movq -0x40(%rbp), %rdi
movl -0x54(%rbp), %ecx
movl $0x5, %esi
xorl %eax, %eax
movl %eax, %edx
callq 0x7cf0
jmp 0x8812
movq -0x38(%rbp), %rdi
movl $0x1, %esi
callq 0x9040
cmpl $0x0, %eax
je 0x873c
movq -0x40(%rbp), %rdi
movl $0x1, %esi
xorl %eax, %eax
movl %eax, %edx
xorl %ecx, %ecx
callq 0x7cf0
movq -0x38(%rbp), %rdi
movl $0x4, %esi
callq 0x9040
cmpl $0x0, %eax
je 0x880e
movq -0x40(%rbp), %rax
addq $0x38, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rdi
callq 0x7f90
cmpl $0x0, %eax
jle 0x87dc
movl $0x0, -0x64(%rbp)
movl $0x0, -0x68(%rbp)
movq -0x60(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x9060
movq %rax, -0x70(%rbp)
movq -0x40(%rbp), %rdi
movq -0x70(%rbp), %rsi
movl -0x68(%rbp), %edx
callq 0x8080
movl %eax, -0x64(%rbp)
movq -0x60(%rbp), %rdi
movl -0x64(%rbp), %esi
callq 0x90b0
movl -0x64(%rbp), %ecx
xorl %eax, %eax
cmpl -0x68(%rbp), %ecx
movb %al, -0xd1(%rbp)
jl 0x87d0
movq -0x60(%rbp), %rdi
callq 0x7f90
cmpl $0x0, %eax
setg %al
movb %al, -0xd1(%rbp)
movb -0xd1(%rbp), %al
testb $0x1, %al
jne 0x877b
jmp 0x880c
movq -0x40(%rbp), %rax
cmpl $0x0, 0x70(%rax)
je 0x87fc
movq -0x40(%rbp), %rdi
movl $0x2, %esi
xorl %eax, %eax
movl %eax, %edx
xorl %ecx, %ecx
callq 0x7cf0
jmp 0x880a
movq -0x40(%rbp), %rdi
movl $0x1, %esi
callq 0x79f0
jmp 0x880c
jmp 0x880e
jmp 0x8812
jmp 0x8812
jmp 0x8814
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x83dd
jmp 0x8824
movq -0x18(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x78(%rbp)
cmpq $0x0, -0x78(%rbp)
je 0x885d
movq -0x78(%rbp), %rax
movq 0x80(%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x18(%rbp), %rdi
movq -0x78(%rbp), %rsi
callq 0x6a70
movq -0x80(%rbp), %rax
movq %rax, -0x78(%rbp)
jmp 0x8830
movq -0x18(%rbp), %rax
movq $0x0, 0x38(%rax)
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
nop