mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-21 12:16:02 +08:00
Refactor options
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
* [Server] The client connection is now closed if sending of one pending application message has failed
|
* [Server] The client connection is now closed if sending of one pending application message has failed
|
||||||
* [Server] Fixed handling of _Dup_ flag (Thanks to haeberle)
|
* [Server] Fixed handling of _Dup_ flag (Thanks to haeberle)
|
||||||
* [Core] Optimized exception handling
|
* [Core] Optimized exception handling
|
||||||
|
* [Core] Mono is now also supported (Thanks to JTrotta)
|
||||||
</releaseNotes>
|
</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2017</copyright>
|
<copyright>Copyright Christian Kratky 2016-2017</copyright>
|
||||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M</tags>
|
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M</tags>
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using MQTTnet.Core.Adapter;
|
||||||
|
using MQTTnet.Core.Client;
|
||||||
|
using MQTTnet.Core.Serializer;
|
||||||
|
|
||||||
|
namespace MQTTnet.Implementations
|
||||||
|
{
|
||||||
|
public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory
|
||||||
|
{
|
||||||
|
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options)
|
||||||
|
{
|
||||||
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
|
if (options is MqttClientTcpOptions tcpOptions)
|
||||||
|
{
|
||||||
|
return new MqttChannelCommunicationAdapter(new MqttTcpChannel(tcpOptions), new MqttPacketSerializer { ProtocolVersion = options.ProtocolVersion });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options is MqttClientWebSocketOptions webSocketOptions)
|
||||||
|
{
|
||||||
|
return new MqttChannelCommunicationAdapter(new MqttWebSocketChannel(webSocketOptions), new MqttPacketSerializer { ProtocolVersion = options.ProtocolVersion });
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,8 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly MqttClientTcpOptions _options;
|
||||||
|
|
||||||
// ReSharper disable once MemberCanBePrivate.Global
|
// ReSharper disable once MemberCanBePrivate.Global
|
||||||
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
|
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
|
||||||
public static int BufferSize { get; set; } = 4096 * 20; // Can be changed for fine tuning by library user.
|
public static int BufferSize { get; set; } = 4096 * 20; // Can be changed for fine tuning by library user.
|
||||||
@@ -22,9 +24,9 @@ namespace MQTTnet.Implementations
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// called on client sockets are created in connect
|
/// called on client sockets are created in connect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttTcpChannel()
|
public MqttTcpChannel(MqttClientTcpOptions options)
|
||||||
{
|
{
|
||||||
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -42,22 +44,20 @@ namespace MQTTnet.Implementations
|
|||||||
public Stream ReceiveStream { get; private set; }
|
public Stream ReceiveStream { get; private set; }
|
||||||
public Stream RawReceiveStream { get; private set; }
|
public Stream RawReceiveStream { get; private set; }
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
public async Task ConnectAsync()
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
if (_socket == null)
|
if (_socket == null)
|
||||||
{
|
{
|
||||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, options.Server, options.GetPort(), null).ConfigureAwait(false);
|
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, _options.Server, _options.GetPort(), null).ConfigureAwait(false);
|
||||||
|
|
||||||
if (options.TlsOptions.UseTls)
|
if (_options.TlsOptions.UseTls)
|
||||||
{
|
{
|
||||||
_sslStream = new SslStream(new NetworkStream(_socket, true));
|
_sslStream = new SslStream(new NetworkStream(_socket, true));
|
||||||
|
|
||||||
await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.TlsOptions.CheckCertificateRevocation).ConfigureAwait(false);
|
await _sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(_options), SslProtocols.Tls12, _options.TlsOptions.CheckCertificateRevocation).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateStreams(_socket, _sslStream);
|
CreateStreams(_socket, _sslStream);
|
||||||
|
|||||||
@@ -10,27 +10,29 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly MqttClientWebSocketOptions _options;
|
||||||
|
|
||||||
private ClientWebSocket _webSocket;
|
private ClientWebSocket _webSocket;
|
||||||
|
|
||||||
|
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
||||||
|
{
|
||||||
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
public Stream RawReceiveStream { get; private set; }
|
public Stream RawReceiveStream { get; private set; }
|
||||||
public Stream SendStream => RawReceiveStream;
|
public Stream SendStream => RawReceiveStream;
|
||||||
public Stream ReceiveStream => RawReceiveStream;
|
public Stream ReceiveStream => RawReceiveStream;
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
public async Task ConnectAsync()
|
||||||
{
|
{
|
||||||
var uri = options.Server;
|
var uri = _options.Uri;
|
||||||
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase))
|
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
uri = "ws://" + uri;
|
uri = "ws://" + uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.Port.HasValue)
|
|
||||||
{
|
|
||||||
uri += ":" + options.Port;
|
|
||||||
}
|
|
||||||
|
|
||||||
_webSocket = new ClientWebSocket();
|
_webSocket = new ClientWebSocket();
|
||||||
_webSocket.Options.KeepAliveInterval = options.KeepAlivePeriod;
|
_webSocket.Options.KeepAliveInterval = _options.KeepAlivePeriod;
|
||||||
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None).ConfigureAwait(false);
|
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None).ConfigureAwait(false);
|
||||||
RawReceiveStream = new WebSocketStream(_webSocket);
|
RawReceiveStream = new WebSocketStream(_webSocket);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@
|
|||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Implementations\MqttCommunicationAdapterFactory.cs" />
|
||||||
<Compile Include="Implementations\MqttWebSocketChannel.cs" />
|
<Compile Include="Implementations\MqttWebSocketChannel.cs" />
|
||||||
<Compile Include="Implementations\WebSocketStream.cs" />
|
<Compile Include="Implementations\WebSocketStream.cs" />
|
||||||
<Compile Include="MqttClientFactory.cs" />
|
<Compile Include="MqttClientFactory.cs" />
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Client;
|
using MQTTnet.Core.Client;
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
using MQTTnet.Implementations;
|
using MQTTnet.Implementations;
|
||||||
|
|
||||||
namespace MQTTnet
|
namespace MQTTnet
|
||||||
@@ -13,21 +10,7 @@ namespace MQTTnet
|
|||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
return new MqttClient(options, new MqttChannelCommunicationAdapter(GetMqttCommunicationChannel(options), new MqttPacketSerializer()));
|
return new MqttClient(new MqttCommunicationAdapterFactory());
|
||||||
}
|
|
||||||
|
|
||||||
private static IMqttCommunicationChannel GetMqttCommunicationChannel(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
switch (options.ConnectionType)
|
|
||||||
{
|
|
||||||
case MqttConnectionType.Tcp:
|
|
||||||
return new MqttTcpChannel();
|
|
||||||
case MqttConnectionType.Ws:
|
|
||||||
return new MqttWebSocketChannel();
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using MQTTnet.Core.Adapter;
|
||||||
|
using MQTTnet.Core.Client;
|
||||||
|
using MQTTnet.Core.Serializer;
|
||||||
|
|
||||||
|
namespace MQTTnet.Implementations
|
||||||
|
{
|
||||||
|
public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory
|
||||||
|
{
|
||||||
|
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options)
|
||||||
|
{
|
||||||
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
|
if (options is MqttClientTcpOptions tcpOptions)
|
||||||
|
{
|
||||||
|
return new MqttChannelCommunicationAdapter(new MqttTcpChannel(tcpOptions), new MqttPacketSerializer { ProtocolVersion = options.ProtocolVersion });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options is MqttClientWebSocketOptions webSocketOptions)
|
||||||
|
{
|
||||||
|
return new MqttChannelCommunicationAdapter(new MqttWebSocketChannel(webSocketOptions), new MqttPacketSerializer { ProtocolVersion = options.ProtocolVersion });
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,14 +12,17 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly MqttClientTcpOptions _options;
|
||||||
|
|
||||||
private Socket _socket;
|
private Socket _socket;
|
||||||
private SslStream _sslStream;
|
private SslStream _sslStream;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// called on client sockets are created in connect
|
/// called on client sockets are created in connect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttTcpChannel()
|
public MqttTcpChannel(MqttClientTcpOptions options)
|
||||||
{
|
{
|
||||||
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -37,22 +40,20 @@ namespace MQTTnet.Implementations
|
|||||||
public Stream ReceiveStream { get; private set; }
|
public Stream ReceiveStream { get; private set; }
|
||||||
public Stream RawReceiveStream => ReceiveStream;
|
public Stream RawReceiveStream => ReceiveStream;
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
public async Task ConnectAsync()
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
if (_socket == null)
|
if (_socket == null)
|
||||||
{
|
{
|
||||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _socket.ConnectAsync(options.Server, options.GetPort()).ConfigureAwait(false);
|
await _socket.ConnectAsync(_options.Server, _options.GetPort()).ConfigureAwait(false);
|
||||||
|
|
||||||
if (options.TlsOptions.UseTls)
|
if (_options.TlsOptions.UseTls)
|
||||||
{
|
{
|
||||||
_sslStream = new SslStream(new NetworkStream(_socket, true));
|
_sslStream = new SslStream(new NetworkStream(_socket, true));
|
||||||
ReceiveStream = _sslStream;
|
ReceiveStream = _sslStream;
|
||||||
await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.TlsOptions.CheckCertificateRevocation).ConfigureAwait(false);
|
await _sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(_options), SslProtocols.Tls12, _options.TlsOptions.CheckCertificateRevocation).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,27 +10,28 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly MqttClientWebSocketOptions _options;
|
||||||
private ClientWebSocket _webSocket;
|
private ClientWebSocket _webSocket;
|
||||||
|
|
||||||
|
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
||||||
|
{
|
||||||
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
public Stream SendStream => RawReceiveStream;
|
public Stream SendStream => RawReceiveStream;
|
||||||
public Stream ReceiveStream => RawReceiveStream;
|
public Stream ReceiveStream => RawReceiveStream;
|
||||||
public Stream RawReceiveStream { get; private set; }
|
public Stream RawReceiveStream { get; private set; }
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
public async Task ConnectAsync()
|
||||||
{
|
{
|
||||||
var uri = options.Server;
|
var uri = _options.Uri;
|
||||||
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase))
|
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
uri = "ws://" + uri;
|
uri = "ws://" + uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.Port.HasValue)
|
|
||||||
{
|
|
||||||
uri += ":" + options.Port;
|
|
||||||
}
|
|
||||||
|
|
||||||
_webSocket = new ClientWebSocket();
|
_webSocket = new ClientWebSocket();
|
||||||
_webSocket.Options.KeepAliveInterval = options.KeepAlivePeriod;
|
_webSocket.Options.KeepAliveInterval = _options.KeepAlivePeriod;
|
||||||
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None);
|
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None);
|
||||||
RawReceiveStream = new WebSocketStream(_webSocket);
|
RawReceiveStream = new WebSocketStream(_webSocket);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Client;
|
using MQTTnet.Core.Client;
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
using MQTTnet.Implementations;
|
using MQTTnet.Implementations;
|
||||||
|
|
||||||
namespace MQTTnet
|
namespace MQTTnet
|
||||||
@@ -13,21 +10,7 @@ namespace MQTTnet
|
|||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
return new MqttClient(options, new MqttChannelCommunicationAdapter(GetMqttCommunicationChannel(options), new MqttPacketSerializer()));
|
return new MqttClient(new MqttCommunicationAdapterFactory());
|
||||||
}
|
|
||||||
|
|
||||||
private static IMqttCommunicationChannel GetMqttCommunicationChannel(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
switch (options.ConnectionType)
|
|
||||||
{
|
|
||||||
case MqttConnectionType.Tcp:
|
|
||||||
return new MqttTcpChannel();
|
|
||||||
case MqttConnectionType.Ws:
|
|
||||||
return new MqttWebSocketChannel();
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using MQTTnet.Core.Adapter;
|
||||||
|
using MQTTnet.Core.Client;
|
||||||
|
using MQTTnet.Core.Serializer;
|
||||||
|
|
||||||
|
namespace MQTTnet.Implementations
|
||||||
|
{
|
||||||
|
public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory
|
||||||
|
{
|
||||||
|
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options)
|
||||||
|
{
|
||||||
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
|
if (options is MqttClientTcpOptions tcpOptions)
|
||||||
|
{
|
||||||
|
return new MqttChannelCommunicationAdapter(new MqttTcpChannel(tcpOptions), new MqttPacketSerializer { ProtocolVersion = options.ProtocolVersion });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options is MqttClientWebSocketOptions webSocketOptions)
|
||||||
|
{
|
||||||
|
return new MqttChannelCommunicationAdapter(new MqttWebSocketChannel(webSocketOptions), new MqttPacketSerializer { ProtocolVersion = options.ProtocolVersion });
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,10 +13,12 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly MqttClientTcpOptions _options;
|
||||||
private StreamSocket _socket;
|
private StreamSocket _socket;
|
||||||
|
|
||||||
public MqttTcpChannel()
|
public MqttTcpChannel(MqttClientTcpOptions options)
|
||||||
{
|
{
|
||||||
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttTcpChannel(StreamSocket socket)
|
public MqttTcpChannel(StreamSocket socket)
|
||||||
@@ -29,30 +31,28 @@ namespace MQTTnet.Implementations
|
|||||||
public Stream ReceiveStream { get; private set; }
|
public Stream ReceiveStream { get; private set; }
|
||||||
public Stream RawReceiveStream { get; private set; }
|
public Stream RawReceiveStream { get; private set; }
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
public async Task ConnectAsync()
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
if (_socket == null)
|
if (_socket == null)
|
||||||
{
|
{
|
||||||
_socket = new StreamSocket();
|
_socket = new StreamSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.TlsOptions.UseTls)
|
if (!_options.TlsOptions.UseTls)
|
||||||
{
|
{
|
||||||
await _socket.ConnectAsync(new HostName(options.Server), options.GetPort().ToString());
|
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_socket.Control.ClientCertificate = LoadCertificate(options);
|
_socket.Control.ClientCertificate = LoadCertificate(_options);
|
||||||
|
|
||||||
if (!options.TlsOptions.CheckCertificateRevocation)
|
if (!_options.TlsOptions.CheckCertificateRevocation)
|
||||||
{
|
{
|
||||||
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.IncompleteChain);
|
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.IncompleteChain);
|
||||||
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationInformationMissing);
|
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationInformationMissing);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _socket.ConnectAsync(new HostName(options.Server), options.GetPort().ToString(), SocketProtectionLevel.Tls12);
|
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString(), SocketProtectionLevel.Tls12);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateStreams();
|
CreateStreams();
|
||||||
|
|||||||
@@ -10,27 +10,28 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
public sealed class MqttWebSocketChannel : IMqttCommunicationChannel, IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly MqttClientWebSocketOptions _options;
|
||||||
private ClientWebSocket _webSocket = new ClientWebSocket();
|
private ClientWebSocket _webSocket = new ClientWebSocket();
|
||||||
|
|
||||||
|
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
||||||
|
{
|
||||||
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
public Stream RawReceiveStream { get; private set; }
|
public Stream RawReceiveStream { get; private set; }
|
||||||
public Stream SendStream => RawReceiveStream;
|
public Stream SendStream => RawReceiveStream;
|
||||||
public Stream ReceiveStream => RawReceiveStream;
|
public Stream ReceiveStream => RawReceiveStream;
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttClientOptions options)
|
public async Task ConnectAsync()
|
||||||
{
|
{
|
||||||
var uri = options.Server;
|
var uri = _options.Uri;
|
||||||
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase))
|
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
uri = "ws://" + uri;
|
uri = "ws://" + uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.Port.HasValue)
|
|
||||||
{
|
|
||||||
uri += ":" + options.Port;
|
|
||||||
}
|
|
||||||
|
|
||||||
_webSocket = new ClientWebSocket();
|
_webSocket = new ClientWebSocket();
|
||||||
_webSocket.Options.KeepAliveInterval = options.KeepAlivePeriod;
|
_webSocket.Options.KeepAliveInterval = _options.KeepAlivePeriod;
|
||||||
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None).ConfigureAwait(false);
|
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
RawReceiveStream = new WebSocketStream(_webSocket);
|
RawReceiveStream = new WebSocketStream(_webSocket);
|
||||||
|
|||||||
@@ -110,6 +110,7 @@
|
|||||||
<DocumentationFile>bin\x64\Release\MQTTnet.XML</DocumentationFile>
|
<DocumentationFile>bin\x64\Release\MQTTnet.XML</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Implementations\MqttCommunicationAdapterFactory.cs" />
|
||||||
<Compile Include="Implementations\MqttWebSocketChannel.cs" />
|
<Compile Include="Implementations\MqttWebSocketChannel.cs" />
|
||||||
<Compile Include="MqttClientFactory.cs" />
|
<Compile Include="MqttClientFactory.cs" />
|
||||||
<Compile Include="Implementations\MqttServerAdapter.cs" />
|
<Compile Include="Implementations\MqttServerAdapter.cs" />
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using MQTTnet.Core.Adapter;
|
|
||||||
using MQTTnet.Core.Channel;
|
|
||||||
using MQTTnet.Core.Client;
|
using MQTTnet.Core.Client;
|
||||||
using MQTTnet.Core.Serializer;
|
|
||||||
using MQTTnet.Implementations;
|
using MQTTnet.Implementations;
|
||||||
|
|
||||||
namespace MQTTnet
|
namespace MQTTnet
|
||||||
@@ -13,21 +10,7 @@ namespace MQTTnet
|
|||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
return new MqttClient(options, new MqttChannelCommunicationAdapter(GetMqttCommunicationChannel(options), new MqttPacketSerializer()));
|
return new MqttClient(new MqttCommunicationAdapterFactory());
|
||||||
}
|
|
||||||
|
|
||||||
private static IMqttCommunicationChannel GetMqttCommunicationChannel(MqttClientOptions options)
|
|
||||||
{
|
|
||||||
switch (options.ConnectionType)
|
|
||||||
{
|
|
||||||
case MqttConnectionType.Tcp:
|
|
||||||
return new MqttTcpChannel();
|
|
||||||
case MqttConnectionType.Ws:
|
|
||||||
return new MqttWebSocketChannel();
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Packets;
|
using MQTTnet.Core.Packets;
|
||||||
using MQTTnet.Core.Serializer;
|
using MQTTnet.Core.Serializer;
|
||||||
|
|
||||||
@@ -12,7 +11,7 @@ namespace MQTTnet.Core.Adapter
|
|||||||
{
|
{
|
||||||
IMqttPacketSerializer PacketSerializer { get; }
|
IMqttPacketSerializer PacketSerializer { get; }
|
||||||
|
|
||||||
Task ConnectAsync(TimeSpan timeout, MqttClientOptions options);
|
Task ConnectAsync(TimeSpan timeout);
|
||||||
|
|
||||||
Task DisconnectAsync(TimeSpan timeout);
|
Task DisconnectAsync(TimeSpan timeout);
|
||||||
|
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ namespace MQTTnet.Core.Adapter
|
|||||||
|
|
||||||
public IMqttPacketSerializer PacketSerializer { get; }
|
public IMqttPacketSerializer PacketSerializer { get; }
|
||||||
|
|
||||||
public async Task ConnectAsync(TimeSpan timeout, MqttClientOptions options)
|
public async Task ConnectAsync(TimeSpan timeout)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _channel.ConnectAsync(options).TimeoutAfter(timeout).ConfigureAwait(false);
|
await _channel.ConnectAsync().TimeoutAfter(timeout).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException)
|
catch (TaskCanceledException)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace MQTTnet.Core.Channel
|
namespace MQTTnet.Core.Channel
|
||||||
@@ -10,7 +9,7 @@ namespace MQTTnet.Core.Channel
|
|||||||
Stream ReceiveStream { get; }
|
Stream ReceiveStream { get; }
|
||||||
Stream RawReceiveStream { get; }
|
Stream RawReceiveStream { get; }
|
||||||
|
|
||||||
Task ConnectAsync(MqttClientOptions options);
|
Task ConnectAsync();
|
||||||
Task DisconnectAsync();
|
Task DisconnectAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace MQTTnet.Core.Client
|
|||||||
event EventHandler Connected;
|
event EventHandler Connected;
|
||||||
event EventHandler Disconnected;
|
event EventHandler Disconnected;
|
||||||
|
|
||||||
Task ConnectAsync(MqttApplicationMessage willApplicationMessage = null);
|
Task ConnectAsync(MqttClientOptions options);
|
||||||
Task DisconnectAsync();
|
Task DisconnectAsync();
|
||||||
|
|
||||||
Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
|
Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using MQTTnet.Core.Adapter;
|
||||||
|
|
||||||
|
namespace MQTTnet.Core.Client
|
||||||
|
{
|
||||||
|
public interface IMqttCommunicationAdapterFactory
|
||||||
|
{
|
||||||
|
IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,19 +16,17 @@ namespace MQTTnet.Core.Client
|
|||||||
{
|
{
|
||||||
private readonly HashSet<ushort> _unacknowledgedPublishPackets = new HashSet<ushort>();
|
private readonly HashSet<ushort> _unacknowledgedPublishPackets = new HashSet<ushort>();
|
||||||
private readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher();
|
private readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher();
|
||||||
private readonly MqttClientOptions _options;
|
private readonly IMqttCommunicationAdapterFactory _communicationChannelFactory;
|
||||||
private readonly IMqttCommunicationAdapter _adapter;
|
|
||||||
|
|
||||||
|
private MqttClientOptions _options;
|
||||||
private bool _isReceivingPackets;
|
private bool _isReceivingPackets;
|
||||||
private int _latestPacketIdentifier;
|
private int _latestPacketIdentifier;
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
|
private IMqttCommunicationAdapter _adapter;
|
||||||
|
|
||||||
public MqttClient(MqttClientOptions options, IMqttCommunicationAdapter adapter)
|
public MqttClient(IMqttCommunicationAdapterFactory communicationChannelFactory)
|
||||||
{
|
{
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
_communicationChannelFactory = communicationChannelFactory;
|
||||||
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
|
|
||||||
|
|
||||||
_adapter.PacketSerializer.ProtocolVersion = options.ProtocolVersion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler Connected;
|
public event EventHandler Connected;
|
||||||
@@ -37,22 +35,27 @@ namespace MQTTnet.Core.Client
|
|||||||
|
|
||||||
public bool IsConnected => _cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested;
|
public bool IsConnected => _cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested;
|
||||||
|
|
||||||
public async Task ConnectAsync(MqttApplicationMessage willApplicationMessage = null)
|
public async Task ConnectAsync(MqttClientOptions options)
|
||||||
{
|
{
|
||||||
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
ThrowIfConnected("It is not allowed to connect with a server after the connection is established.");
|
ThrowIfConnected("It is not allowed to connect with a server after the connection is established.");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_options = options;
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
_latestPacketIdentifier = 0;
|
_latestPacketIdentifier = 0;
|
||||||
_packetDispatcher.Reset();
|
_packetDispatcher.Reset();
|
||||||
|
|
||||||
|
_adapter = _communicationChannelFactory.CreateMqttCommunicationAdapter(options);
|
||||||
|
|
||||||
MqttTrace.Verbose(nameof(MqttClient), "Trying to connect with server.");
|
MqttTrace.Verbose(nameof(MqttClient), "Trying to connect with server.");
|
||||||
await _adapter.ConnectAsync(_options.DefaultCommunicationTimeout, _options).ConfigureAwait(false);
|
await _adapter.ConnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false);
|
||||||
MqttTrace.Verbose(nameof(MqttClient), "Connection with server established.");
|
MqttTrace.Verbose(nameof(MqttClient), "Connection with server established.");
|
||||||
|
|
||||||
await SetupIncomingPacketProcessingAsync();
|
await SetupIncomingPacketProcessingAsync();
|
||||||
await AuthenticateAsync(willApplicationMessage);
|
await AuthenticateAsync(options.WillMessage);
|
||||||
|
|
||||||
MqttTrace.Verbose(nameof(MqttClient), "MQTT connection with server established.");
|
MqttTrace.Verbose(nameof(MqttClient), "MQTT connection with server established.");
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,12 @@ using MQTTnet.Core.Serializer;
|
|||||||
|
|
||||||
namespace MQTTnet.Core.Client
|
namespace MQTTnet.Core.Client
|
||||||
{
|
{
|
||||||
public sealed class MqttClientOptions
|
public abstract class MqttClientOptions
|
||||||
{
|
{
|
||||||
public string Server { get; set; }
|
|
||||||
|
|
||||||
public int? Port { get; set; }
|
|
||||||
|
|
||||||
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
||||||
|
|
||||||
|
public MqttApplicationMessage WillMessage { get; set; }
|
||||||
|
|
||||||
public string UserName { get; set; }
|
public string UserName { get; set; }
|
||||||
|
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
@@ -24,7 +22,5 @@ namespace MQTTnet.Core.Client
|
|||||||
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
||||||
|
|
||||||
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
|
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
|
||||||
|
|
||||||
public MqttConnectionType ConnectionType { get; set; } = MqttConnectionType.Tcp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace MQTTnet.Core.Client
|
||||||
|
{
|
||||||
|
public class MqttClientTcpOptions : MqttClientOptions
|
||||||
|
{
|
||||||
|
public string Server { get; set; }
|
||||||
|
|
||||||
|
public int? Port { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace MQTTnet.Core.Client
|
namespace MQTTnet.Core.Client
|
||||||
{
|
{
|
||||||
public static class MqttClientOptionsExtensions
|
public static class MqttClientTcpOptionsExtensions
|
||||||
{
|
{
|
||||||
public static int GetPort(this MqttClientOptions options)
|
public static int GetPort(this MqttClientTcpOptions options)
|
||||||
{
|
{
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace MQTTnet.Core.Client
|
||||||
|
{
|
||||||
|
public class MqttClientWebSocketOptions : MqttClientOptions
|
||||||
|
{
|
||||||
|
public string Uri { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace MQTTnet.Core.Client
|
|
||||||
{
|
|
||||||
public enum MqttConnectionType
|
|
||||||
{
|
|
||||||
Tcp,
|
|
||||||
Ws
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -72,6 +72,9 @@ namespace MQTTnet.Core.Server
|
|||||||
{
|
{
|
||||||
MqttTrace.Warning(nameof(MqttClientPendingMessagesQueue), exception, "Sending publish packet failed due to communication exception.");
|
MqttTrace.Warning(nameof(MqttClientPendingMessagesQueue), exception, "Sending publish packet failed due to communication exception.");
|
||||||
}
|
}
|
||||||
|
if (exception is OperationCanceledException)
|
||||||
|
{
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MqttTrace.Error(nameof(MqttClientPendingMessagesQueue), exception, "Sending publish packet failed.");
|
MqttTrace.Error(nameof(MqttClientPendingMessagesQueue), exception, "Sending publish packet failed.");
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using MQTTnet.Core.Exceptions;
|
|||||||
using MQTTnet.Core.Internal;
|
using MQTTnet.Core.Internal;
|
||||||
using MQTTnet.Core.Packets;
|
using MQTTnet.Core.Packets;
|
||||||
using MQTTnet.Core.Protocol;
|
using MQTTnet.Core.Protocol;
|
||||||
|
using MQTTnet.Core.Serializer;
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
namespace MQTTnet.Core.Server
|
||||||
{
|
{
|
||||||
@@ -19,7 +20,8 @@ namespace MQTTnet.Core.Server
|
|||||||
private readonly MqttClientSessionsManager _mqttClientSessionsManager;
|
private readonly MqttClientSessionsManager _mqttClientSessionsManager;
|
||||||
private readonly MqttClientPendingMessagesQueue _pendingMessagesQueue;
|
private readonly MqttClientPendingMessagesQueue _pendingMessagesQueue;
|
||||||
private readonly MqttServerOptions _options;
|
private readonly MqttServerOptions _options;
|
||||||
|
|
||||||
|
private IMqttCommunicationAdapter _adapter;
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
private MqttApplicationMessage _willMessage;
|
private MqttApplicationMessage _willMessage;
|
||||||
|
|
||||||
@@ -33,9 +35,9 @@ namespace MQTTnet.Core.Server
|
|||||||
|
|
||||||
public string ClientId { get; }
|
public string ClientId { get; }
|
||||||
|
|
||||||
public bool IsConnected => Adapter != null;
|
public MqttProtocolVersion? ProtocolVersion => _adapter?.PacketSerializer.ProtocolVersion;
|
||||||
|
|
||||||
public IMqttCommunicationAdapter Adapter { get; private set; }
|
public bool IsConnected => _adapter != null;
|
||||||
|
|
||||||
public async Task RunAsync(MqttApplicationMessage willMessage, IMqttCommunicationAdapter adapter)
|
public async Task RunAsync(MqttApplicationMessage willMessage, IMqttCommunicationAdapter adapter)
|
||||||
{
|
{
|
||||||
@@ -45,7 +47,7 @@ namespace MQTTnet.Core.Server
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Adapter = adapter;
|
_adapter = adapter;
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
_pendingMessagesQueue.Start(adapter, _cancellationTokenSource.Token);
|
_pendingMessagesQueue.Start(adapter, _cancellationTokenSource.Token);
|
||||||
@@ -75,7 +77,7 @@ namespace MQTTnet.Core.Server
|
|||||||
_cancellationTokenSource?.Dispose();
|
_cancellationTokenSource?.Dispose();
|
||||||
_cancellationTokenSource = null;
|
_cancellationTokenSource = null;
|
||||||
|
|
||||||
Adapter = null;
|
_adapter = null;
|
||||||
|
|
||||||
MqttTrace.Information(nameof(MqttClientSession), "Client '{0}': Disconnected.", ClientId);
|
MqttTrace.Information(nameof(MqttClientSession), "Client '{0}': Disconnected.", ClientId);
|
||||||
}
|
}
|
||||||
@@ -106,7 +108,7 @@ namespace MQTTnet.Core.Server
|
|||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
var packet = await adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(false);
|
var packet = await adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(false);
|
||||||
await ProcessReceivedPacketAsync(packet).ConfigureAwait(false);
|
await ProcessReceivedPacketAsync(adapter, packet).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
@@ -124,28 +126,28 @@ namespace MQTTnet.Core.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessReceivedPacketAsync(MqttBasePacket packet)
|
private async Task ProcessReceivedPacketAsync(IMqttCommunicationAdapter adapter, MqttBasePacket packet)
|
||||||
{
|
{
|
||||||
if (packet is MqttSubscribePacket subscribePacket)
|
if (packet is MqttSubscribePacket subscribePacket)
|
||||||
{
|
{
|
||||||
await Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, _subscriptionsManager.Subscribe(subscribePacket));
|
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, _subscriptionsManager.Subscribe(subscribePacket));
|
||||||
EnqueueRetainedMessages(subscribePacket);
|
EnqueueRetainedMessages(subscribePacket);
|
||||||
}
|
}
|
||||||
else if (packet is MqttUnsubscribePacket unsubscribePacket)
|
else if (packet is MqttUnsubscribePacket unsubscribePacket)
|
||||||
{
|
{
|
||||||
await Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, _subscriptionsManager.Unsubscribe(unsubscribePacket));
|
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, _subscriptionsManager.Unsubscribe(unsubscribePacket));
|
||||||
}
|
}
|
||||||
else if (packet is MqttPublishPacket publishPacket)
|
else if (packet is MqttPublishPacket publishPacket)
|
||||||
{
|
{
|
||||||
await HandleIncomingPublishPacketAsync(publishPacket);
|
await HandleIncomingPublishPacketAsync(adapter, publishPacket);
|
||||||
}
|
}
|
||||||
else if (packet is MqttPubRelPacket pubRelPacket)
|
else if (packet is MqttPubRelPacket pubRelPacket)
|
||||||
{
|
{
|
||||||
await HandleIncomingPubRelPacketAsync(pubRelPacket);
|
await HandleIncomingPubRelPacketAsync(adapter, pubRelPacket);
|
||||||
}
|
}
|
||||||
else if (packet is MqttPubRecPacket pubRecPacket)
|
else if (packet is MqttPubRecPacket pubRecPacket)
|
||||||
{
|
{
|
||||||
await Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, pubRecPacket.CreateResponse<MqttPubRelPacket>());
|
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, pubRecPacket.CreateResponse<MqttPubRelPacket>());
|
||||||
}
|
}
|
||||||
else if (packet is MqttPubAckPacket || packet is MqttPubCompPacket)
|
else if (packet is MqttPubAckPacket || packet is MqttPubCompPacket)
|
||||||
{
|
{
|
||||||
@@ -153,7 +155,7 @@ namespace MQTTnet.Core.Server
|
|||||||
}
|
}
|
||||||
else if (packet is MqttPingReqPacket)
|
else if (packet is MqttPingReqPacket)
|
||||||
{
|
{
|
||||||
await Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPingRespPacket());
|
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPingRespPacket());
|
||||||
}
|
}
|
||||||
else if (packet is MqttDisconnectPacket || packet is MqttConnectPacket)
|
else if (packet is MqttDisconnectPacket || packet is MqttConnectPacket)
|
||||||
{
|
{
|
||||||
@@ -175,7 +177,7 @@ namespace MQTTnet.Core.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleIncomingPublishPacketAsync(MqttPublishPacket publishPacket)
|
private async Task HandleIncomingPublishPacketAsync(IMqttCommunicationAdapter adapter, MqttPublishPacket publishPacket)
|
||||||
{
|
{
|
||||||
if (publishPacket.Retain)
|
if (publishPacket.Retain)
|
||||||
{
|
{
|
||||||
@@ -191,7 +193,7 @@ namespace MQTTnet.Core.Server
|
|||||||
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
|
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
|
||||||
{
|
{
|
||||||
_mqttClientSessionsManager.DispatchPublishPacket(this, publishPacket);
|
_mqttClientSessionsManager.DispatchPublishPacket(this, publishPacket);
|
||||||
await Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier });
|
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,21 +207,21 @@ namespace MQTTnet.Core.Server
|
|||||||
|
|
||||||
_mqttClientSessionsManager.DispatchPublishPacket(this, publishPacket);
|
_mqttClientSessionsManager.DispatchPublishPacket(this, publishPacket);
|
||||||
|
|
||||||
await Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier });
|
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new MqttCommunicationException("Received a not supported QoS level.");
|
throw new MqttCommunicationException("Received a not supported QoS level.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task HandleIncomingPubRelPacketAsync(MqttPubRelPacket pubRelPacket)
|
private Task HandleIncomingPubRelPacketAsync(IMqttCommunicationAdapter adapter, MqttPubRelPacket pubRelPacket)
|
||||||
{
|
{
|
||||||
lock (_unacknowledgedPublishPackets)
|
lock (_unacknowledgedPublishPackets)
|
||||||
{
|
{
|
||||||
_unacknowledgedPublishPackets.Remove(pubRelPacket.PacketIdentifier);
|
_unacknowledgedPublishPackets.Remove(pubRelPacket.PacketIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPubCompPacket { PacketIdentifier = pubRelPacket.PacketIdentifier });
|
return adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPubCompPacket { PacketIdentifier = pubRelPacket.PacketIdentifier });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using MQTTnet.Core.Exceptions;
|
|||||||
using MQTTnet.Core.Internal;
|
using MQTTnet.Core.Internal;
|
||||||
using MQTTnet.Core.Packets;
|
using MQTTnet.Core.Packets;
|
||||||
using MQTTnet.Core.Protocol;
|
using MQTTnet.Core.Protocol;
|
||||||
|
using MQTTnet.Core.Serializer;
|
||||||
|
|
||||||
namespace MQTTnet.Core.Server
|
namespace MQTTnet.Core.Server
|
||||||
{
|
{
|
||||||
@@ -24,9 +25,7 @@ namespace MQTTnet.Core.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
|
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
|
||||||
|
|
||||||
public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
|
public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
|
||||||
|
|
||||||
public event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected;
|
public event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected;
|
||||||
|
|
||||||
public MqttClientRetainedMessagesManager RetainedMessagesManager { get; }
|
public MqttClientRetainedMessagesManager RetainedMessagesManager { get; }
|
||||||
@@ -111,7 +110,7 @@ namespace MQTTnet.Core.Server
|
|||||||
return _clientSessions.Where(s => s.Value.IsConnected).Select(s => new ConnectedMqttClient
|
return _clientSessions.Where(s => s.Value.IsConnected).Select(s => new ConnectedMqttClient
|
||||||
{
|
{
|
||||||
ClientId = s.Value.ClientId,
|
ClientId = s.Value.ClientId,
|
||||||
ProtocolVersion = s.Value.Adapter.PacketSerializer.ProtocolVersion
|
ProtocolVersion = s.Value.ProtocolVersion ?? MqttProtocolVersion.V311
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26730.16
|
VisualStudioVersion = 15.0.26730.16
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Core.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Core.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Core.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.NetFramework", "Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj", "{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.NetFramework", "Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj", "{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ MQTTnet is a .NET library for MQTT based communication. It provides a MQTT clien
|
|||||||
* Performance optimized (processing ~27.000 messages / second)*
|
* Performance optimized (processing ~27.000 messages / second)*
|
||||||
* Interfaces included for mocking and testing
|
* Interfaces included for mocking and testing
|
||||||
* Access to internal trace messages
|
* Access to internal trace messages
|
||||||
* Unit tested (57+ tests)
|
* Unit tested (58+ tests)
|
||||||
|
|
||||||
\* Tested on local machine with MQTTnet client and server running in the same process using the TCP channel. The app for verification is part of this repository and stored in _/Tests/MQTTnet.TestApp.NetFramework_.
|
\* Tested on local machine with MQTTnet client and server running in the same process using the TCP channel. The app for verification is part of this repository and stored in _/Tests/MQTTnet.TestApp.NetFramework_.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using MQTTnet.Core.Adapter;
|
||||||
|
using MQTTnet.Core.Client;
|
||||||
|
|
||||||
|
namespace MQTTnet.Core.Tests
|
||||||
|
{
|
||||||
|
public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory
|
||||||
|
{
|
||||||
|
private readonly IMqttCommunicationAdapter _adapter;
|
||||||
|
|
||||||
|
public MqttCommunicationAdapterFactory(IMqttCommunicationAdapter adapter)
|
||||||
|
{
|
||||||
|
_adapter = adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options)
|
||||||
|
{
|
||||||
|
return _adapter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using MQTTnet.Core.Adapter;
|
using MQTTnet.Core.Adapter;
|
||||||
using MQTTnet.Core.Channel;
|
using MQTTnet.Core.Channel;
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Packets;
|
using MQTTnet.Core.Packets;
|
||||||
using MQTTnet.Core.Protocol;
|
using MQTTnet.Core.Protocol;
|
||||||
using MQTTnet.Core.Serializer;
|
using MQTTnet.Core.Serializer;
|
||||||
@@ -411,7 +410,7 @@ namespace MQTTnet.Core.Tests
|
|||||||
_stream.Position = 0;
|
_stream.Position = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ConnectAsync(MqttClientOptions options)
|
public Task ConnectAsync()
|
||||||
{
|
{
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using MQTTnet.Core.Client;
|
|||||||
using MQTTnet.Core.Packets;
|
using MQTTnet.Core.Packets;
|
||||||
using MQTTnet.Core.Protocol;
|
using MQTTnet.Core.Protocol;
|
||||||
using MQTTnet.Core.Server;
|
using MQTTnet.Core.Server;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Core.Tests
|
namespace MQTTnet.Core.Tests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using System.Collections.Generic;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Core.Adapter;
|
using MQTTnet.Core.Adapter;
|
||||||
using MQTTnet.Core.Client;
|
|
||||||
using MQTTnet.Core.Packets;
|
using MQTTnet.Core.Packets;
|
||||||
using MQTTnet.Core.Serializer;
|
using MQTTnet.Core.Serializer;
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ namespace MQTTnet.Core.Tests
|
|||||||
|
|
||||||
public IMqttPacketSerializer PacketSerializer { get; } = new MqttPacketSerializer();
|
public IMqttPacketSerializer PacketSerializer { get; } = new MqttPacketSerializer();
|
||||||
|
|
||||||
public Task ConnectAsync(TimeSpan timeout, MqttClientOptions options)
|
public Task ConnectAsync(TimeSpan timeout)
|
||||||
{
|
{
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,11 @@ namespace MQTTnet.Core.Tests
|
|||||||
adapterA.Partner = adapterB;
|
adapterA.Partner = adapterB;
|
||||||
adapterB.Partner = adapterA;
|
adapterB.Partner = adapterA;
|
||||||
|
|
||||||
var client = new MqttClient(new MqttClientOptions() { ClientId = clientId }, adapterA);
|
var client = new MqttClient(new MqttCommunicationAdapterFactory(adapterA));
|
||||||
var connected = WaitForClientToConnect(server, clientId);
|
var connected = WaitForClientToConnect(server, clientId);
|
||||||
|
|
||||||
FireClientAcceptedEvent(adapterB);
|
FireClientAcceptedEvent(adapterB);
|
||||||
await client.ConnectAsync(willMessage);
|
await client.ConnectAsync(new MqttClientTcpOptions { ClientId = clientId, WillMessage = willMessage });
|
||||||
await connected;
|
await connected;
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
@@ -30,17 +31,16 @@ namespace MQTTnet.Core.Tests
|
|||||||
{
|
{
|
||||||
var tcs = new TaskCompletionSource<object>();
|
var tcs = new TaskCompletionSource<object>();
|
||||||
|
|
||||||
EventHandler<MqttClientConnectedEventArgs> handler = null;
|
void Handler(object sender, MqttClientConnectedEventArgs args)
|
||||||
handler = (sender, args) =>
|
|
||||||
{
|
{
|
||||||
if (args.Client.ClientId == clientId)
|
if (args.Client.ClientId == clientId)
|
||||||
{
|
{
|
||||||
s.ClientConnected -= handler;
|
s.ClientConnected -= Handler;
|
||||||
tcs.SetResult(null);
|
tcs.SetResult(null);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
s.ClientConnected += handler;
|
s.ClientConnected += Handler;
|
||||||
|
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,12 +46,11 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var options = new MqttClientOptions
|
var options = new MqttClientWebSocketOptions
|
||||||
{
|
{
|
||||||
Server = "localhost",
|
Uri = "localhost",
|
||||||
ClientId = "XYZ",
|
ClientId = "XYZ",
|
||||||
CleanSession = true,
|
CleanSession = true
|
||||||
ConnectionType = MqttConnectionType.Ws
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var client = new MqttClientFactory().CreateMqttClient(options);
|
var client = new MqttClientFactory().CreateMqttClient(options);
|
||||||
@@ -84,7 +83,7 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await client.ConnectAsync();
|
await client.ConnectAsync(options);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -94,7 +93,7 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await client.ConnectAsync();
|
await client.ConnectAsync(options);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace MQTTnet.TestApp.NetFramework
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var options = new MqttClientOptions
|
var options = new MqttClientTcpOptions
|
||||||
{
|
{
|
||||||
Server = "localhost",
|
Server = "localhost",
|
||||||
ClientId = "XYZ",
|
ClientId = "XYZ",
|
||||||
@@ -64,7 +64,7 @@ namespace MQTTnet.TestApp.NetFramework
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await client.ConnectAsync();
|
await client.ConnectAsync(options);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -74,7 +74,7 @@ namespace MQTTnet.TestApp.NetFramework
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await client.ConnectAsync();
|
await client.ConnectAsync(options);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -52,13 +52,18 @@ namespace MQTTnet.TestApp.NetFramework
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var options = new MqttClientOptions
|
var options = new MqttClientWebSocketOptions
|
||||||
{
|
{
|
||||||
Server = "localhost",
|
Uri = "broker.hivemq.com:8000/mqtt"
|
||||||
ClientId = "XYZ",
|
|
||||||
CleanSession = true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////var options = new MqttClientOptions
|
||||||
|
////{
|
||||||
|
//// Server = "localhost",
|
||||||
|
//// ClientId = "XYZ",
|
||||||
|
//// CleanSession = true
|
||||||
|
////};
|
||||||
|
|
||||||
var client = new MqttClientFactory().CreateMqttClient(options);
|
var client = new MqttClientFactory().CreateMqttClient(options);
|
||||||
client.ApplicationMessageReceived += (s, e) =>
|
client.ApplicationMessageReceived += (s, e) =>
|
||||||
{
|
{
|
||||||
@@ -87,7 +92,7 @@ namespace MQTTnet.TestApp.NetFramework
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await client.ConnectAsync();
|
await client.ConnectAsync(options);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -97,7 +102,7 @@ namespace MQTTnet.TestApp.NetFramework
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await client.ConnectAsync();
|
await client.ConnectAsync(options);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,15 +37,32 @@ namespace MQTTnet.TestApp.UniversalWindows
|
|||||||
|
|
||||||
private async void Connect(object sender, RoutedEventArgs e)
|
private async void Connect(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var options = new MqttClientOptions
|
MqttClientOptions options = null;
|
||||||
|
if (UseTcp.IsChecked == true)
|
||||||
{
|
{
|
||||||
Server = Server.Text,
|
options = new MqttClientTcpOptions
|
||||||
UserName = User.Text,
|
{
|
||||||
Password = Password.Text,
|
Server = Server.Text
|
||||||
ClientId = ClientId.Text,
|
};
|
||||||
TlsOptions = { UseTls = UseTls.IsChecked == true },
|
}
|
||||||
ConnectionType = UseTcp.IsChecked == true ? MqttConnectionType.Tcp : MqttConnectionType.Ws
|
|
||||||
};
|
if (UseWs.IsChecked == true)
|
||||||
|
{
|
||||||
|
options = new MqttClientWebSocketOptions
|
||||||
|
{
|
||||||
|
Uri = Server.Text
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
options.UserName = User.Text;
|
||||||
|
options.Password = Password.Text;
|
||||||
|
options.ClientId = ClientId.Text;
|
||||||
|
options.TlsOptions.UseTls = UseTls.IsChecked == true;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -56,7 +73,7 @@ namespace MQTTnet.TestApp.UniversalWindows
|
|||||||
|
|
||||||
var factory = new MqttClientFactory();
|
var factory = new MqttClientFactory();
|
||||||
_mqttClient = factory.CreateMqttClient(options);
|
_mqttClient = factory.CreateMqttClient(options);
|
||||||
await _mqttClient.ConnectAsync();
|
await _mqttClient.ConnectAsync(options);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user