/** * * when you received a low level packet (eg. UDP packet), call it * * @param data * @return */ public int Input(ByteBuf data) { int una_temp = snd_una; int flag = 0, maxack = 0; if (data == null || data.ReadableBytes() < IKCP_OVERHEAD) { return(-1); } while (true) { bool readed = false; int ts; int sn; int len; int una; int conv_; int wnd; byte cmd; byte frg; if (data.ReadableBytes() < IKCP_OVERHEAD) { break; } conv_ = data.ReadIntLE(); if (this.conv != conv_) { return(-1); } cmd = data.ReadByte(); frg = data.ReadByte(); wnd = data.ReadShortLE(); ts = data.ReadIntLE(); sn = data.ReadIntLE(); una = data.ReadIntLE(); len = data.ReadIntLE(); if (data.ReadableBytes() < len) { return(-2); } switch ((int)cmd) { case IKCP_CMD_PUSH: case IKCP_CMD_ACK: case IKCP_CMD_WASK: case IKCP_CMD_WINS: break; default: return(-3); } rmt_wnd = wnd & 0x0000ffff; Parse_una(una); Shrink_buf(); switch (cmd) { case IKCP_CMD_ACK: if (_itimediff(current, ts) >= 0) { Update_ack(_itimediff(current, ts)); } Parse_ack(sn); Shrink_buf(); if (flag == 0) { flag = 1; maxack = sn; } else if (_itimediff(sn, maxack) > 0) { maxack = sn; } break; case IKCP_CMD_PUSH: if (_itimediff(sn, rcv_nxt + rcv_wnd) < 0) { Ack_push(sn, ts); if (_itimediff(sn, rcv_nxt) >= 0) { Segment seg = new Segment(len); seg.conv = conv_; seg.cmd = cmd; seg.frg = frg & 0x000000ff; seg.wnd = wnd; seg.ts = ts; seg.sn = sn; seg.una = una; if (len > 0) { seg.data.WriteBytes(data, len); readed = true; } Parse_data(seg); } } break; case IKCP_CMD_WASK: // ready to send back IKCP_CMD_WINS in Ikcp_flush // tell remote my window size probe |= IKCP_ASK_TELL; break; case IKCP_CMD_WINS: // do nothing break; default: return(-3); } if (!readed) { data.SkipBytes(len); } } if (flag != 0) { Parse_fastack(maxack); } if (_itimediff(snd_una, una_temp) > 0) { if (this.cwnd < this.rmt_wnd) { if (this.cwnd < this.ssthresh) { this.cwnd++; this.incr += mss; } else { if (this.incr < mss) { this.incr = mss; } this.incr += (mss * mss) / this.incr + (mss / 16); if ((this.cwnd + 1) * mss <= this.incr) { this.cwnd++; } } if (this.cwnd > this.rmt_wnd) { this.cwnd = this.rmt_wnd; this.incr = this.rmt_wnd * mss; } } } return(0); }