diff --git a/.gitignore b/.gitignore index 6a93dd2c85..07c085a82d 100644 --- a/.gitignore +++ b/.gitignore @@ -56,5 +56,8 @@ Barotrauma/**/GameAnalyticsKeys.cs Deploy/DeployAll/PrivateKey.* .github/ISSUE_TEMPLATE/release-checklist.md -#Rider +# Rider *.DotSettings.user + +# VSCode +.vscode/ diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/DnsSrvResolver.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/DnsSrvResolver.cs new file mode 100644 index 0000000000..314ffd681b --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/DnsSrvResolver.cs @@ -0,0 +1,47 @@ +#nullable enable +using DnsClient; +using System.Linq; + +namespace Barotrauma.Networking +{ + internal static class DnsSrvResolver + { + private static readonly LookupClient lookup = new(); + private const string Service = "_barotrauma"; + private const string Proto = "_udp"; + + /// Returns true if a SRV record was found. + public static bool TryResolve(string host, string service, string proto, out string targetHost, out int targetPort) + { + targetHost = ""; + targetPort = 0; + var queryName = $"{service}.{proto}.{host.TrimEnd('.')}"; + + IDnsQueryResponse result; + try + { + result = lookup.Query(queryName, QueryType.SRV); + } + catch + { + return false; + } + + var record = result.Answers + .SrvRecords() + .OrderBy(r => r.Priority) + .ThenByDescending(r => r.Weight) + .FirstOrDefault(); + if (record is null) return false; + + targetHost = record.Target.Value.TrimEnd('.'); + targetPort = record.Port; + + return true; + } + + /// Returns true if a SRV record was found. + public static bool TryResolve(string host, out string targetHost, out int targetPort) + => TryResolve(host, Service, Proto, out targetHost, out targetPort); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs index 8b50a608c0..4b070a90cf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/Primitives/Endpoint/LidgrenEndpoint.cs @@ -38,6 +38,15 @@ public static Option ParseFromWithHostNameCheck(string endpoint port = int.TryParse(split[1], out var tmpPort) ? tmpPort : port; } + // SRV look-up: only when the user did not specify a port + if (port == NetConfig.DefaultPort + && tryParseHostName + && DnsSrvResolver.TryResolve(hostName, out var srvHost, out var srvPort)) + { + hostName = srvHost; + port = srvPort; + } + if (LidgrenAddress.Parse(hostName).TryUnwrap(out var adr) || (tryParseHostName && LidgrenAddress.ParseHostName(hostName).TryUnwrap(out adr))) { diff --git a/Barotrauma/BarotraumaTest/DnsSrvResolverTests.cs b/Barotrauma/BarotraumaTest/DnsSrvResolverTests.cs new file mode 100644 index 0000000000..6d9d937f1e --- /dev/null +++ b/Barotrauma/BarotraumaTest/DnsSrvResolverTests.cs @@ -0,0 +1,26 @@ +// Add extern alias to pick up WindowsClient reference +extern alias Client; + +using System; +using Xunit; + +namespace WindowsTest +{ + public class DnsSrvResolverTests + { + [Fact] + public void DefaultTryResolve_NoSrvRecord_ReturnsFalse() + => Assert.False(Client::Barotrauma.Networking.DnsSrvResolver.TryResolve("example.com", out _, out _)); + + [Fact] + public void OverloadedTryResolve_XmppJabber_ReturnsTrue() + { + // jabber.org provides a stable XMPP server SRV record + bool ok = Client::Barotrauma.Networking.DnsSrvResolver.TryResolve( + "jabber.org", "_xmpp-server", "_tcp", out var host, out var port); + Assert.True(ok, "Expected SRV record for _xmpp-server._tcp.jabber.org"); + Assert.EndsWith("jabber.org", host); + Assert.True(port > 0); + } + } +} \ No newline at end of file diff --git a/Libraries/BarotraumaLibs/BarotraumaCore/BarotraumaCore.csproj b/Libraries/BarotraumaLibs/BarotraumaCore/BarotraumaCore.csproj index 693263fbca..97709ffdc4 100644 --- a/Libraries/BarotraumaLibs/BarotraumaCore/BarotraumaCore.csproj +++ b/Libraries/BarotraumaLibs/BarotraumaCore/BarotraumaCore.csproj @@ -23,6 +23,7 @@ +