// File: xocoder[P]m_kcptun/vendor/kcp/ikcp.c
// Function: ikcp_input
int ikcp_input(ikcpcb *kcp, const char *data, long size)
{
	IUINT32 una = kcp->snd_una;
	IUINT32 maxack = 0;
	int flag = 0;

	if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) {
		ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", size);
	}

	if (data == NULL || (int)size < (int)IKCP_OVERHEAD) return -1;

	while (1) {
		IUINT32 ts, sn, len, una, conv;
		IUINT16 wnd;
		IUINT8 cmd, frg;
		IKCPSEG *seg;

		if (size < (int)IKCP_OVERHEAD) break;

		data = ikcp_decode32u(data, &conv);
		if (conv != kcp->conv) return -1;

		data = ikcp_decode8u(data, &cmd);
		data = ikcp_decode8u(data, &frg);
		data = ikcp_decode16u(data, &wnd);
		data = ikcp_decode32u(data, &ts);
		data = ikcp_decode32u(data, &sn);
		data = ikcp_decode32u(data, &una);
		data = ikcp_decode32u(data, &len);

		size -= IKCP_OVERHEAD;

		if ((long)size < (long)len) return -2;

		if (cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK &&
			cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS) 
			return -3;

		kcp->rmt_wnd = wnd;
		ikcp_parse_una(kcp, una);
		ikcp_shrink_buf(kcp);

		if (cmd == IKCP_CMD_ACK) {
			if (_itimediff(kcp->current, ts) >= 0) {
				ikcp_update_ack(kcp, _itimediff(kcp->current, ts));
			}
			ikcp_parse_ack(kcp, sn);
			ikcp_shrink_buf(kcp);
			if (flag == 0) {
				flag = 1;
				maxack = sn;
			}	else {
				if (_itimediff(sn, maxack) > 0) {
					maxack = sn;
				}
			}
			if (ikcp_canlog(kcp, IKCP_LOG_IN_ACK)) {
				ikcp_log(kcp, IKCP_LOG_IN_DATA, 
					"input ack: sn=%lu rtt=%ld rto=%ld", sn, 
					(long)_itimediff(kcp->current, ts),
					(long)kcp->rx_rto);
			}
		}
		else if (cmd == IKCP_CMD_PUSH) {
			if (ikcp_canlog(kcp, IKCP_LOG_IN_DATA)) {
				ikcp_log(kcp, IKCP_LOG_IN_DATA, 
					"input psh: sn=%lu ts=%lu", sn, ts);
			}
			if (_itimediff(sn, kcp->rcv_nxt + kcp->rcv_wnd) < 0) {
				ikcp_ack_push(kcp, sn, ts);
				if (_itimediff(sn, kcp->rcv_nxt) >= 0) {
					seg = ikcp_segment_new(kcp, len);
					seg->conv = conv;
					seg->cmd = cmd;
					seg->frg = frg;
					seg->wnd = wnd;
					seg->ts = ts;
					seg->sn = sn;
					seg->una = una;
					seg->len = len;

					if (len > 0) {
						memcpy(seg->data, data, len);
					}

					ikcp_parse_data(kcp, seg);
				}
			}
		}
		else if (cmd == IKCP_CMD_WASK) {
			// ready to send back IKCP_CMD_WINS in ikcp_flush
			// tell remote my window size
			kcp->probe |= IKCP_ASK_TELL;
			if (ikcp_canlog(kcp, IKCP_LOG_IN_PROBE)) {
				ikcp_log(kcp, IKCP_LOG_IN_PROBE, "input probe");
			}
		}
		else if (cmd == IKCP_CMD_WINS) {
			// do nothing
			if (ikcp_canlog(kcp, IKCP_LOG_IN_WINS)) {
				ikcp_log(kcp, IKCP_LOG_IN_WINS,
					"input wins: %lu", (IUINT32)(wnd));
			}
		}
		else {
			return -3;
		}

		data += len;
		size -= len;
	}

	if (flag != 0) {
		ikcp_parse_fastack(kcp, maxack);
	}

	if (_itimediff(kcp->snd_una, una) > 0) {
		if (kcp->cwnd < kcp->rmt_wnd) {
			IUINT32 mss = kcp->mss;
			if (kcp->cwnd < kcp->ssthresh) {
				kcp->cwnd++;
				kcp->incr += mss;
			}	else {
				if (kcp->incr < mss) kcp->incr = mss;
				kcp->incr += (mss * mss) / kcp->incr + (mss / 16);
				if ((kcp->cwnd + 1) * mss <= kcp->incr) {
					kcp->cwnd++;
				}
			}
			if (kcp->cwnd > kcp->rmt_wnd) {
				kcp->cwnd = kcp->rmt_wnd;
				kcp->incr = kcp->rmt_wnd * mss;
			}
		}
	}

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movq -0x10(%rbp), %rdi
movl $0x2, %esi
callq 0x43e0
cmpl $0x0, %eax
je 0x4b5a
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rcx
movl $0x2, %esi
leaq 0xe582(%rip), %rdx      # 0x130d5
movb $0x0, %al
callq 0x3780
cmpq $0x0, -0x18(%rbp)
je 0x4b6a
movq -0x20(%rbp), %rax
cmpl $0x18, %eax
jge 0x4b76
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x506e
jmp 0x4b78
cmpq $0x18, -0x20(%rbp)
jge 0x4b84
jmp 0x4f43
movq -0x18(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x5080
movq %rax, -0x18(%rbp)
movl -0x40(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl (%rcx), %eax
je 0x4bac
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x506e
movq -0x18(%rbp), %rdi
leaq -0x43(%rbp), %rsi
callq 0x50b0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
leaq -0x44(%rbp), %rsi
callq 0x50b0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
leaq -0x42(%rbp), %rsi
callq 0x50e0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x5080
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
leaq -0x34(%rbp), %rsi
callq 0x5080
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
leaq -0x3c(%rbp), %rsi
callq 0x5080
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x5080
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
subq $0x18, %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movl -0x38(%rbp), %ecx
cmpq %rcx, %rax
jge 0x4c47
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
jmp 0x506e
movzbl -0x43(%rbp), %eax
cmpl $0x51, %eax
je 0x4c77
movzbl -0x43(%rbp), %eax
cmpl $0x52, %eax
je 0x4c77
movzbl -0x43(%rbp), %eax
cmpl $0x53, %eax
je 0x4c77
movzbl -0x43(%rbp), %eax
cmpl $0x54, %eax
je 0x4c77
movl $0xfffffffd, -0x4(%rbp) # imm = 0xFFFFFFFD
jmp 0x506e
movzwl -0x42(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x40(%rax)
movq -0x10(%rbp), %rdi
movl -0x3c(%rbp), %esi
callq 0x5110
movq -0x10(%rbp), %rdi
callq 0x51e0
movzbl -0x43(%rbp), %eax
cmpl $0x52, %eax
jne 0x4d78
movq -0x10(%rbp), %rax
movl 0x4c(%rax), %edi
movl -0x30(%rbp), %esi
callq 0x4ae0
cmpq $0x0, %rax
jl 0x4cdb
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x10(%rbp), %rax
movl 0x4c(%rax), %edi
movl -0x30(%rbp), %esi
callq 0x4ae0
movq -0x60(%rbp), %rdi
movl %eax, %esi
callq 0x5240
movq -0x10(%rbp), %rdi
movl -0x34(%rbp), %esi
callq 0x5350
movq -0x10(%rbp), %rdi
callq 0x51e0
cmpl $0x0, -0x2c(%rbp)
jne 0x4d05
movl $0x1, -0x2c(%rbp)
movl -0x34(%rbp), %eax
movl %eax, -0x28(%rbp)
jmp 0x4d1e
movl -0x34(%rbp), %edi
movl -0x28(%rbp), %esi
callq 0x4ae0
cmpq $0x0, %rax
jle 0x4d1c
movl -0x34(%rbp), %eax
movl %eax, -0x28(%rbp)
jmp 0x4d1e
movq -0x10(%rbp), %rdi
movl $0x20, %esi
callq 0x43e0
cmpl $0x0, %eax
je 0x4d73
movq -0x10(%rbp), %rax
movq %rax, -0x70(%rbp)
movl -0x34(%rbp), %eax
movl %eax, -0x64(%rbp)
movq -0x10(%rbp), %rax
movl 0x4c(%rax), %edi
movl -0x30(%rbp), %esi
callq 0x4ae0
movq -0x70(%rbp), %rdi
movl -0x64(%rbp), %ecx
movq %rax, %r8
movq -0x10(%rbp), %rax
movslq 0x30(%rax), %r9
movl $0x10, %esi
leaq 0xe377(%rip), %rdx      # 0x130e3
movb $0x0, %al
callq 0x3780
jmp 0x4f1e
movzbl -0x43(%rbp), %eax
cmpl $0x51, %eax
jne 0x4e91
movq -0x10(%rbp), %rdi
movl $0x10, %esi
callq 0x43e0
cmpl $0x0, %eax
je 0x4db6
movq -0x10(%rbp), %rdi
movl -0x34(%rbp), %ecx
movl -0x30(%rbp), %r8d
movl $0x10, %esi
leaq 0xe356(%rip), %rdx      # 0x13105
movb $0x0, %al
callq 0x3780
movl -0x34(%rbp), %edi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %esi
movq -0x10(%rbp), %rax
addl 0x3c(%rax), %esi
callq 0x4ae0
cmpq $0x0, %rax
jge 0x4e8c
movq -0x10(%rbp), %rdi
movl -0x34(%rbp), %esi
movl -0x30(%rbp), %edx
callq 0x5460
movl -0x34(%rbp), %edi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %esi
callq 0x4ae0
cmpq $0x0, %rax
jl 0x4e8a
movq -0x10(%rbp), %rdi
movl -0x38(%rbp), %esi
callq 0x4850
movq %rax, -0x50(%rbp)
movl -0x40(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x10(%rax)
movzbl -0x43(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x14(%rax)
movzbl -0x44(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x18(%rax)
movzwl -0x42(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x1c(%rax)
movl -0x30(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x20(%rax)
movl -0x34(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x24(%rax)
movl -0x3c(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x28(%rax)
movl -0x38(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x2c(%rax)
cmpl $0x0, -0x38(%rbp)
jbe 0x4e7d
movq -0x50(%rbp), %rdi
addq $0x40, %rdi
movq -0x18(%rbp), %rsi
movl -0x38(%rbp), %eax
movl %eax, %edx
callq 0x3290
movq -0x10(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x4880
jmp 0x4e8c
jmp 0x4f1c
movzbl -0x43(%rbp), %eax
cmpl $0x53, %eax
jne 0x4ed3
movq -0x10(%rbp), %rax
movl 0x48(%rax), %ecx
orl $0x2, %ecx
movl %ecx, 0x48(%rax)
movq -0x10(%rbp), %rdi
movl $0x40, %esi
callq 0x43e0
cmpl $0x0, %eax
je 0x4ed1
movq -0x10(%rbp), %rdi
movl $0x40, %esi
leaq 0xe254(%rip), %rdx      # 0x1311e
movb $0x0, %al
callq 0x3780
jmp 0x4f1a
movzbl -0x43(%rbp), %eax
cmpl $0x54, %eax
jne 0x4f0c
movq -0x10(%rbp), %rdi
movl $0x80, %esi
callq 0x43e0
cmpl $0x0, %eax
je 0x4f0a
movq -0x10(%rbp), %rdi
movzwl -0x42(%rbp), %ecx
movl $0x80, %esi
leaq 0xe227(%rip), %rdx      # 0x1312a
movb $0x0, %al
callq 0x3780
jmp 0x4f18
movl $0xfffffffd, -0x4(%rbp) # imm = 0xFFFFFFFD
jmp 0x506e
jmp 0x4f1a
jmp 0x4f1c
jmp 0x4f1e
movl -0x38(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x18(%rbp)
movl -0x38(%rbp), %eax
movl %eax, %ecx
movq -0x20(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x20(%rbp)
jmp 0x4b78
cmpl $0x0, -0x2c(%rbp)
je 0x4f55
movq -0x10(%rbp), %rdi
movl -0x28(%rbp), %esi
callq 0x5610
movq -0x10(%rbp), %rax
movl 0x10(%rax), %edi
movl -0x24(%rbp), %esi
callq 0x4ae0
cmpq $0x0, %rax
jle 0x5067
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x40(%rcx), %eax
jae 0x5065
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x54(%rbp)
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x24(%rcx), %eax
jae 0x4fbe
movq -0x10(%rbp), %rax
movl 0x44(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x44(%rax)
movl -0x54(%rbp), %ecx
movq -0x10(%rbp), %rax
addl 0x80(%rax), %ecx
movl %ecx, 0x80(%rax)
jmp 0x5030
movq -0x10(%rbp), %rax
movl 0x80(%rax), %eax
cmpl -0x54(%rbp), %eax
jae 0x4fda
movl -0x54(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x80(%rax)
movl -0x54(%rbp), %eax
imull -0x54(%rbp), %eax
movq -0x10(%rbp), %rcx
xorl %edx, %edx
divl 0x80(%rcx)
movl %eax, %ecx
movl -0x54(%rbp), %eax
shrl $0x4, %eax
addl %eax, %ecx
movq -0x10(%rbp), %rax
addl 0x80(%rax), %ecx
movl %ecx, 0x80(%rax)
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
addl $0x1, %eax
imull -0x54(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x80(%rcx), %eax
ja 0x502e
movq -0x10(%rbp), %rax
movl 0x44(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x44(%rax)
jmp 0x5030
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x40(%rcx), %eax
jbe 0x5063
movq -0x10(%rbp), %rax
movl 0x40(%rax), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x44(%rax)
movq -0x10(%rbp), %rax
movl 0x40(%rax), %ecx
imull -0x54(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x80(%rax)
jmp 0x5065
jmp 0x5067
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopw (%rax,%rax)