Fixed: Exceptions when checking for routable IPv4 addresses
This commit is contained in:
parent
7353fe479d
commit
060b789bc6
|
@ -9,6 +9,7 @@ using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http.Proxy;
|
using NzbDrone.Common.Http.Proxy;
|
||||||
|
@ -30,11 +31,14 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
private readonly ICached<System.Net.Http.HttpClient> _httpClientCache;
|
private readonly ICached<System.Net.Http.HttpClient> _httpClientCache;
|
||||||
private readonly ICached<CredentialCache> _credentialCache;
|
private readonly ICached<CredentialCache> _credentialCache;
|
||||||
|
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public ManagedHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider,
|
public ManagedHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider,
|
||||||
ICreateManagedWebProxy createManagedWebProxy,
|
ICreateManagedWebProxy createManagedWebProxy,
|
||||||
ICertificateValidationService certificateValidationService,
|
ICertificateValidationService certificateValidationService,
|
||||||
IUserAgentBuilder userAgentBuilder,
|
IUserAgentBuilder userAgentBuilder,
|
||||||
ICacheManager cacheManager)
|
ICacheManager cacheManager,
|
||||||
|
Logger logger)
|
||||||
{
|
{
|
||||||
_proxySettingsProvider = proxySettingsProvider;
|
_proxySettingsProvider = proxySettingsProvider;
|
||||||
_createManagedWebProxy = createManagedWebProxy;
|
_createManagedWebProxy = createManagedWebProxy;
|
||||||
|
@ -43,6 +47,8 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
|
|
||||||
_httpClientCache = cacheManager.GetCache<System.Net.Http.HttpClient>(typeof(ManagedHttpDispatcher));
|
_httpClientCache = cacheManager.GetCache<System.Net.Http.HttpClient>(typeof(ManagedHttpDispatcher));
|
||||||
_credentialCache = cacheManager.GetCache<CredentialCache>(typeof(ManagedHttpDispatcher), "credentialcache");
|
_credentialCache = cacheManager.GetCache<CredentialCache>(typeof(ManagedHttpDispatcher), "credentialcache");
|
||||||
|
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HttpResponse> GetResponseAsync(HttpRequest request, CookieContainer cookies)
|
public async Task<HttpResponse> GetResponseAsync(HttpRequest request, CookieContainer cookies)
|
||||||
|
@ -249,9 +255,11 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
return _credentialCache.Get("credentialCache", () => new CredentialCache());
|
return _credentialCache.Get("credentialCache", () => new CredentialCache());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasRoutableIPv4Address()
|
private bool HasRoutableIPv4Address()
|
||||||
{
|
{
|
||||||
// Get all IPv4 addresses from all interfaces and return true if there are any with non-loopback addresses
|
// Get all IPv4 addresses from all interfaces and return true if there are any with non-loopback addresses
|
||||||
|
try
|
||||||
|
{
|
||||||
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
|
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||||
|
|
||||||
return networkInterfaces.Any(ni =>
|
return networkInterfaces.Any(ni =>
|
||||||
|
@ -260,8 +268,14 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
ip.Address.AddressFamily == AddressFamily.InterNetwork &&
|
ip.Address.AddressFamily == AddressFamily.InterNetwork &&
|
||||||
!IPAddress.IsLoopback(ip.Address)));
|
!IPAddress.IsLoopback(ip.Address)));
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Debug(e, "Caught exception while GetAllNetworkInterfaces assuming IPv4 connectivity: {0}", e.Message);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static async ValueTask<Stream> onConnect(SocketsHttpConnectionContext context, CancellationToken cancellationToken)
|
private async ValueTask<Stream> onConnect(SocketsHttpConnectionContext context, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Until .NET supports an implementation of Happy Eyeballs (https://tools.ietf.org/html/rfc8305#section-2), let's make IPv4 fallback work in a simple way.
|
// Until .NET supports an implementation of Happy Eyeballs (https://tools.ietf.org/html/rfc8305#section-2), let's make IPv4 fallback work in a simple way.
|
||||||
// This issue is being tracked at https://github.com/dotnet/runtime/issues/26177 and expected to be fixed in .NET 6.
|
// This issue is being tracked at https://github.com/dotnet/runtime/issues/26177 and expected to be fixed in .NET 6.
|
||||||
|
@ -285,7 +299,9 @@ namespace NzbDrone.Common.Http.Dispatchers
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// Do not retry IPv6 if a routable IPv4 address is available, otherwise continue to attempt IPv6 connections.
|
// Do not retry IPv6 if a routable IPv4 address is available, otherwise continue to attempt IPv6 connections.
|
||||||
useIPv6 = !HasRoutableIPv4Address();
|
var routableIPv4 = HasRoutableIPv4Address();
|
||||||
|
_logger.Info("IPv4 is available: {0}, IPv6 will be {1}", routableIPv4, routableIPv4 ? "disabled" : "left enabled");
|
||||||
|
useIPv6 = !routableIPv4;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.Framework
|
||||||
Mocker.SetConstant<IHttpProxySettingsProvider>(new HttpProxySettingsProvider(Mocker.Resolve<ConfigService>()));
|
Mocker.SetConstant<IHttpProxySettingsProvider>(new HttpProxySettingsProvider(Mocker.Resolve<ConfigService>()));
|
||||||
Mocker.SetConstant<ICreateManagedWebProxy>(new ManagedWebProxyFactory(Mocker.Resolve<CacheManager>()));
|
Mocker.SetConstant<ICreateManagedWebProxy>(new ManagedWebProxyFactory(Mocker.Resolve<CacheManager>()));
|
||||||
Mocker.SetConstant<ICertificateValidationService>(new X509CertificateValidationService(Mocker.Resolve<ConfigService>(), TestLogger));
|
Mocker.SetConstant<ICertificateValidationService>(new X509CertificateValidationService(Mocker.Resolve<ConfigService>(), TestLogger));
|
||||||
Mocker.SetConstant<IHttpDispatcher>(new ManagedHttpDispatcher(Mocker.Resolve<IHttpProxySettingsProvider>(), Mocker.Resolve<ICreateManagedWebProxy>(), Mocker.Resolve<ICertificateValidationService>(), Mocker.Resolve<UserAgentBuilder>(), Mocker.Resolve<CacheManager>()));
|
Mocker.SetConstant<IHttpDispatcher>(new ManagedHttpDispatcher(Mocker.Resolve<IHttpProxySettingsProvider>(), Mocker.Resolve<ICreateManagedWebProxy>(), Mocker.Resolve<ICertificateValidationService>(), Mocker.Resolve<UserAgentBuilder>(), Mocker.Resolve<CacheManager>(), TestLogger));
|
||||||
Mocker.SetConstant<IHttpClient>(new HttpClient(Array.Empty<IHttpRequestInterceptor>(), Mocker.Resolve<CacheManager>(), Mocker.Resolve<RateLimitService>(), Mocker.Resolve<IHttpDispatcher>(), TestLogger));
|
Mocker.SetConstant<IHttpClient>(new HttpClient(Array.Empty<IHttpRequestInterceptor>(), Mocker.Resolve<CacheManager>(), Mocker.Resolve<RateLimitService>(), Mocker.Resolve<IHttpDispatcher>(), TestLogger));
|
||||||
Mocker.SetConstant<ISonarrCloudRequestBuilder>(new SonarrCloudRequestBuilder());
|
Mocker.SetConstant<ISonarrCloudRequestBuilder>(new SonarrCloudRequestBuilder());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue