From 61105ae59d799d4fce2d760e3615f20378453a3e Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Fri, 20 Oct 2017 16:10:06 -0400 Subject: [PATCH] Document BYOND updater --- TGServerService/ServerInstance/Byond.cs | 144 ++++++++++++++++-------- 1 file changed, 99 insertions(+), 45 deletions(-) diff --git a/TGServerService/ServerInstance/Byond.cs b/TGServerService/ServerInstance/Byond.cs index bc0baa4e3e..6fe793a819 100644 --- a/TGServerService/ServerInstance/Byond.cs +++ b/TGServerService/ServerInstance/Byond.cs @@ -12,30 +12,76 @@ namespace TGServerService { partial class ServerInstance : ITGByond { + /// + /// The instance directory to store the BYOND installation + /// const string ByondDirectory = "BYOND"; + /// + /// The instance directory to use when updating the BYOND installation + /// const string StagingDirectory = "BYOND_staged"; - const string StagingDirectoryInner = "BYOND_staged/byond"; + /// + /// Path to the actual BYOND installation within the + /// + const string StagingDirectoryInner = StagingDirectory + "/byond"; + /// + /// The path in the instance directory to store the downloaded BYOND revision + /// const string RevisionDownloadPath = "BYONDRevision.zip"; + /// + /// The location of the BYOND version data of an installation + /// const string VersionFile = "/byond_version.dat"; + /// + /// The URL format string for getting BYOND version {0}.{1} zipfile + /// const string ByondRevisionsURL = "https://secure.byond.com/download/build/{0}/{0}.{1}_byond.zip"; + /// + /// The URL for getting the latest BYOND version zipfile + /// const string ByondLatestURL = "https://secure.byond.com/download/build/LATEST/"; - - const string ByondConfigDir = "BYOND_staged/BYOND/cfg"; - const string ByondDDConfig = "/daemon.txt"; + /// + /// The instance directory to modify the BYOND cfg before installation + /// + const string ByondConfigDir = ""; + /// + /// BYOND's DreamDaemon config file in the cfg modification directory + /// + const string ByondDDConfig = ByondConfigDir + "/daemon.txt"; + /// + /// Setting to add to to suppress an invisible user prompt for running a trusted mode .dmb + /// const string ByondNoPromptTrustedMode = "trusted-check 0"; + /// + /// The status of the BYOND updater + /// ByondStatus updateStat = ByondStatus.Idle; - object ByondLock = new object(); - string lastError; + /// + /// Used for multithreading safety + /// + object ByondLock = new object(); + /// + /// The last error the BYOND updater encountered + /// + string lastError; + /// + /// Thread used for staging BYOND revisions + /// Thread RevisionStaging; - //Just cleanup + /// + /// Called when the is setup. Prepares the BYOND updater + /// void InitByond() { CleanByondStaging(); } + /// + /// Cleans the BYOND staging directory + /// void CleanByondStaging() { //linger not @@ -44,7 +90,9 @@ namespace TGServerService Program.DeleteDirectory(StagingDirectory); } - //Kill the thread and cleanup again + /// + /// Called when the is shutdown + /// void DisposeByond() { lock (ByondLock) @@ -55,21 +103,25 @@ namespace TGServerService } } - //requires ByondLock to be locked - bool BusyCheckNoLock() + /// + /// Checks if the updater is considered busy + /// + /// if the updater is considered busy, otherwise + bool BusyCheck() { - switch (updateStat) - { - default: - case ByondStatus.Starting: - case ByondStatus.Downloading: - case ByondStatus.Staging: - case ByondStatus.Updating: - return true; - case ByondStatus.Idle: - case ByondStatus.Staged: - return false; - } + lock (ByondLock) + switch (updateStat) + { + default: + case ByondStatus.Starting: + case ByondStatus.Downloading: + case ByondStatus.Staging: + case ByondStatus.Updating: + return true; + case ByondStatus.Idle: + case ByondStatus.Staged: + return false; + } } /// @@ -139,15 +191,11 @@ namespace TGServerService return "Error: " + e.ToString(); } } - - //literally just for passing 2 ints to the thread function - class VersionInfo - { - public int major, minor; - } - - //does the downloading and unzipping - //calls ApplyStagedUpdate() after if the server isn't running + + /// + /// Downloads and unzips a BYOND revision. Calls afterwards if the isn't running, otherwise, calls . Sets on failure + /// + /// Stringified BYOND revision public void UpdateToVersionImpl(object param) { lock (ByondLock) { @@ -160,22 +208,24 @@ namespace TGServerService { CleanByondStaging(); - var vi = (VersionInfo)param; + var vi = ((string)param).Split('.'); + var major = Convert.ToInt32(vi[0]); + var minor = Convert.ToInt32(vi[1]); using (var client = new WebClient()) { - SendMessage(String.Format("BYOND: Updating to version {0}.{1}...", vi.major, vi.minor), MessageType.DeveloperInfo); + SendMessage(String.Format("BYOND: Updating to version {0}.{1}...", major, minor), MessageType.DeveloperInfo); //DOWNLOADING try { - client.DownloadFile(String.Format(ByondRevisionsURL, vi.major, vi.minor), RevisionDownloadPath); + client.DownloadFile(String.Format(ByondRevisionsURL, major, minor), RevisionDownloadPath); } catch { SendMessage("BYOND: Update download failed. Does the specified version exist?", MessageType.DeveloperInfo); - lastError = String.Format("Download of BYOND version {0}.{1} failed! Does it exist?", vi.major, vi.minor); - Service.WriteWarning(String.Format("Failed to update BYOND to version {0}.{1}!", vi.major, vi.minor), EventID.BYONDUpdateFail); + lastError = String.Format("Download of BYOND version {0}.{1} failed! Does it exist?", major, minor); + Service.WriteWarning(String.Format("Failed to update BYOND to version {0}.{1}!", major, minor), EventID.BYONDUpdateFail); lock (ByondLock) { updateStat = ByondStatus.Idle; @@ -193,10 +243,10 @@ namespace TGServerService ZipFile.ExtractToDirectory(RevisionDownloadPath, StagingDirectory); lock (ByondLock) { - File.WriteAllText(StagingDirectoryInner + VersionFile, String.Format("{0}.{1}", vi.major, vi.minor)); + File.WriteAllText(StagingDirectoryInner + VersionFile, String.Format("{0}.{1}", major, minor)); //IMPORTANT: SET THE BYOND CONFIG TO NOT PROMPT FOR TRUSTED MODE REEE Directory.CreateDirectory(ByondConfigDir); - File.WriteAllText(ByondConfigDir + ByondDDConfig, ByondNoPromptTrustedMode); + File.WriteAllText(ByondDDConfig, ByondNoPromptTrustedMode); } File.Delete(RevisionDownloadPath); @@ -216,8 +266,8 @@ namespace TGServerService default: RequestRestart(); lastError = "Update staged. Awaiting server restart..."; - SendMessage(String.Format("BYOND: Staging complete. Awaiting server restart...", vi.major, vi.minor), MessageType.DeveloperInfo); - Service.WriteInfo(String.Format("BYOND update {0}.{1} staged", vi.major, vi.minor), EventID.BYONDUpdateStaged); + SendMessage(String.Format("BYOND: Staging complete. Awaiting server restart...", major, minor), MessageType.DeveloperInfo); + Service.WriteInfo(String.Format("BYOND update {0}.{1} staged", major, minor), EventID.BYONDUpdateStaged); break; } } @@ -237,25 +287,29 @@ namespace TGServerService } } /// - public bool UpdateToVersion(int ma, int mi) + public bool UpdateToVersion(int major, int minor) { lock (ByondLock) { - if (!BusyCheckNoLock()) + if (!BusyCheck()) { updateStat = ByondStatus.Starting; RevisionStaging = new Thread(new ParameterizedThreadStart(UpdateToVersionImpl)) { IsBackground = true //don't slow me down }; - RevisionStaging.Start(new VersionInfo { major = ma, minor = mi }); + RevisionStaging.Start(String.Format("{0}.{1}", major, minor)); return true; } return false; } } - //tries to apply the staged update - public bool ApplyStagedUpdate() + + /// + /// Attempts to move the staged update from to . Sets on failure + /// + /// on success, on failure + bool ApplyStagedUpdate() { lock (CompilerLock) {