// ikcp_input /// used when you receive a low level packet (eg. UDP packet) public int Input(byte[] data, int size) { uint prev_una = snd_una; uint maxack = 0; bool flag = false; // the data is expected to have the reserved space size -= Reserved; if (size < OVERHEAD) { return(-1); } int reservedOffset = Reserved; while (size >= OVERHEAD) { var decoder = new Decoder(data, reservedOffset); uint conv_ = decoder.Decode32U(); var cmd = (CommandType)decoder.Decode8U(); byte frg = decoder.Decode8U(); ushort wnd = decoder.Decode16U(); uint ts = decoder.Decode32U(); uint sn = decoder.Decode32U(); uint una = decoder.Decode32U(); int len = (int)decoder.Decode32U(); reservedOffset = decoder.Position; size -= OVERHEAD; if (!ValidateSegment(size, conv_, cmd, len)) { return(-1); } rmt_wnd = wnd; ParseUna(una); ShrinkBuf(); switch (cmd) { case CommandType.Ack: UpdateAck(ts); ParseAck(sn); ShrinkBuf(); maxack = Math.Max(maxack, sn); flag = true; break; case CommandType.Push: if (sn >= rcv_nxt + rcv_wnd) { break; } AckPush(sn, ts); if (sn < rcv_nxt) { break; } var seg = Segment.Lease(); seg.conversation = conv_; seg.cmd = cmd; seg.fragment = frg; seg.window = wnd; seg.timeStamp = ts; seg.serialNumber = sn; seg.unacknowledged = una; seg.data.Write(data, reservedOffset, len); ParseData(seg); break; case CommandType.WindowAsk: // ready to send back CMD_WINS in flush // tell remote my window size probe |= ASK_TELL; break; } reservedOffset += len; size -= len; } if (flag) { ParseFastack(maxack); } // cwnd update when packet arrived UpdateCongestionWindow(prev_una); return(0); }