35#pragma warning disable CA1506
38#pragma warning restore CA1506
43 internal static bool LogTopicRequests {
get;
set; } =
true;
341 primeTcs =
new TaskCompletionSource();
367 "Not registering session with {reasonWhyDmApiIsBad} DMAPI version for interop!",
370 :
$"incompatible ({reattachInformation.Dmb.CompileJob.DMApiVersion})");
385 assemblyInformationProvider,
392 "Created session controller. CommsKey: {accessIdentifier}, Port: {port}",
407 Logger.LogTrace(
"Disposing...");
454 Logger.LogWarning(
"Ignoring bridge request from session without confirmed DMAPI!");
458 Logger.LogTrace(
"Handling bridge request...");
507 Logger.LogTrace(
"Resetting reboot state...");
592 "Waiting for LaunchResult based on {launchResultCompletionCause}{possibleTimeout}...",
604 Logger.LogTrace(
"Launch result: {launchResult}",
result);
610 assemblyInformationProvider.
Version,
624 "DMAPI Interop v{interopVersion} isn't returning the TGS custom commands list. Functionality added in v5.2.0.",
644 Logger.LogTrace(
"Entered post validation terminate task.");
647 Logger.LogTrace(
"Not running post validation terminate task for repeated bridge request.");
658 Logger.LogWarning(
"DMAPI took too long to shutdown server after validation request!");
663 Logger.LogTrace(
"Server exited properly post validation.");
672#pragma warning disable CA1502
673#pragma warning disable CA1506
683 if (
parameters.ChatMessage.ChannelIds ==
null)
684 return BridgeError(
"Missing channelIds field in chatMessage!");
687 return BridgeError(
"Invalid channelIds in chatMessage!");
690 return BridgeError(
"Missing message field in chatMessage!");
701 return BridgeError(
"Failed to parse channelIds as U64!");
711 Logger.LogInformation(
"Bridge requested process termination!");
717 return BridgeError(
"Port switching is no longer supported!");
729 return BridgeError(
"Startup bridge request was repeated!");
757 return BridgeError(
"Missing minimumSecurityLevel field!");
759 return BridgeError(
"Invalid minimumSecurityLevel!");
778 Logger.LogInformation(
"Server is requesting use of port {topicPort} for topic communications",
newTopicPort);
813 databaseContextFactory,
822 return BridgeError(
$"commandType {parameters.CommandType} not supported!");
827#pragma warning restore CA1506
828#pragma warning restore CA1502
837 Logger.LogWarning(
"Bridge request error: {message}",
message);
855 if (LogTopicRequests)
856 Logger.LogTrace(
"Topic request: {json}",
json);
866 "Cannot send topic request as it is exceeds the single request limit of {limitBytes}B ({actualBytes}B) and requires chunking and the current compile job's interop version must be at least {chunkingVersionRequired}!",
935 "Topic request {chunkingStatus} failed!{potentialRequestError}",
938 ?
$" Request error: {combinedResponse.InteropResponse.ErrorMessage}"
955 Logger.LogWarning(
"DD is still missing some chunks of topic request P{payloadId}! Sending missing chunks...",
payloadId);
999 "Attempted to send a topic on a disposed SessionController");
1020 "Unable to send priority topic \"{queryString}\"!",
1056 "Attempted to send a command to an inactive SessionController: {commandType}",
1063 Logger.LogTrace(
"Not sending topic request {commandType} to server without/with incompatible DMAPI!",
parameters.CommandType);
1073 Logger.LogDebug(
"Not sending topic request {commandType} to server that failed to launch!",
parameters.CommandType);
1081 Logger.LogDebug(
"Not sending topic request {commandType} to server that is rebooting/starting.",
parameters.CommandType);
1094 "Server {action}, cancelling pending command: {commandType}",
1107 Logger.LogError(
ex,
"Error in CancelIfLifetimeElapses!");
1120 Logger.LogTrace(
"Topic response: {topicString}",
combinedResponse.ByondTopicResponse.StringData ??
"(NO STRING DATA)");
1127 Logger.LogTrace(
"Topic response is chunked...");
1140 Logger.LogWarning(
"Topic response chunking error: {message}",
error);
1165 "Topic request {cancellationType}!",
1167 ? cancellationToken.IsCancellationRequested
1173 cancellationToken.ThrowIfCancellationRequested();
1183 "Errored topic response for command {commandType}: {errorMessage}",
1245 Logger.LogTrace(
"Finished custom event {eventId}, not sending notification.",
eventId);
1252 Logger.LogDebug(
ex,
"Custom event invocation {eventId} aborted!",
eventId);
1256 Logger.LogWarning(
ex,
"Custom event invocation {eventId} errored!",
eventId);
1261 return BridgeError(
"Event refused to execute due to matching a TGS event!");
Information about an engine installation.
EngineType? Engine
The EngineType.
Metadata about a server instance.
Represents a command made from DM code.
Parameters for a bridge request.
A response to a bridge request.
Parameters for invoking a custom event.
Represents an update of ChannelRepresentations.
A packet of a split serialized set of data.
uint? PayloadId
The ID of the full request to differentiate different chunkings.Nullable to prevent default value omi...
Class that deserializes chunked interop payloads.
ILogger< Chunker > Logger
The ILogger for the Chunker.
uint NextPayloadId
Gets a payload ID for use in a new ChunkSetInfo.
Constants used for communication with the DMAPI.
static readonly JsonSerializerSettings SerializerSettings
JsonSerializerSettings for use when communicating with the DMAPI.
const uint MaximumTopicRequestLength
The maximum length in bytes of a Byond.TopicSender.ITopicClient payload.
static readonly Version InteropVersion
The DMAPI InteropVersion being used.
const string TopicData
Parameter json is encoded in for topic requests.
Common base for interop parameters.
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance.
TopicParameters for TopicCommandType.ReceiveChunk.
Parameters for a topic request.
static TopicParameters CreateInstanceRenamedTopicParameters(string newInstanceName)
Initializes a new instance of the TopicParameters class.
ChunkData? Chunk
The ChunkData for a partial request.
A response to a topic request.
Combines a Byond.TopicSender.TopicResponse with a TopicResponse.
Represents the result of trying to start a DD process.
async ValueTask InstanceRenamed(string newInstanceName, CancellationToken cancellationToken)
Called when the owning Instance is renamed.A ValueTask representing the running operation.
ValueTask< TopicResponse?> SendCommand(TopicParameters parameters, CancellationToken cancellationToken)
Sends a command to DreamDaemon through /world/Topic().A ValueTask<TResult> resulting in the TopicResp...
async ValueTask< BridgeResponse?> ProcessBridgeCommand(BridgeParameters parameters, CancellationToken cancellationToken)
Handle a set of bridge parameters .
readonly Byond.TopicSender.ITopicClient byondTopicSender
The Byond.TopicSender.ITopicClient for the SessionController.
string DumpFileExtension
The file extension to use for process dumps created from this session.
ApiValidationStatus apiValidationStatus
The ApiValidationStatus for the SessionController.
async ValueTask DisposeAsync()
readonly object synchronizationLock
lock object for port updates and disposed.
DateTimeOffset? LaunchTime
When the process was started.
void AdjustPriority(bool higher)
Set's the owned global::System.Diagnostics.Process.PriorityClass to a non-normal value.
async ValueTask< TopicResponse?> SendCommand(TopicParameters parameters, bool bypassLaunchResult, CancellationToken cancellationToken)
Sends a command to DreamDaemon through /world/Topic().
volatile uint rebootBridgeRequestsProcessing
The number of currently active calls to ProcessBridgeRequest(BridgeParameters, CancellationToken) fro...
readonly IDotnetDumpService dotnetDumpService
The IDotnetDumpService for the SessionController.
readonly Api.Models.Instance metadata
The Instance metadata.
Task OnReboot
A Task that completes when the server calls /world/TgsReboot().
bool DMApiAvailable
If the DMAPI may be used this session.
readonly TaskCompletionSource initialBridgeRequestTcs
The TaskCompletionSource that completes when DD makes it's first bridge request.
bool disposed
If the SessionController has been disposed.
void SuspendProcess()
Suspends the process.
void ResetRebootState()
Changes RebootState to RebootState.Normal without telling the DMAPI.
readonly IEngineExecutableLock engineLock
The IEngineExecutableLock for the SessionController.
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the SessionController.
long? StartupBridgeRequestsReceived
The number of times a startup bridge request has been received. null if DMApiAvailable is false.
async ValueTask< BridgeResponse?> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
Handle a set of bridge parameters .A ValueTask<TResult> resulting in the BridgeResponse for the reque...
ReattachInformation ReattachInformation
The up to date Session.ReattachInformation.
volatile Task rebootGate
Backing field for RebootGate.
bool TerminationWasIntentional
If the DreamDaemon instance sent a.
readonly IEventConsumer eventConsumer
The IEventConsumer for the SessionController.
BridgeResponse BridgeError(string message)
Log and return a BridgeResponse for a given message .
bool released
If process should be kept alive instead.
bool terminationWasIntentionalForced
Backing field for overriding TerminationWasIntentional.
readonly IChatManager chat
The IChatManager for the SessionController.
double MeasureProcessorTimeDelta()
Gets the estimated CPU usage fraction of the process based on the last time this was called....
readonly IChatTrackingContext chatTrackingContext
The IChatTrackingContext for the SessionController.
Task< int?> Lifetime
The Task<TResult> resulting in the exit code of the process or null if the process was detached.
readonly CancellationTokenSource sessionDurationCts
A CancellationTokenSource used for tasks that should not exceed the lifetime of the session.
ValueTask CreateDump(string outputFile, bool minidump, CancellationToken cancellationToken)
Create a dump file of the process.A ValueTask representing the running operation.
volatile TaskCompletionSource startupTcs
The TaskCompletionSource that completes when DD sends a valid startup bridge request.
async Task PostValidationShutdown(Task< bool > proceedTask)
Terminates the server after ten seconds if it does not exit.
void ResumeProcess()
Resumes the process.
readonly bool apiValidationSession
If this session is meant to validate the presence of the DMAPI.
FifoSemaphore TopicSendSemaphore
The FifoSemaphore used to prevent concurrent calls into /world/Topic().
async ValueTask UpdateChannels(IEnumerable< ChannelRepresentation > newChannels, CancellationToken cancellationToken)
Called when newChannels are set.A ValueTask representing the running operation.
string GenerateQueryString(TopicParameters parameters, out string json)
Generates a Byond.TopicSender.ITopicClient query string for a given set of parameters .
readonly IDreamMaker dreamMaker
The IDreamMaker for the SessionController.
void CheckDisposed()
Throws an ObjectDisposedException if DisposeAsync has been called.
readonly? IBridgeRegistration bridgeRegistration
The IBridgeRegistration for the SessionController.
long? MemoryUsage
Gets the process' memory usage in bytes.
async Task< LaunchResult > GetLaunchResult(IAssemblyInformationProvider assemblyInformationProvider, IAsyncDelayer asyncDelayer, uint? startupTimeout, bool reattached, bool apiValidate)
The Task<TResult> for LaunchResult.
IAsyncDisposable ReplaceDmbProvider(IDmbProvider dmbProvider)
Replace the IDmbProvider in use with a given newProvider , disposing the old one.An IAsyncDisposable ...
Task OnStartup
A Task that completes when the server calls /world/TgsNew().
bool ProcessingRebootBridgeRequest
If the ISessionController is currently processing a bridge request from TgsReboot().
ValueTask Release()
Releases the IProcess without terminating it. Also calls IDisposable.Dispose.A ValueTask representing...
volatile? Task postValidationShutdownTask
Task for shutting down the server if it is taking too long after validation.
readonly IJobManager jobManager
The IJobManager for the SessionController.
volatile Task customEventProcessingTask
The Task representing calls to TriggerCustomEvent(CustomEventInvocation?).
Task OnPrime
A Task that completes when the server calls /world/TgsInitializationComplete().
async ValueTask< CombinedTopicResponse?> SendTopicRequest(TopicParameters parameters, CancellationToken cancellationToken)
Send a topic request for given parameters to DreamDaemon, chunking it if necessary.
volatile TaskCompletionSource rebootTcs
The TaskCompletionSource that completes when DD tells us about a reboot.
async ValueTask< CombinedTopicResponse?> SendRawTopic(string queryString, bool priority, CancellationToken cancellationToken)
Send a given queryString to DreamDaemon's /world/Topic.
volatile TaskCompletionSource primeTcs
The TaskCompletionSource that completes when DD tells us it's primed.
async ValueTask< bool > SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
Attempts to change the current RebootState to newRebootState .A ValueTask<TResult> resulting in true ...
Task RebootGate
A Task that must complete before a TgsReboot() bridge request can complete.
Version? DMApiVersion
The DMAPI Version.
readonly IProcess process
The IProcess for the SessionController.
BridgeResponse TriggerCustomEvent(CustomEventInvocation? invocation)
Trigger a custom event from a given invocation .
SessionController(ReattachInformation reattachInformation, Api.Models.Instance metadata, IProcess process, IEngineExecutableLock engineLock, Byond.TopicSender.ITopicClient byondTopicSender, IChatTrackingContext chatTrackingContext, IBridgeRegistrar bridgeRegistrar, IChatManager chat, IAssemblyInformationProvider assemblyInformationProvider, IAsyncDelayer asyncDelayer, IDotnetDumpService dotnetDumpService, IEventConsumer eventConsumer, IJobManager jobManager, IDreamMaker dreamMaker, ILogger< SessionController > logger, Func< ValueTask > postLifetimeCallback, uint? startupTimeout, bool reattached, bool apiValidate)
Initializes a new instance of the SessionController class.
override? Version DMApiVersion
static Job Create(JobCode code, User? startedBy, Api.Models.Instance instance)
Creates a new job for registering in the Jobs.IJobService.
A first-in first-out async semaphore.
async ValueTask< SemaphoreSlimContext > Lock(CancellationToken cancellationToken)
Locks the FifoSemaphore.
Helpers for manipulating the Serilog.Context.LogContext.
const string InstanceIdContextProperty
The Serilog.Context.LogContext property name for Models.Instance Api.Models.EntityId....
Notifyee of when ChannelRepresentations in a IChatTrackingContext are updated.
For managing connected chat services.
void QueueMessage(MessageContent message, IEnumerable< ulong > channelIds)
Queue a chat message to a given set of channelIds .
Represents a tracking of dynamic chat json files.
bool Active
If the CustomCommands should be used.
void SetChannelSink(IChannelSink channelSink)
Sets the channelSink for the IChatTrackingContext.
Provides absolute paths to the latest compiled .dmbs.
void KeepAlive()
Disposing the IDmbProvider won't cause a cleanup of the working directory.
EngineVersion EngineVersion
The Api.Models.EngineVersion used to build the .dmb.
string Directory
The primary game directory.
Models.CompileJob CompileJob
The CompileJob of the .dmb.
For managing the compiler.
ValueTask DeploymentProcess(Job job, IDatabaseContextFactory databaseContextFactory, JobProgressReporter progressReporter, CancellationToken cancellationToken)
Create and a compile job and insert it into the database. Meant to be called by a IJobManager.
Represents usage of the two primary BYOND server executables.
void DoNotDeleteThisSession()
Call if, during a detach, this version should not be deleted.
bool UseDotnetDump
If dotnet-dump should be used to create process dumps for this installation.
ValueTask StopServerProcess(ILogger logger, IProcess process, string accessIdentifier, ushort port, CancellationToken cancellationToken)
Kills a given engine server process .
Consumes EventTypes and takes the appropriate actions.
ValueTask? HandleCustomEvent(string eventName, IEnumerable< string?> parameters, CancellationToken cancellationToken)
Handles a given custom event.
Registers IBridgeHandlers.
IBridgeRegistration RegisterHandler(IBridgeHandler bridgeHandler)
Register a given bridgeHandler .
Represents a registration of an interop session.
Handles communication with a DreamDaemon IProcess.
Manages the runtime of Jobs.
ValueTask RegisterOperation(Job job, JobEntrypoint operation, CancellationToken cancellationToken)
Registers a given Job and begins running it.
Service for managing the dotnet-dump installation.
ValueTask Dump(IProcess process, string outputFile, bool minidump, CancellationToken cancellationToken)
Attempt to dump a given process .
void SuspendProcess()
Suspends the process.
void ResumeProcess()
Resumes the process.
void AdjustPriority(bool higher)
Set's the owned global::System.Diagnostics.Process.PriorityClass to a non-normal value.
long? MemoryUsage
Gets the process' memory usage in bytes.
double MeasureProcessorTimeDelta()
Gets the estimated CPU usage fraction of the process based on the last time this was called.
DateTimeOffset? LaunchTime
When the process was started.
ValueTask CreateDump(string outputFile, bool minidump, CancellationToken cancellationToken)
Create a dump file of the process.
Task< int?> Lifetime
The Task<TResult> resulting in the exit code of the process or null if the process was detached.
Abstraction over a global::System.Diagnostics.Process.
Task Startup
The Task representing the time until the IProcess becomes "idle".
void Terminate()
Asycnhronously terminates the process.
For waiting asynchronously.
ValueTask Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan .
JobCode
The different types of Response.JobResponse.
DreamDaemonSecurity
DreamDaemon's security level.
EngineType
The type of engine the codebase is using.
@ Byond
Build your own net dream.
@ List
User may list files if the Models.Instance allows it.
DreamMakerRights
Rights for deployment.
BridgeCommandType
Represents the BridgeParameters.CommandType.
@ Chunk
DreamDaemon attempting to send a longer bridge message.
RebootState
Represents the action to take when /world/Reboot() is called.
ApiValidationStatus
Status of DMAPI validation.