Ejemplo n.º 1
0
        public override void OnDatagram(Datagram datagram)
        {
            CheckDatagramValid(datagram);

            connection.SendDatagramAsync(datagram.CreateAck());

            lock (channelMutex)
            {
                int relate = RelativeSequenceNumber(datagram.Sequence, recvWindowStart);
                if (relate == 0)
                {
                    //right in time
                    connection.ReleaseDatagram(datagram);
                    AdvanceWindow();

                    int nextSeqNr = (datagram.Sequence + 1) % MAX_SEQUENCE;

                    if (ordered)
                    {
                        while (recvWithheld[nextSeqNr % WINDOW_SIZE] != null)
                        {
                            connection.ReleaseDatagram(recvWithheld[nextSeqNr % WINDOW_SIZE]);
                            AdvanceWindow();
                            nextSeqNr++;
                        }
                    }
                    else
                    {
                        while (recvEarlyReceived[nextSeqNr % WINDOW_SIZE])
                        {
                            AdvanceWindow();
                            nextSeqNr++;
                        }
                    }

                    return;
                }

                if (relate < 0)
                {
                    //duplicate
                    logger.Trace($"Dropped duplicate {datagram}");
                    datagram.Dispose();
                    return;
                }

                if (relate > WINDOW_SIZE)
                {
                    //too early message
                    logger.Trace($"Dropped too early {datagram}");
                    datagram.Dispose();
                    return;
                }

                if (ordered)
                {
                    if (recvWithheld[datagram.Sequence % WINDOW_SIZE] != null)
                    {
                        //duplicate
                        logger.Trace($"Dropped duplicate {datagram}");
                        datagram.Dispose();
                        return;
                    }

                    recvWithheld[datagram.Sequence % WINDOW_SIZE] = datagram;
                }
                else
                {
                    if (recvEarlyReceived[datagram.Sequence % WINDOW_SIZE])
                    {
                        //duplicate
                        logger.Trace($"Dropped duplicate {datagram}");
                        datagram.Dispose();
                        return;
                    }

                    recvEarlyReceived[datagram.Sequence % WINDOW_SIZE] = true;
                    connection.ReleaseDatagram(datagram);
                }
            }
        }