Beispiel #1
0
 /// <summary>
 /// Read a double precision floating point value.
 /// </summary>
 /// <returns>The requested value.</returns>
 public override double ReadDouble()
 {
     // For floating point values we must bit convert the bytes, then convert to float or we can
     // mutate the data.
     return(BitConverter.ToDouble(Endian.FromNetwork(base.ReadBytes(Marshal.SizeOf(typeof(double)))), 0));
     //return Endian.FromNetwork(base.ReadDouble());
 }
Beispiel #2
0
 /// <summary>
 /// Peek at four bytes in the message content.
 /// </summary>
 /// <param name="offset">Offset from the packet start to peek at.</param>
 /// <returns>The peeked value or zero when <paramref name="offset"/> is out of range.</returns>
 /// <remarks>
 /// Four bytes are read from the message at the given offset and converted from network to local Endian.
 /// </remarks>
 public ulong PeekUInt64(int offset)
 {
     if (0 <= offset && offset < _currentByteCount)
     {
         return(Endian.FromNetwork(BitConverter.ToUInt64(_internalBuffer, offset)));
     }
     return(0);
 }
Beispiel #3
0
        /// <summary>
        /// Check the buffer contents looking for a valid header.
        /// </summary>
        /// <remarks>
        /// If there are sufficient bytes for a header, the buffer is searched for the expected
        /// <see cref="PacketHeader.Marker"/> followed by sufficient bytes to complete the <see cref="PacketHeader"/>
        /// and <see cref="ValidHeader"/> is set to <code>true</code>. Note how this consumes bytes
        /// before the marker.
        ///
        /// Bytes are also consumed when the marker cannot be found, appropriately adjusting
        /// <see cref="DroppedByteCount"/>.
        /// </remarks>
        private void ValidateHeader()
        {
            // First check that we have enough bytes for the header.
            // Loop through available bytes in case we have bad data to consume.
            int offset = 0;

            ValidHeader = false;
            UInt32 marker = 0;

            while (!ValidHeader && _currentByteCount - offset >= PacketHeader.Size)
            {
                marker = Endian.FromNetwork(BitConverter.ToUInt32(_internalBuffer, _cursor + offset));
                if (marker == PacketHeader.PacketMarker)
                {
                    // We have enough to extract a header.
                    NetworkReader reader = new NetworkReader(new System.IO.MemoryStream(_internalBuffer, _cursor + offset, _currentByteCount - offset, false));
                    if (_header.Read(reader))
                    {
                        ValidHeader = true;
                    }
                    else
                    {
                        ++offset;
                    }
                }
                else
                {
                    ++offset;
                }
            }

            // Consume bad bytes.
            if (offset != 0)
            {
                _cursor           += offset;
                _currentByteCount -= offset;
                DroppedByteCount  += offset;
            }

            //if (_currentByteCount >= _header.PacketSize)
            //{
            //  Status = PacketBufferStatus.Complete;
            //}
            if (ValidHeader)
            {
                Status = PacketBufferStatus.Collating;
            }
            else // if (ValidHeader)
            {
                Status = PacketBufferStatus.Empty;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Calculates the CRC for <paramref name="packetSize"/> and checks it against
        /// what is in the buffer.
        /// </summary>
        /// <param name="packetSize">The number of bytes in the pending packet including the CRC.</param>
        /// <returns><c>true</c>, the calculated CRC matches the reported CRC</returns>
        /// <remarks>
        /// The expected <paramref name="packetSize"/> includes the two CRC bytes at the
        /// very end of the buffer.
        /// </remarks>
        private bool CheckCrc(int packetSize)
        {
            // Check the CRC flag.
            byte packetFlags = _internalBuffer[_cursor + PacketHeader.FlagsOffset];

            if ((packetFlags & (byte)PacketFlag.NoCrc) == 0)
            {
                ushort crc      = Crc16.Crc.Calculate(_internalBuffer, (uint)_cursor, (uint)(packetSize - Crc16.CrcSize));
                byte[] crcBytes = new byte[2];
                crcBytes[0] = _internalBuffer[_cursor + packetSize - 2];
                crcBytes[1] = _internalBuffer[_cursor + packetSize - 1];
                ushort packetCrc = Endian.FromNetwork(BitConverter.ToUInt16(crcBytes, 0));
                return(packetCrc == crc);
            }
            return(true);
        }
Beispiel #5
0
 /// <summary>
 /// Read a 32-bit integer value.
 /// </summary>
 /// <returns>The requested value.</returns>
 public override uint ReadUInt32()
 {
     return(Endian.FromNetwork(base.ReadUInt32()));
 }
Beispiel #6
0
 /// <summary>
 /// Read a 16-bit integer value.
 /// </summary>
 /// <returns>The requested value.</returns>
 public override ushort ReadUInt16()
 {
     return(Endian.FromNetwork(base.ReadUInt16()));
 }
Beispiel #7
0
 /// <summary>
 /// Read a 64-bit integer value.
 /// </summary>
 /// <returns>The requested value.</returns>
 public override ulong ReadUInt64()
 {
     return(Endian.FromNetwork(base.ReadUInt64()));
 }
        /// <summary>
        /// Read the next <see cref="T:PacketBuffer"/> from the stream.
        /// </summary>
        /// <returns>The next packet extracted from the stream.</returns>
        /// <param name="processedBytes">Incremented by the number of bytes read from the stream. See remarks.</param>
        /// <remarks>
        /// The next packet is returned first from the current <see cref="T:CollatedPacketDecoder"/> if possible.
        /// Otherwise packet data are read from the stream and decoded as required. The <paramref name="processedBytes"/>
        /// value is only adjusted when data are read from the stream, not when a packet is extracted from the
        /// collation buffer.
        /// </remarks>
        /// <exception cref="MarkerNotFoundException">Thrown when the <see cref="PacketHeader.PacketMarker" /> bytes cannot
        /// be found.</exception>
        /// <exception cref="DecodeException">Thrown when decoding the packet header fails.</exception>
        /// <exception cref="InsufficientDataException">Thrown when the stream does not contain sufficient bytes to
        /// complete a packet once the header has been read or when there are insufficient bytes to read a packet header.
        /// </exception>
        public PacketBuffer NextPacket(ref long processedBytes)
        {
            PacketBuffer packet = null;

            // If decoding, just pull from the decoder.
            if (DecodingCollated)
            {
                packet = _decoder.Next();
                if (packet != null)
                {
                    return(packet);
                }
            }

            // Check for transition from raw stream to GZip stream.
            if (!_isGZipStream && GZipUtil.IsGZipStream(_activeStream))
            {
                _isGZipStream = true;
                _activeStream = new GZipStream(_activeStream, CompressionMode.Decompress);
            }

            // Read next packet.
            int bytesRead = 0;

            _headerStream.Position = 0;
            _headerStream.SetLength(PacketHeader.Size);

            if (!_searchForHeader)
            {
                bytesRead = _activeStream.Read(_headerStream.GetBuffer(), 0, PacketHeader.Size);
            }
            else
            {
                _searchForHeader = false;
                // Look for the marker bytes.
                UInt32 marker     = 0;
                int    markerSize = 4;
                while (!EndOfStream && marker != PacketHeader.PacketMarker)
                {
                    bytesRead = _activeStream.Read(_headerStream.GetBuffer(), 0, markerSize);
                    marker    = Endian.FromNetwork(BitConverter.ToUInt32(_headerStream.GetBuffer(), 0));
                }

                if (marker != PacketHeader.PacketMarker)
                {
                    // Failed.
                    EndOfStream = true;
                    throw new MarkerNotFoundException("Packet marker not found in stream");
                }

                bytesRead += _activeStream.Read(_headerStream.GetBuffer(), markerSize, PacketHeader.Size - markerSize);
            }

            if (bytesRead == 0 && (_decoder == null || !_decoder.Decoding))
            {
                // Nothing more read and fully up to date.
                EndOfStream = true;
                return(null);
            }

            if (bytesRead < PacketHeader.Size)
            {
                EndOfStream = true;
                throw new InsufficientDataException("Insufficient data in stream to complete packet");
            }

            _headerStream.SetLength(bytesRead);

            // Decode header.
            if (!_header.Read(new NetworkReader(_headerStream)))
            {
                // TODO: Throw exception
                _searchForHeader = true;
                throw new DecodeException("Packet header decoding failure");
            }

            // Extract packet.
            int crcSize = ((_header.Flags & (byte)PacketFlag.NoCrc) == 0) ? Crc16.CrcSize : 0;

            packet = new PacketBuffer(_header.PacketSize + crcSize);
            packet.Emplace(_headerStream.GetBuffer(), bytesRead);
            processedBytes += packet.Emplace(_activeStream, _header.PacketSize + crcSize - bytesRead);
            if (packet.Status != PacketBufferStatus.Complete)
            {
                _searchForHeader = true;
                if (packet.Status == PacketBufferStatus.CrcError)
                {
                    throw new CrcFailureException("Invalid CRC.");
                }
                throw new InsufficientDataException("Incomplete packet");
            }

            // Decoder packet.
            _decoder.SetPacket(packet);
            packet = _decoder.Next();
            return(packet);
        }