diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index b839e64b22..b404563eeb 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -32,7 +32,7 @@ The [WiX Toolset](http://wixtoolset.org/) is used for creating the installer .ms
#### Debugging
-So you've built the project and everything's good, right? Now you have to debug it. Debugging the command line and control panel are easy enough, just launch them like any other process. Debugging the TGS.Server.Service itself though requires a bit of finagling due to how Windows services work.
+So you've built the project and everything's good, right? Now you have to debug it. Debugging the command line and control panel are easy enough, just launch them like any other process. Debugging the TGS.Server itself though requires a bit of finagling due to how Windows services work.
1. Uninstall any release versions of TG Station Server 3 you may have on your machine
1. Open an administrative Windows cmd prompt
diff --git a/README.md b/README.md
index e99ccffc5f..8c1ca4f6c4 100644
--- a/README.md
+++ b/README.md
@@ -191,7 +191,7 @@ You can clear all active test merges using `Reset to Origin Branch` in the `Repo
### Viewing Server Logs
* Logs are stored in the Windows event viewer under `Windows Logs` -> `Application`. You'll need to filter this list for `TG Station Server`
-* Every event type is keyed with an ID. A complete listing of these IDs and their purpose can be found [here](https://github.com/tgstation/tgstation-server/blob/master/TGS.Server.Service/EventID.cs).
+* Every event type is keyed with an ID. A complete listing of these IDs and their purpose can be found [here](https://github.com/tgstation/tgstation-server/blob/master/TGS.Server/EventID.cs).
* You can also import the custom view `View TGS3 Logs.xml` in this folder to have them automatically filtered
### Enabling upstream changelog generation
diff --git a/TGS.Installer/Product.wxs b/TGS.Installer/Product.wxs
index a65794dd14..dfb6546fce 100644
--- a/TGS.Installer/Product.wxs
+++ b/TGS.Installer/Product.wxs
@@ -84,37 +84,40 @@
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -128,24 +131,24 @@
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/TGS.Installer/TGS.Installer.wixproj b/TGS.Installer/TGS.Installer.wixproj
index 6d26789638..bc81125088 100644
--- a/TGS.Installer/TGS.Installer.wixproj
+++ b/TGS.Installer/TGS.Installer.wixproj
@@ -50,6 +50,14 @@
TGS.Server.Service
+ {3f81e398-b223-4006-b40c-c2800714ce29}
+ True
+ True
+ Binaries;Content;Satellites
+ INSTALLFOLDER
+
+
+ TGS.Server
{f32eda25-0855-411c-af5e-f0d042917e2d}
True
True
diff --git a/TGS.Server.Service/App.config b/TGS.Server.Service/App.config
index cfd0a6b77d..8227adb989 100644
--- a/TGS.Server.Service/App.config
+++ b/TGS.Server.Service/App.config
@@ -1,28 +1,6 @@
-
+
-
-
-
-
-
-
-
+
-
-
-
- C:\Python27
-
-
- True
-
-
- 7
-
-
- 38607
-
-
-
diff --git a/TGS.Server.Service/Properties/AssemblyInfo.cs b/TGS.Server.Service/Properties/AssemblyInfo.cs
index b7a644ae25..e4e22f2673 100644
--- a/TGS.Server.Service/Properties/AssemblyInfo.cs
+++ b/TGS.Server.Service/Properties/AssemblyInfo.cs
@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TGStation Server Service")]
-[assembly: AssemblyDescription("Server Service for running BYOND games")]
+[assembly: AssemblyDescription("Windows service adapter for TGStation Server")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
@@ -13,4 +13,4 @@ using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("f32eda25-0855-411c-af5e-f0d042917e2d")]
+[assembly: Guid("3f81e398-b223-4006-b40c-c2800714ce29")]
diff --git a/TGS.Server.Service/Service.cs b/TGS.Server.Service/Service.cs
index 99ec13e82e..af88d24b50 100644
--- a/TGS.Server.Service/Service.cs
+++ b/TGS.Server.Service/Service.cs
@@ -1,693 +1,63 @@
using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
using System.Diagnostics;
-using System.IO;
-using System.Security.Principal;
-using System.ServiceModel;
using System.ServiceProcess;
-using TGS.Interface;
-using TGS.Interface.Components;
namespace TGS.Server.Service
{
///
- /// The windows service the application runs as
+ /// Windows adapter for
///
- [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
- class Service : ServiceBase, ITGSService, ITGConnectivity, ITGLanding, ITGInstanceManager
+ public sealed class Service : ServiceBase, ILogger
{
///
- /// The logging ID used for events
+ /// The entry point for the program. Calls with a new as a parameter
///
- public const byte LoggingID = 0;
+ public static void Main() => Run(new Service());
///
- /// The service version based on the
+ /// The the manages
///
- public static readonly string VersionString = "/tg/station 13 Server Service v" + FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion;
+ Server activeServer;
- ///
- /// Singleton instance
- ///
- static Service ActiveService;
-
- ///
- /// Cancels WCF's user impersonation to allow clean access to writing log files
- ///
- public static void CancelImpersonation()
+ ///
+ public void WriteAccess(string username, bool authSuccess, byte loggingID)
{
- WindowsIdentity.Impersonate(IntPtr.Zero);
+ EventLog.WriteEntry(String.Format("Access from: {0}", username), authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit , (int)EventID.Authentication + loggingID);
+ }
+
+ ///
+ public void WriteError(string message, EventID id, byte loggingID)
+ {
+ EventLog.WriteEntry(message, EventLogEntryType.Error, (int)id + loggingID);
+ }
+
+ ///
+ public void WriteInfo(string message, EventID id, byte loggingID)
+ {
+ EventLog.WriteEntry(message, EventLogEntryType.Information, (int)id + loggingID);
+ }
+
+ ///
+ public void WriteWarning(string message, EventID id, byte loggingID)
+ {
+ EventLog.WriteEntry(message, EventLogEntryType.Warning, (int)id + loggingID);
}
///
- /// Writes an event to Windows the event log
+ /// Called when the is started. Creates a new
///
- /// The log message
- /// The of the message
- /// The of the event
- /// The logging source ID for the event
- public static void WriteEntry(string message, EventID id, EventLogEntryType eventType, byte loggingID)
- {
- ActiveService.EventLog.WriteEntry(message, eventType, (int)id + loggingID);
- }
-
- ///
- /// Checks an for illegal characters
- ///
- /// The name to check
- /// if contains no illegal characters, error message otherwise
- static string CheckInstanceName(string instanceName)
- {
- char[] bannedCharacters = { ';', '&', '=', '%' };
- foreach (var I in bannedCharacters)
- if (instanceName.Contains(I.ToString()))
- return "Instance names may not contain the following characters: ';', '&', '=', or '%'";
- return null;
- }
-
- ///
- /// Sets up ServiceName and
- ///
- public Service()
- {
- ServiceName = "TG Station Server";
- if (ActiveService != null)
- throw new Exception("There is already a Service instance running!");
- ActiveService = this;
- }
-
- ///
- /// Clears
- ///
- /// if this method was invoked from , otherwise it was invoked by the finalizer
- protected override void Dispose(bool disposing)
- {
- ActiveService = null;
- base.Dispose(disposing);
- }
-
- ///
- /// The WCF host that contains connects to
- ///
- ServiceHost serviceHost;
- ///
- /// Map of to the respective hosting the
- ///
- IDictionary hosts;
- ///
- /// List of s in use
- ///
- IList UsedLoggingIDs = new List();
-
- ///
- /// Migrates the .NET config from to + 1
- ///
- /// The version to migrate from
- void MigrateSettings(int oldVersion)
- {
- var Config = Properties.Settings.Default;
- switch (oldVersion)
- {
- case 6: //switch to per-instance configs
- var IC = DeprecatedInstanceConfig.CreateFromNETSettings();
- IC.Save();
- Config.InstancePaths.Add(IC.Directory);
- break;
- }
- }
-
- ///
- /// Enumerates configured s. Detaches those that fail to load
- ///
- /// Each configured
- IEnumerable GetInstanceConfigs()
- {
- var pathsToRemove = new List();
- lock (this)
- {
- var IPS = Properties.Settings.Default.InstancePaths;
- foreach (var I in IPS)
- {
- IInstanceConfig ic;
- try
- {
- ic = InstanceConfig.Load(I);
- }
- catch (Exception e)
- {
- WriteEntry(String.Format("Unable load instance config at path {0}. Error: {1} Detaching...", I, e.ToString()), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
- pathsToRemove.Add(I);
- continue;
- }
- yield return ic;
- }
- foreach (var I in pathsToRemove)
- IPS.Remove(I);
- }
- }
-
- ///
- /// Overrides and saves the configured if requested by command line parameters
- ///
- /// The command line parameters for the
- void ChangePortFromCommandLine(string[] args)
- {
- var Config = Properties.Settings.Default;
-
- for (var I = 0; I < args.Length - 1; ++I)
- if (args[I].ToLower() == "-port")
- {
- try
- {
- var res = Convert.ToUInt16(args[I + 1]);
- if (res == 0)
- throw new Exception("Cannot bind to port 0");
- Config.RemoteAccessPort = res;
- }
- catch (Exception e)
- {
- throw new Exception("Invalid argument for \"-port\"", e);
- }
- Config.Save();
- break;
- }
- }
-
- ///
- /// Called by the Windows service manager. Initializes and starts configured s
- ///
- /// Command line arguments for the
+ /// The service start arguments
protected override void OnStart(string[] args)
{
- Environment.CurrentDirectory = Directory.CreateDirectory(Path.GetTempPath() + "/TGStationServerService").FullName; //MOVE THIS POINTER BECAUSE ONE TIME I ALMOST ACCIDENTALLY NUKED MYSELF BY REFACTORING! http://imgur.com/zvGEpJD.png
-
- SetupConfig();
-
- ChangePortFromCommandLine(args);
-
- SetupService();
-
- SetupInstances();
-
- OnlineAllHosts();
+ activeServer = new Server(args, this);
}
///
- /// Writes some changes to the that always need to be done.
- ///
- void PrePrepConfig()
- {
- var Config = Properties.Settings.Default;
-
- if (Config.InstancePaths == null)
- Config.InstancePaths = new StringCollection();
- }
-
- ///
- /// Upgrades up the service configuration
- ///
- void SetupConfig()
- {
- var Config = Properties.Settings.Default;
- if (Config.UpgradeRequired)
- {
- var newVersion = Config.SettingsVersion;
- Config.Upgrade();
-
- PrePrepConfig();
-
- for (var oldVersion = Config.SettingsVersion; oldVersion < newVersion; ++oldVersion)
- MigrateSettings(oldVersion);
-
- Config.SettingsVersion = newVersion;
-
- Config.UpgradeRequired = false;
- Config.Save();
- }
- else
- PrePrepConfig();
- }
-
- ///
- /// Creates the for
- ///
- void SetupService()
- {
- serviceHost = CreateHost(this, ServerInterface.MasterInterfaceName);
- foreach (var I in ServerInterface.ValidServiceInterfaces)
- AddEndpoint(serviceHost, I);
- serviceHost.Authorization.ServiceAuthorizationManager = new RootAuthorizationManager(); //only admins can diddle us
- }
-
- ///
- /// Opens all created s
- ///
- void OnlineAllHosts()
- {
- serviceHost.Open();
- foreach (var I in hosts)
- I.Value.Open();
- }
-
- ///
- /// Creates a for using the default pipe, CloseTimeout for the , and the configured
- ///
- /// The
- /// The URL to access components on the
- /// The created
- static ServiceHost CreateHost(object singleton, string endpointPostfix)
- {
- return new ServiceHost(singleton, new Uri[] { new Uri(String.Format("net.pipe://localhost/{0}", endpointPostfix)), new Uri(String.Format("https://localhost:{0}/{1}", Properties.Settings.Default.RemoteAccessPort, endpointPostfix)) })
- {
- CloseTimeout = new TimeSpan(0, 0, 5)
- };
- }
-
- ///
- /// Creates s for all s as listed in , detaches bad ones
- ///
- void SetupInstances()
- {
- hosts = new Dictionary();
- var pathsToRemove = new List();
- var seenNames = new List();
- foreach (var I in GetInstanceConfigs())
- {
- if (seenNames.Contains(I.Name))
- {
- WriteEntry(String.Format("Instance at {0} has a duplicate name! Detaching...", I.Directory), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
- pathsToRemove.Add(I.Directory);
- }
- if (I.Enabled && SetupInstance(I) == null)
- pathsToRemove.Add(I.Directory);
- else
- seenNames.Add(I.Name);
- }
- foreach (var I in pathsToRemove)
- Properties.Settings.Default.InstancePaths.Remove(I);
- }
-
- ///
- /// Unlocks a acquired with
- ///
- /// The to unlock
- void UnlockLoggingID(byte ID)
- {
- lock (UsedLoggingIDs)
- {
- UsedLoggingIDs.Remove(ID);
- }
- }
-
- ///
- /// Gets and locks a
- ///
- /// A logging ID for the must be released using
- byte LockLoggingID()
- {
- lock (UsedLoggingIDs)
- {
- for (byte I = 1; I < 100; ++I)
- if (!UsedLoggingIDs.Contains(I))
- {
- UsedLoggingIDs.Add(I);
- return I;
- }
- }
- throw new Exception("All logging IDs in use!");
- }
-
- ///
- /// Creates and starts a for a at
- ///
- /// The for the
- /// The inactive on success, on failure
- ServiceHost SetupInstance(IInstanceConfig config)
- {
- ServerInstance instance;
- string instanceName;
- try
- {
- if (hosts.ContainsKey(config.Directory))
- {
- var datInstance = ((ServerInstance)hosts[config.Directory].SingletonInstance);
- WriteEntry(String.Format("Unable to start instance at path {0}. Has the same name as instance at path {1}. Detaching...", config.Directory, datInstance.ServerDirectory()), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
- return null;
- }
- if (!config.Enabled)
- return null;
- var ID = LockLoggingID();
- WriteEntry(String.Format("Instance {0} ({1}) assigned logging ID {2}", config.Name, config.Directory, ID), EventID.InstanceIDAssigned, EventLogEntryType.Information, ID);
- instanceName = config.Name;
- instance = new ServerInstance(config, ID);
- }
- catch (Exception e)
- {
- WriteEntry(String.Format("Unable to start instance at path {0}. Detaching... Error: {1}", config.Directory, e.ToString()), EventID.InstanceInitializationFailure, EventLogEntryType.Error, LoggingID);
- return null;
- }
-
- var host = CreateHost(instance, String.Format("{0}/{1}", ServerInterface.InstanceInterfaceName, instanceName));
- hosts.Add(instanceName, host);
-
- foreach (var J in ServerInterface.ValidInstanceInterfaces)
- AddEndpoint(host, J);
-
- host.Authorization.ServiceAuthorizationManager = instance;
- return host;
- }
-
- ///
- /// Adds a WCF endpoint for a component
- ///
- /// The service host to add the component to
- /// The type of the component
- 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);
- var httpsBinding = new WSHttpBinding()
- {
- SendTimeout = new TimeSpan(0, 0, 40),
- MaxReceivedMessageSize = ServerInterface.TransferLimitRemote
- };
- var requireAuth = typetype.Name != typeof(ITGConnectivity).Name;
- httpsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
- httpsBinding.Security.Mode = requireAuth ? SecurityMode.TransportWithMessageCredential : SecurityMode.Transport; //do not require auth for a connectivity check
- httpsBinding.Security.Message.ClientCredentialType = requireAuth ? MessageCredentialType.UserName : MessageCredentialType.None;
- host.AddServiceEndpoint(typetype, httpsBinding, bindingName);
- }
-
- ///
- /// Shuts down all active s and calls on it's
+ /// Called when the is stopped. Calls on
///
protected override void OnStop()
{
- lock (this)
- {
- try
- {
- foreach (var I in hosts)
- {
- var host = I.Value;
- var instance = (ServerInstance)host.SingletonInstance;
- host.Close();
- instance.Dispose();
- UnlockLoggingID(instance.LoggingID);
- }
- }
- catch (Exception e)
- {
- WriteEntry(e.ToString(), EventID.ServiceShutdownFail, EventLogEntryType.Error, LoggingID);
- }
- serviceHost.Close();
- }
- Properties.Settings.Default.Save();
- ActiveService = null;
- }
-
- ///
- public void VerifyConnection() { }
-
- ///
- public void PrepareForUpdate()
- {
- foreach (var I in hosts)
- ((ServerInstance)I.Value.SingletonInstance).Reattach(false);
- }
-
- ///
- public ushort RemoteAccessPort()
- {
- return Properties.Settings.Default.RemoteAccessPort;
- }
-
- ///
- public string SetRemoteAccessPort(ushort port)
- {
- if (port == 0)
- return "Cannot bind to port 0";
- Properties.Settings.Default.RemoteAccessPort = port;
- return null;
- }
-
- ///
- public string Version()
- {
- return VersionString;
- }
-
- ///
- public bool SetPythonPath(string path)
- {
- if (!Directory.Exists(path))
- return false;
- Properties.Settings.Default.PythonPath = Path.GetFullPath(path);
- return true;
- }
-
- ///
- public string PythonPath()
- {
- return Properties.Settings.Default.PythonPath;
- }
-
- ///
- public IList ListInstances()
- {
- var result = new List();
- lock (this)
- foreach (var ic in GetInstanceConfigs())
- result.Add(new InstanceMetadata
- {
- Name = ic.Name,
- Path = ic.Directory,
- Enabled = ic.Enabled,
- LoggingID = (byte)(ic.Enabled ? ((ServerInstance)hosts[ic.Name].SingletonInstance).LoggingID : 0)
- });
- return result;
- }
-
- ///
- public string CreateInstance(string Name, string path)
- {
- path = Program.NormalizePath(path);
- var res = CheckInstanceName(Name);
- if (res != null)
- return res;
- if (File.Exists(path) || Directory.Exists(path))
- return "Cannot create instance at pre-existing path!";
- var Config = Properties.Settings.Default;
- lock (this)
- {
- if (Config.InstancePaths.Contains(path))
- return String.Format("Instance at {0} already exists!", path);
- foreach (var oic in GetInstanceConfigs())
- if (Name == oic.Name)
- return String.Format("Instance named {0} already exists!", oic.Name);
- IInstanceConfig ic;
- try
- {
- ic = new InstanceConfig(path)
- {
- Name = Name
- };
- Directory.CreateDirectory(path);
- ic.Save();
- Properties.Settings.Default.InstancePaths.Add(path);
- }
- catch (Exception e)
- {
- return e.ToString();
- }
- return SetupOneInstance(ic);
- }
- }
-
- ///
- /// Starts and onlines an instance located at
- ///
- /// The for the
- /// on success, error message on failure
- string SetupOneInstance(IInstanceConfig config)
- {
- if (!config.Enabled)
- return null;
- try
- {
- var host = SetupInstance(config);
- if (host != null)
- host.Open();
- else
- lock (this)
- Properties.Settings.Default.InstancePaths.Remove(config.Directory);
- return null;
- }
- catch (Exception e)
- {
- return "Instance set up but an error occurred while starting it: " + e.ToString();
- }
- }
-
- ///
- public string ImportInstance(string path)
- {
- path = Program.NormalizePath(path);
- var Config = Properties.Settings.Default;
- lock (this)
- {
- if (Config.InstancePaths.Contains(path))
- return String.Format("Instance at {0} already exists!", path);
- if(!Directory.Exists(path))
- return String.Format("There is no instance located at {0}!", path);
- IInstanceConfig ic;
- try
- {
- ic = InstanceConfig.Load(path);
- foreach(var oic in GetInstanceConfigs())
- if(ic.Name == oic.Name)
- return String.Format("Instance named {0} already exists!", oic.Name);
- ic.Save();
- Properties.Settings.Default.InstancePaths.Add(path);
- }
- catch (Exception e)
- {
- return e.ToString();
- }
- return SetupOneInstance(ic);
- }
- }
-
- ///
- public bool InstanceEnabled(string Name)
- {
- lock(this)
- {
- return hosts.ContainsKey(Name);
- }
- }
-
- ///
- public string SetInstanceEnabled(string Name, bool enabled)
- {
- return SetInstanceEnabledImpl(Name, enabled, out string path);
- }
-
-
- ///
- /// Sets a 's enabled status
- ///
- /// The whom's status should be changed
- /// to enable the , to disable it
- /// The path to the modified
- /// on success, error message on failure
- string SetInstanceEnabledImpl(string Name, bool enabled, out string path)
- {
- path = null;
- lock (this)
- {
- var hostIsOnline = hosts.ContainsKey(Name);
- if (enabled)
- {
- if (hostIsOnline)
- return null;
- foreach (var ic in GetInstanceConfigs())
- if (ic.Name == Name)
- {
- path = ic.Directory;
- ic.Enabled = true;
- ic.Save();
- return SetupOneInstance(ic);
- }
- return String.Format("Instance {0} does not exist!", Name);
- }
- else
- {
- if (!hostIsOnline)
- return null;
- var host = hosts[Name];
- hosts.Remove(Name);
- var inst = (ServerInstance)host.SingletonInstance;
- host.Close();
- path = inst.ServerDirectory();
- inst.Offline();
- inst.Dispose();
- UnlockLoggingID(inst.LoggingID);
- return null;
- }
- }
- }
-
- ///
- public string RenameInstance(string name, string new_name)
- {
- if (name == new_name)
- return null;
- var res = CheckInstanceName(new_name);
- if (res != null)
- return res;
- lock (this)
- {
- //we have to check em all anyway
- IInstanceConfig the_droid_were_looking_for = null;
- foreach (var ic in GetInstanceConfigs())
- if (ic.Name == name)
- {
- the_droid_were_looking_for = ic;
- break;
- }
- else if (ic.Name == new_name)
- return String.Format("There is already another instance named {0}!", new_name);
- if (the_droid_were_looking_for == null)
- return String.Format("There is no instance named {0}!", name);
- var ie = InstanceEnabled(name);
- if(ie)
- SetInstanceEnabled(name, false);
- the_droid_were_looking_for.Name = new_name;
- string result = "";
- try
- {
- the_droid_were_looking_for.Save();
- result = null;
- }
- catch(Exception e)
- {
- result = "Could not save instance config! Error: " + e.ToString();
- }
- finally
- {
- if (ie)
- {
- var resRestore = SetInstanceEnabled(new_name, true);
- if (resRestore != null)
- result = (result + " " + resRestore).Trim();
- }
- }
- return result;
- }
- }
-
- ///
- public string DetachInstance(string name)
- {
- lock (this)
- {
- var res = SetInstanceEnabledImpl(name, false, out string path);
- if (res != null)
- return res;
- if (path == null) //gotta find it ourselves
- foreach (var ic in GetInstanceConfigs())
- if (ic.Name == name)
- {
- path = ic.Directory;
- break;
- }
- if (path == null)
- return String.Format("No instance named {0} exists!", name);
- Properties.Settings.Default.InstancePaths.Remove(path);
- return null;
- }
+ activeServer.Dispose();
}
}
}
diff --git a/TGS.Server.Service/TGS.Server.Service.csproj b/TGS.Server.Service/TGS.Server.Service.csproj
index 37e2262efc..cd31701a92 100644
--- a/TGS.Server.Service/TGS.Server.Service.csproj
+++ b/TGS.Server.Service/TGS.Server.Service.csproj
@@ -1,162 +1,63 @@
-
Debug
AnyCPU
- {F32EDA25-0855-411C-AF5E-F0D042917E2D}
+ {3F81E398-B223-4006-B40C-C2800714CE29}
WinExe
TGS.Server.Service
TGServerService
v4.5.2
512
true
-
-
-
- tgs.ico
-
-
+
+ AnyCPU
true
+ full
+ false
bin\Debug\
DEBUG;TRACE
- full
- AnyCPU
prompt
- MinimumRecommendedRules.ruleset
- true
+ 4
-
+
+ AnyCPU
+ pdbonly
+ true
bin\Release\
TRACE
- bin\x86\Release\TGS.Server.Service.xml
- true
- true
- pdbonly
- AnyCPU
prompt
- MinimumRecommendedRules.ruleset
- true
+ 4
- false
+ TGS.Server.Service.Service
-
- ..\packages\Discord.Net.Core.1.0.2\lib\net45\Discord.Net.Core.dll
-
-
- ..\packages\Discord.Net.Rest.1.0.2\lib\net45\Discord.Net.Rest.dll
-
-
- ..\packages\Discord.Net.WebSocket.1.0.2\lib\net45\Discord.Net.WebSocket.dll
-
-
- ..\packages\LibGit2Sharp-SSH.1.0.22\lib\net40\LibGit2Sharp.dll
-
-
- ..\packages\SmartIrc4net.1.1\lib\Meebey.SmartIrc4net.dll
-
-
- ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll
-
-
- ..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
-
-
-
-
-
- ..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- Settings.settings
-
-
Component
Component
-
-
+
-
- Designer
-
-
- Designer
-
-
- SettingsSingleFileGenerator
- Settings.Designer.cs
-
+
-
- {ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}
- TGS.Interface
+
+ {f32eda25-0855-411c-af5e-f0d042917e2d}
+ TGS.Server
-
-
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
\ No newline at end of file
diff --git a/TGS.Server/App.config b/TGS.Server/App.config
new file mode 100644
index 0000000000..91aa70ce1c
--- /dev/null
+++ b/TGS.Server/App.config
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ C:\Python27
+
+
+ True
+
+
+ 7
+
+
+ 38607
+
+
+
+
diff --git a/TGS.Server.Service/ChatCommands/ByondCommand.cs b/TGS.Server/ChatCommands/ByondCommand.cs
similarity index 95%
rename from TGS.Server.Service/ChatCommands/ByondCommand.cs
rename to TGS.Server/ChatCommands/ByondCommand.cs
index 5cc1a90740..b983339816 100644
--- a/TGS.Server.Service/ChatCommands/ByondCommand.cs
+++ b/TGS.Server/ChatCommands/ByondCommand.cs
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using TGS.Interface;
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// Retrieve the installed, staged, or latest availab
diff --git a/TGS.Server.Service/ChatCommands/ChatCommand.cs b/TGS.Server/ChatCommands/ChatCommand.cs
similarity index 96%
rename from TGS.Server.Service/ChatCommands/ChatCommand.cs
rename to TGS.Server/ChatCommands/ChatCommand.cs
index 7137fa0447..f742fadbf6 100644
--- a/TGS.Server.Service/ChatCommands/ChatCommand.cs
+++ b/TGS.Server/ChatCommands/ChatCommand.cs
@@ -2,7 +2,7 @@
using System.Threading;
using TGS.Interface;
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// A command heard by a
diff --git a/TGS.Server.Service/ChatCommands/CommandInfo.cs b/TGS.Server/ChatCommands/CommandInfo.cs
similarity index 94%
rename from TGS.Server.Service/ChatCommands/CommandInfo.cs
rename to TGS.Server/ChatCommands/CommandInfo.cs
index bc6ae15eed..4e650eaf89 100644
--- a/TGS.Server.Service/ChatCommands/CommandInfo.cs
+++ b/TGS.Server/ChatCommands/CommandInfo.cs
@@ -1,4 +1,4 @@
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// Metadata about the currently running
diff --git a/TGS.Server.Service/ChatCommands/KekCommand.cs b/TGS.Server/ChatCommands/KekCommand.cs
similarity index 91%
rename from TGS.Server.Service/ChatCommands/KekCommand.cs
rename to TGS.Server/ChatCommands/KekCommand.cs
index 6fe495690c..1826bf1876 100644
--- a/TGS.Server.Service/ChatCommands/KekCommand.cs
+++ b/TGS.Server/ChatCommands/KekCommand.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// kek
diff --git a/TGS.Server.Service/ChatCommands/PullRequestsCommand.cs b/TGS.Server/ChatCommands/PullRequestsCommand.cs
similarity index 95%
rename from TGS.Server.Service/ChatCommands/PullRequestsCommand.cs
rename to TGS.Server/ChatCommands/PullRequestsCommand.cs
index f3046931cc..e03d426c04 100644
--- a/TGS.Server.Service/ChatCommands/PullRequestsCommand.cs
+++ b/TGS.Server/ChatCommands/PullRequestsCommand.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// Retrieve the list of test-merged github pull requests
diff --git a/TGS.Server.Service/ChatCommands/RevisionCommand.cs b/TGS.Server/ChatCommands/RevisionCommand.cs
similarity index 94%
rename from TGS.Server.Service/ChatCommands/RevisionCommand.cs
rename to TGS.Server/ChatCommands/RevisionCommand.cs
index 3b91cdebd9..7fd99c0f28 100644
--- a/TGS.Server.Service/ChatCommands/RevisionCommand.cs
+++ b/TGS.Server/ChatCommands/RevisionCommand.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// Retrieves the git SHA of the live DreamDaemon code
diff --git a/TGS.Server.Service/ChatCommands/RootChatCommand.cs b/TGS.Server/ChatCommands/RootChatCommand.cs
similarity index 94%
rename from TGS.Server.Service/ChatCommands/RootChatCommand.cs
rename to TGS.Server/ChatCommands/RootChatCommand.cs
index 1fac6ee2ce..800147a412 100644
--- a/TGS.Server.Service/ChatCommands/RootChatCommand.cs
+++ b/TGS.Server/ChatCommands/RootChatCommand.cs
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using TGS.Interface;
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// The main root chat command
diff --git a/TGS.Server.Service/ChatCommands/ServerChatCommand.cs b/TGS.Server/ChatCommands/ServerChatCommand.cs
similarity index 93%
rename from TGS.Server.Service/ChatCommands/ServerChatCommand.cs
rename to TGS.Server/ChatCommands/ServerChatCommand.cs
index 0729409c1e..fee9f70eb5 100644
--- a/TGS.Server.Service/ChatCommands/ServerChatCommand.cs
+++ b/TGS.Server/ChatCommands/ServerChatCommand.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// s generated by DreamDaemon via the API
@@ -37,7 +37,7 @@ namespace TGS.Server.Service.ChatCommands
///
protected override ExitCode Run(IList parameters)
{
- var res = Instance.SendCommand(String.Format("{0};sender={1};custom={2}", Keyword, CommandInfo.Value.Speaker, Program.SanitizeTopicString(String.Join(" ", parameters))));
+ var res = Instance.SendCommand(String.Format("{0};sender={1};custom={2}", Keyword, CommandInfo.Value.Speaker, Helpers.SanitizeTopicString(String.Join(" ", parameters))));
if (res != "SUCCESS" && !String.IsNullOrWhiteSpace(res))
OutputProc(res);
return ExitCode.Normal;
diff --git a/TGS.Server.Service/ChatCommands/VersionCommand.cs b/TGS.Server/ChatCommands/VersionCommand.cs
similarity index 93%
rename from TGS.Server.Service/ChatCommands/VersionCommand.cs
rename to TGS.Server/ChatCommands/VersionCommand.cs
index afbd926c02..538bcb4e7f 100644
--- a/TGS.Server.Service/ChatCommands/VersionCommand.cs
+++ b/TGS.Server/ChatCommands/VersionCommand.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace TGS.Server.Service.ChatCommands
+namespace TGS.Server.ChatCommands
{
///
/// Retrieve the current service version
diff --git a/TGS.Server.Service/ChatProviders/ChatProvider.cs b/TGS.Server/ChatProviders/ChatProvider.cs
similarity index 98%
rename from TGS.Server.Service/ChatProviders/ChatProvider.cs
rename to TGS.Server/ChatProviders/ChatProvider.cs
index dbcf6d14d7..974d79eaf8 100644
--- a/TGS.Server.Service/ChatProviders/ChatProvider.cs
+++ b/TGS.Server/ChatProviders/ChatProvider.cs
@@ -1,7 +1,7 @@
using System;
using TGS.Interface;
-namespace TGS.Server.Service.ChatProviders
+namespace TGS.Server.ChatProviders
{
///
/// Callback for the chat provider recieving a
diff --git a/TGS.Server.Service/ChatProviders/DiscordChatProvider.cs b/TGS.Server/ChatProviders/DiscordChatProvider.cs
similarity index 98%
rename from TGS.Server.Service/ChatProviders/DiscordChatProvider.cs
rename to TGS.Server/ChatProviders/DiscordChatProvider.cs
index 1b2a936cb5..7809df8af9 100644
--- a/TGS.Server.Service/ChatProviders/DiscordChatProvider.cs
+++ b/TGS.Server/ChatProviders/DiscordChatProvider.cs
@@ -6,7 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using TGS.Interface;
-namespace TGS.Server.Service.ChatProviders
+namespace TGS.Server.ChatProviders
{
///
/// for Discord: https://discordapp.com/
@@ -179,7 +179,6 @@ namespace TGS.Server.Service.ChatProviders
lock (DiscordLock)
{
var tasks = new List();
- var Config = Properties.Settings.Default;
foreach (var I in client.Guilds)
foreach (var J in I.TextChannels)
{
@@ -208,7 +207,6 @@ namespace TGS.Server.Service.ChatProviders
lock (DiscordLock)
{
var tasks = new List();
- var Config = Properties.Settings.Default;
var channel = Convert.ToUInt64(channelname);
if (SeenPrivateChannels.ContainsKey(channel))
SeenPrivateChannels[channel].SendMessageAsync(message).Wait();
diff --git a/TGS.Server.Service/ChatProviders/IRCChatProvider.cs b/TGS.Server/ChatProviders/IRCChatProvider.cs
similarity index 99%
rename from TGS.Server.Service/ChatProviders/IRCChatProvider.cs
rename to TGS.Server/ChatProviders/IRCChatProvider.cs
index 550f3a1aee..9074219cec 100644
--- a/TGS.Server.Service/ChatProviders/IRCChatProvider.cs
+++ b/TGS.Server/ChatProviders/IRCChatProvider.cs
@@ -4,7 +4,7 @@ using System.Threading;
using TGS.Interface;
using Meebey.SmartIrc4net;
-namespace TGS.Server.Service.ChatProviders
+namespace TGS.Server.ChatProviders
{
///
/// for internet relay chat
@@ -48,7 +48,7 @@ namespace TGS.Server.Service.ChatProviders
irc = new IrcFeatures()
{
SupportNonRfc = true,
- CtcpUserInfo = Service.VersionString,
+ CtcpUserInfo = Server.VersionString,
AutoRejoin = true,
AutoRejoinOnKick = true,
AutoRelogin = true,
diff --git a/TGS.Server.Service/DeprecatedInstanceConfig.cs b/TGS.Server/DeprecatedInstanceConfig.cs
similarity index 94%
rename from TGS.Server.Service/DeprecatedInstanceConfig.cs
rename to TGS.Server/DeprecatedInstanceConfig.cs
index c6127601af..3cac746331 100644
--- a/TGS.Server.Service/DeprecatedInstanceConfig.cs
+++ b/TGS.Server/DeprecatedInstanceConfig.cs
@@ -1,7 +1,7 @@
using System;
using System.Configuration;
-namespace TGS.Server.Service
+namespace TGS.Server
{
///
/// Used to migrate old config settings
@@ -19,8 +19,8 @@ namespace TGS.Server.Service
/// An based off the old .NET setting file
public static IInstanceConfig CreateFromNETSettings()
{
- var Config = Properties.Settings.Default;
- var result = new DeprecatedInstanceConfig(Program.NormalizePath(LoadPreviousNetPropertyOrDefault("ServerDirectory", "C:\\tgstation-server-3")));
+ var Config = TGServerService.Properties.Settings.Default;
+ var result = new DeprecatedInstanceConfig(Helpers.NormalizePath(LoadPreviousNetPropertyOrDefault("ServerDirectory", "C:\\tgstation-server-3")));
// using nameof for sanity where possible
result.ProjectName = LoadPreviousNetPropertyOrDefault(nameof(ProjectName), result.ProjectName);
result.Port = LoadPreviousNetPropertyOrDefault("ServerPort", result.Port);
@@ -53,7 +53,7 @@ namespace TGS.Server.Service
//try it the simple way first
try
{
- var result = (T)Properties.Settings.Default.GetPreviousVersion(property);
+ var result = (T)TGServerService.Properties.Settings.Default.GetPreviousVersion(property);
return result == null ? defaultValue : result;
}
catch
@@ -65,7 +65,7 @@ namespace TGS.Server.Service
//Which means we can never fucking delete config settings
//Which is fucking retarded
//This hooks into the settings provider and forces it to load it anyway
- var Config = Properties.Settings.Default;
+ var Config = TGServerService.Properties.Settings.Default;
var Provider = Config.Properties[nameof(Config.SettingsVersion)].Provider; //nameof for sanity
var sp = new SettingsProperty(property)
diff --git a/TGS.Server.Service/EventID.cs b/TGS.Server/EventID.cs
similarity index 98%
rename from TGS.Server.Service/EventID.cs
rename to TGS.Server/EventID.cs
index ef542764dd..0f7267594b 100644
--- a/TGS.Server.Service/EventID.cs
+++ b/TGS.Server/EventID.cs
@@ -1,6 +1,6 @@
using System;
-namespace TGS.Server.Service
+namespace TGS.Server
{
///
/// Various events and their IDs in no particular order. Found in the Windows event log. These key incremented by 100 and are guaranteed to never be reused in the future. In the windows event viewer, these IDs will be offset by the to distinguish events between instances. Each event ID may be information, a warning, or error and will be documented accordingly. Warnings will occur due to user, data, or network errors. Errors will occur due to filesystem errors or hard faults
@@ -76,11 +76,11 @@ namespace TGS.Server.Service
///
DMCompileCancel = 1600,
///
- /// Error: Failed to reattach the watchdog to a running DreamDaemon instance after a update
+ /// Error: Failed to reattach the watchdog to a running DreamDaemon instance after a update
///
DDReattachFail = 1700,
///
- /// Info: Successfully reattached the watchdog to a running DreamDaemon instance after a update
+ /// Info: Successfully reattached the watchdog to a running DreamDaemon instance after a update
///
DDReattachSuccess = 1800,
///
@@ -261,7 +261,7 @@ namespace TGS.Server.Service
///
InstanceInitializationFailure = 6000,
///
- /// Error: When an exception occurs while the is stopping
+ /// Error: When an exception occurs while the is stopping
///
ServiceShutdownFail = 6100,
///
diff --git a/TGS.Server.Service/Program.cs b/TGS.Server/Helpers.cs
similarity index 97%
rename from TGS.Server.Service/Program.cs
rename to TGS.Server/Helpers.cs
index 8d12789234..7cff312bca 100644
--- a/TGS.Server.Service/Program.cs
+++ b/TGS.Server/Helpers.cs
@@ -1,21 +1,15 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.ServiceProcess;
using System.Threading.Tasks;
-namespace TGS.Server.Service
+namespace TGS.Server
{
- static class Program
+ ///
+ /// Generic helpers for the
+ ///
+ static class Helpers
{
- ///
- /// Entry point to the program
- ///
- static void Main() {
- using (var S = new Service())
- ServiceBase.Run(S);
- }
-
///
/// Copy a file from to , but first ensure the destination directory exists
///
diff --git a/TGS.Server/ILogger.cs b/TGS.Server/ILogger.cs
new file mode 100644
index 0000000000..b63246f06a
--- /dev/null
+++ b/TGS.Server/ILogger.cs
@@ -0,0 +1,39 @@
+namespace TGS.Server
+{
+ ///
+ /// Used for writing logs to a provider
+ ///
+ public interface ILogger
+ {
+ ///
+ /// Writes information to the log
+ ///
+ /// The log message
+ /// The of the message
+ /// The 0-99 ID of the log source
+ void WriteInfo(string message, EventID id, byte loggingID);
+
+ ///
+ /// Writes an error to the log
+ ///
+ /// The log message
+ /// The of the message
+ /// The 0-99 ID of the log source
+ void WriteError(string message, EventID id, byte loggingID);
+
+ ///
+ /// Writes a warning to the log
+ ///
+ /// The log message
+ /// The of the message
+ /// The 0-99 ID of the log source
+ void WriteWarning(string message, EventID id, byte loggingID);
+ ///
+ /// Writes an access event to the log
+ ///
+ /// The (un)authenticated Windows user's name
+ /// if authenticated sucessfully, otherwise
+ /// The 0-99 ID of the log source
+ void WriteAccess(string username, bool authSuccess, byte loggingID);
+ }
+}
diff --git a/TGS.Server.Service/InstanceConfig.cs b/TGS.Server/InstanceConfig.cs
similarity index 99%
rename from TGS.Server.Service/InstanceConfig.cs
rename to TGS.Server/InstanceConfig.cs
index d824c418c0..11d2469192 100644
--- a/TGS.Server.Service/InstanceConfig.cs
+++ b/TGS.Server/InstanceConfig.cs
@@ -2,7 +2,7 @@
using System.Web.Script.Serialization;
using TGS.Interface;
-namespace TGS.Server.Service
+namespace TGS.Server
{
///
/// Configuration settings for a
diff --git a/TGS.Server.Service/MessageType.cs b/TGS.Server/MessageType.cs
similarity index 94%
rename from TGS.Server.Service/MessageType.cs
rename to TGS.Server/MessageType.cs
index 803a3fb4a5..72d930bb0e 100644
--- a/TGS.Server.Service/MessageType.cs
+++ b/TGS.Server/MessageType.cs
@@ -1,6 +1,6 @@
using System;
-namespace TGS.Server.Service
+namespace TGS.Server
{
///
/// Type of chat message, these may be OR'd together
diff --git a/TGS.Server.Service/ProcessExtension.cs b/TGS.Server/ProcessExtension.cs
similarity index 98%
rename from TGS.Server.Service/ProcessExtension.cs
rename to TGS.Server/ProcessExtension.cs
index fab7bebdcc..0d24a8351c 100644
--- a/TGS.Server.Service/ProcessExtension.cs
+++ b/TGS.Server/ProcessExtension.cs
@@ -2,7 +2,7 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
-namespace TGS.Server.Service
+namespace TGS.Server
{
///
/// Helpers to ing and a . Lightly massaged code from https://stackoverflow.com/a/13109774. Documentation linked from MSDN on 20/10/2017
diff --git a/TGS.Server/Properties/AssemblyInfo.cs b/TGS.Server/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..5dc00523b0
--- /dev/null
+++ b/TGS.Server/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TGStation Server")]
+[assembly: AssemblyDescription("Server management suite for running BYOND games")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f32eda25-0855-411c-af5e-f0d042917e2d")]
diff --git a/TGS.Server.Service/Properties/Settings.Designer.cs b/TGS.Server/Properties/Settings.Designer.cs
similarity index 98%
rename from TGS.Server.Service/Properties/Settings.Designer.cs
rename to TGS.Server/Properties/Settings.Designer.cs
index 9b807e1637..1bbb0d95f0 100644
--- a/TGS.Server.Service/Properties/Settings.Designer.cs
+++ b/TGS.Server/Properties/Settings.Designer.cs
@@ -8,7 +8,7 @@
//
//------------------------------------------------------------------------------
-namespace TGS.Server.Service.Properties {
+namespace TGServerService.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
diff --git a/TGS.Server.Service/Properties/Settings.settings b/TGS.Server/Properties/Settings.settings
similarity index 91%
rename from TGS.Server.Service/Properties/Settings.settings
rename to TGS.Server/Properties/Settings.settings
index 3770ccac32..d3f9248e61 100644
--- a/TGS.Server.Service/Properties/Settings.settings
+++ b/TGS.Server/Properties/Settings.settings
@@ -1,5 +1,5 @@
-
+
diff --git a/TGS.Server.Service/RepoConfig.cs b/TGS.Server/RepoConfig.cs
similarity index 99%
rename from TGS.Server.Service/RepoConfig.cs
rename to TGS.Server/RepoConfig.cs
index d3b7cf2d5b..91a165171f 100644
--- a/TGS.Server.Service/RepoConfig.cs
+++ b/TGS.Server/RepoConfig.cs
@@ -4,7 +4,7 @@ using System.IO;
using System.Linq;
using System.Web.Script.Serialization;
-namespace TGS.Server.Service
+namespace TGS.Server
{
///
/// Repository specific information for a
diff --git a/TGS.Server.Service/RootAuthorizationManager.cs b/TGS.Server/RootAuthorizationManager.cs
similarity index 83%
rename from TGS.Server.Service/RootAuthorizationManager.cs
rename to TGS.Server/RootAuthorizationManager.cs
index 4c62acb8a7..8d80dc48ed 100644
--- a/TGS.Server.Service/RootAuthorizationManager.cs
+++ b/TGS.Server/RootAuthorizationManager.cs
@@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using System.Security.Principal;
using System.ServiceModel;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
///
/// A used to determine only if the caller is an admin
@@ -33,7 +32,7 @@ namespace TGS.Server.Service
if (LastSeenUser != user)
{
LastSeenUser = user;
- Service.WriteEntry(String.Format("Root access from: {0}", user), EventID.Authentication, authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, Service.LoggingID);
+ Server.Logger.WriteAccess(String.Format("Root access from: {0}", user), authSuccess, Server.LoggingID);
}
return authSuccess;
}
diff --git a/TGS.Server/Server.cs b/TGS.Server/Server.cs
new file mode 100644
index 0000000000..71278e7ec8
--- /dev/null
+++ b/TGS.Server/Server.cs
@@ -0,0 +1,704 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Security.Principal;
+using System.ServiceModel;
+using TGS.Interface;
+using TGS.Interface.Components;
+
+namespace TGS.Server
+{
+ ///
+ /// The windows service the application runs as
+ ///
+ [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
+ public sealed class Server : ITGSService, ITGConnectivity, ITGLanding, ITGInstanceManager, IDisposable
+ {
+ ///
+ /// The logging ID used for events
+ ///
+ public const byte LoggingID = 0;
+
+ ///
+ /// The service version based on the
+ ///
+ public static readonly string VersionString = "/tg/station 13 Server Service v" + FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;
+
+ ///
+ /// Singleton
+ ///
+ public static ILogger Logger { get; private set; }
+
+ ///
+ /// Cancels WCF's user impersonation to allow clean access to writing log files
+ ///
+ public static void CancelImpersonation()
+ {
+ WindowsIdentity.Impersonate(IntPtr.Zero);
+ }
+
+ ///
+ /// Checks an for illegal characters
+ ///
+ /// The name to check
+ /// if contains no illegal characters, error message otherwise
+ static string CheckInstanceName(string instanceName)
+ {
+ char[] bannedCharacters = { ';', '&', '=', '%' };
+ foreach (var I in bannedCharacters)
+ if (instanceName.Contains(I.ToString()))
+ return "Instance names may not contain the following characters: ';', '&', '=', or '%'";
+ return null;
+ }
+
+ ///
+ /// The WCF host that contains connects to
+ ///
+ ServiceHost serviceHost;
+ ///
+ /// Map of to the respective hosting the
+ ///
+ IDictionary hosts;
+ ///
+ /// List of s in use
+ ///
+ IList UsedLoggingIDs = new List();
+
+ ///
+ /// Construct a
+ ///
+ /// Command line arguments for the
+ /// The to use
+ public Server(string[] args, ILogger logger)
+ {
+ Environment.CurrentDirectory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Assembly.GetExecutingAssembly().GetName().Name)).FullName; //MOVE THIS POINTER BECAUSE ONE TIME I ALMOST ACCIDENTALLY NUKED MYSELF BY REFACTORING! http://imgur.com/zvGEpJD.png
+
+ SetupConfig();
+
+ ChangePortFromCommandLine(args);
+
+ SetupService();
+
+ SetupInstances();
+
+ OnlineAllHosts();
+ }
+
+ ///
+ /// Migrates the .NET config from to + 1
+ ///
+ /// The version to migrate from
+ void MigrateSettings(int oldVersion)
+ {
+ var Config = TGServerService.Properties.Settings.Default;
+ switch (oldVersion)
+ {
+ case 6: //switch to per-instance configs
+ var IC = DeprecatedInstanceConfig.CreateFromNETSettings();
+ IC.Save();
+ Config.InstancePaths.Add(IC.Directory);
+ break;
+ }
+ }
+
+ ///
+ /// Enumerates configured s. Detaches those that fail to load
+ ///
+ /// Each configured
+ IEnumerable GetInstanceConfigs()
+ {
+ var pathsToRemove = new List();
+ lock (this)
+ {
+ var IPS = TGServerService.Properties.Settings.Default.InstancePaths;
+ foreach (var I in IPS)
+ {
+ IInstanceConfig ic;
+ try
+ {
+ ic = InstanceConfig.Load(I);
+ }
+ catch (Exception e)
+ {
+ Logger.WriteError(String.Format("Unable load instance config at path {0}. Error: {1} Detaching...", I, e.ToString()), EventID.InstanceInitializationFailure, LoggingID);
+ pathsToRemove.Add(I);
+ continue;
+ }
+ yield return ic;
+ }
+ foreach (var I in pathsToRemove)
+ IPS.Remove(I);
+ }
+ }
+
+ ///
+ /// Overrides and saves the configured if requested by command line parameters
+ ///
+ /// The command line parameters for the
+ void ChangePortFromCommandLine(string[] args)
+ {
+ var Config = TGServerService.Properties.Settings.Default;
+
+ for (var I = 0; I < args.Length - 1; ++I)
+ if (args[I].ToLower() == "-port")
+ {
+ try
+ {
+ var res = Convert.ToUInt16(args[I + 1]);
+ if (res == 0)
+ throw new Exception("Cannot bind to port 0");
+ Config.RemoteAccessPort = res;
+ }
+ catch (Exception e)
+ {
+ throw new Exception("Invalid argument for \"-port\"", e);
+ }
+ Config.Save();
+ break;
+ }
+ }
+
+ ///
+ /// Writes some changes to the that always need to be done.
+ ///
+ void PrePrepConfig()
+ {
+ var Config = TGServerService.Properties.Settings.Default;
+
+ if (Config.InstancePaths == null)
+ Config.InstancePaths = new StringCollection();
+ }
+
+ ///
+ /// Upgrades up the service configuration
+ ///
+ void SetupConfig()
+ {
+ var Config = TGServerService.Properties.Settings.Default;
+ if (Config.UpgradeRequired)
+ {
+ var newVersion = Config.SettingsVersion;
+ Config.Upgrade();
+
+ PrePrepConfig();
+
+ for (var oldVersion = Config.SettingsVersion; oldVersion < newVersion; ++oldVersion)
+ MigrateSettings(oldVersion);
+
+ Config.SettingsVersion = newVersion;
+
+ Config.UpgradeRequired = false;
+ Config.Save();
+ }
+ else
+ PrePrepConfig();
+ }
+
+ ///
+ /// Creates the for
+ ///
+ void SetupService()
+ {
+ serviceHost = CreateHost(this, ServerInterface.MasterInterfaceName);
+ foreach (var I in ServerInterface.ValidServiceInterfaces)
+ AddEndpoint(serviceHost, I);
+ serviceHost.Authorization.ServiceAuthorizationManager = new RootAuthorizationManager(); //only admins can diddle us
+ }
+
+ ///
+ /// Opens all created s
+ ///
+ void OnlineAllHosts()
+ {
+ serviceHost.Open();
+ foreach (var I in hosts)
+ I.Value.Open();
+ }
+
+ ///
+ /// Creates a for using the default pipe, CloseTimeout for the , and the configured
+ ///
+ /// The
+ /// The URL to access components on the
+ /// The created
+ static ServiceHost CreateHost(object singleton, string endpointPostfix)
+ {
+ return new ServiceHost(singleton, new Uri[] { new Uri(String.Format("net.pipe://localhost/{0}", endpointPostfix)), new Uri(String.Format("https://localhost:{0}/{1}", TGServerService.Properties.Settings.Default.RemoteAccessPort, endpointPostfix)) })
+ {
+ CloseTimeout = new TimeSpan(0, 0, 5)
+ };
+ }
+
+ ///
+ /// Creates s for all s as listed in , detaches bad ones
+ ///
+ void SetupInstances()
+ {
+ hosts = new Dictionary();
+ var pathsToRemove = new List();
+ var seenNames = new List();
+ foreach (var I in GetInstanceConfigs())
+ {
+ if (seenNames.Contains(I.Name))
+ {
+ Logger.WriteError(String.Format("Instance at {0} has a duplicate name! Detaching...", I.Directory), EventID.InstanceInitializationFailure, LoggingID);
+ pathsToRemove.Add(I.Directory);
+ }
+ if (I.Enabled && SetupInstance(I) == null)
+ pathsToRemove.Add(I.Directory);
+ else
+ seenNames.Add(I.Name);
+ }
+ foreach (var I in pathsToRemove)
+ TGServerService.Properties.Settings.Default.InstancePaths.Remove(I);
+ }
+
+ ///
+ /// Unlocks a acquired with
+ ///
+ /// The to unlock
+ void UnlockLoggingID(byte ID)
+ {
+ lock (UsedLoggingIDs)
+ {
+ UsedLoggingIDs.Remove(ID);
+ }
+ }
+
+ ///
+ /// Gets and locks a
+ ///
+ /// A logging ID for the must be released using
+ byte LockLoggingID()
+ {
+ lock (UsedLoggingIDs)
+ {
+ for (byte I = 1; I < 100; ++I)
+ if (!UsedLoggingIDs.Contains(I))
+ {
+ UsedLoggingIDs.Add(I);
+ return I;
+ }
+ }
+ throw new Exception("All logging IDs in use!");
+ }
+
+ ///
+ /// Creates and starts a for a at
+ ///
+ /// The for the
+ /// The inactive on success, on failure
+ ServiceHost SetupInstance(IInstanceConfig config)
+ {
+ ServerInstance instance;
+ string instanceName;
+ try
+ {
+ if (hosts.ContainsKey(config.Directory))
+ {
+ var datInstance = ((ServerInstance)hosts[config.Directory].SingletonInstance);
+ Logger.WriteError(String.Format("Unable to start instance at path {0}. Has the same name as instance at path {1}. Detaching...", config.Directory, datInstance.ServerDirectory()), EventID.InstanceInitializationFailure, LoggingID);
+ return null;
+ }
+ if (!config.Enabled)
+ return null;
+ var ID = LockLoggingID();
+ Logger.WriteInfo(String.Format("Instance {0} ({1}) assigned logging ID {2}", config.Name, config.Directory, ID), EventID.InstanceIDAssigned, ID);
+ instanceName = config.Name;
+ instance = new ServerInstance(config, ID);
+ }
+ catch (Exception e)
+ {
+ Logger.WriteError(String.Format("Unable to start instance at path {0}. Detaching... Error: {1}", config.Directory, e.ToString()), EventID.InstanceInitializationFailure, LoggingID);
+ return null;
+ }
+
+ var host = CreateHost(instance, String.Format("{0}/{1}", ServerInterface.InstanceInterfaceName, instanceName));
+ hosts.Add(instanceName, host);
+
+ foreach (var J in ServerInterface.ValidInstanceInterfaces)
+ AddEndpoint(host, J);
+
+ host.Authorization.ServiceAuthorizationManager = instance;
+ return host;
+ }
+
+ ///
+ /// Adds a WCF endpoint for a component
+ ///
+ /// The service host to add the component to
+ /// The type of the component
+ 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);
+ var httpsBinding = new WSHttpBinding()
+ {
+ SendTimeout = new TimeSpan(0, 0, 40),
+ MaxReceivedMessageSize = ServerInterface.TransferLimitRemote
+ };
+ var requireAuth = typetype.Name != typeof(ITGConnectivity).Name;
+ httpsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
+ httpsBinding.Security.Mode = requireAuth ? SecurityMode.TransportWithMessageCredential : SecurityMode.Transport; //do not require auth for a connectivity check
+ httpsBinding.Security.Message.ClientCredentialType = requireAuth ? MessageCredentialType.UserName : MessageCredentialType.None;
+ host.AddServiceEndpoint(typetype, httpsBinding, bindingName);
+ }
+
+ ///
+ /// Shuts down all active s and calls on it's
+ ///
+ void OnStop()
+ {
+ lock (this)
+ {
+ try
+ {
+ foreach (var I in hosts)
+ {
+ var host = I.Value;
+ var instance = (ServerInstance)host.SingletonInstance;
+ host.Close();
+ instance.Dispose();
+ UnlockLoggingID(instance.LoggingID);
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.WriteError(e.ToString(), EventID.ServiceShutdownFail, LoggingID);
+ }
+ serviceHost.Close();
+ }
+ TGServerService.Properties.Settings.Default.Save();
+ }
+
+ ///
+ public void VerifyConnection() { }
+
+ ///
+ public void PrepareForUpdate()
+ {
+ foreach (var I in hosts)
+ ((ServerInstance)I.Value.SingletonInstance).Reattach(false);
+ }
+
+ ///
+ public ushort RemoteAccessPort()
+ {
+ return TGServerService.Properties.Settings.Default.RemoteAccessPort;
+ }
+
+ ///
+ public string SetRemoteAccessPort(ushort port)
+ {
+ if (port == 0)
+ return "Cannot bind to port 0";
+ TGServerService.Properties.Settings.Default.RemoteAccessPort = port;
+ return null;
+ }
+
+ ///
+ public string Version()
+ {
+ return VersionString;
+ }
+
+ ///
+ public bool SetPythonPath(string path)
+ {
+ if (!Directory.Exists(path))
+ return false;
+ TGServerService.Properties.Settings.Default.PythonPath = Path.GetFullPath(path);
+ return true;
+ }
+
+ ///
+ public string PythonPath()
+ {
+ return TGServerService.Properties.Settings.Default.PythonPath;
+ }
+
+ ///
+ public IList ListInstances()
+ {
+ var result = new List();
+ lock (this)
+ foreach (var ic in GetInstanceConfigs())
+ result.Add(new InstanceMetadata
+ {
+ Name = ic.Name,
+ Path = ic.Directory,
+ Enabled = ic.Enabled,
+ LoggingID = (byte)(ic.Enabled ? ((ServerInstance)hosts[ic.Name].SingletonInstance).LoggingID : 0)
+ });
+ return result;
+ }
+
+ ///
+ public string CreateInstance(string Name, string path)
+ {
+ path = Helpers.NormalizePath(path);
+ var res = CheckInstanceName(Name);
+ if (res != null)
+ return res;
+ if (File.Exists(path) || Directory.Exists(path))
+ return "Cannot create instance at pre-existing path!";
+ var Config = TGServerService.Properties.Settings.Default;
+ lock (this)
+ {
+ if (Config.InstancePaths.Contains(path))
+ return String.Format("Instance at {0} already exists!", path);
+ foreach (var oic in GetInstanceConfigs())
+ if (Name == oic.Name)
+ return String.Format("Instance named {0} already exists!", oic.Name);
+ IInstanceConfig ic;
+ try
+ {
+ ic = new InstanceConfig(path)
+ {
+ Name = Name
+ };
+ Directory.CreateDirectory(path);
+ ic.Save();
+ TGServerService.Properties.Settings.Default.InstancePaths.Add(path);
+ }
+ catch (Exception e)
+ {
+ return e.ToString();
+ }
+ return SetupOneInstance(ic);
+ }
+ }
+
+ ///
+ /// Starts and onlines an instance located at
+ ///
+ /// The for the
+ /// on success, error message on failure
+ string SetupOneInstance(IInstanceConfig config)
+ {
+ if (!config.Enabled)
+ return null;
+ try
+ {
+ var host = SetupInstance(config);
+ if (host != null)
+ host.Open();
+ else
+ lock (this)
+ TGServerService.Properties.Settings.Default.InstancePaths.Remove(config.Directory);
+ return null;
+ }
+ catch (Exception e)
+ {
+ return "Instance set up but an error occurred while starting it: " + e.ToString();
+ }
+ }
+
+ ///
+ public string ImportInstance(string path)
+ {
+ path = Helpers.NormalizePath(path);
+ var Config = TGServerService.Properties.Settings.Default;
+ lock (this)
+ {
+ if (Config.InstancePaths.Contains(path))
+ return String.Format("Instance at {0} already exists!", path);
+ if(!Directory.Exists(path))
+ return String.Format("There is no instance located at {0}!", path);
+ IInstanceConfig ic;
+ try
+ {
+ ic = InstanceConfig.Load(path);
+ foreach(var oic in GetInstanceConfigs())
+ if(ic.Name == oic.Name)
+ return String.Format("Instance named {0} already exists!", oic.Name);
+ ic.Save();
+ TGServerService.Properties.Settings.Default.InstancePaths.Add(path);
+ }
+ catch (Exception e)
+ {
+ return e.ToString();
+ }
+ return SetupOneInstance(ic);
+ }
+ }
+
+ ///
+ public bool InstanceEnabled(string Name)
+ {
+ lock(this)
+ {
+ return hosts.ContainsKey(Name);
+ }
+ }
+
+ ///
+ public string SetInstanceEnabled(string Name, bool enabled)
+ {
+ return SetInstanceEnabledImpl(Name, enabled, out string path);
+ }
+
+
+ ///
+ /// Sets a 's enabled status
+ ///
+ /// The whom's status should be changed
+ /// to enable the , to disable it
+ /// The path to the modified
+ /// on success, error message on failure
+ string SetInstanceEnabledImpl(string Name, bool enabled, out string path)
+ {
+ path = null;
+ lock (this)
+ {
+ var hostIsOnline = hosts.ContainsKey(Name);
+ if (enabled)
+ {
+ if (hostIsOnline)
+ return null;
+ foreach (var ic in GetInstanceConfigs())
+ if (ic.Name == Name)
+ {
+ path = ic.Directory;
+ ic.Enabled = true;
+ ic.Save();
+ return SetupOneInstance(ic);
+ }
+ return String.Format("Instance {0} does not exist!", Name);
+ }
+ else
+ {
+ if (!hostIsOnline)
+ return null;
+ var host = hosts[Name];
+ hosts.Remove(Name);
+ var inst = (ServerInstance)host.SingletonInstance;
+ host.Close();
+ path = inst.ServerDirectory();
+ inst.Offline();
+ inst.Dispose();
+ UnlockLoggingID(inst.LoggingID);
+ return null;
+ }
+ }
+ }
+
+ ///
+ public string RenameInstance(string name, string new_name)
+ {
+ if (name == new_name)
+ return null;
+ var res = CheckInstanceName(new_name);
+ if (res != null)
+ return res;
+ lock (this)
+ {
+ //we have to check em all anyway
+ IInstanceConfig the_droid_were_looking_for = null;
+ foreach (var ic in GetInstanceConfigs())
+ if (ic.Name == name)
+ {
+ the_droid_were_looking_for = ic;
+ break;
+ }
+ else if (ic.Name == new_name)
+ return String.Format("There is already another instance named {0}!", new_name);
+ if (the_droid_were_looking_for == null)
+ return String.Format("There is no instance named {0}!", name);
+ var ie = InstanceEnabled(name);
+ if(ie)
+ SetInstanceEnabled(name, false);
+ the_droid_were_looking_for.Name = new_name;
+ string result = "";
+ try
+ {
+ the_droid_were_looking_for.Save();
+ result = null;
+ }
+ catch(Exception e)
+ {
+ result = "Could not save instance config! Error: " + e.ToString();
+ }
+ finally
+ {
+ if (ie)
+ {
+ var resRestore = SetInstanceEnabled(new_name, true);
+ if (resRestore != null)
+ result = (result + " " + resRestore).Trim();
+ }
+ }
+ return result;
+ }
+ }
+
+ ///
+ public string DetachInstance(string name)
+ {
+ lock (this)
+ {
+ var res = SetInstanceEnabledImpl(name, false, out string path);
+ if (res != null)
+ return res;
+ if (path == null) //gotta find it ourselves
+ foreach (var ic in GetInstanceConfigs())
+ if (ic.Name == name)
+ {
+ path = ic.Directory;
+ break;
+ }
+ if (path == null)
+ return String.Format("No instance named {0} exists!", name);
+ TGServerService.Properties.Settings.Default.InstancePaths.Remove(path);
+ return null;
+ }
+ }
+
+ #region IDisposable Support
+ ///
+ /// To detect redundant calls
+ ///
+ private bool disposedValue = false;
+
+ ///
+ /// Implements the pattern. Calls
+ ///
+ /// if was called manually, if it was from the finalizer
+ void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ OnStop();
+ }
+
+ // 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.
+ // ~Server() {
+ // // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ // Dispose(false);
+ // }
+
+ ///
+ /// Implements the pattern
+ ///
+ 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
+ }
+}
diff --git a/TGS.Server.Service/ServerInstance/Administration.cs b/TGS.Server/ServerInstance/Administration.cs
similarity index 98%
rename from TGS.Server.Service/ServerInstance/Administration.cs
rename to TGS.Server/ServerInstance/Administration.cs
index 03b7caf1c3..eb8a4b3c2e 100644
--- a/TGS.Server.Service/ServerInstance/Administration.cs
+++ b/TGS.Server/ServerInstance/Administration.cs
@@ -6,7 +6,7 @@ using System.Threading;
using TGS.Interface;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
//note this only works with MACHINE LOCAL groups and admins for now
//if someone wants AD shit, code it yourself
@@ -26,7 +26,7 @@ namespace TGS.Server.Service
string LastSeenUser;
///
- /// The of the account the is running as
+ /// The of the account the is running as
///
readonly SecurityIdentifier ServiceSID = WindowsIdentity.GetCurrent().User;
diff --git a/TGS.Server.Service/ServerInstance/Byond.cs b/TGS.Server/ServerInstance/Byond.cs
similarity index 98%
rename from TGS.Server.Service/ServerInstance/Byond.cs
rename to TGS.Server/ServerInstance/Byond.cs
index bd00bfb10f..fa725720ad 100644
--- a/TGS.Server.Service/ServerInstance/Byond.cs
+++ b/TGS.Server/ServerInstance/Byond.cs
@@ -8,7 +8,7 @@ using System.Threading;
using TGS.Interface;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
sealed partial class ServerInstance : ITGByond
{
@@ -88,7 +88,7 @@ namespace TGS.Server.Service
//linger not
if (File.Exists(rrdp))
File.Delete(rrdp);
- Program.DeleteDirectory(RelativePath(StagingDirectory));
+ Helpers.DeleteDirectory(RelativePath(StagingDirectory));
}
///
@@ -326,9 +326,9 @@ namespace TGS.Server.Service
try
{
var rbd = RelativePath(ByondDirectory);
- Program.DeleteDirectory(rbd);
+ Helpers.DeleteDirectory(rbd);
Directory.Move(RelativePath(StagingDirectoryInner), rbd);
- Program.DeleteDirectory(RelativePath(StagingDirectory));
+ Helpers.DeleteDirectory(RelativePath(StagingDirectory));
lastError = null;
SendMessage("BYOND: Update completed!", MessageType.DeveloperInfo);
WriteInfo(String.Format("BYOND update {0} completed!", GetVersion(ByondVersion.Installed)), EventID.BYONDUpdateComplete);
diff --git a/TGS.Server.Service/ServerInstance/Chat.cs b/TGS.Server/ServerInstance/Chat.cs
similarity index 96%
rename from TGS.Server.Service/ServerInstance/Chat.cs
rename to TGS.Server/ServerInstance/Chat.cs
index 8c6bb66464..396c15a5f2 100644
--- a/TGS.Server.Service/ServerInstance/Chat.cs
+++ b/TGS.Server/ServerInstance/Chat.cs
@@ -2,12 +2,12 @@
using System.Linq;
using System.Collections.Generic;
using System.Web.Script.Serialization;
-using TGS.Server.Service.ChatCommands;
-using TGS.Server.Service.ChatProviders;
+using TGS.Server.ChatCommands;
+using TGS.Server.ChatProviders;
using TGS.Interface;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
sealed partial class ServerInstance : ITGChat
{
@@ -114,7 +114,7 @@ namespace TGS.Server.Service
var rawdata = new JavaScriptSerializer().Serialize(infosList);
- Config.ChatProviderData = Helpers.EncryptData(rawdata, out string entrp);
+ Config.ChatProviderData = Interface.Helpers.EncryptData(rawdata, out string entrp);
Config.ChatProviderEntropy = entrp;
}
@@ -142,7 +142,7 @@ namespace TGS.Server.Service
string plaintext;
try
{
- plaintext = Helpers.DecryptData(rawdata, Config.ChatProviderEntropy);
+ plaintext = Interface.Helpers.DecryptData(rawdata, Config.ChatProviderEntropy);
var lists = new JavaScriptSerializer().Deserialize>>(plaintext);
var output = new List(lists.Count);
diff --git a/TGS.Server.Service/ServerInstance/Compiler.cs b/TGS.Server/ServerInstance/Compiler.cs
similarity index 98%
rename from TGS.Server.Service/ServerInstance/Compiler.cs
rename to TGS.Server/ServerInstance/Compiler.cs
index dd5a2867ea..d503e921ff 100644
--- a/TGS.Server.Service/ServerInstance/Compiler.cs
+++ b/TGS.Server/ServerInstance/Compiler.cs
@@ -9,7 +9,7 @@ using System.Threading;
using TGS.Interface;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
sealed partial class ServerInstance : ITGCompiler
{
@@ -178,7 +178,7 @@ namespace TGS.Server.Service
{
SendMessage("DM: Setting up symlinks...", MessageType.DeveloperInfo);
CleanGameFolder();
- Program.DeleteDirectory(RelativePath(GameDir));
+ Helpers.DeleteDirectory(RelativePath(GameDir));
Directory.CreateDirectory(RelativePath(GameDirA));
Directory.CreateDirectory(RelativePath(GameDirB));
@@ -350,7 +350,7 @@ namespace TGS.Server.Service
var deleteExcludeList = new List { BridgeDLLName };
deleteExcludeList.AddRange(Config.StaticDirectoryPaths);
deleteExcludeList.AddRange(Config.DLLPaths);
- Program.DeleteDirectory(resurrectee, true, deleteExcludeList);
+ Helpers.DeleteDirectory(resurrectee, true, deleteExcludeList);
Directory.CreateDirectory(resurrectee + "/.git/logs");
@@ -372,11 +372,11 @@ namespace TGS.Server.Service
CreateSymlink(Path.Combine(resurrectee, BridgeDLLName), RelativePath(BridgeDLLName));
deleteExcludeList.Add(".git");
- Program.CopyDirectory(RelativePath(RepoPath), resurrectee, deleteExcludeList);
+ Helpers.CopyDirectory(RelativePath(RepoPath), resurrectee, deleteExcludeList);
CurrentSha = GetHead(false, out string error);
//just the tip
const string GitLogsDir = "/.git/logs";
- Program.CopyDirectory(RelativePath(RepoPath + GitLogsDir), resurrectee + GitLogsDir);
+ Helpers.CopyDirectory(RelativePath(RepoPath + GitLogsDir), resurrectee + GitLogsDir);
try
{
File.Copy(RelativePath(PRJobFile), Path.Combine(resurrectee, PRJobFile));
diff --git a/TGS.Server.Service/ServerInstance/Config.cs b/TGS.Server/ServerInstance/Config.cs
similarity index 95%
rename from TGS.Server.Service/ServerInstance/Config.cs
rename to TGS.Server/ServerInstance/Config.cs
index af81f094cc..41cad7cfe0 100644
--- a/TGS.Server.Service/ServerInstance/Config.cs
+++ b/TGS.Server/ServerInstance/Config.cs
@@ -4,7 +4,7 @@ using System.IO;
using System.ServiceModel;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
//knobs and such
sealed partial class ServerInstance : ITGConfig
@@ -75,7 +75,7 @@ namespace TGS.Server.Service
}
var output = File.ReadAllText(path);
- Service.CancelImpersonation();
+ Server.CancelImpersonation();
WriteInfo("Read of " + path, EventID.StaticRead);
error = null;
unauthorized = false;
@@ -92,7 +92,7 @@ namespace TGS.Server.Service
catch (Exception e)
{
error = e.ToString();
- Service.CancelImpersonation();
+ Server.CancelImpersonation();
WriteWarning(String.Format("Read of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
unauthorized = false;
return null;
@@ -131,7 +131,7 @@ namespace TGS.Server.Service
Directory.CreateDirectory(destdir);
File.WriteAllText(path, data);
- Service.CancelImpersonation();
+ Server.CancelImpersonation();
WriteInfo("Write to " + path, EventID.StaticWrite);
unauthorized = false;
return null;
@@ -146,7 +146,7 @@ namespace TGS.Server.Service
catch (Exception e)
{
unauthorized = false;
- Service.CancelImpersonation();
+ Server.CancelImpersonation();
WriteWarning(String.Format("Write of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
return e.ToString();
}
@@ -184,8 +184,8 @@ namespace TGS.Server.Service
if (fi.Exists)
File.Delete(path);
else if (Directory.Exists(path))
- Program.DeleteDirectory(path);
- Service.CancelImpersonation();
+ Helpers.DeleteDirectory(path);
+ Server.CancelImpersonation();
WriteInfo("Delete of " + path, EventID.StaticDelete);
unauthorized = false;
return null;
@@ -200,7 +200,7 @@ namespace TGS.Server.Service
catch (Exception e)
{
unauthorized = false;
- Service.CancelImpersonation();
+ Server.CancelImpersonation();
WriteWarning(String.Format("Delete of {0} failed! Error: {1}", path, e.ToString()), EventID.StaticRead);
return e.ToString();
}
diff --git a/TGS.Server.Service/ServerInstance/DreamDaemon.cs b/TGS.Server/ServerInstance/DreamDaemon.cs
similarity index 99%
rename from TGS.Server.Service/ServerInstance/DreamDaemon.cs
rename to TGS.Server/ServerInstance/DreamDaemon.cs
index 1682f4b7a5..02290aa7e4 100644
--- a/TGS.Server.Service/ServerInstance/DreamDaemon.cs
+++ b/TGS.Server/ServerInstance/DreamDaemon.cs
@@ -8,7 +8,7 @@ using System.Timers;
using TGS.Interface;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
//manages the dd window.
//It's not possible to actually click it while starting it in CL mode, so in order to change visibility, security, etc. It restarts the process when the world reboots
@@ -721,7 +721,7 @@ namespace TGS.Server.Service
///
public string WorldAnnounce(string message)
{
- var res = SendCommand(SCWorldAnnounce + ";message=" + Program.SanitizeTopicString(message));
+ var res = SendCommand(SCWorldAnnounce + ";message=" + Helpers.SanitizeTopicString(message));
if (res == "SUCCESS")
return null;
return res;
diff --git a/TGS.Server.Service/ServerInstance/Interop.cs b/TGS.Server/ServerInstance/Interop.cs
similarity index 99%
rename from TGS.Server.Service/ServerInstance/Interop.cs
rename to TGS.Server/ServerInstance/Interop.cs
index 621b0502cc..96d3f5a5d3 100644
--- a/TGS.Server.Service/ServerInstance/Interop.cs
+++ b/TGS.Server/ServerInstance/Interop.cs
@@ -6,11 +6,11 @@ using System.Text;
using System.Threading;
using System.Web.Script.Serialization;
using System.Web.Security;
-using TGS.Server.Service.ChatCommands;
+using TGS.Server.ChatCommands;
using TGS.Interface;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
//handles talking between the world and us
sealed partial class ServerInstance : ITGInterop
diff --git a/TGS.Server.Service/ServerInstance/PreactionHandler.cs b/TGS.Server/ServerInstance/PreactionHandler.cs
similarity index 99%
rename from TGS.Server.Service/ServerInstance/PreactionHandler.cs
rename to TGS.Server/ServerInstance/PreactionHandler.cs
index f3991ef8f6..0026c4495e 100644
--- a/TGS.Server.Service/ServerInstance/PreactionHandler.cs
+++ b/TGS.Server/ServerInstance/PreactionHandler.cs
@@ -2,7 +2,7 @@
using System.Diagnostics;
using System.IO;
-namespace TGS.Server.Service
+namespace TGS.Server
{
// Some useful functions for triggering pre action events
sealed partial class ServerInstance
diff --git a/TGS.Server.Service/ServerInstance/Repository.cs b/TGS.Server/ServerInstance/Repository.cs
similarity index 99%
rename from TGS.Server.Service/ServerInstance/Repository.cs
rename to TGS.Server/ServerInstance/Repository.cs
index 4ff01a7cb9..70b7bd89a0 100644
--- a/TGS.Server.Service/ServerInstance/Repository.cs
+++ b/TGS.Server/ServerInstance/Repository.cs
@@ -10,7 +10,7 @@ using System.Web.Script.Serialization;
using TGS.Interface;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
sealed partial class ServerInstance : ITGRepository, IDisposable
{
@@ -231,7 +231,7 @@ namespace TGS.Server.Service
try
{
DisposeRepo();
- Program.DeleteDirectory(RelativePath(RepoPath));
+ Helpers.DeleteDirectory(RelativePath(RepoPath));
DeletePRList();
lock (configLock)
{
@@ -311,9 +311,9 @@ namespace TGS.Server.Service
newFullPath = Path.Combine(path, tempDirName);
}
- Program.CopyDirectory(rsd, newFullPath);
+ Helpers.CopyDirectory(rsd, newFullPath);
}
- Program.DeleteDirectory(rsd);
+ Helpers.DeleteDirectory(rsd);
}
///
@@ -352,7 +352,7 @@ namespace TGS.Server.Service
var source = Path.Combine(RelativePath(RepoPath), I);
var dest = Path.Combine(RelativePath(StaticDirs), I);
if (Directory.Exists(source))
- Program.CopyDirectory(source, dest);
+ Helpers.CopyDirectory(source, dest);
else
Directory.CreateDirectory(dest);
}
@@ -372,7 +372,7 @@ namespace TGS.Server.Service
continue;
}
var dest = Path.Combine(RelativePath(StaticDirs), I);
- Program.CopyFileForceDirectories(source, dest, false);
+ Helpers.CopyFileForceDirectories(source, dest, false);
}
catch
{
@@ -712,7 +712,7 @@ namespace TGS.Server.Service
//kill off the modules/ folder in .git and try again
try
{
- Program.DeleteDirectory(String.Format("{0}/.git/modules/{1}", RepoPath, I.Path));
+ Helpers.DeleteDirectory(String.Format("{0}/.git/modules/{1}", RepoPath, I.Path));
}
catch
{
@@ -1271,7 +1271,7 @@ namespace TGS.Server.Service
return null;
}
- var Config = Properties.Settings.Default;
+ var Config = TGServerService.Properties.Settings.Default;
var PythonFile = Path.Combine(Config.PythonPath, "python.exe");
if (!File.Exists(PythonFile))
diff --git a/TGS.Server.Service/ServerInstance/ServerInstance.cs b/TGS.Server/ServerInstance/ServerInstance.cs
similarity index 91%
rename from TGS.Server.Service/ServerInstance/ServerInstance.cs
rename to TGS.Server/ServerInstance/ServerInstance.cs
index 64ef3506ca..19eed58dc7 100644
--- a/TGS.Server.Service/ServerInstance/ServerInstance.cs
+++ b/TGS.Server/ServerInstance/ServerInstance.cs
@@ -4,7 +4,7 @@ using System.IO;
using System.ServiceModel;
using TGS.Interface.Components;
-namespace TGS.Server.Service
+namespace TGS.Server
{
//I know the fact that this is one massive partial class is gonna trigger everyone
//There really was no other succinct way to do it (<= He's lying through his teeth, don't listen to him)
@@ -62,7 +62,7 @@ namespace TGS.Server.Service
/// The of the message
void WriteInfo(string message, EventID id)
{
- Service.WriteEntry(message, id, EventLogEntryType.Information, LoggingID);
+ Server.Logger.WriteInfo(message, id, LoggingID);
}
///
@@ -72,7 +72,7 @@ namespace TGS.Server.Service
/// The of the message
void WriteError(string message, EventID id)
{
- Service.WriteEntry(message, id, EventLogEntryType.Error, LoggingID);
+ Server.Logger.WriteError(message, id, LoggingID);
}
///
@@ -82,7 +82,7 @@ namespace TGS.Server.Service
/// The of the message
void WriteWarning(string message, EventID id)
{
- Service.WriteEntry(message, id, EventLogEntryType.Warning, LoggingID);
+ Server.Logger.WriteWarning(message, id, LoggingID);
}
///
@@ -92,7 +92,7 @@ namespace TGS.Server.Service
/// if authenticated sucessfully, otherwise
void WriteAccess(string username, bool authSuccess)
{
- Service.WriteEntry(String.Format("Access from: {0}", username), EventID.Authentication, authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, LoggingID);
+ Server.Logger.WriteAccess(String.Format("Access from: {0}", username), authSuccess, LoggingID);
}
///
@@ -107,7 +107,7 @@ namespace TGS.Server.Service
///
public string Version()
{
- return Service.VersionString;
+ return Server.VersionString;
}
///
diff --git a/TGS.Server/TGS.Server.csproj b/TGS.Server/TGS.Server.csproj
new file mode 100644
index 0000000000..8841b1a5fa
--- /dev/null
+++ b/TGS.Server/TGS.Server.csproj
@@ -0,0 +1,153 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ {F32EDA25-0855-411C-AF5E-F0D042917E2D}
+ Library
+ TGS.Server
+ TGS.Server
+ v4.5.2
+ 512
+ true
+
+
+
+
+
+ tgs.ico
+
+
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ full
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\Release\
+ TRACE
+ bin\x86\Release\TGS.Server.xml
+ true
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ false
+
+
+
+
+
+
+ ..\packages\Discord.Net.Core.1.0.2\lib\net45\Discord.Net.Core.dll
+
+
+ ..\packages\Discord.Net.Rest.1.0.2\lib\net45\Discord.Net.Rest.dll
+
+
+ ..\packages\Discord.Net.WebSocket.1.0.2\lib\net45\Discord.Net.WebSocket.dll
+
+
+ ..\packages\LibGit2Sharp-SSH.1.0.22\lib\net40\LibGit2Sharp.dll
+
+
+ ..\packages\SmartIrc4net.1.1\lib\Meebey.SmartIrc4net.dll
+
+
+ ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll
+
+
+
+ ..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+
+
+
+ ..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+ {ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}
+ TGS.Interface
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
\ No newline at end of file
diff --git a/TGS.Server.Service/packages.config b/TGS.Server/packages.config
similarity index 100%
rename from TGS.Server.Service/packages.config
rename to TGS.Server/packages.config
diff --git a/TGS.Server.Service/tgs.ico b/TGS.Server/tgs.ico
similarity index 100%
rename from TGS.Server.Service/tgs.ico
rename to TGS.Server/tgs.ico
diff --git a/TGS.Tests/Service/ServiceAccessor.cs b/TGS.Tests/Service/ServiceAccessor.cs
deleted file mode 100644
index adf073c53e..0000000000
--- a/TGS.Tests/Service/ServiceAccessor.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-namespace TGS.Server.Service.Tests
-{
- ///
- /// For accessing service control methods of
- ///
- class ServiceAccessor : Service
- {
- ///
- /// Fake a start up
- ///
- /// Fake commandline parameters passed to
- public void FakeStart(string[] args)
- {
- OnStart(args);
- }
-
- ///
- /// Fake a shutdown
- ///
- public void FakeStop()
- {
- OnStop();
- }
- }
-}
diff --git a/TGS.Tests/Service/TestInstanceConfig.cs b/TGS.Tests/Service/TestInstanceConfig.cs
deleted file mode 100644
index a319a968ef..0000000000
--- a/TGS.Tests/Service/TestInstanceConfig.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.IO;
-using TGServiceTests;
-
-namespace TGS.Server.Service.Tests
-{
- ///
- /// Tests for
- ///
- [TestClass]
- public class TestInstanceConfig : TempDirectoryRequiredTest
- {
- ///
- /// The path to the JSON at
- ///
- string InstanceJSONPath { get { return Path.Combine(TempPath, InstanceConfig.JSONFilename); } }
-
- ///
- /// Creates a default at
- ///
- ///
- IInstanceConfig CreateTempConfig()
- {
- return new InstanceConfig(TempPath);
- }
-
- ///
- /// Test that can execute successfully and doesn't automatically save
- ///
- [TestMethod]
- public void TestCreate()
- {
- var IC = CreateTempConfig();
- Assert.IsFalse(File.Exists(InstanceJSONPath));
- }
-
- ///
- /// Test that works correctly
- ///
- [TestMethod]
- public void TestSave()
- {
- var IC = CreateTempConfig();
- IC.Save();
- Assert.IsTrue(File.Exists(InstanceJSONPath));
- }
-
- ///
- /// Test that works correctly
- ///
- [TestMethod]
- public void TestLoad()
- {
- var IC = CreateTempConfig();
- var name = "asdf";
- IC.Name = name;
- IC.Save();
- var IC2 = InstanceConfig.Load(TempPath);
- Assert.AreEqual(name, IC2.Name);
- }
- }
-}
diff --git a/TGS.Tests/Service/TestServerInstance.cs b/TGS.Tests/Service/TestServerInstance.cs
deleted file mode 100644
index 7888567999..0000000000
--- a/TGS.Tests/Service/TestServerInstance.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using TGServiceTests;
-
-namespace TGS.Server.Service.Tests
-{
- ///
- /// Tests for
- ///
- [TestClass]
- public class TestServerInstance : TempDirectoryRequiredTest
- {
- ///
- /// Test a can be created and destroyed successfully with a basic
- ///
- [TestMethod]
- public void TestBasicInstantiation()
- {
- new ServerInstance(new InstanceConfig(TempPath), 1).Dispose();
- }
-
- ///
- /// Test the return value of
- ///
- [TestMethod]
- public void TestPushTestMergeCommits()
- {
- var ic = new InstanceConfig(TempPath) { PushTestmergeCommits = false };
- using (var si = new ServerInstance(ic, 1))
- {
- Assert.IsFalse(si.PushTestmergeCommits());
- ic.PushTestmergeCommits = true;
- Assert.IsTrue(si.PushTestmergeCommits());
- }
- }
-
- [TestMethod]
- public void TestSetPushTestMergeCommits()
- {
- var ic = new InstanceConfig(TempPath) { PushTestmergeCommits = false };
- using (var si = new ServerInstance(ic, 1))
- {
- si.SetPushTestmergeCommits(true);
- Assert.IsTrue(ic.PushTestmergeCommits);
- si.SetPushTestmergeCommits(false);
- Assert.IsFalse(ic.PushTestmergeCommits);
- }
- }
- }
-}
diff --git a/TGS.Tests/Service/TestService.cs b/TGS.Tests/Service/TestService.cs
deleted file mode 100644
index 249517064f..0000000000
--- a/TGS.Tests/Service/TestService.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using TGServiceTests;
-
-namespace TGS.Server.Service.Tests
-{
- ///
- /// Tests for
- ///
- [TestClass]
- public class TestService : TempDirectoryRequiredTest
- {
- ///
- /// Test can execute successfully
- ///
- [TestMethod]
- public void TestInstantiation()
- {
- new Service().Dispose();
- }
-
- ///
- /// Starts and stops a
- ///
- void StartStopServiceBasic()
- {
- using (var S = new ServiceAccessor())
- {
- S.FakeStart(new string[] { });
- S.FakeStop();
- }
- }
-
- ///
- /// Test and can execute successfully
- ///
- [TestMethod]
- public void TestStartupAndShutdown()
- {
- StartStopServiceBasic();
- }
-
- ///
- /// Test and can execute successfully with a commandline port override
- ///
- [TestMethod]
- public void TestCommandLinePortSet()
- {
- Properties.Settings.Default.RemoteAccessPort = 11111;
- using (var S = new ServiceAccessor())
- {
- S.FakeStart(new string[] { "-port", "36785" });
- S.FakeStop();
- }
- Assert.AreEqual(Properties.Settings.Default.RemoteAccessPort, 36785);
- }
-
- ///
- /// Test that the .NET config is always initialized regardless of
- ///
- [TestMethod]
- public void TestNETConfigIsAlwaysPrepped()
- {
- Properties.Settings.Default.UpgradeRequired = true;
- Properties.Settings.Default.InstancePaths = null;
- StartStopServiceBasic();
- Assert.IsNotNull(Properties.Settings.Default.InstancePaths);
- Properties.Settings.Default.UpgradeRequired = false;
- Properties.Settings.Default.InstancePaths = null;
- StartStopServiceBasic();
- Assert.IsNotNull(Properties.Settings.Default.InstancePaths);
- }
- }
-}
diff --git a/TGS.Tests/TGS.Tests.csproj b/TGS.Tests/TGS.Tests.csproj
index ba749c6384..1c470a65a3 100644
--- a/TGS.Tests/TGS.Tests.csproj
+++ b/TGS.Tests/TGS.Tests.csproj
@@ -68,12 +68,6 @@
-
- Component
-
-
-
-
@@ -94,7 +88,7 @@
{8956d4c3-bfb9-448e-bf5f-ee7e6f9996f9}
TGInstallerWrapper
-
+
{f32eda25-0855-411c-af5e-f0d042917e2d}
TGServerService
diff --git a/TGStationServer3.sln b/TGStationServer3.sln
index 8759bbedc0..12df2c84d9 100644
--- a/TGStationServer3.sln
+++ b/TGStationServer3.sln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2006
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Server.Service", "TGS.Server.Service\TGS.Server.Service.csproj", "{F32EDA25-0855-411C-AF5E-F0D042917E2D}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Server", "TGS.Server\TGS.Server.csproj", "{F32EDA25-0855-411C-AF5E-F0D042917E2D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.ControlPanel", "TGS.ControlPanel\TGS.ControlPanel.csproj", "{394E7643-6B8C-416F-AB18-95AC12648CDC}"
EndProject
@@ -97,6 +97,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Interface.Bridge", "TGS
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Tests", "TGS.Tests\TGS.Tests.csproj", "{FB693FFB-17E3-4E84-8CBF-6FFA9C8FD971}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGS.Server.Service", "TGS.Server.Service\TGS.Server.Service.csproj", "{3F81E398-B223-4006-B40C-C2800714CE29}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -159,6 +161,14 @@ Global
{FB693FFB-17E3-4E84-8CBF-6FFA9C8FD971}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FB693FFB-17E3-4E84-8CBF-6FFA9C8FD971}.Release|Any CPU.Build.0 = Release|Any CPU
{FB693FFB-17E3-4E84-8CBF-6FFA9C8FD971}.Release-Client|Any CPU.ActiveCfg = Release|Any CPU
+ {3F81E398-B223-4006-B40C-C2800714CE29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F81E398-B223-4006-B40C-C2800714CE29}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3F81E398-B223-4006-B40C-C2800714CE29}.Debug-Client|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F81E398-B223-4006-B40C-C2800714CE29}.Debug-Client|Any CPU.Build.0 = Debug|Any CPU
+ {3F81E398-B223-4006-B40C-C2800714CE29}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3F81E398-B223-4006-B40C-C2800714CE29}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3F81E398-B223-4006-B40C-C2800714CE29}.Release-Client|Any CPU.ActiveCfg = Release|Any CPU
+ {3F81E398-B223-4006-B40C-C2800714CE29}.Release-Client|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Tools/SignBasics.ps1 b/Tools/SignBasics.ps1
index a87d6920c9..65765abd26 100644
--- a/Tools/SignBasics.ps1
+++ b/Tools/SignBasics.ps1
@@ -11,6 +11,7 @@ if (Test-Path env:snk_passphrase)
{
CodeSign "$bf/TGS.CommandLine/bin/Release/TGCommandLine.exe"
CodeSign "$bf/TGS.ControlPanel/bin/Release/TGControlPanel.exe"
+ CodeSign "$bf/TGS.Server/bin/Release/TGS.Server.dll"
CodeSign "$bf/TGS.Server.Service/bin/Release/TGServerService.exe"
CodeSign "$bf/TGS.Interface.Bridge/bin/x86/Release/TGDreamDaemonBridge.dll"
CodeSign "$bf/TGS.Interface/bin/Release/TGServiceInterface.dll"
diff --git a/appveyor.yml b/appveyor.yml
index 476fddd2c7..ba5b51e4b9 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -34,7 +34,7 @@ build:
after_build:
- ps: Tools/PostCIBuild.ps1
- ps: if($env:APPVEYOR_REPO_COMMIT_MESSAGE -match "\[TGSDeploy\]"){$env:TGSDeploy = "Do it."}
- - ps: $env:TGSVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("$env:APPVEYOR_BUILD_FOLDER/TGS.Server.Service/bin/Release/TGS.Server.Service.exe").FileVersion
+ - ps: $env:TGSVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("$env:APPVEYOR_BUILD_FOLDER/TGS.Server/bin/Release/TGS.Server.dll").FileVersion
test_script:
- set path=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow;%path%
- copy "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions\appveyor.*" "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions" /y