@@ -7,7 +7,7 @@ namespace MQTTnet.Implementations | |||||
{ | { | ||||
public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory | public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory | ||||
{ | { | ||||
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options) | |||||
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(IMqttClientOptions options) | |||||
{ | { | ||||
if (options == null) throw new ArgumentNullException(nameof(options)); | if (options == null) throw new ArgumentNullException(nameof(options)); | ||||
@@ -48,8 +48,7 @@ namespace MQTTnet.Implementations | |||||
public Stream SendStream { get; private set; } | public Stream SendStream { get; private set; } | ||||
public Stream ReceiveStream { get; private set; } | public Stream ReceiveStream { get; private set; } | ||||
public Stream RawReceiveStream { get; private set; } | public Stream RawReceiveStream { get; private set; } | ||||
public static Func<X509Certificate, X509Chain, SslPolicyErrors, MqttClientTcpOptions, bool> CustomCertificateValidationCallback { get; set; } | public static Func<X509Certificate, X509Chain, SslPolicyErrors, MqttClientTcpOptions, bool> CustomCertificateValidationCallback { get; set; } | ||||
public async Task ConnectAsync() | public async Task ConnectAsync() | ||||
@@ -121,7 +120,7 @@ namespace MQTTnet.Implementations | |||||
return _options.TlsOptions.AllowUntrustedCertificates; | return _options.TlsOptions.AllowUntrustedCertificates; | ||||
} | } | ||||
private static X509CertificateCollection LoadCertificates(MqttClientOptions options) | |||||
private static X509CertificateCollection LoadCertificates(IMqttClientOptions options) | |||||
{ | { | ||||
var certificates = new X509CertificateCollection(); | var certificates = new X509CertificateCollection(); | ||||
if (options.TlsOptions.Certificates == null) | if (options.TlsOptions.Certificates == null) | ||||
@@ -7,7 +7,7 @@ namespace MQTTnet.Implementations | |||||
{ | { | ||||
public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory | public class MqttCommunicationAdapterFactory : IMqttCommunicationAdapterFactory | ||||
{ | { | ||||
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options) | |||||
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(IMqttClientOptions options) | |||||
{ | { | ||||
if (options == null) throw new ArgumentNullException(nameof(options)); | if (options == null) throw new ArgumentNullException(nameof(options)); | ||||
@@ -89,7 +89,7 @@ namespace MQTTnet.Implementations | |||||
RawReceiveStream = ReceiveStream; | RawReceiveStream = ReceiveStream; | ||||
} | } | ||||
private static Certificate LoadCertificate(MqttClientOptions options) | |||||
private static Certificate LoadCertificate(BaseMqttClientOptions options) | |||||
{ | { | ||||
if (options.TlsOptions.Certificates == null || !options.TlsOptions.Certificates.Any()) | if (options.TlsOptions.Certificates == null || !options.TlsOptions.Certificates.Any()) | ||||
{ | { | ||||
@@ -3,7 +3,7 @@ using MQTTnet.Core.Serializer; | |||||
namespace MQTTnet.Core.Client | namespace MQTTnet.Core.Client | ||||
{ | { | ||||
public abstract class MqttClientOptions | |||||
public abstract class BaseMqttClientOptions : IMqttClientOptions | |||||
{ | { | ||||
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions(); | public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions(); | ||||
@@ -13,7 +13,7 @@ namespace MQTTnet.Core.Client | |||||
public string Password { get; set; } | 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; | public bool CleanSession { get; set; } = true; | ||||
@@ -11,9 +11,9 @@ namespace MQTTnet.Core.Client | |||||
event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived; | event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived; | ||||
event EventHandler Connected; | event EventHandler Connected; | ||||
event EventHandler Disconnected; | |||||
event EventHandler<MqttClientDisconnectedEventArgs> Disconnected; | |||||
Task ConnectAsync(MqttClientOptions options); | |||||
Task ConnectAsync(IMqttClientOptions options); | |||||
Task DisconnectAsync(); | Task DisconnectAsync(); | ||||
Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters); | Task<IList<MqttSubscribeResult>> SubscribeAsync(IEnumerable<TopicFilter> topicFilters); | ||||
@@ -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; } | |||||
} | |||||
} |
@@ -4,6 +4,6 @@ namespace MQTTnet.Core.Client | |||||
{ | { | ||||
public interface IMqttCommunicationAdapterFactory | public interface IMqttCommunicationAdapterFactory | ||||
{ | { | ||||
IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options); | |||||
IMqttCommunicationAdapter CreateMqttCommunicationAdapter(IMqttClientOptions options); | |||||
} | } | ||||
} | } |
@@ -18,7 +18,7 @@ namespace MQTTnet.Core.Client | |||||
private readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher(); | private readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher(); | ||||
private readonly IMqttCommunicationAdapterFactory _communicationChannelFactory; | private readonly IMqttCommunicationAdapterFactory _communicationChannelFactory; | ||||
private MqttClientOptions _options; | |||||
private IMqttClientOptions _options; | |||||
private bool _isReceivingPackets; | private bool _isReceivingPackets; | ||||
private int _latestPacketIdentifier; | private int _latestPacketIdentifier; | ||||
private CancellationTokenSource _cancellationTokenSource; | private CancellationTokenSource _cancellationTokenSource; | ||||
@@ -30,12 +30,12 @@ namespace MQTTnet.Core.Client | |||||
} | } | ||||
public event EventHandler Connected; | public event EventHandler Connected; | ||||
public event EventHandler Disconnected; | |||||
public event EventHandler<MqttClientDisconnectedEventArgs> Disconnected; | |||||
public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived; | public event EventHandler<MqttApplicationMessageReceivedEventArgs> 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)); | if (options == null) throw new ArgumentNullException(nameof(options)); | ||||
@@ -64,6 +64,7 @@ namespace MQTTnet.Core.Client | |||||
StartSendKeepAliveMessages(_cancellationTokenSource.Token); | StartSendKeepAliveMessages(_cancellationTokenSource.Token); | ||||
} | } | ||||
IsConnected = true; | |||||
Connected?.Invoke(this, EventArgs.Empty); | Connected?.Invoke(this, EventArgs.Empty); | ||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
@@ -222,6 +223,9 @@ namespace MQTTnet.Core.Client | |||||
private async Task DisconnectInternalAsync() | private async Task DisconnectInternalAsync() | ||||
{ | { | ||||
var clientWasConnected = IsConnected; | |||||
IsConnected = false; | |||||
var cts = _cancellationTokenSource; | var cts = _cancellationTokenSource; | ||||
if (cts == null || cts.IsCancellationRequested) | if (cts == null || cts.IsCancellationRequested) | ||||
{ | { | ||||
@@ -243,7 +247,7 @@ namespace MQTTnet.Core.Client | |||||
} | } | ||||
finally | finally | ||||
{ | { | ||||
Disconnected?.Invoke(this, EventArgs.Empty); | |||||
Disconnected?.Invoke(this, new MqttClientDisconnectedEventArgs(clientWasConnected)); | |||||
} | } | ||||
} | } | ||||
@@ -0,0 +1,14 @@ | |||||
using System; | |||||
namespace MQTTnet.Core.Client | |||||
{ | |||||
public class MqttClientDisconnectedEventArgs : EventArgs | |||||
{ | |||||
public MqttClientDisconnectedEventArgs(bool clientWasConnected) | |||||
{ | |||||
ClientWasConnected = clientWasConnected; | |||||
} | |||||
public bool ClientWasConnected { get; } | |||||
} | |||||
} |
@@ -1,6 +1,6 @@ | |||||
namespace MQTTnet.Core.Client | namespace MQTTnet.Core.Client | ||||
{ | { | ||||
public class MqttClientTcpOptions : MqttClientOptions | |||||
public class MqttClientTcpOptions : BaseMqttClientOptions | |||||
{ | { | ||||
public string Server { get; set; } | public string Server { get; set; } | ||||
@@ -1,6 +1,6 @@ | |||||
namespace MQTTnet.Core.Client | namespace MQTTnet.Core.Client | ||||
{ | { | ||||
public class MqttClientWebSocketOptions : MqttClientOptions | |||||
public class MqttClientWebSocketOptions : BaseMqttClientOptions | |||||
{ | { | ||||
public string Uri { get; set; } | public string Uri { get; set; } | ||||
} | } | ||||
@@ -17,10 +17,5 @@ namespace MQTTnet.Core.Exceptions | |||||
: base(message) | : base(message) | ||||
{ | { | ||||
} | } | ||||
public MqttCommunicationException(string message, Exception innerException) | |||||
: base(message, innerException) | |||||
{ | |||||
} | |||||
} | } | ||||
} | } |
@@ -32,4 +32,8 @@ | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x86'" /> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Any CPU|x86'" /> | ||||
<ItemGroup> | |||||
<Folder Include="ManagedClient\" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -8,13 +8,6 @@ namespace MQTTnet.Core | |||||
{ | { | ||||
public class MqttApplicationMessageFactory | 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) | public MqttApplicationMessage CreateApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce, bool retain = false) | ||||
{ | { | ||||
if (topic == null) throw new ArgumentNullException(nameof(topic)); | if (topic == null) throw new ArgumentNullException(nameof(topic)); | ||||
@@ -12,8 +12,7 @@ namespace MQTTnet.Core.Packets | |||||
if (responsePacket is IMqttPacketWithIdentifier responsePacketWithIdentifier) | 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."); | throw new InvalidOperationException("Response packet has PacketIdentifier but request packet does not."); | ||||
} | } | ||||
@@ -8,7 +8,7 @@ namespace MQTTnet.Core.Packets | |||||
{ | { | ||||
public ushort PacketIdentifier { get; set; } | public ushort PacketIdentifier { get; set; } | ||||
public IList<MqttSubscribeReturnCode> SubscribeReturnCodes { get; set; } = new List<MqttSubscribeReturnCode>(); | |||||
public IList<MqttSubscribeReturnCode> SubscribeReturnCodes { get; } = new List<MqttSubscribeReturnCode>(); | |||||
public override string ToString() | public override string ToString() | ||||
{ | { | ||||
@@ -58,19 +58,19 @@ namespace MQTTnet.Core.Serializer | |||||
return Serialize(connAckPacket, writer); | 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) | if (packet is MqttPublishPacket publishPacket) | ||||
@@ -338,6 +338,8 @@ namespace MQTTnet.Core.Serializer | |||||
private static void ValidateConnectPacket(MqttConnectPacket packet) | private static void ValidateConnectPacket(MqttConnectPacket packet) | ||||
{ | { | ||||
if (packet == null) throw new ArgumentNullException(nameof(packet)); | |||||
if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession) | if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession) | ||||
{ | { | ||||
throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7]."); | 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) | private static void ValidatePublishPacket(MqttPublishPacket packet) | ||||
{ | { | ||||
if (packet == null) throw new ArgumentNullException(nameof(packet)); | |||||
if (packet.QualityOfServiceLevel == 0 && packet.Dup) | if (packet.QualityOfServiceLevel == 0 && packet.Dup) | ||||
{ | { | ||||
throw new MqttProtocolViolationException("Dup flag must be false for QoS 0 packets [MQTT-3.3.1-2]."); | 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); | 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) | private static byte Serialize(MqttPublishPacket packet, MqttPacketWriter writer) | ||||
{ | { | ||||
ValidatePublishPacket(packet); | ValidatePublishPacket(packet); | ||||
@@ -1,7 +1,6 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using MQTTnet.Core.Adapter; | |||||
namespace MQTTnet.Core.Server | namespace MQTTnet.Core.Server | ||||
{ | { | ||||
@@ -11,7 +10,7 @@ namespace MQTTnet.Core.Server | |||||
event EventHandler<MqttClientConnectedEventArgs> ClientConnected; | event EventHandler<MqttClientConnectedEventArgs> ClientConnected; | ||||
event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected; | event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected; | ||||
IReadOnlyList<ConnectedMqttClient> GetConnectedClients(); | |||||
IList<ConnectedMqttClient> GetConnectedClients(); | |||||
void Publish(MqttApplicationMessage applicationMessage); | void Publish(MqttApplicationMessage applicationMessage); | ||||
Task StartAsync(); | Task StartAsync(); | ||||
@@ -103,7 +103,7 @@ namespace MQTTnet.Core.Server | |||||
} | } | ||||
} | } | ||||
public IReadOnlyList<ConnectedMqttClient> GetConnectedClients() | |||||
public IList<ConnectedMqttClient> GetConnectedClients() | |||||
{ | { | ||||
lock (_clientSessions) | lock (_clientSessions) | ||||
{ | { | ||||
@@ -27,7 +27,7 @@ namespace MQTTnet.Core.Server | |||||
_clientSessionsManager.ClientDisconnected += OnClientDisconnected; | _clientSessionsManager.ClientDisconnected += OnClientDisconnected; | ||||
} | } | ||||
public IReadOnlyList<ConnectedMqttClient> GetConnectedClients() | |||||
public IList<ConnectedMqttClient> GetConnectedClients() | |||||
{ | { | ||||
return _clientSessionsManager.GetConnectedClients(); | return _clientSessionsManager.GetConnectedClients(); | ||||
} | } | ||||
@@ -55,7 +55,7 @@ namespace MQTTnet.Core.Tests | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
var r = await Task.Run(() => | |||||
await Task.Run(() => | |||||
{ | { | ||||
var iis = new int[0]; | var iis = new int[0]; | ||||
return iis[1]; | return iis[1]; | ||||
@@ -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"); | |||||
} | |||||
} | |||||
} |
@@ -12,7 +12,7 @@ namespace MQTTnet.Core.Tests | |||||
_adapter = adapter; | _adapter = adapter; | ||||
} | } | ||||
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(MqttClientOptions options) | |||||
public IMqttCommunicationAdapter CreateMqttCommunicationAdapter(IMqttClientOptions options) | |||||
{ | { | ||||
return _adapter; | return _adapter; | ||||
} | } | ||||
@@ -2,10 +2,8 @@ | |||||
using System.IO; | using System.IO; | ||||
using System.Text; | using System.Text; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | |||||
using Microsoft.VisualStudio.TestTools.UnitTesting; | using Microsoft.VisualStudio.TestTools.UnitTesting; | ||||
using MQTTnet.Core.Adapter; | using MQTTnet.Core.Adapter; | ||||
using MQTTnet.Core.Channel; | |||||
using MQTTnet.Core.Packets; | using MQTTnet.Core.Packets; | ||||
using MQTTnet.Core.Protocol; | using MQTTnet.Core.Protocol; | ||||
using MQTTnet.Core.Serializer; | using MQTTnet.Core.Serializer; | ||||
@@ -387,45 +385,6 @@ namespace MQTTnet.Core.Tests | |||||
DeserializeAndCompare(p, "sAIAew=="); | 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) | private static void SerializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) | ||||
{ | { | ||||
var serializer = new MqttPacketSerializer { ProtocolVersion = protocolVersion }; | var serializer = new MqttPacketSerializer { ProtocolVersion = protocolVersion }; | ||||
@@ -6,6 +6,10 @@ | |||||
<TargetFrameworks>netcoreapp2.0;net45</TargetFrameworks> | <TargetFrameworks>netcoreapp2.0;net45</TargetFrameworks> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | |||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\..\Frameworks\MQTTnet.Netstandard\MQTTnet.NetStandard.csproj" /> | <ProjectReference Include="..\..\Frameworks\MQTTnet.Netstandard\MQTTnet.NetStandard.csproj" /> | ||||
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj" /> | <ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj" /> | ||||
@@ -113,7 +113,8 @@ namespace MQTTnet.TestApp.NetCore | |||||
.Select(i => CreateMessage()) | .Select(i => CreateMessage()) | ||||
.ToList(); | .ToList(); | ||||
if (true) | |||||
Console.WriteLine("Press 'c' for concurrent sends. Otherwise in one batch."); | |||||
if (Console.ReadKey().KeyChar == 'c') | |||||
{ | { | ||||
//send concurrent (test for raceconditions) | //send concurrent (test for raceconditions) | ||||
var sendTasks = msgs | var sendTasks = msgs | ||||
@@ -161,10 +162,7 @@ namespace MQTTnet.TestApp.NetCore | |||||
private static Task PublishSingleMessage(IMqttClient client, MqttApplicationMessage applicationMessage, ref int count) | private static Task PublishSingleMessage(IMqttClient client, MqttApplicationMessage applicationMessage, ref int count) | ||||
{ | { | ||||
Interlocked.Increment(ref count); | Interlocked.Increment(ref count); | ||||
return Task.Run(() => | |||||
{ | |||||
return client.PublishAsync(applicationMessage); | |||||
}); | |||||
return Task.Run(() => client.PublishAsync(applicationMessage)); | |||||
} | } | ||||
private static async Task RunServerAsync() | private static async Task RunServerAsync() | ||||
@@ -6,16 +6,18 @@ 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.Security.Cryptography.X509Certificates; | using System.Security.Cryptography.X509Certificates; | ||||
using System.Text; | using System.Text; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using Newtonsoft.Json; | |||||
namespace MQTTnet.TestApp.NetCore | namespace MQTTnet.TestApp.NetCore | ||||
{ | { | ||||
public static class Program | public static class Program | ||||
{ | { | ||||
public static void Main(string[] args) | |||||
public static void Main() | |||||
{ | { | ||||
Console.WriteLine("MQTTnet - TestApp.NetFramework"); | Console.WriteLine("MQTTnet - TestApp.NetFramework"); | ||||
Console.WriteLine("1 = Start client"); | Console.WriteLine("1 = Start client"); | ||||
@@ -24,12 +26,12 @@ namespace MQTTnet.TestApp.NetCore | |||||
var pressedKey = Console.ReadKey(true); | var pressedKey = Console.ReadKey(true); | ||||
if (pressedKey.Key == ConsoleKey.D1) | if (pressedKey.Key == ConsoleKey.D1) | ||||
{ | { | ||||
Task.Run(() => RunClientAsync(args)); | |||||
Task.Run(RunClientAsync); | |||||
Thread.Sleep(Timeout.Infinite); | Thread.Sleep(Timeout.Infinite); | ||||
} | } | ||||
else if (pressedKey.Key == ConsoleKey.D2) | else if (pressedKey.Key == ConsoleKey.D2) | ||||
{ | { | ||||
Task.Run(() => RunServerAsync(args)); | |||||
Task.Run(() => RunServerAsync()); | |||||
Thread.Sleep(Timeout.Infinite); | Thread.Sleep(Timeout.Infinite); | ||||
} | } | ||||
else if (pressedKey.Key == ConsoleKey.D3) | 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) => | 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) => | 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", ""); | var certificate = new X509Certificate(@"C:\certs\test\test.cer", ""); | ||||
options.TlsEndpointOptions.Certificate = certificate.Export(X509ContentType.Cert); | options.TlsEndpointOptions.Certificate = certificate.Export(X509ContentType.Cert); | ||||
options.ConnectionBacklog = 5; | |||||
options.DefaultEndpointOptions.IsEnabled = true; | |||||
options.TlsEndpointOptions.IsEnabled = false; | |||||
var mqttServer = new MqttServerFactory().CreateMqttServer(options); | var mqttServer = new MqttServerFactory().CreateMqttServer(options); | ||||
mqttServer.ClientDisconnected += (s, e) => | |||||
{ | |||||
Console.Write("Client disconnected event fired."); | |||||
}; | |||||
mqttServer.StartAsync(); | mqttServer.StartAsync(); | ||||
Console.WriteLine("Press any key to exit."); | Console.WriteLine("Press any key to exit."); | ||||
@@ -174,6 +187,34 @@ namespace MQTTnet.TestApp.NetCore | |||||
} | } | ||||
Console.ReadLine(); | Console.ReadLine(); | ||||
return Task.FromResult(0); | |||||
} | |||||
} | |||||
public class RetainedMessageHandler : IMqttServerStorage | |||||
{ | |||||
private const string Filename = "C:\\MQTT\\RetainedMessages.json"; | |||||
public Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages) | |||||
{ | |||||
File.WriteAllText(Filename, JsonConvert.SerializeObject(messages)); | |||||
return Task.FromResult(0); | |||||
} | |||||
public Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync() | |||||
{ | |||||
IList<MqttApplicationMessage> retainedMessages; | |||||
if (File.Exists(Filename)) | |||||
{ | |||||
var json = File.ReadAllText(Filename); | |||||
retainedMessages = JsonConvert.DeserializeObject<List<MqttApplicationMessage>>(json); | |||||
} | |||||
else | |||||
{ | |||||
retainedMessages = new List<MqttApplicationMessage>(); | |||||
} | |||||
return Task.FromResult(retainedMessages); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,35 +1,18 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Runtime.InteropServices.WindowsRuntime; | |||||
using Windows.ApplicationModel; | using Windows.ApplicationModel; | ||||
using Windows.ApplicationModel.Activation; | using Windows.ApplicationModel.Activation; | ||||
using Windows.Foundation; | |||||
using Windows.Foundation.Collections; | |||||
using Windows.UI.Xaml; | using Windows.UI.Xaml; | ||||
using Windows.UI.Xaml.Controls; | 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; | using Windows.UI.Xaml.Navigation; | ||||
namespace MQTTnet.TestApp.UniversalWindows | namespace MQTTnet.TestApp.UniversalWindows | ||||
{ | { | ||||
/// <summary> | |||||
/// Provides application-specific behavior to supplement the default Application class. | |||||
/// </summary> | |||||
sealed partial class App : Application | |||||
sealed partial class App | |||||
{ | { | ||||
/// <summary> | |||||
/// 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(). | |||||
/// </summary> | |||||
public App() | public App() | ||||
{ | { | ||||
this.InitializeComponent(); | |||||
this.Suspending += OnSuspending; | |||||
InitializeComponent(); | |||||
Suspending += OnSuspending; | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -39,11 +22,9 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
/// <param name="e">Details about the launch request and process.</param> | /// <param name="e">Details about the launch request and process.</param> | ||||
protected override void OnLaunched(LaunchActivatedEventArgs e) | protected override void OnLaunched(LaunchActivatedEventArgs e) | ||||
{ | { | ||||
Frame rootFrame = Window.Current.Content as Frame; | |||||
// Do not repeat app initialization when the Window already has content, | // Do not repeat app initialization when the Window already has content, | ||||
// just ensure that the window is active | // 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 | // Create a Frame to act as the navigation context and navigate to the first page | ||||
rootFrame = new Frame(); | rootFrame = new Frame(); | ||||
@@ -58,7 +58,7 @@ | |||||
<TextBlock>QoS:</TextBlock> | <TextBlock>QoS:</TextBlock> | ||||
<StackPanel Orientation="Horizontal"> | <StackPanel Orientation="Horizontal"> | ||||
<RadioButton Margin="0,0,10,0" x:Name="QoS0" IsChecked="True" GroupName="qos">0 (At most once)</RadioButton> | |||||
<RadioButton Margin="0,0,10,0" IsChecked="True" GroupName="qos">0 (At most once)</RadioButton> | |||||
<RadioButton Margin="0,0,10,0" x:Name="QoS1" GroupName="qos">1 (At least once)</RadioButton> | <RadioButton Margin="0,0,10,0" x:Name="QoS1" GroupName="qos">1 (At least once)</RadioButton> | ||||
<RadioButton Margin="0,0,10,0" x:Name="QoS2" GroupName="qos">2 (Exactly once)</RadioButton> | <RadioButton Margin="0,0,10,0" x:Name="QoS2" GroupName="qos">2 (Exactly once)</RadioButton> | ||||
</StackPanel> | </StackPanel> | ||||
@@ -73,7 +73,7 @@ | |||||
<TextBlock>QoS:</TextBlock> | <TextBlock>QoS:</TextBlock> | ||||
<StackPanel Orientation="Horizontal"> | <StackPanel Orientation="Horizontal"> | ||||
<RadioButton Margin="0,0,10,0" x:Name="SubscribeQoS0" IsChecked="True" GroupName="sqos">0 (At most once)</RadioButton> | |||||
<RadioButton Margin="0,0,10,0" IsChecked="True" GroupName="sqos">0 (At most once)</RadioButton> | |||||
<RadioButton Margin="0,0,10,0" x:Name="SubscribeQoS1" GroupName="sqos">1 (At least once)</RadioButton> | <RadioButton Margin="0,0,10,0" x:Name="SubscribeQoS1" GroupName="sqos">1 (At least once)</RadioButton> | ||||
<RadioButton Margin="0,0,10,0" x:Name="SubscribeQoS2" GroupName="sqos">2 (Exactly once)</RadioButton> | <RadioButton Margin="0,0,10,0" x:Name="SubscribeQoS2" GroupName="sqos">2 (Exactly once)</RadioButton> | ||||
</StackPanel> | </StackPanel> | ||||
@@ -41,7 +41,7 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
private async void Connect(object sender, RoutedEventArgs e) | private async void Connect(object sender, RoutedEventArgs e) | ||||
{ | { | ||||
MqttClientOptions options = null; | |||||
BaseMqttClientOptions options = null; | |||||
if (UseTcp.IsChecked == true) | if (UseTcp.IsChecked == true) | ||||
{ | { | ||||
options = new MqttClientTcpOptions | 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() | private async Task WikiCode() | ||||
{ | { | ||||
var mqttClient = new MqttClientFactory().CreateMqttClient(); | var mqttClient = new MqttClientFactory().CreateMqttClient(); | ||||