Exemple #1
0
 public byte[] GetPayload(ChunkedMessage message, bool clearAfterRetrieval = true)
 {
     if (message == null)
     {
         return(null);
     }
     return(GetPayload(message.NetworkMessageHeader.PublisherID.Value,
                       message.PayloadHeader.DataSetWriterID,
                       message.MessageSequenceNumber,
                       clearAfterRetrieval
                       ));
 }
        public void MetaMessageFirstChunk()
        {
            string chunkFilePath = Path.Combine(TestDataFolder, "01.meta.chunk.bin");

            byte[]         rawMessage = File.ReadAllBytes(chunkFilePath);
            NetworkMessage message    = null;

            Assert.DoesNotThrow(() => message = Decoder.ParseBinaryMessage(rawMessage));
            Assert.That(message, Is.Not.Null);
            Assert.That(message.NetworkMessageHeader.PublisherID.Value, Is.EqualTo(PublisherID));
            Assert.That(message, Is.InstanceOf(typeof(ChunkedMessage)));
            ChunkedMessage chunkedMessage = (ChunkedMessage)message;

            Assert.That(chunkedMessage.ChunkOffset, Is.EqualTo(0));
            Assert.That(chunkedMessage.TotalSize, Is.EqualTo(21189));
        }
Exemple #3
0
        private List <byte[]> GetChunkedFrame(uint chunkSize, DataFrame dataFrame)
        {
            byte[] rawData;
            using (MemoryStream stream = new MemoryStream())
            {
                dataFrame.EncodeChunk(stream);
                rawData = stream.ToArray();
            }
            List <byte[]> rawChunks = new List <byte[]>();

            if (chunkSize == 0)
            {
                using (MemoryStream completeOutputStream = new MemoryStream())
                {
                    dataFrame.NetworkMessageHeader.Encode(completeOutputStream);
                    dataFrame.PayloadHeader.Encode(completeOutputStream);
                    completeOutputStream.Write(rawData, 0, rawData.Length);
                    rawChunks.Add(completeOutputStream.ToArray());
                }
            }
            else
            {
                for (uint i = 0; i < rawData.LongLength; i += chunkSize)
                {
                    NetworkMessageHeader networkHeader  = GetChunkedNetworkHeader();
                    ChunkedMessage       chunkedMessage = new ChunkedMessage();
                    chunkedMessage.PayloadHeader = new ChunkedPayloadHeader();
                    chunkedMessage.PayloadHeader.DataSetWriterID = dataFrame.PayloadHeader.DataSetWriterID[0];
                    chunkedMessage.NetworkMessageHeader          = networkHeader;
                    chunkedMessage.TotalSize             = (uint)rawData.LongLength;
                    chunkedMessage.ChunkOffset           = i;
                    chunkedMessage.MessageSequenceNumber = dataFrame.DataSetMessageSequenceNumber;

                    // Check if can copy a "full" chunk or just the remaining elements of the array.
                    long length = Math.Min(chunkSize, rawData.LongLength - chunkedMessage.ChunkOffset);
                    chunkedMessage.ChunkData = new byte[length];
                    Array.Copy(rawData, i, chunkedMessage.ChunkData, 0, length);
                    using (MemoryStream stream = new MemoryStream())
                    {
                        chunkedMessage.Encode(stream);
                        rawChunks.Add(stream.ToArray());
                    }
                }
            }
            return(rawChunks);
        }
Exemple #4
0
        public List <byte[]> GetChunkedMetaFrame(uint chunkSize, EncodingOptions options, ushort sequenceNumber)
        {
            byte[]        rawMessage = GetEncodedMetaFrame(options, sequenceNumber, false);
            List <byte[]> rawChunks  = new List <byte[]>();

            if (chunkSize == 0)
            {
                using (MemoryStream completeOutputStream = new MemoryStream())
                {
                    m_MetaFrame.NetworkMessageHeader.Encode(completeOutputStream);
                    completeOutputStream.Write(rawMessage, 0, rawMessage.Length);
                    rawChunks.Add(completeOutputStream.ToArray());
                }
            }
            else
            {
                for (uint i = 0; i < rawMessage.LongLength; i += chunkSize)
                {
                    NetworkMessageHeader networkHeader  = GetChunkedNetworkHeader(true);
                    ChunkedMessage       chunkedMessage = new ChunkedMessage();
                    chunkedMessage.PayloadHeader = new ChunkedPayloadHeader();

                    //chunkedMessage.PayloadHeader.DataSetWriterID = m_MetaFrame.DataSetWriterID;
                    chunkedMessage.NetworkMessageHeader  = networkHeader;
                    chunkedMessage.TotalSize             = (uint)rawMessage.LongLength;
                    chunkedMessage.ChunkOffset           = i;
                    chunkedMessage.MessageSequenceNumber = m_MetaFrame.SequenceNumber;

                    // Check if can copy a "full" chunk or just the remaining elements of the array.
                    long length = Math.Min(chunkSize, rawMessage.LongLength - chunkedMessage.ChunkOffset);
                    chunkedMessage.ChunkData = new byte[length];
                    Array.Copy(rawMessage, i, chunkedMessage.ChunkData, 0, length);
                    using (MemoryStream stream = new MemoryStream())
                    {
                        chunkedMessage.Encode(stream);
                        rawChunks.Add(stream.ToArray());
                    }
                }
            }
            return(rawChunks);
        }
        public virtual List <byte[]> GetChunkedMetaFrame(uint chunkSize)
        {
            if (m_MetaFrame == null || chunkSize == 0)
            {
                return(null);
            }
            byte[] rawMessage = null;
            using (MemoryStream outputStream = new MemoryStream())
            {
                m_MetaFrame.EncodeChunk(outputStream);
                rawMessage = outputStream.ToArray();
            }
            List <byte[]> rawChunks = new List <byte[]>();

            for (uint i = 0; i < rawMessage.LongLength; i += chunkSize)
            {
                NetworkMessageHeader networkHeader  = GetChunkedMetaNetworkHeader();
                ChunkedMessage       chunkedMessage = new ChunkedMessage();
                chunkedMessage.PayloadHeader = new ChunkedPayloadHeader();

                //chunkedMessage.PayloadHeader.DataSetWriterID = m_MetaFrame.DataSetWriterID;
                chunkedMessage.NetworkMessageHeader  = networkHeader;
                chunkedMessage.TotalSize             = (uint)rawMessage.LongLength;
                chunkedMessage.ChunkOffset           = i;
                chunkedMessage.MessageSequenceNumber = m_MetaFrame.SequenceNumber;

                // Check if can copy a "full" chunk or just the remaining elements of the array.
                long length = Math.Min(chunkSize, rawMessage.LongLength - chunkedMessage.ChunkOffset);
                chunkedMessage.ChunkData = new byte[length];
                Array.Copy(rawMessage, i, chunkedMessage.ChunkData, 0, length);
                using (MemoryStream stream = new MemoryStream())
                {
                    chunkedMessage.Encode(stream);
                    rawChunks.Add(stream.ToArray());
                }
            }
            return(rawChunks);
        }
Exemple #6
0
        /// <summary>
        ///     Store a chunk for the given Chunked Network Message.
        ///     The method returns true, if the provided chunk was the last missing element.
        ///     Otherwise false is returned.
        /// </summary>
        /// <param name="message"></param>
        /// <returns>true if all chunks are available, otherwise false.</returns>
        public bool Store(ChunkedMessage message)
        {
            string publisherID    = message.NetworkMessageHeader.PublisherID.Value;
            ushort writerID       = message.PayloadHeader.DataSetWriterID;
            ushort sequenceNumber = message.MessageSequenceNumber;
            Dictionary <ushort, ChunkStorage> sequenceStorage = GetSequenceStorage(publisherID, writerID);

            if (!sequenceStorage.TryGetValue(sequenceNumber, out ChunkStorage storage))
            {
                storage = new ChunkStorage
                {
                    TotalSize       = message.TotalSize,
                    PublisherID     = publisherID,
                    DataSetWriterID = sequenceNumber
                };
                sequenceStorage.Add(sequenceNumber, storage);
            }
            if (storage.TotalSize != message.TotalSize)
            {
                string text =
                    $"TotalSize mismatch for Publisher {publisherID} and Message Sequence {message.MessageSequenceNumber}: previous TotalSize: {storage.TotalSize} != {message.TotalSize}";
                Logger.Error(text);
                throw new ApplicationException(text);
            }
            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Storing chunk from Publisher {publisherID} with WriterID {writerID} and Sequence Number {sequenceNumber}. OffSet: {message.ChunkOffset}, TotalSize: {message.TotalSize}, ChunkSize: {message.ChunkData.Length}"
                             );
            }
            Chunk newChunk = new Chunk
            {
                Offset = message.ChunkOffset,
                Data   = message.ChunkData
            };

            return(storage.Add(newChunk));
        }
        /// <summary>
        ///     Parses a binary encoded OPC UA PubSub message.
        ///     In case a message was decoded successfully a <see cref="MessageDecoded" /> event is raised.
        /// </summary>
        /// <param name="payload">Binary payload which should be decoded.</param>
        /// <returns><see cref="NetworkMessage" />The decoded message or <c>null</c> if the decoding failed for any reason.</returns>
        public NetworkMessage ParseBinaryMessage(byte[] payload)
        {
            if (payload == null)
            {
                Logger.Warn("ParsePayload - payload == null");
                return(null);
            }
            if (payload.Length == 0)
            {
                Logger.Warn("ParsePayload - payload.Length == 0");
                return(null);
            }
            NetworkMessage parsedMessage = null;

            using (MemoryStream memoryStream = new MemoryStream(payload, false))
            {
                NetworkMessageHeader networkMessageHeader = NetworkMessageHeader.Decode(memoryStream);
                byte version = networkMessageHeader.ProtocolVersion;
                if (version != 1)
                {
                    Logger.Warn($"Not supported protocol version: {version}. Skipping message.");
                    return(null);
                }
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug($"Message\t\t[{networkMessageHeader.ExtendedFlags2.MessageType}]\t\tfrom: {networkMessageHeader.PublisherID}");
                }
                bool isChunkMessage = networkMessageHeader.ExtendedFlags2.Chunk;
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug($"Chunked Message: {isChunkMessage}");
                }
                if (isChunkMessage)
                {
                    ChunkedMessage chunkedMessage = ChunkedMessage.Decode(memoryStream);
                    if (chunkedMessage == null)
                    {
                        Logger.Error("Unable to parse chunked message.");
                    }
                    else
                    {
                        chunkedMessage.NetworkMessageHeader = networkMessageHeader;
                        if (m_ChunkManager.Store(chunkedMessage))
                        {
                            if (Logger.IsDebugEnabled)
                            {
                                Logger.Debug("All chunks received. Starting decoding of message.");
                            }
                            byte[] completeMessage = m_ChunkManager.GetPayload(chunkedMessage);
                            using (MemoryStream chunkedStream = new MemoryStream(completeMessage, false))
                            {
                                parsedMessage = GetSpecificMessage(networkMessageHeader, chunkedStream, chunkedMessage.PayloadHeader.DataSetWriterID);
                            }
                            if (Logger.IsDebugEnabled)
                            {
                                Logger.Debug(parsedMessage != null ? "Chunked message successfully decoded." : "Failed to decode chunked message.");
                            }
                        }
                        else
                        {
                            if (Logger.IsDebugEnabled)
                            {
                                Logger.Debug("Not all chunked received yet. Cannot decode message.");
                            }
                            parsedMessage = chunkedMessage;
                        }
                    }
                }
                else
                {
                    parsedMessage = GetSpecificMessage(networkMessageHeader, memoryStream);
                }

                // Ensure that we have at least the Network Message Header available.
                if (parsedMessage == null)
                {
                    parsedMessage = new NetworkMessage
                    {
                        NetworkMessageHeader = networkMessageHeader
                    };
                }
                else
                {
                    if (parsedMessage.NetworkMessageHeader == null)
                    {
                        parsedMessage.NetworkMessageHeader = networkMessageHeader;
                    }
                }

                // Because we might have modified the PublisherID,
                // the RawPayload is set to null to avoid inconsistencies.
                parsedMessage.RawPayload = null;
            }
            return(parsedMessage);
        }