MqttPacketBodyReader.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using System;
  2. using System.Linq;
  3. using System.Runtime.CompilerServices;
  4. using System.Text;
  5. using MQTTnet.Exceptions;
  6. namespace MQTTnet.Formatter
  7. {
  8. public class MqttPacketBodyReader : IMqttPacketBodyReader
  9. {
  10. private readonly byte[] _buffer;
  11. private readonly int _initialOffset;
  12. private readonly int _length;
  13. private int _offset;
  14. public MqttPacketBodyReader(byte[] buffer, int offset, int length)
  15. {
  16. _buffer = buffer;
  17. _initialOffset = offset;
  18. _offset = offset;
  19. _length = length;
  20. }
  21. public int Offset => _offset;
  22. public int Length => _length - _offset;
  23. public bool EndOfStream => _offset == _length;
  24. public void Seek(int position)
  25. {
  26. _offset = _initialOffset + position;
  27. }
  28. public byte ReadByte()
  29. {
  30. ValidateReceiveBuffer(1);
  31. return _buffer[_offset++];
  32. }
  33. public bool ReadBoolean()
  34. {
  35. ValidateReceiveBuffer(1);
  36. var buffer = _buffer[_offset++];
  37. if (buffer == 0)
  38. {
  39. return false;
  40. }
  41. if (buffer == 1)
  42. {
  43. return true;
  44. }
  45. throw new MqttProtocolViolationException("Boolean values can be 0 or 1 only.");
  46. }
  47. public byte[] ReadRemainingData()
  48. {
  49. var bufferLength = _length - _offset;
  50. var buffer = new byte[bufferLength];
  51. Array.Copy(_buffer, _offset, buffer, 0, bufferLength);
  52. return buffer;
  53. }
  54. public ushort ReadTwoByteInteger()
  55. {
  56. ValidateReceiveBuffer(2);
  57. var msb = _buffer[_offset++];
  58. var lsb = _buffer[_offset++];
  59. return (ushort)(msb << 8 | lsb);
  60. }
  61. public uint ReadFourByteInteger()
  62. {
  63. ValidateReceiveBuffer(4);
  64. var byte0 = _buffer[_offset++];
  65. var byte1 = _buffer[_offset++];
  66. var byte2 = _buffer[_offset++];
  67. var byte3 = _buffer[_offset++];
  68. return (uint)(byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3);
  69. }
  70. public uint ReadVariableLengthInteger()
  71. {
  72. var multiplier = 1;
  73. var value = 0U;
  74. byte encodedByte;
  75. do
  76. {
  77. encodedByte = ReadByte();
  78. value += (uint)((encodedByte & 127) * multiplier);
  79. if (multiplier > 2097152)
  80. {
  81. throw new MqttProtocolViolationException("Variable length integer is invalid.");
  82. }
  83. multiplier *= 128;
  84. } while ((encodedByte & 128) != 0);
  85. return value;
  86. }
  87. public byte[] ReadWithLengthPrefix()
  88. {
  89. return ReadSegmentWithLengthPrefix().ToArray();
  90. }
  91. private ArraySegment<byte> ReadSegmentWithLengthPrefix()
  92. {
  93. var length = ReadTwoByteInteger();
  94. ValidateReceiveBuffer(length);
  95. var result = new ArraySegment<byte>(_buffer, _offset, length);
  96. _offset += length;
  97. return result;
  98. }
  99. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  100. private void ValidateReceiveBuffer(int length)
  101. {
  102. if (_length < _offset + length)
  103. {
  104. throw new ArgumentOutOfRangeException(nameof(_buffer), $"Expected at least {_offset + length} bytes but there are only {_length} bytes");
  105. }
  106. }
  107. public string ReadStringWithLengthPrefix()
  108. {
  109. var buffer = ReadSegmentWithLengthPrefix();
  110. return Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
  111. }
  112. }
  113. }