// File: xocoder[P]m_kcptun/vendor/kcp/ikcp.c
// Function: ikcp_recv
int ikcp_recv(ikcpcb *kcp, char *buffer, int len)
{
	struct IQUEUEHEAD *p;
	int ispeek = (len < 0)? 1 : 0;
	int peeksize;
	int recover = 0;
	IKCPSEG *seg;
	assert(kcp);

	if (iqueue_is_empty(&kcp->rcv_queue))
		return -1;

	if (len < 0) len = -len;

	peeksize = ikcp_peeksize(kcp);

	if (peeksize < 0) 
		return -2;

	if (peeksize > len) 
		return -3;

	if (kcp->nrcv_que >= kcp->rcv_wnd)
		recover = 1;

	// merge fragment
	for (len = 0, p = kcp->rcv_queue.next; p != &kcp->rcv_queue; ) {
		int fragment;
		seg = iqueue_entry(p, IKCPSEG, node);
		p = p->next;

		if (buffer) {
			memcpy(buffer, seg->data, seg->len);
			buffer += seg->len;
		}

		len += seg->len;
		fragment = seg->frg;

		if (ikcp_canlog(kcp, IKCP_LOG_RECV)) {
			ikcp_log(kcp, IKCP_LOG_RECV, "recv sn=%lu", seg->sn);
		}

		if (ispeek == 0) {
			iqueue_del(&seg->node);
			ikcp_segment_delete(kcp, seg);
			kcp->nrcv_que--;
		}

		if (fragment == 0) 
			break;
	}

	assert(len == peeksize);

	// move available data from rcv_buf -> rcv_queue
	while (! iqueue_is_empty(&kcp->rcv_buf)) {
		IKCPSEG *seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
		if (seg->sn == kcp->rcv_nxt && kcp->nrcv_que < kcp->rcv_wnd) {
			iqueue_del(&seg->node);
			kcp->nrcv_buf--;
			iqueue_add_tail(&seg->node, &kcp->rcv_queue);
			kcp->nrcv_que++;
			kcp->rcv_nxt++;
		}	else {
			break;
		}
	}

	// fast recover
	if (kcp->nrcv_que < kcp->rcv_wnd && recover) {
		// ready to send back IKCP_CMD_WINS in ikcp_flush
		// tell remote my window size
		kcp->probe |= IKCP_ASK_TELL;
	}

	return len;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movl -0x1c(%rbp), %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x0, %edx
cmovll %ecx, %eax
movl %eax, -0x2c(%rbp)
movl $0x0, -0x34(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x3fa6
jmp 0x3fc5
leaq 0xf057(%rip), %rdi      # 0x13004
leaq 0xf054(%rip), %rsi      # 0x13008
movl $0x16b, %edx            # imm = 0x16B
leaq 0xf076(%rip), %rcx      # 0x13036
callq 0x3210
movq -0x10(%rbp), %rax
addq $0x98, %rax
movq -0x10(%rbp), %rcx
cmpq 0x98(%rcx), %rax
jne 0x3fe8
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x42c6
cmpl $0x0, -0x1c(%rbp)
jge 0x3ff6
xorl %eax, %eax
subl -0x1c(%rbp), %eax
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rdi
callq 0x42d0
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jge 0x4014
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
jmp 0x42c6
movl -0x30(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jle 0x4028
movl $0xfffffffd, -0x4(%rbp) # imm = 0xFFFFFFFD
jmp 0x42c6
movq -0x10(%rbp), %rax
movl 0x64(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x3c(%rcx), %eax
jb 0x403f
movl $0x1, -0x34(%rbp)
movl $0x0, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movq 0x98(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq -0x10(%rbp), %rcx
addq $0x98, %rcx
cmpq %rcx, %rax
je 0x4166
movq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x40b5
movq -0x18(%rbp), %rdi
movq -0x40(%rbp), %rsi
addq $0x40, %rsi
movq -0x40(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, %edx
callq 0x3290
movq -0x40(%rbp), %rax
movl 0x2c(%rax), %ecx
movq -0x18(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x18(%rbp)
movq -0x40(%rbp), %rax
movl 0x2c(%rax), %eax
addl -0x1c(%rbp), %eax
movl %eax, -0x1c(%rbp)
movq -0x40(%rbp), %rax
movl 0x18(%rax), %eax
movl %eax, -0x44(%rbp)
movq -0x10(%rbp), %rdi
movl $0x8, %esi
callq 0x43e0
cmpl $0x0, %eax
je 0x40fd
movq -0x10(%rbp), %rdi
movq -0x40(%rbp), %rax
movl 0x24(%rax), %ecx
movl $0x8, %esi
leaq 0xef65(%rip), %rdx      # 0x1305b
movb $0x0, %al
callq 0x3780
cmpl $0x0, -0x2c(%rbp)
jne 0x4159
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x40(%rbp), %rax
movq (%rax), %rax
movq %rcx, 0x8(%rax)
movq -0x40(%rbp), %rax
movq (%rax), %rcx
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rcx, (%rax)
movq -0x40(%rbp), %rax
movq $0x0, (%rax)
movq -0x40(%rbp), %rax
movq $0x0, 0x8(%rax)
movq -0x10(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x3f30
movq -0x10(%rbp), %rax
movl 0x64(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x64(%rax)
cmpl $0x0, -0x44(%rbp)
jne 0x4161
jmp 0x4166
jmp 0x4055
movl -0x1c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jne 0x4170
jmp 0x418f
leaq 0xeef0(%rip), %rdi      # 0x13067
leaq 0xee8a(%rip), %rsi      # 0x13008
movl $0x199, %edx            # imm = 0x199
leaq 0xeeac(%rip), %rcx      # 0x13036
callq 0x3210
jmp 0x4191
movq -0x10(%rbp), %rax
addq $0xb8, %rax
movq -0x10(%rbp), %rcx
cmpq 0xb8(%rcx), %rax
sete %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x41b4
jmp 0x429d
movq -0x10(%rbp), %rax
movq 0xb8(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movl 0x24(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x18(%rcx), %eax
jne 0x4296
movq -0x10(%rbp), %rax
movl 0x64(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x3c(%rcx), %eax
jae 0x4296
movq -0x50(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x50(%rbp), %rax
movq (%rax), %rax
movq %rcx, 0x8(%rax)
movq -0x50(%rbp), %rax
movq (%rax), %rcx
movq -0x50(%rbp), %rax
movq 0x8(%rax), %rax
movq %rcx, (%rax)
movq -0x50(%rbp), %rax
movq $0x0, (%rax)
movq -0x50(%rbp), %rax
movq $0x0, 0x8(%rax)
movq -0x10(%rbp), %rax
movl 0x5c(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x5c(%rax)
movq -0x10(%rbp), %rax
movq 0xa0(%rax), %rcx
movq -0x50(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rcx
addq $0x98, %rcx
movq -0x50(%rbp), %rax
movq %rcx, (%rax)
movq -0x50(%rbp), %rcx
movq -0x10(%rbp), %rax
movq 0xa0(%rax), %rax
movq %rcx, (%rax)
movq -0x50(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0xa0(%rax)
movq -0x10(%rbp), %rax
movl 0x64(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x64(%rax)
movq -0x10(%rbp), %rax
movl 0x18(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x18(%rax)
jmp 0x4298
jmp 0x429d
jmp 0x4191
movq -0x10(%rbp), %rax
movl 0x64(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x3c(%rcx), %eax
jae 0x42c0
cmpl $0x0, -0x34(%rbp)
je 0x42c0
movq -0x10(%rbp), %rax
movl 0x48(%rax), %ecx
orl $0x2, %ecx
movl %ecx, 0x48(%rax)
movl -0x1c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nop