Пример #1
0
        /// <summary>
        /// Returns whether this message did acknowledge the specified sequence number.
        /// </summary>
        /// <param name="sequence">
        /// The sequence number to check.
        /// </param>
        /// <returns>
        /// Whether this message acknowledges the specified sequence number.
        /// </returns>
        public bool DidAck(uint sequence)
        {
            if (!this.HasAck(sequence))
            {
                return(false);
            }

            var diff = (MxUtility.UIntBitsize - MxUtility.GetSequenceNumberDifference(this.Ack, sequence)) - 1;

            return(((this.AckBitfield & (0x1u << (int)diff)) >> (int)diff) == 0x1);
        }
Пример #2
0
        /// <summary>
        /// Handles the packets currently queued in the receive queue.
        /// </summary>
        private void PerformReceive()
        {
            if (this.m_ReceivedPackets.Count == 0)
            {
                this.m_DisconnectAccumulator++;
                return;
            }

            foreach (var packet in this.m_ReceivedPackets)
            {
                this.m_DisconnectAccumulator = 0;

                using (var memory = new MemoryStream(packet))
                {
                    var serializer = new MxMessageSerializer();
                    var message    = (MxMessage)serializer.Deserialize(memory, null, typeof(MxMessage));

                    if (message.Payloads == null)
                    {
                        message.Payloads = new MxPayload[0];
                    }

                    foreach (var payload in message.Payloads.Where(payload => payload.Data == null))
                    {
                        payload.Data = new byte[0];
                    }

                    var difference = MxUtility.GetSequenceNumberDifference(
                        message.Sequence,
                        this.m_RemoteSequenceNumber);

                    if (difference > 0)
                    {
                        // Calculate the difference between the old
                        // sequence number and the new sequence number
                        // we need to push "false" into the queue for
                        // the missing messages.
                        for (var i = 0; i < difference - 1; i++)
                        {
                            this.PushIntoQueue(this.m_ReceiveQueue, false);
                        }

                        // We push the "true" value for this message after
                        // firing the OnReceived event (so we can not acknowledge
                        // it if the event callbacks do not want us to).

                        // Check based on items in the queue.
                        foreach (var kv in this.m_SendQueue.ToArray())
                        {
                            var idx = kv.Key;

                            if (!message.HasAck(idx))
                            {
                                // We aren't acking this message yet.
                                continue;
                            }

                            if (message.DidAck(idx))
                            {
                                // We already checked for existance of the key above.
                                var sendTimestamp = this.m_SendQueue[idx];
                                var rtt           = this.GetUnixTimestamp() - sendTimestamp;
                                this.PushIntoQueue(this.m_RTTQueue, rtt);

                                var payloads = this.m_SendMessageQueue[idx];
                                this.m_SendQueue.Remove(idx);
                                this.m_SendMessageQueue.Remove(idx);

                                this.Latency = rtt;

                                foreach (var payload in payloads.Value)
                                {
                                    this.OnMessageAcknowledged(
                                        new MxMessageEventArgs {
                                        Client = this, Payload = payload, ProtocolID = payloads.Key
                                    });
                                }
                            }
                            else
                            {
                                this.HandleLostMessage(idx);
                            }
                        }

                        foreach (var kv in this.m_SendQueue.ToArray())
                        {
                            var idx = kv.Key;

                            if (MxUtility.GetSequenceNumberDifference(message.Ack - MxUtility.UIntBitsize, idx) > 0)
                            {
                                this.HandleLostMessage(idx);
                            }
                        }

                        this.m_RemoteSequenceNumber = message.Sequence;

                        var doNotAcknowledge = false;

                        foreach (var payload in message.Payloads)
                        {
                            var eventArgs = new MxMessageReceiveEventArgs {
                                Client = this, Payload = payload.Data, DoNotAcknowledge = doNotAcknowledge, ProtocolID = message.ProtocolID
                            };
                            this.OnMessageReceived(eventArgs);
                            doNotAcknowledge = eventArgs.DoNotAcknowledge;
                        }

                        if (!doNotAcknowledge)
                        {
                            this.PushIntoQueue(this.m_ReceiveQueue, true);
                        }
                    }
                }
            }

            this.m_ReceivedPackets.Clear();
        }
Пример #3
0
 /// <summary>
 /// Returns whether or not this message can acknowledge the specified sequence number.
 /// This will return false if the specified sequence number is more than 32 messages ago.
 /// </summary>
 /// <param name="sequence">
 /// The sequence number to check.
 /// </param>
 /// <returns>
 /// Whether this message can acknowledge the specified sequence number.
 /// </returns>
 public bool HasAck(uint sequence)
 {
     return(MxUtility.GetSequenceNumberDifference(this.Ack, sequence) >= 0 &&
            MxUtility.GetSequenceNumberDifference(this.Ack, sequence) < MxUtility.UIntBitsize);
 }