コード例 #1
0
        /// <summary>
        /// Factory method parsing <see cref="GsePacket"/>.
        /// </summary>
        /// <param name="reader"><see cref="PDUStreamReader"/> for stream from which the <see cref="GsePacket"/>
        /// should be parsed.</param>
        /// <exception cref="InvalidPacketFormatException">If read data does not correspond to valid format.</exception>
        /// <returns>Parsed <see cref="GsePacket"/> object.</returns>
        public static GsePacket Parse(PDUStreamReader reader)
        {
            // Header
            var h = GseHeader.Parse(reader);

            // Type
            PacketType type;

            if (!h.StartIndicator && !h.EndIndicator && h.LabelTypeIndicator == LabelType.Byte6)
            {
                type = PacketType.Padding;
            }
            else if (!h.StartIndicator && !h.EndIndicator && h.LabelTypeIndicator == LabelType.LabelReuse)
            {
                type = PacketType.Intermediate;
            }
            else if (h.StartIndicator && !h.EndIndicator)
            {
                type = PacketType.Start;
            }
            else if (!h.StartIndicator && h.EndIndicator && h.LabelTypeIndicator == LabelType.LabelReuse)
            {
                type = PacketType.End;
            }
            else if (h.StartIndicator && h.EndIndicator)
            {
                type = PacketType.Complete;
            }
            else
            {
                throw new InvalidPacketFormatException(
                          $"Invalid packet type. StartIndicator={h.StartIndicator}, EndIndicator={h.EndIndicator}, LabelTypeIndicator={h.LabelTypeIndicator}.");
            }

            // PDU
            // Check whether this GSE packet isn't a padding packet
            byte[] pdu = null;
            if (type != PacketType.Padding)
            {
                if (h.GSELength == null)
                {
                    throw new InvalidPacketFormatException("GSELength field is missing.");
                }

                if (h.BytesAfterGseLengthField == null)
                {
                    throw new InvalidPacketFormatException("BytesAfterGseLengthField unknown.");
                }

                var pduLength = (ushort)h.GSELength - (ushort)h.BytesAfterGseLengthField;
                if (!h.StartIndicator && h.EndIndicator) // if CRC is present after PDU
                {
                    pduLength -= 4;                      // CRC is 4 bytes long
                }

                pdu = new byte[pduLength];
                var readLength = reader.Read(pdu, 0, pduLength);
                if (readLength != pduLength)
                {
                    throw new InvalidPacketFormatException(
                              $"Reader could not read whole PDU. Read {readLength} out of {pduLength} bytes.");
                }
            }

            // CRC-32
            int?crc32 = null;

            if (!h.StartIndicator && h.EndIndicator)
            {
                crc32 = reader.ReadInt32();
                // CRC-32 can't be verified here, because we need all GSE packets from this fragmentation group.
            }

            return(new GsePacket(h, pdu, crc32, type, reader.PDUStreamBasedProvider.GetCurrentPDU().FrameList.Last()));
        }