Just weave the dll and make everyones life easier

This commit is contained in:
Cyberboss
2017-11-02 12:35:25 -04:00
parent 9cfd154111
commit 2a1aad5314
8 changed files with 87 additions and 90 deletions
+2 -1
View File
@@ -9,7 +9,7 @@ namespace TGDreamDaemonBridge
/// <summary>
/// Holds the proc that DD calls to access <see cref="ITGInterop"/>
/// </summary>
public sealed class DreamDaemonBridge
public static class DreamDaemonBridge
{
/// <summary>
/// The proc that DD calls to access <see cref="ITGInterop"/>
@@ -20,6 +20,7 @@ namespace TGDreamDaemonBridge
[DllExport("DDEntryPoint", CallingConvention = CallingConvention.Cdecl)]
public static int DDEntryPoint(int argc, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 0)]string[] args)
{
System.Diagnostics.Debugger.Launch();
try
{
using (var I = new Interface())
+24 -6
View File
@@ -17,6 +17,8 @@
<DllExportOrdinalsBase>1</DllExportOrdinalsBase>
<DllExportGenExpLib>false</DllExportGenExpLib>
<DllExportOurILAsm>false</DllExportOurILAsm>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -40,12 +42,10 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGServiceInterface\TGServiceInterface.csproj">
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
<Name>TGServiceInterface</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="Costura, Version=1.6.2.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
<HintPath>..\packages\Costura.Fody.1.6.2\lib\dotnet\Costura.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RGiesecke.DllExport.Metadata, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8f52d83c1a22df51, processorArchitecture=MSIL">
<HintPath>..\packages\UnmanagedExports.1.2.7\lib\net\RGiesecke.DllExport.Metadata.dll</HintPath>
<Private>False</Private>
@@ -55,6 +55,24 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGServiceInterface\TGServiceInterface.csproj">
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
<Name>TGServiceInterface</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="FodyWeavers.xml" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="../packages/UnmanagedExports.1.2.7/tools/RGiesecke.DllExport.targets" Condition="Exists('../packages/UnmanagedExports.1.2.7/tools/RGiesecke.DllExport.targets')" />
<Import Project="..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets" Condition="Exists('..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>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}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets'))" />
<Error Condition="!Exists('..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets'))" />
</Target>
<Import Project="..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets" Condition="Exists('..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets')" />
</Project>
+2
View File
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Costura.Fody" version="1.6.2" targetFramework="net461" developmentDependency="true" />
<package id="Fody" version="2.0.0" targetFramework="net461" developmentDependency="true" />
<package id="UnmanagedExports" version="1.2.7" targetFramework="net452" developmentDependency="true" />
</packages>
+2 -2
View File
@@ -245,11 +245,11 @@ namespace TGServerService
/// <summary>
/// Info: When the <see cref="TGServiceInterface"/> dll is updated for the <see cref="ServerInstance"/>
/// </summary>
InterfaceDLLUpdated = 5800,
BridgeDLLUpdated = 5800,
/// <summary>
/// Error: An error occurred while updating the <see cref="TGServiceInterface"/> dll for the <see cref="ServerInstance"/>
/// </summary>
InterfaceDLLUpdateFail = 5900,
BridgeDLLUpdateFail = 5900,
//YO THERE'S SPACE FOR 1 MORE ID HERE, USE IT!!!
+11 -22
View File
@@ -38,7 +38,7 @@ namespace TGServerService
object CompilerLock = new object();
CompilerStatus compilerCurrentStatus;
string lastCompilerError;
Thread CompilerThread;
bool compilationCancellationRequestation = false;
bool canCancelCompilation = false;
@@ -49,7 +49,7 @@ namespace TGServerService
//deletes leftovers and checks current status
void InitCompiler()
{
if(File.Exists(LiveDirTest))
if (File.Exists(LiveDirTest))
File.Delete(LiveDirTest);
compilerCurrentStatus = IsInitialized();
}
@@ -82,7 +82,7 @@ namespace TGServerService
if (CompilerThread == null || !CompilerThread.IsAlive)
return;
CompilerThread.Abort(); //this will safely kill dm
InitCompiler(); //also cleanup
InitCompiler(); //also cleanup
}
}
@@ -98,7 +98,7 @@ namespace TGServerService
{
return compilerCurrentStatus == CompilerStatus.Uninitialized || compilerCurrentStatus == CompilerStatus.Initialized;
}
/// <inheritdoc />
public bool Initialize()
{
@@ -117,7 +117,7 @@ namespace TGServerService
//what is says on the tin
CompilerStatus IsInitialized()
{
if (File.Exists(Path.Combine(GameDirLive, InterfaceDLLName))) //its a good tell, jim
if (File.Exists(Path.Combine(GameDirLive, BridgeDLLName))) //its a good tell, jim
return CompilerStatus.Initialized;
return CompilerStatus.Uninitialized;
}
@@ -135,15 +135,9 @@ namespace TGServerService
//we need to remove symlinks before we can recursively delete
void CleanGameFolder()
{
if (Directory.Exists(Path.Combine(GameDirA, InterfaceDLLName)))
Directory.Delete(Path.Combine(GameDirA, InterfaceDLLName));
if (Directory.Exists(Path.Combine(GameDirA, BridgeDLLName)))
Directory.Delete(Path.Combine(GameDirA, BridgeDLLName));
if (Directory.Exists(Path.Combine(GameDirB, InterfaceDLLName)))
Directory.Delete(Path.Combine(GameDirB, InterfaceDLLName));
if (Directory.Exists(Path.Combine(GameDirB, BridgeDLLName)))
Directory.Delete(Path.Combine(GameDirB, BridgeDLLName));
@@ -196,21 +190,19 @@ namespace TGServerService
var Config = GetCachedRepoConfig();
if (Config != null) {
if (Config != null)
{
foreach (var I in Config.StaticDirectoryPaths)
CreateSymlink(Path.Combine(GameDirA, I), Path.Combine(StaticDirs, I));
foreach (var I in Config.DLLPaths)
CreateSymlink(Path.Combine(GameDirA, I), Path.Combine(StaticDirs, I));
}
CreateSymlink(Path.Combine(GameDirA, InterfaceDLLName), InterfaceDLLName);
CreateSymlink(Path.Combine(GameDirB, InterfaceDLLName), InterfaceDLLName);
CreateSymlink(Path.Combine(GameDirA, BridgeDLLName), BridgeDLLName);
CreateSymlink(Path.Combine(GameDirB, BridgeDLLName), BridgeDLLName);
CreateSymlink(GameDirLive, GameDirA);
lock (CompilerLock)
{
compilerCurrentStatus = CompilerStatus.Compiling;
@@ -238,7 +230,7 @@ namespace TGServerService
return;
}
CompileImpl();
}
}
//Returns the A or B dir in which the game is NOT running
string GetStagingDir()
@@ -277,7 +269,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(GameDirLive);
@@ -360,7 +352,7 @@ namespace TGServerService
resurrectee = GetStagingDir();
var Config = GetCachedRepoConfig();
var deleteExcludeList = new List<string> { InterfaceDLLName, BridgeDLLName };
var deleteExcludeList = new List<string> { BridgeDLLName };
deleteExcludeList.AddRange(Config.StaticDirectoryPaths);
deleteExcludeList.AddRange(Config.DLLPaths);
Program.DeleteDirectory(resurrectee, true, deleteExcludeList);
@@ -381,9 +373,6 @@ namespace TGServerService
CreateSymlink(the_path, Path.Combine(StaticDirs, I));
}
if (!File.Exists(Path.Combine(resurrectee, InterfaceDLLName)))
CreateSymlink(Path.Combine(resurrectee, InterfaceDLLName), InterfaceDLLName);
if (!File.Exists(Path.Combine(resurrectee, BridgeDLLName)))
CreateSymlink(Path.Combine(resurrectee, BridgeDLLName), BridgeDLLName);
+31 -57
View File
@@ -38,23 +38,6 @@ namespace TGServerService
/// </summary>
const int DDBadStartTime = 10;
/// <summary>
/// The file name of the .dll that contains the <see cref="Interface"/>
/// </summary>
static readonly string InterfaceDLLName = Path.GetFileName(Assembly.GetAssembly(typeof(Interface)).Location);
/// <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";
/// <summary>
/// The DreamDaemon process
/// </summary>
@@ -168,7 +151,7 @@ namespace TGServerService
//autostart the server
if (Properties.Settings.Default.DDAutoStart)
//break this off so we don't hold up starting the service
ThreadPool.QueueUserWorkItem( _ => { Start(); });
ThreadPool.QueueUserWorkItem(_ => { Start(); });
}
/// <summary>
@@ -195,7 +178,7 @@ namespace TGServerService
else if (Detach)
Properties.Settings.Default.ReattachToDD = false;
Stop();
if(pcpu != null)
if (pcpu != null)
pcpu.Dispose();
if (RenameLog)
try
@@ -283,7 +266,7 @@ namespace TGServerService
{
if (DaemonStatus() == DreamDaemonStatus.Offline)
return Start();
lock(restartLock)
lock (restartLock)
{
if (RestartInProgress)
return "Restart already in progress";
@@ -292,8 +275,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;
}
@@ -512,7 +495,7 @@ namespace TGServerService
}
return StartImpl(false);
}
/// <summary>
/// Translate the configured <see cref="DreamDaemonSecurity"/> level into a byond command line param
/// </summary>
@@ -535,56 +518,46 @@ namespace TGServerService
}
/// <summary>
/// Copies <see cref="InterfaceDLLName"/> and <see cref="BridgeDLLName"/> from the program directory to the the <see cref="ServerInstance"/> directory
/// Copies <see cref="InterfaceDLLName"/> 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 UpdateInterfaceDlls(bool overwrite)
/// <param name="overwrite">If <see langword="true"/>, overwrites the <see cref="ServerInstance"/>'s current interface .dll if it exists</param>
void UpdateInterfaceDll(bool overwrite)
{
var InterfacePath = Assembly.GetAssembly(typeof(Interface)).Location;
UpdateInterfaceDLL(InterfacePath, InterfaceDLLName, overwrite);
var FileExists = File.Exists(BridgeDLLName);
if (FileExists && !overwrite)
return;
//Copy the interface dll to the static dir
var InterfacePath = Assembly.GetAssembly(typeof(Interface)).Location;
var BridgePath = Path.Combine(Path.GetDirectoryName(InterfacePath), BridgeDLLName);
#if DEBUG
//We could be debugging from the project directory
if(!File.Exists(BridgePath))
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/Debug", BridgeDLLName);
#endif
try
{
//Use reflection to ensure these are the droids we're looking for
var bridge = Assembly.ReflectionOnlyLoadFrom(BridgePath);
bridge.GetType(DreamDaemonBridgeType);
UpdateInterfaceDLL(BridgePath, BridgeDLLName, overwrite);
Assembly.ReflectionOnlyLoadFrom(BridgePath).GetType(DreamDaemonBridgeType, true);
}
catch (Exception e) {
Service.WriteError(String.Format("Unable to locate {0}! Error: {1}", BridgeDLLName, e.ToString()), EventID.InterfaceDLLUpdateFail);
}
}
/// <summary>
/// Copies the .dll at <paramref name="path"/> to <paramref name="targetPath"/> in the <see cref="ServerInstance"/>, optionally with an <paramref name="overwrite"/> paremeter, retrying once if the file is locked
/// </summary>
/// <param name="path">The path of the source .dll</param>
/// <param name="targetPath">The path of the destination .dll</param>
/// <param name="overwrite">If <see langword="true"/>, overwrites the <see cref="ServerInstance"/>'s current <paramref name="targetPath"/> .dll, if it exists</param>
void UpdateInterfaceDLL(string path, string targetPath, bool overwrite)
{
var FileExists = File.Exists(targetPath);
if (FileExists && !overwrite)
catch (Exception e)
{
Service.WriteError(String.Format("Unable to locate {0}! Error: {1}", BridgeDLLName, e.ToString()), EventID.BridgeDLLUpdateFail);
return;
//Copy the interface dll to the static dir
}
try
{
if (FileExists)
{
var Old = File.ReadAllBytes(path);
var New = File.ReadAllBytes(targetPath);
var Old = File.ReadAllBytes(BridgeDLLName);
var New = File.ReadAllBytes(BridgePath);
if (Old.SequenceEqual(New))
return; //no need
}
File.Copy(path, targetPath, overwrite);
Service.WriteInfo("Updated interface DLL", EventID.InterfaceDLLUpdated);
File.Copy(InterfacePath, BridgeDLLName, overwrite);
Service.WriteInfo("Updated interface DLL", EventID.BridgeDLLUpdated);
}
catch
{
@@ -592,18 +565,18 @@ namespace TGServerService
{
//ok the things being stupid and hasn't released the dll yet, try ONCE more
Thread.Sleep(1000);
File.Copy(path, targetPath, overwrite);
File.Copy(InterfacePath, BridgeDLLName, overwrite);
}
catch (Exception e)
{
//intentionally using the fi
Service.WriteError(String.Format("Failed to update interface DLL {0}! Error: {1}", targetPath, e.ToString()), EventID.InterfaceDLLUpdateFail);
Service.WriteError("Failed to update interface DLL! Error: " + e.ToString(), EventID.BridgeDLLUpdateFail);
}
}
}
/// <summary>
/// Clears the current <see cref="GameAPIVersion"/>, calls <see cref="UpdateInterfaceDlls(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="UpdateInterfaceDll(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>
@@ -623,7 +596,7 @@ namespace TGServerService
GenCommsKey();
StartingSecurity = (DreamDaemonSecurity)Config.ServerSecurity;
Proc.StartInfo.Arguments = String.Format("{0} -port {1} {5}-close -verbose -params \"server_service={3}&server_service_version={4}\" -{2} -public", DMB, Config.ServerPort, SecurityWord(), serviceCommsKey, Version(), Config.Webclient ? "-webclient " : "");
UpdateInterfaceDlls(true);
UpdateInterfaceDll(true);
lock (topicLock)
{
GameAPIVersion = null; //needs updating
@@ -763,7 +736,8 @@ namespace TGServerService
public void SetWebclient(bool on)
{
var Config = Properties.Settings.Default;
lock (watchdogLock) {
lock (watchdogLock)
{
var diff = on != Config.Webclient;
if (diff)
{
+13
View File
@@ -42,6 +42,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()
+2 -2
View File
@@ -96,7 +96,7 @@ namespace TGServerService
{
Directory.CreateDirectory(RepoKeyDir);
if(Exists())
UpdateInterfaceDlls(false);
UpdateInterfaceDll(false);
if(LoadRepo() == null)
DisableGarbageCollectionNoLock();
//start the autoupdate timer
@@ -336,7 +336,7 @@ namespace TGServerService
void InitialConfigureRepository()
{
Directory.CreateDirectory(StaticDirs);
UpdateInterfaceDlls(false);
UpdateInterfaceDll(false);
UpdateTGS3Json();
var Config = GetCachedRepoConfig(); //RepoBusy is set if we're here
foreach(var I in Config.StaticDirectoryPaths)