Browse Source

Fix breaking changes.

release/3.x.x
Christian Kratky 7 years ago
parent
commit
929cdb971a
92 changed files with 1363 additions and 1309 deletions
  1. +117
    -0
      Frameworks/MQTTnet.NetCoreApp/Implementations/MqttServerAdapter.cs
  2. +122
    -0
      Frameworks/MQTTnet.NetCoreApp/Implementations/MqttTcpChannel.cs
  3. +2
    -4
      Frameworks/MQTTnet.NetCoreApp/MqttClientFactory.cs
  4. +0
    -122
      Frameworks/MQTTnet.NetCoreApp/MqttClientSslChannel.cs
  5. +0
    -56
      Frameworks/MQTTnet.NetCoreApp/MqttServerAdapter.cs
  6. +4
    -2
      Frameworks/MQTTnet.NetCoreApp/MqttServerFactory.cs
  7. +0
    -123
      Frameworks/MQTTnet.NetCoreApp/MqttServerSslChannel.cs
  8. +0
    -64
      Frameworks/MQTTnet.NetCoreApp/MqttSslServerAdapter.cs
  9. +0
    -81
      Frameworks/MQTTnet.NetCoreApp/MqttTcpChannel.cs
  10. +117
    -0
      Frameworks/MQTTnet.NetFramework/Implementations/MqttServerAdapter.cs
  11. +49
    -5
      Frameworks/MQTTnet.NetFramework/Implementations/MqttTcpChannel.cs
  12. +2
    -5
      Frameworks/MQTTnet.NetFramework/MQTTnet.NetFramework.csproj
  13. +4
    -6
      Frameworks/MQTTnet.NetFramework/MqttClientFactory.cs
  14. +0
    -121
      Frameworks/MQTTnet.NetFramework/MqttClientSslChannel.cs
  15. +0
    -56
      Frameworks/MQTTnet.NetFramework/MqttServerAdapter.cs
  16. +4
    -2
      Frameworks/MQTTnet.NetFramework/MqttServerFactory.cs
  17. +0
    -123
      Frameworks/MQTTnet.NetFramework/MqttServerSslChannel.cs
  18. +0
    -64
      Frameworks/MQTTnet.NetFramework/MqttSslServerAdapter.cs
  19. +90
    -0
      Frameworks/MQTTnet.UniversalWindows/Implementations/MqttServerAdapter.cs
  20. +121
    -0
      Frameworks/MQTTnet.UniversalWindows/Implementations/MqttTcpChannel.cs
  21. +2
    -2
      Frameworks/MQTTnet.UniversalWindows/MQTTnet.UniversalWindows.csproj
  22. +2
    -1
      Frameworks/MQTTnet.UniversalWindows/MqttClientFactory.cs
  23. +0
    -54
      Frameworks/MQTTnet.UniversalWindows/MqttServerAdapter.cs
  24. +4
    -1
      Frameworks/MQTTnet.UniversalWindows/MqttServerFactory.cs
  25. +0
    -62
      Frameworks/MQTTnet.UniversalWindows/MqttTcpChannel.cs
  26. +9
    -3
      MQTTnet.Core/Client/MqttClient.cs
  27. +4
    -21
      MQTTnet.Core/Client/MqttClientOptions.cs
  28. +19
    -0
      MQTTnet.Core/Client/MqttClientOptionsExtensions.cs
  29. +13
    -0
      MQTTnet.Core/Client/MqttClientSslOptions.cs
  30. +1
    -1
      MQTTnet.Core/Diagnostics/MqttTraceMessagePublishedEventArgs.cs
  31. +1
    -1
      MQTTnet.Core/Exceptions/MqttCommunicationTimedOutException.cs
  32. +1
    -1
      MQTTnet.Core/Exceptions/MqttProtocolViolationException.cs
  33. +1
    -1
      MQTTnet.Core/Internal/AsyncAutoResetEvent.cs
  34. +0
    -11
      MQTTnet.Core/Internal/TaskExtensions.cs
  35. +1
    -1
      MQTTnet.Core/MqttApplicationMessage.cs
  36. +1
    -1
      MQTTnet.Core/MqttApplicationMessageReceivedEventArgs.cs
  37. +1
    -1
      MQTTnet.Core/Packets/MqttConnAckPacket.cs
  38. +1
    -1
      MQTTnet.Core/Packets/MqttConnectPacket.cs
  39. +1
    -1
      MQTTnet.Core/Packets/MqttDisconnectPacket.cs
  40. +1
    -1
      MQTTnet.Core/Packets/MqttPingReqPacket.cs
  41. +1
    -1
      MQTTnet.Core/Packets/MqttPingRespPacket.cs
  42. +1
    -1
      MQTTnet.Core/Packets/MqttPubAckPacket.cs
  43. +1
    -1
      MQTTnet.Core/Packets/MqttPubCompPacket.cs
  44. +1
    -1
      MQTTnet.Core/Packets/MqttPubRecPacket.cs
  45. +1
    -1
      MQTTnet.Core/Packets/MqttPubRelPacket.cs
  46. +1
    -1
      MQTTnet.Core/Packets/MqttPublishPacket.cs
  47. +1
    -1
      MQTTnet.Core/Packets/MqttSubAckPacket.cs
  48. +1
    -1
      MQTTnet.Core/Packets/MqttSubscribePacket.cs
  49. +1
    -1
      MQTTnet.Core/Packets/MqttUnsubAckPacket.cs
  50. +1
    -1
      MQTTnet.Core/Packets/MqttUnsubscribe.cs
  51. +1
    -1
      MQTTnet.Core/Packets/TopicFilter.cs
  52. +1
    -1
      MQTTnet.Core/Serializer/ByteReader.cs
  53. +1
    -1
      MQTTnet.Core/Serializer/ByteWriter.cs
  54. +1
    -1
      MQTTnet.Core/Serializer/DefaultMqttV311PacketSerializer.cs
  55. +9
    -0
      MQTTnet.Core/Server/DefaultEndpointOptions.cs
  56. +1
    -1
      MQTTnet.Core/Server/GetOrCreateClientSessionResult.cs
  57. +1
    -1
      MQTTnet.Core/Server/MqttClientMessageQueue.cs
  58. +1
    -1
      MQTTnet.Core/Server/MqttClientPublishPacketContext.cs
  59. +1
    -1
      MQTTnet.Core/Server/MqttClientSessionsManager.cs
  60. +1
    -1
      MQTTnet.Core/Server/MqttClientSubscriptionsManager.cs
  61. +15
    -9
      MQTTnet.Core/Server/MqttServer.cs
  62. +4
    -9
      MQTTnet.Core/Server/MqttServerOptions.cs
  63. +31
    -0
      MQTTnet.Core/Server/MqttServerOptionsExtensions.cs
  64. +11
    -0
      MQTTnet.Core/Server/SslEndpointOptions.cs
  65. +19
    -0
      MQTTnet.Core/Server/SslEndpointOptionsExtensions.cs
  66. +3
    -1
      MQTTnet.nuspec
  67. +63
    -55
      MQTTnet.sln
  68. +12
    -2
      README.md
  69. +6
    -4
      Tests/MQTTnet.Core.Tests/MqttServerTests.cs
  70. +0
    -0
      Tests/MQTTnet.TestApp.NetFramework/App.config
  71. +9
    -37
      Tests/MQTTnet.TestApp.NetFramework/MQTTnet.TestApp.NetFramework.csproj
  72. +67
    -8
      Tests/MQTTnet.TestApp.NetFramework/Program.cs
  73. +1
    -1
      Tests/MQTTnet.TestApp.NetFramework/Properties/AssemblyInfo.cs
  74. +8
    -0
      Tests/MQTTnet.TestApp.UniversalWindows/App.xaml
  75. +100
    -0
      Tests/MQTTnet.TestApp.UniversalWindows/App.xaml.cs
  76. BIN
     
  77. BIN
     
  78. BIN
     
  79. BIN
     
  80. BIN
     
  81. BIN
     
  82. BIN
     
  83. +149
    -0
      Tests/MQTTnet.TestApp.UniversalWindows/MQTTnet.TestApp.UniversalWindows.csproj
  84. +13
    -0
      Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml
  85. +30
    -0
      Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml.cs
  86. +49
    -0
      Tests/MQTTnet.TestApp.UniversalWindows/Package.appxmanifest
  87. +3
    -4
      Tests/MQTTnet.TestApp.UniversalWindows/Properties/AssemblyInfo.cs
  88. +31
    -0
      Tests/MQTTnet.TestApp.UniversalWindows/Properties/Default.rd.xml
  89. +16
    -0
      Tests/MQTTnet.TestApp.UniversalWindows/project.json
  90. +0
    -6
      Tests/MQTTnet.TestMqttClient/App.config
  91. +0
    -100
      Tests/MQTTnet.TestMqttClient/MQTTnet.TestMqttClient.csproj
  92. +0
    -55
      Tests/MQTTnet.TestMqttServer/Program.cs

+ 117
- 0
Frameworks/MQTTnet.NetCoreApp/Implementations/MqttServerAdapter.cs View File

@@ -0,0 +1,117 @@
using System;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;

namespace MQTTnet.Implementations
{
public class MqttServerAdapter : IMqttServerAdapter, IDisposable
{
private CancellationTokenSource _cancellationTokenSource;
private Socket _defaultEndpointSocket;
private Socket _sslEndpointSocket;
private X509Certificate2 _sslCertificate;

private bool _isRunning;

public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;

public void Start(MqttServerOptions options)
{
if (_isRunning) throw new InvalidOperationException("Server is already started.");
_isRunning = true;

_cancellationTokenSource = new CancellationTokenSource();

if (options.DefaultEndpointOptions.IsEnabled)
{
_defaultEndpointSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_defaultEndpointSocket.Bind(new IPEndPoint(IPAddress.Any, options.GetDefaultEndpointPort()));
_defaultEndpointSocket.Listen(options.ConnectionBacklog);

Task.Run(() => AcceptDefaultEndpointConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
}

if (options.SslEndpointOptions.IsEnabled)
{
if (options.SslEndpointOptions.Certificate == null)
{
throw new ArgumentException("SSL certificate is not set.");
}

_sslCertificate = new X509Certificate2(options.SslEndpointOptions.Certificate);

_sslEndpointSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_sslEndpointSocket.Bind(new IPEndPoint(IPAddress.Any, options.GetSslEndpointPort()));
_sslEndpointSocket.Listen(options.ConnectionBacklog);

Task.Run(() => AcceptSslEndpointConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
}
}

public void Stop()
{
_isRunning = false;

_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;

_defaultEndpointSocket?.Dispose();
_defaultEndpointSocket = null;

_sslEndpointSocket?.Dispose();
_sslEndpointSocket = null;
}

public void Dispose()
{
Stop();
}

private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
var clientSocket = await _defaultEndpointSocket.AcceptAsync();
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, null), new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at default endpoint.");
}
}
}

private async Task AcceptSslEndpointConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
var clientSocket = await _defaultEndpointSocket.AcceptAsync();

var sslStream = new SslStream(new NetworkStream(clientSocket));
await sslStream.AuthenticateAsServerAsync(_sslCertificate, false, SslProtocols.Tls12, false);
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, sslStream), new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at SSL endpoint.");
}
}
}
}
}

+ 122
- 0
Frameworks/MQTTnet.NetCoreApp/Implementations/MqttTcpChannel.cs View File

@@ -0,0 +1,122 @@
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions;

namespace MQTTnet.Implementations
{
public class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
{
private readonly Socket _socket;
private SslStream _sslStream;

public MqttTcpChannel()
{
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
}

public MqttTcpChannel(Socket socket, SslStream sslStream)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
_sslStream = sslStream;
}

public async Task ConnectAsync(MqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
try
{
await _socket.ConnectAsync(options.Server, options.GetPort());
if (options.SslOptions.UseSsl)
{
_sslStream = new SslStream(new NetworkStream(_socket, true));
await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.SslOptions.CheckCertificateRevocation);
}
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public Task DisconnectAsync()
{
try
{
_sslStream.Dispose();
_socket.Dispose();
return Task.FromResult(0);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public Task WriteAsync(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));

try
{
if (_sslStream != null)
{
return _sslStream.WriteAsync(buffer, 0, buffer.Length);
}

return _socket.SendAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public Task ReadAsync(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));

try
{
if (_sslStream != null)
{
return _sslStream.ReadAsync(buffer, 0, buffer.Length);
}

return _socket.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public void Dispose()
{
_socket?.Dispose();
_sslStream?.Dispose();
}

private static X509CertificateCollection LoadCertificates(MqttClientOptions options)
{
var certificates = new X509CertificateCollection();
if (options.SslOptions.Certificates == null)
{
return certificates;
}

foreach (var certificate in options.SslOptions.Certificates)
{
certificates.Add(new X509Certificate(certificate));
}

return certificates;
}
}
}

+ 2
- 4
Frameworks/MQTTnet.NetCoreApp/MqttClientFactory.cs View File

@@ -1,8 +1,8 @@
using System;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Serializer;
using MQTTnet.Implementations;

namespace MQTTnet
{
@@ -12,9 +12,7 @@ namespace MQTTnet
{
if (options == null) throw new ArgumentNullException(nameof(options));

return new MqttClient(options,
new MqttChannelCommunicationAdapter(options.UseSSL ? new MqttClientSslChannel() : (IMqttCommunicationChannel) new MqttTcpChannel(),
new DefaultMqttV311PacketSerializer()));
return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
}
}
}

+ 0
- 122
Frameworks/MQTTnet.NetCoreApp/MqttClientSslChannel.cs View File

@@ -1,122 +0,0 @@
using System;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions;

namespace MQTTnet
{
/// <summary>
/// Describes an SSL channel to an MQTT server.
/// </summary>
public class MqttClientSslChannel : IMqttCommunicationChannel, IDisposable
{
private readonly Socket _socket;
private SslStream _sslStream;

/// <summary>
/// Creates a new <see cref="MqttClientSslChannel"/>.
/// </summary>
public MqttClientSslChannel()
{
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
}

/// <summary>
/// Creates a new <see cref="MqttClientSslChannel"/> with a predefined <paramref name="socket"/>.
/// </summary>
/// <param name="socket"></param>
public MqttClientSslChannel(Socket socket)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
}

/// <summary>
/// Asynchronously connects to the host described in the <see cref="MqttClientOptions"/>.
/// </summary>
/// <param name="options">The <see cref="MqttClientOptions"/> describing the connection.</param>
public async Task ConnectAsync(MqttClientOptions options)
{
try
{
await _socket.ConnectAsync(options.Server, options.Port);

NetworkStream ns = new NetworkStream(_socket, true);
_sslStream = new SslStream(ns);

await _sslStream.AuthenticateAsClientAsync(options.Server, null, SslProtocols.Tls12, false);

}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

/// <summary>
/// Asynchronously disconnects the client from the server.
/// </summary>
public Task DisconnectAsync()
{
try
{
_socket.Dispose();
return Task.FromResult(0);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

/// <summary>
/// Asynchronously writes a sequence of bytes to the socket.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
public Task WriteAsync(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));

try
{
return _sslStream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
when (ex is SocketException || ex is IOException)
{
throw new MqttCommunicationException(ex);
}
}

/// <summary>
/// Asynchronously reads a sequence of bytes from the socket.
/// </summary>
/// <param name="buffer">The buffer to write the data into.</param>
public Task ReadAsync(byte[] buffer)
{
try
{
return _sslStream.ReadAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
when (ex is SocketException || ex is IOException)
{
throw new MqttCommunicationException(ex);
}
}

/// <summary>
/// Releases all resources used by the <see cref="MqttClientSslChannel"/>.
/// </summary>
public void Dispose()
{
_sslStream?.Dispose();
_socket?.Dispose();
}
}
}

+ 0
- 56
Frameworks/MQTTnet.NetCoreApp/MqttServerAdapter.cs View File

@@ -1,56 +0,0 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;

namespace MQTTnet
{
public sealed class MqttServerAdapter : IMqttServerAdapter, IDisposable
{
private CancellationTokenSource _cancellationTokenSource;
private Socket _socket;

public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;

public void Start(MqttServerOptions options)
{
if (_socket != null) throw new InvalidOperationException("Server is already started.");

_cancellationTokenSource = new CancellationTokenSource();

_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(IPAddress.Any, options.Port));
_socket.Listen(options.ConnectionBacklog);
Task.Run(async () => await AcceptConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
}

public void Stop()
{
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;

_socket?.Dispose();
_socket = null;
}

public void Dispose()
{
Stop();
}

private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var clientSocket = await _socket.AcceptAsync();
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket), new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
}
}
}
}

+ 4
- 2
Frameworks/MQTTnet.NetCoreApp/MqttServerFactory.cs View File

@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server;
using MQTTnet.Implementations;

namespace MQTTnet
{
@@ -9,8 +11,8 @@ namespace MQTTnet
public MqttServer CreateMqttServer(MqttServerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
return new MqttServer(options, options.UseSSL ? (IMqttServerAdapter)new MqttSslServerAdapter() : new MqttServerAdapter());
return new MqttServer(options, new List<IMqttServerAdapter> { new MqttServerAdapter() });
}
}
}

+ 0
- 123
Frameworks/MQTTnet.NetCoreApp/MqttServerSslChannel.cs View File

@@ -1,123 +0,0 @@
using System;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions;

namespace MQTTnet
{
/// <summary>
/// Describes an SSL channel to a client.
/// </summary>
public class MqttServerSslChannel : IMqttCommunicationChannel, IDisposable
{
private readonly Socket _socket;
private readonly SslStream _sslStream;
private readonly X509Certificate2 _cert;
/// <summary>
/// Creates a new <see cref="MqttClientSslChannel"/> with a predefined <paramref name="socket"/>.
/// </summary>
/// <param name="socket">The client socket.</param>
/// <param name="cert">The X509 certificate used to authenticate as a server.</param>
public MqttServerSslChannel(Socket socket, X509Certificate2 cert)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
_cert = cert ?? throw new ArgumentNullException(nameof(cert));

if (!_socket.Connected)
return;

NetworkStream ns = new NetworkStream(_socket, true);
_sslStream = new SslStream(ns);
}

public Task Authenticate()
{
return _sslStream.AuthenticateAsServerAsync(_cert, false, SslProtocols.Tls12, false);
}

/// <summary>
/// Asynchronously connects to the client described in the <see cref="MqttClientOptions"/>.
/// </summary>
/// <param name="options">The <see cref="MqttClientOptions"/> describing the connection.</param>
public Task ConnectAsync(MqttClientOptions options)
{
try
{
return _socket.ConnectAsync(options.Server, options.Port);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

/// <summary>
/// Asynchronously disconnects the client from the server.
/// </summary>
public Task DisconnectAsync()
{
try
{
_socket.Dispose();
return Task.FromResult(0);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

/// <summary>
/// Asynchronously writes a sequence of bytes to the socket.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
public Task WriteAsync(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));

try
{
return _sslStream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
when (ex is SocketException || ex is IOException)
{
throw new MqttCommunicationException(ex);
}
}

/// <summary>
/// Asynchronously reads a sequence of bytes from the socket.
/// </summary>
/// <param name="buffer">The buffer to write the data into.</param>
public Task ReadAsync(byte[] buffer)
{
try
{
return _sslStream.ReadAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
when (ex is SocketException || ex is IOException)
{
throw new MqttCommunicationException(ex);
}
}

/// <summary>
/// Releases all resources used by the <see cref="MqttClientSslChannel"/>.
/// </summary>
public void Dispose()
{
_sslStream?.Dispose();
_socket?.Dispose();
}
}
}

+ 0
- 64
Frameworks/MQTTnet.NetCoreApp/MqttSslServerAdapter.cs View File

@@ -1,64 +0,0 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;

namespace MQTTnet
{
public class MqttSslServerAdapter : IMqttServerAdapter, IDisposable
{
private CancellationTokenSource _cancellationTokenSource;
private Socket _socket;
private X509Certificate2 _x590Certificate2;

public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;

public void Start(MqttServerOptions options)
{
if (_socket != null) throw new InvalidOperationException("Server is already started.");

_cancellationTokenSource = new CancellationTokenSource();

_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(IPAddress.Any, options.Port));
_socket.Listen(options.ConnectionBacklog);

Task.Run(async () => await AcceptConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);

_x590Certificate2 = new X509Certificate2(options.CertificatePath);
}

public void Stop()
{
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;

_socket?.Dispose();
_socket = null;
}

public void Dispose()
{
Stop();
}

private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var clientSocket = await _socket.AcceptAsync();

MqttServerSslChannel mssc = new MqttServerSslChannel(clientSocket, _x590Certificate2);
await mssc.Authenticate();

var clientAdapter = new MqttChannelCommunicationAdapter(mssc, new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
}
}
}
}

+ 0
- 81
Frameworks/MQTTnet.NetCoreApp/MqttTcpChannel.cs View File

@@ -1,81 +0,0 @@
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions;

namespace MQTTnet
{
public class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
{
private readonly Socket _socket;

public MqttTcpChannel()
{
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
}

public MqttTcpChannel(Socket socket)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
}

public Task ConnectAsync(MqttClientOptions options)
{
try
{
return _socket.ConnectAsync(options.Server, options.Port);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public Task DisconnectAsync()
{
try
{
_socket.Dispose();
return Task.FromResult(0);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public Task WriteAsync(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));

try
{
return _socket.SendAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public Task ReadAsync(byte[] buffer)
{
try
{
var buffer2 = new ArraySegment<byte>(buffer);
return _socket.ReceiveAsync(buffer2, SocketFlags.None);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public void Dispose()
{
_socket?.Dispose();
}
}
}

+ 117
- 0
Frameworks/MQTTnet.NetFramework/Implementations/MqttServerAdapter.cs View File

@@ -0,0 +1,117 @@
using System;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;

namespace MQTTnet.Implementations
{
public class MqttServerAdapter : IMqttServerAdapter, IDisposable
{
private CancellationTokenSource _cancellationTokenSource;
private Socket _defaultEndpointSocket;
private Socket _sslEndpointSocket;
private X509Certificate2 _sslCertificate;

private bool _isRunning;

public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;

public void Start(MqttServerOptions options)
{
if (_isRunning) throw new InvalidOperationException("Server is already started.");
_isRunning = true;

_cancellationTokenSource = new CancellationTokenSource();

if (options.DefaultEndpointOptions.IsEnabled)
{
_defaultEndpointSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_defaultEndpointSocket.Bind(new IPEndPoint(IPAddress.Any, options.GetDefaultEndpointPort()));
_defaultEndpointSocket.Listen(options.ConnectionBacklog);

Task.Run(() => AcceptDefaultEndpointConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
}

if (options.SslEndpointOptions.IsEnabled)
{
if (options.SslEndpointOptions.Certificate == null)
{
throw new ArgumentException("SSL certificate is not set.");
}

_sslCertificate = new X509Certificate2(options.SslEndpointOptions.Certificate);

_sslEndpointSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_sslEndpointSocket.Bind(new IPEndPoint(IPAddress.Any, options.GetSslEndpointPort()));
_sslEndpointSocket.Listen(options.ConnectionBacklog);

Task.Run(() => AcceptSslEndpointConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
}
}

public void Stop()
{
_isRunning = false;

_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;

_defaultEndpointSocket?.Dispose();
_defaultEndpointSocket = null;

_sslEndpointSocket?.Dispose();
_sslEndpointSocket = null;
}

public void Dispose()
{
Stop();
}

private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null);
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, null), new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at default endpoint.");
}
}
}

private async Task AcceptSslEndpointConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null);

var sslStream = new SslStream(new NetworkStream(clientSocket));
await sslStream.AuthenticateAsServerAsync(_sslCertificate, false, SslProtocols.Tls12, false);
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, sslStream), new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at SSL endpoint.");
}
}
}
}
}

Frameworks/MQTTnet.NetFramework/MqttTcpChannel.cs → Frameworks/MQTTnet.NetFramework/Implementations/MqttTcpChannel.cs View File

@@ -1,31 +1,43 @@
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions;

namespace MQTTnet
namespace MQTTnet.Implementations
{
public class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
{
private readonly Socket _socket;
private SslStream _sslStream;

public MqttTcpChannel()
{
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
}

public MqttTcpChannel(Socket socket)
public MqttTcpChannel(Socket socket, SslStream sslStream)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
_sslStream = sslStream;
}

public Task ConnectAsync(MqttClientOptions options)
public async Task ConnectAsync(MqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
try
{
return Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, options.Server, options.Port, null);
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, options.Server, options.GetPort(), null);

if (options.SslOptions.UseSsl)
{
_sslStream = new SslStream(new NetworkStream(_socket, true));
await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.SslOptions.CheckCertificateRevocation);
}
}
catch (SocketException exception)
{
@@ -37,7 +49,9 @@ namespace MQTTnet
{
try
{
return Task.Factory.FromAsync(_socket.BeginDisconnect, _socket.EndDisconnect, true, null);
_sslStream.Dispose();
_socket.Dispose();
return Task.FromResult(0);
}
catch (SocketException exception)
{
@@ -51,10 +65,16 @@ namespace MQTTnet

try
{
if (_sslStream != null)
{
return _sslStream.WriteAsync(buffer, 0, buffer.Length);
}

return Task.Factory.FromAsync(
// ReSharper disable once AssignNullToNotNullAttribute
_socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null),
_socket.EndSend);

}
catch (SocketException exception)
{
@@ -64,8 +84,15 @@ namespace MQTTnet

public Task ReadAsync(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));

try
{
if (_sslStream != null)
{
return _sslStream.ReadAsync(buffer, 0, buffer.Length);
}

return Task.Factory.FromAsync(
// ReSharper disable once AssignNullToNotNullAttribute
_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, null, null),
@@ -80,6 +107,23 @@ namespace MQTTnet
public void Dispose()
{
_socket?.Dispose();
_sslStream?.Dispose();
}

private static X509CertificateCollection LoadCertificates(MqttClientOptions options)
{
var certificates = new X509CertificateCollection();
if (options.SslOptions.Certificates == null)
{
return certificates;
}

foreach (var certificate in options.SslOptions.Certificates)
{
certificates.Add(new X509Certificate(certificate));
}

return certificates;
}
}
}

+ 2
- 5
Frameworks/MQTTnet.NetFramework/MQTTnet.NetFramework.csproj View File

@@ -101,13 +101,10 @@
</ItemGroup>
<ItemGroup>
<Compile Include="MqttClientFactory.cs" />
<Compile Include="MqttServerAdapter.cs" />
<Compile Include="MqttServerFactory.cs" />
<Compile Include="MqttClientSslChannel.cs" />
<Compile Include="MqttServerSslChannel.cs" />
<Compile Include="MqttSslServerAdapter.cs" />
<Compile Include="Implementations\MqttServerAdapter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MqttTcpChannel.cs" />
<Compile Include="Implementations\MqttTcpChannel.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">


+ 4
- 6
Frameworks/MQTTnet.NetFramework/MqttClientFactory.cs View File

@@ -1,8 +1,8 @@
using System;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Serializer;
using MQTTnet.Implementations;

namespace MQTTnet
{
@@ -11,10 +11,8 @@ namespace MQTTnet
public MqttClient CreateMqttClient(MqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
return new MqttClient(options,
new MqttChannelCommunicationAdapter(options.UseSSL ? new MqttClientSslChannel() : (IMqttCommunicationChannel)new MqttTcpChannel(),
new DefaultMqttV311PacketSerializer()));

return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
}
}
}
}

+ 0
- 121
Frameworks/MQTTnet.NetFramework/MqttClientSslChannel.cs View File

@@ -1,121 +0,0 @@
using System;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions;

namespace MQTTnet
{
/// <summary>
/// Describes an SSL channel to an MQTT server.
/// </summary>
public class MqttClientSslChannel : IMqttCommunicationChannel, IDisposable
{
private readonly Socket _socket;
private SslStream _sslStream;

/// <summary>
/// Creates a new <see cref="MqttClientSslChannel"/>.
/// </summary>
public MqttClientSslChannel()
{
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
}

/// <summary>
/// Creates a new <see cref="MqttClientSslChannel"/> with a predefined <paramref name="socket"/>.
/// </summary>
/// <param name="socket"></param>
public MqttClientSslChannel(Socket socket)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
}

/// <summary>
/// Asynchronously connects to the host described in the <see cref="MqttClientOptions"/>.
/// </summary>
/// <param name="options">The <see cref="MqttClientOptions"/> describing the connection.</param>
public async Task ConnectAsync(MqttClientOptions options)
{
try
{
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, options.Server, options.Port,
null);

NetworkStream ns = new NetworkStream(_socket, true);
_sslStream = new SslStream(ns);

await _sslStream.AuthenticateAsClientAsync(options.Server, null, SslProtocols.Tls12, false);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

/// <summary>
/// Asynchronously disconnects the client from the server.
/// </summary>
public Task DisconnectAsync()
{
try
{
return Task.Factory.FromAsync(_socket.BeginDisconnect, _socket.EndDisconnect, true, null);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

/// <summary>
/// Asynchronously writes a sequence of bytes to the socket.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
public Task WriteAsync(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));

try
{
return _sslStream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
when (ex is SocketException || ex is IOException)
{
throw new MqttCommunicationException(ex);
}
}

/// <summary>
/// Asynchronously reads a sequence of bytes from the socket.
/// </summary>
/// <param name="buffer">The buffer to write the data into.</param>
public Task ReadAsync(byte[] buffer)
{
try
{
return _sslStream.ReadAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
when (ex is SocketException || ex is IOException)
{
throw new MqttCommunicationException(ex);
}
}

/// <summary>
/// Releases all resources used by the <see cref="MqttClientSslChannel"/>.
/// </summary>
public void Dispose()
{
_sslStream?.Dispose();
_socket?.Dispose();
}
}
}

+ 0
- 56
Frameworks/MQTTnet.NetFramework/MqttServerAdapter.cs View File

@@ -1,56 +0,0 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;

namespace MQTTnet
{
public sealed class MqttServerAdapter : IMqttServerAdapter, IDisposable
{
private CancellationTokenSource _cancellationTokenSource;
private Socket _socket;

public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;

public void Start(MqttServerOptions options)
{
if (_socket != null) throw new InvalidOperationException("Server is already started.");

_cancellationTokenSource = new CancellationTokenSource();

_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(IPAddress.Any, options.Port));
_socket.Listen(options.ConnectionBacklog);
Task.Run(async () => await AcceptConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
}

public void Stop()
{
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;

_socket?.Dispose();
_socket = null;
}

public void Dispose()
{
Stop();
}

private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var clientSocket = await Task.Factory.FromAsync(_socket.BeginAccept, _socket.EndAccept, null);
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket), new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
}
}
}
}

+ 4
- 2
Frameworks/MQTTnet.NetFramework/MqttServerFactory.cs View File

@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server;
using MQTTnet.Implementations;

namespace MQTTnet
{
@@ -9,8 +11,8 @@ namespace MQTTnet
public MqttServer CreateMqttServer(MqttServerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
return new MqttServer(options, options.UseSSL ? (IMqttServerAdapter) new MqttSslServerAdapter() : new MqttServerAdapter());
return new MqttServer(options, new List<IMqttServerAdapter> { new MqttServerAdapter() });
}
}
}

+ 0
- 123
Frameworks/MQTTnet.NetFramework/MqttServerSslChannel.cs View File

@@ -1,123 +0,0 @@
using System;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions;

namespace MQTTnet
{
/// <summary>
/// Describes an SSL channel to a client.
/// </summary>
public class MqttServerSslChannel : IMqttCommunicationChannel, IDisposable
{
private readonly Socket _socket;
private SslStream _sslStream;
private X509Certificate2 _cert;
/// <summary>
/// Creates a new <see cref="MqttClientSslChannel"/> with a predefined <paramref name="socket"/>.
/// </summary>
/// <param name="socket">The client socket.</param>
/// <param name="cert">The X509 certificate used to authenticate as a server.</param>
public MqttServerSslChannel(Socket socket, X509Certificate2 cert)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
_cert = cert ?? throw new ArgumentNullException(nameof(cert));

if (!_socket.Connected)
return;

NetworkStream ns = new NetworkStream(_socket, true);
_sslStream = new SslStream(ns);
}

public async Task Authenticate()
{
await _sslStream.AuthenticateAsServerAsync(_cert, false, SslProtocols.Tls12, false);
}

/// <summary>
/// Asynchronously connects to the client described in the <see cref="MqttClientOptions"/>.
/// </summary>
/// <param name="options">The <see cref="MqttClientOptions"/> describing the connection.</param>
public Task ConnectAsync(MqttClientOptions options)
{
try
{
return Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, options.Server, options.Port,
null);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

/// <summary>
/// Asynchronously disconnects the client from the server.
/// </summary>
public Task DisconnectAsync()
{
try
{
return Task.Factory.FromAsync(_socket.BeginDisconnect, _socket.EndDisconnect, true, null);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

/// <summary>
/// Asynchronously writes a sequence of bytes to the socket.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
public Task WriteAsync(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));

try
{
return _sslStream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
when (ex is SocketException || ex is IOException)
{
throw new MqttCommunicationException(ex);
}
}

/// <summary>
/// Asynchronously reads a sequence of bytes from the socket.
/// </summary>
/// <param name="buffer">The buffer to write the data into.</param>
public Task ReadAsync(byte[] buffer)
{
try
{
return _sslStream.ReadAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
when (ex is SocketException || ex is IOException)
{
throw new MqttCommunicationException(ex);
}
}

/// <summary>
/// Releases all resources used by the <see cref="MqttClientSslChannel"/>.
/// </summary>
public void Dispose()
{
_sslStream?.Dispose();
_socket?.Dispose();
}
}
}

+ 0
- 64
Frameworks/MQTTnet.NetFramework/MqttSslServerAdapter.cs View File

@@ -1,64 +0,0 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;

namespace MQTTnet
{
public class MqttSslServerAdapter : IMqttServerAdapter, IDisposable
{
private CancellationTokenSource _cancellationTokenSource;
private Socket _socket;
private X509Certificate2 _x590Certificate2;

public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;

public void Start(MqttServerOptions options)
{
if (_socket != null) throw new InvalidOperationException("Server is already started.");

_cancellationTokenSource = new CancellationTokenSource();

_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(IPAddress.Any, options.Port));
_socket.Listen(options.ConnectionBacklog);

Task.Run(async () => await AcceptConnectionsAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);

_x590Certificate2 = new X509Certificate2(options.CertificatePath);
}

public void Stop()
{
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;

_socket?.Dispose();
_socket = null;
}

public void Dispose()
{
Stop();
}

private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var clientSocket = await Task.Factory.FromAsync(_socket.BeginAccept, _socket.EndAccept, null);

MqttServerSslChannel mssc = new MqttServerSslChannel(clientSocket, _x590Certificate2);
await mssc.Authenticate();

var clientAdapter = new MqttChannelCommunicationAdapter(mssc, new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter));
}
}
}
}

+ 90
- 0
Frameworks/MQTTnet.UniversalWindows/Implementations/MqttServerAdapter.cs View File

@@ -0,0 +1,90 @@
using System;
using System.Security.Cryptography.X509Certificates;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;
using Windows.Networking.Sockets;

namespace MQTTnet.Implementations
{
public class MqttServerAdapter : IMqttServerAdapter, IDisposable
{
private StreamSocketListener _defaultEndpointSocket;
private StreamSocketListener _sslEndpointSocket;
private X509Certificate2 _sslCertificate;

private bool _isRunning;

public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;

public void Start(MqttServerOptions options)
{
if (_isRunning) throw new InvalidOperationException("Server is already started.");
_isRunning = true;

if (options.DefaultEndpointOptions.IsEnabled)
{
_defaultEndpointSocket = new StreamSocketListener();
_defaultEndpointSocket.BindServiceNameAsync(options.GetDefaultEndpointPort().ToString(), SocketProtectionLevel.PlainSocket).GetAwaiter().GetResult();
_defaultEndpointSocket.ConnectionReceived += AcceptDefaultEndpointConnectionsAsync;
}

if (options.SslEndpointOptions.IsEnabled)
{
if (options.SslEndpointOptions.Certificate == null)
{
throw new ArgumentException("SSL certificate is not set.");
}

_sslCertificate = new X509Certificate2(options.SslEndpointOptions.Certificate);

_sslEndpointSocket = new StreamSocketListener();
_sslEndpointSocket.BindServiceNameAsync(options.GetSslEndpointPort().ToString(), SocketProtectionLevel.Tls12).GetAwaiter().GetResult();
_sslEndpointSocket.ConnectionReceived += AcceptSslEndpointConnectionsAsync;
}
}

public void Stop()
{
_isRunning = false;

_defaultEndpointSocket?.Dispose();
_defaultEndpointSocket = null;

_sslEndpointSocket?.Dispose();
_sslEndpointSocket = null;
}

public void Dispose()
{
Stop();
}

private void AcceptDefaultEndpointConnectionsAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
try
{
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(args.Socket), new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(args.Socket.Information.RemoteAddress.ToString(), clientAdapter));
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at default endpoint.");
}
}

private void AcceptSslEndpointConnectionsAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
try
{
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(args.Socket), new DefaultMqttV311PacketSerializer());
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(args.Socket.Information.RemoteAddress.ToString(), clientAdapter));
}
catch (Exception exception)
{
MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at SSL endpoint.");
}
}
}
}

+ 121
- 0
Frameworks/MQTTnet.UniversalWindows/Implementations/MqttTcpChannel.cs View File

@@ -0,0 +1,121 @@
using System;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Security.Cryptography.Certificates;
using Windows.Storage.Streams;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions;

namespace MQTTnet.Implementations
{
public class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
{
private readonly StreamSocket _socket;

public MqttTcpChannel()
{
_socket = new StreamSocket();
}

public MqttTcpChannel(StreamSocket socket)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
}

public async Task ConnectAsync(MqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
try
{
if (!options.SslOptions.UseSsl)
{
await _socket.ConnectAsync(new HostName(options.Server), options.GetPort().ToString());
}
else
{
_socket.Control.ClientCertificate = LoadCertificate(options);

if (!options.SslOptions.CheckCertificateRevocation)
{
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Revoked);
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.IncompleteChain);
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationInformationMissing);
}
await _socket.ConnectAsync(new HostName(options.Server), options.GetPort().ToString(), SocketProtectionLevel.Tls12);
}
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public Task DisconnectAsync()
{
try
{
_socket.Dispose();
return Task.FromResult(0);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public async Task WriteAsync(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));

try
{
await _socket.OutputStream.WriteAsync(buffer.AsBuffer());
await _socket.OutputStream.FlushAsync();
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public async Task ReadAsync(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));

try
{
await _socket.InputStream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.Partial);
}
catch (SocketException exception)
{
throw new MqttCommunicationException(exception);
}
}

public void Dispose()
{
_socket?.Dispose();
}

private static Certificate LoadCertificate(MqttClientOptions options)
{
if (options.SslOptions.Certificates == null || !options.SslOptions.Certificates.Any())
{
return null;
}

if (options.SslOptions.Certificates.Count > 1)
{
throw new NotSupportedException("Only one client certificate is supported for UWP.");
}

return new Certificate(options.SslOptions.Certificates.First().AsBuffer());
}
}
}

+ 2
- 2
Frameworks/MQTTnet.UniversalWindows/MQTTnet.UniversalWindows.csproj View File

@@ -112,9 +112,9 @@
</ItemGroup>
<ItemGroup>
<Compile Include="MqttClientFactory.cs" />
<Compile Include="MqttServerAdapter.cs" />
<Compile Include="Implementations\MqttServerAdapter.cs" />
<Compile Include="MqttServerFactory.cs" />
<Compile Include="MqttTcpChannel.cs" />
<Compile Include="Implementations\MqttTcpChannel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Properties\MQTTnet.Universal.rd.xml" />
</ItemGroup>


+ 2
- 1
Frameworks/MQTTnet.UniversalWindows/MqttClientFactory.cs View File

@@ -2,6 +2,7 @@
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Client;
using MQTTnet.Core.Serializer;
using MQTTnet.Implementations;

namespace MQTTnet
{
@@ -14,4 +15,4 @@ namespace MQTTnet
return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
}
}
}
}

+ 0
- 54
Frameworks/MQTTnet.UniversalWindows/MqttServerAdapter.cs View File

@@ -1,54 +0,0 @@
using System;
using System.Threading;
using Windows.Networking.Sockets;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Serializer;
using MQTTnet.Core.Server;

namespace MQTTnet
{
public sealed class MqttServerAdapter : IMqttServerAdapter, IDisposable
{
private CancellationTokenSource _cancellationTokenSource;
private StreamSocketListener _socket;

public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;

public void Start(MqttServerOptions options)
{
if (_socket != null) throw new InvalidOperationException("Server is already started.");

_cancellationTokenSource = new CancellationTokenSource();

_socket = new StreamSocketListener();
_socket.BindServiceNameAsync(options.Port.ToString()).AsTask().Wait();
_socket.ConnectionReceived += ConnectionReceived;
}

private void ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(args.Socket), new DefaultMqttV311PacketSerializer());

var identifier = $"{args.Socket.Information.RemoteAddress}:{args.Socket.Information.RemotePort}";
ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(identifier, clientAdapter));
}

public void Stop()
{
_cancellationTokenSource?.Dispose();

if (_socket != null)
{
_socket.ConnectionReceived -= ConnectionReceived;
}

_socket?.Dispose();
_socket = null;
}

public void Dispose()
{
Stop();
}
}
}

+ 4
- 1
Frameworks/MQTTnet.UniversalWindows/MqttServerFactory.cs View File

@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server;
using MQTTnet.Implementations;

namespace MQTTnet
{
@@ -9,7 +12,7 @@ namespace MQTTnet
{
if (options == null) throw new ArgumentNullException(nameof(options));

return new MqttServer(options, new MqttServerAdapter());
return new MqttServer(options, new List<IMqttServerAdapter> { new MqttServerAdapter() });
}
}
}

+ 0
- 62
Frameworks/MQTTnet.UniversalWindows/MqttTcpChannel.cs View File

@@ -1,62 +0,0 @@
using System;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client;
using Buffer = Windows.Storage.Streams.Buffer;

namespace MQTTnet
{
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
{
private readonly StreamSocket _socket;

public MqttTcpChannel()
{
_socket = new StreamSocket();
}

public MqttTcpChannel(StreamSocket socket)
{
_socket = socket ?? throw new ArgumentNullException(nameof(socket));
}

public async Task ConnectAsync(MqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));

await _socket.ConnectAsync(new HostName(options.Server), options.Port.ToString());
}

public async Task DisconnectAsync()
{
await _socket.CancelIOAsync();
_socket.Dispose();
}

public async Task WriteAsync(byte[] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));

await _socket.OutputStream.WriteAsync(buffer.AsBuffer());
await _socket.OutputStream.FlushAsync();
}

public async Task ReadAsync(byte[] buffer)
{
var buffer2 = new Buffer((uint)buffer.Length);
await _socket.InputStream.ReadAsync(buffer2, (uint)buffer.Length, InputStreamOptions.None);

var array2 = buffer2.ToArray();
Array.Copy(array2, buffer, array2.Length);
}

public void Dispose()
{
_socket?.Dispose();
}
}
}

+ 9
- 3
MQTTnet.Core/Client/MqttClient.cs View File

@@ -67,7 +67,9 @@ namespace MQTTnet.Core.Client
_packetDispatcher.Reset();
IsConnected = true;

Task.Run(() => ReceivePackets(_cancellationTokenSource.Token), _cancellationTokenSource.Token).Forget();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(() => ReceivePackets(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

var response = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket);
if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
@@ -77,7 +79,9 @@ namespace MQTTnet.Core.Client

if (_options.KeepAlivePeriod != TimeSpan.Zero)
{
Task.Run(() => SendKeepAliveMessagesAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token).Forget();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(() => SendKeepAliveMessagesAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}

Connected?.Invoke(this, EventArgs.Empty);
@@ -350,7 +354,9 @@ namespace MQTTnet.Core.Client
var mqttPacket = await _adapter.ReceivePacketAsync(TimeSpan.Zero);
MqttTrace.Information(nameof(MqttClient), $"Received <<< {mqttPacket}");

Task.Run(() => ProcessReceivedPacket(mqttPacket), cancellationToken).Forget();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Run(() => ProcessReceivedPacket(mqttPacket), cancellationToken);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
}
catch (MqttCommunicationException exception)


+ 4
- 21
MQTTnet.Core/Client/MqttClientOptions.cs View File

@@ -2,11 +2,13 @@

namespace MQTTnet.Core.Client
{
public class MqttClientOptions
public sealed class MqttClientOptions
{
public string Server { get; set; }

public int Port { get; set; } = 1883;
public int? Port { get; set; }
public MqttClientSslOptions SslOptions { get; } = new MqttClientSslOptions();

public string UserName { get; set; }

@@ -19,24 +21,5 @@ namespace MQTTnet.Core.Client
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(5);

public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);

/// <summary>
/// Use SSL to communicate with the MQTT server.
/// </summary>
/// <remarks>Setting this value to <c>true</c> will also set <see cref="Port"/> to <c>8883</c> if its value was <c>1883</c> (not set).</remarks>
public bool UseSSL
{
get => _useSSL;
set
{
// Automatically set the port to the MQTT SSL port (8883) if it wasn't set already
if (value && Port == 1883)
Port = 8883;

_useSSL = value;
}
}

private bool _useSSL;
}
}

+ 19
- 0
MQTTnet.Core/Client/MqttClientOptionsExtensions.cs View File

@@ -0,0 +1,19 @@
using System;

namespace MQTTnet.Core.Client
{
public static class MqttClientOptionsExtensions
{
public static int GetPort(this MqttClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));

if (options.Port.HasValue)
{
return options.Port.Value;
}

return !options.SslOptions.UseSsl ? 1883 : 8883;
}
}
}

+ 13
- 0
MQTTnet.Core/Client/MqttClientSslOptions.cs View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace MQTTnet.Core.Client
{
public sealed class MqttClientSslOptions
{
public bool UseSsl { get; set; }

public bool CheckCertificateRevocation { get; set; }

public List<byte[]> Certificates { get; set; }
}
}

+ 1
- 1
MQTTnet.Core/Diagnostics/MqttTraceMessagePublishedEventArgs.cs View File

@@ -2,7 +2,7 @@

namespace MQTTnet.Core.Diagnostics
{
public class MqttTraceMessagePublishedEventArgs : EventArgs
public sealed class MqttTraceMessagePublishedEventArgs : EventArgs
{
public MqttTraceMessagePublishedEventArgs(int threadId, string source, MqttTraceLevel level, string message, Exception exception)
{


+ 1
- 1
MQTTnet.Core/Exceptions/MqttCommunicationTimedOutException.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Exceptions
{
public class MqttCommunicationTimedOutException : MqttCommunicationException
public sealed class MqttCommunicationTimedOutException : MqttCommunicationException
{
}
}

+ 1
- 1
MQTTnet.Core/Exceptions/MqttProtocolViolationException.cs View File

@@ -2,7 +2,7 @@

namespace MQTTnet.Core.Exceptions
{
public class MqttProtocolViolationException : Exception
public sealed class MqttProtocolViolationException : Exception
{
public MqttProtocolViolationException(string message)
: base(message)


+ 1
- 1
MQTTnet.Core/Internal/AsyncAutoResetEvent.cs View File

@@ -3,7 +3,7 @@ using System.Threading.Tasks;

namespace MQTTnet.Core.Internal
{
public class AsyncGate
public sealed class AsyncGate
{
private readonly Queue<TaskCompletionSource<bool>> _waitingTasks = new Queue<TaskCompletionSource<bool>>();



+ 0
- 11
MQTTnet.Core/Internal/TaskExtensions.cs View File

@@ -1,11 +0,0 @@
using System.Threading.Tasks;

namespace MQTTnet.Core.Internal
{
internal static class TaskExtensions
{
public static void Forget(this Task task)
{
}
}
}

+ 1
- 1
MQTTnet.Core/MqttApplicationMessage.cs View File

@@ -3,7 +3,7 @@ using MQTTnet.Core.Protocol;

namespace MQTTnet.Core
{
public class MqttApplicationMessage
public sealed class MqttApplicationMessage
{
public MqttApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
{


+ 1
- 1
MQTTnet.Core/MqttApplicationMessageReceivedEventArgs.cs View File

@@ -2,7 +2,7 @@

namespace MQTTnet.Core
{
public class MqttApplicationMessageReceivedEventArgs : EventArgs
public sealed class MqttApplicationMessageReceivedEventArgs : EventArgs
{
public MqttApplicationMessageReceivedEventArgs(MqttApplicationMessage applicationMessage)
{


+ 1
- 1
MQTTnet.Core/Packets/MqttConnAckPacket.cs View File

@@ -2,7 +2,7 @@

namespace MQTTnet.Core.Packets
{
public class MqttConnAckPacket : MqttBasePacket
public sealed class MqttConnAckPacket : MqttBasePacket
{
public bool IsSessionPresent { get; set; }



+ 1
- 1
MQTTnet.Core/Packets/MqttConnectPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttConnectPacket: MqttBasePacket
public sealed class MqttConnectPacket: MqttBasePacket
{
public string ClientId { get; set; }



+ 1
- 1
MQTTnet.Core/Packets/MqttDisconnectPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttDisconnectPacket : MqttBasePacket
public sealed class MqttDisconnectPacket : MqttBasePacket
{
}
}

+ 1
- 1
MQTTnet.Core/Packets/MqttPingReqPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttPingReqPacket : MqttBasePacket
public sealed class MqttPingReqPacket : MqttBasePacket
{
public override string ToString()
{


+ 1
- 1
MQTTnet.Core/Packets/MqttPingRespPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttPingRespPacket : MqttBasePacket
public sealed class MqttPingRespPacket : MqttBasePacket
{
public override string ToString()
{


+ 1
- 1
MQTTnet.Core/Packets/MqttPubAckPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttPubAckPacket : MqttBasePublishPacket
public sealed class MqttPubAckPacket : MqttBasePublishPacket
{
}
}

+ 1
- 1
MQTTnet.Core/Packets/MqttPubCompPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttPubCompPacket : MqttBasePublishPacket
public sealed class MqttPubCompPacket : MqttBasePublishPacket
{
}
}

+ 1
- 1
MQTTnet.Core/Packets/MqttPubRecPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttPubRecPacket : MqttBasePublishPacket
public sealed class MqttPubRecPacket : MqttBasePublishPacket
{
}
}

+ 1
- 1
MQTTnet.Core/Packets/MqttPubRelPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttPubRelPacket : MqttBasePublishPacket
public sealed class MqttPubRelPacket : MqttBasePublishPacket
{
}
}

+ 1
- 1
MQTTnet.Core/Packets/MqttPublishPacket.cs View File

@@ -3,7 +3,7 @@ using MQTTnet.Core.Protocol;

namespace MQTTnet.Core.Packets
{
public class MqttPublishPacket : MqttBasePublishPacket
public sealed class MqttPublishPacket : MqttBasePublishPacket
{
public bool Retain { get; set; }



+ 1
- 1
MQTTnet.Core/Packets/MqttSubAckPacket.cs View File

@@ -4,7 +4,7 @@ using MQTTnet.Core.Protocol;

namespace MQTTnet.Core.Packets
{
public class MqttSubAckPacket : MqttBasePacket, IPacketWithIdentifier
public sealed class MqttSubAckPacket : MqttBasePacket, IPacketWithIdentifier
{
public ushort PacketIdentifier { get; set; }



+ 1
- 1
MQTTnet.Core/Packets/MqttSubscribePacket.cs View File

@@ -3,7 +3,7 @@ using System.Linq;

namespace MQTTnet.Core.Packets
{
public class MqttSubscribePacket : MqttBasePacket, IPacketWithIdentifier
public sealed class MqttSubscribePacket : MqttBasePacket, IPacketWithIdentifier
{
public ushort PacketIdentifier { get; set; }


+ 1
- 1
MQTTnet.Core/Packets/MqttUnsubAckPacket.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets
{
public class MqttUnsubAckPacket : MqttBasePacket, IPacketWithIdentifier
public sealed class MqttUnsubAckPacket : MqttBasePacket, IPacketWithIdentifier
{
public ushort PacketIdentifier { get; set; }
}


+ 1
- 1
MQTTnet.Core/Packets/MqttUnsubscribe.cs View File

@@ -2,7 +2,7 @@

namespace MQTTnet.Core.Packets
{
public class MqttUnsubscribePacket : MqttBasePacket, IPacketWithIdentifier
public sealed class MqttUnsubscribePacket : MqttBasePacket, IPacketWithIdentifier
{
public ushort PacketIdentifier { get; set; }


+ 1
- 1
MQTTnet.Core/Packets/TopicFilter.cs View File

@@ -2,7 +2,7 @@

namespace MQTTnet.Core.Packets
{
public class TopicFilter
public sealed class TopicFilter
{
public TopicFilter(string topic, MqttQualityOfServiceLevel qualityOfServiceLevel)
{


+ 1
- 1
MQTTnet.Core/Serializer/ByteReader.cs View File

@@ -2,7 +2,7 @@

namespace MQTTnet.Core.Serializer
{
public class ByteReader
public sealed class ByteReader
{
private readonly int _source;
private int _index;


+ 1
- 1
MQTTnet.Core/Serializer/ByteWriter.cs View File

@@ -2,7 +2,7 @@

namespace MQTTnet.Core.Serializer
{
public class ByteWriter
public sealed class ByteWriter
{
private int _index;
private int _byte;


+ 1
- 1
MQTTnet.Core/Serializer/DefaultMqttV311PacketSerializer.cs View File

@@ -9,7 +9,7 @@ using MQTTnet.Core.Protocol;

namespace MQTTnet.Core.Serializer
{
public class DefaultMqttV311PacketSerializer : IMqttPacketSerializer
public sealed class DefaultMqttV311PacketSerializer : IMqttPacketSerializer
{
public Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination)
{


+ 9
- 0
MQTTnet.Core/Server/DefaultEndpointOptions.cs View File

@@ -0,0 +1,9 @@
namespace MQTTnet.Core.Server
{
public sealed class DefaultEndpointOptions
{
public bool IsEnabled { get; set; } = true;

public int? Port { get; set; }
}
}

+ 1
- 1
MQTTnet.Core/Server/GetOrCreateClientSessionResult.cs View File

@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Server
{
public class GetOrCreateClientSessionResult
public sealed class GetOrCreateClientSessionResult
{
public bool IsExistingSession { get; set; }



+ 1
- 1
MQTTnet.Core/Server/MqttClientMessageQueue.cs View File

@@ -11,7 +11,7 @@ using MQTTnet.Core.Packets;

namespace MQTTnet.Core.Server
{
public class MqttClientMessageQueue
public sealed class MqttClientMessageQueue
{
private readonly List<MqttClientPublishPacketContext> _pendingPublishPackets = new List<MqttClientPublishPacketContext>();
private readonly AsyncGate _gate = new AsyncGate();


+ 1
- 1
MQTTnet.Core/Server/MqttClientPublishPacketContext.cs View File

@@ -3,7 +3,7 @@ using MQTTnet.Core.Packets;

namespace MQTTnet.Core.Server
{
public class MqttClientPublishPacketContext
public sealed class MqttClientPublishPacketContext
{
public MqttClientPublishPacketContext(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
{


+ 1
- 1
MQTTnet.Core/Server/MqttClientSessionsManager.cs View File

@@ -10,7 +10,7 @@ using MQTTnet.Core.Protocol;

namespace MQTTnet.Core.Server
{
public class MqttClientSessionsManager
public sealed class MqttClientSessionsManager
{
private readonly object _syncRoot = new object();
private readonly Dictionary<string, MqttClientSession> _clientSessions = new Dictionary<string, MqttClientSession>();


+ 1
- 1
MQTTnet.Core/Server/MqttClientSubscriptionsManager.cs View File

@@ -5,7 +5,7 @@ using MQTTnet.Core.Protocol;

namespace MQTTnet.Core.Server
{
public class MqttClientSubscriptionsManager
public sealed class MqttClientSubscriptionsManager
{
private readonly ConcurrentDictionary<string, MqttQualityOfServiceLevel> _subscribedTopics = new ConcurrentDictionary<string, MqttQualityOfServiceLevel>();



+ 15
- 9
MQTTnet.Core/Server/MqttServer.cs View File

@@ -7,18 +7,18 @@ using MQTTnet.Core.Diagnostics;

namespace MQTTnet.Core.Server
{
public class MqttServer
public sealed class MqttServer
{
private readonly MqttClientSessionsManager _clientSessionsManager;
private readonly IMqttServerAdapter _adapter;
private readonly ICollection<IMqttServerAdapter> _adapters;
private readonly MqttServerOptions _options;

private CancellationTokenSource _cancellationTokenSource;

public MqttServer(MqttServerOptions options, IMqttServerAdapter adapter)
public MqttServer(MqttServerOptions options, ICollection<IMqttServerAdapter> adapters)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
_adapters = adapters ?? throw new ArgumentNullException(nameof(adapters));
_clientSessionsManager = new MqttClientSessionsManager(options);
}
@@ -45,9 +45,12 @@ namespace MQTTnet.Core.Server

_cancellationTokenSource = new CancellationTokenSource();

_adapter.ClientConnected += OnClientConnected;
_adapter.Start(_options);

foreach (var adapter in _adapters)
{
adapter.ClientConnected += OnClientConnected;
adapter.Start(_options);
}
MqttTrace.Information(nameof(MqttServer), "Started.");
}

@@ -56,8 +59,11 @@ namespace MQTTnet.Core.Server
_cancellationTokenSource?.Cancel();
_cancellationTokenSource = null;

_adapter.ClientConnected -= OnClientConnected;
_adapter.Stop();
foreach (var adapter in _adapters)
{
adapter.ClientConnected -= OnClientConnected;
adapter.Stop();
}

_clientSessionsManager.Clear();



+ 4
- 9
MQTTnet.Core/Server/MqttServerOptions.cs View File

@@ -4,21 +4,16 @@ using MQTTnet.Core.Protocol;

namespace MQTTnet.Core.Server
{
public class MqttServerOptions
public sealed class MqttServerOptions
{
public int Port { get; set; } = 1883;
public DefaultEndpointOptions DefaultEndpointOptions { get; } = new DefaultEndpointOptions();

public SslEndpointOptions SslEndpointOptions { get; } = new SslEndpointOptions();
public int ConnectionBacklog { get; set; } = 10;

public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);

public Func<MqttConnectPacket, MqttConnectReturnCode> ConnectionValidator { get; set; }

public bool UseSSL = false;

/// <summary>
/// The path to the X509 SSL certificate.
/// </summary>
public string CertificatePath = string.Empty;
}
}

+ 31
- 0
MQTTnet.Core/Server/MqttServerOptionsExtensions.cs View File

@@ -0,0 +1,31 @@
using System;

namespace MQTTnet.Core.Server
{
public static class MqttServerOptionsExtensions
{
public static int GetSslEndpointPort(this MqttServerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));

if (!options.SslEndpointOptions.Port.HasValue)
{
return 8883;
}

return options.SslEndpointOptions.Port.Value;
}

public static int GetDefaultEndpointPort(this MqttServerOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));

if (!options.DefaultEndpointOptions.Port.HasValue)
{
return 1883;
}

return options.DefaultEndpointOptions.Port.Value;
}
}
}

+ 11
- 0
MQTTnet.Core/Server/SslEndpointOptions.cs View File

@@ -0,0 +1,11 @@
namespace MQTTnet.Core.Server
{
public sealed class SslEndpointOptions
{
public bool IsEnabled { get; set; }

public int? Port { get; set; }

public byte[] Certificate { get; set; }
}
}

+ 19
- 0
MQTTnet.Core/Server/SslEndpointOptionsExtensions.cs View File

@@ -0,0 +1,19 @@
using System;

namespace MQTTnet.Core.Server
{
public static class SslEndpointOptionsExtensions
{
public static int GetPort(this DefaultEndpointOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));

if (!options.Port.HasValue)
{
return 1883;
}

return options.Port.Value;
}
}
}

+ 3
- 1
MQTTnet.nuspec View File

@@ -11,7 +11,9 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description>
<releaseNotes>* [Core] Any exception while accessing the underlying data source is now rethrown as "MqttCommunicationException".
* [Core] Extended exception information when an invalid packet type is received.</releaseNotes>
* [Core] Extended exception information when an invalid packet type is received.
* [Server] Added SSL (TLS1.2) support (thanks to Zazzmatazz)
* [Client] Added SSL (TLS1.2) support (thanks to Zazzmatazz)</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2017</copyright>
<tags>MQTT MQTTClient MQTTServer MQTTBroker Broker</tags>
</metadata>


+ 63
- 55
MQTTnet.sln View File

@@ -1,10 +1,8 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.9
VisualStudioVersion = 15.0.26430.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestMqttClient", "Tests\MQTTnet.TestMqttClient\MQTTnet.TestMqttClient.csproj", "{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Core.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.NetFramework", "Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj", "{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}"
@@ -15,8 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frameworks", "Frameworks", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestMqttServer", "Tests\MQTTnet.TestMqttServer\MQTTnet.TestMqttServer.csproj", "{6F8C0C0C-59EC-4921-9267-370AE113C34F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core", "MQTTnet.Core\MQTTnet.Core.csproj", "{2ECB99E4-72D0-4C23-99BA-93D511D3967D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{002203AF-2565-4C0D-95ED-027FDEFE0C35}"
@@ -26,6 +22,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.NetCoreApp", "Frameworks\MQTTnet.NetCoreApp\MQTTnet.NetCoreApp.csproj", "{1A1B7F51-5328-4395-9D9C-07D70965825E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestApp.NetFramework", "Tests\MQTTnet.TestApp.NetFramework\MQTTnet.TestApp.NetFramework.csproj", "{D9D74F33-6943-49B2-B765-7BD589082098}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestApp.UniversalWindows", "Tests\MQTTnet.TestApp.UniversalWindows\MQTTnet.TestApp.UniversalWindows.csproj", "{FF1F72D6-9524-4422-9497-3CC0002216ED}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Any CPU|Any CPU = Any CPU|Any CPU
@@ -42,30 +42,6 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x64.ActiveCfg = Any CPU|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x64.Build.0 = Any CPU|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x86.ActiveCfg = Any CPU|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Any CPU|x86.Build.0 = Any CPU|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|ARM.Build.0 = Debug|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x64.ActiveCfg = Debug|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x64.Build.0 = Debug|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x86.ActiveCfg = Debug|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Debug|x86.Build.0 = Debug|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|Any CPU.Build.0 = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|ARM.ActiveCfg = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|ARM.Build.0 = Release|Any CPU
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x64.ActiveCfg = Release|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x64.Build.0 = Release|x64
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x86.ActiveCfg = Release|x86
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}.Release|x86.Build.0 = Release|x86
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
@@ -138,30 +114,6 @@ Global
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x64.Build.0 = Release|x64
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.ActiveCfg = Release|x86
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.Build.0 = Release|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|ARM.Build.0 = Any CPU|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x64.ActiveCfg = Any CPU|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x64.Build.0 = Any CPU|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x86.ActiveCfg = Any CPU|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Any CPU|x86.Build.0 = Any CPU|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|ARM.ActiveCfg = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|ARM.Build.0 = Debug|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x64.ActiveCfg = Debug|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x64.Build.0 = Debug|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x86.ActiveCfg = Debug|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Debug|x86.Build.0 = Debug|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|Any CPU.Build.0 = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|ARM.ActiveCfg = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|ARM.Build.0 = Release|Any CPU
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x64.ActiveCfg = Release|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x64.Build.0 = Release|x64
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x86.ActiveCfg = Release|x86
{6F8C0C0C-59EC-4921-9267-370AE113C34F}.Release|x86.Build.0 = Release|x86
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|Any CPU.ActiveCfg = Any CPU|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|Any CPU.Build.0 = Any CPU|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|ARM.ActiveCfg = Any CPU|Any CPU
@@ -210,16 +162,72 @@ Global
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x64.Build.0 = Release|x64
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.ActiveCfg = Release|x86
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.Build.0 = Release|x86
{D9D74F33-6943-49B2-B765-7BD589082098}.Any CPU|Any CPU.ActiveCfg = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Any CPU|Any CPU.Build.0 = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Any CPU|ARM.ActiveCfg = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Any CPU|ARM.Build.0 = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Any CPU|x64.ActiveCfg = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Any CPU|x64.Build.0 = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Any CPU|x86.ActiveCfg = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Any CPU|x86.Build.0 = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Debug|ARM.ActiveCfg = Debug|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Debug|ARM.Build.0 = Debug|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Debug|x64.ActiveCfg = Debug|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Debug|x64.Build.0 = Debug|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Debug|x86.ActiveCfg = Debug|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Debug|x86.Build.0 = Debug|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Release|Any CPU.Build.0 = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Release|ARM.ActiveCfg = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Release|ARM.Build.0 = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Release|x64.ActiveCfg = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Release|x64.Build.0 = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Release|x86.ActiveCfg = Release|Any CPU
{D9D74F33-6943-49B2-B765-7BD589082098}.Release|x86.Build.0 = Release|Any CPU
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|Any CPU.ActiveCfg = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|Any CPU.Build.0 = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|Any CPU.Deploy.0 = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|ARM.ActiveCfg = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|ARM.Build.0 = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|ARM.Deploy.0 = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|x64.ActiveCfg = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|x64.Build.0 = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|x64.Deploy.0 = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|x86.ActiveCfg = Release|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|x86.Build.0 = Release|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Any CPU|x86.Deploy.0 = Release|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|Any CPU.ActiveCfg = Debug|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.ActiveCfg = Debug|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.Build.0 = Debug|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|ARM.Deploy.0 = Debug|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.ActiveCfg = Debug|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.Build.0 = Debug|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x64.Deploy.0 = Debug|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.ActiveCfg = Debug|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.Build.0 = Debug|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Debug|x86.Deploy.0 = Debug|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|Any CPU.ActiveCfg = Release|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.ActiveCfg = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.Build.0 = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|ARM.Deploy.0 = Release|ARM
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.ActiveCfg = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.Build.0 = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x64.Deploy.0 = Release|x64
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.ActiveCfg = Release|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.Build.0 = Release|x86
{FF1F72D6-9524-4422-9497-3CC0002216ED}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{BD60C727-D8E8-40C3-B8E3-C95A864AE611} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{6F8C0C0C-59EC-4921-9267-370AE113C34F} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{1A1B7F51-5328-4395-9D9C-07D70965825E} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{D9D74F33-6943-49B2-B765-7BD589082098} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{FF1F72D6-9524-4422-9497-3CC0002216ED} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
EndGlobalSection
EndGlobal

+ 12
- 2
README.md View File

@@ -7,8 +7,19 @@
# MQTTnet
MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server. The implementation is based on the documentation from http://mqtt.org/.

## Supported frameworks
## Features
* MQTT client included
* MQTT server (broker) included
* SSL (TLS 1.2) support for Client and Server
* Async support
* List of connected clients available (server only)
* Extensible communication channels (i.e. In-Memory, TCP, TCP+SSL, WebSockets (not included in this project))
* Access to internal trace messages
* Extensible client credential validation (server only)
* Unit tested (48+ tests)
* Lightweight (only the low level implementation of MQTT)

## Supported frameworks
* .NET Standard 1.1+
* .NET Core 1.1+
* .NET Core App 1.1+
@@ -16,7 +27,6 @@ MQTTnet is a .NET library for MQTT based communication. It provides a MQTT clien
* Universal Windows (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU)

## Supported MQTT versions

* 3.1.1

## Nuget


+ 6
- 4
Tests/MQTTnet.Core.Tests/MqttServerTests.cs View File

@@ -1,5 +1,7 @@
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Client;
using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
@@ -46,11 +48,11 @@ namespace MQTTnet.Core.Tests
[TestMethod]
public async Task MqttServer_WillMessage()
{
var s = new MqttServer(new MqttServerOptions(), new TestMqttServerAdapter());
var s = new MqttServer(new MqttServerOptions(), new List<IMqttServerAdapter> { new TestMqttServerAdapter() });
s.Start();

var willMessage = new MqttApplicationMessage("My/last/will", new byte[0], MqttQualityOfServiceLevel.AtMostOnce, false);
var c1 = ConnectTestClient("c1", null, s);
var c1 = ConnectTestClient("c1", null, s);
var c2 = ConnectTestClient("c2", willMessage, s);

var receivedMessagesCount = 0;
@@ -86,7 +88,7 @@ namespace MQTTnet.Core.Tests
MqttQualityOfServiceLevel filterQualityOfServiceLevel,
int expectedReceivedMessagesCount)
{
var s = new MqttServer(new MqttServerOptions(), new TestMqttServerAdapter());
var s = new MqttServer(new MqttServerOptions(), new List<IMqttServerAdapter> { new TestMqttServerAdapter() });
s.Start();

var c1 = ConnectTestClient("c1", null, s);


Tests/MQTTnet.TestMqttServer/App.config → Tests/MQTTnet.TestApp.NetFramework/App.config View File


Tests/MQTTnet.TestMqttServer/MQTTnet.TestMqttServer.csproj → Tests/MQTTnet.TestApp.NetFramework/MQTTnet.TestApp.NetFramework.csproj View File

@@ -4,10 +4,10 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6F8C0C0C-59EC-4921-9267-370AE113C34F}</ProjectGuid>
<ProjectGuid>{D9D74F33-6943-49B2-B765-7BD589082098}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>MQTTnet.TestMqttServer</RootNamespace>
<AssemblyName>MQTTnet.TestMqttServer</AssemblyName>
<RootNamespace>MQTTnet.TestApp.NetFramework</RootNamespace>
<AssemblyName>MQTTnet.TestApp.NetFramework</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
@@ -31,43 +31,15 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
<OutputPath>bin\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Any CPU\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Any CPU\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />

Tests/MQTTnet.TestMqttClient/Program.cs → Tests/MQTTnet.TestApp.NetFramework/Program.cs View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Core;
using MQTTnet.Core.Client;
@@ -9,16 +10,29 @@ using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol;
using MQTTnet.Core.Server;

namespace MQTTnet.TestMqttClient
namespace MQTTnet.TestApp.NetFramework
{
public static class Program
{
public static void Main(string[] arguments)
public static void Main(string[] args)
{
Task.Run(() => Run(arguments)).Wait();
Console.WriteLine("MQTTnet - TestApp.NetFramework");
Console.WriteLine("1 = Start client");
Console.WriteLine("2 = Start server");
var pressedKey = Console.ReadKey(true);
if (pressedKey.Key == ConsoleKey.D1)
{
Task.Run(() => RunClientAsync(args));
Thread.Sleep(Timeout.Infinite);
}
else if (pressedKey.Key == ConsoleKey.D2)
{
Task.Run(() => RunServerAsync(args));
Thread.Sleep(Timeout.Infinite);
}
}

private static async Task Run(string[] arguments)
private static async Task RunClientAsync(string[] arguments)
{
MqttTrace.TraceMessagePublished += (s, e) =>
{
@@ -28,7 +42,7 @@ namespace MQTTnet.TestMqttClient
Console.WriteLine(e.Exception);
}
};
try
{
var options = new MqttClientOptions
@@ -61,7 +75,7 @@ namespace MQTTnet.TestMqttClient
Console.WriteLine("### SUBSCRIBED ###");
};

client.Disconnected += async (s, e) =>
client.Disconnected += async (s, e) =>
{
Console.WriteLine("### DISCONNECTED FROM SERVER ###");
await Task.Delay(TimeSpan.FromSeconds(5));
@@ -80,9 +94,9 @@ namespace MQTTnet.TestMqttClient
{
await client.ConnectAsync();
}
catch
catch (Exception exception)
{
Console.WriteLine("### CONNECTING FAILED ###");
Console.WriteLine("### CONNECTING FAILED ###" + Environment.NewLine + exception);
}

Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###");
@@ -106,5 +120,50 @@ namespace MQTTnet.TestMqttClient
Console.WriteLine(exception);
}
}

private static async Task RunServerAsync(string[] arguments)
{
MqttTrace.TraceMessagePublished += (s, e) =>
{
Console.WriteLine($">> [{e.ThreadId}] [{e.Source}] [{e.Level}]: {e.Message}");
if (e.Exception != null)
{
Console.WriteLine(e.Exception);
}
};

try
{
var options = new MqttServerOptions
{
ConnectionValidator = p =>
{
if (p.ClientId == "SpecialClient")
{
if (p.Username != "USER" || p.Password != "PASS")
{
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
}
}

return MqttConnectReturnCode.ConnectionAccepted;
}
};

var mqttServer = new MqttServerFactory().CreateMqttServer(options);
mqttServer.Start();

Console.WriteLine("Press any key to exit.");
Console.ReadLine();

mqttServer.Stop();
}
catch (Exception e)
{
Console.WriteLine(e);
}

Console.ReadLine();
}
}
}

Tests/MQTTnet.TestMqttClient/Properties/AssemblyInfo.cs → Tests/MQTTnet.TestApp.NetFramework/Properties/AssemblyInfo.cs View File

@@ -1,7 +1,7 @@
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("MQTTnet.TestMqttClient")]
[assembly: AssemblyTitle("MQTTnet.TestApp.NetFramework")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Christian Kratky")]

+ 8
- 0
Tests/MQTTnet.TestApp.UniversalWindows/App.xaml View File

@@ -0,0 +1,8 @@
<Application
x:Class="MQTTnet.TestApp.UniversalWindows.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MQTTnet.TestApp.UniversalWindows"
RequestedTheme="Light">

</Application>

+ 100
- 0
Tests/MQTTnet.TestApp.UniversalWindows/App.xaml.cs View File

@@ -0,0 +1,100 @@
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
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <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()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}

/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
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)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();

rootFrame.NavigationFailed += OnNavigationFailed;

if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}

// Place the frame in the current Window
Window.Current.Content = rootFrame;
}

if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
}

/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}

/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}

BIN
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


+ 149
- 0
Tests/MQTTnet.TestApp.UniversalWindows/MQTTnet.TestApp.UniversalWindows.csproj View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{ff1f72d6-9524-4422-9497-3cc0002216ed}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MQTTnet.TestApp.UniversalWindows</RootNamespace>
<AssemblyName>MQTTnet.TestApp.UniversalWindows</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.14393.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
<PackageCertificateKeyFile>MQTTnet.TestApp.UniversalWindows_TemporaryKey.pfx</PackageCertificateKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>

<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="project.json" />
</ItemGroup>

<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<None Include="MQTTnet.TestApp.UniversalWindows_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<Content Include="Properties\Default.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>

<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 13
- 0
Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml View File

@@ -0,0 +1,13 @@
<Page
x:Class="MQTTnet.TestApp.UniversalWindows.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MQTTnet.TestApp.UniversalWindows"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

</Grid>
</Page>

+ 30
- 0
Tests/MQTTnet.TestApp.UniversalWindows/MainPage.xaml.cs View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
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;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace MQTTnet.TestApp.UniversalWindows
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
}
}

+ 49
- 0
Tests/MQTTnet.TestApp.UniversalWindows/Package.appxmanifest View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>

<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">

<Identity
Name="4fa21172-9128-4e84-8a6d-74b9acde4d58"
Publisher="CN=chris"
Version="1.0.0.0" />

<mp:PhoneIdentity PhoneProductId="4fa21172-9128-4e84-8a6d-74b9acde4d58" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

<Properties>
<DisplayName>MQTTnet.TestApp.UniversalWindows</DisplayName>
<PublisherDisplayName>chris</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>

<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>

<Resources>
<Resource Language="x-generate"/>
</Resources>

<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="MQTTnet.TestApp.UniversalWindows.App">
<uap:VisualElements
DisplayName="MQTTnet.TestApp.UniversalWindows"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="MQTTnet.TestApp.UniversalWindows"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>

<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>

Tests/MQTTnet.TestMqttServer/Properties/AssemblyInfo.cs → Tests/MQTTnet.TestApp.UniversalWindows/Properties/AssemblyInfo.cs View File

@@ -1,7 +1,7 @@
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("MQTTnet.TestMqttServer")]
[assembly: AssemblyTitle("MQTTnet.TestApp.UniversalWindows")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Christian Kratky")]
@@ -9,7 +9,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © Christian Kratky 2016-2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("59c1090b-1734-4185-bc2f-53b9edd30079")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

+ 31
- 0
Tests/MQTTnet.TestApp.UniversalWindows/Properties/Default.rd.xml View File

@@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.

Runtime Directives are documented at https://go.microsoft.com/fwlink/?LinkID=391919

To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>

To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />

Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Seralize="All" />
-->

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->


</Application>
</Directives>

+ 16
- 0
Tests/MQTTnet.TestApp.UniversalWindows/project.json View File

@@ -0,0 +1,16 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.3"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}

+ 0
- 6
Tests/MQTTnet.TestMqttClient/App.config View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
</configuration>

+ 0
- 100
Tests/MQTTnet.TestMqttClient/MQTTnet.TestMqttClient.csproj View File

@@ -1,100 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7B19B139-2E9D-4F1D-88B4-6180B4CF872A}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MQTTnet.TestMqttClient</RootNamespace>
<AssemblyName>MQTTnet.TestMqttClient</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|AnyCPU'">
<OutputPath>bin\Any CPU\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Any CPU\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Any CPU|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Any CPU\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj">
<Project>{a480ef90-0eaa-4d9a-b271-47a9c47f6f7d}</Project>
<Name>MQTTnet.NetFramework</Name>
</ProjectReference>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
<Project>{2ecb99e4-72d0-4c23-99ba-93d511d3967d}</Project>
<Name>MQTTnet.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 0
- 55
Tests/MQTTnet.TestMqttServer/Program.cs View File

@@ -1,55 +0,0 @@
using System;
using MQTTnet.Core.Diagnostics;
using MQTTnet.Core.Protocol;
using MQTTnet.Core.Server;

namespace MQTTnet.TestMqttServer
{
public static class Program
{
public static void Main(string[] arguments)
{
MqttTrace.TraceMessagePublished += (s, e) =>
{
Console.WriteLine($">> [{e.ThreadId}] [{e.Source}] [{e.Level}]: {e.Message}");
if (e.Exception != null)
{
Console.WriteLine(e.Exception);
}
};

try
{
var options = new MqttServerOptions
{
ConnectionValidator = p =>
{
if (p.ClientId == "SpecialClient")
{
if (p.Username != "USER" || p.Password != "PASS")
{
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
}
}

return MqttConnectReturnCode.ConnectionAccepted;
}
};

var mqttServer = new MqttServerFactory().CreateMqttServer(options);
mqttServer.Start();

Console.WriteLine("Press any key to exit.");
Console.ReadLine();

mqttServer.Stop();
}
catch (Exception e)
{
Console.WriteLine(e);
}

Console.ReadLine();
}
}
}

Loading…
Cancel
Save