public HTTPContent(PDUStreamReader reader, TransferCoding coding, string contentLen = "0") { var sb = new StringBuilder(); switch (coding) { case TransferCoding.CHUNKED: ParseChunk(reader, sb); break; default: var readed = 0; var dLen = Convert.ToInt32(contentLen); var dt = new char[dLen]; while (true) { var len = reader.Read(dt, readed, dLen - readed); readed += len; if (readed == dLen) { break; } if (len == 0) { break; } } sb.Append(dt); break; } this.Content = Encoding.GetEncoding(437).GetBytes(sb.ToString()); }
private static void ParseChunk(PDUStreamReader reader, StringBuilder sb) { var chunkStart = true; var chunkSize = 0; while (true) { if (chunkStart) { var line = reader.ReadLine(); if (line == null) { return; } // TODO check if correct chunk coding or else unread chunkSize = Convert.ToInt32(line, 16); chunkStart = false; } else { var data = new char[chunkSize]; var read = 0; do { var len = reader.Read(data, read, data.Length - read); if (len == 0) { return; } read += len; } while(read < chunkSize); sb.Append(data); // chunk boundary if (reader.ReadLine() == null) { return; } chunkStart = true; } if (chunkSize == 0) { /* * // read last line - chunk boundary * if(reader.ReadLine() == null) * { * reader.NewMessage(); * reader.ReadLine(); // TODO unread line if not empty string * } * break; */ reader.ReadLine(); return; } } }
/// <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())); }
/// <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."); } } } }