mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-30 08:33:19 +01:00
Merge upstream
This commit is contained in:
@@ -35,12 +35,10 @@ namespace TGServerService
|
||||
const string BDirTest = GameDirB + LiveFile;
|
||||
const string LiveDirTest = GameDirLive + LiveFile;
|
||||
|
||||
const string InterfaceDLLName = "TGServiceInterface.dll";
|
||||
|
||||
object CompilerLock = new object();
|
||||
CompilerStatus compilerCurrentStatus;
|
||||
string lastCompilerError;
|
||||
|
||||
|
||||
Thread CompilerThread;
|
||||
bool compilationCancellationRequestation = false;
|
||||
bool canCancelCompilation = false;
|
||||
@@ -85,7 +83,7 @@ namespace TGServerService
|
||||
if (CompilerThread == null || !CompilerThread.IsAlive)
|
||||
return;
|
||||
CompilerThread.Abort(); //this will safely kill dm
|
||||
InitCompiler(); //also cleanup
|
||||
InitCompiler(); //also cleanup
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +99,7 @@ namespace TGServerService
|
||||
{
|
||||
return compilerCurrentStatus == CompilerStatus.Uninitialized || compilerCurrentStatus == CompilerStatus.Initialized;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Initialize()
|
||||
{
|
||||
@@ -120,7 +118,7 @@ namespace TGServerService
|
||||
//what is says on the tin
|
||||
CompilerStatus IsInitialized()
|
||||
{
|
||||
if (File.Exists(RelativePath(Path.Combine(GameDirLive, InterfaceDLLName)))) //its a good tell, jim
|
||||
if (File.Exists(RelativePath(Path.Combine(GameDirLive, BridgeDLLName)))) //its a good tell, jim
|
||||
return CompilerStatus.Initialized;
|
||||
return CompilerStatus.Uninitialized;
|
||||
}
|
||||
@@ -128,13 +126,13 @@ namespace TGServerService
|
||||
//we need to remove symlinks before we can recursively delete
|
||||
void CleanGameFolder()
|
||||
{
|
||||
var GameDirAInterface = RelativePath(Path.Combine(GameDirA, InterfaceDLLName));
|
||||
if (Directory.Exists(GameDirAInterface))
|
||||
Directory.Delete(GameDirAInterface);
|
||||
var GameDirABridge = RelativePath(Path.Combine(GameDirA, BridgeDLLName));
|
||||
if (Directory.Exists(GameDirABridge))
|
||||
Directory.Delete(GameDirABridge);
|
||||
|
||||
var GameDirBInterface = RelativePath(Path.Combine(GameDirB, InterfaceDLLName));
|
||||
if (Directory.Exists(GameDirBInterface))
|
||||
Directory.Delete(GameDirBInterface);
|
||||
var GameDirBBridge = RelativePath(Path.Combine(GameDirB, BridgeDLLName));
|
||||
if (Directory.Exists(GameDirBBridge))
|
||||
Directory.Delete(GameDirBBridge);
|
||||
|
||||
var rgdl = RelativePath(GameDirLive);
|
||||
if (Directory.Exists(rgdl))
|
||||
@@ -193,9 +191,9 @@ namespace TGServerService
|
||||
CreateSymlink(RelativePath(Path.Combine(GameDirA, I)), RelativePath(Path.Combine(StaticDirs, I)));
|
||||
}
|
||||
|
||||
var ridlln = RelativePath(InterfaceDLLName);
|
||||
CreateSymlink(RelativePath(Path.Combine(GameDirA, InterfaceDLLName)), ridlln);
|
||||
CreateSymlink(RelativePath(Path.Combine(GameDirB, InterfaceDLLName)), ridlln);
|
||||
var rbdlln = RelativePath(BridgeDLLName);
|
||||
CreateSymlink(RelativePath(Path.Combine(GameDirA, BridgeDLLName)), rbdlln);
|
||||
CreateSymlink(RelativePath(Path.Combine(GameDirB, BridgeDLLName)), rbdlln);
|
||||
|
||||
CreateSymlink(RelativePath(GameDirLive), RelativePath(GameDirA));
|
||||
|
||||
@@ -226,7 +224,7 @@ namespace TGServerService
|
||||
return;
|
||||
}
|
||||
CompileImpl();
|
||||
}
|
||||
}
|
||||
|
||||
//Returns the A or B dir in which the game is NOT running
|
||||
string GetStagingDir()
|
||||
@@ -265,7 +263,7 @@ namespace TGServerService
|
||||
{
|
||||
File.Delete(rsclock);
|
||||
}
|
||||
catch //held open by byond
|
||||
catch //held open by byond
|
||||
{
|
||||
//This means there is a staged update waiting to be applied, we have to unstage it before we can work
|
||||
Directory.Delete(RelativePath(GameDirLive));
|
||||
@@ -348,7 +346,7 @@ namespace TGServerService
|
||||
resurrectee = GetStagingDir(); //non-relative
|
||||
|
||||
var Config = GetCachedRepoConfig();
|
||||
var deleteExcludeList = new List<string> { InterfaceDLLName };
|
||||
var deleteExcludeList = new List<string> { BridgeDLLName };
|
||||
deleteExcludeList.AddRange(Config.StaticDirectoryPaths);
|
||||
deleteExcludeList.AddRange(Config.DLLPaths);
|
||||
Program.DeleteDirectory(resurrectee, true, deleteExcludeList);
|
||||
@@ -369,8 +367,8 @@ namespace TGServerService
|
||||
CreateSymlink(the_path, RelativePath(Path.Combine(StaticDirs, I)));
|
||||
}
|
||||
|
||||
if (!File.Exists(Path.Combine(resurrectee, InterfaceDLLName)))
|
||||
CreateSymlink(Path.Combine(resurrectee, InterfaceDLLName), RelativePath(InterfaceDLLName));
|
||||
if (!File.Exists(Path.Combine(resurrectee, BridgeDLLName)))
|
||||
CreateSymlink(Path.Combine(resurrectee, BridgeDLLName), RelativePath(BridgeDLLName));
|
||||
|
||||
deleteExcludeList.Add(".git");
|
||||
Program.CopyDirectory(RelativePath(RepoPath), resurrectee, deleteExcludeList);
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace TGServerService
|
||||
//autostart the server
|
||||
if (Config.Autostart)
|
||||
//break this off so we don't hold up starting the service
|
||||
ThreadPool.QueueUserWorkItem( _ => { Start(); });
|
||||
ThreadPool.QueueUserWorkItem(_ => { Start(); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -178,7 +178,7 @@ namespace TGServerService
|
||||
else if (Detach)
|
||||
Config.ReattachRequired = false;
|
||||
Stop();
|
||||
if(pcpu != null)
|
||||
if (pcpu != null)
|
||||
pcpu.Dispose();
|
||||
if (RenameLog)
|
||||
try
|
||||
@@ -267,7 +267,7 @@ namespace TGServerService
|
||||
{
|
||||
if (DaemonStatus() == DreamDaemonStatus.Offline)
|
||||
return Start();
|
||||
lock(restartLock)
|
||||
lock (restartLock)
|
||||
{
|
||||
if (RestartInProgress)
|
||||
return "Restart already in progress";
|
||||
@@ -276,8 +276,8 @@ namespace TGServerService
|
||||
SendMessage("DD: Hard restart triggered", MessageType.WatchdogInfo);
|
||||
Stop();
|
||||
var res = Start();
|
||||
if(res != null)
|
||||
lock(restartLock)
|
||||
if (res != null)
|
||||
lock (restartLock)
|
||||
{
|
||||
RestartInProgress = false;
|
||||
}
|
||||
@@ -496,7 +496,7 @@ namespace TGServerService
|
||||
}
|
||||
return StartImpl(false);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Translate the configured <see cref="DreamDaemonSecurity"/> level into a byond command line param
|
||||
/// </summary>
|
||||
@@ -519,28 +519,47 @@ namespace TGServerService
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies <see cref="InterfaceDLLName"/> from the program directory to the the <see cref="ServerInstance"/> directory
|
||||
/// Copies <see cref="BridgeDLLName"/> from the program directory to the the <see cref="ServerInstance"/> directory
|
||||
/// </summary>
|
||||
/// <param name="overwrite">If <see langword="true"/>, overwrites the <see cref="ServerInstance"/>'s current interface .dll if it exists</param>
|
||||
void UpdateInterfaceDll(bool overwrite)
|
||||
void UpdateBridgeDll(bool overwrite)
|
||||
{
|
||||
var ridlln = RelativePath(InterfaceDLLName);
|
||||
var FileExists = File.Exists(ridlln);
|
||||
var rbdlln = RelativePath(BridgeDLLName);
|
||||
var FileExists = File.Exists(rbdlln);
|
||||
if (FileExists && !overwrite)
|
||||
return;
|
||||
//Copy the interface dll to the static dir
|
||||
var InterfacePath = Assembly.GetAssembly(typeof(DreamDaemonBridge)).Location;
|
||||
|
||||
var InterfacePath = Assembly.GetAssembly(typeof(Interface)).Location;
|
||||
//bridge is installed next to the interface
|
||||
var BridgePath = Path.Combine(Path.GetDirectoryName(InterfacePath), BridgeDLLName);
|
||||
#if DEBUG
|
||||
//We could be debugging from the project directory
|
||||
if (!File.Exists(BridgePath))
|
||||
//A little hackish debug mode doctoring never hurt anyone
|
||||
BridgePath = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(InterfacePath)))), "TGDreamDaemonBridge/bin/x86/Debug", BridgeDLLName);
|
||||
#endif
|
||||
try
|
||||
{
|
||||
//Use reflection to ensure these are the droids we're looking for
|
||||
Assembly.ReflectionOnlyLoadFrom(BridgePath).GetType(DreamDaemonBridgeType, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
WriteError(String.Format("Unable to locate {0}! Error: {1}", BridgeDLLName, e.ToString()), EventID.BridgeDLLUpdateFail);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (FileExists)
|
||||
{
|
||||
var Old = File.ReadAllBytes(ridlln);
|
||||
var New = File.ReadAllBytes(InterfacePath);
|
||||
var Old = File.ReadAllBytes(rbdlln);
|
||||
var New = File.ReadAllBytes(BridgePath);
|
||||
if (Old.SequenceEqual(New))
|
||||
return; //no need
|
||||
}
|
||||
File.Copy(InterfacePath, ridlln, overwrite);
|
||||
WriteInfo("Updated interface DLL", EventID.InterfaceDLLUpdated);
|
||||
File.Copy(BridgePath, rbdlln, overwrite);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -548,18 +567,20 @@ namespace TGServerService
|
||||
{
|
||||
//ok the things being stupid and hasn't released the dll yet, try ONCE more
|
||||
Thread.Sleep(1000);
|
||||
File.Copy(InterfacePath, ridlln, overwrite);
|
||||
File.Copy(InterfacePath, rbdlln, overwrite);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//intentionally using the fi
|
||||
WriteError("Failed to update interface DLL! Error: " + e.ToString(), EventID.InterfaceDLLUpdateFail);
|
||||
WriteError("Failed to update bridge DLL! Error: " + e.ToString(), EventID.BridgeDLLUpdateFail);
|
||||
return;
|
||||
}
|
||||
}
|
||||
WriteInfo("Updated interface DLL", EventID.BridgeDLLUpdated);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the current <see cref="GameAPIVersion"/>, calls <see cref="UpdateInterfaceDll(bool)"/> with a <see langword="true"/> parameter, and attempts to start the DreamDaemon <see cref="Proc"/>
|
||||
/// Clears the current <see cref="GameAPIVersion"/>, calls <see cref="UpdateBridgeDll(bool)"/> with a <see langword="true"/> parameter, and attempts to start the DreamDaemon <see cref="Proc"/>
|
||||
/// </summary>
|
||||
/// <param name="watchdog">If <see langword="false"/>, sets <see cref="DDWatchdog"/> to a new <see cref="Thread"/> pointing to <see cref="Watchdog"/> and starts it</param>
|
||||
/// <returns><see langword="null"/> on success, error message on failure</returns>
|
||||
@@ -578,7 +599,7 @@ namespace TGServerService
|
||||
GenCommsKey();
|
||||
StartingSecurity = Config.Security;
|
||||
Proc.StartInfo.Arguments = String.Format("{0} -port {1} {5}-close -verbose -params \"server_service={3}&server_service_version={4}&{6}={7}\" -{2} -public", DMB, Config.Port, SecurityWord(), serviceCommsKey, Version(), Config.Webclient ? "-webclient " : "", SPInstanceName, Config.Name);
|
||||
UpdateInterfaceDll(true);
|
||||
UpdateBridgeDll(true);
|
||||
lock (topicLock)
|
||||
{
|
||||
GameAPIVersion = null; //needs updating
|
||||
@@ -715,7 +736,8 @@ namespace TGServerService
|
||||
/// <inheritdoc />
|
||||
public void SetWebclient(bool on)
|
||||
{
|
||||
lock (watchdogLock) {
|
||||
lock (watchdogLock)
|
||||
{
|
||||
var diff = on != Config.Webclient;
|
||||
if (diff)
|
||||
{
|
||||
|
||||
@@ -49,6 +49,19 @@ namespace TGServerService
|
||||
const string CCPAdminOnly = "admin_only";
|
||||
const string CCPRequiredParameters = "required_parameters";
|
||||
|
||||
/// <summary>
|
||||
/// The file name of the .dll that contains the <see cref="ITGInterop"/> bridge class
|
||||
/// </summary>
|
||||
const string BridgeDLLName = "TGDreamDaemonBridge.dll";
|
||||
/// <summary>
|
||||
/// The namespace that contains the <see cref="ITGInterop"/> bridge class. Used for reflection
|
||||
/// </summary>
|
||||
const string DreamDaemonBridgeNamespace = "TGDreamDaemonBridge";
|
||||
/// <summary>
|
||||
/// The <see cref="ITGInterop"/> bridge class. Used for reflection
|
||||
/// </summary>
|
||||
const string DreamDaemonBridgeType = DreamDaemonBridgeNamespace + ".DreamDaemonBridge";
|
||||
|
||||
List<Command> ServerChatCommands;
|
||||
|
||||
void LoadServerChatCommands()
|
||||
@@ -172,34 +185,33 @@ namespace TGServerService
|
||||
lock (topicLock) {
|
||||
if (!CheckAPIVersionConstraints())
|
||||
return "Incompatible API!";
|
||||
|
||||
StringBuilder stringPacket = new StringBuilder();
|
||||
stringPacket.Append((char)'\x00', 8);
|
||||
stringPacket.Append('?' + topicdata);
|
||||
stringPacket.Append((char)'\x00');
|
||||
string fullString = stringPacket.ToString();
|
||||
var packet = Encoding.ASCII.GetBytes(fullString);
|
||||
packet[1] = 0x83;
|
||||
var FinalLength = packet.Length - 4;
|
||||
if (FinalLength > UInt16.MaxValue)
|
||||
return "Error: Topic too long";
|
||||
|
||||
var lengthBytes = BitConverter.GetBytes((ushort)FinalLength);
|
||||
|
||||
packet[2] = lengthBytes[1]; //fucking endianess
|
||||
packet[3] = lengthBytes[0];
|
||||
|
||||
var returnedString = "NULL";
|
||||
var returnedData = new byte[UInt16.MaxValue];
|
||||
using (var topicSender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { SendTimeout = 5000, ReceiveTimeout = 5000 })
|
||||
{
|
||||
try
|
||||
{
|
||||
topicSender.Connect(IPAddress.Loopback, port);
|
||||
|
||||
StringBuilder stringPacket = new StringBuilder();
|
||||
stringPacket.Append((char)'\x00', 8);
|
||||
stringPacket.Append('?' + topicdata);
|
||||
stringPacket.Append((char)'\x00');
|
||||
string fullString = stringPacket.ToString();
|
||||
var packet = Encoding.ASCII.GetBytes(fullString);
|
||||
packet[1] = 0x83;
|
||||
var FinalLength = packet.Length - 4;
|
||||
if (FinalLength > UInt16.MaxValue)
|
||||
return "Error: Topic too long";
|
||||
|
||||
var lengthBytes = BitConverter.GetBytes((ushort)FinalLength);
|
||||
|
||||
packet[2] = lengthBytes[1]; //fucking endianess
|
||||
packet[3] = lengthBytes[0];
|
||||
|
||||
topicSender.Send(packet);
|
||||
|
||||
string returnedString = "NULL";
|
||||
try
|
||||
{
|
||||
var returnedData = new byte[UInt16.MaxValue];
|
||||
topicSender.Receive(returnedData);
|
||||
var raw_string = Encoding.ASCII.GetString(returnedData).TrimEnd(new char[] { (char)0 }).Trim();
|
||||
if (raw_string.Length > 6)
|
||||
@@ -213,14 +225,13 @@ namespace TGServerService
|
||||
{
|
||||
topicSender.Shutdown(SocketShutdown.Both);
|
||||
}
|
||||
|
||||
return returnedString;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "Topic delivery failed!";
|
||||
}
|
||||
}
|
||||
|
||||
return returnedString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace TGServerService
|
||||
{
|
||||
Directory.CreateDirectory(RelativePath(RepoKeyDir));
|
||||
if(Exists())
|
||||
UpdateInterfaceDll(false);
|
||||
UpdateBridgeDll(false);
|
||||
if(LoadRepo() == null)
|
||||
DisableGarbageCollectionNoLock();
|
||||
//start the autoupdate timer
|
||||
@@ -338,7 +338,7 @@ namespace TGServerService
|
||||
void InitialConfigureRepository()
|
||||
{
|
||||
Directory.CreateDirectory(RelativePath(StaticDirs));
|
||||
UpdateInterfaceDll(false);
|
||||
UpdateBridgeDll(false);
|
||||
UpdateTGS3Json();
|
||||
var Config = GetCachedRepoConfig(); //RepoBusy is set if we're here
|
||||
foreach(var I in Config.StaticDirectoryPaths)
|
||||
|
||||
Reference in New Issue
Block a user