mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-29 16:11:05 +01:00
240 lines
7.0 KiB
C#
240 lines
7.0 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Security.Principal;
|
|
using System.ServiceModel;
|
|
using System.ServiceProcess;
|
|
using TGServiceInterface;
|
|
|
|
namespace TGServerService
|
|
{
|
|
public partial class TGServerService : ServiceBase
|
|
{
|
|
//only deprecate events, do not reuse them
|
|
public enum EventID
|
|
{
|
|
ChatCommand = 100,
|
|
ChatConnectFail = 200,
|
|
ChatProviderStartFail = 300,
|
|
InvalidChatProvider = 400,
|
|
UpdateRequest = 500,
|
|
BYONDUpdateFail = 600,
|
|
BYONDUpdateStaged = 700,
|
|
BYONDUpdateComplete = 800,
|
|
ServerMoveFailed = 900,
|
|
ServerMovePartial = 1000,
|
|
ServerMoveComplete = 1100,
|
|
DMCompileCrash = 1200,
|
|
DMInitializeCrash = 1300,
|
|
DMCompileError = 1400,
|
|
DMCompileSuccess = 1500,
|
|
DMCompileCancel = 1600,
|
|
DDReattachFail = 1700,
|
|
DDReattachSuccess = 1800,
|
|
DDWatchdogCrash = 1900,
|
|
DDWatchdogExit = 2000,
|
|
DDWatchdogRebootedServer = 2100,
|
|
DDWatchdogRebootingServer = 2200,
|
|
DDWatchdogRestart = 2300,
|
|
DDWatchdogRestarted = 2400,
|
|
DDWatchdogStarted = 2500,
|
|
ChatSend = 2600,
|
|
ChatBroadcast = 2700,
|
|
//ChatAdminBroadcast = 2800,
|
|
ChatDisconnectFail = 2900,
|
|
//TopicSent = 3000,
|
|
//TopicFailed = 3100,
|
|
CommsKeySet = 3200,
|
|
NudgeStartFail = 3300,
|
|
NudgeCrash = 3400,
|
|
RepoClone = 3500,
|
|
RepoCloneFail = 3600,
|
|
RepoCheckout = 3700,
|
|
RepoCheckoutFail = 3800,
|
|
RepoHardUpdate = 3900,
|
|
RepoHardUpdateFail = 4000,
|
|
RepoMergeUpdate = 4100,
|
|
RepoMergeUpdateFail = 4200,
|
|
RepoBackupTag = 4300,
|
|
RepoBackupTagFail = 4400,
|
|
RepoResetTracked = 4500,
|
|
RepoResetTrackedFail = 4600,
|
|
RepoReset = 4700,
|
|
RepoResetFail = 4800,
|
|
RepoPRListError = 4900,
|
|
RepoPRMerge = 5000,
|
|
RepoPRMergeFail = 5100,
|
|
RepoCommit = 5200,
|
|
RepoCommitFail = 5300,
|
|
RepoPush = 5400,
|
|
RepoPushFail = 5500,
|
|
RepoChangelog = 5600,
|
|
RepoChangelogFail = 5700,
|
|
ServiceShutdownFail = 6100,
|
|
WorldReboot = 6200,
|
|
ServerUpdateApplied = 6300,
|
|
ChatBroadcastFail = 6400,
|
|
IRCLogModes = 6500,
|
|
SubmoduleReclone = 6600,
|
|
Authentication = 6700,
|
|
PreactionEvent = 6800,
|
|
PreactionFail = 6900,
|
|
InteropCallException = 7000,
|
|
APIVersionMismatch = 7100,
|
|
RepoConfigurationFail = 7200,
|
|
StaticRead = 7300,
|
|
StaticWrite = 7400,
|
|
StaticDelete = 7500,
|
|
}
|
|
|
|
static TGServerService ActiveService; //So everyone else can write to our eventlog
|
|
|
|
public static readonly string Version = "/tg/station 13 Server Service v" + FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion;
|
|
|
|
/// <summary>
|
|
/// You can't write to logs while impersonating, call this to cancel WCF's impersonation first
|
|
/// </summary>
|
|
public static void CancelImpersonation()
|
|
{
|
|
WindowsIdentity.Impersonate(IntPtr.Zero);
|
|
}
|
|
|
|
public static void WriteInfo(string message, EventID id)
|
|
{
|
|
ActiveService.EventLog.WriteEntry(message, EventLogEntryType.Information, (int)id);
|
|
}
|
|
public static void WriteError(string message, EventID id)
|
|
{
|
|
ActiveService.EventLog.WriteEntry(message, EventLogEntryType.Error, (int)id);
|
|
}
|
|
public static void WriteWarning(string message, EventID id)
|
|
{
|
|
ActiveService.EventLog.WriteEntry(message, EventLogEntryType.Warning, (int)id);
|
|
}
|
|
|
|
public static void WriteAccess(string username, bool authSuccess)
|
|
{
|
|
ActiveService.EventLog.WriteEntry(String.Format("Access from: {0}", username), authSuccess ? EventLogEntryType.SuccessAudit : EventLogEntryType.FailureAudit, (int)EventID.Authentication);
|
|
}
|
|
|
|
ServiceHost host; //the WCF host
|
|
|
|
void MigrateSettings(int oldVersion, int newVersion)
|
|
{
|
|
if (oldVersion == newVersion && newVersion == 0) //chat refactor
|
|
Properties.Settings.Default.ChatProviderData = "NEEDS INITIALIZING"; //reset chat settings to be safe
|
|
}
|
|
|
|
//you should seriously not add anything here
|
|
//Use OnStart instead
|
|
public TGServerService()
|
|
{
|
|
try
|
|
{
|
|
if (Properties.Settings.Default.UpgradeRequired)
|
|
{
|
|
var newVersion = Properties.Settings.Default.SettingsVersion;
|
|
Properties.Settings.Default.Upgrade();
|
|
var oldVersion = Properties.Settings.Default.SettingsVersion;
|
|
Properties.Settings.Default.SettingsVersion = newVersion;
|
|
|
|
MigrateSettings(oldVersion, newVersion);
|
|
|
|
Properties.Settings.Default.UpgradeRequired = false;
|
|
Properties.Settings.Default.Save();
|
|
}
|
|
InitializeComponent();
|
|
ActiveService = this;
|
|
Run(this);
|
|
}
|
|
finally
|
|
{
|
|
Properties.Settings.Default.Save();
|
|
}
|
|
}
|
|
|
|
//when babby is formed
|
|
protected override void OnStart(string[] args)
|
|
{
|
|
var Config = Properties.Settings.Default;
|
|
if (!Directory.Exists(Config.ServerDirectory))
|
|
{
|
|
EventLog.WriteEntry("Creating server directory: " + Config.ServerDirectory);
|
|
Directory.CreateDirectory(Config.ServerDirectory);
|
|
}
|
|
Environment.CurrentDirectory = Config.ServerDirectory;
|
|
|
|
var instance = new TGStationServer();
|
|
|
|
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;
|
|
}
|
|
|
|
host = new ServiceHost(instance, new Uri[] { new Uri("net.pipe://localhost"), new Uri(String.Format("https://localhost:{0}", Config.RemoteAccessPort)) })
|
|
{
|
|
CloseTimeout = new TimeSpan(0, 0, 5)
|
|
};
|
|
|
|
foreach (var I in Server.ValidInterfaces)
|
|
AddEndpoint(I);
|
|
|
|
host.Authorization.ServiceAuthorizationManager = instance;
|
|
|
|
try
|
|
{
|
|
host.Open();
|
|
}
|
|
catch (AddressAlreadyInUseException e)
|
|
{
|
|
throw new Exception("Can't start the service due to the configured remote access port being in use. To fix this change it by starting the service with the \"-port <port>\" argument.", e);
|
|
}
|
|
}
|
|
|
|
//shorthand for adding the WCF endpoint
|
|
void AddEndpoint(Type typetype)
|
|
{
|
|
var bindingName = Server.MasterInterfaceName + "/" + typetype.Name;
|
|
host.AddServiceEndpoint(typetype, new NetNamedPipeBinding() { SendTimeout = new TimeSpan(0, 0, 30), MaxReceivedMessageSize = Server.TransferLimitLocal }, bindingName);
|
|
var httpsBinding = new WSHttpBinding()
|
|
{
|
|
SendTimeout = new TimeSpan(0, 0, 40),
|
|
MaxReceivedMessageSize = Server.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);
|
|
}
|
|
|
|
//when we is kill
|
|
protected override void OnStop()
|
|
{
|
|
try
|
|
{
|
|
TGStationServer instance = (TGStationServer)host.SingletonInstance;
|
|
host.Close();
|
|
instance.Dispose();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
WriteError(e.ToString(), EventID.ServiceShutdownFail);
|
|
}
|
|
}
|
|
}
|
|
}
|