/** * * 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.ReadInt(); if (this.conv != conv_) { return(-1); } cmd = data.ReadByte(); frg = data.ReadByte(); wnd = data.ReadShort(); ts = data.ReadInt(); sn = data.ReadInt(); una = data.ReadInt(); len = data.ReadInt(); 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: Console.WriteLine(sn); 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); }
/** * * when you received a low level packet (eg. UDP packet), call it * * @param data * @return */ public int Input(ByteBuf data) { int s_una = snd_una; if (data == null || data.ReadableBytes() < IKCP_OVERHEAD) { return(-1); } int offset = 0; while (true) { int ts; int sn; int length; int una; int conv_; int wnd; byte cmd; byte frg; if (data.ReadableBytes() < IKCP_OVERHEAD) { break; } conv_ = data.ReadInt(); offset += 4; if (conv != conv_) { return(-1); } cmd = data.ReadByte(); offset += 1; frg = data.ReadByte(); offset += 1; wnd = data.ReadShort(); offset += 2; ts = data.ReadInt(); offset += 4; sn = data.ReadInt(); offset += 4; una = data.ReadInt(); offset += 4; length = data.ReadInt(); offset += 4; if (data.ReadableBytes() < length) { 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(); 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(length); seg.conv = conv_; seg.cmd = cmd; seg.frg = frg & 0x000000ff; seg.wnd = wnd; seg.ts = ts; seg.sn = sn; seg.una = una; if (length > 0) { seg.data.WriteBytes(data, length); } 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; // do nothing case IKCP_CMD_WINS: break; default: return(-3); } offset += length; } if (_itimediff(snd_una, s_una) > 0) { if (cwnd < rmt_wnd) { int mss_ = mss; if (cwnd < ssthresh) { cwnd++; incr += mss_; } else { if (incr < mss_) { incr = mss_; } incr += (mss_ * mss_) / incr + (mss_ / 16); if ((cwnd + 1) * mss_ <= incr) { cwnd++; } } if (cwnd > rmt_wnd) { cwnd = rmt_wnd; incr = rmt_wnd * mss_; } } } return(0); }