Merge pull request #2 from chkr1011/develop

From develop
This commit is contained in:
Gerardo
2017-10-26 12:09:02 +02:00
committed by GitHub
49 changed files with 586 additions and 381 deletions
+5
View File
@@ -13,12 +13,17 @@
<releaseNotes>* [Core] Merged the .NET Framwork and netstandard projects (Thanks to @JanEggers) <releaseNotes>* [Core] Merged the .NET Framwork and netstandard projects (Thanks to @JanEggers)
* [Core] Migrated the trace to a non-static approach (Breaking Change!) * [Core] Migrated the trace to a non-static approach (Breaking Change!)
* [Core] Added a builder for application messages using a fluent API * [Core] Added a builder for application messages using a fluent API
* [Core] Introduced CI (Thanks to @JanEggers)
* [Core] Added interfaces for publishing and receiving which applies to every client and server (Thanks to @ChristianRiedl)
* [Client] Added a first version of a managed client which will manage the connection, subscription etc. automatically (Thanks to @JTrotta) * [Client] Added a first version of a managed client which will manage the connection, subscription etc. automatically (Thanks to @JTrotta)
* [Client] The session state response from the server is now returned in the _ConnectAsync_ method and also part of the _Connected_ event args * [Client] The session state response from the server is now returned in the _ConnectAsync_ method and also part of the _Connected_ event args
* [Client] Added a _TopicFilterBuilder_ using a fluent API (Namespace Changes!) * [Client] Added a _TopicFilterBuilder_ using a fluent API (Namespace Changes!)
* [Client] Added several new options for the WebSocket channel (Thanks to @ChristianRiedl) * [Client] Added several new options for the WebSocket channel (Thanks to @ChristianRiedl)
* [Client] Refactored the options and added a builder using a fluent API (Breaking Change!)
* [Client] Added more options for WebSocket connections like RequestHeaders, SubProtocol etc.
* [Server] Added support for WebSockets via ASP.NET Core 2.0 (Thanks to @ChristianRiedl) * [Server] Added support for WebSockets via ASP.NET Core 2.0 (Thanks to @ChristianRiedl)
* [Server] Added support for a custom application message interceptor * [Server] Added support for a custom application message interceptor
* [Server] Fixed an issue with dropped connections on UWP (Thanks to @haeberle)
</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 ESP Smart Home Cities Automation</tags> <tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation</tags>
@@ -1,7 +1,6 @@
using System; using System;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using MQTTnet.AspNetCore;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
namespace MQTTnet.AspnetCore namespace MQTTnet.AspnetCore
@@ -8,7 +8,7 @@ using MQTTnet.Core.Channel;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using MQTTnet.Implementations; using MQTTnet.Implementations;
namespace MQTTnet.AspNetCore namespace MQTTnet.AspnetCore
{ {
public class MqttWebSocketServerAdapter : IMqttServerAdapter, IDisposable public class MqttWebSocketServerAdapter : IMqttServerAdapter, IDisposable
{ {
@@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using MQTTnet.AspNetCore;
using MQTTnet.Core.Adapter; using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
@@ -7,10 +7,8 @@ using System.Security.Cryptography.X509Certificates;
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.Serializer;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using MQTTnet.Core.Client;
namespace MQTTnet.Implementations namespace MQTTnet.Implementations
{ {
@@ -18,6 +16,7 @@ namespace MQTTnet.Implementations
{ {
private readonly ILogger<MqttServerAdapter> _logger; private readonly ILogger<MqttServerAdapter> _logger;
private readonly IMqttCommunicationAdapterFactory _mqttCommunicationAdapterFactory; private readonly IMqttCommunicationAdapterFactory _mqttCommunicationAdapterFactory;
private CancellationTokenSource _cancellationTokenSource; private CancellationTokenSource _cancellationTokenSource;
private Socket _defaultEndpointSocket; private Socket _defaultEndpointSocket;
private Socket _tlsEndpointSocket; private Socket _tlsEndpointSocket;
@@ -15,7 +15,7 @@ namespace MQTTnet.Implementations
{ {
private readonly MqttClientTcpOptions _options; private readonly MqttClientTcpOptions _options;
//todo: this can be used with min dependency NetStandard1.6 //todo: this can be used with min dependency NetStandard1.6
#if NET45 #if NET45
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
@@ -58,7 +58,7 @@ namespace MQTTnet.Implementations
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp); _socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
} }
//todo: else brach can be used with min dependency NET46 //todo: else brach can be used with min dependency NET46
#if NET451 #if NET451
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);
#else #else
@@ -120,7 +120,7 @@ namespace MQTTnet.Implementations
return _options.TlsOptions.AllowUntrustedCertificates; return _options.TlsOptions.AllowUntrustedCertificates;
} }
private static X509CertificateCollection LoadCertificates(IMqttClientOptions options) private static X509CertificateCollection LoadCertificates(MqttClientTcpOptions options)
{ {
var certificates = new X509CertificateCollection(); var certificates = new X509CertificateCollection();
if (options.TlsOptions.Certificates == null) if (options.TlsOptions.Certificates == null)
@@ -144,7 +144,7 @@ namespace MQTTnet.Implementations
//cannot use this as default buffering prevents from receiving the first connect message //cannot use this as default buffering prevents from receiving the first connect message
//need two streams otherwise read and write have to be synchronized //need two streams otherwise read and write have to be synchronized
//todo: if branch can be used with min dependency NetStandard1.6 //todo: if branch can be used with min dependency NetStandard1.6
#if NET45 #if NET45
SendStream = new BufferedStream(RawReceiveStream, BufferSize); SendStream = new BufferedStream(RawReceiveStream, BufferSize);
ReceiveStream = new BufferedStream(RawReceiveStream, BufferSize); ReceiveStream = new BufferedStream(RawReceiveStream, BufferSize);
@@ -32,7 +32,6 @@ namespace MQTTnet.Implementations
} }
_webSocket = new ClientWebSocket(); _webSocket = new ClientWebSocket();
_webSocket.Options.KeepAliveInterval = _options.KeepAlivePeriod;
if (_options.RequestHeaders != null) if (_options.RequestHeaders != null)
{ {
@@ -77,12 +76,16 @@ namespace MQTTnet.Implementations
return; return;
} }
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).ConfigureAwait(false); if (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.Connecting)
{
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).ConfigureAwait(false);
}
} }
public void Dispose() public void Dispose()
{ {
_webSocket?.Dispose(); _webSocket?.Dispose();
_webSocket = null;
} }
} }
} }
+11 -7
View File
@@ -7,7 +7,6 @@ using Microsoft.Extensions.DependencyInjection;
using MQTTnet.Implementations; using MQTTnet.Implementations;
using MQTTnet.Core.ManagedClient; using MQTTnet.Core.ManagedClient;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using System.Linq;
using MQTTnet.Core.Channel; using MQTTnet.Core.Channel;
namespace MQTTnet namespace MQTTnet
@@ -18,7 +17,7 @@ namespace MQTTnet
private static IServiceProvider BuildServiceProvider() private static IServiceProvider BuildServiceProvider()
{ {
var serviceProvider = new ServiceCollection() var serviceProvider = new ServiceCollection()
.AddMqttClient() .AddMqttClient()
.AddMqttServer() .AddMqttServer()
.AddLogging() .AddLogging()
@@ -40,10 +39,15 @@ namespace MQTTnet
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
} }
public ILoggerFactory GetLoggerFactory()
{
return _serviceProvider.GetRequiredService<ILoggerFactory>();
}
public IMqttCommunicationAdapter CreateClientMqttCommunicationAdapter(IMqttClientOptions options) public IMqttCommunicationAdapter CreateClientMqttCommunicationAdapter(IMqttClientOptions options)
{ {
var logger = _serviceProvider.GetRequiredService<ILogger<MqttChannelCommunicationAdapter>>(); var logger = _serviceProvider.GetRequiredService<ILogger<MqttChannelCommunicationAdapter>>();
return new MqttChannelCommunicationAdapter(CreateMqttCommunicationChannel(options), CreateSerializer(options.ProtocolVersion), logger); return new MqttChannelCommunicationAdapter(CreateMqttCommunicationChannel(options.ChannelOptions), CreateSerializer(options.ProtocolVersion), logger);
} }
public IMqttCommunicationAdapter CreateServerMqttCommunicationAdapter(IMqttCommunicationChannel channel) public IMqttCommunicationAdapter CreateServerMqttCommunicationAdapter(IMqttCommunicationChannel channel)
@@ -53,7 +57,7 @@ namespace MQTTnet
return new MqttChannelCommunicationAdapter(channel, serializer, logger); return new MqttChannelCommunicationAdapter(channel, serializer, logger);
} }
public IMqttCommunicationChannel CreateMqttCommunicationChannel(IMqttClientOptions options) public IMqttCommunicationChannel CreateMqttCommunicationChannel(IMqttClientChannelOptions options)
{ {
if (options == null) throw new ArgumentNullException(nameof(options)); if (options == null) throw new ArgumentNullException(nameof(options));
@@ -80,7 +84,7 @@ namespace MQTTnet
public MqttPacketSerializer CreateSerializer(MqttProtocolVersion protocolVersion) public MqttPacketSerializer CreateSerializer(MqttProtocolVersion protocolVersion)
{ {
return new MqttPacketSerializer() return new MqttPacketSerializer
{ {
ProtocolVersion = protocolVersion ProtocolVersion = protocolVersion
}; };
@@ -96,9 +100,9 @@ namespace MQTTnet
return _serviceProvider.GetRequiredService<IMqttClient>(); return _serviceProvider.GetRequiredService<IMqttClient>();
} }
public ManagedMqttClient CreateManagedMqttClient() public IManagedMqttClient CreateManagedMqttClient()
{ {
return _serviceProvider.GetRequiredService<ManagedMqttClient>(); return _serviceProvider.GetRequiredService<IManagedMqttClient>();
} }
public IMqttServer CreateMqttServer() public IMqttServer CreateMqttServer()
@@ -52,8 +52,9 @@ namespace MQTTnet
services.AddTransient<IMqttClient, MqttClient>(); services.AddTransient<IMqttClient, MqttClient>();
services.AddTransient<MqttClient>(); services.AddTransient<MqttClient>();
services.AddTransient<IMqttPacketSerializer, MqttPacketSerializer>(); services.AddTransient<IManagedMqttClient, ManagedMqttClient>();
services.AddTransient<ManagedMqttClient>(); services.AddTransient<ManagedMqttClient>();
services.AddTransient<IMqttPacketSerializer, MqttPacketSerializer>();
services.AddTransient<MqttPacketDispatcher>(); services.AddTransient<MqttPacketDispatcher>();
return services; return services;
@@ -89,7 +89,7 @@ namespace MQTTnet.Implementations
RawReceiveStream = ReceiveStream; RawReceiveStream = ReceiveStream;
} }
private static Certificate LoadCertificate(BaseMqttClientOptions options) private static Certificate LoadCertificate(MqttClientTcpOptions options)
{ {
if (options.TlsOptions.Certificates == null || !options.TlsOptions.Certificates.Any()) if (options.TlsOptions.Certificates == null || !options.TlsOptions.Certificates.Any())
{ {
@@ -32,7 +32,6 @@ namespace MQTTnet.Implementations
} }
_webSocket = new ClientWebSocket(); _webSocket = new ClientWebSocket();
_webSocket.Options.KeepAliveInterval = _options.KeepAlivePeriod;
if (_options.RequestHeaders != null) if (_options.RequestHeaders != null)
{ {
@@ -78,12 +77,16 @@ namespace MQTTnet.Implementations
return; return;
} }
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).ConfigureAwait(false); if (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.Connecting)
{
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).ConfigureAwait(false);
}
} }
public void Dispose() public void Dispose()
{ {
_webSocket?.Dispose(); _webSocket?.Dispose();
_webSocket = null;
} }
} }
} }
@@ -42,7 +42,7 @@ namespace MQTTnet
public IMqttCommunicationAdapter CreateClientMqttCommunicationAdapter(IMqttClientOptions options) public IMqttCommunicationAdapter CreateClientMqttCommunicationAdapter(IMqttClientOptions options)
{ {
var logger = _serviceProvider.GetRequiredService<ILogger<MqttChannelCommunicationAdapter>>(); var logger = _serviceProvider.GetRequiredService<ILogger<MqttChannelCommunicationAdapter>>();
return new MqttChannelCommunicationAdapter(CreateMqttCommunicationChannel(options), CreateSerializer(options.ProtocolVersion), logger); return new MqttChannelCommunicationAdapter(CreateMqttCommunicationChannel(options.ChannelOptions), CreateSerializer(options.ProtocolVersion), logger);
} }
public IMqttCommunicationAdapter CreateServerMqttCommunicationAdapter(IMqttCommunicationChannel channel) public IMqttCommunicationAdapter CreateServerMqttCommunicationAdapter(IMqttCommunicationChannel channel)
@@ -52,7 +52,7 @@ namespace MQTTnet
return new MqttChannelCommunicationAdapter(channel, serializer, logger); return new MqttChannelCommunicationAdapter(channel, serializer, logger);
} }
public IMqttCommunicationChannel CreateMqttCommunicationChannel(IMqttClientOptions options) public IMqttCommunicationChannel CreateMqttCommunicationChannel(IMqttClientChannelOptions options)
{ {
if (options == null) throw new ArgumentNullException(nameof(options)); if (options == null) throw new ArgumentNullException(nameof(options));
@@ -79,7 +79,7 @@ namespace MQTTnet
public MqttPacketSerializer CreateSerializer(MqttProtocolVersion protocolVersion) public MqttPacketSerializer CreateSerializer(MqttProtocolVersion protocolVersion)
{ {
return new MqttPacketSerializer() return new MqttPacketSerializer
{ {
ProtocolVersion = protocolVersion ProtocolVersion = protocolVersion
}; };
@@ -95,7 +95,7 @@ namespace MQTTnet
return _serviceProvider.GetRequiredService<IMqttClient>(); return _serviceProvider.GetRequiredService<IMqttClient>();
} }
public ManagedMqttClient CreateManagedMqttClient() public IManagedMqttClient CreateManagedMqttClient()
{ {
return _serviceProvider.GetRequiredService<ManagedMqttClient>(); return _serviceProvider.GetRequiredService<ManagedMqttClient>();
} }
@@ -46,8 +46,9 @@ namespace MQTTnet
services.AddTransient<IMqttClient, MqttClient>(); services.AddTransient<IMqttClient, MqttClient>();
services.AddTransient<MqttClient>(); services.AddTransient<MqttClient>();
services.AddTransient<IMqttPacketSerializer, MqttPacketSerializer>(); services.AddTransient<IManagedMqttClient, ManagedMqttClient>();
services.AddTransient<ManagedMqttClient>(); services.AddTransient<ManagedMqttClient>();
services.AddTransient<IMqttPacketSerializer, MqttPacketSerializer>();
services.AddTransient<MqttPacketDispatcher>(); services.AddTransient<MqttPacketDispatcher>();
return services; return services;
@@ -0,0 +1,10 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MQTTnet.Core.Client
{
public interface IApplicationMessagePublisher
{
Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages);
}
}
+1 -3
View File
@@ -5,7 +5,7 @@ using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Client namespace MQTTnet.Core.Client
{ {
public interface IMqttClient : IApplicationMessageReceiver public interface IMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher
{ {
bool IsConnected { get; } bool IsConnected { get; }
@@ -17,7 +17,5 @@ namespace MQTTnet.Core.Client
Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters); Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
Task UnsubscribeAsync(IEnumerable<string> topicFilters); Task UnsubscribeAsync(IEnumerable<string> topicFilters);
Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages);
} }
} }
@@ -0,0 +1,7 @@
namespace MQTTnet.Core.Client
{
public interface IMqttClientChannelOptions
{
MqttClientTlsOptions TlsOptions { get; }
}
}
@@ -0,0 +1,8 @@
namespace MQTTnet.Core.Client
{
public interface IMqttClientCredentials
{
string Password { get; }
string Username { get; }
}
}
+1 -1
View File
@@ -6,6 +6,6 @@ namespace MQTTnet.Core.Client
{ {
IMqttClient CreateMqttClient(); IMqttClient CreateMqttClient();
ManagedMqttClient CreateManagedMqttClient(); IManagedMqttClient CreateManagedMqttClient();
} }
} }
+8 -7
View File
@@ -5,14 +5,15 @@ namespace MQTTnet.Core.Client
{ {
public interface IMqttClientOptions public interface IMqttClientOptions
{ {
bool CleanSession { get; }
string ClientId { get; } string ClientId { get; }
TimeSpan DefaultCommunicationTimeout { get; } IMqttClientCredentials Credentials { get; }
TimeSpan KeepAlivePeriod { get; } bool CleanSession { get; }
string Password { get; }
MqttProtocolVersion ProtocolVersion { get; }
MqttClientTlsOptions TlsOptions { get; }
string UserName { get; }
MqttApplicationMessage WillMessage { get; } MqttApplicationMessage WillMessage { get; }
TimeSpan CommunicationTimeout { get; }
TimeSpan KeepAlivePeriod { get; }
MqttProtocolVersion ProtocolVersion { get; }
IMqttClientChannelOptions ChannelOptions { get; }
} }
} }
@@ -4,11 +4,14 @@ namespace MQTTnet.Core.Client
{ {
public sealed class MqttApplicationMessageReceivedEventArgs : EventArgs public sealed class MqttApplicationMessageReceivedEventArgs : EventArgs
{ {
public MqttApplicationMessageReceivedEventArgs(MqttApplicationMessage applicationMessage) public MqttApplicationMessageReceivedEventArgs(string clientId, MqttApplicationMessage applicationMessage)
{ {
ClientId = clientId;
ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage)); ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage));
} }
public string ClientId { get; }
public MqttApplicationMessage ApplicationMessage { get; } public MqttApplicationMessage ApplicationMessage { get; }
} }
} }
+12 -10
View File
@@ -42,6 +42,7 @@ namespace MQTTnet.Core.Client
public async Task<MqttClientConnectResult> ConnectAsync(IMqttClientOptions options) public async Task<MqttClientConnectResult> ConnectAsync(IMqttClientOptions options)
{ {
if (options == null) throw new ArgumentNullException(nameof(options)); if (options == null) throw new ArgumentNullException(nameof(options));
if (options.ChannelOptions == null) throw new ArgumentException("ChannelOptions are not set.");
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.");
@@ -56,7 +57,7 @@ namespace MQTTnet.Core.Client
_scopeHandle = _logger.BeginScope(options.ClientId); _scopeHandle = _logger.BeginScope(options.ClientId);
_logger.LogTrace("Trying to connect with server."); _logger.LogTrace("Trying to connect with server.");
await _adapter.ConnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false); await _adapter.ConnectAsync(_options.CommunicationTimeout).ConfigureAwait(false);
_logger.LogTrace("Connection with server established."); _logger.LogTrace("Connection with server established.");
await SetupIncomingPacketProcessingAsync(); await SetupIncomingPacketProcessingAsync();
@@ -73,8 +74,9 @@ namespace MQTTnet.Core.Client
Connected?.Invoke(this, new MqttClientConnectedEventArgs(connectResponse.IsSessionPresent)); Connected?.Invoke(this, new MqttClientConnectedEventArgs(connectResponse.IsSessionPresent));
return new MqttClientConnectResult(connectResponse.IsSessionPresent); return new MqttClientConnectResult(connectResponse.IsSessionPresent);
} }
catch (Exception) catch (Exception exception)
{ {
_logger.LogError(new EventId(), exception, "Error while connecting with server.");
await DisconnectInternalAsync().ConfigureAwait(false); await DisconnectInternalAsync().ConfigureAwait(false);
throw; throw;
} }
@@ -149,7 +151,7 @@ namespace MQTTnet.Core.Client
case MqttQualityOfServiceLevel.AtMostOnce: case MqttQualityOfServiceLevel.AtMostOnce:
{ {
// No packet identifier is used for QoS 0 [3.3.2.2 Packet Identifier] // No packet identifier is used for QoS 0 [3.3.2.2 Packet Identifier]
await _adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, qosPackets); await _adapter.SendPacketsAsync(_options.CommunicationTimeout, _cancellationTokenSource.Token, qosPackets);
break; break;
} }
case MqttQualityOfServiceLevel.AtLeastOnce: case MqttQualityOfServiceLevel.AtLeastOnce:
@@ -186,8 +188,8 @@ namespace MQTTnet.Core.Client
var connectPacket = new MqttConnectPacket var connectPacket = new MqttConnectPacket
{ {
ClientId = _options.ClientId, ClientId = _options.ClientId,
Username = _options.UserName, Username = _options.Credentials?.Username,
Password = _options.Password, Password = _options.Credentials?.Password,
CleanSession = _options.CleanSession, CleanSession = _options.CleanSession,
KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds, KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds,
WillMessage = willApplicationMessage WillMessage = willApplicationMessage
@@ -247,7 +249,7 @@ namespace MQTTnet.Core.Client
try try
{ {
await _adapter.DisconnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false); await _adapter.DisconnectAsync(_options.CommunicationTimeout).ConfigureAwait(false);
_logger.LogInformation("Disconnected from adapter."); _logger.LogInformation("Disconnected from adapter.");
} }
catch (Exception exception) catch (Exception exception)
@@ -303,7 +305,7 @@ namespace MQTTnet.Core.Client
try try
{ {
var applicationMessage = publishPacket.ToApplicationMessage(); var applicationMessage = publishPacket.ToApplicationMessage();
ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(applicationMessage)); ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(_options.ClientId, applicationMessage));
} }
catch (Exception exception) catch (Exception exception)
{ {
@@ -354,13 +356,13 @@ namespace MQTTnet.Core.Client
private Task SendAsync(MqttBasePacket packet) private Task SendAsync(MqttBasePacket packet)
{ {
return _adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, packet); return _adapter.SendPacketsAsync(_options.CommunicationTimeout, _cancellationTokenSource.Token, packet);
} }
private async Task<TResponsePacket> SendAndReceiveAsync<TResponsePacket>(MqttBasePacket requestPacket) where TResponsePacket : MqttBasePacket private async Task<TResponsePacket> SendAndReceiveAsync<TResponsePacket>(MqttBasePacket requestPacket) where TResponsePacket : MqttBasePacket
{ {
var packetAwaiter = _packetDispatcher.WaitForPacketAsync(requestPacket, typeof(TResponsePacket), _options.DefaultCommunicationTimeout); var packetAwaiter = _packetDispatcher.WaitForPacketAsync(requestPacket, typeof(TResponsePacket), _options.CommunicationTimeout);
await _adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, requestPacket).ConfigureAwait(false); await _adapter.SendPacketsAsync(_options.CommunicationTimeout, _cancellationTokenSource.Token, requestPacket).ConfigureAwait(false);
return (TResponsePacket)await packetAwaiter.ConfigureAwait(false); return (TResponsePacket)await packetAwaiter.ConfigureAwait(false);
} }
@@ -0,0 +1,9 @@
namespace MQTTnet.Core.Client
{
public class MqttClientCredentials : IMqttClientCredentials
{
public string Username { get; set; }
public string Password { get; set; }
}
}
+1 -2
View File
@@ -2,13 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Client namespace MQTTnet.Core.Client
{ {
public static class MqttClientExtensions public static class MqttClientExtensions
{ {
public static Task PublishAsync(this IMqttClient client, params MqttApplicationMessage[] applicationMessages) public static Task PublishAsync(this IApplicationMessagePublisher client, params MqttApplicationMessage[] applicationMessages)
{ {
if (client == null) throw new ArgumentNullException(nameof(client)); if (client == null) throw new ArgumentNullException(nameof(client));
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages)); if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
@@ -3,24 +3,22 @@ using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Client namespace MQTTnet.Core.Client
{ {
public abstract class BaseMqttClientOptions : IMqttClientOptions public class MqttClientOptions : IMqttClientOptions
{ {
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
public MqttApplicationMessage WillMessage { get; set; } public MqttApplicationMessage WillMessage { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string ClientId { get; set; } = Guid.NewGuid().ToString("N"); public string ClientId { get; set; } = Guid.NewGuid().ToString("N");
public bool CleanSession { get; set; } = true; public bool CleanSession { get; set; } = true;
public IMqttClientCredentials Credentials { get; set; } = new MqttClientCredentials();
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(5); public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(5);
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan CommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311; public MqttProtocolVersion ProtocolVersion { get; set; } = MqttProtocolVersion.V311;
public IMqttClientChannelOptions ChannelOptions { get; set; }
} }
} }
@@ -0,0 +1,116 @@
using System;
using MQTTnet.Core.Serializer;
namespace MQTTnet.Core.Client
{
public class MqttClientOptionsBuilder
{
private readonly MqttClientOptions _options = new MqttClientOptions();
private MqttClientTcpOptions _tcpOptions;
private MqttClientWebSocketOptions _webSocketOptions;
private MqttClientTlsOptions _tlsOptions;
public MqttClientOptionsBuilder WithProtocolVersion(MqttProtocolVersion protocolVersion)
{
_options.ProtocolVersion = protocolVersion;
return this;
}
public MqttClientOptionsBuilder WithCommunicationTimeout(TimeSpan communicationTimeout)
{
_options.CommunicationTimeout = communicationTimeout;
return this;
}
public MqttClientOptionsBuilder WithCleanSession(bool value = true)
{
_options.CleanSession = value;
return this;
}
public MqttClientOptionsBuilder WithKeepAlivePeriod(TimeSpan keepAlivePeriod)
{
_options.KeepAlivePeriod = keepAlivePeriod;
return this;
}
public MqttClientOptionsBuilder WithClientId(string clientId)
{
_options.ClientId = clientId;
return this;
}
public MqttClientOptionsBuilder WithWillMessage(MqttApplicationMessage applicationMessage)
{
_options.WillMessage = applicationMessage;
return this;
}
public MqttClientOptionsBuilder WithCredentials(string username, string password = null)
{
_options.Credentials = new MqttClientCredentials
{
Username = username,
Password = password
};
return this;
}
public MqttClientOptionsBuilder WithTcpServer(string server, int? port = null)
{
_tcpOptions = new MqttClientTcpOptions
{
Server = server,
Port = port
};
return this;
}
public MqttClientOptionsBuilder WithWebSocketServer(string uri)
{
_webSocketOptions = new MqttClientWebSocketOptions
{
Uri = uri
};
return this;
}
public MqttClientOptionsBuilder WithTls()
{
_tlsOptions = new MqttClientTlsOptions
{
UseTls = true
};
return this;
}
public IMqttClientOptions Build()
{
if (_tlsOptions != null)
{
if (_tcpOptions == null && _webSocketOptions == null)
{
throw new InvalidOperationException("A channel (TCP or WebSocket) must be set if TLS is configured.");
}
if (_tcpOptions != null)
{
_options.ChannelOptions = _tcpOptions;
}
else
{
_options.ChannelOptions = _webSocketOptions;
}
}
_options.ChannelOptions = (IMqttClientChannelOptions)_tcpOptions ?? _webSocketOptions;
return _options;
}
}
}
+3 -1
View File
@@ -1,9 +1,11 @@
namespace MQTTnet.Core.Client namespace MQTTnet.Core.Client
{ {
public class MqttClientTcpOptions : BaseMqttClientOptions public class MqttClientTcpOptions : IMqttClientChannelOptions
{ {
public string Server { get; set; } public string Server { get; set; }
public int? Port { get; set; } public int? Port { get; set; }
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
} }
} }
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MQTTnet.Core.Client namespace MQTTnet.Core.Client
{ {
public sealed class MqttClientTlsOptions public class MqttClientTlsOptions
{ {
public bool UseTls { get; set; } public bool UseTls { get; set; }
@@ -3,7 +3,7 @@ using System.Net;
namespace MQTTnet.Core.Client namespace MQTTnet.Core.Client
{ {
public class MqttClientWebSocketOptions : BaseMqttClientOptions public class MqttClientWebSocketOptions : IMqttClientChannelOptions
{ {
public string Uri { get; set; } public string Uri { get; set; }
@@ -12,5 +12,7 @@ namespace MQTTnet.Core.Client
public ICollection<string> SubProtocols { get; set; } public ICollection<string> SubProtocols { get; set; }
public CookieContainer CookieContainer { get; set; } public CookieContainer CookieContainer { get; set; }
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
} }
} }
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MQTTnet.Core.Client;
namespace MQTTnet.Core.ManagedClient
{
public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher
{
bool IsConnected { get; }
event EventHandler<MqttClientConnectedEventArgs> Connected;
event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
Task StartAsync(IManagedMqttClientOptions options);
Task StopAsync();
Task SubscribeAsync(IEnumerable<TopicFilter> topicFilters);
Task UnsubscribeAsync(IEnumerable<TopicFilter> topicFilters);
}
}
@@ -10,7 +10,5 @@ namespace MQTTnet.Core.ManagedClient
TimeSpan AutoReconnectDelay { get; } TimeSpan AutoReconnectDelay { get; }
IManagedMqttClientStorage Storage { get; } IManagedMqttClientStorage Storage { get; }
Func<IManagedMqttClientOptions, string> PasswordProvider { get; }
} }
} }
@@ -6,13 +6,12 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions; using MQTTnet.Core.Exceptions;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol; using MQTTnet.Core.Protocol;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace MQTTnet.Core.ManagedClient namespace MQTTnet.Core.ManagedClient
{ {
public class ManagedMqttClient : IApplicationMessageReceiver public class ManagedMqttClient : IManagedMqttClient
{ {
private readonly ManagedMqttClientStorageManager _storageManager = new ManagedMqttClientStorageManager(); private readonly ManagedMqttClientStorageManager _storageManager = new ManagedMqttClientStorageManager();
private readonly BlockingCollection<MqttApplicationMessage> _messageQueue = new BlockingCollection<MqttApplicationMessage>(); private readonly BlockingCollection<MqttApplicationMessage> _messageQueue = new BlockingCollection<MqttApplicationMessage>();
@@ -92,7 +91,7 @@ namespace MQTTnet.Core.ManagedClient
return Task.FromResult(0); return Task.FromResult(0);
} }
public Task EnqueueAsync(IEnumerable<MqttApplicationMessage> applicationMessages) public Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages)
{ {
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages)); if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
@@ -277,7 +276,6 @@ namespace MQTTnet.Core.ManagedClient
try try
{ {
_options.PasswordProvider?.Invoke(_options);
await _mqttClient.ConnectAsync(_options.ClientOptions).ConfigureAwait(false); await _mqttClient.ConnectAsync(_options.ClientOptions).ConfigureAwait(false);
return ReconnectionResult.Reconnected; return ReconnectionResult.Reconnected;
} }
@@ -10,8 +10,5 @@ namespace MQTTnet.Core.ManagedClient
public TimeSpan AutoReconnectDelay { get; set; } = TimeSpan.FromSeconds(5); public TimeSpan AutoReconnectDelay { get; set; } = TimeSpan.FromSeconds(5);
public IManagedMqttClientStorage Storage { get; set; } public IManagedMqttClientStorage Storage { get; set; }
public Func<IManagedMqttClientOptions, string> PasswordProvider { get; set; }
} }
} }
+2 -4
View File
@@ -1,18 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using MQTTnet.Core.Client;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
public interface IMqttServer public interface IMqttServer : IApplicationMessageReceiver, IApplicationMessagePublisher
{ {
event EventHandler<MqttClientConnectedEventArgs> ClientConnected; event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected; event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected;
event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
IList<ConnectedMqttClient> GetConnectedClients(); IList<ConnectedMqttClient> GetConnectedClients();
void Publish(MqttApplicationMessage applicationMessage);
Task StartAsync(); Task StartAsync();
Task StopAsync(); Task StopAsync();
@@ -1,17 +0,0 @@
using System;
namespace MQTTnet.Core.Server
{
public sealed class MqttApplicationMessageReceivedEventArgs : EventArgs
{
public MqttApplicationMessageReceivedEventArgs(string clientId, MqttApplicationMessage applicationMessage)
{
ClientId = clientId;
ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage));
}
public string ClientId { get; }
public MqttApplicationMessage ApplicationMessage { get; }
}
}
@@ -28,7 +28,7 @@ namespace MQTTnet.Core.Server
{ {
if (adapter == null) throw new ArgumentNullException(nameof(adapter)); if (adapter == null) throw new ArgumentNullException(nameof(adapter));
Task.Run(() => SendPendingPublishPacketsAsync(adapter, cancellationToken), cancellationToken); Task.Factory.StartNew(async () => await SendPendingPublishPacketsAsync(adapter, cancellationToken), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default).ConfigureAwait(false);
} }
public void Enqueue(MqttPublishPacket publishPacket) public void Enqueue(MqttPublishPacket publishPacket)
@@ -74,7 +74,7 @@ namespace MQTTnet.Core.Server
{ {
_logger.LogWarning(new EventId(), exception, "Sending publish packet failed due to communication exception."); _logger.LogWarning(new EventId(), exception, "Sending publish packet failed due to communication exception.");
} }
if (exception is OperationCanceledException) else if (exception is OperationCanceledException)
{ {
} }
else else
+18 -14
View File
@@ -28,11 +28,11 @@ namespace MQTTnet.Core.Server
public MqttClientSession(string clientId, MqttClientSessionsManager mqttClientSessionsManager, ILogger<MqttClientSession> logger, ILogger<MqttClientPendingMessagesQueue> msgQueueLogger) public MqttClientSession(string clientId, MqttClientSessionsManager mqttClientSessionsManager, ILogger<MqttClientSession> logger, ILogger<MqttClientPendingMessagesQueue> msgQueueLogger)
{ {
ClientId = clientId;
_options = mqttClientSessionsManager.Options;
_mqttClientSessionsManager = mqttClientSessionsManager ?? throw new ArgumentNullException(nameof(mqttClientSessionsManager)); _mqttClientSessionsManager = mqttClientSessionsManager ?? throw new ArgumentNullException(nameof(mqttClientSessionsManager));
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
ClientId = clientId;
_options = mqttClientSessionsManager.Options;
_pendingMessagesQueue = new MqttClientPendingMessagesQueue(mqttClientSessionsManager.Options, this, msgQueueLogger); _pendingMessagesQueue = new MqttClientPendingMessagesQueue(mqttClientSessionsManager.Options, this, msgQueueLogger);
} }
@@ -46,10 +46,9 @@ namespace MQTTnet.Core.Server
{ {
if (adapter == null) throw new ArgumentNullException(nameof(adapter)); if (adapter == null) throw new ArgumentNullException(nameof(adapter));
_willMessage = willMessage;
try try
{ {
_willMessage = willMessage;
_adapter = adapter; _adapter = adapter;
_cancellationTokenSource = new CancellationTokenSource(); _cancellationTokenSource = new CancellationTokenSource();
@@ -71,18 +70,23 @@ namespace MQTTnet.Core.Server
public void Stop() public void Stop()
{ {
if (_willMessage != null) try
{ {
_mqttClientSessionsManager.DispatchApplicationMessage(this, _willMessage); _cancellationTokenSource?.Cancel(false);
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
_adapter = null;
_logger.LogInformation("Client '{0}': Disconnected.", ClientId);
}
finally
{
if (_willMessage != null)
{
_mqttClientSessionsManager.DispatchApplicationMessage(this, _willMessage);
}
} }
_cancellationTokenSource?.Cancel(false);
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
_adapter = null;
_logger.LogInformation("Client '{0}': Disconnected.", ClientId);
} }
public void EnqueuePublishPacket(MqttPublishPacket publishPacket) public void EnqueuePublishPacket(MqttPublishPacket publishPacket)
@@ -11,6 +11,7 @@ using MQTTnet.Core.Protocol;
using MQTTnet.Core.Serializer; using MQTTnet.Core.Serializer;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using MQTTnet.Core.Client;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
@@ -28,9 +29,9 @@ namespace MQTTnet.Core.Server
_mqttClientSesssionFactory = mqttClientSesssionFactory ?? throw new ArgumentNullException(nameof(mqttClientSesssionFactory)); _mqttClientSesssionFactory = mqttClientSesssionFactory ?? throw new ArgumentNullException(nameof(mqttClientSesssionFactory));
} }
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 event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
public MqttClientRetainedMessagesManager RetainedMessagesManager { get; } public MqttClientRetainedMessagesManager RetainedMessagesManager { get; }
public MqttServerOptions Options { get; } public MqttServerOptions Options { get; }
@@ -166,6 +167,7 @@ namespace MQTTnet.Core.Server
_clientSessions.Remove(connectPacket.ClientId); _clientSessions.Remove(connectPacket.ClientId);
clientSession.Dispose(); clientSession.Dispose();
clientSession = null; clientSession = null;
_logger.LogTrace("Disposed existing session of client '{0}'.", connectPacket.ClientId); _logger.LogTrace("Disposed existing session of client '{0}'.", connectPacket.ClientId);
} }
else else
+16 -4
View File
@@ -6,6 +6,7 @@ using MQTTnet.Core.Adapter;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Linq; using System.Linq;
using MQTTnet.Core.Client;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
@@ -28,6 +29,7 @@ namespace MQTTnet.Core.Server
{ {
throw new ArgumentNullException(nameof(adapters)); throw new ArgumentNullException(nameof(adapters));
} }
_adapters = adapters.ToList(); _adapters = adapters.ToList();
_clientSessionsManager.ApplicationMessageReceived += (s, e) => ApplicationMessageReceived?.Invoke(s, e); _clientSessionsManager.ApplicationMessageReceived += (s, e) => ApplicationMessageReceived?.Invoke(s, e);
@@ -44,12 +46,22 @@ namespace MQTTnet.Core.Server
public event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected; public event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected;
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived; public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
public void Publish(MqttApplicationMessage applicationMessage) public Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages)
{ {
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage)); if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
_options.ApplicationMessageInterceptor?.Invoke(applicationMessage); if (_cancellationTokenSource == null)
_clientSessionsManager.DispatchApplicationMessage(null, applicationMessage); {
throw new InvalidOperationException("The server is not started.");
}
foreach (var applicationMessage in applicationMessages)
{
_options.ApplicationMessageInterceptor?.Invoke(applicationMessage);
_clientSessionsManager.DispatchApplicationMessage(null, applicationMessage);
}
return Task.FromResult(0);
} }
public async Task StartAsync() public async Task StartAsync()
+1 -1
View File
@@ -4,7 +4,7 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
public sealed class MqttServerOptions public class MqttServerOptions
{ {
public MqttServerDefaultEndpointOptions DefaultEndpointOptions { get; } = new MqttServerDefaultEndpointOptions(); public MqttServerDefaultEndpointOptions DefaultEndpointOptions { get; } = new MqttServerDefaultEndpointOptions();
+1 -1
View File
@@ -18,7 +18,7 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov
* 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 (67+ tests) * Unit tested (70+ 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_.
+27 -53
View File
@@ -5,7 +5,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.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol; using MQTTnet.Core.Protocol;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -52,12 +51,7 @@ namespace MQTTnet.Core.Tests
public async Task MqttServer_WillMessage() public async Task MqttServer_WillMessage()
{ {
var serverAdapter = new TestMqttServerAdapter(); var serverAdapter = new TestMqttServerAdapter();
var services = new ServiceCollection() var s = new MqttFactory().CreateMqttServer();
.AddMqttServer()
.AddSingleton<IMqttServerAdapter>(serverAdapter)
.BuildServiceProvider();
var s = services.GetRequiredService<IMqttServer>();
await s.StartAsync(); await s.StartAsync();
var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build(); var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build();
@@ -81,12 +75,7 @@ namespace MQTTnet.Core.Tests
public async Task MqttServer_Unsubscribe() public async Task MqttServer_Unsubscribe()
{ {
var serverAdapter = new TestMqttServerAdapter(); var serverAdapter = new TestMqttServerAdapter();
var services = new ServiceCollection() var s = new MqttFactory().CreateMqttServer();
.AddMqttServer()
.AddSingleton<IMqttServerAdapter>(serverAdapter)
.BuildServiceProvider();
var s = services.GetRequiredService<IMqttServer>();
await s.StartAsync(); await s.StartAsync();
var c1 = await serverAdapter.ConnectTestClient(s, "c1"); var c1 = await serverAdapter.ConnectTestClient(s, "c1");
@@ -122,12 +111,7 @@ namespace MQTTnet.Core.Tests
public async Task MqttServer_Publish() public async Task MqttServer_Publish()
{ {
var serverAdapter = new TestMqttServerAdapter(); var serverAdapter = new TestMqttServerAdapter();
var services = new ServiceCollection() var s = new MqttFactory().CreateMqttServer();
.AddMqttServer()
.AddSingleton<IMqttServerAdapter>(serverAdapter)
.BuildServiceProvider();
var s = services.GetRequiredService<IMqttServer>();
await s.StartAsync(); await s.StartAsync();
var c1 = await serverAdapter.ConnectTestClient(s, "c1"); var c1 = await serverAdapter.ConnectTestClient(s, "c1");
@@ -138,7 +122,7 @@ namespace MQTTnet.Core.Tests
var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build(); var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce)); await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
s.Publish(message); s.PublishAsync(message).Wait();
await Task.Delay(500); await Task.Delay(500);
await s.StopAsync(); await s.StopAsync();
@@ -150,22 +134,17 @@ namespace MQTTnet.Core.Tests
public async Task MqttServer_NoRetainedMessage() public async Task MqttServer_NoRetainedMessage()
{ {
var serverAdapter = new TestMqttServerAdapter(); var serverAdapter = new TestMqttServerAdapter();
var services = new ServiceCollection() var s = new MqttFactory().CreateMqttServer();
.AddMqttServer()
.AddSingleton<IMqttServerAdapter>(serverAdapter)
.BuildServiceProvider();
var s = services.GetRequiredService<IMqttServer>();
await s.StartAsync(); await s.StartAsync();
var c1 = await serverAdapter.ConnectTestClient(s, "c1"); var c1 = await serverAdapter.ConnectTestClient(s, "c1");
await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[3], MqttQualityOfServiceLevel.AtLeastOnce, false)); await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).Build());
await c1.DisconnectAsync(); await c1.DisconnectAsync();
var c2 = await serverAdapter.ConnectTestClient(s, "c2"); var c2 = await serverAdapter.ConnectTestClient(s, "c2");
var receivedMessagesCount = 0; var receivedMessagesCount = 0;
c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++; c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtLeastOnce)); await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
await Task.Delay(500); await Task.Delay(500);
@@ -178,22 +157,17 @@ namespace MQTTnet.Core.Tests
public async Task MqttServer_RetainedMessage() public async Task MqttServer_RetainedMessage()
{ {
var serverAdapter = new TestMqttServerAdapter(); var serverAdapter = new TestMqttServerAdapter();
var services = new ServiceCollection() var s = new MqttFactory().CreateMqttServer();
.AddMqttServer()
.AddSingleton<IMqttServerAdapter>(serverAdapter)
.BuildServiceProvider();
var s = services.GetRequiredService<IMqttServer>();
await s.StartAsync(); await s.StartAsync();
var c1 = await serverAdapter.ConnectTestClient(s, "c1"); var c1 = await serverAdapter.ConnectTestClient(s, "c1");
await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[3], MqttQualityOfServiceLevel.AtLeastOnce, true)); await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
await c1.DisconnectAsync(); await c1.DisconnectAsync();
var c2 = await serverAdapter.ConnectTestClient(s, "c2"); var c2 = await serverAdapter.ConnectTestClient(s, "c2");
var receivedMessagesCount = 0; var receivedMessagesCount = 0;
c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++; c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtLeastOnce)); await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
await Task.Delay(500); await Task.Delay(500);
@@ -207,22 +181,23 @@ namespace MQTTnet.Core.Tests
{ {
var serverAdapter = new TestMqttServerAdapter(); var serverAdapter = new TestMqttServerAdapter();
var services = new ServiceCollection() var services = new ServiceCollection()
.AddMqttServer() .AddLogging()
.AddMqttServer() // TODO: Is there maybe an easier way for the library user to set the options?
.AddSingleton<IMqttServerAdapter>(serverAdapter) .AddSingleton<IMqttServerAdapter>(serverAdapter)
.BuildServiceProvider(); .BuildServiceProvider();
var s = services.GetRequiredService<IMqttServer>(); var s = new MqttFactory(services).CreateMqttServer();
await s.StartAsync(); await s.StartAsync();
var c1 = await serverAdapter.ConnectTestClient(s, "c1"); var c1 = await serverAdapter.ConnectTestClient(s, "c1");
await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[3], MqttQualityOfServiceLevel.AtLeastOnce, true)); await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[0], MqttQualityOfServiceLevel.AtLeastOnce, true)); await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[0]).WithRetainFlag().Build());
await c1.DisconnectAsync(); await c1.DisconnectAsync();
var c2 = await serverAdapter.ConnectTestClient(s, "c2"); var c2 = await serverAdapter.ConnectTestClient(s, "c2");
var receivedMessagesCount = 0; var receivedMessagesCount = 0;
c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++; c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtLeastOnce)); await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
await Task.Delay(500); await Task.Delay(500);
@@ -238,15 +213,16 @@ namespace MQTTnet.Core.Tests
var serverAdapter = new TestMqttServerAdapter(); var serverAdapter = new TestMqttServerAdapter();
var services = new ServiceCollection() var services = new ServiceCollection()
.AddMqttServer() .AddLogging()
.AddMqttServer(options => options.Storage = storage) // TODO: Is there maybe an easier way for the library user to set the options?
.AddSingleton<IMqttServerAdapter>(serverAdapter) .AddSingleton<IMqttServerAdapter>(serverAdapter)
.BuildServiceProvider(); .BuildServiceProvider();
var s = services.GetRequiredService<IMqttServer>(); var s = new MqttFactory(services).CreateMqttServer(); // TODO: Like here?
await s.StartAsync(); await s.StartAsync();
var c1 = await serverAdapter.ConnectTestClient(s, "c1"); var c1 = await serverAdapter.ConnectTestClient(s, "c1");
await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[3], MqttQualityOfServiceLevel.AtLeastOnce, true)); await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
await c1.DisconnectAsync(); await c1.DisconnectAsync();
await s.StopAsync(); await s.StopAsync();
@@ -257,7 +233,7 @@ namespace MQTTnet.Core.Tests
var c2 = await serverAdapter.ConnectTestClient(s, "c2"); var c2 = await serverAdapter.ConnectTestClient(s, "c2");
var receivedMessagesCount = 0; var receivedMessagesCount = 0;
c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++; c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtLeastOnce)); await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
await Task.Delay(500); await Task.Delay(500);
@@ -269,18 +245,16 @@ namespace MQTTnet.Core.Tests
[TestMethod] [TestMethod]
public async Task MqttServer_InterceptMessage() public async Task MqttServer_InterceptMessage()
{ {
var options = new MqttServerOptions MqttApplicationMessage Interceptor(MqttApplicationMessage message)
{ {
ApplicationMessageInterceptor = message => message.Payload = Encoding.ASCII.GetBytes("extended");
{ return message;
message.Payload = Encoding.ASCII.GetBytes("extended"); }
return message;
}
};
var serverAdapter = new TestMqttServerAdapter(); var serverAdapter = new TestMqttServerAdapter();
var services = new ServiceCollection() var services = new ServiceCollection()
.AddMqttServer() .AddLogging()
.AddMqttServer(options => options.ApplicationMessageInterceptor = Interceptor)
.AddSingleton<IMqttServerAdapter>(serverAdapter) .AddSingleton<IMqttServerAdapter>(serverAdapter)
.BuildServiceProvider(); .BuildServiceProvider();
@@ -21,7 +21,17 @@ namespace MQTTnet.Core.Tests
var connected = WaitForClientToConnect(server, clientId); var connected = WaitForClientToConnect(server, clientId);
FireClientAcceptedEvent(adapterB); FireClientAcceptedEvent(adapterB);
await client.ConnectAsync(new MqttClientTcpOptions { ClientId = clientId, WillMessage = willMessage });
var options = new MqttClientOptions
{
ClientId = clientId,
WillMessage = willMessage,
ChannelOptions = new MqttClientTcpOptions()
};
options.ChannelOptions = new MqttClientTcpOptions();
await client.ConnectAsync(options);
await connected; await connected;
return client; return client;
+2 -1
View File
@@ -8,6 +8,7 @@ using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using MQTTnet.AspnetCore; using MQTTnet.AspnetCore;
using MQTTnet.Core; using MQTTnet.Core;
using MQTTnet.Core.Client;
namespace MQTTnet.TestApp.AspNetCore2 namespace MQTTnet.TestApp.AspNetCore2
{ {
@@ -29,7 +30,7 @@ namespace MQTTnet.TestApp.AspNetCore2
while (true) while (true)
{ {
server.Publish(msg.Build()); server.PublishAsync(msg.Build()).Wait();
await Task.Delay(TimeSpan.FromSeconds(2)); await Task.Delay(TimeSpan.FromSeconds(2));
msg.WithPayload("Mqtt is still awesome at " + DateTime.Now); msg.WithPayload("Mqtt is still awesome at " + DateTime.Now);
} }
@@ -0,0 +1,99 @@
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using MQTTnet.Core;
using MQTTnet.Core.Client;
namespace MQTTnet.TestApp.NetCore
{
public static class ClientTest
{
public static async Task RunAsync()
{
try
{
var options = new MqttClientOptions
{
ClientId = "XYZ",
CleanSession = true,
ChannelOptions = new MqttClientTcpOptions
{
Server = "localhost"
},
////ChannelOptions = new MqttClientWebSocketOptions
////{
//// Uri = "localhost"
////}
};
var factory = new MqttFactory();
factory.GetLoggerFactory().AddConsole();
var client = factory.CreateMqttClient();
client.ApplicationMessageReceived += (s, e) =>
{
Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
Console.WriteLine();
};
client.Connected += async (s, e) =>
{
Console.WriteLine("### CONNECTED WITH SERVER ###");
await client.SubscribeAsync(new TopicFilterBuilder().WithTopic("#").Build());
Console.WriteLine("### SUBSCRIBED ###");
};
client.Disconnected += async (s, e) =>
{
Console.WriteLine("### DISCONNECTED FROM SERVER ###");
await Task.Delay(TimeSpan.FromSeconds(5));
try
{
await client.ConnectAsync(options);
}
catch
{
Console.WriteLine("### RECONNECTING FAILED ###");
}
};
try
{
await client.ConnectAsync(options);
}
catch (Exception exception)
{
Console.WriteLine("### CONNECTING FAILED ###" + Environment.NewLine + exception);
}
Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###");
while (true)
{
Console.ReadLine();
var applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic("A/B/C")
.WithPayload("Hello World")
.WithAtLeastOnceQoS()
.Build();
await client.PublishAsync(applicationMessage);
}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
}
@@ -3,7 +3,6 @@ using System.Threading.Tasks;
using MQTTnet.Core; using MQTTnet.Core;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.ManagedClient; using MQTTnet.Core.ManagedClient;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol; using MQTTnet.Core.Protocol;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -25,32 +24,24 @@ namespace MQTTnet.TestApp.NetCore
services.GetService<ILoggerFactory>() services.GetService<ILoggerFactory>()
.AddConsole(); .AddConsole();
ClientRetainedMessageHandler ms = new ClientRetainedMessageHandler(); var ms = new ClientRetainedMessageHandler();
Func<ManagedMqttClientOptions, string> func = delegate (ManagedMqttClientOptions managedMqttClientOptions)
{
return "password";
};
var options = new ManagedMqttClientOptions var options = new ManagedMqttClientOptions
{ {
ClientOptions = new MqttClientTcpOptions ClientOptions = new MqttClientOptions
{ {
Server = "broker.hivemq.com",
ClientId = "MQTTnetManagedClientTest", ClientId = "MQTTnetManagedClientTest",
Password = "pippo", Credentials = new RandomPassword(),
ChannelOptions = new MqttClientTcpOptions
{
Server = "broker.hivemq.com"
}
}, },
AutoReconnectDelay = TimeSpan.FromSeconds(1), AutoReconnectDelay = TimeSpan.FromSeconds(1),
Storage = ms, Storage = ms
PasswordProvider = o =>
{
//o.ClientOptions.Password = GetPassword();
return o.ClientOptions.Password;
}
}; };
try try
{ {
var managedClient = services.GetRequiredService<ManagedMqttClient>(); var managedClient = services.GetRequiredService<ManagedMqttClient>();
@@ -78,11 +69,18 @@ namespace MQTTnet.TestApp.NetCore
} }
public static string GetPassword() public class RandomPassword : IMqttClientCredentials
{ {
return "password"; public string Password
} {
get
{
return Guid.NewGuid().ToString(); // The random password.
}
}
public string Username => "the_static_user";
}
public class ClientRetainedMessageHandler : IManagedMqttClientStorage public class ClientRetainedMessageHandler : IManagedMqttClientStorage
{ {
@@ -2,7 +2,6 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using MQTTnet.Core; using MQTTnet.Core;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol; using MQTTnet.Core.Protocol;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using System; using System;
@@ -20,7 +19,8 @@ namespace MQTTnet.TestApp.NetCore
public static async Task RunAsync() public static async Task RunAsync()
{ {
var services = new ServiceCollection() var services = new ServiceCollection()
.AddMqttServer(options => { .AddMqttServer(options =>
{
options.ConnectionValidator = p => options.ConnectionValidator = p =>
{ {
@@ -41,11 +41,10 @@ namespace MQTTnet.TestApp.NetCore
.AddLogging() .AddLogging()
.BuildServiceProvider(); .BuildServiceProvider();
services.GetService<ILoggerFactory>() services.GetService<ILoggerFactory>().AddConsole(LogLevel.Warning, true);
.AddConsole(minLevel: LogLevel.Warning, includeScopes: true);
Console.WriteLine("Press 'c' for concurrent sends. Otherwise in one batch."); Console.WriteLine("Press 'c' for concurrent sends. Otherwise in one batch.");
var concurrent = Console.ReadKey(intercept: true).KeyChar == 'c'; var concurrent = Console.ReadKey(true).KeyChar == 'c';
var server = Task.Factory.StartNew(() => RunServerAsync(services), TaskCreationOptions.LongRunning); var server = Task.Factory.StartNew(() => RunServerAsync(services), TaskCreationOptions.LongRunning);
var client = Task.Factory.StartNew(() => RunClientAsync(2000, TimeSpan.FromMilliseconds(10), services, concurrent), TaskCreationOptions.LongRunning); var client = Task.Factory.StartNew(() => RunClientAsync(2000, TimeSpan.FromMilliseconds(10), services, concurrent), TaskCreationOptions.LongRunning);
@@ -62,12 +61,12 @@ namespace MQTTnet.TestApp.NetCore
{ {
try try
{ {
var options = new MqttClientTcpOptions var options = new MqttClientOptions
{ {
Server = "localhost", ChannelOptions = new MqttClientTcpOptions { Server = "localhost" },
ClientId = "Client1", ClientId = "Client1",
CleanSession = true, CleanSession = true,
DefaultCommunicationTimeout = TimeSpan.FromMinutes(10) CommunicationTimeout = TimeSpan.FromMinutes(10)
}; };
var client = serviceProvider.GetRequiredService<IMqttClient>(); var client = serviceProvider.GetRequiredService<IMqttClient>();
+15 -102
View File
@@ -1,17 +1,12 @@
using MQTTnet.Core; using MQTTnet.Core;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace MQTTnet.TestApp.NetCore namespace MQTTnet.TestApp.NetCore
@@ -29,7 +24,7 @@ namespace MQTTnet.TestApp.NetCore
var pressedKey = Console.ReadKey(true); var pressedKey = Console.ReadKey(true);
if (pressedKey.KeyChar == '1') if (pressedKey.KeyChar == '1')
{ {
Task.Run(RunClientAsync); Task.Run(ClientTest.RunAsync);
} }
else if (pressedKey.KeyChar == '2') else if (pressedKey.KeyChar == '2')
{ {
@@ -47,104 +42,21 @@ namespace MQTTnet.TestApp.NetCore
Thread.Sleep(Timeout.Infinite); Thread.Sleep(Timeout.Infinite);
} }
private static async Task RunClientAsync() // This code is used at the Wiki on GitHub!
{
try
{
var services = new ServiceCollection()
.AddMqttServer()
.AddLogging()
.BuildServiceProvider();
services.GetService<ILoggerFactory>()
.AddConsole();
var options = new MqttClientWebSocketOptions
{
Uri = "localhost",
ClientId = "XYZ",
CleanSession = true
};
var client = services.GetRequiredService<IMqttClient>();
client.ApplicationMessageReceived += (s, e) =>
{
Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
Console.WriteLine();
};
client.Connected += async (s, e) =>
{
Console.WriteLine("### CONNECTED WITH SERVER ###");
await client.SubscribeAsync(new List<TopicFilter>
{
new TopicFilter("#", MqttQualityOfServiceLevel.AtMostOnce)
});
Console.WriteLine("### SUBSCRIBED ###");
};
client.Disconnected += async (s, e) =>
{
Console.WriteLine("### DISCONNECTED FROM SERVER ###");
await Task.Delay(TimeSpan.FromSeconds(5));
try
{
await client.ConnectAsync(options);
}
catch
{
Console.WriteLine("### RECONNECTING FAILED ###");
}
};
try
{
await client.ConnectAsync(options);
}
catch (Exception exception)
{
Console.WriteLine("### CONNECTING FAILED ###" + Environment.NewLine + exception);
}
Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###");
while (true)
{
Console.ReadLine();
var applicationMessage = new MqttApplicationMessage
{
Topic = "A/B/C",
Payload = Encoding.UTF8.GetBytes("Hello World"),
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce
};
await client.PublishAsync(applicationMessage);
}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
// ReSharper disable once UnusedMember.Local // ReSharper disable once UnusedMember.Local
private static async void WikiCode() private static async void WikiCode()
{ {
{ {
var serviceProvider = new ServiceCollection() var client = new MqttFactory().CreateMqttClient();
.AddMqttServer()
.AddLogging()
.BuildServiceProvider();
var client = serviceProvider.GetRequiredService<IMqttClient>(); var options = new MqttClientOptionsBuilder()
.WithClientId("Client1")
.WithTcpServer("broker.hivemq.com")
.WithCredentials("bud", "%spencer%")
.WithTls()
.Build();
await client.ConnectAsync(options);
var message = new MqttApplicationMessageBuilder() var message = new MqttApplicationMessageBuilder()
.WithTopic("MyTopic") .WithTopic("MyTopic")
@@ -157,9 +69,10 @@ namespace MQTTnet.TestApp.NetCore
} }
{ {
var message = new MqttApplicationMessageBuilder() var factory = new MqttFactory();
.WithTopic("/MQTTnet/is/awesome") factory.GetLoggerFactory().AddConsole();
.Build();
var client = factory.CreateMqttClient();
} }
} }
} }
+2 -1
View File
@@ -49,6 +49,7 @@ namespace MQTTnet.TestApp.NetCore
}); });
var serviceProvider = services.BuildServiceProvider(); var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetRequiredService<ILoggerFactory>().AddConsole();
//var certificate = new X509Certificate(@"C:\certs\test\test.cer", ""); //var certificate = new X509Certificate(@"C:\certs\test\test.cer", "");
//options.TlsEndpointOptions.Certificate = certificate.Export(X509ContentType.Cert); //options.TlsEndpointOptions.Certificate = certificate.Export(X509ContentType.Cert);
@@ -56,7 +57,7 @@ namespace MQTTnet.TestApp.NetCore
//options.DefaultEndpointOptions.IsEnabled = true; //options.DefaultEndpointOptions.IsEnabled = true;
//options.TlsEndpointOptions.IsEnabled = false; //options.TlsEndpointOptions.IsEnabled = false;
var mqttServer = serviceProvider.GetRequiredService<IMqttServer>(); var mqttServer = new MqttFactory(serviceProvider).CreateMqttServer();
mqttServer.ClientDisconnected += (s, e) => mqttServer.ClientDisconnected += (s, e) =>
{ {
Console.Write("Client disconnected event fired."); Console.Write("Client disconnected event fired.");
@@ -8,9 +8,7 @@ using Microsoft.Extensions.DependencyInjection;
using MQTTnet.Core; using MQTTnet.Core;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Diagnostics; using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol; using MQTTnet.Core.Protocol;
using MQTTnet.Core.Server;
using MQTTnet.Implementations; using MQTTnet.Implementations;
namespace MQTTnet.TestApp.UniversalWindows namespace MQTTnet.TestApp.UniversalWindows
@@ -42,35 +40,44 @@ namespace MQTTnet.TestApp.UniversalWindows
private async void Connect(object sender, RoutedEventArgs e) private async void Connect(object sender, RoutedEventArgs e)
{ {
BaseMqttClientOptions options = null; var tlsOptions = new MqttClientTlsOptions
{
UseTls = UseTls.IsChecked == true,
IgnoreCertificateChainErrors = true,
IgnoreCertificateRevocationErrors = true,
AllowUntrustedCertificates = true
};
var options = new MqttClientOptions { ClientId = ClientId.Text };
if (UseTcp.IsChecked == true) if (UseTcp.IsChecked == true)
{ {
options = new MqttClientTcpOptions options.ChannelOptions = new MqttClientTcpOptions
{ {
Server = Server.Text Server = Server.Text,
TlsOptions = tlsOptions
}; };
} }
if (UseWs.IsChecked == true) if (UseWs.IsChecked == true)
{ {
options = new MqttClientWebSocketOptions options.ChannelOptions = new MqttClientWebSocketOptions
{ {
Uri = Server.Text Uri = Server.Text,
TlsOptions = tlsOptions
}; };
} }
if (options == null) if (options.ChannelOptions == null)
{ {
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
options.UserName = User.Text; options.Credentials = new MqttClientCredentials
options.Password = Password.Text; {
options.ClientId = ClientId.Text; Username = User.Text,
options.TlsOptions.UseTls = UseTls.IsChecked == true; Password = Password.Text
options.TlsOptions.IgnoreCertificateChainErrors = true; };
options.TlsOptions.IgnoreCertificateRevocationErrors = true;
options.TlsOptions.AllowUntrustedCertificates = true;
try try
{ {
@@ -201,73 +208,94 @@ namespace MQTTnet.TestApp.UniversalWindows
// ReSharper disable once UnusedMember.Local // ReSharper disable once UnusedMember.Local
private async Task WikiCode() private async Task WikiCode()
{ {
var services = new ServiceCollection()
.AddMqttClient()
.AddMqttServer(options =>
{
options.ConnectionValidator = c =>
{
if (c.ClientId.Length < 10)
{
return MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
}
if (c.Username != "mySecretUser")
{
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
}
if (c.Password != "mySecretPassword")
{
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
}
return MqttConnectReturnCode.ConnectionAccepted;
};
})
.BuildServiceProvider();
var factory = new MqttFactory(services);
var mqttClient = factory.CreateMqttClient();
// ----------------------------------
var tcpOptions = new MqttClientTcpOptions
{ {
Server = "broker.hivemq.org", // Create a new MQTT client
ClientId = "TestClient" var services = new ServiceCollection()
}; .AddMqttClient()
.BuildServiceProvider();
await mqttClient.ConnectAsync(tcpOptions); var factory = new MqttFactory(services);
var client = factory.CreateMqttClient();
// ----------------------------------
var secureTcpOptions = new MqttClientTcpOptions
{
Server = "broker.hivemq.org",
ClientId = "TestClient",
TlsOptions = new MqttClientTlsOptions
{ {
UseTls = true, // Create TCP based options using the builder
IgnoreCertificateChainErrors = true, var options = new MqttClientOptionsBuilder()
IgnoreCertificateRevocationErrors = true, .WithClientId("Client1")
AllowUntrustedCertificates = true .WithTcpServer("broker.hivemq.com")
.WithCredentials("bud", "%spencer%")
.WithTls()
.Build();
await client.ConnectAsync(options);
} }
};
// ---------------------------------- {
// Create TCP based options manually
var options = new MqttClientOptions
{
ClientId = "Client1",
Credentials = new MqttClientCredentials
{
Username = "bud",
Password = "%spencer%"
},
ChannelOptions = new MqttClientTcpOptions
{
Server = "broker.hivemq.org",
TlsOptions = new MqttClientTlsOptions
{
UseTls = true
}
},
};
}
var wsOptions = new MqttClientWebSocketOptions {
{ // Subscribe to a topic
Uri = "broker.hivemq.com:8000/mqtt", await client.SubscribeAsync(new TopicFilterBuilder().WithTopic("my/topic").Build());
ClientId = "TestClient"
};
await mqttClient.ConnectAsync(wsOptions); // Unsubscribe from a topic
await client.UnsubscribeAsync("my/topic");
// Publish an application message
var applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic("A/B/C")
.WithPayload("Hello World")
.WithAtLeastOnceQoS()
.Build();
await client.PublishAsync(applicationMessage);
}
}
// ---------------------------------- // ----------------------------------
{ {
var services = new ServiceCollection()
.AddMqttServer(options =>
{
options.ConnectionValidator = c =>
{
if (c.ClientId.Length < 10)
{
return MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
}
if (c.Username != "mySecretUser")
{
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
}
if (c.Password != "mySecretPassword")
{
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
}
return MqttConnectReturnCode.ConnectionAccepted;
};
})
.BuildServiceProvider();
var factory = new MqttFactory(services);
var mqttServer = factory.CreateMqttServer(); var mqttServer = factory.CreateMqttServer();
await mqttServer.StartAsync(); await mqttServer.StartAsync();