RelativeSequenceNumber() static private method

static private RelativeSequenceNumber ( int nr, int expected ) : int
nr int
expected int
return int
        // remoteWindowStart is remote expected sequence number; everything below this has arrived properly
        // seqNr is the actual nr received
        internal override void ReceiveAcknowledge(double now, int seqNr)
        {
            // late (dupe), on time or early ack?
            int relate = NetUtility.RelativeSequenceNumber(seqNr, m_windowStart);

            if (relate < 0)
            {
                //m_connection.m_peer.LogDebug("Received late/dupe ack for #" + seqNr);
                return;                 // late/duplicate ack
            }

            if (relate == 0)
            {
                //m_connection.m_peer.LogDebug("Received right-on-time ack for #" + seqNr);

                // ack arrived right on time
                NetException.Assert(seqNr == m_windowStart);

                m_receivedAcks[m_windowStart] = false;
                m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;

                return;
            }

            // Advance window to this position
            m_receivedAcks[seqNr] = true;

            while (m_windowStart != seqNr)
            {
                m_receivedAcks[m_windowStart] = false;
                m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;
            }
        }
Example #2
0
        internal override void ReceiveMessage(NetIncomingMessage message)
        {
            int relate = NetUtility.RelativeSequenceNumber(message.m_sequenceNumber, m_windowStart);

            // ack no matter what
            m_connection.QueueAck(message.m_receivedMessageType, message.m_sequenceNumber);

            if (relate == 0)
            {
                // Log("Received message #" + message.SequenceNumber + " right on time");

                //
                // excellent, right on time
                //
                //m_peer.LogVerbose("Received RIGHT-ON-TIME " + message);

                AdvanceWindow();
                m_peer.ReleaseMessage(message);

                // release withheld messages
                int nextSeqNr = (message.m_sequenceNumber + 1) % NetConstants.NumSequenceNumbers;

                while (m_earlyReceived[nextSeqNr % m_windowSize])
                {
                    message = m_withheldMessages[nextSeqNr % m_windowSize];
                    NetException.Assert(message != null);

                    // remove it from withheld messages
                    m_withheldMessages[nextSeqNr % m_windowSize] = null;

                    m_peer.LogVerbose("Releasing withheld message #" + message);

                    m_peer.ReleaseMessage(message);

                    AdvanceWindow();
                    nextSeqNr++;
                }

                return;
            }

            if (relate < 0)
            {
                m_peer.LogVerbose("Received message #" + message.m_sequenceNumber + " DROPPING DUPLICATE");
                // duplicate
                return;
            }

            // relate > 0 = early message
            if (relate > m_windowSize)
            {
                // too early message!
                m_peer.LogDebug("Received " + message + " TOO EARLY! Expected " + m_windowStart);
                return;
            }

            m_earlyReceived.Set(message.m_sequenceNumber % m_windowSize, true);
            m_peer.LogVerbose("Received " + message + " WITHHOLDING, waiting for " + m_windowStart);
            m_withheldMessages[message.m_sequenceNumber % m_windowSize] = message;
        }
        internal override void ReceiveMessage(NetIncomingMessage message)
        {
            int nr = message.m_sequenceNumber;

            int relate = NetUtility.RelativeSequenceNumber(nr, m_windowStart);

            // ack no matter what
            m_connection.QueueAck(message.m_receivedMessageType, nr);

            if (relate == 0)
            {
                AdvanceWindow();
                m_peer.ReleaseMessage(message);
                return;
            }

            if (relate < 0)
            {
                m_peer.LogVerbose("Received message #" + message.m_sequenceNumber + " DROPPING LATE or DUPE");
                return;
            }

            // relate > 0 = early message
            if (relate > m_windowSize)
            {
                // too early message!
                m_peer.LogDebug("Received " + message + " TOO EARLY! Expected " + m_windowStart);
                return;
            }

            // ok
            m_windowStart = (m_windowStart + relate) % NetConstants.NumSequenceNumbers;
            m_peer.ReleaseMessage(message);
            return;
        }
Example #4
0
        internal override void ReceiveMessage(NetIncomingMessage msg)
        {
            int nr = msg.m_sequenceNumber;

            // ack no matter what
            m_connection.QueueAck(msg.m_receivedMessageType, nr);

            int relate = NetUtility.RelativeSequenceNumber(nr, m_lastReceivedSequenceNumber);

            if (relate < 0)
            {
                return; // drop if late
            }
            m_lastReceivedSequenceNumber = nr;
            m_peer.ReleaseMessage(msg);
        }
        internal override void ReceiveMessage(NetIncomingMessage message)
        {
            int relate = NetUtility.RelativeSequenceNumber(message.m_sequenceNumber, m_windowStart);

            // ack no matter what
            m_connection.QueueAck(message.m_receivedMessageType, message.m_sequenceNumber);

            if (relate == 0)
            {
                AdvanceWindow();
                m_peer.ReleaseMessage(message);

                // release withheld messages
                int nextSeqNr = (message.m_sequenceNumber + 1) % NetConstants.NumSequenceNumbers;

                while (m_earlyReceived[nextSeqNr % m_windowSize])
                {
                    AdvanceWindow();
                    nextSeqNr++;
                }

                return;
            }

            if (relate < 0)
            {
                // duplicate
                m_peer.LogVerbose("Received message #" + message.m_sequenceNumber + " DROPPING DUPLICATE");
                return;
            }

            // relate > 0 = early message
            if (relate > m_windowSize)
            {
                // too early message!
                m_peer.LogDebug("Received " + message + " TOO EARLY! Expected " + m_windowStart);
                return;
            }

            m_earlyReceived.Set(message.m_sequenceNumber % m_windowSize, true);

            m_peer.ReleaseMessage(message);
        }
        internal override void ReceiveMessage(NetIncomingMessage msg)
        {
            int nr = msg.m_sequenceNumber;

            // ack no matter what
            m_connection.QueueAck(msg.m_receivedMessageType, nr);

            int relate = NetUtility.RelativeSequenceNumber(nr, m_lastReceivedSequenceNumber + 1);

            if (relate < 0)
            {
                m_connection.m_statistics.MessageDropped();
                m_peer.LogVerbose("Received message #" + nr + " DROPPING DUPLICATE");
                return;                 // drop if late
            }

            m_lastReceivedSequenceNumber = nr;
            m_peer.ReleaseMessage(msg);
        }
        // remoteWindowStart is remote expected sequence number; everything below this has arrived properly
        // seqNr is the actual nr received
        public override NetSocketResult ReceiveAcknowledge(TimeSpan now, int seqNr)
        {
            if (!_doFlowControl)
            {
                // we have no use for acks on this channel since we don't respect the window anyway
                _connection.Peer.LogWarning(new NetLogMessage(NetLogCode.SuppressedUnreliableAck, endPoint: _connection));
                return(new NetSocketResult(true, false));
            }

            // late (dupe), on time or early ack?
            int relate = NetUtility.RelativeSequenceNumber(seqNr, _windowStart);

            if (relate < 0)
            {
                //m_connection.m_peer.LogDebug("Received late/dupe ack for #" + seqNr);
                return(new NetSocketResult(true, false)); // late/duplicate ack
            }

            if (relate == 0)
            {
                //m_connection.m_peer.LogDebug("Received right-on-time ack for #" + seqNr);

                // ack arrived right on time
                LidgrenException.Assert(seqNr == _windowStart);

                _receivedAcks[_windowStart] = false;
                _windowStart = NetUtility.PowOf2Mod(_windowStart + 1, NetConstants.SequenceNumbers);
                return(new NetSocketResult(true, false));
            }

            // Advance window to this position
            _receivedAcks[seqNr] = true;

            while (_windowStart != seqNr)
            {
                _receivedAcks[_windowStart] = false;
                _windowStart = NetUtility.PowOf2Mod(_windowStart + 1, NetConstants.SequenceNumbers);
            }

            return(new NetSocketResult(true, false));
        }
Example #8
0
        // remoteWindowStart is remote expected sequence number; everything below this has arrived properly
        // seqNr is the actual nr received
        internal override void ReceiveAcknowledge(double now, int seqNr)
        {
            if (m_doFlowControl == false)
            {
                // we have no use for acks on this channel since we don't respect the window anyway
                m_connection.m_peer.LogVerbose("SuppressUnreliableUnorderedAcks sender/receiver mismatch!");
                return;
            }

            // late (dupe), on time or early ack?
            int relate = NetUtility.RelativeSequenceNumber(seqNr, m_windowStart);

            if (relate < 0)
            {
                //m_connection.m_peer.LogDebug("Received late/dupe ack for #" + seqNr);
                return;                 // late/duplicate ack
            }

            if (relate == 0)
            {
                //m_connection.m_peer.LogDebug("Received right-on-time ack for #" + seqNr);

                // ack arrived right on time
                NetException.Assert(seqNr == m_windowStart);

                m_receivedAcks[m_windowStart] = false;
                m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;

                return;
            }

            // Advance window to this position
            m_receivedAcks[seqNr] = true;

            while (m_windowStart != seqNr)
            {
                m_receivedAcks[m_windowStart] = false;
                m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;
            }
        }
        // remoteWindowStart is remote expected sequence number; everything below this has arrived properly
        // seqNr is the actual nr received
        internal override void ReceiveAcknowledge(float now, int seqNr)
        {
            // late (dupe), on time or early ack?
            int relate = NetUtility.RelativeSequenceNumber(seqNr, m_windowStart);

            if (relate < 0)
            {
                //m_connection.m_peer.LogDebug("Received late/dupe ack for #" + seqNr);
                return; // late/duplicate ack
            }

            if (relate == 0)
            {
                //m_connection.m_peer.LogDebug("Received right-on-time ack for #" + seqNr);

                // ack arrived right on time
                NetException.Assert(seqNr == m_windowStart);

                m_receivedAcks[m_windowStart] = false;
                DestoreMessage(m_windowStart % m_windowSize);
                m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;

                // advance window if we already have early acks
                while (m_receivedAcks.Get(m_windowStart))
                {
                    //m_connection.m_peer.LogDebug("Using early ack for #" + m_windowStart + "...");
                    m_receivedAcks[m_windowStart] = false;
                    DestoreMessage(m_windowStart % m_windowSize);

                    NetException.Assert(m_storedMessages[m_windowStart % m_windowSize].Message == null); // should already be destored
                    m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;
                    //m_connection.m_peer.LogDebug("Advancing window to #" + m_windowStart);
                }

                return;
            }

            //
            // early ack... (if it has been sent!)
            //
            // If it has been sent either the m_windowStart message was lost
            // ... or the ack for that message was lost
            //

            //m_connection.m_peer.LogDebug("Received early ack for #" + seqNr);

            int sendRelate = NetUtility.RelativeSequenceNumber(seqNr, m_sendStart);

            if (sendRelate <= 0)
            {
                // yes, we've sent this message - it's an early (but valid) ack
                if (m_receivedAcks[seqNr])
                {
                    // we've already destored/been acked for this message
                }
                else
                {
                    m_receivedAcks[seqNr] = true;
                }
            }
            else if (sendRelate > 0)
            {
                // This is a bug in Lidgren (that I don't have time to mess around with) (-AR)
                // Disconnecting causes the channel to Reset() (resets pending sequence number), but somehow we still receive acks.
                // (Status gets set to Disconnected after the Reset, but seems to all be on the network thread, so not a race condition)
                if (m_connection == null || m_connection.m_status == NetConnectionStatus.Disconnected)
                {
                    return; // Let's not call NetException.Assert!
                }
                // uh... we haven't sent this message yet? Weird, dupe or error...
                NetException.Assert(false, "Got ack for message not yet sent?");
                return;
            }

            // Ok, lets resend all missing acks
            int rnr = seqNr;

            do
            {
                rnr--;
                if (rnr < 0)
                {
                    rnr = NetConstants.NumSequenceNumbers - 1;
                }

                if (m_receivedAcks[rnr])
                {
                    // m_connection.m_peer.LogDebug("Not resending #" + rnr + " (since we got ack)");
                }
                else
                {
                    int slot = rnr % m_windowSize;
                    NetException.Assert(m_storedMessages[slot].Message != null);
                    if (m_storedMessages[slot].NumSent == 1)
                    {
                        // just sent once; resend immediately since we found gap in ack sequence
                        NetOutgoingMessage rmsg = m_storedMessages[slot].Message;
                        //m_connection.m_peer.LogVerbose("Resending #" + rnr + " (" + rmsg + ")");

                        if (now - m_storedMessages[slot].LastSent < (m_resendDelay * 0.35f))
                        {
                            // already resent recently
                        }
                        else
                        {
                            m_storedMessages[slot].LastSent = now;
                            m_storedMessages[slot].NumSent++;
                            m_connection.m_statistics.MessageResent(MessageResendReason.HoleInSequence);
                            m_connection.QueueSendMessage(rmsg, rnr);
                        }
                    }
                }
            } while (rnr != m_windowStart);
        }
        // remoteWindowStart is remote expected sequence number; everything below this has arrived properly
        // seqNr is the actual nr received
        internal override void ReceiveAcknowledge(double now, int seqNr)
        {
            // late (dupe), on time or early ack?
            int relate = NetUtility.RelativeSequenceNumber(seqNr, m_windowStart);

            if (relate < 0)
            {
                //m_connection.m_peer.LogDebug("Received late/dupe ack for #" + seqNr);
                return;                 // late/duplicate ack
            }

            if (relate == 0)
            {
                //m_connection.m_peer.LogDebug("Received right-on-time ack for #" + seqNr);

                // ack arrived right on time
                NetException.Assert(seqNr == m_windowStart);

                bool resetTimeout;
                m_receivedAcks[m_windowStart] = false;
                DestoreMessage(now, m_windowStart % m_windowSize, out resetTimeout);
                m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;

                // advance window if we already have early acks
                while (m_receivedAcks.Get(m_windowStart))
                {
                    //m_connection.m_peer.LogDebug("Using early ack for #" + m_windowStart + "...");
                    m_receivedAcks[m_windowStart] = false;
                    bool rt;
                    DestoreMessage(now, m_windowStart % m_windowSize, out rt);
                    resetTimeout |= rt;

                    NetException.Assert(m_storedMessages[m_windowStart % m_windowSize].Message == null);                     // should already be destored
                    m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;
                    //m_connection.m_peer.LogDebug("Advancing window to #" + m_windowStart);
                }
                if (resetTimeout)
                {
                    m_connection.ResetTimeout(now);
                }
                return;
            }

            //
            // early ack... (if it has been sent!)
            //
            // If it has been sent either the m_windowStart message was lost
            // ... or the ack for that message was lost
            //

            //m_connection.m_peer.LogDebug("Received early ack for #" + seqNr);

            int sendRelate = NetUtility.RelativeSequenceNumber(seqNr, m_sendStart);

            if (sendRelate <= 0)
            {
                // yes, we've sent this message - it's an early (but valid) ack
                if (m_receivedAcks[seqNr])
                {
                    // we've already destored/been acked for this message
                }
                else
                {
                    m_receivedAcks[seqNr] = true;
                }
            }
            else if (sendRelate > 0)
            {
                // uh... we haven't sent this message yet? Weird, dupe or error...
                NetException.Assert(false, "Got ack for message not yet sent?");
                return;
            }

            // Ok, lets resend all missing acks
            int rnr = seqNr;

            do
            {
                rnr--;
                if (rnr < 0)
                {
                    rnr = NetConstants.NumSequenceNumbers - 1;
                }

                if (m_receivedAcks[rnr])
                {
                    // m_connection.m_peer.LogDebug("Not resending #" + rnr + " (since we got ack)");
                }
                else
                {
                    int slot = rnr % m_windowSize;
                    NetException.Assert(m_storedMessages[slot].Message != null);
                    if (m_storedMessages[slot].NumSent == 1)
                    {
                        // just sent once; resend immediately since we found gap in ack sequence
                        NetOutgoingMessage rmsg = m_storedMessages[slot].Message;
                        //m_connection.m_peer.LogVerbose("Resending #" + rnr + " (" + rmsg + ")");

                        if (now - m_storedMessages[slot].LastSent < (m_resendDelay * 0.35))
                        {
                            // already resent recently
                        }
                        else
                        {
                            m_storedMessages[slot].LastSent = now;
                            m_storedMessages[slot].NumSent++;
                            m_connection.m_statistics.MessageResent(MessageResendReason.HoleInSequence);
                            Interlocked.Increment(ref rmsg.m_recyclingCount);                             // increment this since it's being decremented in QueueSendMessage
                            m_connection.QueueSendMessage(rmsg, rnr);
                        }
                    }
                }
            } while (rnr != m_windowStart);
        }
        // remoteWindowStart is remote expected sequence number; everything below this has arrived properly
        // seqNr is the actual nr received
        internal override void ReceiveAcknowledge(float now, int seqNr)
        {
            // late (dupe), on time or early ack?
            int relate = NetUtility.RelativeSequenceNumber(seqNr, m_windowStart);

            if (relate < 0)
            {
                return;                 // late/duplicate ack
            }
            if (relate == 0)
            {
                // ack arrived right on time
                NetException.Assert(seqNr == m_windowStart);

                m_receivedAcks[m_windowStart] = false;
                DestoreMessage(m_windowStart % m_windowSize);
                m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;

                // advance window if we already have early acks
                while (m_receivedAcks.Get(m_windowStart))
                {
                    m_receivedAcks[m_windowStart] = false;
                    DestoreMessage(m_windowStart % m_windowSize);

                    NetException.Assert(m_storedMessages[m_windowStart % m_windowSize].Message == null);                     // should already be destored
                    m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;
                }

                return;
            }

            //
            // early ack... (if it has been sent!)
            //
            // If it has been sent either the m_windowStart message was lost
            // ... or the ack for that message was lost
            //

            int sendRelate = NetUtility.RelativeSequenceNumber(seqNr, m_sendStart);

            if (sendRelate <= 0)
            {
                // yes, we've sent this message - it's an early (but valid) ack
                if (m_receivedAcks[seqNr])
                {
                    // we've already destored/been acked for this message
                }
                else
                {
                    m_receivedAcks[seqNr] = true;
                }
            }
            else if (sendRelate > 0)
            {
                // uh... we haven't sent this message yet? Weird, dupe or error...
                NetException.Assert(false, "Got ack for message not yet sent?");
                return;
            }

            // Ok, lets resend all missing acks
            int rnr = seqNr;

            do
            {
                rnr--;
                if (rnr < 0)
                {
                    rnr = NetConstants.NumSequenceNumbers - 1;
                }

                if (!m_receivedAcks[rnr])
                {
                    int slot = rnr % m_windowSize;
                    NetException.Assert(m_storedMessages[slot].Message != null);
                    if (m_storedMessages[slot].NumSent == 1)
                    {
                        // just sent once; resend immediately since we found gap in ack sequence
                        NetOutgoingMessage rmsg = m_storedMessages[slot].Message;

                        if (now - m_storedMessages[slot].LastSent < (m_resendDelay * 0.35f))
                        {
                            // already resent recently
                        }
                        else
                        {
                            m_storedMessages[slot].LastSent = now;
                            m_storedMessages[slot].NumSent++;
                            m_connection.m_statistics.MessageResent(MessageResendReason.HoleInSequence);
                            m_connection.QueueSendMessage(rmsg, rnr);
                        }
                    }
                }
            } while (rnr != m_windowStart);
        }