Fixed: Don't disable IPv6 in IPv6-only Environment

(cherry picked from commit 13af6f57796e54c3949cf340e03f020e6f8575c4)
This commit is contained in:
Louis R 2024-03-03 06:20:36 +01:00 committed by servarr
parent 0ca0f68af1
commit 50bb54ff60
1 changed files with 16 additions and 4 deletions

View File

@ -1,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.NetworkInformation;
using System.Net.Security; using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
@ -249,6 +251,18 @@ namespace NzbDrone.Common.Http.Dispatchers
return _credentialCache.Get("credentialCache", () => new CredentialCache()); return _credentialCache.Get("credentialCache", () => new CredentialCache());
} }
private static bool HasRoutableIPv4Address()
{
// Get all IPv4 addresses from all interfaces and return true if there are any with non-loopback addresses
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
return networkInterfaces.Any(ni =>
ni.OperationalStatus == OperationalStatus.Up &&
ni.GetIPProperties().UnicastAddresses.Any(ip =>
ip.Address.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.IsLoopback(ip.Address)));
}
private static async ValueTask<Stream> onConnect(SocketsHttpConnectionContext context, CancellationToken cancellationToken) private static 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.
@ -272,10 +286,8 @@ namespace NzbDrone.Common.Http.Dispatchers
} }
catch catch
{ {
// very naively fallback to ipv4 permanently for this execution based on the response of the first connection attempt. // Do not retry IPv6 if a routable IPv4 address is available, otherwise continue to attempt IPv6 connections.
// note that this may cause users to eventually get switched to ipv4 (on a random failure when they are switching networks, for instance) useIPv6 = !HasRoutableIPv4Address();
// but in the interest of keeping this implementation simple, this is acceptable.
useIPv6 = false;
} }
finally finally
{ {