mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-27 16:52:40 +08:00
Refactor server socket management for Linux support.
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
* [Server] Rewritten the _ConnectedClients_ API and added new features for disconnecting and Endpoint information (IP etc.).
|
* [Server] Rewritten the _ConnectedClients_ API and added new features for disconnecting and Endpoint information (IP etc.).
|
||||||
* [Server] Added settings for disabling persistent sessions and defining a max pending messages queue size per session.
|
* [Server] Added settings for disabling persistent sessions and defining a max pending messages queue size per session.
|
||||||
* [Server] Added a new interceptor which is invoked before a new message is added to the client queue.
|
* [Server] Added a new interceptor which is invoked before a new message is added to the client queue.
|
||||||
|
* [Server] Added support for Linux servers by dividing IPv4 and IPv6 support and adding new options (BREAKING CHANGE!).
|
||||||
</releaseNotes>
|
</releaseNotes>
|
||||||
<copyright>Copyright Christian Kratky 2016-2018</copyright>
|
<copyright>Copyright Christian Kratky 2016-2018</copyright>
|
||||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin</tags>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.NetStandard.csproj" />
|
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.NetStandard.csproj" />
|
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MQTTnet.NetStandard\MQTTnet.NetStandard.csproj" />
|
<ProjectReference Include="..\MQTTnet.NetStandard\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ namespace MQTTnet.Implementations
|
|||||||
_defaultEndpointSocket.Control.KeepAlive = true;
|
_defaultEndpointSocket.Control.KeepAlive = true;
|
||||||
_defaultEndpointSocket.Control.QualityOfService = SocketQualityOfService.LowLatency;
|
_defaultEndpointSocket.Control.QualityOfService = SocketQualityOfService.LowLatency;
|
||||||
_defaultEndpointSocket.ConnectionReceived += AcceptDefaultEndpointConnectionsAsync;
|
_defaultEndpointSocket.ConnectionReceived += AcceptDefaultEndpointConnectionsAsync;
|
||||||
|
|
||||||
await _defaultEndpointSocket.BindServiceNameAsync(options.GetDefaultEndpointPort().ToString(), SocketProtectionLevel.PlainSocket);
|
await _defaultEndpointSocket.BindServiceNameAsync(options.DefaultEndpointOptions.Port.ToString(), SocketProtectionLevel.PlainSocket);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,23 @@
|
|||||||
#if NET452 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0
|
#if NET452 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Collections.Generic;
|
||||||
using System.Net.Security;
|
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Security.Authentication;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Serializer;
|
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
|
||||||
namespace MQTTnet.Implementations
|
namespace MQTTnet.Implementations
|
||||||
{
|
{
|
||||||
public class MqttTcpServerAdapter : IMqttServerAdapter
|
public class MqttTcpServerAdapter : IMqttServerAdapter
|
||||||
{
|
{
|
||||||
|
private readonly List<MqttTcpServerListener> _listeners = new List<MqttTcpServerListener>();
|
||||||
private readonly IMqttNetChildLogger _logger;
|
private readonly IMqttNetChildLogger _logger;
|
||||||
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
private Socket _defaultEndpointSocket;
|
|
||||||
private Socket _tlsEndpointSocket;
|
|
||||||
private X509Certificate2 _tlsCertificate;
|
|
||||||
|
|
||||||
public MqttTcpServerAdapter(IMqttNetChildLogger logger)
|
public MqttTcpServerAdapter(IMqttNetChildLogger logger)
|
||||||
{
|
{
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
@@ -40,13 +35,7 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
if (options.DefaultEndpointOptions.IsEnabled)
|
if (options.DefaultEndpointOptions.IsEnabled)
|
||||||
{
|
{
|
||||||
_defaultEndpointSocket = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
|
RegisterListeners(options.DefaultEndpointOptions);
|
||||||
|
|
||||||
_defaultEndpointSocket.Bind(new IPEndPoint(options.DefaultEndpointOptions.BoundIPAddress, options.GetDefaultEndpointPort()));
|
|
||||||
_defaultEndpointSocket.Listen(options.ConnectionBacklog);
|
|
||||||
|
|
||||||
Task.Run(() => AcceptDefaultEndpointConnectionsAsync(_cancellationTokenSource.Token),
|
|
||||||
_cancellationTokenSource.Token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.TlsEndpointOptions.IsEnabled)
|
if (options.TlsEndpointOptions.IsEnabled)
|
||||||
@@ -56,19 +45,13 @@ namespace MQTTnet.Implementations
|
|||||||
throw new ArgumentException("TLS certificate is not set.");
|
throw new ArgumentException("TLS certificate is not set.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate);
|
var tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate);
|
||||||
if (!_tlsCertificate.HasPrivateKey)
|
if (!tlsCertificate.HasPrivateKey)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("The certificate for TLS encryption must contain the private key.");
|
throw new InvalidOperationException("The certificate for TLS encryption must contain the private key.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_tlsEndpointSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
RegisterListeners(options.TlsEndpointOptions);
|
||||||
_tlsEndpointSocket.Bind(new IPEndPoint(options.TlsEndpointOptions.BoundIPAddress, options.GetTlsEndpointPort()));
|
|
||||||
_tlsEndpointSocket.Listen(options.ConnectionBacklog);
|
|
||||||
|
|
||||||
Task.Run(
|
|
||||||
() => AcceptTlsEndpointConnectionsAsync(_cancellationTokenSource.Token),
|
|
||||||
_cancellationTokenSource.Token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
@@ -76,93 +59,60 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
public Task StopAsync()
|
public Task StopAsync()
|
||||||
{
|
{
|
||||||
_cancellationTokenSource?.Cancel(false);
|
Dispose();
|
||||||
_cancellationTokenSource?.Dispose();
|
|
||||||
_cancellationTokenSource = null;
|
|
||||||
|
|
||||||
_defaultEndpointSocket?.Dispose();
|
|
||||||
_defaultEndpointSocket = null;
|
|
||||||
|
|
||||||
_tlsCertificate = null;
|
|
||||||
|
|
||||||
_tlsEndpointSocket?.Dispose();
|
|
||||||
_tlsEndpointSocket = null;
|
|
||||||
|
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
StopAsync().GetAwaiter().GetResult();
|
_cancellationTokenSource?.Cancel(false);
|
||||||
|
_cancellationTokenSource?.Dispose();
|
||||||
|
_cancellationTokenSource = null;
|
||||||
|
|
||||||
|
foreach (var listener in _listeners)
|
||||||
|
{
|
||||||
|
listener.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_listeners.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken)
|
private void RegisterListeners(MqttServerTcpEndpointBaseOptions options)
|
||||||
{
|
{
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
var tlsOptions = options as MqttServerTlsTcpEndpointOptions;
|
||||||
|
|
||||||
|
X509Certificate2 tlsCertificate = null;
|
||||||
|
if (tlsOptions != null)
|
||||||
{
|
{
|
||||||
try
|
tlsCertificate = new X509Certificate2(tlsOptions.Certificate);
|
||||||
{
|
|
||||||
//todo: else branch can be used with min dependency NET46
|
|
||||||
#if NET452 || NET461
|
|
||||||
var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null).ConfigureAwait(false);
|
|
||||||
#else
|
|
||||||
var clientSocket = await _defaultEndpointSocket.AcceptAsync().ConfigureAwait(false);
|
|
||||||
#endif
|
|
||||||
clientSocket.NoDelay = true;
|
|
||||||
|
|
||||||
var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, null), new MqttPacketSerializer(), _logger);
|
|
||||||
ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter));
|
|
||||||
}
|
|
||||||
catch (ObjectDisposedException)
|
|
||||||
{
|
|
||||||
// It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed.
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
if (exception is SocketException s && s.SocketErrorCode == SocketError.OperationAborted)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Error(exception, "Error while accepting connection at default endpoint.");
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var listenerV4 = new MqttTcpServerListener(
|
||||||
|
AddressFamily.InterNetwork,
|
||||||
|
options,
|
||||||
|
tlsCertificate,
|
||||||
|
_cancellationTokenSource.Token,
|
||||||
|
_logger);
|
||||||
|
|
||||||
|
listenerV4.ClientAccepted += OnClientAccepted;
|
||||||
|
listenerV4.Start();
|
||||||
|
_listeners.Add(listenerV4);
|
||||||
|
|
||||||
|
var listenerV6 = new MqttTcpServerListener(
|
||||||
|
AddressFamily.InterNetworkV6,
|
||||||
|
options,
|
||||||
|
tlsCertificate,
|
||||||
|
_cancellationTokenSource.Token,
|
||||||
|
_logger);
|
||||||
|
|
||||||
|
listenerV6.ClientAccepted += OnClientAccepted;
|
||||||
|
listenerV6.Start();
|
||||||
|
_listeners.Add(listenerV6);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AcceptTlsEndpointConnectionsAsync(CancellationToken cancellationToken)
|
private void OnClientAccepted(object sender, MqttServerAdapterClientAcceptedEventArgs e)
|
||||||
{
|
{
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
ClientAccepted?.Invoke(this, e);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#if NET452 || NET461
|
|
||||||
var clientSocket = await Task.Factory.FromAsync(_tlsEndpointSocket.BeginAccept, _tlsEndpointSocket.EndAccept, null).ConfigureAwait(false);
|
|
||||||
#else
|
|
||||||
var clientSocket = await _tlsEndpointSocket.AcceptAsync().ConfigureAwait(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var sslStream = new SslStream(new NetworkStream(clientSocket));
|
|
||||||
await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, sslStream), new MqttPacketSerializer(), _logger);
|
|
||||||
ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter));
|
|
||||||
}
|
|
||||||
catch (ObjectDisposedException)
|
|
||||||
{
|
|
||||||
// It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed.
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
if (exception is SocketException s && s.SocketErrorCode == SocketError.OperationAborted)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Error(exception, "Error while accepting connection at TLS endpoint.");
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
#if NET452 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0
|
||||||
|
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.Adapter;
|
||||||
|
using MQTTnet.Diagnostics;
|
||||||
|
using MQTTnet.Serializer;
|
||||||
|
using MQTTnet.Server;
|
||||||
|
|
||||||
|
namespace MQTTnet.Implementations
|
||||||
|
{
|
||||||
|
public class MqttTcpServerListener : IDisposable
|
||||||
|
{
|
||||||
|
private readonly IMqttNetChildLogger _logger;
|
||||||
|
private readonly CancellationToken _cancellationToken;
|
||||||
|
private readonly AddressFamily _addressFamily;
|
||||||
|
private readonly MqttServerTcpEndpointBaseOptions _options;
|
||||||
|
private readonly X509Certificate2 _tlsCertificate;
|
||||||
|
|
||||||
|
private Socket _socket;
|
||||||
|
|
||||||
|
public MqttTcpServerListener(
|
||||||
|
AddressFamily addressFamily,
|
||||||
|
MqttServerTcpEndpointBaseOptions options,
|
||||||
|
X509Certificate2 tlsCertificate,
|
||||||
|
CancellationToken cancellationToken,
|
||||||
|
IMqttNetChildLogger logger)
|
||||||
|
{
|
||||||
|
_addressFamily = addressFamily;
|
||||||
|
_options = options;
|
||||||
|
_tlsCertificate = tlsCertificate;
|
||||||
|
_cancellationToken = cancellationToken;
|
||||||
|
_logger = logger.CreateChildLogger(nameof(MqttTcpServerListener));
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<MqttServerAdapterClientAcceptedEventArgs> ClientAccepted;
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
var boundIp = _options.BoundInterNetworkAddress;
|
||||||
|
if (_addressFamily == AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
boundIp = _options.BoundInterNetworkV6Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
_socket = new Socket(_addressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
_socket.Bind(new IPEndPoint(boundIp, _options.Port));
|
||||||
|
|
||||||
|
_logger.Info($"Starting TCP listener for {_socket.LocalEndPoint} TLS={_tlsCertificate != null}.");
|
||||||
|
|
||||||
|
_socket.Listen(_options.ConnectionBacklog);
|
||||||
|
Task.Run(AcceptClientConnectionsAsync, _cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AcceptClientConnectionsAsync()
|
||||||
|
{
|
||||||
|
while (!_cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if NET452 || NET461
|
||||||
|
var clientSocket = await Task.Factory.FromAsync(_socket.BeginAccept, _socket.EndAccept, null).ConfigureAwait(false);
|
||||||
|
#else
|
||||||
|
var clientSocket = await _socket.AcceptAsync().ConfigureAwait(false);
|
||||||
|
#endif
|
||||||
|
clientSocket.NoDelay = true;
|
||||||
|
|
||||||
|
if (_tlsCertificate != null)
|
||||||
|
{
|
||||||
|
var sslStream = new SslStream(new NetworkStream(clientSocket), false);
|
||||||
|
await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, null), new MqttPacketSerializer(), _logger);
|
||||||
|
ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter));
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed.
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
if (exception is SocketException s && s.SocketErrorCode == SocketError.OperationAborted)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Error(exception, $"Error while accepting connection at TCP listener {_socket.LocalEndPoint} TLS={_tlsCertificate != null}.");
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_socket?.Dispose();
|
||||||
|
|
||||||
|
#if NETSTANDARD1_3 || NETSTANDARD2_0 || NET461
|
||||||
|
_tlsCertificate?.Dispose();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -4,8 +4,6 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
public interface IMqttServerOptions
|
public interface IMqttServerOptions
|
||||||
{
|
{
|
||||||
int ConnectionBacklog { get; }
|
|
||||||
|
|
||||||
bool EnablePersistentSessions { get; }
|
bool EnablePersistentSessions { get; }
|
||||||
|
|
||||||
int MaxPendingMessagesPerClient { get; }
|
int MaxPendingMessagesPerClient { get; }
|
||||||
@@ -18,8 +16,8 @@ namespace MQTTnet.Server
|
|||||||
Action<MqttApplicationMessageInterceptorContext> ApplicationMessageInterceptor { get; }
|
Action<MqttApplicationMessageInterceptorContext> ApplicationMessageInterceptor { get; }
|
||||||
Action<MqttClientMessageQueueInterceptorContext> ClientMessageQueueInterceptor { get; set; }
|
Action<MqttClientMessageQueueInterceptorContext> ClientMessageQueueInterceptor { get; set; }
|
||||||
|
|
||||||
MqttServerDefaultEndpointOptions DefaultEndpointOptions { get; }
|
MqttServerTcpEndpointOptions DefaultEndpointOptions { get; }
|
||||||
MqttServerTlsEndpointOptions TlsEndpointOptions { get; }
|
MqttServerTlsTcpEndpointOptions TlsEndpointOptions { get; }
|
||||||
|
|
||||||
IMqttServerStorage Storage { get; }
|
IMqttServerStorage Storage { get; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
|
||||||
{
|
|
||||||
public class MqttServerDefaultEndpointOptions
|
|
||||||
{
|
|
||||||
public bool IsEnabled { get; set; } = true;
|
|
||||||
|
|
||||||
public int? Port { get; set; }
|
|
||||||
|
|
||||||
public IPAddress BoundIPAddress { get; set; } = IPAddress.Any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,14 +4,12 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
public class MqttServerOptions : IMqttServerOptions
|
public class MqttServerOptions : IMqttServerOptions
|
||||||
{
|
{
|
||||||
public MqttServerDefaultEndpointOptions DefaultEndpointOptions { get; } = new MqttServerDefaultEndpointOptions();
|
public MqttServerTcpEndpointOptions DefaultEndpointOptions { get; } = new MqttServerTcpEndpointOptions();
|
||||||
|
|
||||||
public MqttServerTlsEndpointOptions TlsEndpointOptions { get; } = new MqttServerTlsEndpointOptions();
|
public MqttServerTlsTcpEndpointOptions TlsEndpointOptions { get; } = new MqttServerTlsTcpEndpointOptions();
|
||||||
|
|
||||||
public bool EnablePersistentSessions { get; set; }
|
public bool EnablePersistentSessions { get; set; }
|
||||||
|
|
||||||
public int ConnectionBacklog { get; set; } = 10;
|
|
||||||
|
|
||||||
public int MaxPendingMessagesPerClient { get; set; } = 250;
|
public int MaxPendingMessagesPerClient { get; set; } = 250;
|
||||||
public MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; set; } = MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage;
|
public MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; set; } = MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public MqttServerOptionsBuilder WithConnectionBacklog(int value)
|
public MqttServerOptionsBuilder WithConnectionBacklog(int value)
|
||||||
{
|
{
|
||||||
_options.ConnectionBacklog = value;
|
_options.DefaultEndpointOptions.ConnectionBacklog = value;
|
||||||
|
_options.TlsEndpointOptions.ConnectionBacklog = value;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ namespace MQTTnet.Server
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttServerOptionsBuilder WithDefaultEndpointPort(int? value)
|
public MqttServerOptionsBuilder WithDefaultEndpointPort(int value)
|
||||||
{
|
{
|
||||||
_options.DefaultEndpointOptions.Port = value;
|
_options.DefaultEndpointOptions.Port = value;
|
||||||
return this;
|
return this;
|
||||||
@@ -39,10 +40,16 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public MqttServerOptionsBuilder WithDefaultEndpointBoundIPAddress(IPAddress value)
|
public MqttServerOptionsBuilder WithDefaultEndpointBoundIPAddress(IPAddress value)
|
||||||
{
|
{
|
||||||
_options.DefaultEndpointOptions.BoundIPAddress = value ?? IPAddress.Any;
|
_options.DefaultEndpointOptions.BoundInterNetworkAddress = value ?? IPAddress.Any;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MqttServerOptionsBuilder WithDefaultEndpointBoundIPV6Address(IPAddress value)
|
||||||
|
{
|
||||||
|
_options.DefaultEndpointOptions.BoundInterNetworkV6Address = value ?? IPAddress.Any;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public MqttServerOptionsBuilder WithoutDefaultEndpoint()
|
public MqttServerOptionsBuilder WithoutDefaultEndpoint()
|
||||||
{
|
{
|
||||||
_options.DefaultEndpointOptions.IsEnabled = false;
|
_options.DefaultEndpointOptions.IsEnabled = false;
|
||||||
@@ -55,7 +62,7 @@ namespace MQTTnet.Server
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttServerOptionsBuilder WithEncryptedEndpointPort(int? value)
|
public MqttServerOptionsBuilder WithEncryptedEndpointPort(int value)
|
||||||
{
|
{
|
||||||
_options.TlsEndpointOptions.Port = value;
|
_options.TlsEndpointOptions.Port = value;
|
||||||
return this;
|
return this;
|
||||||
@@ -63,7 +70,7 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public MqttServerOptionsBuilder WithEncryptedEndpointBoundIPAddress(IPAddress value)
|
public MqttServerOptionsBuilder WithEncryptedEndpointBoundIPAddress(IPAddress value)
|
||||||
{
|
{
|
||||||
_options.TlsEndpointOptions.BoundIPAddress = value;
|
_options.TlsEndpointOptions.BoundInterNetworkAddress = value;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
|
||||||
{
|
|
||||||
public static class MqttServerOptionsExtensions
|
|
||||||
{
|
|
||||||
public static int GetTlsEndpointPort(this IMqttServerOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
if (!options.TlsEndpointOptions.Port.HasValue)
|
|
||||||
{
|
|
||||||
return 8883;
|
|
||||||
}
|
|
||||||
|
|
||||||
return options.TlsEndpointOptions.Port.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetDefaultEndpointPort(this IMqttServerOptions options)
|
|
||||||
{
|
|
||||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
|
||||||
|
|
||||||
if (!options.DefaultEndpointOptions.Port.HasValue)
|
|
||||||
{
|
|
||||||
return 1883;
|
|
||||||
}
|
|
||||||
|
|
||||||
return options.DefaultEndpointOptions.Port.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server
|
||||||
|
{
|
||||||
|
public abstract class MqttServerTcpEndpointBaseOptions
|
||||||
|
{
|
||||||
|
public bool IsEnabled { get; set; }
|
||||||
|
|
||||||
|
public int Port { get; set; }
|
||||||
|
|
||||||
|
public int ConnectionBacklog { get; set; } = 10;
|
||||||
|
|
||||||
|
public IPAddress BoundInterNetworkAddress { get; set; } = IPAddress.Any;
|
||||||
|
|
||||||
|
public IPAddress BoundInterNetworkV6Address { get; set; } = IPAddress.IPv6Any;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace MQTTnet.Server
|
||||||
|
{
|
||||||
|
public class MqttServerTcpEndpointOptions : MqttServerTcpEndpointBaseOptions
|
||||||
|
{
|
||||||
|
public MqttServerTcpEndpointOptions()
|
||||||
|
{
|
||||||
|
IsEnabled = true;
|
||||||
|
Port = 1883;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
|
||||||
{
|
|
||||||
public class MqttServerTlsEndpointOptions
|
|
||||||
{
|
|
||||||
public bool IsEnabled { get; set; }
|
|
||||||
|
|
||||||
public int? Port { get; set; }
|
|
||||||
|
|
||||||
public byte[] Certificate { get; set; }
|
|
||||||
|
|
||||||
public IPAddress BoundIPAddress { get; set; } = IPAddress.Any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace MQTTnet.Server
|
||||||
|
{
|
||||||
|
public class MqttServerTlsTcpEndpointOptions : MqttServerTcpEndpointBaseOptions
|
||||||
|
{
|
||||||
|
public MqttServerTlsTcpEndpointOptions()
|
||||||
|
{
|
||||||
|
Port = 8883;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Certificate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -11,7 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frameworks", "Frameworks",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestApp.UniversalWindows", "Tests\MQTTnet.TestApp.UniversalWindows\MQTTnet.TestApp.UniversalWindows.csproj", "{FF1F72D6-9524-4422-9497-3CC0002216ED}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MQTTnet.TestApp.UniversalWindows", "Tests\MQTTnet.TestApp.UniversalWindows\MQTTnet.TestApp.UniversalWindows.csproj", "{FF1F72D6-9524-4422-9497-3CC0002216ED}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.NetStandard", "Frameworks\MQTTnet.NetStandard\MQTTnet.NetStandard.csproj", "{3587E506-55A2-4EB3-99C7-DC01E42D25D2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "Frameworks\MQTTnet.NetStandard\MQTTnet.csproj", "{3587E506-55A2-4EB3-99C7-DC01E42D25D2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1-BC3A-420A-BE9C-FA2401431CF9}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1-BC3A-420A-BE9C-FA2401431CF9}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.NetStandard.csproj" />
|
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -21,7 +20,7 @@ namespace MQTTnet.Benchmarks.Tcp
|
|||||||
|
|
||||||
public TcpConnection(EndPoint endPoint)
|
public TcpConnection(EndPoint endPoint)
|
||||||
{
|
{
|
||||||
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
_endPoint = endPoint;
|
_endPoint = endPoint;
|
||||||
|
|
||||||
_sender = new SocketSender(_socket, PipeScheduler.ThreadPool);
|
_sender = new SocketSender(_socket, PipeScheduler.ThreadPool);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.NetStandard.csproj" />
|
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Extensions\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj" />
|
<ProjectReference Include="..\..\Extensions\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj" />
|
||||||
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.NetStandard.csproj" />
|
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
var concurrent = Console.ReadKey(true).KeyChar == 'c';
|
var concurrent = Console.ReadKey(true).KeyChar == 'c';
|
||||||
|
|
||||||
var server = Task.Run(RunServerAsync);
|
var server = Task.Run(RunServerAsync);
|
||||||
|
await Task.Delay(1000);
|
||||||
var client = Task.Run(() => RunClientAsync(2000, TimeSpan.FromMilliseconds(10), concurrent));
|
var client = Task.Run(() => RunClientAsync(2000, TimeSpan.FromMilliseconds(10), concurrent));
|
||||||
|
|
||||||
await Task.WhenAll(server, client).ConfigureAwait(false);
|
await Task.WhenAll(server, client).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -135,9 +135,9 @@
|
|||||||
<Project>{c444e9c8-95fa-430e-9126-274129de16cd}</Project>
|
<Project>{c444e9c8-95fa-430e-9126-274129de16cd}</Project>
|
||||||
<Name>MQTTnet.Extensions.Rpc</Name>
|
<Name>MQTTnet.Extensions.Rpc</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\..\Frameworks\MQTTnet.Netstandard\MQTTnet.NetStandard.csproj">
|
<ProjectReference Include="..\..\Frameworks\MQTTnet.NetStandard\MQTTnet.csproj">
|
||||||
<Project>{3587e506-55a2-4eb3-99c7-dc01e42d25d2}</Project>
|
<Project>{3587e506-55a2-4eb3-99c7-dc01e42d25d2}</Project>
|
||||||
<Name>MQTTnet.NetStandard</Name>
|
<Name>MQTTnet</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user