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