Use latest language features (#2176)

* Make use of language features line AsyncDispose, init etc.

* Fix build errors

* Improve Unit Tests

* Improve Unit Tests

* Improve Unit Tests

* Update samples

* Remove obsolete benchmarks

* Code cleanup

* Improve unit tests

* Improve Unit Tests

* Fix Unit Tests

* Improve Unit Tests

* Improve Unit Tests

* Restore unit tests

* Exclude load tests from unit tests
This commit is contained in:
Christian
2025-08-30 10:52:59 +02:00
committed by GitHub
parent 247988e633
commit e43e7f8e36
330 changed files with 21417 additions and 22919 deletions
@@ -2,10 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace MQTTnet.Server
namespace MQTTnet.Server;
public interface IMqttServerCertificateCredentials
{
public interface IMqttServerCertificateCredentials
{
string Password { get; }
}
}
string Password { get; }
}
@@ -2,12 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace MQTTnet.Server
{
public enum MqttPendingMessagesOverflowStrategy
{
DropOldestQueuedMessage,
namespace MQTTnet.Server;
DropNewMessage
}
}
public enum MqttPendingMessagesOverflowStrategy
{
DropOldestQueuedMessage,
DropNewMessage
}
@@ -2,10 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace MQTTnet.Server
namespace MQTTnet.Server;
public class MqttServerCertificateCredentials : IMqttServerCertificateCredentials
{
public class MqttServerCertificateCredentials : IMqttServerCertificateCredentials
{
public string Password { get; set; }
}
}
public string Password { get; set; }
}
@@ -2,20 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
namespace MQTTnet.Server;
namespace MQTTnet.Server
public sealed class MqttServerKeepAliveOptions
{
public sealed class MqttServerKeepAliveOptions
{
/// <summary>
/// When this mode is enabled the MQTT server will not close a connection when the
/// client is currently sending a (large) payload. This may lead to "dead" connections
/// When this mode is disabled the MQTT server will disconnect a client when the keep
/// alive timeout is reached even if the client is currently sending a (large) payload.
/// </summary>
public bool DisconnectClientWhenReadingPayload { get; set; }
/// <summary>
/// When this mode is enabled the MQTT server will not close a connection when the
/// client is currently sending a (large) payload. This may lead to "dead" connections
/// When this mode is disabled the MQTT server will disconnect a client when the keep
/// alive timeout is reached even if the client is currently sending a (large) payload.
/// </summary>
public bool DisconnectClientWhenReadingPayload { get; set; }
public TimeSpan MonitorInterval { get; set; } = TimeSpan.FromMilliseconds(500);
}
public TimeSpan MonitorInterval { get; set; } = TimeSpan.FromMilliseconds(500);
}
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Net;
using System.Net.Security;
using System.Security.Authentication;
@@ -10,207 +9,206 @@ using MQTTnet.Certificates;
using System.Security.Cryptography.X509Certificates;
// ReSharper disable UnusedMember.Global
namespace MQTTnet.Server
namespace MQTTnet.Server;
public class MqttServerOptionsBuilder
{
public class MqttServerOptionsBuilder
readonly MqttServerOptions _options = new();
public MqttServerOptions Build()
{
readonly MqttServerOptions _options = new MqttServerOptions();
return _options;
}
public MqttServerOptions Build()
public MqttServerOptionsBuilder WithClientCertificate(RemoteCertificateValidationCallback validationCallback = null, bool checkCertificateRevocation = false)
{
_options.TlsEndpointOptions.ClientCertificateRequired = true;
_options.TlsEndpointOptions.CheckCertificateRevocation = checkCertificateRevocation;
_options.TlsEndpointOptions.RemoteCertificateValidationCallback = validationCallback;
return this;
}
public MqttServerOptionsBuilder WithConnectionBacklog(int value)
{
_options.DefaultEndpointOptions.ConnectionBacklog = value;
_options.TlsEndpointOptions.ConnectionBacklog = value;
return this;
}
public MqttServerOptionsBuilder WithDefaultCommunicationTimeout(TimeSpan value)
{
_options.DefaultCommunicationTimeout = value;
return this;
}
public MqttServerOptionsBuilder WithDefaultEndpoint()
{
_options.DefaultEndpointOptions.IsEnabled = true;
return this;
}
public MqttServerOptionsBuilder WithDefaultEndpointBoundIPAddress(IPAddress value)
{
_options.DefaultEndpointOptions.BoundInterNetworkAddress = value ?? IPAddress.Any;
return this;
}
public MqttServerOptionsBuilder WithDefaultEndpointBoundIPV6Address(IPAddress value)
{
_options.DefaultEndpointOptions.BoundInterNetworkV6Address = value ?? IPAddress.Any;
return this;
}
public MqttServerOptionsBuilder WithDefaultEndpointPort(int value)
{
_options.DefaultEndpointOptions.Port = value;
return this;
}
public MqttServerOptionsBuilder WithDefaultEndpointReuseAddress()
{
_options.DefaultEndpointOptions.ReuseAddress = true;
return this;
}
public MqttServerOptionsBuilder WithEncryptedEndpoint()
{
_options.TlsEndpointOptions.IsEnabled = true;
return this;
}
public MqttServerOptionsBuilder WithEncryptedEndpointBoundIPAddress(IPAddress value)
{
_options.TlsEndpointOptions.BoundInterNetworkAddress = value;
return this;
}
public MqttServerOptionsBuilder WithEncryptedEndpointBoundIPV6Address(IPAddress value)
{
_options.TlsEndpointOptions.BoundInterNetworkV6Address = value;
return this;
}
public MqttServerOptionsBuilder WithEncryptedEndpointPort(int value)
{
_options.TlsEndpointOptions.Port = value;
return this;
}
public MqttServerOptionsBuilder WithEncryptionSslProtocol(SslProtocols value)
{
_options.TlsEndpointOptions.SslProtocol = value;
return this;
}
public MqttServerOptionsBuilder WithKeepAlive()
{
_options.DefaultEndpointOptions.KeepAlive = true;
_options.TlsEndpointOptions.KeepAlive = true;
return this;
}
public MqttServerOptionsBuilder WithMaxPendingMessagesPerClient(int value)
{
_options.MaxPendingMessagesPerClient = value;
return this;
}
public MqttServerOptionsBuilder WithPendingMessagesOverflowStrategy(MqttPendingMessagesOverflowStrategy value)
{
_options.PendingMessagesOverflowStrategy = value;
return this;
}
public MqttServerOptionsBuilder WithoutDefaultEndpoint()
{
_options.DefaultEndpointOptions.IsEnabled = false;
return this;
}
public MqttServerOptionsBuilder WithoutEncryptedEndpoint()
{
_options.TlsEndpointOptions.IsEnabled = false;
return this;
}
/// <summary>
/// Usually the MQTT packets can be send partially to improve memory allocations.
/// This is done by using multiple TCP packets or WebSocket frames etc.
/// Unfortunately not all clients do support this and will close the connection when receiving partial packets.
/// </summary>
public MqttServerOptionsBuilder WithoutPacketFragmentation()
{
_options.DefaultEndpointOptions.AllowPacketFragmentation = false;
_options.TlsEndpointOptions.AllowPacketFragmentation = false;
return this;
}
public MqttServerOptionsBuilder WithPersistentSessions(bool value = true)
{
_options.EnablePersistentSessions = value;
return this;
}
public MqttServerOptionsBuilder WithRemoteCertificateValidationCallback(RemoteCertificateValidationCallback value)
{
_options.TlsEndpointOptions.RemoteCertificateValidationCallback = value;
return this;
}
public MqttServerOptionsBuilder WithTcpKeepAliveInterval(int value)
{
_options.DefaultEndpointOptions.TcpKeepAliveInterval = value;
_options.TlsEndpointOptions.TcpKeepAliveInterval = value;
return this;
}
public MqttServerOptionsBuilder WithTcpKeepAliveRetryCount(int value)
{
_options.DefaultEndpointOptions.TcpKeepAliveRetryCount = value;
_options.TlsEndpointOptions.TcpKeepAliveRetryCount = value;
return this;
}
public MqttServerOptionsBuilder WithTcpKeepAliveTime(int value)
{
_options.DefaultEndpointOptions.TcpKeepAliveTime = value;
_options.TlsEndpointOptions.TcpKeepAliveTime = value;
return this;
}
public MqttServerOptionsBuilder WithTlsEndpointReuseAddress()
{
_options.TlsEndpointOptions.ReuseAddress = true;
return this;
}
public MqttServerOptionsBuilder WithEncryptionCertificate(byte[] value, IMqttServerCertificateCredentials credentials = null)
{
ArgumentNullException.ThrowIfNull(value);
_options.TlsEndpointOptions.CertificateProvider = new BlobCertificateProvider(value)
{
return _options;
}
Password = credentials?.Password
};
public MqttServerOptionsBuilder WithClientCertificate(RemoteCertificateValidationCallback validationCallback = null, bool checkCertificateRevocation = false)
{
_options.TlsEndpointOptions.ClientCertificateRequired = true;
_options.TlsEndpointOptions.CheckCertificateRevocation = checkCertificateRevocation;
_options.TlsEndpointOptions.RemoteCertificateValidationCallback = validationCallback;
return this;
}
return this;
}
public MqttServerOptionsBuilder WithConnectionBacklog(int value)
{
_options.DefaultEndpointOptions.ConnectionBacklog = value;
_options.TlsEndpointOptions.ConnectionBacklog = value;
return this;
}
public MqttServerOptionsBuilder WithEncryptionCertificate(X509Certificate2 certificate)
{
ArgumentNullException.ThrowIfNull(certificate);
public MqttServerOptionsBuilder WithDefaultCommunicationTimeout(TimeSpan value)
{
_options.DefaultCommunicationTimeout = value;
return this;
}
_options.TlsEndpointOptions.CertificateProvider = new X509CertificateProvider(certificate);
return this;
}
public MqttServerOptionsBuilder WithDefaultEndpoint()
{
_options.DefaultEndpointOptions.IsEnabled = true;
return this;
}
public MqttServerOptionsBuilder WithEncryptionCertificate(ICertificateProvider certificateProvider)
{
ArgumentNullException.ThrowIfNull(certificateProvider);
public MqttServerOptionsBuilder WithDefaultEndpointBoundIPAddress(IPAddress value)
{
_options.DefaultEndpointOptions.BoundInterNetworkAddress = value ?? IPAddress.Any;
return this;
}
_options.TlsEndpointOptions.CertificateProvider = certificateProvider;
public MqttServerOptionsBuilder WithDefaultEndpointBoundIPV6Address(IPAddress value)
{
_options.DefaultEndpointOptions.BoundInterNetworkV6Address = value ?? IPAddress.Any;
return this;
}
public MqttServerOptionsBuilder WithDefaultEndpointPort(int value)
{
_options.DefaultEndpointOptions.Port = value;
return this;
}
public MqttServerOptionsBuilder WithDefaultEndpointReuseAddress()
{
_options.DefaultEndpointOptions.ReuseAddress = true;
return this;
}
public MqttServerOptionsBuilder WithEncryptedEndpoint()
{
_options.TlsEndpointOptions.IsEnabled = true;
return this;
}
public MqttServerOptionsBuilder WithEncryptedEndpointBoundIPAddress(IPAddress value)
{
_options.TlsEndpointOptions.BoundInterNetworkAddress = value;
return this;
}
public MqttServerOptionsBuilder WithEncryptedEndpointBoundIPV6Address(IPAddress value)
{
_options.TlsEndpointOptions.BoundInterNetworkV6Address = value;
return this;
}
public MqttServerOptionsBuilder WithEncryptedEndpointPort(int value)
{
_options.TlsEndpointOptions.Port = value;
return this;
}
public MqttServerOptionsBuilder WithEncryptionSslProtocol(SslProtocols value)
{
_options.TlsEndpointOptions.SslProtocol = value;
return this;
}
public MqttServerOptionsBuilder WithKeepAlive()
{
_options.DefaultEndpointOptions.KeepAlive = true;
_options.TlsEndpointOptions.KeepAlive = true;
return this;
}
public MqttServerOptionsBuilder WithMaxPendingMessagesPerClient(int value)
{
_options.MaxPendingMessagesPerClient = value;
return this;
}
public MqttServerOptionsBuilder WithPendingMessagesOverflowStrategy(MqttPendingMessagesOverflowStrategy value)
{
_options.PendingMessagesOverflowStrategy = value;
return this;
}
public MqttServerOptionsBuilder WithoutDefaultEndpoint()
{
_options.DefaultEndpointOptions.IsEnabled = false;
return this;
}
public MqttServerOptionsBuilder WithoutEncryptedEndpoint()
{
_options.TlsEndpointOptions.IsEnabled = false;
return this;
}
/// <summary>
/// Usually the MQTT packets can be send partially to improve memory allocations.
/// This is done by using multiple TCP packets or WebSocket frames etc.
/// Unfortunately not all clients do support this and will close the connection when receiving partial packets.
/// </summary>
public MqttServerOptionsBuilder WithoutPacketFragmentation()
{
_options.DefaultEndpointOptions.AllowPacketFragmentation = false;
_options.TlsEndpointOptions.AllowPacketFragmentation = false;
return this;
}
public MqttServerOptionsBuilder WithPersistentSessions(bool value = true)
{
_options.EnablePersistentSessions = value;
return this;
}
public MqttServerOptionsBuilder WithRemoteCertificateValidationCallback(RemoteCertificateValidationCallback value)
{
_options.TlsEndpointOptions.RemoteCertificateValidationCallback = value;
return this;
}
public MqttServerOptionsBuilder WithTcpKeepAliveInterval(int value)
{
_options.DefaultEndpointOptions.TcpKeepAliveInterval = value;
_options.TlsEndpointOptions.TcpKeepAliveInterval = value;
return this;
}
public MqttServerOptionsBuilder WithTcpKeepAliveRetryCount(int value)
{
_options.DefaultEndpointOptions.TcpKeepAliveRetryCount = value;
_options.TlsEndpointOptions.TcpKeepAliveRetryCount = value;
return this;
}
public MqttServerOptionsBuilder WithTcpKeepAliveTime(int value)
{
_options.DefaultEndpointOptions.TcpKeepAliveTime = value;
_options.TlsEndpointOptions.TcpKeepAliveTime = value;
return this;
}
public MqttServerOptionsBuilder WithTlsEndpointReuseAddress()
{
_options.TlsEndpointOptions.ReuseAddress = true;
return this;
}
public MqttServerOptionsBuilder WithEncryptionCertificate(byte[] value, IMqttServerCertificateCredentials credentials = null)
{
ArgumentNullException.ThrowIfNull(value);
_options.TlsEndpointOptions.CertificateProvider = new BlobCertificateProvider(value)
{
Password = credentials?.Password
};
return this;
}
public MqttServerOptionsBuilder WithEncryptionCertificate(X509Certificate2 certificate)
{
ArgumentNullException.ThrowIfNull(certificate);
_options.TlsEndpointOptions.CertificateProvider = new X509CertificateProvider(certificate);
return this;
}
public MqttServerOptionsBuilder WithEncryptionCertificate(ICertificateProvider certificateProvider)
{
ArgumentNullException.ThrowIfNull(certificateProvider);
_options.TlsEndpointOptions.CertificateProvider = certificateProvider;
return this;
}
return this;
}
}
@@ -5,59 +5,58 @@
using System.Net;
using System.Net.Sockets;
namespace MQTTnet.Server
namespace MQTTnet.Server;
public abstract class MqttServerTcpEndpointBaseOptions
{
public abstract class MqttServerTcpEndpointBaseOptions
{
public bool IsEnabled { get; set; }
public bool IsEnabled { get; set; }
public int Port { get; set; }
public int Port { get; set; }
public int ConnectionBacklog { get; set; } = 100;
public int ConnectionBacklog { get; set; } = 100;
public bool NoDelay { get; set; } = true;
public bool NoDelay { get; set; } = true;
/// <summary>
/// Gets or sets whether the sockets keep alive feature should be used.
/// The value _null_ indicates that the OS and framework defaults should be used.
/// </summary>
public bool? KeepAlive { get; set; }
/// <summary>
/// Gets or sets whether the sockets keep alive feature should be used.
/// The value _null_ indicates that the OS and framework defaults should be used.
/// </summary>
public bool? KeepAlive { get; set; }
/// <summary>
/// Usually the MQTT packets can be send partially. This is done by using multiple TCP packets
/// or WebSocket frames etc. Unfortunately not all clients do support this feature and
/// will close the connection when receiving such packets. If such clients are connecting to this
/// server the flag must be set to _false_.
/// </summary>
public bool AllowPacketFragmentation { get; set; } = true;
/// <summary>
/// Usually the MQTT packets can be send partially. This is done by using multiple TCP packets
/// or WebSocket frames etc. Unfortunately not all clients do support this feature and
/// will close the connection when receiving such packets. If such clients are connecting to this
/// server the flag must be set to _false_.
/// </summary>
public bool AllowPacketFragmentation { get; set; } = true;
/// <summary>
/// Gets or sets the TCP keep alive interval.
/// The value _null_ indicates that the OS and framework defaults should be used.
/// </summary>
public int? TcpKeepAliveInterval { get; set; }
/// <summary>
/// Gets or sets the TCP keep alive interval.
/// The value _null_ indicates that the OS and framework defaults should be used.
/// </summary>
public int? TcpKeepAliveInterval { get; set; }
/// <summary>
/// Gets or sets the TCP keep alive retry count.
/// The value _null_ indicates that the OS and framework defaults should be used.
/// </summary>
public int? TcpKeepAliveRetryCount { get; set; }
/// <summary>
/// Gets or sets the TCP keep alive retry count.
/// The value _null_ indicates that the OS and framework defaults should be used.
/// </summary>
public int? TcpKeepAliveRetryCount { get; set; }
/// <summary>
/// Gets or sets the TCP keep alive time.
/// The value _null_ indicates that the OS and framework defaults should be used.
/// </summary>
public int? TcpKeepAliveTime { get; set; }
/// <summary>
/// Gets or sets the TCP keep alive time.
/// The value _null_ indicates that the OS and framework defaults should be used.
/// </summary>
public int? TcpKeepAliveTime { get; set; }
public LingerOption LingerState { get; set; } = new LingerOption(true, 0);
public LingerOption LingerState { get; set; } = new LingerOption(true, 0);
public IPAddress BoundInterNetworkAddress { get; set; } = IPAddress.Any;
public IPAddress BoundInterNetworkAddress { get; set; } = IPAddress.Any;
public IPAddress BoundInterNetworkV6Address { get; set; } = IPAddress.IPv6Any;
public IPAddress BoundInterNetworkV6Address { get; set; } = IPAddress.IPv6Any;
/// <summary>
/// This requires admin permissions on Linux.
/// </summary>
public bool ReuseAddress { get; set; }
}
/// <summary>
/// This requires admin permissions on Linux.
/// </summary>
public bool ReuseAddress { get; set; }
}
@@ -2,13 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace MQTTnet.Server
namespace MQTTnet.Server;
public class MqttServerTcpEndpointOptions : MqttServerTcpEndpointBaseOptions
{
public class MqttServerTcpEndpointOptions : MqttServerTcpEndpointBaseOptions
public MqttServerTcpEndpointOptions()
{
public MqttServerTcpEndpointOptions()
{
Port = 1883;
}
Port = 1883;
}
}
}
@@ -5,29 +5,28 @@
using System.Security.Authentication;
using MQTTnet.Certificates;
namespace MQTTnet.Server
namespace MQTTnet.Server;
public sealed class MqttServerTlsTcpEndpointOptions : MqttServerTcpEndpointBaseOptions
{
public sealed class MqttServerTlsTcpEndpointOptions : MqttServerTcpEndpointBaseOptions
public MqttServerTlsTcpEndpointOptions()
{
public MqttServerTlsTcpEndpointOptions()
{
Port = 8883;
}
public System.Net.Security.RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; }
public ICertificateProvider CertificateProvider { get; set; }
public bool ClientCertificateRequired { get; set; }
public bool CheckCertificateRevocation { get; set; }
/// <summary>
/// The default value is SslProtocols.None, which allows the operating system to choose the best protocol to use, and to block protocols that are not secure.
/// </summary>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/api/system.security.authentication.sslprotocols">SslProtocols</seealso>
public SslProtocols SslProtocol { get; set; } = SslProtocols.None;
public System.Net.Security.CipherSuitesPolicy CipherSuitesPolicy { get; set; }
Port = 8883;
}
}
public System.Net.Security.RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; }
public ICertificateProvider CertificateProvider { get; set; }
public bool ClientCertificateRequired { get; set; }
public bool CheckCertificateRevocation { get; set; }
/// <summary>
/// The default value is SslProtocols.None, which allows the operating system to choose the best protocol to use, and to block protocols that are not secure.
/// </summary>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/api/system.security.authentication.sslprotocols">SslProtocols</seealso>
public SslProtocols SslProtocol { get; set; } = SslProtocols.None;
public System.Net.Security.CipherSuitesPolicy CipherSuitesPolicy { get; set; }
}