@@ -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.Net.Security; | |||||
using System.Collections.Generic; | |||||
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 }; | |||||
_defaultEndpointSocket.Bind(new IPEndPoint(options.DefaultEndpointOptions.BoundIPAddress, options.GetDefaultEndpointPort())); | |||||
_defaultEndpointSocket.Listen(options.ConnectionBacklog); | |||||
Task.Run(() => AcceptDefaultEndpointConnectionsAsync(_cancellationTokenSource.Token), | |||||
_cancellationTokenSource.Token); | |||||
RegisterListeners(options.DefaultEndpointOptions); | |||||
} | } | ||||
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); | |||||
if (!_tlsCertificate.HasPrivateKey) | |||||
var tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate); | |||||
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); | |||||
_tlsEndpointSocket.Bind(new IPEndPoint(options.TlsEndpointOptions.BoundIPAddress, options.GetTlsEndpointPort())); | |||||
_tlsEndpointSocket.Listen(options.ConnectionBacklog); | |||||
Task.Run( | |||||
() => AcceptTlsEndpointConnectionsAsync(_cancellationTokenSource.Token), | |||||
_cancellationTokenSource.Token); | |||||
RegisterListeners(options.TlsEndpointOptions); | |||||
} | } | ||||
return Task.FromResult(0); | return Task.FromResult(0); | ||||
@@ -76,93 +59,60 @@ namespace MQTTnet.Implementations | |||||
public Task StopAsync() | public Task StopAsync() | ||||
{ | { | ||||
_cancellationTokenSource?.Cancel(false); | |||||
_cancellationTokenSource?.Dispose(); | |||||
_cancellationTokenSource = null; | |||||
_defaultEndpointSocket?.Dispose(); | |||||
_defaultEndpointSocket = null; | |||||
_tlsCertificate = null; | |||||
_tlsEndpointSocket?.Dispose(); | |||||
_tlsEndpointSocket = null; | |||||
Dispose(); | |||||
return Task.FromResult(0); | return Task.FromResult(0); | ||||
} | } | ||||
public void Dispose() | public void Dispose() | ||||
{ | { | ||||
StopAsync().GetAwaiter().GetResult(); | |||||
} | |||||
_cancellationTokenSource?.Cancel(false); | |||||
_cancellationTokenSource?.Dispose(); | |||||
_cancellationTokenSource = null; | |||||
private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken) | |||||
{ | |||||
while (!cancellationToken.IsCancellationRequested) | |||||
foreach (var listener in _listeners) | |||||
{ | { | ||||
try | |||||
{ | |||||
//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); | |||||
} | |||||
listener.Dispose(); | |||||
} | } | ||||
_listeners.Clear(); | |||||
} | } | ||||
private async Task AcceptTlsEndpointConnectionsAsync(CancellationToken cancellationToken) | |||||
private void RegisterListeners(MqttServerTcpEndpointBaseOptions options) | |||||
{ | { | ||||
while (!cancellationToken.IsCancellationRequested) | |||||
{ | |||||
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 tlsOptions = options as MqttServerTlsTcpEndpointOptions; | |||||
var sslStream = new SslStream(new NetworkStream(clientSocket)); | |||||
await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false); | |||||
X509Certificate2 tlsCertificate = null; | |||||
if (tlsOptions != null) | |||||
{ | |||||
tlsCertificate = new X509Certificate2(tlsOptions.Certificate); | |||||
} | |||||
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; | |||||
} | |||||
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); | |||||
} | |||||
_logger.Error(exception, "Error while accepting connection at TLS endpoint."); | |||||
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false); | |||||
} | |||||
} | |||||
private void OnClientAccepted(object sender, MqttServerAdapterClientAcceptedEventArgs e) | |||||
{ | |||||
ClientAccepted?.Invoke(this, e); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -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; } | |||||
MqttServerTlsEndpointOptions TlsEndpointOptions { get; } | |||||
MqttServerTcpEndpointOptions DefaultEndpointOptions { 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; } | |||||
} | |||||
} |
@@ -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> | ||||