diff --git a/Frameworks/MQTTnet.NetStandard/Implementations/MqttCommunicationAdapterFactory.cs b/Frameworks/MQTTnet.NetStandard/Implementations/MqttCommunicationAdapterFactory.cs index 799ccdd..05e6fb6 100644 --- a/Frameworks/MQTTnet.NetStandard/Implementations/MqttCommunicationAdapterFactory.cs +++ b/Frameworks/MQTTnet.NetStandard/Implementations/MqttCommunicationAdapterFactory.cs @@ -7,7 +7,7 @@ namespace MQTTnet.Implementations { public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory { - public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options) + public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(IMqttClientOptions options) { if (options == null) throw new ArgumentNullException(nameof(options)); diff --git a/Frameworks/MQTTnet.NetStandard/Implementations/MqttTcpChannel.cs b/Frameworks/MQTTnet.NetStandard/Implementations/MqttTcpChannel.cs index dfe3654..cd9151e 100644 --- a/Frameworks/MQTTnet.NetStandard/Implementations/MqttTcpChannel.cs +++ b/Frameworks/MQTTnet.NetStandard/Implementations/MqttTcpChannel.cs @@ -48,8 +48,7 @@ namespace MQTTnet.Implementations public Stream SendStream { get; private set; } public Stream ReceiveStream { get; private set; } public Stream RawReceiveStream { get; private set; } - - + public static Func CustomCertificateValidationCallback { get; set; } public async Task ConnectAsync() @@ -121,7 +120,7 @@ namespace MQTTnet.Implementations return _options.TlsOptions.AllowUntrustedCertificates; } - private static X509CertificateCollection LoadCertificates(MqttClientOptions options) + private static X509CertificateCollection LoadCertificates(IMqttClientOptions options) { var certificates = new X509CertificateCollection(); if (options.TlsOptions.Certificates == null) diff --git a/Frameworks/MQTTnet.UniversalWindows/Implementations/MqttCommunicationAdapterFactory.cs b/Frameworks/MQTTnet.UniversalWindows/Implementations/MqttCommunicationAdapterFactory.cs index 799ccdd..05e6fb6 100644 --- a/Frameworks/MQTTnet.UniversalWindows/Implementations/MqttCommunicationAdapterFactory.cs +++ b/Frameworks/MQTTnet.UniversalWindows/Implementations/MqttCommunicationAdapterFactory.cs @@ -7,7 +7,7 @@ namespace MQTTnet.Implementations { public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory { - public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options) + public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(IMqttClientOptions options) { if (options == null) throw new ArgumentNullException(nameof(options)); diff --git a/Frameworks/MQTTnet.UniversalWindows/Implementations/MqttTcpChannel.cs b/Frameworks/MQTTnet.UniversalWindows/Implementations/MqttTcpChannel.cs index 03206f1..1a96f1e 100644 --- a/Frameworks/MQTTnet.UniversalWindows/Implementations/MqttTcpChannel.cs +++ b/Frameworks/MQTTnet.UniversalWindows/Implementations/MqttTcpChannel.cs @@ -89,7 +89,7 @@ namespace MQTTnet.Implementations RawReceiveStream = ReceiveStream; } - private static Certificate LoadCertificate(MqttClientOptions options) + private static Certificate LoadCertificate(BaseMqttClientOptions options) { if (options.TlsOptions.Certificates == null || !options.TlsOptions.Certificates.Any()) { diff --git a/MQTTnet.Core/Client/MqttClientOptions.cs b/MQTTnet.Core/Client/BaseMqttClientOptions.cs similarity index 89% rename from MQTTnet.Core/Client/MqttClientOptions.cs rename to MQTTnet.Core/Client/BaseMqttClientOptions.cs index f2e28fb..ca3f82e 100644 --- a/MQTTnet.Core/Client/MqttClientOptions.cs +++ b/MQTTnet.Core/Client/BaseMqttClientOptions.cs @@ -3,7 +3,7 @@ using MQTTnet.Core.Serializer; namespace MQTTnet.Core.Client { - public abstract class MqttClientOptions + public abstract class BaseMqttClientOptions : IMqttClientOptions { public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions(); @@ -13,7 +13,7 @@ namespace MQTTnet.Core.Client public string Password { get; set; } - public string ClientId { get; set; } = Guid.NewGuid().ToString().Replace("-", string.Empty); + public string ClientId { get; set; } = Guid.NewGuid().ToString("N"); public bool CleanSession { get; set; } = true; diff --git a/MQTTnet.Core/Client/IMqttClient.cs b/MQTTnet.Core/Client/IMqttClient.cs index 7622867..7219c58 100644 --- a/MQTTnet.Core/Client/IMqttClient.cs +++ b/MQTTnet.Core/Client/IMqttClient.cs @@ -11,9 +11,9 @@ namespace MQTTnet.Core.Client event EventHandler ApplicationMessageReceived; event EventHandler Connected; - event EventHandler Disconnected; + event EventHandler Disconnected; - Task ConnectAsync(MqttClientOptions options); + Task ConnectAsync(IMqttClientOptions options); Task DisconnectAsync(); Task> SubscribeAsync(IEnumerable topicFilters); diff --git a/MQTTnet.Core/Client/IMqttClientOptions.cs b/MQTTnet.Core/Client/IMqttClientOptions.cs new file mode 100644 index 0000000..7e675ff --- /dev/null +++ b/MQTTnet.Core/Client/IMqttClientOptions.cs @@ -0,0 +1,18 @@ +using System; +using MQTTnet.Core.Serializer; + +namespace MQTTnet.Core.Client +{ + public interface IMqttClientOptions + { + bool CleanSession { get; } + string ClientId { get; } + TimeSpan DefaultCommunicationTimeout { get; } + TimeSpan KeepAlivePeriod { get; } + string Password { get; } + MqttProtocolVersion ProtocolVersion { get; } + MqttClientTlsOptions TlsOptions { get; } + string UserName { get; } + MqttApplicationMessage WillMessage { get; } + } +} \ No newline at end of file diff --git a/MQTTnet.Core/Client/IMqttCommunicationAdapterFactory.cs b/MQTTnet.Core/Client/IMqttCommunicationAdapterFactory.cs index 092ea04..0e29590 100644 --- a/MQTTnet.Core/Client/IMqttCommunicationAdapterFactory.cs +++ b/MQTTnet.Core/Client/IMqttCommunicationAdapterFactory.cs @@ -4,6 +4,6 @@ namespace MQTTnet.Core.Client { public interface IMqttCommunicationAdapterFactory { - IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options); + IMqttCommunicationAdapter CreateMqttCommunicationAdapter(IMqttClientOptions options); } } \ No newline at end of file diff --git a/MQTTnet.Core/Client/MqttClient.cs b/MQTTnet.Core/Client/MqttClient.cs index 80b850a..5385790 100644 --- a/MQTTnet.Core/Client/MqttClient.cs +++ b/MQTTnet.Core/Client/MqttClient.cs @@ -18,7 +18,7 @@ namespace MQTTnet.Core.Client private readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher(); private readonly IMqttCommunicationAdapterFactory _communicationChannelFactory; - private MqttClientOptions _options; + private IMqttClientOptions _options; private bool _isReceivingPackets; private int _latestPacketIdentifier; private CancellationTokenSource _cancellationTokenSource; @@ -30,12 +30,12 @@ namespace MQTTnet.Core.Client } public event EventHandler Connected; - public event EventHandler Disconnected; + public event EventHandler Disconnected; public event EventHandler ApplicationMessageReceived; - public bool IsConnected => _cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested; + public bool IsConnected { get; private set; } - public async Task ConnectAsync(MqttClientOptions options) + public async Task ConnectAsync(IMqttClientOptions options) { if (options == null) throw new ArgumentNullException(nameof(options)); @@ -64,6 +64,7 @@ namespace MQTTnet.Core.Client StartSendKeepAliveMessages(_cancellationTokenSource.Token); } + IsConnected = true; Connected?.Invoke(this, EventArgs.Empty); } catch (Exception) @@ -222,6 +223,9 @@ namespace MQTTnet.Core.Client private async Task DisconnectInternalAsync() { + var clientWasConnected = IsConnected; + IsConnected = false; + var cts = _cancellationTokenSource; if (cts == null || cts.IsCancellationRequested) { @@ -243,7 +247,7 @@ namespace MQTTnet.Core.Client } finally { - Disconnected?.Invoke(this, EventArgs.Empty); + Disconnected?.Invoke(this, new MqttClientDisconnectedEventArgs(clientWasConnected)); } } diff --git a/MQTTnet.Core/Client/MqttClientDisconnectedEventArgs.cs b/MQTTnet.Core/Client/MqttClientDisconnectedEventArgs.cs new file mode 100644 index 0000000..1e9609e --- /dev/null +++ b/MQTTnet.Core/Client/MqttClientDisconnectedEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace MQTTnet.Core.Client +{ + public class MqttClientDisconnectedEventArgs : EventArgs + { + public MqttClientDisconnectedEventArgs(bool clientWasConnected) + { + ClientWasConnected = clientWasConnected; + } + + public bool ClientWasConnected { get; } + } +} diff --git a/MQTTnet.Core/Client/MqttClientTcpOptions.cs b/MQTTnet.Core/Client/MqttClientTcpOptions.cs index beaa506..51d2b97 100644 --- a/MQTTnet.Core/Client/MqttClientTcpOptions.cs +++ b/MQTTnet.Core/Client/MqttClientTcpOptions.cs @@ -1,6 +1,6 @@ namespace MQTTnet.Core.Client { - public class MqttClientTcpOptions : MqttClientOptions + public class MqttClientTcpOptions : BaseMqttClientOptions { public string Server { get; set; } diff --git a/MQTTnet.Core/Client/MqttClientWebSocketOptions.cs b/MQTTnet.Core/Client/MqttClientWebSocketOptions.cs index 4b90524..b2b5777 100644 --- a/MQTTnet.Core/Client/MqttClientWebSocketOptions.cs +++ b/MQTTnet.Core/Client/MqttClientWebSocketOptions.cs @@ -1,6 +1,6 @@ namespace MQTTnet.Core.Client { - public class MqttClientWebSocketOptions : MqttClientOptions + public class MqttClientWebSocketOptions : BaseMqttClientOptions { public string Uri { get; set; } } diff --git a/MQTTnet.Core/Exceptions/MqttCommunicationException.cs b/MQTTnet.Core/Exceptions/MqttCommunicationException.cs index 2fc578e..e019f4e 100644 --- a/MQTTnet.Core/Exceptions/MqttCommunicationException.cs +++ b/MQTTnet.Core/Exceptions/MqttCommunicationException.cs @@ -17,10 +17,5 @@ namespace MQTTnet.Core.Exceptions : base(message) { } - - public MqttCommunicationException(string message, Exception innerException) - : base(message, innerException) - { - } } } diff --git a/MQTTnet.Core/MQTTnet.Core.csproj b/MQTTnet.Core/MQTTnet.Core.csproj index 0e9b965..679e4a8 100644 --- a/MQTTnet.Core/MQTTnet.Core.csproj +++ b/MQTTnet.Core/MQTTnet.Core.csproj @@ -32,4 +32,8 @@ + + + + \ No newline at end of file diff --git a/MQTTnet.Core/MqttApplicationMessageFactory.cs b/MQTTnet.Core/MqttApplicationMessageFactory.cs index 55025a3..c5bbee5 100644 --- a/MQTTnet.Core/MqttApplicationMessageFactory.cs +++ b/MQTTnet.Core/MqttApplicationMessageFactory.cs @@ -8,13 +8,6 @@ namespace MQTTnet.Core { public class MqttApplicationMessageFactory { - public MqttApplicationMessage CreateApplicationMessage(string topic, MqttQualityOfServiceLevel qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce, bool retain = false) - { - if (topic == null) throw new ArgumentNullException(nameof(topic)); - - return CreateApplicationMessage(topic, new byte[0], qualityOfServiceLevel, retain); - } - public MqttApplicationMessage CreateApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce, bool retain = false) { if (topic == null) throw new ArgumentNullException(nameof(topic)); diff --git a/MQTTnet.Core/Packets/MqttPacketExtensions.cs b/MQTTnet.Core/Packets/MqttPacketExtensions.cs index fef1054..6a7e0ce 100644 --- a/MQTTnet.Core/Packets/MqttPacketExtensions.cs +++ b/MQTTnet.Core/Packets/MqttPacketExtensions.cs @@ -12,8 +12,7 @@ namespace MQTTnet.Core.Packets if (responsePacket is IMqttPacketWithIdentifier responsePacketWithIdentifier) { - var requestPacketWithIdentifier = packet as IMqttPacketWithIdentifier; - if (requestPacketWithIdentifier == null) + if (!(packet is IMqttPacketWithIdentifier requestPacketWithIdentifier)) { throw new InvalidOperationException("Response packet has PacketIdentifier but request packet does not."); } diff --git a/MQTTnet.Core/Packets/MqttSubAckPacket.cs b/MQTTnet.Core/Packets/MqttSubAckPacket.cs index ee577ae..5882d4c 100644 --- a/MQTTnet.Core/Packets/MqttSubAckPacket.cs +++ b/MQTTnet.Core/Packets/MqttSubAckPacket.cs @@ -8,7 +8,7 @@ namespace MQTTnet.Core.Packets { public ushort PacketIdentifier { get; set; } - public IList SubscribeReturnCodes { get; set; } = new List(); + public IList SubscribeReturnCodes { get; } = new List(); public override string ToString() { diff --git a/MQTTnet.Core/Serializer/MqttPacketSerializer.cs b/MQTTnet.Core/Serializer/MqttPacketSerializer.cs index d31a8fe..833d798 100644 --- a/MQTTnet.Core/Serializer/MqttPacketSerializer.cs +++ b/MQTTnet.Core/Serializer/MqttPacketSerializer.cs @@ -58,19 +58,19 @@ namespace MQTTnet.Core.Serializer return Serialize(connAckPacket, writer); } - if (packet is MqttDisconnectPacket disconnectPacket) + if (packet is MqttDisconnectPacket) { - return Serialize(disconnectPacket); + return SerializeEmptyPacket(MqttControlPacketType.Disconnect); } - if (packet is MqttPingReqPacket pingReqPacket) + if (packet is MqttPingReqPacket) { - return Serialize(pingReqPacket); + return SerializeEmptyPacket(MqttControlPacketType.PingReq); } - if (packet is MqttPingRespPacket pingRespPacket) + if (packet is MqttPingRespPacket) { - return Serialize(pingRespPacket); + return SerializeEmptyPacket(MqttControlPacketType.PingResp); } if (packet is MqttPublishPacket publishPacket) @@ -338,6 +338,8 @@ namespace MQTTnet.Core.Serializer private static void ValidateConnectPacket(MqttConnectPacket packet) { + if (packet == null) throw new ArgumentNullException(nameof(packet)); + if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession) { throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7]."); @@ -346,6 +348,8 @@ namespace MQTTnet.Core.Serializer private static void ValidatePublishPacket(MqttPublishPacket packet) { + if (packet == null) throw new ArgumentNullException(nameof(packet)); + if (packet.QualityOfServiceLevel == 0 && packet.Dup) { throw new MqttProtocolViolationException("Dup flag must be false for QoS 0 packets [MQTT-3.3.1-2]."); @@ -433,21 +437,6 @@ namespace MQTTnet.Core.Serializer return MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.PubRel, 0x02); } - private static byte Serialize(MqttDisconnectPacket packet) - { - return SerializeEmptyPacket(MqttControlPacketType.Disconnect); - } - - private static byte Serialize(MqttPingReqPacket packet) - { - return SerializeEmptyPacket(MqttControlPacketType.PingReq); - } - - private static byte Serialize(MqttPingRespPacket packet) - { - return SerializeEmptyPacket(MqttControlPacketType.PingResp); - } - private static byte Serialize(MqttPublishPacket packet, MqttPacketWriter writer) { ValidatePublishPacket(packet); diff --git a/MQTTnet.Core/Server/IMqttServer.cs b/MQTTnet.Core/Server/IMqttServer.cs index 023feb8..a35a266 100644 --- a/MQTTnet.Core/Server/IMqttServer.cs +++ b/MQTTnet.Core/Server/IMqttServer.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using MQTTnet.Core.Adapter; namespace MQTTnet.Core.Server { @@ -11,7 +10,7 @@ namespace MQTTnet.Core.Server event EventHandler ClientConnected; event EventHandler ClientDisconnected; - IReadOnlyList GetConnectedClients(); + IList GetConnectedClients(); void Publish(MqttApplicationMessage applicationMessage); Task StartAsync(); diff --git a/MQTTnet.Core/Server/MqttClientSessionsManager.cs b/MQTTnet.Core/Server/MqttClientSessionsManager.cs index f78a541..9c9fbfd 100644 --- a/MQTTnet.Core/Server/MqttClientSessionsManager.cs +++ b/MQTTnet.Core/Server/MqttClientSessionsManager.cs @@ -103,7 +103,7 @@ namespace MQTTnet.Core.Server } } - public IReadOnlyList GetConnectedClients() + public IList GetConnectedClients() { lock (_clientSessions) { diff --git a/MQTTnet.Core/Server/MqttServer.cs b/MQTTnet.Core/Server/MqttServer.cs index d6f2379..d1615d8 100644 --- a/MQTTnet.Core/Server/MqttServer.cs +++ b/MQTTnet.Core/Server/MqttServer.cs @@ -27,7 +27,7 @@ namespace MQTTnet.Core.Server _clientSessionsManager.ClientDisconnected += OnClientDisconnected; } - public IReadOnlyList GetConnectedClients() + public IList GetConnectedClients() { return _clientSessionsManager.GetConnectedClients(); } diff --git a/Tests/MQTTnet.Core.Tests/ExtensionTests.cs b/Tests/MQTTnet.Core.Tests/ExtensionTests.cs index 2564e69..2f0966f 100644 --- a/Tests/MQTTnet.Core.Tests/ExtensionTests.cs +++ b/Tests/MQTTnet.Core.Tests/ExtensionTests.cs @@ -55,7 +55,7 @@ namespace MQTTnet.Core.Tests { try { - var r = await Task.Run(() => + await Task.Run(() => { var iis = new int[0]; return iis[1]; diff --git a/Tests/MQTTnet.Core.Tests/MqttApplicationMessageFactoryTests.cs b/Tests/MQTTnet.Core.Tests/MqttApplicationMessageFactoryTests.cs new file mode 100644 index 0000000..f0f464a --- /dev/null +++ b/Tests/MQTTnet.Core.Tests/MqttApplicationMessageFactoryTests.cs @@ -0,0 +1,30 @@ +using System; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using MQTTnet.Core.Protocol; + +namespace MQTTnet.Core.Tests +{ + [TestClass] + public class MqttApplicationMessageFactoryTests + { + [TestMethod] + public void CreateApplicationMessage_TopicOnly() + { + var message = new MqttApplicationMessageFactory().CreateApplicationMessage("Abc", MqttQualityOfServiceLevel.AtLeastOnce); + Assert.AreEqual("Abc", message.Topic); + Assert.IsFalse(message.Retain); + Assert.AreEqual(MqttQualityOfServiceLevel.AtLeastOnce, message.QualityOfServiceLevel); + } + + [TestMethod] + public void CreateApplicationMessage_TimeStampPayload() + { + var message = new MqttApplicationMessageFactory().CreateApplicationMessage("xyz", TimeSpan.FromSeconds(360)); + Assert.AreEqual("xyz", message.Topic); + Assert.IsFalse(message.Retain); + Assert.AreEqual(MqttQualityOfServiceLevel.AtMostOnce, message.QualityOfServiceLevel); + Assert.AreEqual(Encoding.UTF8.GetString(message.Payload), "00:06:00"); + } + } +} diff --git a/Tests/MQTTnet.Core.Tests/MqttCommunicationAdapterFactory.cs b/Tests/MQTTnet.Core.Tests/MqttCommunicationAdapterFactory.cs index c83f83a..bed3218 100644 --- a/Tests/MQTTnet.Core.Tests/MqttCommunicationAdapterFactory.cs +++ b/Tests/MQTTnet.Core.Tests/MqttCommunicationAdapterFactory.cs @@ -12,7 +12,7 @@ namespace MQTTnet.Core.Tests _adapter = adapter; } - public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options) + public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(IMqttClientOptions options) { return _adapter; } diff --git a/Tests/MQTTnet.Core.Tests/MqttPacketSerializerTests.cs b/Tests/MQTTnet.Core.Tests/MqttPacketSerializerTests.cs index de6265f..c78e3ae 100644 --- a/Tests/MQTTnet.Core.Tests/MqttPacketSerializerTests.cs +++ b/Tests/MQTTnet.Core.Tests/MqttPacketSerializerTests.cs @@ -2,10 +2,8 @@ using System.IO; using System.Text; using System.Threading; -using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using MQTTnet.Core.Adapter; -using MQTTnet.Core.Channel; using MQTTnet.Core.Packets; using MQTTnet.Core.Protocol; using MQTTnet.Core.Serializer; @@ -387,45 +385,6 @@ namespace MQTTnet.Core.Tests DeserializeAndCompare(p, "sAIAew=="); } - - public class TestChannel : IMqttCommunicationChannel - { - private readonly MemoryStream _stream = new MemoryStream(); - - public Stream ReceiveStream => _stream; - - public Stream RawReceiveStream => _stream; - - public Stream SendStream => _stream; - - public bool IsConnected { get; } = true; - - public TestChannel() - { - } - - public TestChannel(byte[] initialData) - { - _stream.Write(initialData, 0, initialData.Length); - _stream.Position = 0; - } - - public Task ConnectAsync() - { - return Task.FromResult(0); - } - - public Task DisconnectAsync() - { - return Task.FromResult(0); - } - - public byte[] ToArray() - { - return _stream.ToArray(); - } - } - private static void SerializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { var serializer = new MqttPacketSerializer { ProtocolVersion = protocolVersion }; diff --git a/Tests/MQTTnet.TestApp.NetCore/MQTTnet.TestApp.NetCore.csproj b/Tests/MQTTnet.TestApp.NetCore/MQTTnet.TestApp.NetCore.csproj index 867b013..41ece1b 100644 --- a/Tests/MQTTnet.TestApp.NetCore/MQTTnet.TestApp.NetCore.csproj +++ b/Tests/MQTTnet.TestApp.NetCore/MQTTnet.TestApp.NetCore.csproj @@ -6,6 +6,10 @@ netcoreapp2.0;net45 + + + + diff --git a/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs b/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs index d7060f2..f8b8c33 100644 --- a/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs +++ b/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs @@ -113,7 +113,8 @@ namespace MQTTnet.TestApp.NetCore .Select(i => CreateMessage()) .ToList(); - if (true) + Console.WriteLine("Press 'c' for concurrent sends. Otherwise in one batch."); + if (Console.ReadKey().KeyChar == 'c') { //send concurrent (test for raceconditions) var sendTasks = msgs @@ -161,10 +162,7 @@ namespace MQTTnet.TestApp.NetCore private static Task PublishSingleMessage(IMqttClient client, MqttApplicationMessage applicationMessage, ref int count) { Interlocked.Increment(ref count); - return Task.Run(() => - { - return client.PublishAsync(applicationMessage); - }); + return Task.Run(() => client.PublishAsync(applicationMessage)); } private static async Task RunServerAsync() diff --git a/Tests/MQTTnet.TestApp.NetCore/Program.cs b/Tests/MQTTnet.TestApp.NetCore/Program.cs index 31d26db..88130cb 100644 --- a/Tests/MQTTnet.TestApp.NetCore/Program.cs +++ b/Tests/MQTTnet.TestApp.NetCore/Program.cs @@ -6,16 +6,18 @@ using MQTTnet.Core.Protocol; using MQTTnet.Core.Server; using System; using System.Collections.Generic; +using System.IO; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; +using Newtonsoft.Json; namespace MQTTnet.TestApp.NetCore { public static class Program { - public static void Main(string[] args) + public static void Main() { Console.WriteLine("MQTTnet - TestApp.NetFramework"); Console.WriteLine("1 = Start client"); @@ -24,12 +26,12 @@ namespace MQTTnet.TestApp.NetCore var pressedKey = Console.ReadKey(true); if (pressedKey.Key == ConsoleKey.D1) { - Task.Run(() => RunClientAsync(args)); + Task.Run(RunClientAsync); Thread.Sleep(Timeout.Infinite); } else if (pressedKey.Key == ConsoleKey.D2) { - Task.Run(() => RunServerAsync(args)); + Task.Run(() => RunServerAsync()); Thread.Sleep(Timeout.Infinite); } else if (pressedKey.Key == ConsoleKey.D3) @@ -39,7 +41,7 @@ namespace MQTTnet.TestApp.NetCore } } - private static async Task RunClientAsync(string[] arguments) + private static async Task RunClientAsync() { MqttNetTrace.TraceMessagePublished += (s, e) => { @@ -128,7 +130,7 @@ namespace MQTTnet.TestApp.NetCore } } - private static void RunServerAsync(string[] arguments) + private static Task RunServerAsync() { MqttNetTrace.TraceMessagePublished += (s, e) => { @@ -157,10 +159,21 @@ namespace MQTTnet.TestApp.NetCore } }; + options.Storage = new RetainedMessageHandler(); + + var certificate = new X509Certificate(@"C:\certs\test\test.cer", ""); options.TlsEndpointOptions.Certificate = certificate.Export(X509ContentType.Cert); + options.ConnectionBacklog = 5; + options.DefaultEndpointOptions.IsEnabled = true; + options.TlsEndpointOptions.IsEnabled = false; var mqttServer = new MqttServerFactory().CreateMqttServer(options); + mqttServer.ClientDisconnected += (s, e) => + { + Console.Write("Client disconnected event fired."); + }; + mqttServer.StartAsync(); Console.WriteLine("Press any key to exit."); @@ -174,6 +187,34 @@ namespace MQTTnet.TestApp.NetCore } Console.ReadLine(); + return Task.FromResult(0); + } + } + + public class RetainedMessageHandler : IMqttServerStorage + { + private const string Filename = "C:\\MQTT\\RetainedMessages.json"; + + public Task SaveRetainedMessagesAsync(IList messages) + { + File.WriteAllText(Filename, JsonConvert.SerializeObject(messages)); + return Task.FromResult(0); + } + + public Task> LoadRetainedMessagesAsync() + { + IList retainedMessages; + if (File.Exists(Filename)) + { + var json = File.ReadAllText(Filename); + retainedMessages = JsonConvert.DeserializeObject>(json); + } + else + { + retainedMessages = new List(); + } + + return Task.FromResult(retainedMessages); } } } diff --git a/Tests/MQTTnet.TestApp.UniversalWindows/App.xaml.cs b/Tests/MQTTnet.TestApp.UniversalWindows/App.xaml.cs index de5a9f8..3ed0757 100644 --- a/Tests/MQTTnet.TestApp.UniversalWindows/App.xaml.cs +++ b/Tests/MQTTnet.TestApp.UniversalWindows/App.xaml.cs @@ -1,35 +1,18 @@ using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; -using Windows.Foundation; -using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; namespace MQTTnet.TestApp.UniversalWindows { - /// - /// Provides application-specific behavior to supplement the default Application class. - /// - sealed partial class App : Application + sealed partial class App { - /// - /// Initializes the singleton application object. This is the first line of authored code - /// executed, and as such is the logical equivalent of main() or WinMain(). - /// public App() { - this.InitializeComponent(); - this.Suspending += OnSuspending; + InitializeComponent(); + Suspending += OnSuspending; } /// @@ -39,11 +22,9 @@ namespace MQTTnet.TestApp.UniversalWindows /// Details about the launch request and process. protected override void OnLaunched(LaunchActivatedEventArgs e) { - Frame rootFrame = Window.Current.Content as Frame; - // Do not repeat app initialization when the Window already has content, // just ensure that the window is active - if (rootFrame == null) + if (!(Window.Current.Content is Frame rootFrame)) { // Create a Frame to act as the navigation context and navigate to the first page rootFrame = new Frame(); diff --git a/Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml b/Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml index b097b50..e2b0a18 100644 --- a/Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml +++ b/Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml @@ -58,7 +58,7 @@ QoS: - 0 (At most once) + 0 (At most once) 1 (At least once) 2 (Exactly once) @@ -73,7 +73,7 @@ QoS: - 0 (At most once) + 0 (At most once) 1 (At least once) 2 (Exactly once) diff --git a/Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml.cs b/Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml.cs index 07d5955..de795d5 100644 --- a/Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml.cs +++ b/Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml.cs @@ -41,7 +41,7 @@ namespace MQTTnet.TestApp.UniversalWindows private async void Connect(object sender, RoutedEventArgs e) { - MqttClientOptions options = null; + BaseMqttClientOptions options = null; if (UseTcp.IsChecked == true) { options = new MqttClientTcpOptions @@ -195,6 +195,8 @@ namespace MQTTnet.TestApp.UniversalWindows } } + // This code is for the Wiki at GitHub! + // ReSharper disable once UnusedMember.Local private async Task WikiCode() { var mqttClient = new MqttClientFactory().CreateMqttClient();