Fix breaking changes.

This commit is contained in:
Christian Kratky
2017-06-03 22:48:22 +02:00
parent 1317fa3e2a
commit 929cdb971a
92 changed files with 1363 additions and 1309 deletions
@@ -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.");
}
}
}
}
}
@@ -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;
}
}
}
@@ -1,8 +1,8 @@
using System; using System;
using MQTTnet.Core.Adapter; using MQTTnet.Core.Adapter;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Serializer; using MQTTnet.Core.Serializer;
using MQTTnet.Implementations;
namespace MQTTnet namespace MQTTnet
{ {
@@ -12,9 +12,7 @@ namespace MQTTnet
{ {
if (options == null) throw new ArgumentNullException(nameof(options)); if (options == null) throw new ArgumentNullException(nameof(options));
return new MqttClient(options, return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
new MqttChannelCommunicationAdapter(options.UseSSL ? new MqttClientSslChannel() : (IMqttCommunicationChannel) new MqttTcpChannel(),
new DefaultMqttV311PacketSerializer()));
} }
} }
} }
@@ -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();
}
}
}
@@ -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));
}
}
}
}
@@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic;
using MQTTnet.Core.Adapter; using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using MQTTnet.Implementations;
namespace MQTTnet namespace MQTTnet
{ {
@@ -9,8 +11,8 @@ namespace MQTTnet
public MqttServer CreateMqttServer(MqttServerOptions options) public MqttServer CreateMqttServer(MqttServerOptions options)
{ {
if (options == null) throw new ArgumentNullException(nameof(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() });
} }
} }
} }
@@ -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();
}
}
}
@@ -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));
}
}
}
}
@@ -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();
}
}
}
@@ -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.");
}
}
}
}
}
@@ -1,31 +1,43 @@
using System; using System;
using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks; using System.Threading.Tasks;
using MQTTnet.Core.Channel; using MQTTnet.Core.Channel;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Exceptions; using MQTTnet.Core.Exceptions;
namespace MQTTnet namespace MQTTnet.Implementations
{ {
public class MqttTcpChannel : IMqttCommunicationChannel, IDisposable public class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
{ {
private readonly Socket _socket; private readonly Socket _socket;
private SslStream _sslStream;
public MqttTcpChannel() public MqttTcpChannel()
{ {
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp); _socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
} }
public MqttTcpChannel(Socket socket) public MqttTcpChannel(Socket socket, SslStream sslStream)
{ {
_socket = socket ?? throw new ArgumentNullException(nameof(socket)); _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 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) catch (SocketException exception)
{ {
@@ -37,7 +49,9 @@ namespace MQTTnet
{ {
try try
{ {
return Task.Factory.FromAsync(_socket.BeginDisconnect, _socket.EndDisconnect, true, null); _sslStream.Dispose();
_socket.Dispose();
return Task.FromResult(0);
} }
catch (SocketException exception) catch (SocketException exception)
{ {
@@ -51,10 +65,16 @@ namespace MQTTnet
try try
{ {
if (_sslStream != null)
{
return _sslStream.WriteAsync(buffer, 0, buffer.Length);
}
return Task.Factory.FromAsync( return Task.Factory.FromAsync(
// ReSharper disable once AssignNullToNotNullAttribute // ReSharper disable once AssignNullToNotNullAttribute
_socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null), _socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null),
_socket.EndSend); _socket.EndSend);
} }
catch (SocketException exception) catch (SocketException exception)
{ {
@@ -64,8 +84,15 @@ namespace MQTTnet
public Task ReadAsync(byte[] buffer) public Task ReadAsync(byte[] buffer)
{ {
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
try try
{ {
if (_sslStream != null)
{
return _sslStream.ReadAsync(buffer, 0, buffer.Length);
}
return Task.Factory.FromAsync( return Task.Factory.FromAsync(
// ReSharper disable once AssignNullToNotNullAttribute // ReSharper disable once AssignNullToNotNullAttribute
_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, null, null), _socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, null, null),
@@ -80,6 +107,23 @@ namespace MQTTnet
public void Dispose() public void Dispose()
{ {
_socket?.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;
} }
} }
} }
@@ -101,13 +101,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="MqttClientFactory.cs" /> <Compile Include="MqttClientFactory.cs" />
<Compile Include="MqttServerAdapter.cs" />
<Compile Include="MqttServerFactory.cs" /> <Compile Include="MqttServerFactory.cs" />
<Compile Include="MqttClientSslChannel.cs" /> <Compile Include="Implementations\MqttServerAdapter.cs" />
<Compile Include="MqttServerSslChannel.cs" />
<Compile Include="MqttSslServerAdapter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MqttTcpChannel.cs" /> <Compile Include="Implementations\MqttTcpChannel.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj"> <ProjectReference Include="..\..\MQTTnet.Core\MQTTnet.Core.csproj">
@@ -1,8 +1,8 @@
using System; using System;
using MQTTnet.Core.Adapter; using MQTTnet.Core.Adapter;
using MQTTnet.Core.Channel;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Serializer; using MQTTnet.Core.Serializer;
using MQTTnet.Implementations;
namespace MQTTnet namespace MQTTnet
{ {
@@ -11,10 +11,8 @@ namespace MQTTnet
public MqttClient CreateMqttClient(MqttClientOptions options) public MqttClient CreateMqttClient(MqttClientOptions options)
{ {
if (options == null) throw new ArgumentNullException(nameof(options)); if (options == null) throw new ArgumentNullException(nameof(options));
return new MqttClient(options, return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
new MqttChannelCommunicationAdapter(options.UseSSL ? new MqttClientSslChannel() : (IMqttCommunicationChannel)new MqttTcpChannel(),
new DefaultMqttV311PacketSerializer()));
} }
} }
} }
@@ -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();
}
}
}
@@ -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));
}
}
}
}
@@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic;
using MQTTnet.Core.Adapter; using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using MQTTnet.Implementations;
namespace MQTTnet namespace MQTTnet
{ {
@@ -9,8 +11,8 @@ namespace MQTTnet
public MqttServer CreateMqttServer(MqttServerOptions options) public MqttServer CreateMqttServer(MqttServerOptions options)
{ {
if (options == null) throw new ArgumentNullException(nameof(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() });
} }
} }
} }
@@ -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();
}
}
}
@@ -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));
}
}
}
}
@@ -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.");
}
}
}
}
@@ -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());
}
}
}
@@ -112,9 +112,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="MqttClientFactory.cs" /> <Compile Include="MqttClientFactory.cs" />
<Compile Include="MqttServerAdapter.cs" /> <Compile Include="Implementations\MqttServerAdapter.cs" />
<Compile Include="MqttServerFactory.cs" /> <Compile Include="MqttServerFactory.cs" />
<Compile Include="MqttTcpChannel.cs" /> <Compile Include="Implementations\MqttTcpChannel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Properties\MQTTnet.Universal.rd.xml" /> <EmbeddedResource Include="Properties\MQTTnet.Universal.rd.xml" />
</ItemGroup> </ItemGroup>
@@ -2,6 +2,7 @@
using MQTTnet.Core.Adapter; using MQTTnet.Core.Adapter;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Serializer; using MQTTnet.Core.Serializer;
using MQTTnet.Implementations;
namespace MQTTnet namespace MQTTnet
{ {
@@ -14,4 +15,4 @@ namespace MQTTnet
return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer())); return new MqttClient(options, new MqttChannelCommunicationAdapter(new MqttTcpChannel(), new DefaultMqttV311PacketSerializer()));
} }
} }
} }
@@ -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();
}
}
}
@@ -1,5 +1,8 @@
using System; using System;
using System.Collections.Generic;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
using MQTTnet.Implementations;
namespace MQTTnet namespace MQTTnet
{ {
@@ -9,7 +12,7 @@ namespace MQTTnet
{ {
if (options == null) throw new ArgumentNullException(nameof(options)); if (options == null) throw new ArgumentNullException(nameof(options));
return new MqttServer(options, new MqttServerAdapter()); return new MqttServer(options, new List<IMqttServerAdapter> { new MqttServerAdapter() });
} }
} }
} }
@@ -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
View File
@@ -67,7 +67,9 @@ namespace MQTTnet.Core.Client
_packetDispatcher.Reset(); _packetDispatcher.Reset();
IsConnected = true; 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); var response = await SendAndReceiveAsync<MqttConnAckPacket>(connectPacket);
if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted) if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted)
@@ -77,7 +79,9 @@ namespace MQTTnet.Core.Client
if (_options.KeepAlivePeriod != TimeSpan.Zero) 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); Connected?.Invoke(this, EventArgs.Empty);
@@ -350,7 +354,9 @@ namespace MQTTnet.Core.Client
var mqttPacket = await _adapter.ReceivePacketAsync(TimeSpan.Zero); var mqttPacket = await _adapter.ReceivePacketAsync(TimeSpan.Zero);
MqttTrace.Information(nameof(MqttClient), $"Received <<< {mqttPacket}"); 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) catch (MqttCommunicationException exception)
+4 -21
View File
@@ -2,11 +2,13 @@
namespace MQTTnet.Core.Client namespace MQTTnet.Core.Client
{ {
public class MqttClientOptions public sealed class MqttClientOptions
{ {
public string Server { get; set; } 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; } public string UserName { get; set; }
@@ -19,24 +21,5 @@ namespace MQTTnet.Core.Client
public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(5); public TimeSpan KeepAlivePeriod { get; set; } = TimeSpan.FromSeconds(5);
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan 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;
} }
} }
@@ -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;
}
}
}
@@ -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; }
}
}
@@ -2,7 +2,7 @@
namespace MQTTnet.Core.Diagnostics 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) public MqttTraceMessagePublishedEventArgs(int threadId, string source, MqttTraceLevel level, string message, Exception exception)
{ {
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Exceptions namespace MQTTnet.Core.Exceptions
{ {
public class MqttCommunicationTimedOutException : MqttCommunicationException public sealed class MqttCommunicationTimedOutException : MqttCommunicationException
{ {
} }
} }
@@ -2,7 +2,7 @@
namespace MQTTnet.Core.Exceptions namespace MQTTnet.Core.Exceptions
{ {
public class MqttProtocolViolationException : Exception public sealed class MqttProtocolViolationException : Exception
{ {
public MqttProtocolViolationException(string message) public MqttProtocolViolationException(string message)
: base(message) : base(message)
+1 -1
View File
@@ -3,7 +3,7 @@ using System.Threading.Tasks;
namespace MQTTnet.Core.Internal namespace MQTTnet.Core.Internal
{ {
public class AsyncGate public sealed class AsyncGate
{ {
private readonly Queue<TaskCompletionSource<bool>> _waitingTasks = new Queue<TaskCompletionSource<bool>>(); private readonly Queue<TaskCompletionSource<bool>> _waitingTasks = new Queue<TaskCompletionSource<bool>>();
-11
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
View File
@@ -3,7 +3,7 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core namespace MQTTnet.Core
{ {
public class MqttApplicationMessage public sealed class MqttApplicationMessage
{ {
public MqttApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain) public MqttApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
{ {
@@ -2,7 +2,7 @@
namespace MQTTnet.Core namespace MQTTnet.Core
{ {
public class MqttApplicationMessageReceivedEventArgs : EventArgs public sealed class MqttApplicationMessageReceivedEventArgs : EventArgs
{ {
public MqttApplicationMessageReceivedEventArgs(MqttApplicationMessage applicationMessage) public MqttApplicationMessageReceivedEventArgs(MqttApplicationMessage applicationMessage)
{ {
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttConnAckPacket : MqttBasePacket public sealed class MqttConnAckPacket : MqttBasePacket
{ {
public bool IsSessionPresent { get; set; } public bool IsSessionPresent { get; set; }
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttConnectPacket: MqttBasePacket public sealed class MqttConnectPacket: MqttBasePacket
{ {
public string ClientId { get; set; } public string ClientId { get; set; }
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttDisconnectPacket : MqttBasePacket public sealed class MqttDisconnectPacket : MqttBasePacket
{ {
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttPingReqPacket : MqttBasePacket public sealed class MqttPingReqPacket : MqttBasePacket
{ {
public override string ToString() public override string ToString()
{ {
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttPingRespPacket : MqttBasePacket public sealed class MqttPingRespPacket : MqttBasePacket
{ {
public override string ToString() public override string ToString()
{ {
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttPubAckPacket : MqttBasePublishPacket public sealed class MqttPubAckPacket : MqttBasePublishPacket
{ {
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttPubCompPacket : MqttBasePublishPacket public sealed class MqttPubCompPacket : MqttBasePublishPacket
{ {
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttPubRecPacket : MqttBasePublishPacket public sealed class MqttPubRecPacket : MqttBasePublishPacket
{ {
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttPubRelPacket : MqttBasePublishPacket public sealed class MqttPubRelPacket : MqttBasePublishPacket
{ {
} }
} }
+1 -1
View File
@@ -3,7 +3,7 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttPublishPacket : MqttBasePublishPacket public sealed class MqttPublishPacket : MqttBasePublishPacket
{ {
public bool Retain { get; set; } public bool Retain { get; set; }
+1 -1
View File
@@ -4,7 +4,7 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttSubAckPacket : MqttBasePacket, IPacketWithIdentifier public sealed class MqttSubAckPacket : MqttBasePacket, IPacketWithIdentifier
{ {
public ushort PacketIdentifier { get; set; } public ushort PacketIdentifier { get; set; }
+1 -1
View File
@@ -3,7 +3,7 @@ using System.Linq;
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttSubscribePacket : MqttBasePacket, IPacketWithIdentifier public sealed class MqttSubscribePacket : MqttBasePacket, IPacketWithIdentifier
{ {
public ushort PacketIdentifier { get; set; } public ushort PacketIdentifier { get; set; }
+1 -1
View File
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttUnsubAckPacket : MqttBasePacket, IPacketWithIdentifier public sealed class MqttUnsubAckPacket : MqttBasePacket, IPacketWithIdentifier
{ {
public ushort PacketIdentifier { get; set; } public ushort PacketIdentifier { get; set; }
} }
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class MqttUnsubscribePacket : MqttBasePacket, IPacketWithIdentifier public sealed class MqttUnsubscribePacket : MqttBasePacket, IPacketWithIdentifier
{ {
public ushort PacketIdentifier { get; set; } public ushort PacketIdentifier { get; set; }
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MQTTnet.Core.Packets namespace MQTTnet.Core.Packets
{ {
public class TopicFilter public sealed class TopicFilter
{ {
public TopicFilter(string topic, MqttQualityOfServiceLevel qualityOfServiceLevel) public TopicFilter(string topic, MqttQualityOfServiceLevel qualityOfServiceLevel)
{ {
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MQTTnet.Core.Serializer namespace MQTTnet.Core.Serializer
{ {
public class ByteReader public sealed class ByteReader
{ {
private readonly int _source; private readonly int _source;
private int _index; private int _index;
+1 -1
View File
@@ -2,7 +2,7 @@
namespace MQTTnet.Core.Serializer namespace MQTTnet.Core.Serializer
{ {
public class ByteWriter public sealed class ByteWriter
{ {
private int _index; private int _index;
private int _byte; private int _byte;
@@ -9,7 +9,7 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Serializer namespace MQTTnet.Core.Serializer
{ {
public class DefaultMqttV311PacketSerializer : IMqttPacketSerializer public sealed class DefaultMqttV311PacketSerializer : IMqttPacketSerializer
{ {
public Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination) public Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination)
{ {
@@ -0,0 +1,9 @@
namespace MQTTnet.Core.Server
{
public sealed class DefaultEndpointOptions
{
public bool IsEnabled { get; set; } = true;
public int? Port { get; set; }
}
}
@@ -1,6 +1,6 @@
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
public class GetOrCreateClientSessionResult public sealed class GetOrCreateClientSessionResult
{ {
public bool IsExistingSession { get; set; } public bool IsExistingSession { get; set; }
@@ -11,7 +11,7 @@ using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
public class MqttClientMessageQueue public sealed class MqttClientMessageQueue
{ {
private readonly List<MqttClientPublishPacketContext> _pendingPublishPackets = new List<MqttClientPublishPacketContext>(); private readonly List<MqttClientPublishPacketContext> _pendingPublishPackets = new List<MqttClientPublishPacketContext>();
private readonly AsyncGate _gate = new AsyncGate(); private readonly AsyncGate _gate = new AsyncGate();
@@ -3,7 +3,7 @@ using MQTTnet.Core.Packets;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
public class MqttClientPublishPacketContext public sealed class MqttClientPublishPacketContext
{ {
public MqttClientPublishPacketContext(MqttClientSession senderClientSession, MqttPublishPacket publishPacket) public MqttClientPublishPacketContext(MqttClientSession senderClientSession, MqttPublishPacket publishPacket)
{ {
@@ -10,7 +10,7 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
public class MqttClientSessionsManager public sealed class MqttClientSessionsManager
{ {
private readonly object _syncRoot = new object(); private readonly object _syncRoot = new object();
private readonly Dictionary<string, MqttClientSession> _clientSessions = new Dictionary<string, MqttClientSession>(); private readonly Dictionary<string, MqttClientSession> _clientSessions = new Dictionary<string, MqttClientSession>();
@@ -5,7 +5,7 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
public class MqttClientSubscriptionsManager public sealed class MqttClientSubscriptionsManager
{ {
private readonly ConcurrentDictionary<string, MqttQualityOfServiceLevel> _subscribedTopics = new ConcurrentDictionary<string, MqttQualityOfServiceLevel>(); private readonly ConcurrentDictionary<string, MqttQualityOfServiceLevel> _subscribedTopics = new ConcurrentDictionary<string, MqttQualityOfServiceLevel>();
+15 -9
View File
@@ -7,18 +7,18 @@ using MQTTnet.Core.Diagnostics;
namespace MQTTnet.Core.Server namespace MQTTnet.Core.Server
{ {
public class MqttServer public sealed class MqttServer
{ {
private readonly MqttClientSessionsManager _clientSessionsManager; private readonly MqttClientSessionsManager _clientSessionsManager;
private readonly IMqttServerAdapter _adapter; private readonly ICollection<IMqttServerAdapter> _adapters;
private readonly MqttServerOptions _options; private readonly MqttServerOptions _options;
private CancellationTokenSource _cancellationTokenSource; private CancellationTokenSource _cancellationTokenSource;
public MqttServer(MqttServerOptions options, IMqttServerAdapter adapter) public MqttServer(MqttServerOptions options, ICollection<IMqttServerAdapter> adapters)
{ {
_options = options ?? throw new ArgumentNullException(nameof(options)); _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); _clientSessionsManager = new MqttClientSessionsManager(options);
} }
@@ -45,9 +45,12 @@ namespace MQTTnet.Core.Server
_cancellationTokenSource = new CancellationTokenSource(); _cancellationTokenSource = new CancellationTokenSource();
_adapter.ClientConnected += OnClientConnected; foreach (var adapter in _adapters)
_adapter.Start(_options); {
adapter.ClientConnected += OnClientConnected;
adapter.Start(_options);
}
MqttTrace.Information(nameof(MqttServer), "Started."); MqttTrace.Information(nameof(MqttServer), "Started.");
} }
@@ -56,8 +59,11 @@ namespace MQTTnet.Core.Server
_cancellationTokenSource?.Cancel(); _cancellationTokenSource?.Cancel();
_cancellationTokenSource = null; _cancellationTokenSource = null;
_adapter.ClientConnected -= OnClientConnected; foreach (var adapter in _adapters)
_adapter.Stop(); {
adapter.ClientConnected -= OnClientConnected;
adapter.Stop();
}
_clientSessionsManager.Clear(); _clientSessionsManager.Clear();
+4 -9
View File
@@ -4,21 +4,16 @@ using MQTTnet.Core.Protocol;
namespace MQTTnet.Core.Server 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 int ConnectionBacklog { get; set; } = 10;
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(10);
public Func<MqttConnectPacket, MqttConnectReturnCode> ConnectionValidator { get; set; } 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;
} }
} }
@@ -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
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; }
}
}
@@ -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
View File
@@ -11,7 +11,9 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>MQTTnet is a .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description> <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". <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> <copyright>Copyright Christian Kratky 2016-2017</copyright>
<tags>MQTT MQTTClient MQTTServer MQTTBroker Broker</tags> <tags>MQTT MQTTClient MQTTServer MQTTBroker Broker</tags>
</metadata> </metadata>
+63 -55
View File
@@ -1,10 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.26228.9 VisualStudioVersion = 15.0.26430.12
MinimumVisualStudioVersion = 10.0.40219.1 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}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core.Tests", "Tests\MQTTnet.Core.Tests\MQTTnet.Core.Tests.csproj", "{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.NetFramework", "Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj", "{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.NetFramework", "Frameworks\MQTTnet.NetFramework\MQTTnet.NetFramework.csproj", "{A480EF90-0EAA-4D9A-B271-47A9C47F6F7D}"
@@ -15,8 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9248C2E1
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frameworks", "Frameworks", "{32A630A7-2598-41D7-B625-204CD906F5FB}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frameworks", "Frameworks", "{32A630A7-2598-41D7-B625-204CD906F5FB}"
EndProject 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}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.Core", "MQTTnet.Core\MQTTnet.Core.csproj", "{2ECB99E4-72D0-4C23-99BA-93D511D3967D}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{002203AF-2565-4C0D-95ED-027FDEFE0C35}" 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 EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.NetCoreApp", "Frameworks\MQTTnet.NetCoreApp\MQTTnet.NetCoreApp.csproj", "{1A1B7F51-5328-4395-9D9C-07D70965825E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.NetCoreApp", "Frameworks\MQTTnet.NetCoreApp\MQTTnet.NetCoreApp.csproj", "{1A1B7F51-5328-4395-9D9C-07D70965825E}"
EndProject 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 Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Any CPU|Any CPU = Any CPU|Any CPU Any CPU|Any CPU = Any CPU|Any CPU
@@ -42,30 +42,6 @@ Global
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution 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.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|Any CPU.Build.0 = Any CPU|Any CPU
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC}.Any CPU|ARM.ActiveCfg = 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|x64.Build.0 = Release|x64
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.ActiveCfg = Release|x86 {BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.ActiveCfg = Release|x86
{BD60C727-D8E8-40C3-B8E3-C95A864AE611}.Release|x86.Build.0 = 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.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|Any CPU.Build.0 = Any CPU|Any CPU
{2ECB99E4-72D0-4C23-99BA-93D511D3967D}.Any CPU|ARM.ActiveCfg = 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|x64.Build.0 = Release|x64
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.ActiveCfg = Release|x86 {1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.ActiveCfg = Release|x86
{1A1B7F51-5328-4395-9D9C-07D70965825E}.Release|x86.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{7B19B139-2E9D-4F1D-88B4-6180B4CF872A} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4}
{A7FF0C91-25DE-4BA6-B39E-F54E8DADF1CC} = {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} {A480EF90-0EAA-4D9A-B271-47A9C47F6F7D} = {32A630A7-2598-41D7-B625-204CD906F5FB}
{BD60C727-D8E8-40C3-B8E3-C95A864AE611} = {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} {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 EndGlobalSection
EndGlobal EndGlobal
+12 -2
View File
@@ -7,8 +7,19 @@
# MQTTnet # 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/. 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 Standard 1.1+
* .NET Core 1.1+ * .NET Core 1.1+
* .NET Core App 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) * Universal Windows (UWP) 10.0.10240+ (x86, x64, ARM, AnyCPU)
## Supported MQTT versions ## Supported MQTT versions
* 3.1.1 * 3.1.1
## Nuget ## Nuget
+6 -4
View File
@@ -1,5 +1,7 @@
using System.Threading.Tasks; using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Core.Adapter;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
using MQTTnet.Core.Packets; using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol; using MQTTnet.Core.Protocol;
@@ -46,11 +48,11 @@ namespace MQTTnet.Core.Tests
[TestMethod] [TestMethod]
public async Task MqttServer_WillMessage() 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(); s.Start();
var willMessage = new MqttApplicationMessage("My/last/will", new byte[0], MqttQualityOfServiceLevel.AtMostOnce, false); 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 c2 = ConnectTestClient("c2", willMessage, s);
var receivedMessagesCount = 0; var receivedMessagesCount = 0;
@@ -86,7 +88,7 @@ namespace MQTTnet.Core.Tests
MqttQualityOfServiceLevel filterQualityOfServiceLevel, MqttQualityOfServiceLevel filterQualityOfServiceLevel,
int expectedReceivedMessagesCount) int expectedReceivedMessagesCount)
{ {
var s = new MqttServer(new MqttServerOptions(), new TestMqttServerAdapter()); var s = new MqttServer(new MqttServerOptions(), new List<IMqttServerAdapter> { new TestMqttServerAdapter() });
s.Start(); s.Start();
var c1 = ConnectTestClient("c1", null, s); var c1 = ConnectTestClient("c1", null, s);
@@ -4,10 +4,10 @@
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6F8C0C0C-59EC-4921-9267-370AE113C34F}</ProjectGuid> <ProjectGuid>{D9D74F33-6943-49B2-B765-7BD589082098}</ProjectGuid>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>MQTTnet.TestMqttServer</RootNamespace> <RootNamespace>MQTTnet.TestApp.NetFramework</RootNamespace>
<AssemblyName>MQTTnet.TestMqttServer</AssemblyName> <AssemblyName>MQTTnet.TestApp.NetFramework</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
@@ -31,43 +31,15 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </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> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <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>
<ItemGroup> <ItemGroup>
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MQTTnet.Core; using MQTTnet.Core;
using MQTTnet.Core.Client; using MQTTnet.Core.Client;
@@ -9,16 +10,29 @@ using MQTTnet.Core.Packets;
using MQTTnet.Core.Protocol; using MQTTnet.Core.Protocol;
using MQTTnet.Core.Server; using MQTTnet.Core.Server;
namespace MQTTnet.TestMqttClient namespace MQTTnet.TestApp.NetFramework
{ {
public static class Program 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) => MqttTrace.TraceMessagePublished += (s, e) =>
{ {
@@ -28,7 +42,7 @@ namespace MQTTnet.TestMqttClient
Console.WriteLine(e.Exception); Console.WriteLine(e.Exception);
} }
}; };
try try
{ {
var options = new MqttClientOptions var options = new MqttClientOptions
@@ -61,7 +75,7 @@ namespace MQTTnet.TestMqttClient
Console.WriteLine("### SUBSCRIBED ###"); Console.WriteLine("### SUBSCRIBED ###");
}; };
client.Disconnected += async (s, e) => client.Disconnected += async (s, e) =>
{ {
Console.WriteLine("### DISCONNECTED FROM SERVER ###"); Console.WriteLine("### DISCONNECTED FROM SERVER ###");
await Task.Delay(TimeSpan.FromSeconds(5)); await Task.Delay(TimeSpan.FromSeconds(5));
@@ -80,9 +94,9 @@ namespace MQTTnet.TestMqttClient
{ {
await client.ConnectAsync(); await client.ConnectAsync();
} }
catch catch (Exception exception)
{ {
Console.WriteLine("### CONNECTING FAILED ###"); Console.WriteLine("### CONNECTING FAILED ###" + Environment.NewLine + exception);
} }
Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###"); Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###");
@@ -106,5 +120,50 @@ namespace MQTTnet.TestMqttClient
Console.WriteLine(exception); 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();
}
} }
} }
@@ -1,7 +1,7 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
[assembly: AssemblyTitle("MQTTnet.TestMqttClient")] [assembly: AssemblyTitle("MQTTnet.TestApp.NetFramework")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Christian Kratky")] [assembly: AssemblyCompany("Christian Kratky")]
@@ -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>
@@ -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();
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

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