예제 #1
0
        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());
        }
예제 #2
0
        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;
                }
            }
        }
예제 #3
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()));
        }
예제 #4
0
        /// <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.");
                        }
                    }
                }
            }