Put the interop stuff into it's own namespace

This commit is contained in:
Cyberboss
2018-08-10 10:59:34 -04:00
parent fbbe03f1d2
commit 777505995e
13 changed files with 80 additions and 76 deletions
@@ -1,14 +1,14 @@
using System.Collections.Generic;
namespace Tgstation.Server.Host.Components.Watchdog
namespace Tgstation.Server.Host.Components.Interop
{
/// <summary>
/// Represents a command from DD
/// </summary>
sealed class InteropCommand
sealed class CommCommand
{
/// <summary>
/// The raw JSON decond of the <see cref="InteropCommand"/>
/// The raw JSON decond of the <see cref="CommCommand"/>
/// </summary>
public IReadOnlyDictionary<string, string> Parameters { get; set; }
}
@@ -7,49 +7,49 @@ using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Host.Components.Watchdog
namespace Tgstation.Server.Host.Components.Interop
{
/// <inheritdoc />
sealed class InteropContext : IInteropContext
sealed class CommContext : ICommContext
{
/// <summary>
/// The <see cref="IIOManager"/> for the <see cref="InteropContext"/>
/// The <see cref="IIOManager"/> for the <see cref="CommContext"/>
/// </summary>
readonly IIOManager ioManager;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="InteropContext"/>
/// The <see cref="ILogger"/> for the <see cref="CommContext"/>
/// </summary>
readonly ILogger<InteropContext> logger;
readonly ILogger<CommContext> logger;
/// <summary>
/// The <see cref="FileSystemWatcher"/> for the <see cref="InteropContext"/>
/// The <see cref="FileSystemWatcher"/> for the <see cref="CommContext"/>
/// </summary>
readonly FileSystemWatcher fileSystemWatcher;
/// <summary>
/// The <see cref="CancellationTokenSource"/> for the <see cref="InteropContext"/>
/// The <see cref="CancellationTokenSource"/> for the <see cref="CommContext"/>
/// </summary>
readonly CancellationTokenSource cancellationTokenSource;
/// <summary>
/// The <see cref="CancellationToken"/> for the <see cref="InteropContext"/>
/// The <see cref="CancellationToken"/> for the <see cref="CommContext"/>
/// </summary>
readonly CancellationToken cancellationToken;
/// <summary>
/// The <see cref="IInteropHandler"/> for the <see cref="InteropContext"/>
/// The <see cref="ICommHandler"/> for the <see cref="CommContext"/>
/// </summary>
IInteropHandler handler;
ICommHandler handler;
/// <summary>
/// Construct an <see cref="InteropContext"/>
/// Construct an <see cref="CommContext"/>
/// </summary>
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
/// <param name="logger">The value of <see cref="logger"/></param>
/// <param name="directory">The path to watch</param>
/// <param name="filter">The filter to watch for</param>
public InteropContext(IIOManager ioManager, ILogger<InteropContext> logger, string directory, string filter)
public CommContext(IIOManager ioManager, ILogger<CommContext> logger, string directory, string filter)
{
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -93,10 +93,10 @@ namespace Tgstation.Server.Host.Components.Watchdog
var fileBytes = await ioManager.ReadAllBytes(e.FullPath, cancellationToken).ConfigureAwait(false);
var file = Encoding.UTF8.GetString(fileBytes);
InteropCommand command;
CommCommand command;
try
{
command = JsonConvert.DeserializeObject<InteropCommand>(file);
command = JsonConvert.DeserializeObject<CommCommand>(file);
}
catch (JsonSerializationException ex)
{
@@ -114,7 +114,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
}
/// <inheritdoc />
public void RegisterHandler(IInteropHandler handler)
public void RegisterHandler(ICommHandler handler)
{
if (this.handler != null)
throw new InvalidOperationException("RegisterHandler already called!");
@@ -1,6 +1,6 @@
namespace Tgstation.Server.Host.Components.Watchdog
namespace Tgstation.Server.Host.Components.Interop
{
static class InteropConstants
static class Constants
{
//interop values, match them up with the appropriate api.dm
@@ -0,0 +1,16 @@
using System;
namespace Tgstation.Server.Host.Components.Interop
{
/// <summary>
/// Represents a registration of an interop session
/// </summary>
interface ICommContext : IDisposable
{
/// <summary>
/// Register a <paramref name="handler"/> with the <see cref="ICommContext"/>
/// </summary>
/// <param name="handler">The <see cref="ICommHandler"/> to register</param>
void RegisterHandler(ICommHandler handler);
}
}
@@ -1,19 +1,19 @@
using System.Threading;
using System.Threading.Tasks;
namespace Tgstation.Server.Host.Components.Watchdog
namespace Tgstation.Server.Host.Components.Interop
{
/// <summary>
/// Handles <see cref="InteropCommand"/>s
/// Handles <see cref="CommCommand"/>s
/// </summary>
interface IInteropHandler
interface ICommHandler
{
/// <summary>
/// Handle a <paramref name="command"/>
/// </summary>
/// <param name="command">The <see cref="InteropCommand"/> to handle</param>
/// <param name="command">The <see cref="CommCommand"/> to handle</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
/// <returns>A <see cref="Task"/> representing the running operation</returns>
Task HandleInterop(InteropCommand command, CancellationToken cancellationToken);
Task HandleInterop(CommCommand command, CancellationToken cancellationToken);
}
}
@@ -1,12 +1,12 @@
using System.Collections.Generic;
using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Host.Components.Watchdog
namespace Tgstation.Server.Host.Components.Interop
{
/// <summary>
/// Representation of the initial json passed to DreamDaemon
/// </summary>
sealed class InteropInfo
sealed class JsonFile
{
/// <summary>
/// The code used by the server to authenticate command Topics
@@ -1,12 +1,12 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace Tgstation.Server.Host.Components.Watchdog
namespace Tgstation.Server.Host.Components.Interop
{
/// <summary>
/// Information used in for reattaching and interop
/// </summary>
public class InteropInfoBase
public class JsonSubFileList
{
/// <summary>
/// Path to the chat commands json file
@@ -27,15 +27,15 @@ namespace Tgstation.Server.Host.Components.Watchdog
public string ServerCommandsJson { get; set; }
/// <summary>
/// Construct an <see cref="InteropInfoBase"/>
/// Construct an <see cref="JsonSubFileList"/>
/// </summary>
protected InteropInfoBase() { }
protected JsonSubFileList() { }
/// <summary>
/// Construct an <see cref="InteropInfoBase"/> from a <paramref name="copy"/>
/// Construct an <see cref="JsonSubFileList"/> from a <paramref name="copy"/>
/// </summary>
/// <param name="copy">An <see cref="InteropInfoBase"/> to copy</param>
public InteropInfoBase(InteropInfoBase copy)
/// <param name="copy">An <see cref="JsonSubFileList"/> to copy</param>
public JsonSubFileList(JsonSubFileList copy)
{
if (copy == null)
throw new ArgumentNullException(nameof(copy));
@@ -1,6 +1,6 @@
using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Host.Components.Watchdog
namespace Tgstation.Server.Host.Components.Interop
{
/// <summary>
/// This model mirrors /datum/tgs_revision_information/test_merge
@@ -1,16 +0,0 @@
using System;
namespace Tgstation.Server.Host.Components.Watchdog
{
/// <summary>
/// Represents a registration of an interop session
/// </summary>
interface IInteropContext : IDisposable
{
/// <summary>
/// Register a <paramref name="handler"/> with the <see cref="IInteropContext"/>
/// </summary>
/// <param name="handler">The <see cref="IInteropHandler"/> to register</param>
void RegisterHandler(IInteropHandler handler);
}
}
@@ -10,12 +10,13 @@ using System.Threading.Tasks;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Host.Components.Byond;
using Tgstation.Server.Host.Components.Chat;
using Tgstation.Server.Host.Components.Interop;
using Tgstation.Server.Host.Core;
namespace Tgstation.Server.Host.Components.Watchdog
{
/// <inheritdoc />
sealed class SessionController : ISessionController, IInteropHandler
sealed class SessionController : ISessionController, ICommHandler
{
/// <inheritdoc />
public bool IsPrimary
@@ -93,9 +94,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
readonly IByondTopicSender byondTopicSender;
/// <summary>
/// The <see cref="IInteropContext"/> for the <see cref="SessionController"/>
/// The <see cref="ICommContext"/> for the <see cref="SessionController"/>
/// </summary>
readonly IInteropContext interopContext;
readonly ICommContext interopContext;
/// <summary>
/// The <see cref="IProcess"/> for the <see cref="SessionController"/>
@@ -166,7 +167,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="chat">The value of <see cref="chat"/></param>
/// <param name="chatJsonTrackingContext">The value of <see cref="chatJsonTrackingContext"/></param>
/// <param name="logger">The value of <see cref="logger"/></param>
public SessionController(ReattachInformation reattachInformation, IProcess process, IByondExecutableLock byondLock, IByondTopicSender byondTopicSender, IJsonTrackingContext chatJsonTrackingContext, IInteropContext interopContext, IChat chat, ILogger<SessionController> logger)
public SessionController(ReattachInformation reattachInformation, IProcess process, IByondExecutableLock byondLock, IByondTopicSender byondTopicSender, IJsonTrackingContext chatJsonTrackingContext, ICommContext interopContext, IChat chat, ILogger<SessionController> logger)
{
this.chatJsonTrackingContext = chatJsonTrackingContext; //null valid
this.reattachInformation = reattachInformation ?? throw new ArgumentNullException(nameof(reattachInformation));
@@ -247,7 +248,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
}
/// <inheritdoc />
public Task HandleInterop(InteropCommand command, CancellationToken cancellationToken)
public Task HandleInterop(CommCommand command, CancellationToken cancellationToken)
{
if (command == null)
throw new ArgumentNullException(nameof(command));
@@ -255,17 +256,17 @@ namespace Tgstation.Server.Host.Components.Watchdog
var query = command.Parameters;
object content;
if (query.TryGetValue(InteropConstants.DMParameterCommand, out var method))
if (query.TryGetValue(Constants.DMParameterCommand, out var method))
{
content = new object();
switch (method)
{
case InteropConstants.DMCommandIdentify:
case Constants.DMCommandIdentify:
lock (this)
if (portClosed)
content = new Dictionary<string, int> { { InteropConstants.DMParameterData, nextPort } };
content = new Dictionary<string, int> { { Constants.DMParameterData, nextPort } };
break;
case InteropConstants.DMCommandOnline:
case Constants.DMCommandOnline:
lock (this)
if (portClosed)
{
@@ -275,13 +276,13 @@ namespace Tgstation.Server.Host.Components.Watchdog
portClosed = false;
}
break;
case InteropConstants.DMCommandApiValidate:
case Constants.DMCommandApiValidate:
apiValidated = true;
break;
case InteropConstants.DMCommandWorldReboot:
case Constants.DMCommandWorldReboot:
if (ClosePortOnReboot)
{
content = new Dictionary<string, int> { { InteropConstants.DMParameterData, 0 } };
content = new Dictionary<string, int> { { Constants.DMParameterData, 0 } };
portClosed = true;
}
else
@@ -299,7 +300,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
content = new ErrorMessage { Message = "Missing command parameter!" };
var json = JsonConvert.SerializeObject(content);
return SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(InteropConstants.DMTopicInteropResponse), byondTopicSender.SanitizeString(InteropConstants.DMParameterData), byondTopicSender.SanitizeString(json)), cancellationToken);
return SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicInteropResponse), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(json)), cancellationToken);
}
/// <summary>
@@ -332,9 +333,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
{
var commandString = String.Format(CultureInfo.InvariantCulture,
"?{0}={1}&{2}={3}",
byondTopicSender.SanitizeString(InteropConstants.DMInteropAccessIdentifier),
byondTopicSender.SanitizeString(Constants.DMInteropAccessIdentifier),
byondTopicSender.SanitizeString(reattachInformation.AccessIdentifier),
byondTopicSender.SanitizeString(InteropConstants.DMParameterCommand),
byondTopicSender.SanitizeString(Constants.DMParameterCommand),
//intentionally don't sanitize command, that's up to the caller
command);
@@ -352,7 +353,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
}
}
async Task<bool> SetPortImpl(ushort port, CancellationToken cancellationToken) => await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(InteropConstants.DMTopicChangePort), byondTopicSender.SanitizeString(InteropConstants.DMParameterData), byondTopicSender.SanitizeString(port.ToString(CultureInfo.InvariantCulture))), cancellationToken).ConfigureAwait(false) == InteropConstants.DMResponseSuccess;
async Task<bool> SetPortImpl(ushort port, CancellationToken cancellationToken) => await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChangePort), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(port.ToString(CultureInfo.InvariantCulture))), cancellationToken).ConfigureAwait(false) == Constants.DMResponseSuccess;
/// <inheritdoc />
public async Task<bool> ClosePort(CancellationToken cancellationToken)
@@ -399,7 +400,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
if (RebootState == newRebootState)
return true;
return await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", InteropConstants.DMTopicChangeReboot, InteropConstants.DMParameterData, (int)newRebootState), cancellationToken).ConfigureAwait(false) == InteropConstants.DMResponseSuccess;
return await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", Constants.DMTopicChangeReboot, Constants.DMParameterData, (int)newRebootState), cancellationToken).ConfigureAwait(false) == Constants.DMResponseSuccess;
}
/// <inheritdoc />
@@ -12,6 +12,7 @@ using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Byond;
using Tgstation.Server.Host.Components.Chat;
using Tgstation.Server.Host.Components.Interop;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Security;
@@ -130,7 +131,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
//i changed this back from guids, hopefully i don't regret that
string JsonFile(string name) => String.Format(CultureInfo.InvariantCulture, "{0}.{1}", name, JsonPostfix);
var interopInfo = new InteropInfo
var interopInfo = new JsonFile
{
AccessIdentifier = accessIdentifier,
ApiValidateOnly = apiValidate,
@@ -141,7 +142,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
Revision = dmbProvider.CompileJob.RevisionInformation
};
interopInfo.TestMerges.AddRange(dmbProvider.CompileJob.RevisionInformation.ActiveTestMerges.Select(x => x.TestMerge).Select(x => new TestMerge(x)));
interopInfo.TestMerges.AddRange(dmbProvider.CompileJob.RevisionInformation.ActiveTestMerges.Select(x => x.TestMerge).Select(x => new Interop.TestMerge(x)));
var interopJsonFile = JsonFile("interop");
@@ -166,9 +167,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
try
{
//more sanitization here cause it uses the same scheme
var parameters = String.Format(CultureInfo.InvariantCulture, "{2}={0}&{3}={1}", byondTopicSender.SanitizeString(application.Version.ToString()), byondTopicSender.SanitizeString(interopJsonFile), byondTopicSender.SanitizeString(InteropConstants.DMParamHostVersion), byondTopicSender.SanitizeString(InteropConstants.DMParamInfoJson));
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));
var context = new InteropContext(ioManager, loggerFactory.CreateLogger<InteropContext>(), basePath, interopInfo.ServerCommandsJson);
var context = new CommContext(ioManager, loggerFactory.CreateLogger<CommContext>(), basePath, interopInfo.ServerCommandsJson);
try
{
var arguments = String.Format(CultureInfo.InvariantCulture, "{0} -port {1} {2}-close -{3} -verbose -public -params \"{4}\"",
@@ -232,7 +233,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
var byondLock = await byond.UseExecutables(Version.Parse(reattachInformation.Dmb.CompileJob.ByondVersion), cancellationToken).ConfigureAwait(false);
try
{
var context = new InteropContext(ioManager, loggerFactory.CreateLogger<InteropContext>(), basePath, reattachInformation.ServerCommandsJson);
var context = new CommContext(ioManager, loggerFactory.CreateLogger<CommContext>(), basePath, reattachInformation.ServerCommandsJson);
try
{
var process = processExecutor.GetProcess(reattachInformation.ProcessId);
@@ -11,6 +11,7 @@ using System.Threading.Tasks;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Chat;
using Tgstation.Server.Host.Components.Compiler;
using Tgstation.Server.Host.Components.Interop;
using Tgstation.Server.Host.Core;
namespace Tgstation.Server.Host.Components.Watchdog
@@ -787,7 +788,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
if (!Running)
return true;
var builder = new StringBuilder(InteropConstants.DMTopicEvent);
var builder = new StringBuilder(Constants.DMTopicEvent);
foreach (var I in parameters)
{
builder.Append("&");
@@ -825,7 +826,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
if (!Running)
return "ERROR: Server offline!";
var command = String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(InteropConstants.DMTopicChatCommand), byondTopicSender.SanitizeString(InteropConstants.DMParameterData), byondTopicSender.SanitizeString(JsonConvert.SerializeObject(arguments)));
var command = String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChatCommand), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(JsonConvert.SerializeObject(arguments)));
var activeServer = AlphaIsActive ? alphaServer : bravoServer;
return await activeServer.SendCommand(command, cancellationToken).ConfigureAwait(false) ?? "ERROR: Bad topic exchange!";
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using Tgstation.Server.Host.Components.Interop;
using Tgstation.Server.Host.Components.Watchdog;
namespace Tgstation.Server.Host.Models
@@ -7,7 +8,7 @@ namespace Tgstation.Server.Host.Models
/// <summary>
/// Base class for <see cref="ReattachInformation"/>
/// </summary>
public abstract class ReattachInformationBase : InteropInfoBase
public abstract class ReattachInformationBase : JsonSubFileList
{
/// <summary>
/// Used to identify and authenticate the DreamDaemon instance