diff --git a/src/Tgstation.Server.Api/Models/ErrorCode.cs b/src/Tgstation.Server.Api/Models/ErrorCode.cs
index f36699047d..7b34459278 100644
--- a/src/Tgstation.Server.Api/Models/ErrorCode.cs
+++ b/src/Tgstation.Server.Api/Models/ErrorCode.cs
@@ -477,5 +477,11 @@ namespace Tgstation.Server.Api.Models
///
[Description("Cannot start DreamDaemon headless with the BYOND pager running!")]
DeploymentPagerRunning,
+
+ ///
+ /// Could not bind to port we wanted to launch DreamDaemon on.
+ ///
+ [Description("Could not bind to requested DreamDaemon port! Is there another service running on that port?")]
+ DreamDaemonPortInUse,
}
}
\ No newline at end of file
diff --git a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
index 8f5bb7db31..c397bfe4d2 100644
--- a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
+++ b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
@@ -3,6 +3,8 @@ using Microsoft.Extensions.Logging;
using System;
using System.Globalization;
using System.Linq;
+using System.Net;
+using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
@@ -201,6 +203,7 @@ namespace Tgstation.Server.Host.Components.Session
if (launchParameters.SecurityLevel == DreamDaemonSecurity.Trusted)
await byondLock.TrustDmbPath(ioManager.ConcatPath(basePath, dmbProvider.DmbName), cancellationToken).ConfigureAwait(false);
+ PortBindTest(portToUse.Value);
await CheckPagerIsNotRunning(cancellationToken).ConfigureAwait(false);
var accessIdentifier = cryptographySuite.GetSecureString();
@@ -214,7 +217,7 @@ namespace Tgstation.Server.Host.Components.Session
// important to run on all ports to allow port changing
var arguments = String.Format(CultureInfo.InvariantCulture, "{0} -port {1} -ports 1-65535 {2}-close -{3} -{4} -public -params \"{5}\"",
dmbProvider.DmbName,
- primaryPort ? launchParameters.PrimaryPort : launchParameters.SecondaryPort,
+ portToUse,
launchParameters.AllowWebClient.Value ? "-webclient " : String.Empty,
SecurityWord(launchParameters.SecurityLevel.Value),
visibility,
@@ -422,5 +425,23 @@ namespace Tgstation.Server.Host.Components.Session
if(otherUserName.Equals(ourUserName, StringComparison.Ordinal))
throw new JobException(ErrorCode.DeploymentPagerRunning);
}
+
+ ///
+ /// Check if a given can be bound to.
+ ///
+ /// The port number to test.
+ void PortBindTest(ushort port)
+ {
+ using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+
+ try
+ {
+ socket.Bind(new IPEndPoint(IPAddress.Loopback, port));
+ }
+ catch (Exception ex)
+ {
+ throw new JobException(ErrorCode.DreamDaemonPortInUse, ex);
+ }
+ }
}
}