Exemple #1
0
        /// <summary>
        /// Raise the MessageReceived event.
        /// </summary>
        /// <param name="e">
        /// The event arguments.
        /// </param>
        protected virtual void OnMessageReceived(MxMessageReceiveEventArgs e)
        {
            var handler = this.MessageReceived;

            if (handler != null)
            {
                handler(this, e);
            }
        }
Exemple #2
0
        /// <summary>
        /// Called when we have received a fragment from the underlying client.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="mxMessageEventArgs">
        /// The message event args.
        /// </param>
        private void ClientOnMessageReceived(object sender, MxMessageReceiveEventArgs mxMessageEventArgs)
        {
            if (mxMessageEventArgs.ProtocolID != MxMessage.ReliableProtocol)
            {
                return;
            }

            var data = mxMessageEventArgs.Payload;

            // Format of a packet is:
            // Byte 0 - 3: message ID
            // Byte 4 - 5: length
            // Byte 6: current index
            // Byte 7: total packets
            // Remaining bytes are the fragment data
            var messageID    = BitConverter.ToInt32(data, 0);
            var length       = BitConverter.ToUInt16(data, 4);
            var currentIndex = (int)data[6];
            var totalPackets = (int)data[7];

            if (!this.m_ActiveReceiveMessages.ContainsKey(messageID))
            {
                // Add a new entry in the active receive messages dictionary.
                this.m_ActiveReceiveMessages.Add(
                    messageID,
                    new MxReliabilityReceiveState(messageID, totalPackets));
            }

            // Check for invalid payload.
            if ((length - 1) + DataOffset >= data.Length)
            {
                var errorMessage =
                    "The payload data received had an invalid length for the " +
                    "data that was present. ";
                errorMessage += "\r\n";
                errorMessage += "\r\n";
                errorMessage += "Client Endpoint: " + mxMessageEventArgs.Client.Endpoint + "\r\n";
                errorMessage += "Message ID: " + messageID + "\r\n";
                errorMessage += "Message Protocol: " + mxMessageEventArgs.ProtocolID + "\r\n";
                errorMessage += "Length: " + length + "\r\n";
                errorMessage += "Current Index: " + currentIndex + "\r\n";
                errorMessage += "Total Packets: " + totalPackets + "\r\n";
                errorMessage += "Payload Length: " + data.Length + "\r\n";
                errorMessage += "Payload Length minus Offset: " + (data.Length - DataOffset) + "\r\n";

                var exception = new InvalidDataException(errorMessage);
                exception.Data.Add("Payload", data);

                throw exception;
            }

            // Extract the fragment data.
            var fragmentData = new byte[length];

            for (var i = 0; i < length; i++)
            {
                fragmentData[i] = data[i + DataOffset];
            }

            // Set the fragment data into the received message.
            this.m_ActiveReceiveMessages[messageID].SetFragment(currentIndex, new Fragment(fragmentData, FragmentStatus.Received));

            // Perform the receive update to fire events and finalize state if we have all the fragments.
            this.UpdateReceive();
        }
Exemple #3
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();
        }
        /// <summary>
        /// Called when we have received a fragment from the underlying client.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="mxMessageEventArgs">
        /// The message event args.
        /// </param>
        private void ClientOnMessageReceived(object sender, MxMessageReceiveEventArgs mxMessageEventArgs)
        {
            if (mxMessageEventArgs.ProtocolID != MxMessage.ReliableProtocol)
            {
                return;
            }

            var data = mxMessageEventArgs.Payload;

            // Format of a packet is:
            // Byte 0 - 3: message ID
            // Byte 4 - 5: length
            // Byte 6: current index
            // Byte 7: total packets
            // Remaining bytes are the fragment data
            var messageID = BitConverter.ToInt32(data, 0);
            var length = BitConverter.ToUInt16(data, 4);
            var currentIndex = (int)data[6];
            var totalPackets = (int)data[7];

            if (!this.m_ActiveReceiveMessages.ContainsKey(messageID))
            {
                // Add a new entry in the active receive messages dictionary.
                this.m_ActiveReceiveMessages.Add(
                    messageID,
                    new MxReliabilityReceiveState(messageID, totalPackets));
            }

            // Check for invalid payload.
            if ((length - 1) + DataOffset >= data.Length)
            {
                var errorMessage = 
                    "The payload data received had an invalid length for the " +
                    "data that was present. ";
                errorMessage += "\r\n";
                errorMessage += "\r\n";
                errorMessage += "Client Endpoint: " + mxMessageEventArgs.Client.Endpoint + "\r\n";
                errorMessage += "Message ID: " + messageID + "\r\n";
                errorMessage += "Message Protocol: " + mxMessageEventArgs.ProtocolID + "\r\n";
                errorMessage += "Length: " + length + "\r\n";
                errorMessage += "Current Index: " + currentIndex + "\r\n";
                errorMessage += "Total Packets: " + totalPackets + "\r\n";
                errorMessage += "Payload Length: " + data.Length + "\r\n";
                errorMessage += "Payload Length minus Offset: " + (data.Length - DataOffset) + "\r\n";

                var exception = new InvalidDataException(errorMessage);
                exception.Data.Add("Payload", data);

                throw exception;
            }

            // Extract the fragment data.
            var fragmentData = new byte[length];
            for (var i = 0; i < length; i++)
            {
                fragmentData[i] = data[i + DataOffset];
            }

            // Set the fragment data into the received message.
            this.m_ActiveReceiveMessages[messageID].SetFragment(currentIndex, new Fragment(fragmentData, FragmentStatus.Received));

            // Perform the receive update to fire events and finalize state if we have all the fragments.
            this.UpdateReceive();
        }