diff --git a/ASS.Server/ASS.Server.csproj b/ASS.Server/ASS.Server.csproj index 346714f..346dd4b 100644 --- a/ASS.Server/ASS.Server.csproj +++ b/ASS.Server/ASS.Server.csproj @@ -6,7 +6,9 @@ + + @@ -29,7 +31,6 @@ - diff --git a/ASS.Server/Extensions/ArrayExtension.cs b/ASS.Server/Extensions/ArrayExtension.cs new file mode 100644 index 0000000..ada8c83 --- /dev/null +++ b/ASS.Server/Extensions/ArrayExtension.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ASS.Server.Extensions +{ + public static class ArrayExtension + { + public static T[] PreAppend(this T[] array, params T[] toAppend) + { + var n = new T[toAppend.Length + array.Length]; + toAppend.CopyTo(n, 0); + array.CopyTo(n, toAppend.Length); + return n; + } + } +} diff --git a/ASS.Server/Helpers/FileSystemHelper.cs b/ASS.Server/Helpers/FileSystemHelper.cs new file mode 100644 index 0000000..df4e12c --- /dev/null +++ b/ASS.Server/Helpers/FileSystemHelper.cs @@ -0,0 +1,26 @@ +using ASS.Server.Extensions; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace ASS.Server.Helpers +{ + public static class FileSystemHelper + { + public static string GetPath(IConfiguration globalConfig, params string[] paths) + { + if(Path.IsPathRooted(paths[0])) + return Path.GetFullPath(Path.Combine(paths)); + return Path.GetFullPath(Path.Combine(paths.PreAppend(globalConfig["WorkDir"]))); + } + + public static string GetPath(IConfiguration globalConfig, string[] extraPaths, params string[] paths) + { + if (Path.IsPathRooted(paths[0])) + return Path.GetFullPath(Path.Combine(extraPaths.PreAppend(paths))); + return Path.GetFullPath(Path.Combine(extraPaths.PreAppend(paths).PreAppend(globalConfig["WorkDir"]))); + } + } +} diff --git a/ASS.Server/Program.cs b/ASS.Server/Program.cs index 6975446..4b5f237 100644 --- a/ASS.Server/Program.cs +++ b/ASS.Server/Program.cs @@ -50,6 +50,7 @@ namespace ASS.Server }) .AddSingleton(sp => new GrpcService(sp)) .AddSingleton() + .AddSingleton() .AddSingleton(); ; return services.BuildServiceProvider(); diff --git a/ASS.Server/Services/ByondService.cs b/ASS.Server/Services/ByondService.cs index c1c1ccf..68e0c69 100644 --- a/ASS.Server/Services/ByondService.cs +++ b/ASS.Server/Services/ByondService.cs @@ -1,4 +1,5 @@ using ASS.API; +using ASS.Server.Helpers; using System; using System.Collections.Generic; using System.Net.Http; @@ -8,6 +9,9 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Linq; using Microsoft.Extensions.Configuration; +using System.IO.Compression; +using System.IO; +using Google.Protobuf; namespace ASS.Server.Services { @@ -18,18 +22,16 @@ namespace ASS.Server.Services HttpClient httpclient; IConfiguration config; + IConfiguration globalConfig; public ByondService(HttpClient _httpClient, IConfiguration configuration) { httpclient = _httpClient; + globalConfig = configuration; config = configuration.GetSection("BYOND"); + } - public static string GetDownloadUrl(string version) - { - var split = version.Split("."); - return GetDownloadUrl(split[0], split[1]); - } public static string GetDownloadUrl(int major, int minor) => GetDownloadUrl(major.ToString(), minor.ToString()); public static string GetDownloadUrl(ByondVersion version) => GetDownloadUrl(version.Major, version.Minor); public static string GetDownloadUrl(string major, string minor) @@ -41,13 +43,56 @@ namespace ASS.Server.Services throw new Exception("Unsupported OS"); } + + private static string getByondVersionDirectoryName(ByondVersion version) => $"{version.Major}.{version.Minor}"; + public string GetByondDirectoryPath(ByondVersion version, params string[] extraPaths) => FileSystemHelper.GetPath(globalConfig, extraPaths, config["Dir"], getByondVersionDirectoryName(version)); + public string GetByondDirectoryPath(params string[] extraPaths) => FileSystemHelper.GetPath(globalConfig, extraPaths, config["Dir"], "live"); + public async Task> GetVersions() { var response = await httpclient.SendAsync(new HttpRequestMessage(HttpMethod.Get, BYOND_LATEST_URL)); var content = await response.Content.ReadAsStringAsync(); + response.Dispose(); var regex = new Regex("\\\"([\\d]+)\\.([\\d]+)_byond.zip\\\""); var matches = regex.Matches(content); return matches.Select(m => new ByondVersion() { Major = int.Parse(m.Captures[0].Value), Minor = int.Parse(m.Captures[0].Value) }); } + + public async Task DownloadByond(ByondVersion version) + { + using (var response = await httpclient.SendAsync(new HttpRequestMessage(HttpMethod.Get, GetDownloadUrl(version)))) + using (var stream = await response.Content.ReadAsStreamAsync()) + using (var archive = new ZipArchive(stream, ZipArchiveMode.Read)) + archive.ExtractToDirectory(GetByondDirectoryPath(version), true); + using (var versionData = File.Create(GetByondDirectoryPath(version, "version.dat"))) + version.WriteTo(versionData); + } + + private ByondVersion getVersion() => getVersion(GetByondDirectoryPath()); + private ByondVersion getVersion(string path) + { + var filePath = Path.Combine(path, "version.dat"); + if (!File.Exists(filePath)) + return null; + ByondVersion version; + using (var versionData = File.OpenRead(filePath)) + version = ByondVersion.Parser.ParseFrom(versionData); + return version; + } + + public async Task SwitchToVersion(ByondVersion version) + { + if (version.Equals(getVersion())) + return; + if (!Directory.Exists(GetByondDirectoryPath(version))) + await DownloadByond(version); + if (!getVersion(GetByondDirectoryPath(version)).Equals(version)) + throw new Exception($"Byond version '{version.Major}.{version.Minor}' data mismatches folder name or ByondVersion data. Please manually remove this version."); + if (Directory.Exists(GetByondDirectoryPath())) + Directory.Delete(GetByondDirectoryPath()); + Emet.FileSystems.FileSystem.CreateSymbolicLink(getByondVersionDirectoryName(version), GetByondDirectoryPath()); + if (!version.Equals(getVersion())) + throw new Exception($"Byond version switch failed."); + } } } diff --git a/ASS.Server/Services/InstanceService.cs b/ASS.Server/Services/InstanceService.cs index 6fc1e26..36492cf 100644 --- a/ASS.Server/Services/InstanceService.cs +++ b/ASS.Server/Services/InstanceService.cs @@ -4,17 +4,37 @@ using System.Text; using System.Threading.Tasks; using ASS.API; using Grpc.Core; +using Microsoft.Extensions.DependencyInjection; namespace ASS.Server.Services { class InstanceService : Instance.InstanceBase { + IServiceProvider serviceProvider; + public InstanceService(IServiceProvider sp) : base() + { + serviceProvider = sp; + } + public async override Task GetStatus(EmptyRequest request, ServerCallContext context) { - return new InstanceStatus + switch (request.Auth.Token) { - Message = $"YOU:{request.Auth.Token}:WE:{DateTime.Now.ToString()}" - }; + case "IB": + var version = new ByondVersion() { Major = 512, Minor = 1469 }; + var byond = serviceProvider.GetRequiredService(); + await byond.SwitchToVersion(version); + return new InstanceStatus + { + Message = $"Installed {version}" + }; + default: + return new InstanceStatus + { + Message = $"YOU:{request.Auth.Token}:WE:{DateTime.Now.ToString()}" + }; + } + } } } diff --git a/ASS.Server/Services/UpdateService.cs b/ASS.Server/Services/UpdateService.cs new file mode 100644 index 0000000..851429e --- /dev/null +++ b/ASS.Server/Services/UpdateService.cs @@ -0,0 +1,29 @@ +using ASS.Server.Helpers; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace ASS.Server.Services +{ + + class UpdateService + { + + IConfiguration config; + + + public UpdateService(IConfiguration configuration) + { + config = configuration; + //Emet.FileSystems.FileSystem.ReadLink(GetLiveDirectory()); + } + + public string GetRpositoryDirectory(params string[] extraPaths) => FileSystemHelper.GetPath(config, extraPaths, "Repo"); + public string GetOverrideDirectory(params string[] extraPaths) => FileSystemHelper.GetPath(config, extraPaths, "Override"); + public string GetLiveDirectory(params string[] extraPaths) => FileSystemHelper.GetPath(config, extraPaths, "Live"); + public string GetRealLiveDirectory(params string[] extraPaths) => throw new NotImplementedException(); + public string GetStagingDirectory(params string[] extraPaths) => throw new NotImplementedException(); + } +} diff --git a/ASS.Server/defaultConfig.json b/ASS.Server/defaultConfig.json index d3e034f..ea2f481 100644 --- a/ASS.Server/defaultConfig.json +++ b/ASS.Server/defaultConfig.json @@ -15,7 +15,8 @@ "Version": { "Major": 512, "Minor": 1467 - } + }, + "Dir": "BYOND" }, "WorkDir": "work" }