Merge pull request #449 from Cyberboss/InterfaceRestructure

Interface Restructure
This commit is contained in:
Jordan Brown
2017-12-08 15:06:09 -05:00
committed by GitHub
44 changed files with 1015 additions and 896 deletions
+5 -6
View File
@@ -1,10 +1,9 @@
using System.Collections.Generic;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class AdminCommand : InstanceRootCommand
sealed class AdminCommand : RootCommand
{
public AdminCommand()
{
@@ -26,7 +25,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGAdministration>().RecreateStaticFolder();
var res = Instance.Administration.RecreateStaticFolder();
OutputProc(res ?? "Success");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
@@ -50,7 +49,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var group = Interface.GetComponent<ITGAdministration>().GetCurrentAuthorizedGroup();
var group = Instance.Administration.GetCurrentAuthorizedGroup();
OutputProc(group ?? "ERROR");
return group != null ? ExitCode.Normal : ExitCode.ServerError;
}
@@ -75,7 +74,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var result = Interface.GetComponent<ITGAdministration>().SetAuthorizedGroup(parameters[0]);
var result = Instance.Administration.SetAuthorizedGroup(parameters[0]);
if(result != null)
{
OutputProc("Group set to: " + result);
@@ -103,7 +102,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGAdministration>().SetAuthorizedGroup(null);
var res = Instance.Administration.SetAuthorizedGroup(null);
if(res != "ADMIN")
{
OutputProc("Failed to clear the group??? We are currently set to: " + res);
+4 -5
View File
@@ -2,11 +2,10 @@
using System.Collections.Generic;
using System.Threading;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class BYONDCommand : InstanceRootCommand
class BYONDCommand : RootCommand
{
public BYONDCommand()
{
@@ -33,7 +32,7 @@ namespace TGS.CommandLine
type = ByondVersion.Staged;
else if (parameters[0].ToLower() == "--latest")
type = ByondVersion.Latest;
OutputProc(Interface.GetComponent<ITGByond>().GetVersion(type) ?? "Unistalled");
OutputProc(Instance.Byond.GetVersion(type) ?? "Unistalled");
return ExitCode.Normal;
}
public override string GetArgumentString()
@@ -56,7 +55,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
switch (Interface.GetComponent<ITGByond>().CurrentStatus())
switch (Instance.Byond.CurrentStatus())
{
case ByondStatus.Downloading:
OutputProc("Downloading update...");
@@ -109,7 +108,7 @@ namespace TGS.CommandLine
return ExitCode.BadCommand;
}
var BYOND = Interface.GetComponent<ITGByond>();
var BYOND = Instance.Byond;
if (!BYOND.UpdateToVersion(Major, Minor))
{
+19 -20
View File
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class IRCCommand : InstanceRootCommand
class IRCCommand : RootCommand
{
public IRCCommand()
{
@@ -17,7 +16,7 @@ namespace TGS.CommandLine
return "Manages the IRC bot";
}
}
class DiscordCommand : InstanceRootCommand
class DiscordCommand : RootCommand
{
public DiscordCommand()
{
@@ -48,7 +47,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var Chat = Interface.GetComponent<ITGChat>();
var Chat = Instance.Chat;
Chat.SetProviderInfo(new IRCSetupInfo(Chat.ProviderInfos()[(int)ChatProvider.IRC])
{
Nickname = parameters[0],
@@ -78,7 +77,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
var info = IRC.ProviderInfos()[providerIndex];
List<string> channels;
@@ -156,7 +155,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
var info = IRC.ProviderInfos()[providerIndex];
List<string> channels;
@@ -222,7 +221,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var info = Interface.GetComponent<ITGChat>().ProviderInfos()[providerIndex];
var info = Instance.Chat.ProviderInfos()[providerIndex];
string authType;
switch ((ChatProvider)providerIndex)
{
@@ -281,7 +280,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGChat>().Reconnect(providerIndex);
var res = Instance.Chat.Reconnect(providerIndex);
if (res != null)
{
OutputProc("Error: " + res);
@@ -310,7 +309,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
var info = IRC.ProviderInfos()[providerIndex];
var newmin = parameters[0].ToLower();
@@ -355,7 +354,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
var info = IRC.ProviderInfos()[(int)ChatProvider.IRC];
var lowerparam = parameters[0].ToLower();
if (lowerparam == "channel-mode")
@@ -394,7 +393,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
var info = IRC.ProviderInfos()[(int)ChatProvider.Discord];
var lowerparam = parameters[0].ToLower();
if (lowerparam == "role-id")
@@ -433,7 +432,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
var info = new IRCSetupInfo(IRC.ProviderInfos()[(int)ChatProvider.IRC]);
switch (parameters[0])
{
@@ -482,7 +481,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
var info = IRC.ProviderInfos()[providerIndex];
var newmin = parameters[0].ToLower();
@@ -529,7 +528,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
IRC.SetProviderInfo(new IRCSetupInfo(IRC.ProviderInfos()[(int)ChatProvider.IRC])
{
AuthTarget = parameters[0],
@@ -551,7 +550,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
IRC.SetProviderInfo(new IRCSetupInfo(IRC.ProviderInfos()[(int)ChatProvider.IRC])
{
AuthTarget = null,
@@ -575,7 +574,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var IRC = Interface.GetComponent<ITGChat>();
var IRC = Instance.Chat;
var info = IRC.ProviderInfos()[providerIndex];
OutputProc("Currently configured channels:");
OutputProc("Admin:");
@@ -610,7 +609,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var Chat = Interface.GetComponent<ITGChat>();
var Chat = Instance.Chat;
var info = Chat.ProviderInfos()[providerIndex];
info.Enabled = true;
var res = Chat.SetProviderInfo(info);
@@ -638,7 +637,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var Chat = Interface.GetComponent<ITGChat>();
var Chat = Instance.Chat;
var info = Chat.ProviderInfos()[providerIndex];
info.Enabled = false;
var res = Chat.SetProviderInfo(info);
@@ -675,7 +674,7 @@ namespace TGS.CommandLine
OutputProc("Invalid parameter!");
return ExitCode.BadCommand;
}
var Chat = Interface.GetComponent<ITGChat>();
var Chat = Instance.Chat;
var PI = new IRCSetupInfo(Chat.ProviderInfos()[(int)ChatProvider.IRC])
{
URL = splits[0]
@@ -713,7 +712,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var Chat = Interface.GetComponent<ITGChat>();
var Chat = Instance.Chat;
var res = Chat.SetProviderInfo(new DiscordSetupInfo(Chat.ProviderInfos()[(int)ChatProvider.Discord]) { BotToken = parameters[0] });
OutputProc(res ?? "Success");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
+6 -7
View File
@@ -2,11 +2,10 @@
using System.Collections.Generic;
using System.IO;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class ConfigCommand : InstanceRootCommand
class ConfigCommand : RootCommand
{
public ConfigCommand()
{
@@ -28,7 +27,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGConfig>().DeleteFile(parameters[0], out bool unauthorized);
var res = Instance.Config.DeleteFile(parameters[0], out bool unauthorized);
if (res != null)
{
OutputProc(res);
@@ -64,7 +63,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var list = Interface.GetComponent<ITGConfig>().ListStaticDirectory(parameters.Count > 0 ? parameters[0] : null, out string error, out bool unauthorized);
var list = Instance.Config.ListStaticDirectory(parameters.Count > 0 ? parameters[0] : null, out string error, out bool unauthorized);
if(list == null)
{
OutputProc(error);
@@ -88,7 +87,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
OutputProc(Interface.GetComponent<ITGInstance>().ServerDirectory());
OutputProc(Instance.ServerDirectory());
return ExitCode.Normal;
}
@@ -108,7 +107,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var bytes = Interface.GetComponent<ITGConfig>().ReadText(parameters[0], parameters.Count > 2 && parameters[2].ToLower() == "--repo", out string error, out bool unauthorized);
var bytes = Instance.Config.ReadText(parameters[0], parameters.Count > 2 && parameters[2].ToLower() == "--repo", out string error, out bool unauthorized);
if(bytes == null)
{
OutputProc("Error: " + error);
@@ -148,7 +147,7 @@ namespace TGS.CommandLine
{
try
{
var res = Interface.GetComponent<ITGConfig>().WriteText(parameters[0], File.ReadAllText(parameters[1]), out bool unauthorized);
var res = Instance.Config.WriteText(parameters[0], File.ReadAllText(parameters[1]), out bool unauthorized);
if (res != null)
{
OutputProc("Error: " + res);
+6 -2
View File
@@ -5,8 +5,12 @@ namespace TGS.CommandLine
abstract class ConsoleCommand : Command
{
/// <summary>
/// The <see cref="IServerInterface"/> currently in use by the <see cref="Program"/>
/// The <see cref="IServer"/> currently in use by the <see cref="Program"/>
/// </summary>
public static IServerInterface Interface;
public static IServer Server;
/// <summary>
/// The <see cref="IInstance"/> currently in use by the <see cref="Program"/>
/// </summary>
public static IInstance Instance;
}
}
+10 -11
View File
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class DDCommand : InstanceRootCommand
class DDCommand : RootCommand
{
public DDCommand()
{
@@ -38,7 +37,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGDreamDaemon>().WorldAnnounce(String.Join(" ", parameters));
var res = Instance.DreamDaemon.WorldAnnounce(String.Join(" ", parameters));
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
@@ -58,7 +57,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGDreamDaemon>().Start();
var res = Instance.DreamDaemon.Start();
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
@@ -82,7 +81,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
var DD = Instance.DreamDaemon;
if (parameters.Count > 0 && parameters[0].ToLower() == "--graceful")
{
if (DD.DaemonStatus() != DreamDaemonStatus.Online)
@@ -111,7 +110,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
var DD = Instance.DreamDaemon;
if (parameters.Count > 0 && parameters[0].ToLower() == "--graceful")
{
if (DD.DaemonStatus() != DreamDaemonStatus.Online)
@@ -146,7 +145,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
var DD = Instance.DreamDaemon;
OutputProc(DD.StatusString(true));
if (DD.ShutdownInProgress())
OutputProc("The server will shutdown once the current round completes.");
@@ -167,7 +166,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
var DD = Instance.DreamDaemon;
switch (parameters[0].ToLower())
{
case "on":
@@ -205,7 +204,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
var DD = Instance.DreamDaemon;
switch (parameters[0].ToLower())
{
case "on":
@@ -255,7 +254,7 @@ namespace TGS.CommandLine
return ExitCode.BadCommand;
}
Interface.GetComponent<ITGDreamDaemon>().SetPort(port);
Instance.DreamDaemon.SetPort(port);
return ExitCode.Normal;
}
@@ -298,7 +297,7 @@ namespace TGS.CommandLine
OutputProc("Invalid security word!");
return ExitCode.BadCommand;
}
Interface.GetComponent<ITGDreamDaemon>().SetSecurityLevel(sec);
Instance.DreamDaemon.SetSecurityLevel(sec);
return ExitCode.Normal;
}
+8 -9
View File
@@ -2,11 +2,10 @@
using System.Collections.Generic;
using System.Threading;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class DMCommand : InstanceRootCommand
class DMCommand : RootCommand
{
public DMCommand()
{
@@ -28,7 +27,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var DM = Interface.GetComponent<ITGCompiler>();
var DM = Instance.Compiler;
var stat = DM.GetStatus();
if (stat != CompilerStatus.Initialized)
{
@@ -36,7 +35,7 @@ namespace TGS.CommandLine
return ExitCode.ServerError;
}
if (Interface.GetComponent<ITGByond>().GetVersion(ByondVersion.Installed) == null)
if (Instance.Byond.GetVersion(ByondVersion.Installed) == null)
{
Console.Write("Error: BYOND is not installed!");
return ExitCode.ServerError;
@@ -84,14 +83,14 @@ namespace TGS.CommandLine
void ShowError()
{
var error = Interface.GetComponent<ITGCompiler>().CompileError();
var error = Instance.Compiler.CompileError();
if (error != null)
OutputProc("Last error: " + error);
}
protected override ExitCode Run(IList<string> parameters)
{
var DM = Interface.GetComponent<ITGCompiler>();
var DM = Instance.Compiler;
OutputProc(String.Format("Target Project: /{0}.dme", DM.ProjectName()));
Console.Write("Compilier is currently: ");
switch (DM.GetStatus())
@@ -142,7 +141,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
Interface.GetComponent<ITGCompiler>().SetProjectName(parameters[0]);
Instance.Compiler.SetProjectName(parameters[0]);
return ExitCode.Normal;
}
}
@@ -166,7 +165,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var DM = Interface.GetComponent<ITGCompiler>();
var DM = Instance.Compiler;
var stat = DM.GetStatus();
if (stat == CompilerStatus.Compiling || stat == CompilerStatus.Initializing)
{
@@ -206,7 +205,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGCompiler>().Cancel();
var res = Instance.Compiler.Cancel();
OutputProc(res ?? "Success!");
return ExitCode.Normal; //because failing cancellation implys it's already cancelled
}
-33
View File
@@ -1,33 +0,0 @@
using System.Collections.Generic;
using TGS.Interface;
namespace TGS.CommandLine
{
abstract class InstanceRootCommand : RootCommand
{
public static IServerInterface currentInterface;
public override ExitCode DoRun(IList<string> parameters)
{
if (currentInterface.InstanceName == null)
{
OutputProc("Missing instance!");
return ExitCode.BadCommand;
}
else
{
var res = currentInterface.ConnectToInstance();
if (!res.HasFlag(ConnectivityLevel.Connected))
{
OutputProc("Unable to connect to instance!");
return ExitCode.ConnectionError;
}
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
{
OutputProc("The current user is not authorized to use this instance!");
return ExitCode.ConnectionError;
}
}
return base.DoRun(parameters);
}
}
}
+20 -22
View File
@@ -9,7 +9,7 @@ namespace TGS.CommandLine
class Program
{
static bool interactive = false, saidSrvVersion = false;
static IServerInterface currentInterface;
static IClient currentInterface;
static Command.ExitCode RunCommandLine(IList<string> argsAsList)
{
//first lookup the connection string
@@ -52,7 +52,7 @@ namespace TGS.CommandLine
}
argsAsList.RemoveAt(I);
argsAsList.RemoveAt(I);
ReplaceInterface(new ServerInterface(new RemoteLoginInfo(address, port, username, password)));
ReplaceInterface(new Client(new RemoteLoginInfo(address, port, username, password)));
break;
}
}
@@ -84,7 +84,7 @@ namespace TGS.CommandLine
}
else if (interactive && !saidSrvVersion)
{
Console.WriteLine("Connectd to service version: " + currentInterface.GetServiceComponent<ITGLanding>().Version());
Console.WriteLine("Connectd to service version: " + currentInterface.Server.Version);
saidSrvVersion = true;
}
@@ -99,11 +99,11 @@ namespace TGS.CommandLine
};
}
static void ReplaceInterface(IServerInterface I)
static void ReplaceInterface(IClient I)
{
currentInterface = I;
ConsoleCommand.Interface = I;
InstanceRootCommand.currentInterface = I;
ConsoleCommand.Server = I.Server;
ConsoleCommand.Instance = null;
saidSrvVersion = false;
}
@@ -156,26 +156,24 @@ namespace TGS.CommandLine
/// </summary>
/// <param name="instanceName">The name of the <see cref="ITGInstance"/> to test</param>
/// <param name="silentSuccess">If <see langword="true"/>, does not output on success</param>
/// <returns><see langword="true"/> if a <see cref="ConnectivityLevel.Authenticated"/> was achieved with <see cref="IServerInterface.ConnectToInstance(string, bool)"/>, <see langword="false"/> otherwise</returns>
/// <returns><see langword="true"/> if the connection was made, <see langword="false"/> otherwise</returns>
static bool CheckInstanceConnectivity(string instanceName, bool silentSuccess)
{
var res = currentInterface.ConnectToInstance(instanceName);
if (!res.HasFlag(ConnectivityLevel.Connected))
Console.WriteLine("Unable to connect to instance! Does it exist?");
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
Console.WriteLine("The current user is not authorized to use this instance!");
else
var res = currentInterface.Server.Instances.Where(x => x.Metadata.Name == instanceName).FirstOrDefault();
if (res != null)
{
if(!silentSuccess)
ConsoleCommand.Instance = res;
if (!silentSuccess)
Console.WriteLine("Successfully conected to instance!");
return true;
}
Console.WriteLine("Unable to connect to instance! Does it exist?");
return false;
}
static int Main(string[] args)
{
ReplaceInterface(new ServerInterface());
ReplaceInterface(new Client());
Command.OutputProcVar.Value = Console.WriteLine;
if (args.Length != 0)
{
@@ -193,13 +191,13 @@ namespace TGS.CommandLine
{
argsAsList.RemoveAt(I);
--I;
ServerInterface.SetBadCertificateHandler(_ => false);
Client.SetBadCertificateHandler(_ => false);
}
}
return (int)RunCommandLine(argsAsList);
}
//interactive mode
ServerInterface.SetBadCertificateHandler(BadCertificateInteractive);
Client.SetBadCertificateHandler(BadCertificateInteractive);
Console.WriteLine("Type 'instance' to connect to a server instance");
Console.WriteLine("Type 'remote' to connect to a remote service");
while (true)
@@ -230,17 +228,17 @@ namespace TGS.CommandLine
var username = Console.ReadLine();
Console.Write("Enter password: ");
var password = ReadLineSecure();
ReplaceInterface(new ServerInterface(new RemoteLoginInfo(address, port, username, password)));
ReplaceInterface(new Client(new RemoteLoginInfo(address, port, username, password)));
var res = currentInterface.ConnectionStatus(out string error);
if (!res.HasFlag(ConnectivityLevel.Connected))
{
Console.WriteLine("Unable to connect: " + error);
ReplaceInterface(new ServerInterface());
ReplaceInterface(new Client());
}
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
{
Console.WriteLine("Authentication error: Username/password/windows identity is not authorized! Returning to local mode...");
ReplaceInterface(new ServerInterface());
ReplaceInterface(new Client());
}
else
{
@@ -255,14 +253,14 @@ namespace TGS.CommandLine
break;
case "disconnect":
SentVMMWarning = false;
ReplaceInterface(new ServerInterface());
ReplaceInterface(new Client());
Console.WriteLine("Switch to local mode");
break;
case "quit":
case "exit":
return (int)Command.ExitCode.Normal;
case "debug-upgrade":
currentInterface.GetServiceComponent<ITGSService>().PrepareForUpdate();
currentInterface.Server.Management.PrepareForUpdate();
return (int)Command.ExitCode.Normal;
default:
//linq voodoo to get quoted strings
+15 -16
View File
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
@@ -40,10 +39,10 @@ namespace TGS.CommandLine
switch (parameters[0].ToLower())
{
case "on":
Interface.GetComponent<ITGRepository>().SetPushTestmergeCommits(true);
Instance.Repository.SetPushTestmergeCommits(true);
break;
case "off":
Interface.GetComponent<ITGRepository>().SetPushTestmergeCommits(false);
Instance.Repository.SetPushTestmergeCommits(false);
break;
default:
OutputProc("Invalid option!");
@@ -67,7 +66,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGRepository>().UpdateTGS3Json();
var res = Instance.Repository.UpdateTGS3Json();
if (res != null)
{
OutputProc(res);
@@ -86,7 +85,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGRepository>().Setup(parameters[0], parameters.Count > 1 ? parameters[1] : "master");
var res = Instance.Repository.Setup(parameters[0], parameters.Count > 1 ? parameters[1] : "master");
if (res != null)
{
OutputProc("Error: " + res);
@@ -113,7 +112,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var Repo = Interface.GetComponent<ITGRepository>();
var Repo = Instance.Repository;
var busy = Repo.OperationInProgress();
if (!busy)
{
@@ -167,7 +166,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var result = Interface.GetComponent<ITGRepository>().Reset(parameters.Count > 0 && parameters[0].ToLower() == "--origin");
var result = Instance.Repository.Reset(parameters.Count > 0 && parameters[0].ToLower() == "--origin");
OutputProc(result ?? "Success!");
return result == null ? ExitCode.Normal : ExitCode.ServerError;
}
@@ -203,7 +202,7 @@ namespace TGS.CommandLine
OutputProc("Invalid parameter: " + parameters[0]);
return ExitCode.BadCommand;
}
var res = Interface.GetComponent<ITGRepository>().Update(hard);
var res = Instance.Repository.Update(hard);
OutputProc(res ?? "Success");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
@@ -224,7 +223,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var result = Interface.GetComponent<ITGRepository>().GenerateChangelog(out string error);
var result = Instance.Repository.GenerateChangelog(out string error);
OutputProc(error ?? "Success!");
if (result != null)
OutputProc(result);
@@ -244,7 +243,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var result = Interface.GetComponent<ITGRepository>().SynchronizePush();
var result = Instance.Repository.SynchronizePush();
if(result != null)
OutputProc(result);
return result == null ? ExitCode.Normal : ExitCode.ServerError;
@@ -264,7 +263,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
Interface.GetComponent<ITGRepository>().SetCommitterEmail(parameters[0]);
Instance.Repository.SetCommitterEmail(parameters[0]);
return ExitCode.Normal;
}
@@ -286,7 +285,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
Interface.GetComponent<ITGRepository>().SetCommitterName(parameters[0]);
Instance.Repository.SetCommitterName(parameters[0]);
return ExitCode.Normal;
}
public override string GetArgumentString()
@@ -319,7 +318,7 @@ namespace TGS.CommandLine
OutputProc("Invalid PR Number!");
return ExitCode.BadCommand;
}
var res = Interface.GetComponent<ITGRepository>().MergePullRequest(PR);
var res = Instance.Repository.MergePullRequest(PR);
OutputProc(res ?? "Success");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
@@ -346,7 +345,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var data = Interface.GetComponent<ITGRepository>().MergedPullRequests(out string error);
var data = Instance.Repository.MergedPullRequests(out string error);
if (data == null)
{
OutputProc(error);
@@ -373,7 +372,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var data = Interface.GetComponent<ITGRepository>().ListBackups(out string error);
var data = Instance.Repository.ListBackups(out string error);
if (data == null)
{
OutputProc(error);
@@ -400,7 +399,7 @@ namespace TGS.CommandLine
}
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGRepository>().Checkout(parameters[0]);
var res = Instance.Repository.Checkout(parameters[0]);
OutputProc(res ?? "Success");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
+9 -10
View File
@@ -1,18 +1,17 @@
using System;
using System.Collections.Generic;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class CLICommand : RootCommand
{
public CLICommand(IServerInterface I)
public CLICommand(IClient I)
{
var tmp = new List<Command> { new UpdateCommand(), new TestmergeCommand(), new RepoCommand(), new BYONDCommand(), new DMCommand(), new DDCommand(), new ConfigCommand(), new IRCCommand(), new DiscordCommand(), new AutoUpdateCommand(), new SetAutoUpdateCommand() };
if (I.ConnectToInstance().HasFlag(ConnectivityLevel.Administrator))
if (ConsoleCommand.Instance.Administration != null)
tmp.Add(new AdminCommand());
if (I.ConnectionStatus().HasFlag(ConnectivityLevel.Administrator))
if (ConsoleCommand.Server.Management != null)
tmp.Add(new ServiceCommand());
Children = tmp.ToArray();
}
@@ -37,7 +36,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGRepository>().AutoUpdateInterval();
var res = Instance.Repository.AutoUpdateInterval();
OutputProc(res == 0 ? "OFF" : String.Format("Auto updating every {0} minutes", res));
return ExitCode.Normal;
}
@@ -76,7 +75,7 @@ namespace TGS.CommandLine
return ExitCode.BadCommand;
}
Interface.GetComponent<ITGRepository>().SetAutoUpdateInterval(NewInterval);
Instance.Repository.SetAutoUpdateInterval(NewInterval);
return ExitCode.Normal;
}
@@ -91,7 +90,7 @@ namespace TGS.CommandLine
protected override ExitCode Run(IList<string> parameters)
{
var gen_cl = parameters.Count > 1 && parameters[1].ToLower() == "--cl";
var Repo = Interface.GetComponent<ITGRepository>();
var Repo = Instance.Repository;
switch (parameters[0].ToLower())
{
case "hard":
@@ -126,7 +125,7 @@ namespace TGS.CommandLine
OutputProc(res);
}
}
var resu = Interface.GetComponent<ITGCompiler>().Compile(true);
var resu = Instance.Compiler.Compile(true);
OutputProc(resu ? "Compilation started!" : "Compilation could not be started!");
return resu ? ExitCode.Normal : ExitCode.ServerError;
}
@@ -163,7 +162,7 @@ namespace TGS.CommandLine
OutputProc("Invalid tesmerge #: " + parameters[0]);
return ExitCode.BadCommand;
}
var Repo = Interface.GetComponent<ITGRepository>();
var Repo = Instance.Repository;
var res = Repo.MergePullRequest(tm);
if (res != null)
{
@@ -176,7 +175,7 @@ namespace TGS.CommandLine
OutputProc(res);
return ExitCode.ServerError;
}
var resu = Interface.GetComponent<ITGCompiler>().Compile(true);
var resu = Instance.Compiler.Compile(true);
OutputProc(resu ? "Compilation started!" : "Compilation could not be started!");
return resu ? ExitCode.Normal : ExitCode.ServerError;
}
+13 -13
View File
@@ -55,7 +55,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetServiceComponent<ITGInstanceManager>().CreateInstance(parameters[0], parameters[1]);
var res = Server.InstanceManager.CreateInstance(parameters[0], parameters[1]);
if (res != null)
{
OutputProc(res);
@@ -87,8 +87,8 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
foreach (var I in Interface.GetServiceComponent<ITGLanding>().ListInstances())
OutputProc(String.Format("{0} ({1}):\t{2}{3}", I.Name, I.Path, I.Enabled ? "Online" : "Offline", I.Enabled ? String.Format(" ({0})", I.LoggingID) : ""));
foreach (var I in Server.Instances)
OutputProc(I.ToString());
return ExitCode.Normal;
}
}
@@ -122,7 +122,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetServiceComponent<ITGInstanceManager>().DetachInstance(parameters[0]);
var res = Server.InstanceManager.DetachInstance(parameters[0]);
if (res != null)
{
OutputProc(res);
@@ -161,7 +161,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetServiceComponent<ITGInstanceManager>().ImportInstance(parameters[0]);
var res = Server.InstanceManager.ImportInstance(parameters[0]);
if (res != null)
{
OutputProc(res);
@@ -193,7 +193,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetServiceComponent<ITGSService>().PythonPath();
var res = Server.Management.PythonPath();
if (res != null)
{
OutputProc(res);
@@ -232,7 +232,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
Interface.GetServiceComponent<ITGSService>().SetPythonPath(parameters[0]);
Server.Management.SetPythonPath(parameters[0]);
return ExitCode.Normal;
}
}
@@ -266,7 +266,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetServiceComponent<ITGInstanceManager>().SetInstanceEnabled(parameters[0], true);
var res = Server.InstanceManager.SetInstanceEnabled(parameters[0], true);
if (res != null)
{
OutputProc(res);
@@ -305,7 +305,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetServiceComponent<ITGInstanceManager>().SetInstanceEnabled(parameters[0], false);
var res = Server.InstanceManager.SetInstanceEnabled(parameters[0], false);
if (res != null)
{
OutputProc(res);
@@ -316,7 +316,7 @@ namespace TGS.CommandLine
}
/// <summary>
/// Command for calling <see cref="TGS.Interface.Components.ITGSService.RemoteAccessPort"/>
/// Command for calling <see cref="ITGSService.RemoteAccessPort"/>
/// </summary>
class ServiceRemoteAccessPortCommand : ConsoleCommand
{
@@ -337,7 +337,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
OutputProc(Interface.GetServiceComponent<ITGSService>().RemoteAccessPort().ToString());
OutputProc(Server.Management.RemoteAccessPort().ToString());
return ExitCode.Normal;
}
}
@@ -382,7 +382,7 @@ namespace TGS.CommandLine
return ExitCode.BadCommand;
}
var res = Interface.GetServiceComponent<ITGSService>().SetRemoteAccessPort(port);
var res = Server.Management.SetRemoteAccessPort(port);
if (res != null)
{
OutputProc(res);
@@ -422,7 +422,7 @@ namespace TGS.CommandLine
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetServiceComponent<ITGInstanceManager>().RenameInstance(parameters[0], parameters[1]);
var res = Server.InstanceManager.RenameInstance(parameters[0], parameters[1]);
if (res != null)
{
OutputProc(res);
-1
View File
@@ -51,7 +51,6 @@
<Compile Include="DDCommands.cs" />
<Compile Include="DMCommands.cs" />
<Compile Include="ChatCommands.cs" />
<Compile Include="InstanceRootCommand.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RepoCommands.cs" />
+4 -4
View File
@@ -10,7 +10,7 @@ namespace TGS.ControlPanel
string lastReadError = null;
void InitBYONDPage()
{
var BYOND = Interface.GetComponent<ITGByond>();
var BYOND = Instance.Byond;
var CV = BYOND.GetVersion(ByondVersion.Installed);
if (CV == null)
CV = BYOND.GetVersion(ByondVersion.Staged);
@@ -45,7 +45,7 @@ namespace TGS.ControlPanel
private void UpdateButton_Click(object sender, EventArgs e)
{
UpdateBYONDButtons();
if (!Interface.GetComponent<ITGByond>().UpdateToVersion((int)MajorVersionNumeric.Value, (int)MinorVersionNumeric.Value))
if (!Instance.Byond.UpdateToVersion((int)MajorVersionNumeric.Value, (int)MinorVersionNumeric.Value))
MessageBox.Show("Unable to begin update, there is another operation in progress.");
}
@@ -55,7 +55,7 @@ namespace TGS.ControlPanel
}
void UpdateBYONDButtons()
{
var BYOND = Interface.GetComponent<ITGByond>();
var BYOND = Instance.Byond;
VersionLabel.Text = BYOND.GetVersion(ByondVersion.Installed) ?? "Not Installed";
@@ -88,7 +88,7 @@ namespace TGS.ControlPanel
UpdateButton.Enabled = false;
break;
}
var error = Interface.GetComponent<ITGByond>().GetError();
var error = Instance.Byond.GetError();
if (error != lastReadError)
{
lastReadError = error;
+4 -4
View File
@@ -19,7 +19,7 @@ namespace TGS.ControlPanel
void LoadChatPage()
{
updatingChat = true;
var Chat = Interface.GetComponent<ITGChat>();
var Chat = Instance.Chat;
var PI = Chat.ProviderInfos()[(int)ModifyingProvider];
ChatAdminsTextBox.Visible = true;
IRCModesComboBox.Visible = false;
@@ -112,7 +112,7 @@ namespace TGS.ControlPanel
private void ChatReconnectButton_Click(object sender, EventArgs e)
{
Interface.GetComponent<ITGChat>().Reconnect(ModifyingProvider);
Instance.Chat.Reconnect(ModifyingProvider);
LoadChatPage();
}
@@ -149,7 +149,7 @@ namespace TGS.ControlPanel
}
void SetAdminsAreSpecial(bool value)
{
var Chat = Interface.GetComponent<ITGChat>();
var Chat = Instance.Chat;
var PI = Chat.ProviderInfos()[(int)ModifyingProvider];
PI.AdminsAreSpecial = value;
var res = Chat.SetProviderInfo(PI);
@@ -208,7 +208,7 @@ namespace TGS.ControlPanel
wip.Enabled = ChatEnabledCheckbox.Checked;
wip.AdminsAreSpecial = AdminModeSpecial.Checked;
res = Interface.GetComponent<ITGChat>().SetProviderInfo(wip);
res = Instance.Chat.SetProviderInfo(wip);
}
if (res != null)
MessageBox.Show(res);
+17 -14
View File
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.ControlPanel
{
@@ -18,29 +17,34 @@ namespace TGS.ControlPanel
public static IDictionary<string, ControlPanel> InstancesInUse { get; private set; } = new Dictionary<string, ControlPanel>();
/// <summary>
/// The <see cref="IServerInterface"/> instance for this <see cref="ControlPanel"/>
/// The <see cref="IInstance"/> for this <see cref="ControlPanel"/>
/// </summary>
readonly IServerInterface Interface;
readonly IInstance Instance;
/// <summary>
/// Constructs a <see cref="ControlPanel"/>
/// </summary>
/// <param name="I">The <see cref="IServerInterface"/> for the <see cref="ControlPanel"/></param>
public ControlPanel(IServerInterface I)
/// <param name="server">The <see cref="IServer"/> to use</param>
/// <param name="instance">The <see cref="IInstance"/> to use</param>
public ControlPanel(IServer server, IInstance instance)
{
InitializeComponent();
FormClosed += ControlPanel_FormClosed;
Interface = I;
if (Interface.IsRemoteConnection)
Text = String.Format("TGS {0}: {1}:{2}", Interface.ServerVersion, Interface.LoginInfo.IP, Interface.LoginInfo.Port);
Text = String.Format("{0} Instance: {1}", Text, I.InstanceName);
Panels.SelectedIndexChanged += Panels_SelectedIndexChanged;
Panels.SelectedIndex += Math.Min(Properties.Settings.Default.LastPageIndex, Panels.TabCount - 1);
Instance = instance;
InstancesInUse.Add(Instance.Metadata.Name, this);
Text = String.Format("TGS {0} Instance: {1}", server.Version, Instance.Metadata.Name);
InitRepoPage();
InitBYONDPage();
InitServerPage();
UpdateSelectedPanel();
InstancesInUse.Add(I.InstanceName, this);
}
/// <summary>
@@ -50,7 +54,7 @@ namespace TGS.ControlPanel
/// <param name="e">The <see cref="EventArgs"/></param>
void ControlPanel_FormClosed(object sender, FormClosedEventArgs e)
{
InstancesInUse.Remove(Interface.InstanceName);
InstancesInUse.Remove(Instance.Metadata.Name);
}
/// <summary>
@@ -58,8 +62,7 @@ namespace TGS.ControlPanel
/// </summary>
void Cleanup()
{
InstancesInUse.Remove(Interface.InstanceName);
Interface.Dispose();
InstancesInUse.Remove(Instance.Metadata.Name);
}
private void Main_Resize(object sender, EventArgs e)
@@ -102,7 +105,7 @@ namespace TGS.ControlPanel
bool CheckAdminWithWarning()
{
if (!Interface.ConnectToInstance().HasFlag(ConnectivityLevel.Administrator))
if (Instance.Administration != null)
{
MessageBox.Show("Only system administrators may use this command!");
return false;
+5 -5
View File
@@ -76,7 +76,7 @@ namespace TGS.ControlPanel
if (RepoBusyCheck())
return;
var Repo = Interface.GetComponent<ITGRepository>();
var Repo = Instance.Repository;
RepoProgressBar.Style = ProgressBarStyle.Marquee;
RepoProgressBar.Visible = false;
@@ -148,7 +148,7 @@ namespace TGS.ControlPanel
bool RepoBusyCheck()
{
if (Interface.GetComponent<ITGRepository>().OperationInProgress())
if (Instance.Repository.OperationInProgress())
{
DoAsyncOp(RepoAction.Wait, "Waiting for repository to finish another action...");
return true;
@@ -170,7 +170,7 @@ namespace TGS.ControlPanel
private void RepoBGW_DoWork(object sender, DoWorkEventArgs e)
{
//Only for clones
var Repo = Interface.GetComponent<ITGRepository>();
var Repo = Instance.Repository;
switch (action) {
case RepoAction.Clone:
@@ -273,7 +273,7 @@ namespace TGS.ControlPanel
}
private void RepoApplyButton_Click(object sender, EventArgs e)
{
var Repo = Interface.GetComponent<ITGRepository>();
var Repo = Instance.Repository;
if (RepoBusyCheck())
return;
@@ -344,7 +344,7 @@ namespace TGS.ControlPanel
{
if (MessageBox.Show("This will update the cached TGS3.json to the current repository version, potentially redefining symlinks. Proceed?", "Json Update", MessageBoxButtons.YesNo) != DialogResult.Yes)
return;
var res = Interface.GetComponent<ITGRepository>().UpdateTGS3Json();
var res = Instance.Repository.UpdateTGS3Json();
if (res != null)
MessageBox.Show(res);
}
+28 -28
View File
@@ -46,7 +46,7 @@ namespace TGS.ControlPanel
private void CompileCancelButton_Click(object sender, EventArgs e)
{
var res = Interface.GetComponent<ITGCompiler>().Cancel();
var res = Instance.Compiler.Cancel();
if (res != null)
MessageBox.Show(res);
LoadServerPage();
@@ -54,7 +54,7 @@ namespace TGS.ControlPanel
void LoadServerPage()
{
var RepoExists = Interface.GetComponent<ITGRepository>().Exists();
var RepoExists = Instance.Repository.Exists();
compileButton.Visible = RepoExists;
AutoUpdateCheckbox.Visible = RepoExists;
initializeButton.Visible = RepoExists;
@@ -83,16 +83,16 @@ namespace TGS.ControlPanel
if (updatingFields)
return;
var DM = Interface.GetComponent<ITGCompiler>();
var DD = Interface.GetComponent<ITGDreamDaemon>();
var Config = Interface.GetComponent<ITGConfig>();
var Repo = Interface.GetComponent<ITGRepository>();
var DM = Instance.Compiler;
var DD = Instance.DreamDaemon;
var Config = Instance.Config;
var Repo = Instance.Repository;
try
{
updatingFields = true;
ServerPathLabel.Text = "Server Path: " + Interface.GetComponent<ITGInstance>().ServerDirectory();
ServerPathLabel.Text = "Server Path: " + Instance.ServerDirectory();
SecuritySelector.SelectedIndex = (int)DD.SecurityLevel();
@@ -197,13 +197,13 @@ namespace TGS.ControlPanel
void UpdateProjectName()
{
if (!updatingFields)
Interface.GetComponent<ITGCompiler>().SetProjectName(projectNameText.Text);
Instance.Compiler.SetProjectName(projectNameText.Text);
}
private void PortSelector_ValueChanged(object sender, EventArgs e)
{
if (!updatingFields)
Interface.GetComponent<ITGDreamDaemon>().SetPort((ushort)PortSelector.Value);
Instance.DreamDaemon.SetPort((ushort)PortSelector.Value);
}
private void ServerPageRefreshButton_Click(object sender, EventArgs e)
@@ -213,13 +213,13 @@ namespace TGS.ControlPanel
private void InitializeButton_Click(object sender, EventArgs e)
{
if (!Interface.GetComponent<ITGCompiler>().Initialize())
if (!Instance.Compiler.Initialize())
MessageBox.Show("Unable to start initialization!");
LoadServerPage();
}
private void CompileButton_Click(object sender, EventArgs e)
{
if (!Interface.GetComponent<ITGCompiler>().Compile())
if (!Instance.Compiler.Compile())
MessageBox.Show("Unable to start compilation!");
LoadServerPage();
}
@@ -227,7 +227,7 @@ namespace TGS.ControlPanel
private void AutostartCheckbox_CheckedChanged(object sender, System.EventArgs e)
{
if (!updatingFields)
Interface.GetComponent<ITGDreamDaemon>().SetAutostart(AutostartCheckbox.Checked);
Instance.DreamDaemon.SetAutostart(AutostartCheckbox.Checked);
}
private void ServerStartButton_Click(object sender, System.EventArgs e)
{
@@ -239,7 +239,7 @@ namespace TGS.ControlPanel
{
try
{
e.Result = Interface.GetComponent<ITGDreamDaemon>().Start();
e.Result = Instance.DreamDaemon.Start();
}
catch (Exception ex)
{
@@ -252,7 +252,7 @@ namespace TGS.ControlPanel
var DialogResult = MessageBox.Show("This will immediately shut down the server. Continue?", "Confim", MessageBoxButtons.YesNo);
if (DialogResult == DialogResult.No)
return;
var res = Interface.GetComponent<ITGDreamDaemon>().Stop();
var res = Instance.DreamDaemon.Stop();
if (res != null)
MessageBox.Show(res);
}
@@ -262,7 +262,7 @@ namespace TGS.ControlPanel
var DialogResult = MessageBox.Show("This will immediately restart the server. Continue?", "Confim", MessageBoxButtons.YesNo);
if (DialogResult == DialogResult.No)
return;
var res = Interface.GetComponent<ITGDreamDaemon>().Restart();
var res = Instance.DreamDaemon.Restart();
if (res != null)
MessageBox.Show(res);
}
@@ -274,7 +274,7 @@ namespace TGS.ControlPanel
var DialogResult = MessageBox.Show("This will shut down the server when the current round ends. Continue?", "Confim", MessageBoxButtons.YesNo);
if (DialogResult == DialogResult.No)
return;
Interface.GetComponent<ITGDreamDaemon>().RequestStop();
Instance.DreamDaemon.RequestStop();
LoadServerPage();
}
@@ -283,7 +283,7 @@ namespace TGS.ControlPanel
var DialogResult = MessageBox.Show("This will restart the server when the current round ends. Continue?", "Confim", MessageBoxButtons.YesNo);
if (DialogResult == DialogResult.No)
return;
Interface.GetComponent<ITGDreamDaemon>().RequestRestart();
Instance.DreamDaemon.RequestRestart();
}
/// <summary>
@@ -293,7 +293,7 @@ namespace TGS.ControlPanel
/// <param name="e">The <see cref="EventArgs"/></param>
void TestMergeManagerButton_Click(object sender, System.EventArgs e)
{
using (var TMM = new TestMergeManager(Interface, ghclient))
using (var TMM = new TestMergeManager(Instance, ghclient))
TMM.ShowDialog();
LoadServerPage();
}
@@ -320,7 +320,7 @@ namespace TGS.ControlPanel
try
{
string res = null;
var repo = Interface.GetComponent<ITGRepository>();
var repo = Instance.Repository;
var pulls = await Task.Run(() => repo.MergedPullRequests(out res));
if (pulls == null)
@@ -364,7 +364,7 @@ namespace TGS.ControlPanel
pulls.RemoveAll(x => x.Number == I.Result.Number);
var mergeResults = await Task.Run(() => repo.MergePullRequests(pulls, true));
var compileStartResult = await Task.Run(() => Interface.GetComponent<ITGCompiler>().Compile(true));
var compileStartResult = await Task.Run(() => Instance.Compiler.Compile(true));
//Show any errors
for (var I = 0; I < mergeResults.Count(); ++I)
@@ -410,7 +410,7 @@ namespace TGS.ControlPanel
Enabled = false;
try
{
var repo = Interface.GetComponent<ITGRepository>();
var repo = Instance.Repository;
var res = await Task.Run(() => repo.Reset(true));
@@ -425,7 +425,7 @@ namespace TGS.ControlPanel
if (res != null)
MessageBox.Show(res, "Error generating changelog");
await Task.Run(() => Interface.GetComponent<ITGCompiler>().Compile(false));
await Task.Run(() => Instance.Compiler.Compile(false));
if (res != null)
MessageBox.Show(res, "Error starting compile!");
}
@@ -452,7 +452,7 @@ namespace TGS.ControlPanel
private void SecuritySelector_SelectedIndexChanged(object sender, EventArgs e)
{
if (!updatingFields)
if (!Interface.GetComponent<ITGDreamDaemon>().SetSecurityLevel((DreamDaemonSecurity)SecuritySelector.SelectedIndex))
if (!Instance.DreamDaemon.SetSecurityLevel((DreamDaemonSecurity)SecuritySelector.SelectedIndex))
MessageBox.Show("Security change will be applied after next server reboot.");
}
@@ -461,7 +461,7 @@ namespace TGS.ControlPanel
var msg = WorldAnnounceField.Text;
if (!String.IsNullOrWhiteSpace(msg))
{
var res = Interface.GetComponent<ITGDreamDaemon>().WorldAnnounce(msg);
var res = Instance.DreamDaemon.WorldAnnounce(msg);
if (res != null)
{
MessageBox.Show(res);
@@ -474,13 +474,13 @@ namespace TGS.ControlPanel
private void WebclientCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (!updatingFields)
Interface.GetComponent<ITGDreamDaemon>().SetWebclient(WebclientCheckBox.Checked);
Instance.DreamDaemon.SetWebclient(WebclientCheckBox.Checked);
}
private void AutoUpdateInterval_ValueChanged(object sender, EventArgs e)
{
if (!updatingFields)
Interface.GetComponent<ITGRepository>().SetAutoUpdateInterval((ulong)AutoUpdateInterval.Value);
Instance.Repository.SetAutoUpdateInterval((ulong)AutoUpdateInterval.Value);
}
private void AutoUpdateCheckbox_CheckedChanged(object sender, EventArgs e)
@@ -491,9 +491,9 @@ namespace TGS.ControlPanel
AutoUpdateInterval.Visible = on;
AutoUpdateMLabel.Visible = on;
if (!on)
Interface.GetComponent<ITGRepository>().SetAutoUpdateInterval(0);
Instance.Repository.SetAutoUpdateInterval(0);
else
Interface.GetComponent<ITGRepository>().SetAutoUpdateInterval((ulong)AutoUpdateInterval.Value);
Instance.Repository.SetAutoUpdateInterval((ulong)AutoUpdateInterval.Value);
}
}
}
+9 -9
View File
@@ -29,7 +29,7 @@ namespace TGS.ControlPanel
{
if (initializedStaticPage)
return;
if(!Interface.ConnectToInstance().HasFlag(ConnectivityLevel.Administrator))
if(Instance.Administration != null)
RecreateStaticButton.Visible = false;
BuildFileList();
initializedStaticPage = true;
@@ -41,7 +41,7 @@ namespace TGS.ControlPanel
IndexesToPaths.Clear();
StaticFileListBox.Items.Clear();
IndexesToPaths.Add(StaticFileListBox.Items.Add("/"), "/");
if (EnumeratePath("", Interface.GetComponent<ITGConfig>(), 1) == EnumResult.Unauthorized)
if (EnumeratePath("", Instance.Config, 1) == EnumResult.Unauthorized)
{
StaticFileListBox.Items[0] += " (UNAUTHORIZED)";
IndexesToPaths[0] = null;
@@ -147,7 +147,7 @@ namespace TGS.ControlPanel
if (error == null)
try
{
error = Interface.GetComponent<ITGConfig>().WriteText(FileName, fileContents, out bool unauthorized);
error = Instance.Config.WriteText(FileName, fileContents, out bool unauthorized);
}
catch (Exception ex)
{
@@ -171,7 +171,7 @@ namespace TGS.ControlPanel
string text, error;
try
{
text = Interface.GetComponent<ITGConfig>().ReadText(remotePath, false, out error, out bool unauthorized);
text = Instance.Config.ReadText(remotePath, false, out error, out bool unauthorized);
}
catch (Exception ex)
{
@@ -213,7 +213,7 @@ namespace TGS.ControlPanel
{
if (MessageBox.Show("Are you sure you want to delete " + ((string)StaticFileListBox.SelectedItem).Trim() + "?", "Confirm", MessageBoxButtons.YesNo) != DialogResult.Yes)
return;
var res = Interface.GetComponent<ITGConfig>().DeleteFile(IndexesToPaths[StaticFileListBox.SelectedIndex], out bool unauthorized);
var res = Instance.Config.DeleteFile(IndexesToPaths[StaticFileListBox.SelectedIndex], out bool unauthorized);
if (res != null)
MessageBox.Show(res);
BuildFileList();
@@ -236,7 +236,7 @@ namespace TGS.ControlPanel
var FullFileName = Path.Combine(IndexesToPaths[StaticFileListBox.SelectedIndex], FileName);
if (resu == DialogResult.Yes)
FullFileName = Path.Combine(FullFileName, "__TGS3_CP_DIRECTORY_CREATOR__");
var config = Interface.GetComponent<ITGConfig>();
var config = Instance.Config;
var res = config.WriteText(FullFileName, "", out bool unauthorized);
if (res != null)
MessageBox.Show(res);
@@ -255,7 +255,7 @@ namespace TGS.ControlPanel
bool unauthorized;
try
{
res = Interface.GetComponent<ITGConfig>().WriteText(IndexesToPaths[index], StaticFileEditTextbox.Text, out unauthorized);
res = Instance.Config.WriteText(IndexesToPaths[index], StaticFileEditTextbox.Text, out unauthorized);
}
catch (Exception ex)
{
@@ -307,7 +307,7 @@ namespace TGS.ControlPanel
bool unauthorized;
try
{
entry = Interface.GetComponent<ITGConfig>().ReadText(path, false, out error, out unauthorized);
entry = Instance.Config.ReadText(path, false, out error, out unauthorized);
}
catch(Exception e)
{
@@ -344,7 +344,7 @@ namespace TGS.ControlPanel
RecreateStaticButton.Visible = false;
return;
}
var res = Interface.GetComponent<ITGAdministration>().RecreateStaticFolder();
var res = Instance.Administration.RecreateStaticFolder();
if (res != null)
MessageBox.Show(res);
BuildFileList();
-1
View File
@@ -15,7 +15,6 @@
{
if (disposing && (components != null))
{
Cleanup();
components.Dispose();
}
base.Dispose(disposing);
+34 -70
View File
@@ -3,23 +3,18 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.ControlPanel
{
/// <summary>
/// Form used for managing <see cref="ITGSService"/> <see cref="ITGInstance"/> manipulation functions
/// Form used for managing <see cref="IInstance"/>s
/// </summary>
sealed partial class InstanceSelector : CountedForm
{
/// <summary>
/// The <see cref="IServerInterface"/> we build instance connections from
/// The <see cref="IServer"/> we build instance connections from
/// </summary>
readonly IServerInterface masterInterface;
/// <summary>
/// List of <see cref="InstanceMetadata"/> from <see cref="masterInterface"/>
/// </summary>
IList<InstanceMetadata> InstanceData;
readonly IServer server;
/// <summary>
/// Used for modifying <see cref="EnabledCheckBox"/> without invoking its side effects
/// </summary>
@@ -28,17 +23,17 @@ namespace TGS.ControlPanel
/// <summary>
/// Construct an <see cref="InstanceSelector"/>
/// </summary>
/// <param name="I">An <see cref="IServerInterface"/> connected a the <see cref="ITGSService"/></param>
public InstanceSelector(IServerInterface I)
/// <param name="_server">The value of <see cref="server"/></param>
public InstanceSelector(IServer _server)
{
InitializeComponent();
InstanceListBox.MouseDoubleClick += InstanceListBox_MouseDoubleClick;
masterInterface = I;
server = _server;
RefreshInstances();
}
/// <summary>
/// Connects to a <see cref="ITGInstance"/> if it is double clicked in <see cref="InstanceListBox"/>
/// Connects to a <see cref="IInstance"/> if it is double clicked in <see cref="InstanceListBox"/>
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">The <see cref="MouseEventArgs"/></param>
@@ -53,36 +48,25 @@ namespace TGS.ControlPanel
/// <returns>The <see cref="InstanceMetadata"/> associated with <see cref="InstanceListBox"/>'s current selected index if it exists, <see langword="null"/> otherwise</returns>
InstanceMetadata GetSelectedInstanceMetadata()
{
var index = InstanceListBox.SelectedIndex;
return index != ListBox.NoMatches ? InstanceData[index] : null;
var index = (IInstance)InstanceListBox.SelectedItem;
return index?.Metadata;
}
/// <summary>
/// Called by <see cref="Dispose(bool)"/>
/// Loads the <see cref="InstanceListBox"/> using <see cref="Interface.Components.ITGLanding.ListInstances"/>
/// </summary>
void Cleanup()
{
masterInterface.Dispose();
}
/// <summary>
/// Loads the <see cref="InstanceListBox"/> using <see cref="ITGLanding.ListInstances"/>
/// </summary>
async void RefreshInstances()
void RefreshInstances()
{
InstanceListBox.Items.Clear();
await WrapServerOp(() => {
InstanceData = masterInterface.GetServiceComponent<ITGLanding>().ListInstances();
});
foreach(var I in InstanceData)
InstanceListBox.Items.Add(String.Format("{0}: {1} - {2} - {3}", I.LoggingID, I.Name, I.Path, I.Enabled ? "ONLINE" : "OFFLINE"));
var HasServerAdmin = masterInterface.ConnectionStatus().HasFlag(ConnectivityLevel.Administrator);
foreach(var I in server.Instances)
InstanceListBox.Items.Add(I);
var HasServerAdmin = server.InstanceManager != null;
CreateInstanceButton.Enabled = HasServerAdmin;
ImportInstanceButton.Enabled = HasServerAdmin;
RenameInstanceButton.Enabled = HasServerAdmin;
DetachInstanceButton.Enabled = HasServerAdmin;
EnabledCheckBox.Enabled = HasServerAdmin;
if(InstanceData.Count > 0)
if(InstanceListBox.Items.Count > 0)
InstanceListBox.SelectedIndex = 0;
}
@@ -90,40 +74,22 @@ namespace TGS.ControlPanel
/// Tries to start a <see cref="ControlPanel"/> for a given <see cref="InstanceListBox"/> <paramref name="index"/>
/// </summary>
/// <param name="index">The <see cref="ListBox.SelectedIndex"/> of <see cref="InstanceListBox"/> to connect to</param>
async void TryConnectToIndexInstance(int index)
void TryConnectToIndexInstance(int index)
{
if (index == ListBox.NoMatches)
return;
var instanceName = InstanceData[index].Name;
if (ControlPanel.InstancesInUse.TryGetValue(instanceName, out ControlPanel activeCP))
var instance = (IInstance)InstanceListBox.Items[index];
if (ControlPanel.InstancesInUse.TryGetValue(instance.Metadata.Name, out ControlPanel activeCP))
{
activeCP.BringToFront();
return;
}
var InstanceAccessor = masterInterface.IsRemoteConnection ? new ServerInterface(masterInterface.LoginInfo) : new ServerInterface();
try
{
ConnectivityLevel res = ConnectivityLevel.None;
await WrapServerOp(() => { res = InstanceAccessor.ConnectToInstance(instanceName); });
if (!res.HasFlag(ConnectivityLevel.Connected))
{
MessageBox.Show("Unable to connect to instance! Does it exist?");
RefreshInstances();
}
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
MessageBox.Show("The current user is not authorized to access this instance!");
else
new ControlPanel(InstanceAccessor).Show();
}
catch
{
InstanceAccessor.Dispose();
throw;
}
new ControlPanel(server, instance).Show();
}
/// <summary>
/// Prompts the user for parameters to <see cref="ITGInstanceManager.DetachInstance(string)"/>
/// Prompts the user for parameters to <see cref="Interface.Components.ITGInstanceManager.DetachInstance(string)"/>
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">The <see cref="EventArgs"/></param>
@@ -135,7 +101,7 @@ namespace TGS.ControlPanel
if (MessageBox.Show(String.Format("This will dissociate the server instance at \"{0}\"! Are you sure?", imd.Path), "Instance Detach", MessageBoxButtons.YesNo) != DialogResult.Yes)
return;
string res = null;
await WrapServerOp(() => res = masterInterface.GetServiceComponent<ITGInstanceManager>().DetachInstance(imd.Name));
await WrapServerOp(() => res = server.InstanceManager.DetachInstance(imd.Name));
if (res != null)
MessageBox.Show(res);
RefreshInstances();
@@ -152,7 +118,7 @@ namespace TGS.ControlPanel
}
/// <summary>
/// Prompts the user for parameters to <see cref="ITGInstanceManager.RenameInstance(string, string)"/>
/// Prompts the user for parameters to <see cref="Interface.Components.ITGInstanceManager.RenameInstance(string, string)"/>
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">The <see cref="EventArgs"/></param>
@@ -167,14 +133,14 @@ namespace TGS.ControlPanel
if (imd.Enabled && MessageBox.Show(String.Format("This will temporarily offline the server instance! Are you sure?", imd.Path), "Instance Restart", MessageBoxButtons.YesNo) != DialogResult.Yes)
return;
string res = null;
await WrapServerOp(() => res = masterInterface.GetServiceComponent<ITGInstanceManager>().RenameInstance(imd.Name, new_name));
await WrapServerOp(() => res = server.InstanceManager.RenameInstance(imd.Name, new_name));
if (res != null)
MessageBox.Show(res);
RefreshInstances();
}
/// <summary>
/// Prompts the user for parameters to <see cref="ITGInstanceManager.ImportInstance(string)"/>
/// Prompts the user for parameters to <see cref="Interface.Components.ITGInstanceManager.ImportInstance(string)"/>
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">The <see cref="EventArgs"/></param>
@@ -184,14 +150,14 @@ namespace TGS.ControlPanel
if (instance_path == null)
return;
string res = null;
await WrapServerOp(() => res = masterInterface.GetServiceComponent<ITGInstanceManager>().ImportInstance(instance_path));
await WrapServerOp(() => res = server.InstanceManager.ImportInstance(instance_path));
if (res != null)
MessageBox.Show(res);
RefreshInstances();
}
/// <summary>
/// Prompts the user for parameters to <see cref="ITGInstanceManager.CreateInstance(string, string)"/>
/// Prompts the user for parameters to <see cref="Interface.Components.ITGInstanceManager.CreateInstance(string, string)"/>
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">The <see cref="EventArgs"/></param>
@@ -204,14 +170,14 @@ namespace TGS.ControlPanel
if (instance_path == null)
return;
string res = null;
await WrapServerOp(() => res = masterInterface.GetServiceComponent<ITGInstanceManager>().CreateInstance(instance_name, instance_path));
await WrapServerOp(() => res = server.InstanceManager.CreateInstance(instance_name, instance_path));
if (res != null)
MessageBox.Show(res);
RefreshInstances();
}
/// <summary>
/// Attempts to connect the user to an <see cref="ITGInstance"/> based on the <see cref="ListBox.SelectedIndex"/> of <see cref="InstanceListBox"/>
/// Attempts to connect the user to an <see cref="IInstance"/> based on the <see cref="ListBox.SelectedIndex"/> of <see cref="InstanceListBox"/>
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">The <see cref="EventArgs"/></param>
@@ -221,7 +187,7 @@ namespace TGS.ControlPanel
}
/// <summary>
/// Prompts the user if they want to call <see cref="ITGInstanceManager.SetInstanceEnabled(string, bool)"/> to either online or offline an <see cref="ITGInstance"/> based on its current state
/// Prompts the user if they want to call <see cref="Interface.Components.ITGInstanceManager.SetInstanceEnabled(string, bool)"/> to either online or offline an <see cref="IInstance"/> based on its current state
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">The <see cref="EventArgs"/></param>
@@ -235,8 +201,7 @@ namespace TGS.ControlPanel
if (MessageBox.Show(String.Format("Are you sure you want to {0} this instance?", enabling ? "online" : "offline"), "Instance Status Change", MessageBoxButtons.YesNo) != DialogResult.Yes)
return;
string res = null;
var index = InstanceListBox.SelectedIndex;
await WrapServerOp(() => res = masterInterface.GetServiceComponent<ITGInstanceManager>().SetInstanceEnabled(InstanceData[index].Name, enabling));
await WrapServerOp(() => res = server.InstanceManager.SetInstanceEnabled(GetSelectedInstanceMetadata().Name, enabling));
if (res != null)
MessageBox.Show(res);
}
@@ -247,17 +212,16 @@ namespace TGS.ControlPanel
}
/// <summary>
/// Update <see cref="EnabledCheckBox"/> based on the selected <see cref="ITGInstance"/>'s <see cref="InstanceMetadata.Enabled"/> property
/// Update <see cref="EnabledCheckBox"/> based on the selected <see cref="IInstance"/>'s <see cref="InstanceMetadata.Enabled"/> property
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">The <see cref="EventArgs"/></param>
void InstanceListBox_SelectedIndexChanged(object sender, EventArgs e)
{
var index = InstanceListBox.SelectedIndex;
if (index != ListBox.NoMatches)
if (InstanceListBox.SelectedIndex != ListBox.NoMatches)
{
UpdatingEnabledCheckbox = true;
EnabledCheckBox.Checked = InstanceData[index].Enabled;
EnabledCheckBox.Checked = GetSelectedInstanceMetadata().Enabled;
UpdatingEnabledCheckbox = false;
}
}
+20 -22
View File
@@ -5,7 +5,7 @@ using TGS.Interface;
namespace TGS.ControlPanel
{
sealed partial class Login : CountedForm
sealed partial class Login : Form
{
/// <summary>
/// Currently selected saved <see cref="RemoteLoginInfo"/>
@@ -92,39 +92,37 @@ namespace TGS.ControlPanel
loginInfo.Password = PasswordTextBox.Text;
}
using (var I = new ServerInterface(loginInfo))
var I = new Client(loginInfo);
var Config = Properties.Settings.Default;
//This needs to be read here because V&C Closing us will corrupt the data
var savePassword = SavePasswordCheckBox.Checked;
if (VerifyAndConnect(I))
{
var Config = Properties.Settings.Default;
//This needs to be read here because V&C Closing us will corrupt the data
var savePassword = SavePasswordCheckBox.Checked;
if (VerifyAndConnect(I))
{
Config.RemoteDefault = true;
Config.RemoteDefault = true;
if (!savePassword)
loginInfo.Password = null;
Config.RemoteLoginInfo = new StringCollection { loginInfo.ToJSON() };
foreach (RemoteLoginInfo info in IPComboBox.Items)
if (!info.Equals(loginInfo))
Config.RemoteLoginInfo.Add(info.ToJSON());
}
if (!savePassword)
loginInfo.Password = null;
Config.RemoteLoginInfo = new StringCollection { loginInfo.ToJSON() };
foreach (RemoteLoginInfo info in IPComboBox.Items)
if (!info.Equals(loginInfo))
Config.RemoteLoginInfo.Add(info.ToJSON());
}
}
void LocalLoginButton_Click(object sender, EventArgs e)
{
Properties.Settings.Default.RemoteDefault = false;
VerifyAndConnect(new ServerInterface());
VerifyAndConnect(new Client());
}
/// <summary>
/// Attempts a connection on a given <see cref="IServerInterface"/>
/// Attempts a connection on a given <see cref="IClient"/>
/// </summary>
/// <param name="I">The <see cref="IServerInterface"/> to attempt a connection on</param>
/// <param name="I">The <see cref="IClient"/> to attempt a connection on</param>
/// <returns><see langword="true"/> if the connection was made and authenticated, <see langword="false"/> otherwise</returns>
bool VerifyAndConnect(IServerInterface I)
bool VerifyAndConnect(IClient I)
{
try
{
@@ -143,8 +141,8 @@ namespace TGS.ControlPanel
if (I.VersionMismatch(out error) && MessageBox.Show(error, "Warning", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
return true;
new InstanceSelector(I).Show();
Close();
Program.ServerInterface = I;
return true;
}
catch
+10 -4
View File
@@ -7,6 +7,7 @@ namespace TGS.ControlPanel
{
static class Program
{
public static IClient ServerInterface;
[STAThread]
static void Main(string[] args)
{
@@ -20,13 +21,18 @@ namespace TGS.ControlPanel
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ServerInterface.SetBadCertificateHandler(BadCertificateHandler);
var login = new Login();
login.Show();
Application.Run();
Interface.Client.SetBadCertificateHandler(BadCertificateHandler);
Application.Run(new Login());
if(ServerInterface != null)
{
new InstanceSelector(ServerInterface.Server).Show();
Application.Run();
}
}
catch (Exception e)
{
if (ServerInterface != null)
ServerInterface.Dispose();
ServiceDisconnectException(e);
}
finally
+3 -3
View File
@@ -5,7 +5,7 @@ using System.Windows.Forms;
namespace TGS.ControlPanel
{
/// <summary>
/// Used to provide an ATP function for calls into an <see cref="TGS.Interface.IServerInterface"/>
/// Used to provide an ATP function for calls into an <see cref="TGS.Interface.IClient"/>
/// </summary>
#if !DEBUG
abstract
@@ -13,9 +13,9 @@ namespace TGS.ControlPanel
class ServerOpForm : Form
{
/// <summary>
/// Used to wrap <see cref="TGS.Interface.IServerInterface"/> calls in a non-blocking fashion while disabling the <see cref="Form"/> and enabling the wait cursor
/// Used to wrap <see cref="TGS.Interface.IClient"/> calls in a non-blocking fashion while disabling the <see cref="Form"/> and enabling the wait cursor
/// </summary>
/// <param name="action">The <see cref="TGS.Interface.IServerInterface"/> operation to wrap</param>
/// <param name="action">The <see cref="TGS.Interface.IClient"/> operation to wrap</param>
/// <returns>A <see cref="Task"/> wrapping <paramref name="action"/></returns>
protected Task WrapServerOp(Action action)
{
+9 -9
View File
@@ -17,9 +17,9 @@ namespace TGS.ControlPanel
const string MergedPullsError = "Error retrieving currently merged pull requests: {0}";
/// <summary>
/// The <see cref="IServerInterface"/> connected to an <see cref="ITGInstance"/> to handle the pull requests for
/// The <see cref="IInstance"/>to handle pull requests for
/// </summary>
readonly IServerInterface currentInterface;
readonly IInstance currentInterface;
/// <summary>
/// The <see cref="GitHubClient"/> to use to read PR lists
@@ -38,9 +38,9 @@ namespace TGS.ControlPanel
/// <summary>
/// Construct a <see cref="TestMergeManager"/>
/// </summary>
/// <param name="interfaceToUse">The <see cref="IServerInterface"/> to use for managing the <see cref="ITGInstance"/></param>
/// <param name="interfaceToUse">The <see cref="IInstance"/> to manage pull requests for</param>
/// <param name="clientToUse">The <see cref="GitHubClient"/> to use for getting pull request information</param>
public TestMergeManager(IServerInterface interfaceToUse, GitHubClient clientToUse)
public TestMergeManager(IInstance interfaceToUse, GitHubClient clientToUse)
{
InitializeComponent();
DialogResult = DialogResult.Cancel;
@@ -88,7 +88,7 @@ namespace TGS.ControlPanel
{
PullRequestListBox.Items.Clear();
var repo = currentInterface.GetComponent<ITGRepository>();
var repo = currentInterface.Repository;
string error = null;
List<PullRequestInfo> pulls = null;
@@ -197,7 +197,7 @@ namespace TGS.ControlPanel
void PullRequestManager_Load(object sender, EventArgs e)
{
Enabled = false;
var repo = currentInterface.GetComponent<ITGRepository>();
var repo = currentInterface.Repository;
if(!Program.GetRepositoryRemote(repo, out repoOwner, out repoName))
{
Close();
@@ -256,7 +256,7 @@ namespace TGS.ControlPanel
}
}
var repo = currentInterface.GetComponent<ITGRepository>();
var repo = currentInterface.Repository;
string error = null;
//Do standard repo updates
@@ -297,7 +297,7 @@ namespace TGS.ControlPanel
GenerateChangelog(repo);
//Start the compile
var compileStarted = await Task.Run(() => currentInterface.GetComponent<ITGCompiler>().Compile(pulls.Count == 1));
var compileStarted = await Task.Run(() => currentInterface.Compiler.Compile(pulls.Count == 1));
if (error != null)
MessageBox.Show(String.Format("Error sychronizing repo: {0}", error));
@@ -341,7 +341,7 @@ namespace TGS.ControlPanel
{
IList<PullRequestInfo> pulls = null;
string error = null;
var mergedPullsTask = WrapServerOp(() => pulls = currentInterface.GetComponent<ITGRepository>().MergedPullRequests(out error));
var mergedPullsTask = WrapServerOp(() => pulls = currentInterface.Repository.MergedPullRequests(out error));
int PRNumber;
try
+8 -8
View File
@@ -26,7 +26,7 @@ namespace TGS.Installer.UI
/// </summary>
bool attemptNetSettingsMigration = false;
IServerInterface Interface;
IClient Interface;
/// <summary>
/// Construct an installer form
@@ -75,11 +75,11 @@ namespace TGS.Installer.UI
}
void CheckForExistingVersion() {
Interface = new ServerInterface();
Interface = new Client();
var verifiedConnection = Interface.ConnectionStatus().HasFlag(ConnectivityLevel.Administrator);
try
{
var realVersion = Interface.ServerVersion;
var realVersion = Interface.Server.Version;
var isV0 = realVersion < new Version(3, 1, 0, 0);
if (isV0) //OH GOD!!!!
MessageBox.Show("Upgrading from version 3.0 may trigger a bug that can delete /config and /data. IT IS STRONGLY RECCOMMENDED THAT YOU BACKUP THESE FOLDERS BEFORE UPDATING!", "Warning");
@@ -106,7 +106,7 @@ namespace TGS.Installer.UI
var connectionVerified = Interface.ConnectionStatus().HasFlag(ConnectivityLevel.Administrator);
try
{
Interface.GetServiceComponent<ITGSService>().PrepareForUpdate();
Interface.Server.Management.PrepareForUpdate();
Thread.Sleep(3000); //chat messages
return true;
}
@@ -194,18 +194,18 @@ namespace TGS.Installer.UI
var sc = new ServerConfig();
try
{
sc.PythonPath = Interface.GetServiceComponent<ITGSService>().PythonPath();
sc.PythonPath = Interface.Server.Management.PythonPath();
}
catch { }
try
{
sc.RemoteAccessPort = Interface.GetServiceComponent<ITGSService>().RemoteAccessPort();
sc.RemoteAccessPort = Interface.Server.Management.RemoteAccessPort();
}
catch { }
try
{
foreach (var I in Interface.GetServiceComponent<ITGLanding>().ListInstances())
sc.InstancePaths.Add(I.Path);
foreach (var I in Interface.Server.Instances)
sc.InstancePaths.Add(I.Metadata.Path);
}
catch { }
+2 -5
View File
@@ -2,8 +2,6 @@ using RGiesecke.DllExport;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.Interface.Bridge
{
@@ -27,9 +25,8 @@ namespace TGS.Interface.Bridge
parsedArgs.AddRange(args);
var instance = parsedArgs[0];
parsedArgs.RemoveAt(0);
using (var I = new ServerInterface())
if(I.ConnectToInstance(instance, true).HasFlag(ConnectivityLevel.Connected))
I.GetComponent<ITGInterop>().InteropMessage(String.Join(" ", parsedArgs));
using (var I = new Client())
I.Server.GetInstance(instance).Interop.InteropMessage(String.Join(" ", parsedArgs));
}
catch { }
return 0;
+316
View File
@@ -0,0 +1,316 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Description;
using TGS.Interface.Components;
namespace TGS.Interface
{
/// <inheritdoc />
sealed public class Client : IClient
{
/// <summary>
/// Version of the <see cref="Client"/>
/// </summary>
public static readonly Version Version = Assembly.GetExecutingAssembly().GetName().Version;
/// <inheritdoc />
public IServer Server => server;
/// <inheritdoc />
public Version ServerVersion { get
{
lock (this)
if (_serverVersion == null)
{
string rawVersion;
//check ITGSService first for compatiblity reasons
try
{
rawVersion = GetComponent<ITGSService>(null).Version();
}
catch
{
rawVersion = GetComponent<ITGLanding>(null).Version();
}
var splits = rawVersion.Split(' ');
_serverVersion = new Version(splits[splits.Length - 1].Substring(1));
}
return _serverVersion;
} }
/// <inheritdoc />
public string InstanceName { get; private set; }
/// <inheritdoc />
public RemoteLoginInfo LoginInfo { get { return _loginInfo; } }
/// <summary>
/// Backing field for <see cref="Server"/>
/// </summary>
readonly IServer server;
/// <summary>
/// Backing field for <see cref="LoginInfo"/>
/// </summary>
readonly RemoteLoginInfo _loginInfo;
/// <summary>
/// The <see cref="ServerVersion"/>
/// </summary>
Version _serverVersion;
/// <summary>
/// Associated list of open <see cref="ChannelFactory"/>s keyed by <see langword="interface"/> type name. A <see cref="ChannelFactory"/> in this list may close or fault at any time. <see langword="this"/> must be locked before being accessed
/// </summary>
IDictionary<string, ChannelFactory> ChannelFactoryCache;
/// <summary>
/// Sets the function called when a remote login fails due to the server having an invalid SSL cert
/// </summary>
/// <param name="handler">The <see cref="Func{T, TResult}"/> to be called when a remote login is attempted while the server posesses a bad certificate. Passed a <see cref="string"/> of error information about the and should return <see langword="true"/> if it the connection should be made anyway</param>
public static void SetBadCertificateHandler(Func<string, bool> handler)
{
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) =>
{
string ErrorMessage;
switch (error)
{
case SslPolicyErrors.None:
return true;
case SslPolicyErrors.RemoteCertificateChainErrors:
ErrorMessage = "There are certificate chain errors.";
break;
case SslPolicyErrors.RemoteCertificateNameMismatch:
ErrorMessage = "The certificate name does not match.";
break;
case SslPolicyErrors.RemoteCertificateNotAvailable:
ErrorMessage = "The certificate doesn't exist in the trust store.";
break;
default:
ErrorMessage = "An unknown error occurred.";
break;
}
ErrorMessage = String.Format("The server's certificate failed to verify! Error: {0} Cert: {1}", ErrorMessage, cert.ToString());
return handler(ErrorMessage);
};
}
/// <summary>
/// Construct an <see cref="Client"/> for a local connection
/// </summary>
public Client()
{
ChannelFactoryCache = new Dictionary<string, ChannelFactory>();
server = new Server(this);
}
/// <summary>
/// Construct an <see cref="Client"/> for a remote connection
/// </summary>
/// <param name="loginInfo">The <see cref="RemoteLoginInfo"/> for a remote connection</param>
public Client(RemoteLoginInfo loginInfo) : this()
{
if (!loginInfo.HasPassword)
throw new InvalidOperationException("password must be set on loginInfo!");
_loginInfo = loginInfo;
}
/// <inheritdoc />
public bool IsRemoteConnection { get { return LoginInfo != null; } }
/// <summary>
/// Closes all <see cref="ChannelFactory"/>s stored in <see cref="ChannelFactoryCache"/> and <see langword="nulls"/> it
/// </summary>
public void Dispose()
{
lock (this)
{
if (ChannelFactoryCache == null)
return;
foreach (var I in ChannelFactoryCache)
{
var cf = I.Value;
try
{
cf.Close();
}
catch
{
cf.Abort();
}
}
ChannelFactoryCache = null;
}
}
/// <inheritdoc />
public bool VersionMismatch(out string errorMessage)
{
if (ServerVersion.Major != Version.Major || ServerVersion.Minor != Version.Minor || ServerVersion.Build != Version.Build) //don't care about the patch level
{
errorMessage = String.Format("Version mismatch between interface version ({0}) and service version ({1}). Some functionality may crash this program.", Version, ServerVersion);
return true;
}
errorMessage = null;
return false;
}
/// <summary>
/// Returns the requested <see cref="Client"/> component <see langword="interface"/> for the instance <see cref="InstanceName"/>. This does not guarantee a successful connection. <see cref="ChannelFactory{TChannel}"/>s created this way are recycled for minimum latency and bandwidth usage
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> to retrieve</typeparam>
/// <param name="instanceName">The name of the <see cref="IInstance"/> to use</param>
/// <returns>The correct component <see langword="interface"/></returns>
internal T GetComponent<T>(string instanceName)
{
var actualToT = typeof(T);
var tot = actualToT.Name;
if (instanceName != null)
tot = instanceName + tot;
ChannelFactory<T> cf;
lock (this)
{
if (ChannelFactoryCache == null)
throw new ObjectDisposedException(GetType().Name);
if (ChannelFactoryCache.ContainsKey(tot))
try
{
cf = ((ChannelFactory<T>)ChannelFactoryCache[tot]);
if (cf.State != CommunicationState.Opened)
throw new Exception();
return cf.CreateChannel();
}
catch
{
ChannelFactoryCache[tot].Abort();
ChannelFactoryCache.Remove(tot);
}
cf = CreateChannel<T>(instanceName);
ChannelFactoryCache[tot] = cf;
}
return cf.CreateChannel();
}
/// <summary>
/// Directly creates a <see cref="ChannelFactory{TChannel}"/> for <typeparamref name="T"/> without caching. This should be eventually closed by the caller
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> of the channel to be created</typeparam>
/// <param name="instanceName">The instance to connect to, if any</param>
/// <returns>The correct <see cref="ChannelFactory{TChannel}"/></returns>
ChannelFactory<T> CreateChannel<T>(string instanceName)
{
var accessPath = instanceName == null ? Definitions.MasterInterfaceName : String.Format("{0}/{1}", Definitions.InstanceInterfaceName, instanceName);
if (!IsRemoteConnection)
return CreateLocalChannel<T>(instanceName, accessPath);
return CreateRemoteChannel<T>(instanceName, accessPath);
}
//NOTE: This needs to be kept seperate from CreateRemoteChannel because not all our client implementations have NetNamedPipeBinding and attempting to call this function on those platforms will throw an exception
/// <summary>
/// Directly creates a <see cref="ChannelFactory{TChannel}"/> for on a local connection <typeparamref name="T"/> without caching. This should be eventually closed by the caller
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> of the channel to be created</typeparam>
/// <param name="instanceName">The instance to connect to, if any</param>
/// <param name="accessPath">The URL of the interface to connect to</param>
/// <returns>The correct <see cref="ChannelFactory{TChannel}"/></returns>
ChannelFactory<T> CreateLocalChannel<T>(string instanceName, string accessPath)
{
var interfaceName = typeof(T).Name;
var res2 = new ChannelFactory<T>(
new NetNamedPipeBinding { SendTimeout = new TimeSpan(0, 0, 30), MaxReceivedMessageSize = Definitions.TransferLimitLocal }, new EndpointAddress(String.Format("net.pipe://localhost/{0}/{1}", accessPath, interfaceName))); //10 megs
res2.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
return res2;
}
/// <summary>
/// Directly creates a <see cref="ChannelFactory{TChannel}"/> for on a remote connection <typeparamref name="T"/> without caching. This should be eventually closed by the caller
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> of the channel to be created</typeparam>
/// <param name="instanceName">The instance to connect to, if any</param>
/// <param name="accessPath">The URL of the interface to connect to</param>
/// <returns>The correct <see cref="ChannelFactory{TChannel}"/></returns>
ChannelFactory<T> CreateRemoteChannel<T>(string instanceName, string accessPath)
{
//okay we're going over
var binding = new BasicHttpsBinding()
{
SendTimeout = new TimeSpan(0, 0, 40),
MaxReceivedMessageSize = Definitions.TransferLimitRemote
};
var interfaceName = typeof(T).Name;
var requireAuth = interfaceName != typeof(ITGConnectivity).Name;
var url = String.Format("https://{0}:{1}/{2}/{3}", LoginInfo.IP, LoginInfo.Port, accessPath, interfaceName);
var address = new EndpointAddress(url);
var res = new ChannelFactory<T>(binding, address);
if (requireAuth)
{
var applicator = new AuthenticationHeaderApplicator(LoginInfo);
var t = Type.GetType("Mono.Runtime");
KeyedCollection<Type, IEndpointBehavior> behaviours;
if (t != null)
{
var prop = res.Endpoint.GetType()
.GetTypeInfo()
.GetDeclaredProperty("Behaviors");
behaviours = (KeyedCollection<Type, IEndpointBehavior>)prop
.GetValue(res.Endpoint);
}
else
behaviours = res.Endpoint.EndpointBehaviors;
behaviours.Add(applicator);
}
return res;
}
/// <inheritdoc />
public ConnectivityLevel ConnectionStatus()
{
return ConnectionStatus(out string unused);
}
/// <inheritdoc />
public ConnectivityLevel ConnectionStatus(out string error)
{
try
{
GetComponent<ITGConnectivity>(null).VerifyConnection();
}
catch (Exception e)
{
error = e.ToString();
return ConnectivityLevel.None;
}
try
{
GetComponent<ITGLanding>(null).Version();
}
catch(Exception e)
{
error = e.ToString();
return ConnectivityLevel.Connected;
}
try
{
GetComponent<ITGSService>(null).Version();
error = null;
return ConnectivityLevel.Administrator;
}
catch(Exception e)
{
error = e.ToString();
return ConnectivityLevel.Authenticated;
}
}
}
}
+32
View File
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using TGS.Interface.Components;
namespace TGS.Interface
{
/// <summary>
/// Contains constants for the interface
/// </summary>
public static class Definitions
{
/// <summary>
/// The maximum message size to and from a local server
/// </summary>
public const long TransferLimitLocal = Int32.MaxValue; //2GB can't go higher
/// <summary>
/// The maximum message size to and from a remote server
/// </summary>
public const long TransferLimitRemote = 10485760; //10 MB
/// <summary>
/// Base name of communication URLs
/// </summary>
public const string MasterInterfaceName = "TGStationServerService";
/// <summary>
/// Base name of instance URLs
/// </summary>
public const string InstanceInterfaceName = MasterInterfaceName + "/Instance";
}
}
+44
View File
@@ -0,0 +1,44 @@
using System;
namespace TGS.Interface
{
/// <summary>
/// Main <see langword="interface"/> for communicating the <see cref="Components.ITGSService"/>
/// </summary>
public interface IClient : IDisposable
{
/// <summary>
/// The <see cref="IServer"/> the <see cref="IClient"/> connects to
/// </summary>
IServer Server { get; }
/// <summary>
/// The <see cref="RemoteLoginInfo"/> for the <see cref="IClient"/>. Is <see langword="null"/> for local connections
/// </summary>
RemoteLoginInfo LoginInfo { get; }
/// <summary>
/// Checks if the <see cref="IClient"/> is setup for a remote connection
/// </summary>
bool IsRemoteConnection { get; }
/// <summary>
/// Returns <see langword="true"/> if the <see cref="IClient"/> interface being used to connect to a service does not have the same release version as the service
/// </summary>
/// <param name="errorMessage">An error message to display to the user should this function return <see langword="true"/></param>
/// <returns><see langword="true"/> if the <see cref="IClient"/> interface being used to connect to a service does not have the same release version as the service</returns>
bool VersionMismatch(out string errorMessage);
/// <summary>
/// See <see cref="ConnectionStatus(out string)"/> without the error argument
/// </summary>
ConnectivityLevel ConnectionStatus();
/// <summary>
/// Used to test if the <see cref="Components.ITGSService"/> is avaiable on the target machine. Note that state can change at any time and any call into the may throw an exception because of communcation errors
/// </summary>
/// <param name="error">String of the error that prevented an elevated connectivity level</param>
/// <returns>The apporopriate <see cref="ConnectivityLevel"/></returns>
ConnectivityLevel ConnectionStatus(out string error);
}
}
+55
View File
@@ -0,0 +1,55 @@
using TGS.Interface.Components;
namespace TGS.Interface
{
/// <summary>
/// Wrapper for <see cref="ITGInstance"/> components
/// </summary>
public interface IInstance : ITGInstance
{
/// <summary>
/// Get the <see cref="InstanceMetadata"/> for the <see cref="IInstance"/>
/// </summary>
InstanceMetadata Metadata { get; }
/// <summary>
/// The <see cref="ITGAdministration"/> component. Will be <see langword="null"/> if the connected user is not an administrator of the <see cref="IInstance"/>
/// </summary>
ITGAdministration Administration { get; }
/// <summary>
/// The <see cref="ITGByond"/> component
/// </summary>
ITGByond Byond { get; }
/// <summary>
/// The <see cref="ITGChat"/> component
/// </summary>
ITGChat Chat { get; }
/// <summary>
/// The <see cref="ITGCompiler"/> component
/// </summary>
ITGCompiler Compiler { get; }
/// <summary>
/// The <see cref="ITGConfig"/> component
/// </summary>
ITGConfig Config { get; }
/// <summary>
/// The <see cref="ITGDreamDaemon"/> component
/// </summary>
ITGDreamDaemon DreamDaemon { get; }
/// <summary>
/// The <see cref="ITGInterop"/> component
/// </summary>
ITGInterop Interop { get; }
/// <summary>
/// The <see cref="ITGRepository"/> component
/// </summary>
ITGRepository Repository { get; }
}
}
+39
View File
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using TGS.Interface.Components;
namespace TGS.Interface
{
/// <summary>
/// Wrapper representing a <see cref="ITGSService"/>
/// </summary>
public interface IServer
{
/// <summary>
/// The <see cref="System.Version"/> of the <see cref="IServer"/>
/// </summary>
Version Version { get; }
/// <summary>
/// Get the <see cref="IInstance"/>s the <see cref="IServer"/> contains that the current user can access and connect to
/// </summary>
IEnumerable<IInstance> Instances { get; }
/// <summary>
/// The <see cref="ITGInstanceManager"/> component. Will be <see langword="null"/> if the connected user is not an administrator of the <see cref="IServer"/>
/// </summary>
ITGInstanceManager InstanceManager { get; }
/// <summary>
/// The <see cref="ITGSService"/> component. Will be <see langword="null"/> if the connected user is not an administrator of the <see cref="IServer"/>
/// </summary>
ITGSService Management { get; }
/// <summary>
/// Gets the specified <see cref="IInstance"/> without connectivity checks
/// </summary>
/// <param name="name">The name of the <see cref="IInstance"/> to get</param>
/// <returns>The <see cref="IInstance"/> named <paramref name="name"/> on success, <see langword="null"/> on failure</returns>
IInstance GetInstance(string name);
}
}
+119
View File
@@ -0,0 +1,119 @@
using System;
using System.Linq;
using TGS.Interface.Components;
namespace TGS.Interface
{
/// <inheritdoc />
sealed class Instance : IInstance
{
/// <inheritdoc />
public InstanceMetadata Metadata
{
get
{
if (!metadata.Enabled)
//metadata needs populating
metadata = serverInterface.GetComponent<ITGLanding>(null).ListInstances().Where(x => x.Name == metadata.Name).First();
return metadata;
}
}
/// <summary>
/// Whether or not the current user is known to be an administrator of the <see cref="IInstance"/>
/// </summary>
bool UserIsAdministrator
{
get
{
lock (this)
{
if (isAdministrator)
return true;
try
{
serverInterface.GetComponent<ITGAdministration>(metadata.Name).GetCurrentAuthorizedGroup();
isAdministrator = true;
return true;
}
catch
{
return false;
}
}
}
}
/// <summary>
/// The backing <see cref="Client"/>
/// </summary>
readonly Client serverInterface;
/// <summary>
/// The name of the <see cref="IInstance"/>
/// </summary>
InstanceMetadata metadata;
/// <summary>
/// Backing field for <see cref="UserIsAdministrator"/>
/// </summary>
bool isAdministrator;
/// <summary>
/// Construct an <see cref="Instance"/>
/// </summary>
/// <param name="_serverInterface">The <see cref="Client"/> to use</param>
/// <param name="_metadata">The <see cref="InstanceMetadata"/> for the <see cref="IInstance"/></param>
public Instance(Client _serverInterface, InstanceMetadata _metadata)
{
serverInterface = _serverInterface;
metadata = _metadata;
if (metadata.Enabled)
//run a connectivity check
serverInterface.GetComponent<ITGConnectivity>(metadata.Name).VerifyConnection();
}
/// <inheritdoc />
public ITGAdministration Administration => UserIsAdministrator ? serverInterface.GetComponent<ITGAdministration>(metadata.Name) : null;
/// <inheritdoc />
public ITGByond Byond => serverInterface.GetComponent<ITGByond>(metadata.Name);
/// <inheritdoc />
public ITGChat Chat => serverInterface.GetComponent<ITGChat>(metadata.Name);
/// <inheritdoc />
public ITGCompiler Compiler => serverInterface.GetComponent<ITGCompiler>(metadata.Name);
/// <inheritdoc />
public ITGConfig Config => serverInterface.GetComponent<ITGConfig>(metadata.Name);
/// <inheritdoc />
public ITGDreamDaemon DreamDaemon => serverInterface.GetComponent<ITGDreamDaemon>(metadata.Name);
/// <inheritdoc />
public ITGInterop Interop => serverInterface.GetComponent<ITGInterop>(metadata.Name);
/// <inheritdoc />
public ITGRepository Repository => serverInterface.GetComponent<ITGRepository>(metadata.Name);
/// <inheritdoc />
public string ServerDirectory()
{
return serverInterface.GetComponent<ITGInstance>(metadata.Name).ServerDirectory();
}
/// <inheritdoc />
public string Version()
{
return serverInterface.GetComponent<ITGInstance>(metadata.Name).Version();
}
/// <summary>
/// Get a string representation of the <see cref="Instance"/>
/// </summary>
/// <returns>A string representation of the <see cref="Instance"/></returns>
public override string ToString()
{
return String.Format("{0}: {1} - {2} - {3}", metadata.LoggingID, metadata.Name, metadata.Path, metadata.Enabled ? "ONLINE" : "OFFLINE");
}
}
}
+96
View File
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using TGS.Interface.Components;
namespace TGS.Interface
{
/// <inheritdoc />
sealed class Server : IServer
{
/// <inheritdoc />
public Version Version => serverInterface.ServerVersion;
/// <inheritdoc />
public IEnumerable<IInstance> Instances { get
{
lock (this)
if (knownInstances == null)
knownInstances = serverInterface.GetComponent<ITGLanding>(null).ListInstances();
foreach (var I in knownInstances)
{
IInstance nextInstance;
try
{
nextInstance = new Instance(serverInterface, I);
}
catch
{
continue;
}
yield return nextInstance;
}
}
}
/// <inheritdoc />
public ITGInstanceManager InstanceManager => UserIsAdministrator ? serverInterface.GetComponent<ITGInstanceManager>(null) : null;
/// <inheritdoc />
public ITGSService Management => UserIsAdministrator ? serverInterface.GetComponent<ITGSService>(null) : null;
/// <summary>
/// If the connected user is an administrator of the <see cref="IServer"/>
/// </summary>
bool UserIsAdministrator
{
get
{
lock (this)
{
if (isAdministrator)
return true;
try
{
serverInterface.GetComponent<ITGSService>(null).Version();
isAdministrator = true;
return true;
}
catch
{
return false;
}
}
}
}
/// <summary>
/// The backing <see cref="Client"/>
/// </summary>
readonly Client serverInterface;
/// <summary>
/// Result of a call to <see cref="ITGLanding.ListInstances"/>
/// </summary>
IList<InstanceMetadata> knownInstances;
/// <summary>
/// Backing field for <see cref="UserIsAdministrator"/>
/// </summary>
bool isAdministrator;
/// <summary>
/// Construct an <see cref="Server"/>
/// </summary>
/// <param name="_serverInterface">The <see cref="Client"/> to use</param>
public Server(Client _serverInterface)
{
serverInterface = _serverInterface;
}
/// <inheritdoc />
public IInstance GetInstance(string name)
{
return new Instance(serverInterface, new InstanceMetadata { Name = name, Enabled = false });
}
}
}
-524
View File
@@ -1,524 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Description;
using TGS.Interface.Components;
namespace TGS.Interface
{
/// <summary>
/// Main <see langword="interface"/> for communicating the <see cref="ITGSService"/>
/// </summary>
public interface IServerInterface : IDisposable
{
/// <summary>
/// The <see cref="Version"/> of the connected <see cref="ITGSService"/>
/// </summary>
Version ServerVersion { get; }
/// <summary>
/// The name of the current instance in use. Defaults to <see langword="null"/>
/// </summary>
string InstanceName { get; }
/// <summary>
/// The <see cref="RemoteLoginInfo"/> for the <see cref="IServerInterface"/>. Is <see langword="null"/> for local connections
/// </summary>
RemoteLoginInfo LoginInfo { get; }
/// <summary>
/// Checks if the <see cref="IServerInterface"/> is setup for a remote connection
/// </summary>
bool IsRemoteConnection { get; }
/// <summary>
/// Targets <paramref name="instanceName"/> as the instance to use with <see cref="GetComponent{T}"/>. Closes all connections to any previous instance
/// </summary>
/// <param name="instanceName">The name of the instance to connect to</param>
/// <param name="skipChecks">If set to <see langword="true"/>, skips the connectivity and authentication checks, sets <see cref="InstanceName"/>, and returns <see cref="ConnectivityLevel.Connected"/></param>
/// <returns>The apporopriate <see cref="ConnectivityLevel"/></returns>
ConnectivityLevel ConnectToInstance(string instanceName = null, bool skipChecks = false);
/// <summary>
/// Returns <see langword="true"/> if the <see cref="IServerInterface"/> interface being used to connect to a service does not have the same release version as the service
/// </summary>
/// <param name="errorMessage">An error message to display to the user should this function return <see langword="true"/></param>
/// <returns><see langword="true"/> if the <see cref="IServerInterface"/> interface being used to connect to a service does not have the same release version as the service</returns>
bool VersionMismatch(out string errorMessage);
/// <summary>
/// Returns the requested <see cref="IServerInterface"/> component <see langword="interface"/> for the instance <see cref="InstanceName"/>. This does not guarantee a successful connection.
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> to retrieve</typeparam>
/// <returns>The correct component <see langword="interface"/></returns>
T GetComponent<T>();
/// <summary>
/// Returns a root service component
/// </summary>
/// <returns>The <see cref="ITGSService"/> component for the service</returns>
T GetServiceComponent<T>();
/// <summary>
/// Used to test if the <see cref="ITGSService"/> is avaiable on the target machine. Note that state can change at any time and any call into the may throw an exception because of communcation errors
/// </summary>
/// <returns><see langword="null"/> on successful connection, error message <see cref="string"/> on failure</returns>
ConnectivityLevel ConnectionStatus();
/// <summary>
/// Used to test if the <see cref="ITGSService"/> is avaiable on the target machine. Note that state can change at any time and any call into the may throw an exception because of communcation errors
/// </summary>
/// <param name="error">String of the error that prevented an elevated connectivity level</param>
/// <returns>The apporopriate <see cref="ConnectivityLevel"/></returns>
ConnectivityLevel ConnectionStatus(out string error);
}
/// <inheritdoc />
sealed public class ServerInterface : IServerInterface
{
/// <summary>
/// List of <see langword="interface"/>s that can be used with <see cref="GetServiceComponent{T}"/>
/// </summary>
public static readonly IList<Type> ValidServiceInterfaces = new List<Type> { typeof(ITGSService), typeof(ITGInstanceManager), typeof(ITGConnectivity), typeof(ITGLanding) };
/// <summary>
/// Version of the interface
/// </summary>
public static readonly Version Version = Assembly.GetExecutingAssembly().GetName().Version;
/// <summary>
/// List of <see langword="interface"/>s that can be used with <see cref="GetComponent{T}"/>
/// </summary>
public static readonly IList<Type> ValidInstanceInterfaces = CollectComponents();
/// <summary>
/// The maximum message size to and from a local server
/// </summary>
public const long TransferLimitLocal = Int32.MaxValue; //2GB can't go higher
/// <summary>
/// The maximum message size to and from a remote server
/// </summary>
public const long TransferLimitRemote = 10485760; //10 MB
/// <summary>
/// Base name of communication URLs
/// </summary>
public const string MasterInterfaceName = "TGStationServerService";
/// <summary>
/// Base name of instance URLs
/// </summary>
public const string InstanceInterfaceName = MasterInterfaceName + "/Instance";
/// <summary>
/// The <see cref="ServerVersion"/>
/// </summary>
Version _serverVersion;
/// <inheritdoc />
public Version ServerVersion { get
{
lock (this)
if (_serverVersion == null)
{
string rawVersion;
//check ITGSService first for compatiblity reasons
try
{
rawVersion = GetServiceComponent<ITGSService>().Version();
}
catch
{
rawVersion = GetServiceComponent<ITGLanding>().Version();
}
var splits = rawVersion.Split(' ');
_serverVersion = new Version(splits[splits.Length - 1].Substring(1));
}
return _serverVersion;
} }
/// <inheritdoc />
public string InstanceName { get; private set; }
/// <summary>
/// Backing field for <see cref="LoginInfo"/>
/// </summary>
readonly RemoteLoginInfo _loginInfo;
/// <inheritdoc />
public RemoteLoginInfo LoginInfo { get { return _loginInfo; } }
/// <summary>
/// Associated list of open <see cref="ChannelFactory"/>s keyed by <see langword="interface"/> type name. A <see cref="ChannelFactory"/> in this list may close or fault at any time. Must be locked before being accessed
/// </summary>
IDictionary<string, ChannelFactory> ChannelFactoryCache = new Dictionary<string, ChannelFactory>();
/// <summary>
/// Returns a <see cref="IList{T}"/> of <see langword="interface"/> <see cref="Type"/>s that can be used with the service
/// </summary>
/// <returns>A <see cref="IList{T}"/> of <see langword="interface"/> <see cref="Type"/>s that can be used with the service</returns>
static IList<Type> CollectComponents()
{
var ConnectivityComponent = typeof(ITGConnectivity);
//find all interfaces in this assembly in this namespace that have the service contract attribute
var query = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.IsInterface
&& t.Namespace == ConnectivityComponent.Namespace
&& t.GetCustomAttribute(typeof(ServiceContractAttribute)) != null
&& (t == ConnectivityComponent || !ValidServiceInterfaces.Contains(t))
select t;
return query.ToList();
}
/// <summary>
/// Sets the function called when a remote login fails due to the server having an invalid SSL cert
/// </summary>
/// <param name="handler">The <see cref="Func{T, TResult}"/> to be called when a remote login is attempted while the server posesses a bad certificate. Passed a <see cref="string"/> of error information about the and should return <see langword="true"/> if it the connection should be made anyway</param>
public static void SetBadCertificateHandler(Func<string, bool> handler)
{
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) =>
{
string ErrorMessage;
switch (error)
{
case SslPolicyErrors.None:
return true;
case SslPolicyErrors.RemoteCertificateChainErrors:
ErrorMessage = "There are certificate chain errors.";
break;
case SslPolicyErrors.RemoteCertificateNameMismatch:
ErrorMessage = "The certificate name does not match.";
break;
case SslPolicyErrors.RemoteCertificateNotAvailable:
ErrorMessage = "The certificate doesn't exist in the trust store.";
break;
default:
ErrorMessage = "An unknown error occurred.";
break;
}
ErrorMessage = String.Format("The server's certificate failed to verify! Error: {0} Cert: {1}", ErrorMessage, cert.ToString());
return handler(ErrorMessage);
};
}
/// <summary>
/// Construct an <see cref="ServerInterface"/> for a local connection
/// </summary>
public ServerInterface() { }
/// <summary>
/// Construct an <see cref="ServerInterface"/> for a remote connection
/// </summary>
/// <param name="loginInfo">The <see cref="RemoteLoginInfo"/> for a remote connection</param>
public ServerInterface(RemoteLoginInfo loginInfo)
{
if (!loginInfo.HasPassword)
throw new InvalidOperationException("password must be set on loginInfo!");
_loginInfo = loginInfo;
}
/// <inheritdoc />
public ConnectivityLevel ConnectToInstance(string instanceName = null, bool skipChecks = false)
{
if (instanceName == null)
instanceName = InstanceName;
if (!skipChecks && !ConnectionStatus().HasFlag(ConnectivityLevel.Connected))
return ConnectivityLevel.None;
var prevInstance = InstanceName;
if (prevInstance != instanceName)
CloseAllChannels(false);
InstanceName = instanceName;
if (skipChecks)
return ConnectivityLevel.Connected;
try
{
GetComponent<ITGConnectivity>().VerifyConnection();
}
catch
{
InstanceName = prevInstance;
return ConnectivityLevel.None;
}
try
{
GetComponent<ITGInstance>().ServerDirectory();
}
catch
{
return ConnectivityLevel.Connected;
}
try
{
GetComponent<ITGAdministration>().GetCurrentAuthorizedGroup();
return ConnectivityLevel.Administrator;
}
catch
{
return ConnectivityLevel.Authenticated;
}
}
/// <inheritdoc />
public bool IsRemoteConnection { get { return LoginInfo != null; } }
/// <summary>
/// Closes all <see cref="ChannelFactory"/>s stored in <see cref="ChannelFactoryCache"/> and clears it
/// </summary>
/// <param name="includingRoot">If set to <see langword="false"/>, doesn't clear the channels that are used by <see cref="ITGSService"/></param>
void CloseAllChannels(bool includingRoot)
{
string[] RootThings = { typeof(ITGSService).Name, 'S' + typeof(ITGConnectivity).Name };
lock (ChannelFactoryCache)
{
var toRemove = new List<string>();
foreach (var I in ChannelFactoryCache)
{
if (RootThings.Contains(I.Key))
continue;
var cf = I.Value;
try
{
cf.Close();
}
catch
{
cf.Abort();
}
toRemove.Add(I.Key);
}
foreach (var I in toRemove)
ChannelFactoryCache.Remove(I);
}
}
/// <inheritdoc />
public bool VersionMismatch(out string errorMessage)
{
if(ServerVersion.Major != Version.Major || ServerVersion.Minor != Version.Minor || ServerVersion.Build != Version.Build) //don't care about the patch level
{
errorMessage = String.Format("Version mismatch between interface version ({0}) and service version ({1}). Some functionality may crash this program.", Version, ServerVersion);
return true;
}
errorMessage = null;
return false;
}
/// <inheritdoc />
public T GetComponent<T>()
{
var ToT = typeof(T);
if (!ValidInstanceInterfaces.Contains(ToT))
throw new Exception("Invalid type!");
return GetComponentImpl<T>(true);
}
/// <summary>
/// Returns the requested <see cref="ServerInterface"/> component <see langword="interface"/> for the instance <see cref="InstanceName"/>. This does not guarantee a successful connection. <see cref="ChannelFactory{TChannel}"/>s created this way are recycled for minimum latency and bandwidth usage
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> to retrieve</typeparam>
/// <param name="useInstanceName">If <see cref="InstanceName"/> should be used to connect</param>
/// <returns>The correct component <see langword="interface"/></returns>
T GetComponentImpl<T>(bool useInstanceName)
{
if (useInstanceName & InstanceName == null)
throw new Exception("Instance not selected!");
var actualToT = typeof(T);
var tot = actualToT.Name;
if (actualToT == typeof(ITGConnectivity) && !useInstanceName)
tot = 'S' + tot;
ChannelFactory<T> cf;
lock (ChannelFactoryCache)
{
if (ChannelFactoryCache.ContainsKey(tot))
try
{
cf = ((ChannelFactory<T>)ChannelFactoryCache[tot]);
if (cf.State != CommunicationState.Opened)
throw new Exception();
return cf.CreateChannel();
}
catch
{
ChannelFactoryCache[tot].Abort();
ChannelFactoryCache.Remove(tot);
}
cf = CreateChannel<T>(useInstanceName ? InstanceName : null);
ChannelFactoryCache[tot] = cf;
}
return cf.CreateChannel();
}
/// <inheritdoc />
public T GetServiceComponent<T>()
{
var ToT = typeof(T);
if (!ValidServiceInterfaces.Contains(ToT))
throw new Exception("Invalid type!");
return GetComponentImpl<T>(false);
}
/// <summary>
/// Directly creates a <see cref="ChannelFactory{TChannel}"/> for <typeparamref name="T"/> without caching. This should be eventually closed by the caller
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> of the channel to be created</typeparam>
/// <param name="instanceName">The instance to connect to, if any</param>
/// <returns>The correct <see cref="ChannelFactory{TChannel}"/></returns>
ChannelFactory<T> CreateChannel<T>(string instanceName)
{
var accessPath = instanceName == null ? MasterInterfaceName : String.Format("{0}/{1}", InstanceInterfaceName, instanceName);
if (!IsRemoteConnection)
return CreateLocalChannel<T>(instanceName, accessPath);
return CreateRemoteChannel<T>(instanceName, accessPath);
}
//NOTE: This needs to be kept seperate from CreateRemoteChannel because not all our client implementations have NetNamedPipeBinding and attempting to call this function on those platforms will throw an exception
/// <summary>
/// Directly creates a <see cref="ChannelFactory{TChannel}"/> for on a local connection <typeparamref name="T"/> without caching. This should be eventually closed by the caller
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> of the channel to be created</typeparam>
/// <param name="instanceName">The instance to connect to, if any</param>
/// <param name="accessPath">The URL of the interface to connect to</param>
/// <returns>The correct <see cref="ChannelFactory{TChannel}"/></returns>
ChannelFactory<T> CreateLocalChannel<T>(string instanceName, string accessPath)
{
var interfaceName = typeof(T).Name;
var res2 = new ChannelFactory<T>(
new NetNamedPipeBinding { SendTimeout = new TimeSpan(0, 0, 30), MaxReceivedMessageSize = TransferLimitLocal }, new EndpointAddress(String.Format("net.pipe://localhost/{0}/{1}", accessPath, interfaceName))); //10 megs
res2.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
return res2;
}
/// <summary>
/// Directly creates a <see cref="ChannelFactory{TChannel}"/> for on a remote connection <typeparamref name="T"/> without caching. This should be eventually closed by the caller
/// </summary>
/// <typeparam name="T">The component <see langword="interface"/> of the channel to be created</typeparam>
/// <param name="instanceName">The instance to connect to, if any</param>
/// <param name="accessPath">The URL of the interface to connect to</param>
/// <returns>The correct <see cref="ChannelFactory{TChannel}"/></returns>
ChannelFactory<T> CreateRemoteChannel<T>(string instanceName, string accessPath)
{
//okay we're going over
var binding = new BasicHttpsBinding()
{
SendTimeout = new TimeSpan(0, 0, 40),
MaxReceivedMessageSize = TransferLimitRemote
};
var interfaceName = typeof(T).Name;
var requireAuth = interfaceName != typeof(ITGConnectivity).Name;
var url = String.Format("https://{0}:{1}/{2}/{3}", LoginInfo.IP, LoginInfo.Port, accessPath, interfaceName);
var address = new EndpointAddress(url);
var res = new ChannelFactory<T>(binding, address);
if (requireAuth)
{
var applicator = new AuthenticationHeaderApplicator(LoginInfo);
var t = Type.GetType("Mono.Runtime");
KeyedCollection<Type, IEndpointBehavior> behaviours;
if (t != null)
{
var prop = res.Endpoint.GetType()
.GetTypeInfo()
.GetDeclaredProperty("Behaviors");
behaviours = (KeyedCollection<Type, IEndpointBehavior>)prop
.GetValue(res.Endpoint);
}
else
behaviours = res.Endpoint.EndpointBehaviors;
behaviours.Add(applicator);
}
return res;
}
/// <inheritdoc />
public ConnectivityLevel ConnectionStatus()
{
return ConnectionStatus(out string unused);
}
/// <inheritdoc />
public ConnectivityLevel ConnectionStatus(out string error)
{
try
{
GetComponentImpl<ITGConnectivity>(false).VerifyConnection();
}
catch (Exception e)
{
error = e.ToString();
return ConnectivityLevel.None;
}
try
{
GetServiceComponent<ITGLanding>().Version();
}
catch(Exception e)
{
error = e.ToString();
return ConnectivityLevel.Connected;
}
try
{
GetServiceComponent<ITGSService>().Version();
error = null;
return ConnectivityLevel.Administrator;
}
catch(Exception e)
{
error = e.ToString();
return ConnectivityLevel.Authenticated;
}
}
#region IDisposable Support
/// <summary>
/// To detect redundant <see cref="Dispose(bool)"/> calls
/// </summary>
private bool disposedValue = false;
/// <summary>
/// Implements the <see cref="IDisposable"/> pattern. Calls <see cref="CloseAllChannels"/>
/// </summary>
/// <param name="disposing"><see langword="true"/> if <see cref="Dispose()"/> was called manually, <see langword="false"/> if it was from the finalizer</param>
void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
CloseAllChannels(true);
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~Interface() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
/// <summary>
/// Implements the <see cref="IDisposable"/> pattern
/// </summary>
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
}
+7 -1
View File
@@ -62,18 +62,24 @@
<Compile Include="Components\Instance.cs" />
<Compile Include="Components\InstanceManager.cs" />
<Compile Include="Components\Landing.cs" />
<Compile Include="Definitions.cs" />
<Compile Include="Enumerations.cs" />
<Compile Include="Helpers.cs" />
<Compile Include="IInstance.cs" />
<Compile Include="InstanceMetadata.cs" />
<Compile Include="Instance.cs" />
<Compile Include="IServer.cs" />
<Compile Include="IClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Components\Repository.cs" />
<Compile Include="PullRequestInfo.cs" />
<Compile Include="RemoteLoginInfo.cs" />
<Compile Include="RootCommand.cs" />
<Compile Include="ServerInterface.cs" />
<Compile Include="Client.cs" />
<Compile Include="..\AssemblyInfo.global.cs" />
<Compile Include="Components\Service.cs" />
<Compile Include="Components\Interop.cs" />
<Compile Include="Server.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="tgs.ico" />
+1 -1
View File
@@ -119,7 +119,7 @@ namespace TGS.Server
//what is says on the tin
CompilerStatus IsInitialized()
{
if (File.Exists(RelativePath(Path.Combine(GameDirLive, BridgeDLLName))) || File.Exists(RelativePath(Path.Combine(GameDirLive, Assembly.GetAssembly(typeof(IServerInterface)).GetName().Name + ".dll")))) //its a good tell, jim
if (File.Exists(RelativePath(Path.Combine(GameDirLive, BridgeDLLName))) || File.Exists(RelativePath(Path.Combine(GameDirLive, Assembly.GetAssembly(typeof(IClient)).GetName().Name + ".dll")))) //its a good tell, jim
return CompilerStatus.Initialized;
return CompilerStatus.Uninitialized;
}
+1 -1
View File
@@ -535,7 +535,7 @@ namespace TGS.Server
return;
//Copy the interface dll to the static dir
var InterfacePath = Assembly.GetAssembly(typeof(IServerInterface)).Location;
var InterfacePath = Assembly.GetAssembly(typeof(IClient)).Location;
//bridge is installed next to the interface
var BridgePath = Path.Combine(Path.GetDirectoryName(InterfacePath), BridgeDLLName);
#if DEBUG
+19 -9
View File
@@ -198,9 +198,11 @@ namespace TGS.Server
/// </summary>
void SetupService()
{
serviceHost = CreateHost(this, ServerInterface.MasterInterfaceName);
foreach (var I in ServerInterface.ValidServiceInterfaces)
AddEndpoint(serviceHost, I);
serviceHost = CreateHost(this, Definitions.MasterInterfaceName);
AddEndpoint(serviceHost, typeof(ITGConnectivity));
AddEndpoint(serviceHost, typeof(ITGInstanceManager));
AddEndpoint(serviceHost, typeof(ITGLanding));
AddEndpoint(serviceHost, typeof(ITGSService));
serviceHost.Authorization.ServiceAuthorizationManager = new RootAuthorizationManager(); //only admins can diddle us
serviceHost.Authentication.ServiceAuthenticationManager = new AuthenticationHeaderDecoder();
}
@@ -313,11 +315,19 @@ namespace TGS.Server
return null;
}
var host = CreateHost(instance, String.Format("{0}/{1}", ServerInterface.InstanceInterfaceName, instanceName));
var host = CreateHost(instance, String.Format("{0}/{1}", Definitions.InstanceInterfaceName, instanceName));
hosts.Add(instanceName, host);
foreach (var J in ServerInterface.ValidInstanceInterfaces)
AddEndpoint(host, J);
AddEndpoint(host, typeof(ITGConnectivity));
AddEndpoint(host, typeof(ITGAdministration));
AddEndpoint(host, typeof(ITGChat));
AddEndpoint(host, typeof(ITGCompiler));
AddEndpoint(host, typeof(ITGConfig));
AddEndpoint(host, typeof(ITGConnectivity));
AddEndpoint(host, typeof(ITGDreamDaemon));
AddEndpoint(host, typeof(ITGInstance));
AddEndpoint(host, typeof(ITGInterop));
AddEndpoint(host, typeof(ITGRepository));
host.Authorization.ServiceAuthorizationManager = instance;
host.Authentication.ServiceAuthenticationManager = new AuthenticationHeaderDecoder();
@@ -332,11 +342,11 @@ namespace TGS.Server
void AddEndpoint(ServiceHost host, Type typetype)
{
var bindingName = typetype.Name;
host.AddServiceEndpoint(typetype, new NetNamedPipeBinding() { SendTimeout = new TimeSpan(0, 0, 30), MaxReceivedMessageSize = ServerInterface.TransferLimitLocal }, bindingName);
host.AddServiceEndpoint(typetype, new NetNamedPipeBinding() { SendTimeout = new TimeSpan(0, 0, 30), MaxReceivedMessageSize = Definitions.TransferLimitLocal }, bindingName);
var httpsBinding = new BasicHttpsBinding()
{
SendTimeout = new TimeSpan(0, 0, 40),
MaxReceivedMessageSize = ServerInterface.TransferLimitRemote
MaxReceivedMessageSize = Definitions.TransferLimitRemote
};
var requireAuth = typetype.Name != typeof(ITGConnectivity).Name;
host.AddServiceEndpoint(typetype, httpsBinding, bindingName);
@@ -8,14 +8,14 @@ namespace TGS.CommandLine.Commands.Repository.Tests
public abstract class RepositoryCommandTest : OutputProcOverriderTest
{
/// <summary>
/// Creates a mock <see cref="IServerInterface"/> that returns a specific <see cref="ITGRepository"/> when that component is requested
/// Creates a mock <see cref="IClient"/> that returns a specific <see cref="ITGRepository"/> when that component is requested
/// </summary>
/// <param name="repo">The <see cref="ITGRepository"/> the resulting <see cref="IServerInterface.GetComponent{T}"/> should return</param>
/// <returns>A mock <see cref="IServerInterface"/></returns>
protected IServerInterface MockInterfaceToRepo(ITGRepository repo)
/// <param name="repo">The <see cref="ITGRepository"/> the resulting <see cref="IClient.GetComponent{T}"/> should return</param>
/// <returns>A mock <see cref="IClient"/></returns>
protected IInstance MockInterfaceToRepo(ITGRepository repo)
{
var mock = new Mock<IServerInterface>();
mock.Setup(foo => foo.GetComponent<ITGRepository>()).Returns(repo);
var mock = new Mock<IInstance>();
mock.Setup(foo => foo.Repository).Returns(repo);
return mock.Object;
}
}
@@ -21,7 +21,7 @@ namespace TGS.CommandLine.Commands.Repository.Tests
var ran = false;
var repo = new Mock<ITGRepository>();
repo.Setup(foo => foo.SetPushTestmergeCommits(true)).Callback(() => { ran = true; });
ConsoleCommand.Interface = MockInterfaceToRepo(repo.Object);
ConsoleCommand.Instance = MockInterfaceToRepo(repo.Object);
Assert.AreEqual(new RepoSetPushTestmergeCommitsCommand().DoRun(new List<string> { "on" }), Command.ExitCode.Normal);
Assert.IsTrue(ran);
}
@@ -36,7 +36,7 @@ namespace TGS.CommandLine.Commands.Repository.Tests
var ran = false;
var repo = new Mock<ITGRepository>();
repo.Setup(foo => foo.SetPushTestmergeCommits(false)).Callback(() => { ran = true; });
ConsoleCommand.Interface = MockInterfaceToRepo(repo.Object);
ConsoleCommand.Instance = MockInterfaceToRepo(repo.Object);
Assert.AreEqual(new RepoSetPushTestmergeCommitsCommand().DoRun(new List<string> { "off" }), Command.ExitCode.Normal);
Assert.IsTrue(ran);
}
@@ -32,13 +32,13 @@ namespace TGS.CommandLine.Commands.Repository.Tests
var ran = false;
var mock = GetDefaultMock();
mock.Setup(foo => foo.PushTestmergeCommits()).Returns(false).Callback(() => ran = true);
ConsoleCommand.Interface = MockInterfaceToRepo(mock.Object);
ConsoleCommand.Instance = MockInterfaceToRepo(mock.Object);
Assert.AreEqual(new RepoStatusCommand().DoRun(new List<string> { }), Command.ExitCode.Normal);
Assert.IsTrue(ran);
ran = false;
mock.Setup(foo => foo.PushTestmergeCommits()).Returns(true).Callback(() => ran = true);
ConsoleCommand.Interface = MockInterfaceToRepo(mock.Object);
ConsoleCommand.Instance = MockInterfaceToRepo(mock.Object);
Assert.AreEqual(new RepoStatusCommand().DoRun(new List<string> { }), Command.ExitCode.Normal);
Assert.IsTrue(ran);
}
@@ -20,8 +20,7 @@ namespace TGS.ControlPanel.Tests
{
var mockLanding = new Mock<ITGLanding>();
mockLanding.Setup(x => x.ListInstances()).Returns(new List<InstanceMetadata>());
var mockInter = new Mock<IServerInterface>();
mockInter.Setup(x => x.GetComponent<ITGLanding>()).Returns(mockLanding.Object);
var mockInter = new Mock<IServer>();
new InstanceSelector(mockInter.Object).Dispose();
}
+7 -7
View File
@@ -27,7 +27,7 @@ namespace TGS.Interface.Tests
Assert.IsFalse(String.IsNullOrWhiteSpace(message));
return true;
};
ServerInterface.SetBadCertificateHandler(func);
Client.SetBadCertificateHandler(func);
}
/// <summary>
@@ -37,7 +37,7 @@ namespace TGS.Interface.Tests
public void TestBadCertificateHandler()
{
var ran = false;
ServerInterface.SetBadCertificateHandler(_ =>
Client.SetBadCertificateHandler(_ =>
{
ran = true;
return true;
@@ -50,9 +50,9 @@ namespace TGS.Interface.Tests
/// Creates a remote configured <see cref="Interface"/> pointing at an invalid address
/// </summary>
/// <returns>The created <see cref="Interface"/></returns>
ServerInterface CreateFakeRemoteInterface()
Client CreateFakeRemoteInterface()
{
return new ServerInterface(new RemoteLoginInfo("some.fake.url.420", 34752, "user", "password"));
return new Client(new RemoteLoginInfo("some.fake.url.420", 34752, "user", "password"));
}
/// <summary>
@@ -61,7 +61,7 @@ namespace TGS.Interface.Tests
[TestMethod]
public void TestLocalInstantiation()
{
Assert.IsFalse(new ServerInterface().IsRemoteConnection);
Assert.IsFalse(new Client().IsRemoteConnection);
}
/// <summary>
@@ -77,7 +77,7 @@ namespace TGS.Interface.Tests
public void TestCopyRemoteInterface()
{
var first = CreateFakeRemoteInterface();
var second = new ServerInterface(first.LoginInfo);
var second = new Client(first.LoginInfo);
Assert.AreEqual(first.LoginInfo.IP, second.LoginInfo.IP);
Assert.AreEqual(first.LoginInfo.Port, second.LoginInfo.Port);
Assert.AreEqual(first.LoginInfo.Username, second.LoginInfo.Username);
@@ -88,7 +88,7 @@ namespace TGS.Interface.Tests
[TestMethod]
public void TestLocalAccessInterfaceAllowsWindowsImpersonation()
{
var inter = new ServerInterface();
var inter = new Client();
var po = new PrivateObject(inter);
var cf = (ChannelFactory<ITGConfig>)po.Invoke("CreateChannel", new Type[] { typeof(string) }, new object[] { TestInstanceName }, new Type[] { typeof(ITGConfig) });
Assert.AreEqual(cf.Credentials.Windows.AllowedImpersonationLevel, System.Security.Principal.TokenImpersonationLevel.Impersonation);