示例#1
0
 internal abstract NetSendResult Enqueue(NetOutgoingMessage message);
示例#2
0
        // 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;
                    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
                {
                    DestoreMessage(seqNr % m_windowSize);
                    m_receivedAcks[seqNr] = true;
                }
            }
            else if (sendRelate > 0)
            {
                // uh... we haven't sent this message yet? Weird, dupe or error...
                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);
        }