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)); }
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); }
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); }
/// <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); }