Beispiel #1
0
        // 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);
        }