// Static Methods // Cumulates frame images internal static void CumulateFrameImage(CommonFrameHeader parsedFrameHeader, byte[] buffer, int offset, ref FrameImageCollector frameImages) { // If this is the first frame, cumulate all partial frames together as one complete frame if (parsedFrameHeader.IsFirstFrame) { frameImages = new FrameImageCollector(); } try { // Append next frame image frameImages.AppendFrameImage(buffer, offset, parsedFrameHeader.FrameLength); } catch { // Stop accumulation if CRC check fails frameImages = null; throw; } // Store a reference to frame image collection in common header state so configuration frame // can be parsed from entire combined binary image collection when last frame is received parsedFrameHeader.FrameImages = frameImages; // Clear local reference to frame image collection if this is the last frame if (parsedFrameHeader.IsLastFrame) { frameImages = null; } }
/// <summary> /// Creates a new <see cref="ConfigurationFrame"/> from serialization parameters. /// </summary> /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param> /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param> protected ConfigurationFrame(SerializationInfo info, StreamingContext context) : base(info, context) { // Deserialize configuration frame m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader)); m_idCode = info.GetUInt64("idCode64Bit"); }
/// <summary> /// Raises the <see cref="FrameParserBase{TypeIndentifier}.ReceivedHeaderFrame"/> event. /// </summary> /// <param name="frame"><see cref="IHeaderFrame"/> to send to <see cref="FrameParserBase{TypeIndentifier}.ReceivedHeaderFrame"/> event.</param> protected override void OnReceivedHeaderFrame(IHeaderFrame frame) { // IEEE 1344 header frames can span multiple frame images, so we don't allow base class to raise this event until all frames have been assembled... ISupportFrameImage <FrameType> frameImage = frame as ISupportFrameImage <FrameType>; if (frameImage != null) { CommonFrameHeader commonHeader = frameImage.CommonHeader as CommonFrameHeader; if (commonHeader != null && commonHeader.IsLastFrame) { base.OnReceivedHeaderFrame(frame); } } }
/// <summary> /// Parses a common header instance that implements <see cref="ICommonHeader{TTypeIdentifier}"/> for the output type represented /// in the binary image. /// </summary> /// <param name="buffer">Buffer containing data to parse.</param> /// <param name="offset">Offset index into buffer that represents where to start parsing.</param> /// <param name="length">Maximum length of valid data from offset.</param> /// <returns>The <see cref="ICommonHeader{TTypeIdentifier}"/> which includes a type ID for the <see cref="Type"/> to be parsed.</returns> /// <remarks> /// <para> /// Derived classes need to provide a common header instance (i.e., class that implements <see cref="ICommonHeader{TTypeIdentifier}"/>) /// for the output types; this will primarily include an ID of the <see cref="Type"/> that the data image represents. This parsing is /// only for common header information, actual parsing will be handled by output type via its <see cref="ISupportBinaryImage.ParseBinaryImage"/> /// method. This header image should also be used to add needed complex state information about the output type being parsed if needed. /// </para> /// <para> /// If there is not enough buffer available to parse common header (as determined by <paramref name="length"/>), return null. Also, if /// the protocol allows frame length to be determined at the time common header is being parsed and there is not enough buffer to parse /// the entire frame, it will be optimal to prevent further parsing by returning null. /// </para> /// </remarks> protected override ICommonHeader <FrameType> ParseCommonHeader(byte[] buffer, int offset, int length) { // See if there is enough data in the buffer to parse the common frame header. // Note that in order to get status flags (which contain frame length), we need at least two more bytes if (length >= CommonFrameHeader.FixedLength + 2) { // Parse common frame header CommonFrameHeader parsedFrameHeader = new CommonFrameHeader(buffer, offset); // As an optimization, we also make sure entire frame buffer image is available to be parsed - by doing this // we eliminate the need to validate length on all subsequent data elements that comprise the frame if (length >= parsedFrameHeader.FrameLength) { // Expose the frame buffer image in case client needs this data for any reason OnReceivedFrameBufferImage(parsedFrameHeader.FrameType, buffer, offset, parsedFrameHeader.FrameLength); // Handle special parsing states switch (parsedFrameHeader.TypeID) { case FrameType.DataFrame: // Assign data frame parsing state parsedFrameHeader.State = new DataFrameParsingState(parsedFrameHeader.FrameLength, m_configurationFrame, DataCell.CreateNewCell, TrustHeaderLength, ValidateDataFrameCheckSum); break; case FrameType.ConfigurationFrame: // Assign configuration frame parsing state (note that IEEE 1344 only supports a single device, hence 1 cell) parsedFrameHeader.State = new ConfigurationFrameParsingState(parsedFrameHeader.FrameLength, ConfigurationCell.CreateNewCell, TrustHeaderLength, ValidateConfigurationFrameCheckSum, 1); // Cumulate configuration frame images... CumulateFrameImage(parsedFrameHeader, buffer, offset, ref m_configurationFrameImages); break; case FrameType.HeaderFrame: // Assign header frame parsing state parsedFrameHeader.State = new HeaderFrameParsingState(parsedFrameHeader.FrameLength, parsedFrameHeader.DataLength, TrustHeaderLength, ValidateHeaderFrameCheckSum); // Cumulate header frame images... CumulateFrameImage(parsedFrameHeader, buffer, offset, ref m_headerFrameImages); break; } return(parsedFrameHeader); } } return(null); }
/// <summary> /// Raises the <see cref="FrameParserBase{TypeIndentifier}.ReceivedConfigurationFrame"/> event. /// </summary> /// <param name="frame"><see cref="IConfigurationFrame"/> to send to <see cref="FrameParserBase{TypeIndentifier}.ReceivedConfigurationFrame"/> event.</param> protected override void OnReceivedConfigurationFrame(IConfigurationFrame frame) { // IEEE 1344 configuration frames can span multiple frame images, so we don't allow base class to raise this event until all frames have been assembled... ISupportFrameImage <FrameType> frameImage = frame as ISupportFrameImage <FrameType>; if (frameImage != null) { CommonFrameHeader commonHeader = frameImage.CommonHeader as CommonFrameHeader; if (commonHeader != null && commonHeader.IsLastFrame) { base.OnReceivedConfigurationFrame(frame); // Cache new configuration frame for parsing subsequent data frames... ConfigurationFrame configurationFrame = frame as ConfigurationFrame; if (configurationFrame != null) { m_configurationFrame = configurationFrame; } } } }
/// <summary> /// Appends the current frame image to the frame image collection. /// </summary> /// <param name="buffer">A <see cref="byte"/> array to append to the collection.</param> /// <param name="length">An <see cref="int"/> value indicating the number of bytes to read from the <paramref name="buffer"/>.</param> /// <param name="offset">An <see cref="int"/> value indicating the offset to read from.</param> public void AppendFrameImage(byte[] buffer, int offset, int length) { // Validate CRC of frame image being appended if (!CommonFrameHeader.ChecksumIsValid(buffer, offset, length)) { throw new InvalidOperationException("Invalid binary image detected - check sum of individual IEEE 1344 interleaved frame transmission did not match"); } // Include initial header in new stream... if (m_frameQueue.Length == 0) { m_frameQueue.Write(buffer, offset, CommonFrameHeader.FixedLength); } // Skip past header offset += CommonFrameHeader.FixedLength; // Include frame image m_frameQueue.Write(buffer, offset, length - CommonFrameHeader.FixedLength); // Track total frame images Count++; }
/// <summary> /// Creates a new <see cref="DataFrame"/> from serialization parameters. /// </summary> /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param> /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param> protected DataFrame(SerializationInfo info, StreamingContext context) : base(info, context) { // Deserialize data frame m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader)); }