/// <summary> /// Factory method parsing <see cref="BaseBandFrame"/>. /// </summary> /// <param name="reader"><see cref="PDUStreamReader"/> for stream from which the <see cref="BaseBandFrame"/> /// should be parsed.</param> /// <exception cref="NotImplementedException">If TS/GS (<see cref="TsGs"/>) is other than Generic Continuous Stream Input.</exception> /// <exception cref="InvalidPacketFormatException">If read data does not correspond to valid format.</exception> /// <returns>Parsed <see cref="BaseBandFrame"/> object.</returns> public static BaseBandFrame Parse(PDUStreamReader reader) { var mah = ModeAdaptationHeaderL3.Parse(reader); var bbh = BaseBandHeader.Parse(reader); if (bbh.Matype1.TsGs != TsGs.GenericContinuous) { throw new NotImplementedException("Only Generic Continuous Stream Input is supported at this moment."); } var l7PDU = reader.PDUStreamBasedProvider.GetCurrentPDU(); var userPackets = new List <GsePacket>(); while (!reader.EndOfPDU) { try { userPackets.Add(GsePacket.Parse(reader)); } catch (InvalidPacketFormatException) { // NOTE: Invalid format for GSE packet, in base band frame } } return(new BaseBandFrame(mah, bbh, ImmutableList.CreateRange(userPackets), l7PDU)); }
/// <summary> /// Add fragmented <paramref name="gsePacket"/>, which was carried in <paramref name="encapsulatingFrames"/>, to this buffer. /// </summary> /// <param name="gsePacket">Fragmetned GSE packet</param> /// <param name="encapsulatingFrames">Frames which carried provided <paramref name="gsePacket"/></param> /// <exception cref="ArgumentException">If <paramref name="gsePacket"/> is not a GSE fragment packet (<see cref="GsePacket.IsGseFragment"/>==false).</exception> public void Add([Required] GsePacket gsePacket, [Required] IEnumerable <PmFrameBase> encapsulatingFrames) { if (!gsePacket.IsGseFragment) { throw new ArgumentException("GSE packet is not a GSE fragment packet.", nameof(gsePacket)); } // check if gsePacket can be added to this buffer based on the sequence of types of GSE packets in this buffer // (Start Intermediate* End) switch (gsePacket.Type) { case PacketType.Padding: case PacketType.Complete: throw new ArgumentException($"GSE packet with type {gsePacket.Type} cannot be added to GseReassemblyBuffer.", nameof(gsePacket)); case PacketType.Start: if (this._buffer.Any()) { throw new ArgumentException($"GSE packet with type {gsePacket.Type} cannot be added to not empty GseReassemblyBuffer.", nameof(gsePacket)); } break; case PacketType.Intermediate: case PacketType.End: if (this._buffer.Any()) { if (!(this._buffer.Last().Type == PacketType.Start || this._buffer.Last().Type == PacketType.Intermediate)) { throw new ArgumentException($"GSE packet with type {gsePacket.Type} cannot be added to GseReassemblyBuffer after packet with type {this._buffer.Last().Type}.", nameof(gsePacket)); } } else { throw new ArgumentException($"GSE packet with type {gsePacket.Type} cannot be added to empty GseReassemblyBuffer.", nameof(gsePacket)); } break; default: throw new ArgumentOutOfRangeException(); } this._buffer.Add(gsePacket); foreach (var ef in encapsulatingFrames) { if (!this._encapsulatingFrames.Contains(ef)) { this._encapsulatingFrames.Add(ef); } } }