| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- using System;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Text;
- using MQTTnet.Exceptions;
- namespace MQTTnet.Formatter
- {
- public class MqttPacketBodyReader : IMqttPacketBodyReader
- {
- private readonly byte[] _buffer;
- private readonly int _initialOffset;
- private readonly int _length;
- private int _offset;
- public MqttPacketBodyReader(byte[] buffer, int offset, int length)
- {
- _buffer = buffer;
- _initialOffset = offset;
- _offset = offset;
- _length = length;
- }
- public int Offset => _offset;
- public int Length => _length - _offset;
- public bool EndOfStream => _offset == _length;
- public void Seek(int position)
- {
- _offset = _initialOffset + position;
- }
- public byte ReadByte()
- {
- ValidateReceiveBuffer(1);
- return _buffer[_offset++];
- }
-
- public bool ReadBoolean()
- {
- ValidateReceiveBuffer(1);
- var buffer = _buffer[_offset++];
- if (buffer == 0)
- {
- return false;
- }
- if (buffer == 1)
- {
- return true;
- }
- throw new MqttProtocolViolationException("Boolean values can be 0 or 1 only.");
- }
- public byte[] ReadRemainingData()
- {
- var bufferLength = _length - _offset;
- var buffer = new byte[bufferLength];
- Array.Copy(_buffer, _offset, buffer, 0, bufferLength);
- return buffer;
- }
- public ushort ReadTwoByteInteger()
- {
- ValidateReceiveBuffer(2);
- var msb = _buffer[_offset++];
- var lsb = _buffer[_offset++];
-
- return (ushort)(msb << 8 | lsb);
- }
- public uint ReadFourByteInteger()
- {
- ValidateReceiveBuffer(4);
- var byte0 = _buffer[_offset++];
- var byte1 = _buffer[_offset++];
- var byte2 = _buffer[_offset++];
- var byte3 = _buffer[_offset++];
- return (uint)(byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3);
- }
- public uint ReadVariableLengthInteger()
- {
- var multiplier = 1;
- var value = 0U;
- byte encodedByte;
- do
- {
- encodedByte = ReadByte();
- value += (uint)((encodedByte & 127) * multiplier);
- if (multiplier > 2097152)
- {
- throw new MqttProtocolViolationException("Variable length integer is invalid.");
- }
- multiplier *= 128;
- } while ((encodedByte & 128) != 0);
- return value;
- }
-
- public byte[] ReadWithLengthPrefix()
- {
- return ReadSegmentWithLengthPrefix().ToArray();
- }
- private ArraySegment<byte> ReadSegmentWithLengthPrefix()
- {
- var length = ReadTwoByteInteger();
- ValidateReceiveBuffer(length);
- var result = new ArraySegment<byte>(_buffer, _offset, length);
- _offset += length;
- return result;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void ValidateReceiveBuffer(int length)
- {
- if (_length < _offset + length)
- {
- throw new ArgumentOutOfRangeException(nameof(_buffer), $"Expected at least {_offset + length} bytes but there are only {_length} bytes");
- }
- }
- public string ReadStringWithLengthPrefix()
- {
- var buffer = ReadSegmentWithLengthPrefix();
- return Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
- }
- }
- }
|