1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
4 using Newtonsoft.Json.Serialization;
8 using System.Runtime.InteropServices;
11 using System.Threading.Tasks;
88 switch (securityLevel)
97 throw new ArgumentOutOfRangeException(nameof(securityLevel), securityLevel, String.Format(CultureInfo.InvariantCulture,
"Bad DreamDaemon security level: {0}", securityLevel));
115 public SessionControllerFactory(
IProcessExecutor processExecutor,
IByondManager byond, IByondTopicSender byondTopicSender,
ICryptographySuite cryptographySuite,
IApplication application,
IIOManager ioManager,
IChat chat,
INetworkPromptReaper networkPromptReaper,
IPlatformIdentifier platformIdentifier, ILoggerFactory loggerFactory, Api.Models.Instance instance)
117 this.processExecutor = processExecutor ??
throw new ArgumentNullException(nameof(processExecutor));
118 this.byond = byond ??
throw new ArgumentNullException(nameof(byond));
119 this.byondTopicSender = byondTopicSender ??
throw new ArgumentNullException(nameof(byondTopicSender));
120 this.cryptographySuite = cryptographySuite ??
throw new ArgumentNullException(nameof(cryptographySuite));
121 this.application = application ??
throw new ArgumentNullException(nameof(application));
122 this.instance = instance ??
throw new ArgumentNullException(nameof(instance));
123 this.ioManager = ioManager ??
throw new ArgumentNullException(nameof(ioManager));
124 this.chat = chat ??
throw new ArgumentNullException(nameof(chat));
125 this.networkPromptReaper = networkPromptReaper ??
throw new ArgumentNullException(nameof(networkPromptReaper));
126 this.platformIdentifier = platformIdentifier ??
throw new ArgumentNullException(nameof(platformIdentifier));
127 this.loggerFactory = loggerFactory ??
throw new ArgumentNullException(nameof(loggerFactory));
134 if (!portToUse.HasValue)
135 throw new InvalidOperationException(
"Given port is null!");
136 var accessIdentifier = cryptographySuite.GetSecureString();
138 const string JsonPostfix =
"tgs.json";
142 var files = await ioManager.GetFilesWithExtension(basePath, JsonPostfix, cancellationToken).ConfigureAwait(
false);
144 await Task.WhenAll(files.Select(x => ioManager.DeleteFile(x, cancellationToken))).ConfigureAwait(
false);
147 string JsonFile(
string name) => String.Format(CultureInfo.InvariantCulture,
"{0}.{1}", name, JsonPostfix);
149 var securityLevelToUse = launchParameters.
SecurityLevel.Value;
162 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
"Invalid DreamDaemonSecurity value: {0}", dmbProvider.
CompileJob.
MinimumSecurityLevel));
168 AccessIdentifier = accessIdentifier,
169 ApiValidateOnly = apiValidate,
170 ChatChannelsJson =
JsonFile(
"chat_channels"),
171 ChatCommandsJson =
JsonFile(
"chat_commands"),
172 ServerCommandsJson =
JsonFile(
"server_commands"),
173 InstanceName = instance.Name,
174 SecurityLevel = securityLevelToUse,
175 Revision =
new Api.Models.Internal.RevisionInformation
184 var interopJsonFile =
JsonFile(
"interop");
186 var interopJson = JsonConvert.SerializeObject(interopInfo,
new JsonSerializerSettings
188 ContractResolver =
new CamelCasePropertyNamesContractResolver(),
189 ReferenceLoopHandling = ReferenceLoopHandling.Ignore
194 var chatJsonTrackingTask = chat.TrackJsons(basePath, interopInfo.ChatChannelsJson, interopInfo.ChatCommandsJson, cancellationToken);
196 await localIoManager.WriteAllBytes(interopJsonFile, Encoding.UTF8.GetBytes(interopJson), cancellationToken).ConfigureAwait(
false);
197 var chatJsonTrackingContext = await chatJsonTrackingTask.ConfigureAwait(
false);
201 var byondLock = currentByondLock ?? await byond.UseExecutables(Version.Parse(dmbProvider.
CompileJob.
ByondVersion), cancellationToken).ConfigureAwait(
false);
205 var context =
new CommContext(ioManager, loggerFactory.CreateLogger<
CommContext>(), basePath, interopInfo.ServerCommandsJson);
210 var parameters = String.Format(CultureInfo.InvariantCulture,
"{2}={0}&{3}={1}", byondTopicSender.SanitizeString(application.Version.ToString()), byondTopicSender.SanitizeString(interopJsonFile), byondTopicSender.SanitizeString(
Constants.
DMParamHostVersion), byondTopicSender.SanitizeString(
Constants.
DMParamInfoJson));
213 var arguments = String.Format(CultureInfo.InvariantCulture,
"{0} -port {1} -ports 1-65535 {2}-close -{3} -verbose -public -params \"{4}\"",
216 launchParameters.
AllowWebClient.Value ?
"-webclient " : String.Empty,
217 SecurityWord(securityLevelToUse),
221 var noShellExecute = !platformIdentifier.IsWindows;
223 var process = processExecutor.LaunchProcess(byondLock.DreamDaemonPath, basePath, arguments, noShellExecute: noShellExecute);
226 networkPromptReaper.RegisterProcess(process);
231 AccessIdentifier = accessIdentifier,
233 IsPrimary = primaryDirectory,
234 Port = portToUse.Value,
235 ProcessId = process.Id,
236 ChatChannelsJson = interopInfo.ChatChannelsJson,
237 ChatCommandsJson = interopInfo.ChatCommandsJson,
238 ServerCommandsJson = interopInfo.ServerCommandsJson,
260 if (currentByondLock == null)
267 chatJsonTrackingContext.Dispose();
275 if (reattachInformation == null)
276 throw new ArgumentNullException(nameof(reattachInformation));
280 var chatJsonTrackingContext = await chat.TrackJsons(basePath, reattachInformation.
ChatChannelsJson, reattachInformation.
ChatCommandsJson, cancellationToken).ConfigureAwait(
false);
283 var byondLock = await byond.UseExecutables(Version.Parse(reattachInformation.
Dmb.
CompileJob.
ByondVersion), cancellationToken).ConfigureAwait(
false);
289 var process = processExecutor.GetProcess(reattachInformation.
ProcessId);
294 networkPromptReaper.RegisterProcess(process);
295 result =
new SessionController(reattachInformation, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger<
SessionController>(), null, null);
318 chatJsonTrackingContext.Dispose();
string ServerCommandsJson
Path to the server commands json file
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the SessionControllerFactory
readonly IIOManager ioManager
The IIOManager for the SessionControllerFactory
const string DMParamInfoJson
CompileJob CompileJob
The CompileJob of the .dmb
string DmbName
The file name of the .dmb
readonly IProcessExecutor processExecutor
The IProcessExecutor for the SessionControllerFactory
An IIOManager that resolve relative paths from another IIOManager to a subdirectory of that ...
readonly Api.Models.Instance instance
The Api.Models.Instance for the SessionControllerFactory
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the SessionControllerFactory
Configures the ASP.NET Core web application
Use server authentication
string SecondaryDirectory
The secondary game directory with a trailing directory separator
RevisionInformation RevisionInformation
Git revision the compiler ran on. Not modifiable
string ChatCommandsJson
Path to the chat commands json file
For launching IProcess'
Launch settings for DreamDaemon
readonly INetworkPromptReaper networkPromptReaper
The INetworkPromptReaper for the SessionControllerFactory
DreamDaemonSecurity SecurityLevel
The DreamDaemonSecurity level of DreamDaemon
string PrimaryDirectory
The primary game directory with a trailing directory separator
Representation of the initial json passed to DreamDaemon
For managing connected chat services
Contains various cryptographic functions
Handles communication with a DreamDaemon IProcess
readonly IApplication application
The IApplication for the SessionControllerFactory
ushort SecondaryPort
The second port DreamDaemon uses
async Task< ISessionController > LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance
DreamDaemonSecurity MinimumSecurityLevel
The minimum DreamDaemonSecurity required to run the CompileJob's output
Version ByondVersion
The Byond.Version the CompileJob was made with
Factory for ISessionControllers
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the SessionControllerFactory
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the SessionControllerFactory
async Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
For managing the BYOND installation
const string DMParamHostVersion
Implements a fake "dead" ISessionController
string ChatChannelsJson
Path to the chat channels json file
readonly IChat chat
The IChat for the SessionControllerFactory
SessionControllerFactory(IProcessExecutor processExecutor, IByondManager byond, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, INetworkPromptReaper networkPromptReaper, IPlatformIdentifier platformIdentifier, ILoggerFactory loggerFactory, Api.Models.Instance instance)
Construct a SessionControllerFactory
Represents usage of the two primary BYOND server executables
Represents a BYOND installation
DreamDaemonSecurity
DreamDaemon's security level
Provides absolute paths to the latest compiled .dmbs
Interface for using filesystems
readonly IByondManager byond
The IByondManager for the SessionControllerFactory
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it
static string SecurityWord(DreamDaemonSecurity securityLevel)
Change a given securityLevel into the appropriate DreamDaemon command line word
ushort PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
uint StartupTimeout
The DreamDaemon startup timeout in seconds
bool AllowWebClient
If the BYOND web client can be used to connect to the game server