mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-11-04 13:33:02 +08:00
use streams
This commit is contained in:
@@ -87,7 +87,9 @@ namespace MQTTnet.Implementations
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null).ConfigureAwait(false);
|
var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null).ConfigureAwait(false);
|
||||||
var clientAdapter = new MqttChannelCommunicationAdapter(new BufferedCommunicationChannel(new MqttTcpChannel(clientSocket, null)), new MqttPacketSerializer());
|
|
||||||
|
var tcpChannel = new MqttTcpChannel(clientSocket, null);
|
||||||
|
var clientAdapter = new MqttChannelCommunicationAdapter(tcpChannel, new MqttPacketSerializer());
|
||||||
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
|
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
|
||||||
}
|
}
|
||||||
catch (Exception exception) when (!(exception is ObjectDisposedException))
|
catch (Exception exception) when (!(exception is ObjectDisposedException))
|
||||||
@@ -110,8 +112,9 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
var sslStream = new SslStream(new NetworkStream(clientSocket));
|
var sslStream = new SslStream(new NetworkStream(clientSocket));
|
||||||
await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false);
|
await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false);
|
||||||
|
|
||||||
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, sslStream), new MqttPacketSerializer());
|
var tcpChannel = new MqttTcpChannel(clientSocket, sslStream);
|
||||||
|
var clientAdapter = new MqttChannelCommunicationAdapter(tcpChannel, new MqttPacketSerializer());
|
||||||
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
|
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ namespace MQTTnet.Implementations
|
|||||||
private Socket _socket;
|
private Socket _socket;
|
||||||
private SslStream _sslStream;
|
private SslStream _sslStream;
|
||||||
|
|
||||||
|
public Stream Stream => _dataStream;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// called on client sockets are created in connect
|
/// called on client sockets are created in connect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -79,45 +81,6 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _dataStream.WriteAsync(buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ArraySegment<byte>> ReadAsync(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var totalBytes = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
var read = await _dataStream.ReadAsync(buffer, totalBytes, length - totalBytes).ConfigureAwait(false);
|
|
||||||
if (read == 0)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(new SocketException((int)SocketError.Disconnecting));
|
|
||||||
}
|
|
||||||
|
|
||||||
totalBytes += read;
|
|
||||||
}
|
|
||||||
while (totalBytes < length);
|
|
||||||
return new ArraySegment<byte>(buffer, 0, length);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_socket?.Dispose();
|
_socket?.Dispose();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using MQTTnet.Core.Client;
|
using MQTTnet.Core.Client;
|
||||||
using MQTTnet.Core.Exceptions;
|
using MQTTnet.Core.Exceptions;
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -11,8 +12,8 @@ namespace MQTTnet.Implementations
|
|||||||
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
||||||
{
|
{
|
||||||
private ClientWebSocket _webSocket = new ClientWebSocket();
|
private ClientWebSocket _webSocket = new ClientWebSocket();
|
||||||
private int WebSocketBufferSize;
|
|
||||||
private int WebSocketBufferOffset;
|
public Stream Stream { get; private set; }
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
public async Task ConnectAsync(MqttClientOptions options)
|
||||||
{
|
{
|
||||||
@@ -22,6 +23,8 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
_webSocket = new ClientWebSocket();
|
_webSocket = new ClientWebSocket();
|
||||||
await _webSocket.ConnectAsync(new Uri(options.Server), CancellationToken.None);
|
await _webSocket.ConnectAsync(new Uri(options.Server), CancellationToken.None);
|
||||||
|
|
||||||
|
Stream = new WebSocketStream(_webSocket);
|
||||||
}
|
}
|
||||||
catch (WebSocketException exception)
|
catch (WebSocketException exception)
|
||||||
{
|
{
|
||||||
@@ -31,6 +34,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public Task DisconnectAsync()
|
public Task DisconnectAsync()
|
||||||
{
|
{
|
||||||
|
Stream = null;
|
||||||
return _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
return _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,62 +42,5 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
_webSocket?.Dispose();
|
_webSocket?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ArraySegment<byte>> ReadAsync(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
await ReadToBufferAsync(length, buffer).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var result = new ArraySegment<byte>(buffer, WebSocketBufferOffset, length);
|
|
||||||
WebSocketBufferSize -= length;
|
|
||||||
WebSocketBufferOffset += length;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ReadToBufferAsync(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
if (WebSocketBufferSize > 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var offset = 0;
|
|
||||||
while (_webSocket.State == WebSocketState.Open && WebSocketBufferSize < length)
|
|
||||||
{
|
|
||||||
WebSocketReceiveResult response;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, offset, buffer.Length - offset), CancellationToken.None).ConfigureAwait(false);
|
|
||||||
offset += response.Count;
|
|
||||||
} while (!response.EndOfMessage);
|
|
||||||
|
|
||||||
WebSocketBufferSize = response.Count;
|
|
||||||
if (response.MessageType == WebSocketMessageType.Close)
|
|
||||||
{
|
|
||||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
if (buffer == null) {
|
|
||||||
throw new ArgumentNullException(nameof(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Binary, true, CancellationToken.None);
|
|
||||||
}
|
|
||||||
catch (WebSocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Peek()
|
|
||||||
{
|
|
||||||
return WebSocketBufferSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MQTTnet.Implementations
|
||||||
|
{
|
||||||
|
public class WebSocketStream : Stream
|
||||||
|
{
|
||||||
|
private readonly ClientWebSocket _webSocket;
|
||||||
|
|
||||||
|
public WebSocketStream( ClientWebSocket webSocket )
|
||||||
|
{
|
||||||
|
_webSocket = webSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var currentOffset = offset;
|
||||||
|
var targetOffset = offset + count;
|
||||||
|
while (_webSocket.State == WebSocketState.Open && currentOffset < targetOffset)
|
||||||
|
{
|
||||||
|
var response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, currentOffset, count), cancellationToken).ConfigureAwait(false);
|
||||||
|
currentOffset += response.Count;
|
||||||
|
|
||||||
|
if ( response.MessageType == WebSocketMessageType.Close )
|
||||||
|
{
|
||||||
|
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentOffset - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return _webSocket.SendAsync(new ArraySegment<byte>( buffer, offset, count ), WebSocketMessageType.Binary, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read( byte[] buffer, int offset, int count )
|
||||||
|
{
|
||||||
|
return ReadAsync(buffer, offset, count).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
WriteAsync(buffer, offset, count).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead => true;
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
public override bool CanWrite => true;
|
||||||
|
|
||||||
|
public override long Length
|
||||||
|
{
|
||||||
|
get { throw new NotSupportedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get { throw new NotSupportedException(); }
|
||||||
|
set { throw new NotSupportedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -101,6 +101,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Implementations\MqttWebSocketChannel.cs" />
|
<Compile Include="Implementations\MqttWebSocketChannel.cs" />
|
||||||
|
<Compile Include="Implementations\WebSocketStream.cs" />
|
||||||
<Compile Include="MqttClientFactory.cs" />
|
<Compile Include="MqttClientFactory.cs" />
|
||||||
<Compile Include="MqttServerFactory.cs" />
|
<Compile Include="MqttServerFactory.cs" />
|
||||||
<Compile Include="Implementations\MqttServerAdapter.cs" />
|
<Compile Include="Implementations\MqttServerAdapter.cs" />
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ namespace MQTTnet
|
|||||||
{
|
{
|
||||||
case MqttConnectionType.Tcp:
|
case MqttConnectionType.Tcp:
|
||||||
case MqttConnectionType.Tls:
|
case MqttConnectionType.Tls:
|
||||||
return new BufferedCommunicationChannel( new MqttTcpChannel() );
|
var tcp = new MqttTcpChannel();
|
||||||
|
return tcp;
|
||||||
case MqttConnectionType.Ws:
|
case MqttConnectionType.Ws:
|
||||||
case MqttConnectionType.Wss:
|
case MqttConnectionType.Wss:
|
||||||
return new MqttWebSocketChannel();
|
return new MqttWebSocketChannel();
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ namespace MQTTnet.Implementations
|
|||||||
private Socket _socket;
|
private Socket _socket;
|
||||||
private SslStream _sslStream;
|
private SslStream _sslStream;
|
||||||
|
|
||||||
|
|
||||||
|
public Stream Stream => _dataStream;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// called on client sockets are created in connect
|
/// called on client sockets are created in connect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -78,45 +81,6 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _dataStream.WriteAsync(buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ArraySegment<byte>> ReadAsync(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var totalBytes = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
var read = await _dataStream.ReadAsync(buffer, totalBytes, length - totalBytes).ConfigureAwait(false);
|
|
||||||
if (read == 0)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(new SocketException((int)SocketError.Disconnecting));
|
|
||||||
}
|
|
||||||
|
|
||||||
totalBytes += read;
|
|
||||||
}
|
|
||||||
while (totalBytes < length);
|
|
||||||
return new ArraySegment<byte>(buffer, 0, length);
|
|
||||||
}
|
|
||||||
catch (SocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_socket?.Dispose();
|
_socket?.Dispose();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using MQTTnet.Core.Client;
|
using MQTTnet.Core.Client;
|
||||||
using MQTTnet.Core.Exceptions;
|
using MQTTnet.Core.Exceptions;
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -11,8 +12,8 @@ namespace MQTTnet.Implementations
|
|||||||
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
||||||
{
|
{
|
||||||
private ClientWebSocket _webSocket = new ClientWebSocket();
|
private ClientWebSocket _webSocket = new ClientWebSocket();
|
||||||
private int _bufferSize;
|
|
||||||
private int _bufferOffset;
|
public Stream Stream { get; private set; }
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
public async Task ConnectAsync(MqttClientOptions options)
|
||||||
{
|
{
|
||||||
@@ -22,6 +23,8 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
_webSocket = new ClientWebSocket();
|
_webSocket = new ClientWebSocket();
|
||||||
await _webSocket.ConnectAsync(new Uri(options.Server), CancellationToken.None);
|
await _webSocket.ConnectAsync(new Uri(options.Server), CancellationToken.None);
|
||||||
|
|
||||||
|
Stream = new WebSocketStream(_webSocket);
|
||||||
}
|
}
|
||||||
catch (WebSocketException exception)
|
catch (WebSocketException exception)
|
||||||
{
|
{
|
||||||
@@ -31,6 +34,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public Task DisconnectAsync()
|
public Task DisconnectAsync()
|
||||||
{
|
{
|
||||||
|
Stream = null;
|
||||||
return _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
return _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,64 +42,5 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
_webSocket?.Dispose();
|
_webSocket?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ArraySegment<byte>> ReadAsync(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
await ReadToBufferAsync(length, buffer).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var result = new ArraySegment<byte>(buffer, _bufferOffset, length);
|
|
||||||
_bufferSize -= length;
|
|
||||||
_bufferOffset += length;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ReadToBufferAsync(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
if (_bufferSize > 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var offset = 0;
|
|
||||||
while (_webSocket.State == WebSocketState.Open && _bufferSize < length)
|
|
||||||
{
|
|
||||||
WebSocketReceiveResult response;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, offset, buffer.Length - offset), CancellationToken.None).ConfigureAwait(false);
|
|
||||||
offset += response.Count;
|
|
||||||
} while (!response.EndOfMessage);
|
|
||||||
|
|
||||||
_bufferSize = response.Count;
|
|
||||||
|
|
||||||
if (response.MessageType == WebSocketMessageType.Close)
|
|
||||||
{
|
|
||||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
if (buffer == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Binary, true, CancellationToken.None);
|
|
||||||
}
|
|
||||||
catch (WebSocketException exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Peek()
|
|
||||||
{
|
|
||||||
return _bufferSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MQTTnet.Implementations
|
||||||
|
{
|
||||||
|
public class WebSocketStream : Stream
|
||||||
|
{
|
||||||
|
private readonly ClientWebSocket _webSocket;
|
||||||
|
|
||||||
|
public WebSocketStream(ClientWebSocket webSocket)
|
||||||
|
{
|
||||||
|
_webSocket = webSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var currentOffset = offset;
|
||||||
|
var targetOffset = offset + count;
|
||||||
|
while ( _webSocket.State == WebSocketState.Open && currentOffset < targetOffset )
|
||||||
|
{
|
||||||
|
var response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer, currentOffset, count), cancellationToken).ConfigureAwait(false);
|
||||||
|
currentOffset += response.Count;
|
||||||
|
|
||||||
|
if ( response.MessageType == WebSocketMessageType.Close )
|
||||||
|
{
|
||||||
|
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentOffset - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return _webSocket.SendAsync(new ArraySegment<byte>( buffer, offset, count ), WebSocketMessageType.Binary, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
return ReadAsync(buffer, offset, count).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
WriteAsync( buffer, offset, count ).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead => true;
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
public override bool CanWrite => true;
|
||||||
|
|
||||||
|
public override long Length
|
||||||
|
{
|
||||||
|
get { throw new NotSupportedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get { throw new NotSupportedException(); }
|
||||||
|
set { throw new NotSupportedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Channel
|
|
||||||
{
|
|
||||||
public class BufferedCommunicationChannel : IMqttCommunicationChannel
|
|
||||||
{
|
|
||||||
private readonly IMqttCommunicationChannel _inner;
|
|
||||||
private int _bufferSize;
|
|
||||||
private int _bufferOffset;
|
|
||||||
|
|
||||||
public BufferedCommunicationChannel(IMqttCommunicationChannel inner)
|
|
||||||
{
|
|
||||||
_inner = inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ConnectAsync(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
return _inner.ConnectAsync(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task DisconnectAsync()
|
|
||||||
{
|
|
||||||
return _inner.DisconnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Peek()
|
|
||||||
{
|
|
||||||
return _inner.Peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ArraySegment<byte>> ReadAsync(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
//read from buffer
|
|
||||||
if (_bufferSize > 0)
|
|
||||||
{
|
|
||||||
return ReadFomBuffer(length, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
var available = _inner.Peek();
|
|
||||||
// if there are less or equal bytes available then requested then just read em
|
|
||||||
if (available <= length)
|
|
||||||
{
|
|
||||||
return await _inner.ReadAsync(length, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if more bytes are available than requested do buffer them to reduce calls to network buffers
|
|
||||||
await WriteToBuffer(available, buffer).ConfigureAwait(false);
|
|
||||||
return ReadFomBuffer(length, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task WriteToBuffer(int available, byte[] buffer)
|
|
||||||
{
|
|
||||||
await _inner.ReadAsync(available, buffer).ConfigureAwait(false);
|
|
||||||
_bufferSize = available;
|
|
||||||
_bufferOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ArraySegment<byte> ReadFomBuffer(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
var result = new ArraySegment<byte>(buffer, _bufferOffset, length);
|
|
||||||
_bufferSize -= length;
|
|
||||||
_bufferOffset += length;
|
|
||||||
|
|
||||||
if (_bufferSize < 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
return _inner.WriteAsync(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Core.Client;
|
using MQTTnet.Core.Client;
|
||||||
using System;
|
using System.IO;
|
||||||
|
|
||||||
namespace MQTTnet.Core.Channel
|
namespace MQTTnet.Core.Channel
|
||||||
{
|
{
|
||||||
@@ -9,14 +9,7 @@ namespace MQTTnet.Core.Channel
|
|||||||
Task ConnectAsync(MqttClientOptions options);
|
Task ConnectAsync(MqttClientOptions options);
|
||||||
|
|
||||||
Task DisconnectAsync();
|
Task DisconnectAsync();
|
||||||
|
|
||||||
Task WriteAsync(byte[] buffer);
|
Stream Stream { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// get the currently available number of bytes without reading them
|
|
||||||
/// </summary>
|
|
||||||
int Peek();
|
|
||||||
|
|
||||||
Task<ArraySegment<byte>> ReadAsync(int length, byte[] buffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<AssemblyName>MQTTnet.Core</AssemblyName>
|
<AssemblyName>MQTTnet.Core</AssemblyName>
|
||||||
<RootNamespace>MQTTnet.Core</RootNamespace>
|
<RootNamespace>MQTTnet.Core</RootNamespace>
|
||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
|
<DebugType>Full</DebugType>
|
||||||
<Description></Description>
|
<Description></Description>
|
||||||
<Product></Product>
|
<Product></Product>
|
||||||
<Company></Company>
|
<Company></Company>
|
||||||
|
|||||||
@@ -49,13 +49,13 @@ namespace MQTTnet.Core.Serializer
|
|||||||
return ReadBytes(_header.BodyLength - (int)BaseStream.Position);
|
return ReadBytes(_header.BodyLength - (int)BaseStream.Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<MqttPacketHeader> ReadHeaderFromSourceAsync(IMqttCommunicationChannel source, byte[] buffer)
|
public static MqttPacketHeader ReadHeaderFromSource(IMqttCommunicationChannel source)
|
||||||
{
|
{
|
||||||
var fixedHeader = await ReadStreamByteAsync(source, buffer).ConfigureAwait(false);
|
var fixedHeader = (byte)source.Stream.ReadByte();
|
||||||
var byteReader = new ByteReader(fixedHeader);
|
var byteReader = new ByteReader(fixedHeader);
|
||||||
byteReader.Read(4);
|
byteReader.Read(4);
|
||||||
var controlPacketType = (MqttControlPacketType)byteReader.Read(4);
|
var controlPacketType = (MqttControlPacketType)byteReader.Read(4);
|
||||||
var bodyLength = await ReadBodyLengthFromSourceAsync(source, buffer).ConfigureAwait(false);
|
var bodyLength = ReadBodyLengthFromSource(source);
|
||||||
|
|
||||||
return new MqttPacketHeader()
|
return new MqttPacketHeader()
|
||||||
{
|
{
|
||||||
@@ -64,26 +64,8 @@ namespace MQTTnet.Core.Serializer
|
|||||||
BodyLength = bodyLength
|
BodyLength = bodyLength
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<byte> ReadStreamByteAsync(IMqttCommunicationChannel source, byte[] readBuffer)
|
|
||||||
{
|
|
||||||
var result = await ReadFromSourceAsync(source, 1, readBuffer).ConfigureAwait(false);
|
|
||||||
return result.Array[result.Offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<ArraySegment<byte>> ReadFromSourceAsync(IMqttCommunicationChannel source, int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await source.ReadAsync(length, buffer);
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<int> ReadBodyLengthFromSourceAsync(IMqttCommunicationChannel source, byte[] buffer)
|
private static int ReadBodyLengthFromSource(IMqttCommunicationChannel source)
|
||||||
{
|
{
|
||||||
// Alorithm taken from http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html.
|
// Alorithm taken from http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html.
|
||||||
var multiplier = 1;
|
var multiplier = 1;
|
||||||
@@ -91,7 +73,7 @@ namespace MQTTnet.Core.Serializer
|
|||||||
byte encodedByte;
|
byte encodedByte;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
encodedByte = await ReadStreamByteAsync(source, buffer).ConfigureAwait(false);
|
encodedByte = (byte)source.Stream.ReadByte();
|
||||||
value += (encodedByte & 127) * multiplier;
|
value += (encodedByte & 127) * multiplier;
|
||||||
multiplier *= 128;
|
multiplier *= 128;
|
||||||
if (multiplier > 128 * 128 * 128)
|
if (multiplier > 128 * 128 * 128)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace MQTTnet.Core.Serializer
|
|||||||
private static byte[] ProtocolVersionV310Name { get; } = Encoding.UTF8.GetBytes("MQIs");
|
private static byte[] ProtocolVersionV310Name { get; } = Encoding.UTF8.GetBytes("MQIs");
|
||||||
|
|
||||||
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
|
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
|
||||||
private byte[] _readBuffer = new byte[BufferConstants.Size];
|
private Task _sendTask = Task.FromResult( 0 );
|
||||||
|
|
||||||
public async Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination)
|
public async Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination)
|
||||||
{
|
{
|
||||||
@@ -32,12 +32,21 @@ namespace MQTTnet.Core.Serializer
|
|||||||
|
|
||||||
var body = stream.ToArray();
|
var body = stream.ToArray();
|
||||||
MqttPacketWriter.BuildLengthHeader(body.Length, header);
|
MqttPacketWriter.BuildLengthHeader(body.Length, header);
|
||||||
|
var headerArray = header.ToArray();
|
||||||
await destination.WriteAsync(header.ToArray()).ConfigureAwait(false);
|
var writeBuffer = new byte[header.Count + body.Length];
|
||||||
await destination.WriteAsync(body).ConfigureAwait(false);
|
Buffer.BlockCopy( headerArray, 0, writeBuffer, 0, headerArray.Length );
|
||||||
|
Buffer.BlockCopy( body, 0, writeBuffer, headerArray.Length, body.Length );
|
||||||
|
|
||||||
|
_sendTask = Send( writeBuffer, destination );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task Send(byte[] buffer, IMqttCommunicationChannel destination )
|
||||||
|
{
|
||||||
|
await _sendTask.ConfigureAwait( false );
|
||||||
|
await destination.Stream.WriteAsync( buffer, 0, buffer.Length ).ConfigureAwait( false );
|
||||||
|
}
|
||||||
|
|
||||||
private byte SerializePacket(MqttBasePacket packet, MqttPacketWriter writer)
|
private byte SerializePacket(MqttBasePacket packet, MqttPacketWriter writer)
|
||||||
{
|
{
|
||||||
if (packet is MqttConnectPacket connectPacket)
|
if (packet is MqttConnectPacket connectPacket)
|
||||||
@@ -116,117 +125,127 @@ namespace MQTTnet.Core.Serializer
|
|||||||
public async Task<MqttBasePacket> DeserializeAsync(IMqttCommunicationChannel source)
|
public async Task<MqttBasePacket> DeserializeAsync(IMqttCommunicationChannel source)
|
||||||
{
|
{
|
||||||
if (source == null) throw new ArgumentNullException(nameof(source));
|
if (source == null) throw new ArgumentNullException(nameof(source));
|
||||||
|
|
||||||
var header = await MqttPacketReader.ReadHeaderFromSourceAsync(source, _readBuffer).ConfigureAwait(false);
|
var header = MqttPacketReader.ReadHeaderFromSource(source);
|
||||||
|
|
||||||
var body = await GetBody(source, header).ConfigureAwait(false);
|
MemoryStream body = null;
|
||||||
|
if ( header.BodyLength > 0 )
|
||||||
using (var mqttPacketReader = new MqttPacketReader(body, header))
|
|
||||||
{
|
{
|
||||||
switch (header.ControlPacketType)
|
var totalRead = 0;
|
||||||
|
var readBuffer = new byte[header.BodyLength];
|
||||||
|
do
|
||||||
{
|
{
|
||||||
case MqttControlPacketType.Connect:
|
var read = await source.Stream.ReadAsync( readBuffer, totalRead, header.BodyLength - totalRead ).ConfigureAwait(false);
|
||||||
{
|
totalRead += read;
|
||||||
return DeserializeConnect(mqttPacketReader);
|
} while ( totalRead < header.BodyLength );
|
||||||
}
|
body = new MemoryStream( readBuffer, 0, header.BodyLength );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
body = new MemoryStream();
|
||||||
|
}
|
||||||
|
|
||||||
case MqttControlPacketType.ConnAck:
|
using (var reader = new MqttPacketReader(body, header))
|
||||||
{
|
{
|
||||||
return DeserializeConnAck(mqttPacketReader);
|
return Deserialize( header, reader );
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.Disconnect:
|
|
||||||
{
|
|
||||||
return new MqttDisconnectPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.Publish:
|
|
||||||
{
|
|
||||||
return DeserializePublish(mqttPacketReader, header);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PubAck:
|
|
||||||
{
|
|
||||||
return new MqttPubAckPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = mqttPacketReader.ReadUInt16()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PubRec:
|
|
||||||
{
|
|
||||||
return new MqttPubRecPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = mqttPacketReader.ReadUInt16()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PubRel:
|
|
||||||
{
|
|
||||||
return new MqttPubRelPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = mqttPacketReader.ReadUInt16()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PubComp:
|
|
||||||
{
|
|
||||||
return new MqttPubCompPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = mqttPacketReader.ReadUInt16()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PingReq:
|
|
||||||
{
|
|
||||||
return new MqttPingReqPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.PingResp:
|
|
||||||
{
|
|
||||||
return new MqttPingRespPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.Subscribe:
|
|
||||||
{
|
|
||||||
return DeserializeSubscribe(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.SubAck:
|
|
||||||
{
|
|
||||||
return DeserializeSubAck(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.Unsubscibe:
|
|
||||||
{
|
|
||||||
return DeserializeUnsubscribe(mqttPacketReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
case MqttControlPacketType.UnsubAck:
|
|
||||||
{
|
|
||||||
return new MqttUnsubAckPacket
|
|
||||||
{
|
|
||||||
PacketIdentifier = mqttPacketReader.ReadUInt16()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw new MqttProtocolViolationException($"Packet type ({(int)header.ControlPacketType}) not supported.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<MemoryStream> GetBody(IMqttCommunicationChannel source, MqttPacketHeader header)
|
private static MqttBasePacket Deserialize(MqttPacketHeader header, MqttPacketReader reader)
|
||||||
{
|
{
|
||||||
if (header.BodyLength > 0)
|
switch (header.ControlPacketType)
|
||||||
{
|
{
|
||||||
var segment = await MqttPacketReader.ReadFromSourceAsync(source, header.BodyLength, _readBuffer).ConfigureAwait(false);
|
case MqttControlPacketType.Connect:
|
||||||
return new MemoryStream(segment.Array, segment.Offset, segment.Count);
|
{
|
||||||
}
|
return DeserializeConnect( reader );
|
||||||
|
}
|
||||||
|
|
||||||
return new MemoryStream();
|
case MqttControlPacketType.ConnAck:
|
||||||
|
{
|
||||||
|
return DeserializeConnAck( reader );
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.Disconnect:
|
||||||
|
{
|
||||||
|
return new MqttDisconnectPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.Publish:
|
||||||
|
{
|
||||||
|
return DeserializePublish( reader, header );
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.PubAck:
|
||||||
|
{
|
||||||
|
return new MqttPubAckPacket
|
||||||
|
{
|
||||||
|
PacketIdentifier = reader.ReadUInt16()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.PubRec:
|
||||||
|
{
|
||||||
|
return new MqttPubRecPacket
|
||||||
|
{
|
||||||
|
PacketIdentifier = reader.ReadUInt16()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.PubRel:
|
||||||
|
{
|
||||||
|
return new MqttPubRelPacket
|
||||||
|
{
|
||||||
|
PacketIdentifier = reader.ReadUInt16()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.PubComp:
|
||||||
|
{
|
||||||
|
return new MqttPubCompPacket
|
||||||
|
{
|
||||||
|
PacketIdentifier = reader.ReadUInt16()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.PingReq:
|
||||||
|
{
|
||||||
|
return new MqttPingReqPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.PingResp:
|
||||||
|
{
|
||||||
|
return new MqttPingRespPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.Subscribe:
|
||||||
|
{
|
||||||
|
return DeserializeSubscribe( reader );
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.SubAck:
|
||||||
|
{
|
||||||
|
return DeserializeSubAck( reader );
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.Unsubscibe:
|
||||||
|
{
|
||||||
|
return DeserializeUnsubscribe( reader );
|
||||||
|
}
|
||||||
|
|
||||||
|
case MqttControlPacketType.UnsubAck:
|
||||||
|
{
|
||||||
|
return new MqttUnsubAckPacket
|
||||||
|
{
|
||||||
|
PacketIdentifier = reader.ReadUInt16()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw new MqttProtocolViolationException(
|
||||||
|
$"Packet type ({(int) header.ControlPacketType}) not supported." );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MqttBasePacket DeserializeUnsubscribe(MqttPacketReader reader)
|
private static MqttBasePacket DeserializeUnsubscribe(MqttPacketReader reader)
|
||||||
@@ -268,7 +287,13 @@ namespace MQTTnet.Core.Serializer
|
|||||||
var qualityOfServiceLevel = (MqttQualityOfServiceLevel)fixedHeader.Read(2);
|
var qualityOfServiceLevel = (MqttQualityOfServiceLevel)fixedHeader.Read(2);
|
||||||
var dup = fixedHeader.Read();
|
var dup = fixedHeader.Read();
|
||||||
|
|
||||||
var topic = reader.ReadStringWithLengthPrefix();
|
|
||||||
|
var length = reader.ReadUInt16();
|
||||||
|
if (length != 5)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
var topic = Encoding.UTF8.GetString( reader.ReadBytes( length ), 0, length );
|
||||||
|
|
||||||
ushort packetIdentifier = 0;
|
ushort packetIdentifier = 0;
|
||||||
if (qualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
|
if (qualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
|
||||||
|
|||||||
@@ -391,6 +391,8 @@ namespace MQTTnet.Core.Tests
|
|||||||
{
|
{
|
||||||
private readonly MemoryStream _stream = new MemoryStream();
|
private readonly MemoryStream _stream = new MemoryStream();
|
||||||
|
|
||||||
|
public Stream Stream => _stream;
|
||||||
|
|
||||||
public bool IsConnected { get; } = true;
|
public bool IsConnected { get; } = true;
|
||||||
|
|
||||||
public TestChannel()
|
public TestChannel()
|
||||||
@@ -413,26 +415,10 @@ namespace MQTTnet.Core.Tests
|
|||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task WriteAsync(byte[] buffer)
|
|
||||||
{
|
|
||||||
return _stream.WriteAsync(buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ArraySegment<byte>> ReadAsync(int length, byte[] buffer)
|
|
||||||
{
|
|
||||||
await _stream.ReadAsync(buffer, 0, length);
|
|
||||||
return new ArraySegment<byte>(buffer, 0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ToArray()
|
public byte[] ToArray()
|
||||||
{
|
{
|
||||||
return _stream.ToArray();
|
return _stream.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Peek()
|
|
||||||
{
|
|
||||||
return (int)_stream.Length - (int)_stream.Position;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SerializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311)
|
private static void SerializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311)
|
||||||
|
|||||||
Reference in New Issue
Block a user