mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-21 04:03:05 +08:00
Refactor proxy usage and support. Refactor TLS parameter usage.
This commit is contained in:
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Security;
|
|
||||||
using System.Security.Authentication;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using MQTTnet.Serializer;
|
using MQTTnet.Serializer;
|
||||||
|
|
||||||
namespace MQTTnet.Client
|
namespace MQTTnet.Client
|
||||||
@@ -10,10 +7,10 @@ namespace MQTTnet.Client
|
|||||||
public class MqttClientOptionsBuilder
|
public class MqttClientOptionsBuilder
|
||||||
{
|
{
|
||||||
private readonly MqttClientOptions _options = new MqttClientOptions();
|
private readonly MqttClientOptions _options = new MqttClientOptions();
|
||||||
|
|
||||||
private MqttClientTcpOptions _tcpOptions;
|
private MqttClientTcpOptions _tcpOptions;
|
||||||
private MqttClientWebSocketOptions _webSocketOptions;
|
private MqttClientWebSocketOptions _webSocketOptions;
|
||||||
|
private MqttClientOptionsBuilderTlsParameters _tlsParameters;
|
||||||
private MqttClientTlsOptions _tlsOptions;
|
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithProtocolVersion(MqttProtocolVersion value)
|
public MqttClientOptionsBuilder WithProtocolVersion(MqttProtocolVersion value)
|
||||||
{
|
{
|
||||||
@@ -88,7 +85,7 @@ namespace MQTTnet.Client
|
|||||||
throw new InvalidOperationException("A WebSocket channel must be set if MqttClientWebSocketProxy is configured.");
|
throw new InvalidOperationException("A WebSocket channel must be set if MqttClientWebSocketProxy is configured.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_webSocketOptions.MqttClientWebSocketProxy = new MqttClientWebSocketProxyOptions
|
_webSocketOptions.ProxyOptions = new MqttClientWebSocketProxyOptions
|
||||||
{
|
{
|
||||||
Address = address,
|
Address = address,
|
||||||
Username = username,
|
Username = username,
|
||||||
@@ -112,86 +109,66 @@ namespace MQTTnet.Client
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MqttClientOptionsBuilder WithTls(MqttClientOptionsBuilderTlsParameters parameters)
|
||||||
|
{
|
||||||
|
_tlsParameters = parameters ?? throw new ArgumentNullException(nameof(parameters));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithTls()
|
public MqttClientOptionsBuilder WithTls()
|
||||||
{
|
{
|
||||||
return WithTls(null);
|
return WithTls(new MqttClientOptionsBuilderTlsParameters { UseTls = true });
|
||||||
}
|
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithTls(Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback)
|
|
||||||
{
|
|
||||||
return WithTls(SslProtocols.None, certificateValidationCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithTls(SslProtocols sslProtocol,
|
|
||||||
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
|
||||||
{
|
|
||||||
return WithTls(new byte[][] { }, sslProtocol, certificateValidationCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithTls(byte[][] certificates,
|
|
||||||
SslProtocols sslProtocol = SslProtocols.Tls12,
|
|
||||||
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
|
||||||
{
|
|
||||||
return WithTls(false, certificates, sslProtocol, certificateValidationCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithTls(bool ignoreCertificateRevocationErrors,
|
|
||||||
byte[][] certificates = null,
|
|
||||||
SslProtocols sslProtocol = SslProtocols.Tls12,
|
|
||||||
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
|
||||||
{
|
|
||||||
return WithTls(false, ignoreCertificateRevocationErrors, certificates, sslProtocol, certificateValidationCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttClientOptionsBuilder WithTls(bool ignoreCertificateChainErrors,
|
|
||||||
bool ignoreCertificateRevocationErrors = false,
|
|
||||||
byte[][] certificates = null,
|
|
||||||
SslProtocols sslProtocol = SslProtocols.Tls12,
|
|
||||||
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
|
||||||
{
|
|
||||||
return WithTls(false, ignoreCertificateChainErrors, ignoreCertificateRevocationErrors, certificates, sslProtocol, certificateValidationCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use method _WithTlps_ which accepts the _MqttClientOptionsBuilderTlsParameters_.")]
|
||||||
public MqttClientOptionsBuilder WithTls(
|
public MqttClientOptionsBuilder WithTls(
|
||||||
bool allowUntrustedCertificates,
|
bool allowUntrustedCertificates = false,
|
||||||
bool ignoreCertificateChainErrors = false,
|
bool ignoreCertificateChainErrors = false,
|
||||||
bool ignoreCertificateRevocationErrors = false,
|
bool ignoreCertificateRevocationErrors = false,
|
||||||
byte[][] certificates = null,
|
params byte[][] certificates)
|
||||||
SslProtocols sslProtocol = SslProtocols.Tls12,
|
|
||||||
Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> certificateValidationCallback = null)
|
|
||||||
{
|
{
|
||||||
_tlsOptions = new MqttClientTlsOptions
|
_tlsParameters = new MqttClientOptionsBuilderTlsParameters
|
||||||
{
|
{
|
||||||
UseTls = true,
|
UseTls = true,
|
||||||
AllowUntrustedCertificates = allowUntrustedCertificates,
|
AllowUntrustedCertificates = allowUntrustedCertificates,
|
||||||
IgnoreCertificateChainErrors = ignoreCertificateChainErrors,
|
IgnoreCertificateChainErrors = ignoreCertificateChainErrors,
|
||||||
IgnoreCertificateRevocationErrors = ignoreCertificateRevocationErrors,
|
IgnoreCertificateRevocationErrors = ignoreCertificateRevocationErrors,
|
||||||
Certificates = certificates?.ToList(),
|
Certificates = certificates?.ToList()
|
||||||
SslProtocol = sslProtocol,
|
|
||||||
CertificateValidationCallback = certificateValidationCallback
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IMqttClientOptions Build()
|
public IMqttClientOptions Build()
|
||||||
{
|
{
|
||||||
if (_tlsOptions != null)
|
if (_tlsParameters != null)
|
||||||
{
|
{
|
||||||
if (_tcpOptions == null && _webSocketOptions == null)
|
if (_tcpOptions == null && _webSocketOptions == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("A channel (TCP or WebSocket) must be set if TLS is configured.");
|
throw new InvalidOperationException("A channel (TCP or WebSocket) must be set if TLS is configured.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_tcpOptions != null)
|
if (_tlsParameters?.UseTls == true)
|
||||||
{
|
{
|
||||||
_tcpOptions.TlsOptions = _tlsOptions;
|
var tlsOptions = new MqttClientTlsOptions
|
||||||
}
|
{
|
||||||
else if (_webSocketOptions != null)
|
UseTls = true,
|
||||||
{
|
SslProtocol = _tlsParameters.SslProtocol,
|
||||||
_webSocketOptions.TlsOptions = _tlsOptions;
|
AllowUntrustedCertificates = _tlsParameters.AllowUntrustedCertificates,
|
||||||
|
Certificates = _tlsParameters.Certificates?.Select(c => c.ToArray()).ToList(),
|
||||||
|
CertificateValidationCallback = _tlsParameters.CertificateValidationCallback,
|
||||||
|
IgnoreCertificateChainErrors = _tlsParameters.IgnoreCertificateChainErrors,
|
||||||
|
IgnoreCertificateRevocationErrors = _tlsParameters.IgnoreCertificateRevocationErrors
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_tcpOptions != null)
|
||||||
|
{
|
||||||
|
_tcpOptions.TlsOptions = tlsOptions;
|
||||||
|
}
|
||||||
|
else if (_webSocketOptions != null)
|
||||||
|
{
|
||||||
|
_webSocketOptions.TlsOptions = tlsOptions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
namespace MQTTnet.Client
|
||||||
|
{
|
||||||
|
public class MqttClientOptionsBuilderTlsParameters
|
||||||
|
{
|
||||||
|
public bool UseTls { get; set; }
|
||||||
|
|
||||||
|
public Func<X509Certificate, X509Chain, SslPolicyErrors, IMqttClientOptions, bool> CertificateValidationCallback
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12;
|
||||||
|
|
||||||
|
public IEnumerable<IEnumerable<byte>> Certificates { get; set; }
|
||||||
|
|
||||||
|
public bool AllowUntrustedCertificates { get; set; }
|
||||||
|
|
||||||
|
public bool IgnoreCertificateChainErrors { get; set; }
|
||||||
|
|
||||||
|
public bool IgnoreCertificateRevocationErrors { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,9 +13,7 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
public CookieContainer CookieContainer { get; set; }
|
public CookieContainer CookieContainer { get; set; }
|
||||||
|
|
||||||
#if NET452 || NET461
|
public MqttClientWebSocketProxyOptions ProxyOptions { get; set; }
|
||||||
public MqttClientWebSocketProxyOptions MqttClientWebSocketProxy { get; set; } = new MqttClientWebSocketProxyOptions();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
#if NET452 || NET461
|
namespace MQTTnet.Client
|
||||||
|
|
||||||
namespace MQTTnet.Client
|
|
||||||
{
|
{
|
||||||
public class MqttClientWebSocketProxyOptions
|
public class MqttClientWebSocketProxyOptions
|
||||||
{
|
{
|
||||||
@@ -16,6 +14,4 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
public string[] BypassList { get; set; }
|
public string[] BypassList { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -6,10 +7,6 @@ using System.Threading.Tasks;
|
|||||||
using MQTTnet.Channel;
|
using MQTTnet.Channel;
|
||||||
using MQTTnet.Client;
|
using MQTTnet.Client;
|
||||||
|
|
||||||
#if NET452 || NET461
|
|
||||||
using System.Net;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace MQTTnet.Implementations
|
namespace MQTTnet.Implementations
|
||||||
{
|
{
|
||||||
public class MqttWebSocketChannel : IMqttChannel
|
public class MqttWebSocketChannel : IMqttChannel
|
||||||
@@ -49,25 +46,10 @@ namespace MQTTnet.Implementations
|
|||||||
|
|
||||||
var clientWebSocket = new ClientWebSocket();
|
var clientWebSocket = new ClientWebSocket();
|
||||||
|
|
||||||
#if NET452 || NET461
|
if (_options.ProxyOptions != null)
|
||||||
// use proxy if we have an address
|
|
||||||
if (string.IsNullOrEmpty(_options.MqttClientWebSocketProxy.Address) == false)
|
|
||||||
{
|
{
|
||||||
var proxyUri = new Uri(_options.MqttClientWebSocketProxy.Address);
|
clientWebSocket.Options.Proxy = CreateProxy();
|
||||||
|
|
||||||
// use proxy credentials if we have them
|
|
||||||
if (string.IsNullOrEmpty(_options.MqttClientWebSocketProxy.Username) == false && string.IsNullOrEmpty(_options.MqttClientWebSocketProxy.Password) == false)
|
|
||||||
{
|
|
||||||
var credentials = new NetworkCredential(_options.MqttClientWebSocketProxy.Username, _options.MqttClientWebSocketProxy.Password, _options.MqttClientWebSocketProxy.Domain);
|
|
||||||
clientWebSocket.Options.Proxy = new WebProxy(proxyUri, _options.MqttClientWebSocketProxy.BypassOnLocal, _options.MqttClientWebSocketProxy.BypassList, credentials);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// use proxy without credentials
|
|
||||||
clientWebSocket.Options.Proxy = new WebProxy(proxyUri, _options.MqttClientWebSocketProxy.BypassOnLocal, _options.MqttClientWebSocketProxy.BypassList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (_options.RequestHeaders != null)
|
if (_options.RequestHeaders != null)
|
||||||
{
|
{
|
||||||
@@ -156,5 +138,31 @@ namespace MQTTnet.Implementations
|
|||||||
_webSocket = null;
|
_webSocket = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IWebProxy CreateProxy()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_options.ProxyOptions?.Address))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WINDOWS_UWP
|
||||||
|
throw new NotSupportedException("Proxies are not supported in UWP.");
|
||||||
|
#elif NETSTANDARD1_3
|
||||||
|
throw new NotSupportedException("Proxies are not supported in netstandard 1.3.");
|
||||||
|
#else
|
||||||
|
var proxyUri = new Uri(_options.ProxyOptions.Address);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_options.ProxyOptions.Username) && !string.IsNullOrEmpty(_options.ProxyOptions.Password))
|
||||||
|
{
|
||||||
|
var credentials =
|
||||||
|
new NetworkCredential(_options.ProxyOptions.Username, _options.ProxyOptions.Password, _options.ProxyOptions.Domain);
|
||||||
|
|
||||||
|
return new WebProxy(proxyUri, _options.ProxyOptions.BypassOnLocal, _options.ProxyOptions.BypassList, credentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WebProxy(proxyUri, _options.ProxyOptions.BypassOnLocal, _options.ProxyOptions.BypassList);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user