mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-25 05:56:58 +01:00
Heavy instancing work
Added InstanceRootCommand for blocking instance based commands if no instance is chosen CLI now prints the service version Added service level CLI commands Fixed Service.LockLoggingID Added InstanceMetadata DataContract Implemented Service.ListInstances ExitCode is now set to int parent type Fixed ConnectivityLevel flags Optimized channel closing during instance switching
This commit is contained in:
@@ -4,7 +4,7 @@ using TGServiceInterface.Components;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
class AdminCommand : RootCommand
|
||||
class AdminCommand : InstanceRootCommand
|
||||
{
|
||||
public AdminCommand()
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ using TGServiceInterface.Components;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
class BYONDCommand : RootCommand
|
||||
class BYONDCommand : InstanceRootCommand
|
||||
{
|
||||
public BYONDCommand()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ using TGServiceInterface.Components;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
class IRCCommand : RootCommand
|
||||
class IRCCommand : InstanceRootCommand
|
||||
{
|
||||
public IRCCommand()
|
||||
{
|
||||
@@ -17,7 +17,7 @@ namespace TGCommandLine
|
||||
return "Manages the IRC bot";
|
||||
}
|
||||
}
|
||||
class DiscordCommand : RootCommand
|
||||
class DiscordCommand : InstanceRootCommand
|
||||
{
|
||||
public DiscordCommand()
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ using TGServiceInterface.Components;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
class ConfigCommand : RootCommand
|
||||
class ConfigCommand : InstanceRootCommand
|
||||
{
|
||||
public ConfigCommand()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ using TGServiceInterface.Components;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
class DDCommand : RootCommand
|
||||
class DDCommand : InstanceRootCommand
|
||||
{
|
||||
public DDCommand()
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ using TGServiceInterface.Components;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
class DMCommand : RootCommand
|
||||
class DMCommand : InstanceRootCommand
|
||||
{
|
||||
public DMCommand()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using TGServiceInterface;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
abstract class InstanceRootCommand : RootCommand
|
||||
{
|
||||
public static Interface 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace TGCommandLine
|
||||
|
||||
class Program
|
||||
{
|
||||
static bool interactive = false;
|
||||
static bool interactive = false, saidSrvVersion = false;
|
||||
static Interface currentInterface;
|
||||
static Command.ExitCode RunCommandLine(IList<string> argsAsList)
|
||||
{
|
||||
@@ -83,6 +83,11 @@ namespace TGCommandLine
|
||||
SentVMMWarning = true;
|
||||
Console.WriteLine(error);
|
||||
}
|
||||
else if (interactive && !saidSrvVersion)
|
||||
{
|
||||
Console.WriteLine("Connectd to service version: " + currentInterface.GetService().Version());
|
||||
saidSrvVersion = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -97,7 +102,6 @@ namespace TGCommandLine
|
||||
|
||||
static void ReplaceInterface(Interface I)
|
||||
{
|
||||
|
||||
if (!interactive)
|
||||
I.SetBadCertificateHandler((message) =>
|
||||
{
|
||||
@@ -110,6 +114,8 @@ namespace TGCommandLine
|
||||
I.SetBadCertificateHandler(BadCertificateInteractive);
|
||||
currentInterface = I;
|
||||
ConsoleCommand.Interface = I;
|
||||
InstanceRootCommand.currentInterface = I;
|
||||
saidSrvVersion = false;
|
||||
}
|
||||
|
||||
public static string ReadLineSecure()
|
||||
@@ -156,21 +162,60 @@ namespace TGCommandLine
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to set <see cref="currentInterface"/>'s <see cref="ITGInstance"/> to <paramref name="instanceName"/>, outputting appropriate messages
|
||||
/// </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="Interface.ConnectToInstance(string)"/>, <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
|
||||
{
|
||||
if(!silentSuccess)
|
||||
Console.WriteLine("Successfully conected to instance!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int Main(string[] args)
|
||||
{
|
||||
ReplaceInterface(new Interface());
|
||||
Command.OutputProcVar.Value = Console.WriteLine;
|
||||
if (args.Length != 0)
|
||||
return (int)RunCommandLine(new List<string>(args));
|
||||
|
||||
Console.WriteLine("Type 'remote' to connect to a remote service");
|
||||
{
|
||||
var argsAsList = new List<string>(args);
|
||||
for (var I = 0; I < argsAsList.Count - 1; ++I)
|
||||
if (argsAsList[I].ToLower() == "--instance")
|
||||
{
|
||||
if (!CheckInstanceConnectivity(args[I + 1], true))
|
||||
return (int)Command.ExitCode.ConnectionError;
|
||||
argsAsList.RemoveRange(I, 2);
|
||||
break;
|
||||
}
|
||||
return (int)RunCommandLine(argsAsList);
|
||||
}
|
||||
//interactive mode
|
||||
|
||||
Console.WriteLine("Type 'instance' to connect to a server instance");
|
||||
Console.WriteLine("Type 'remote' to connect to a remote service");
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.Write("Enter command: ");
|
||||
var NextCommand = Console.ReadLine();
|
||||
switch (NextCommand.ToLower())
|
||||
{
|
||||
case "instance":
|
||||
Console.Write("Enter instance name: ");
|
||||
CheckInstanceConnectivity(Console.ReadLine(), false);
|
||||
break;
|
||||
case "remote":
|
||||
SentVMMWarning = false;
|
||||
Console.Write("Enter server address: ");
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace TGCommandLine
|
||||
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))
|
||||
tmp.Add(new AdminCommand());
|
||||
if (I.ConnectionStatus().HasFlag(ConnectivityLevel.Administrator))
|
||||
tmp.Add(new ServiceCommand());
|
||||
Children = tmp.ToArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,433 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TGServiceInterface;
|
||||
|
||||
namespace TGCommandLine
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for managing the <see cref="TGServiceInterface.Components.ITGSService"/>
|
||||
/// </summary>
|
||||
class ServiceCommand : RootCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceCommand"/>
|
||||
/// </summary>
|
||||
public ServiceCommand()
|
||||
{
|
||||
Keyword = "service";
|
||||
Children = new Command[] { new ServiceCreateInstanceCommand(), new ServiceDetachInstanceCommand(), new ServiceEnableInstanceCommand(), new ServiceImportInstanceCommand(), new ServiceListInstancesCommand(), new ServicePythonPathCommand(), new ServiceSetPythonPathCommand(), new ServiceSetRemoteAccessPortCommand(), new ServiceRemoteAccessPortCommand(), new ServiceDisableInstanceCommand(), new ServiceRenameInstanceCommand() };
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Manage service wide settings";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.CreateInstance(string, string)"/>
|
||||
/// </summary>
|
||||
class ServiceCreateInstanceCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceCreateInstanceCommand"/>
|
||||
/// </summary>
|
||||
public ServiceCreateInstanceCommand()
|
||||
{
|
||||
Keyword = "create-instance";
|
||||
RequiredParameters = 2;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Creates a new instance at the given path";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<name> <path>";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Interface.GetService().CreateInstance(parameters[0], parameters[1]);
|
||||
if (res != null)
|
||||
{
|
||||
OutputProc(res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.ListInstances"/>
|
||||
/// </summary>
|
||||
class ServiceListInstancesCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceListInstancesCommand"/>
|
||||
/// </summary>
|
||||
public ServiceListInstancesCommand()
|
||||
{
|
||||
Keyword = "list-instances";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Lists all instances";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
foreach (var I in Interface.GetService().ListInstances())
|
||||
OutputProc(String.Format("{0} ({1}):\t{2}{3}", I.Name, I.Path, I.Enabled ? "Online" : "Offline", I.Enabled ? String.Format(" ({0})", I.LoggingID) : ""));
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.DetachInstance(string)"/>
|
||||
/// </summary>
|
||||
class ServiceDetachInstanceCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceDetachInstanceCommand"/>
|
||||
/// </summary>
|
||||
public ServiceDetachInstanceCommand()
|
||||
{
|
||||
Keyword = "detach-instance";
|
||||
RequiredParameters = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Detaches an instance";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<name>";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Interface.GetService().DetachInstance(parameters[0]);
|
||||
if (res != null)
|
||||
{
|
||||
OutputProc(res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.ImportInstance(string)"/>
|
||||
/// </summary>
|
||||
class ServiceImportInstanceCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceImportInstanceCommand"/>
|
||||
/// </summary>
|
||||
public ServiceImportInstanceCommand()
|
||||
{
|
||||
Keyword = "import-instance";
|
||||
RequiredParameters = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Imports an instance (Chat settings will be lost if they are from a different windows installation)";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<path>";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Interface.GetService().ImportInstance(parameters[0]);
|
||||
if (res != null)
|
||||
{
|
||||
OutputProc(res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.PythonPath"/>
|
||||
/// </summary>
|
||||
class ServicePythonPathCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServicePythonPathCommand"/>
|
||||
/// </summary>
|
||||
public ServicePythonPathCommand()
|
||||
{
|
||||
Keyword = "python";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Displays configured path the service uses for python";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Interface.GetService().PythonPath();
|
||||
if (res != null)
|
||||
{
|
||||
OutputProc(res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetPythonPath(string)"/>
|
||||
/// </summary>
|
||||
class ServiceSetPythonPathCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceSetPythonPathCommand"/>
|
||||
/// </summary>
|
||||
public ServiceSetPythonPathCommand()
|
||||
{
|
||||
Keyword = "set-python";
|
||||
RequiredParameters = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Sets the path to the python installation";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<path>";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
Interface.GetService().SetPythonPath(parameters[0]);
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetInstanceEnabled(string, bool)"/> with a <see langword="true"/> parameter
|
||||
/// </summary>
|
||||
class ServiceEnableInstanceCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceEnableInstanceCommand"/>
|
||||
/// </summary>
|
||||
public ServiceEnableInstanceCommand()
|
||||
{
|
||||
Keyword = "enable-instance";
|
||||
RequiredParameters = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Enables the specified instance";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<name>";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Interface.GetService().SetInstanceEnabled(parameters[0], true);
|
||||
if (res != null)
|
||||
{
|
||||
OutputProc(res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetInstanceEnabled(string, bool)"/> with a <see langword="false"/> parameter
|
||||
/// </summary>
|
||||
class ServiceDisableInstanceCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceDisableInstanceCommand"/>
|
||||
/// </summary>
|
||||
public ServiceDisableInstanceCommand()
|
||||
{
|
||||
Keyword = "disable-instance";
|
||||
RequiredParameters = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Disables the specified instance";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<name>";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Interface.GetService().SetInstanceEnabled(parameters[0], false);
|
||||
if (res != null)
|
||||
{
|
||||
OutputProc(res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.RemoteAccessPort"/>
|
||||
/// </summary>
|
||||
class ServiceRemoteAccessPortCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceRemoteAccessPortCommand"/>
|
||||
/// </summary>
|
||||
public ServiceRemoteAccessPortCommand()
|
||||
{
|
||||
Keyword = "port";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Displays the service's remote access port";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
OutputProc(Interface.GetService().RemoteAccessPort().ToString());
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetRemoteAccessPort(ushort)"/>
|
||||
/// </summary>
|
||||
class ServiceSetRemoteAccessPortCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceSetRemoteAccessPortCommand"/>
|
||||
/// </summary>
|
||||
public ServiceSetRemoteAccessPortCommand()
|
||||
{
|
||||
Keyword = "set-port";
|
||||
RequiredParameters = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Sets the service's remote access port";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<port>";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
ushort port;
|
||||
try
|
||||
{
|
||||
port = Convert.ToUInt16(parameters[0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
OutputProc("Invalid port number!");
|
||||
return ExitCode.BadCommand;
|
||||
}
|
||||
|
||||
var res = Interface.GetService().SetRemoteAccessPort(port);
|
||||
if (res != null)
|
||||
{
|
||||
OutputProc(res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
OutputProc("Change will be applied after service restart");
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.RenameInstance(string, string)"/>
|
||||
/// </summary>
|
||||
class ServiceRenameInstanceCommand : ConsoleCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ServiceRenameInstanceCommand"/>
|
||||
/// </summary>
|
||||
public ServiceRenameInstanceCommand()
|
||||
{
|
||||
Keyword = "rename-instance";
|
||||
RequiredParameters = 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetHelpText()
|
||||
{
|
||||
return "Renames an instance. Will temporarily disable the instance if it is active";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetArgumentString()
|
||||
{
|
||||
return "<name> <new_name>";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ExitCode Run(IList<string> parameters)
|
||||
{
|
||||
var res = Interface.GetService().RenameInstance(parameters[0], parameters[1]);
|
||||
if (res != null)
|
||||
{
|
||||
OutputProc(res);
|
||||
return ExitCode.ServerError;
|
||||
}
|
||||
return ExitCode.Normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,11 +48,13 @@
|
||||
<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" />
|
||||
<Compile Include="RootCommands.cs" />
|
||||
<Compile Include="..\Version.cs" />
|
||||
<Compile Include="ServiceCommands.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
|
||||
@@ -265,6 +265,7 @@ namespace TGServerService
|
||||
for (byte I = 1; I < 100; ++I)
|
||||
if (!UsedLoggingIDs.Contains(I))
|
||||
{
|
||||
UsedLoggingIDs.Add(I);
|
||||
return I;
|
||||
}
|
||||
}
|
||||
@@ -407,9 +408,21 @@ namespace TGServerService
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDictionary<string, string> ListInstances()
|
||||
public IList<InstanceMetadata> ListInstances()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var result = new List<InstanceMetadata>();
|
||||
lock (this)
|
||||
foreach (var I in Properties.Settings.Default.InstancePaths) {
|
||||
var ic = InstanceConfig.Load(I);
|
||||
result.Add(new InstanceMetadata
|
||||
{
|
||||
Name = ic.Name,
|
||||
Path = I,
|
||||
Enabled = ic.Enabled,
|
||||
LoggingID = (byte)(ic.Enabled ? ((ServerInstance)hosts[ic.Name].SingletonInstance).LoggingID : 0)
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -428,6 +441,7 @@ namespace TGServerService
|
||||
try
|
||||
{
|
||||
var ic = new InstanceConfig(path);
|
||||
ic.Name = Name;
|
||||
Directory.CreateDirectory(path);
|
||||
ic.Save();
|
||||
Properties.Settings.Default.InstancePaths.Add(path);
|
||||
@@ -593,7 +607,7 @@ namespace TGServerService
|
||||
finally
|
||||
{
|
||||
if (ie)
|
||||
result = SetInstanceEnabled(new_name, true) + " "+ result;
|
||||
result = SetInstanceEnabled(new_name, true) + " " + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace TGServiceInterface
|
||||
/// <summary>
|
||||
/// Exit codes for <see cref="Command"/>s
|
||||
/// </summary>
|
||||
public enum ExitCode
|
||||
public enum ExitCode : int
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="Command"/> ran successfully
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace TGServiceInterface.Components
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="IDictionary{TKey, TValue}"/> of instance names relating to their paths</returns>
|
||||
[OperationContract]
|
||||
IDictionary<string, string> ListInstances();
|
||||
IList<InstanceMetadata> ListInstances();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new server instance
|
||||
|
||||
@@ -19,11 +19,11 @@ namespace TGServiceInterface
|
||||
/// <summary>
|
||||
/// The connected user is authenticated
|
||||
/// </summary>
|
||||
Authenticated = 2,
|
||||
Authenticated = 2 | Connected,
|
||||
/// <summary>
|
||||
/// The connected user is an administrator
|
||||
/// </summary>
|
||||
Administrator = 4,
|
||||
Administrator = 4 | Authenticated,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TGServiceInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata about an <see cref="Components.ITGInstance"/>
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class InstanceMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the <see cref="Components.ITGInstance"/>
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// The path of the <see cref="Components.ITGInstance"/>
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string Path { get; set; }
|
||||
/// <summary>
|
||||
/// Whether or not the <see cref="Components.ITGInstance"/> is enabled
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public bool Enabled { get; set; }
|
||||
/// <summary>
|
||||
/// The logging ID of the <see cref="Components.ITGInstance"/>. Will be 0 if <see cref="Enabled"/> is <see langword="false"/>
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public byte LoggingID { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -71,9 +71,9 @@ namespace TGServiceInterface
|
||||
readonly string HTTPSPassword;
|
||||
|
||||
/// <summary>
|
||||
/// Associated list of open <see cref="ChannelFactory"/>s keyed by <see langword="interface"/> type. A <see cref="ChannelFactory"/> in this list may close or fault at any time. Must be locked before being accessed
|
||||
/// 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<Type, ChannelFactory> ChannelFactoryCache = new Dictionary<Type, ChannelFactory>();
|
||||
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
|
||||
@@ -136,7 +136,7 @@ namespace TGServiceInterface
|
||||
return ConnectivityLevel.None;
|
||||
var prevInstance = InstanceName;
|
||||
if (prevInstance != instanceName)
|
||||
CloseAllChannels();
|
||||
CloseAllChannels(false);
|
||||
InstanceName = instanceName;
|
||||
if (skipAuthChecks)
|
||||
return ConnectivityLevel.Connected;
|
||||
@@ -202,13 +202,28 @@ namespace TGServiceInterface
|
||||
/// <summary>
|
||||
/// Closes all <see cref="ChannelFactory"/>s stored in <see cref="ChannelFactoryCache"/> and clears it
|
||||
/// </summary>
|
||||
void CloseAllChannels()
|
||||
/// <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)
|
||||
{
|
||||
foreach (var I in ChannelFactoryCache)
|
||||
CloseChannel(I.Value);
|
||||
ChannelFactoryCache.Clear();
|
||||
{
|
||||
if (RootThings.Contains(I.Key))
|
||||
continue;
|
||||
var cf = I.Value;
|
||||
try
|
||||
{
|
||||
cf.Closed += ChannelFactory_Closed;
|
||||
cf.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
cf.Abort();
|
||||
}
|
||||
ChannelFactoryCache.Remove(I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,23 +246,6 @@ namespace TGServiceInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely shuts down a single <see cref="ChannelFactory"/>
|
||||
/// </summary>
|
||||
/// <param name="cf">The <see cref="ChannelFactory"/> to shutdown</param>
|
||||
static void CloseChannel(ChannelFactory cf)
|
||||
{
|
||||
try
|
||||
{
|
||||
cf.Closed += ChannelFactory_Closed;
|
||||
cf.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
cf.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes a closed <see cref="ChannelFactory"/>
|
||||
/// </summary>
|
||||
@@ -275,8 +273,10 @@ namespace TGServiceInterface
|
||||
{
|
||||
if (useInstanceName & InstanceName == null)
|
||||
throw new Exception("Instance not selected!");
|
||||
|
||||
var tot = typeof(T);
|
||||
var actualToT = typeof(T);
|
||||
var tot = actualToT.Name;
|
||||
if (actualToT == typeof(ITGConnectivity) && !useInstanceName)
|
||||
tot = 'S' + tot;
|
||||
ChannelFactory<T> cf;
|
||||
|
||||
lock (ChannelFactoryCache)
|
||||
@@ -413,7 +413,7 @@ namespace TGServiceInterface
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
CloseAllChannels();
|
||||
CloseAllChannels(true);
|
||||
}
|
||||
|
||||
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
<Compile Include="DreamDaemonBridge.cs" />
|
||||
<Compile Include="Enumerations.cs" />
|
||||
<Compile Include="Helpers.cs" />
|
||||
<Compile Include="InstanceMetadata.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Components\Repository.cs" />
|
||||
<Compile Include="PullRequestInfo.cs" />
|
||||
|
||||
Reference in New Issue
Block a user