/// <summary> /// Factory method parsing <see cref="BaseBandHeader"/>. /// </summary> /// <param name="reader"><see cref="PDUStreamReader"/> for stream from which the <see cref="BaseBandHeader"/> /// should be parsed.</param> /// <exception cref="InvalidPacketFormatException">If DFL (Data Field Length) field is not in range [0,58112].</exception> /// <returns>Parsed <see cref="BaseBandHeader"/> object.</returns> public static BaseBandHeader Parse(PDUStreamReader reader) { // Byte 0, MATYPE-1 var matype1 = Matype1.Parse(reader.ReadByte()); // Byte 1, MATYPE-2 var matype2 = reader.ReadByte(); // Byte 2-3, UPL var userPacketLenght = reader.ReadUInt16(); // Byte 4-5, DFL var dataFieldLength = reader.ReadUInt16(); // http://www.etsi.org/deliver/etsi_en/302300_302399/302307/01.01.02_60/en_302307v010102p.pdf#page=18 if (dataFieldLength > 58112) { throw new InvalidPacketFormatException( $"DFL (Data Field Length) field has be in range [0,58112]. {dataFieldLength} > 58112"); } // Byte 6, SYNC var sync = reader.ReadByte(); // Byte 7-8, SYNCD var syncD = reader.ReadUInt16(); // Byte 9, CRC-8 var crc8 = reader.ReadByte(); // NOTE: DVB-S2 base band frame, base band header, CRC-8 is not validated. return(new BaseBandHeader(matype1, matype2, userPacketLenght, dataFieldLength, sync, syncD, crc8)); }
/// <summary> /// Factory method parsing <see cref="GseHeader"/>. /// </summary> /// <param name="reader"><see cref="PDUStreamReader"/> for stream from which the <see cref="GseHeader"/> /// should be parsed.</param> /// <exception cref="InvalidPacketFormatException">If read data does not correspond to valid format.</exception> /// <returns>Parsed <see cref="GseHeader"/> object.</returns> /// <remarks> /// For complete syntax of GSE Packet structure, see Table 2 in /// <a href="http://www.etsi.org/deliver/etsi_ts/102600_102699/10260601/01.02.01_60/ts_10260601v010201p.pdf#page=13"> /// ETSI TS 102 606-1 V1.2.1.</a> /// </remarks> public static GseHeader Parse(PDUStreamReader reader) { var b = reader.ReadByte(); // Byte 0-1, Fixed Header Fields // Bit 15: S var startIndicator = (b & 0b1000_0000) == 0b1000_0000; // Bit 14: E var endIndicator = (b & 0b0100_0000) == 0b0100_0000; // Bit 13-12: LT // LabelType enum has 4 values, therefore we use Enum.Parse instead of Enum.TryParse. var labelTypeIndicator = (LabelType)Enum.Parse(typeof(LabelType), ((b & 0b0011_0000) >> 4).ToString()); // possibly null values which might not be present in packet ushort?gseLength = null; ushort?bytesAfterGseLengthField = null; byte? fragmentID = null; ushort?totalLength = null; ushort?protocolType = null; byte[] label = null; long?gseLengthFieldStreamPosition = null; // Bit 11-0 if (!startIndicator && !endIndicator && labelTypeIndicator == LabelType.Byte6) { // 4 padding bits if ((b & 0b0000_1111) != 0b0000_0000) { throw new InvalidPacketFormatException($"Expected 4 zero-padding bits."); } // N1 Padding bytes (N1 is the number of bytes until the end of the Base-Band frame.) while (!reader.EndOfPDU) { if (reader.ReadByte() != 0) { throw new InvalidPacketFormatException( $"Expected zero-padding bits until the end of the Base-Band frame."); } } } else { // 12 bits byte[] tmpMaskedBytes = { reader.ReadByte(), (byte)(b & 0b0000_1111) }; // BigEndian gseLength = BitConverter.ToUInt16(tmpMaskedBytes, 0); gseLengthFieldStreamPosition = reader.PDUStreamBasedProvider.Position; if (!startIndicator || !endIndicator) { fragmentID = reader.ReadByte(); } if (startIndicator && !endIndicator) { totalLength = reader.ReadUInt16(); } if (startIndicator) { protocolType = reader.ReadUInt16(); if (labelTypeIndicator == LabelType.Byte6) { label = new byte[6]; if (reader.Read(label, 0, 6) != 6) { throw new InvalidPacketFormatException("Reader could not read 6 bytes."); } } else if (labelTypeIndicator == LabelType.Byte3) { label = new byte[3]; if (reader.Read(label, 0, 3) != 3) { throw new InvalidPacketFormatException("Reader could not read 3 bytes."); } } } }