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 @@
+