From ac8df87e08b51453889c5e2dbf08388b658df333 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Tue, 26 May 2020 23:24:43 +0200 Subject: [PATCH] Add support for network groups, #1798 --- ArchiSteamFarm/ASF.cs | 40 +++++++++++++++++++++--------------- ArchiSteamFarm/Program.cs | 29 +++++++++++++++++++++++++- ArchiSteamFarm/SharedInfo.cs | 1 + 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/ArchiSteamFarm/ASF.cs b/ArchiSteamFarm/ASF.cs index 38c588bd4..2a7dbdc3d 100644 --- a/ArchiSteamFarm/ASF.cs +++ b/ArchiSteamFarm/ASF.cs @@ -143,29 +143,37 @@ namespace ArchiSteamFarm { GlobalConfig = globalConfig; - string webProxyText = ""; + StringBuilder networkGroupBuilder = new StringBuilder(); - if (!string.IsNullOrEmpty(globalConfig.WebProxyText)) { - // The only purpose of using hashingAlgorithm here is to cut on a potential size of the resource name - paths can be really long, and we almost certainly have some upper limit on the resource name we can allocate - // At the same time it'd be the best if we avoided all special characters, such as '/' found e.g. in base64, as we can't be sure that it's not a prohibited character in regards to native OS implementation - // Because of that, MD5 is sufficient for our case, as it generates alphanumeric characters only, and is barely 128-bit long. We don't need any kind of complex cryptography or collision detection here, any hashing algorithm will do, and the shorter the better + // The only purpose of using hashingAlgorithm below is to cut on a potential size of the resource name - paths can be really long, and we almost certainly have some upper limit on the resource name we can allocate + // At the same time it'd be the best if we avoided all special characters, such as '/' found e.g. in base64, as we can't be sure that it's not a prohibited character in regards to native OS implementation + // Because of that, MD5 is sufficient for our case, as it generates alphanumeric characters only, and is barely 128-bit long. We don't need any kind of complex cryptography or collision detection here, any hashing algorithm will do, and the shorter the better + if (!string.IsNullOrEmpty(Program.NetworkGroup)) { using MD5 hashingAlgorithm = MD5.Create(); - webProxyText = "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(globalConfig.WebProxyText))).Replace("-", ""); + networkGroupBuilder.Append("-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Program.NetworkGroup))).Replace("-", "")); } - ConfirmationsSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(ConfirmationsSemaphore) + webProxyText); - GiftsSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(GiftsSemaphore) + webProxyText); - InventorySemaphore ??= OS.CreateCrossProcessSemaphore(nameof(InventorySemaphore) + webProxyText); - LoginRateLimitingSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(LoginRateLimitingSemaphore) + webProxyText); - LoginSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(LoginSemaphore) + webProxyText); + if (!string.IsNullOrEmpty(globalConfig.WebProxyText)) { + using MD5 hashingAlgorithm = MD5.Create(); + + networkGroupBuilder.Append("-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(globalConfig.WebProxyText))).Replace("-", "")); + } + + string networkGroupText = networkGroupBuilder.ToString(); + + ConfirmationsSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(ConfirmationsSemaphore) + networkGroupText); + GiftsSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(GiftsSemaphore) + networkGroupText); + InventorySemaphore ??= OS.CreateCrossProcessSemaphore(nameof(InventorySemaphore) + networkGroupText); + LoginRateLimitingSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(LoginRateLimitingSemaphore) + networkGroupText); + LoginSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(LoginSemaphore) + networkGroupText); WebLimitingSemaphores ??= new Dictionary(4, StringComparer.OrdinalIgnoreCase) { - { nameof(ArchiWebHandler), (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { ArchiWebHandler.SteamCommunityURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText + "-" + nameof(ArchiWebHandler.SteamCommunityURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { ArchiWebHandler.SteamHelpURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText + "-" + nameof(ArchiWebHandler.SteamHelpURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { ArchiWebHandler.SteamStoreURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText + "-" + nameof(ArchiWebHandler.SteamStoreURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { WebAPI.DefaultBaseAddress.Host, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText + "-" + nameof(WebAPI)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) } + { nameof(ArchiWebHandler), (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { ArchiWebHandler.SteamCommunityURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText + "-" + nameof(ArchiWebHandler.SteamCommunityURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { ArchiWebHandler.SteamHelpURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText + "-" + nameof(ArchiWebHandler.SteamHelpURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { ArchiWebHandler.SteamStoreURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText + "-" + nameof(ArchiWebHandler.SteamStoreURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { WebAPI.DefaultBaseAddress.Host, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + networkGroupText + "-" + nameof(WebAPI)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) } }.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase); } diff --git a/ArchiSteamFarm/Program.cs b/ArchiSteamFarm/Program.cs index c0503cdbc..a5222df4c 100644 --- a/ArchiSteamFarm/Program.cs +++ b/ArchiSteamFarm/Program.cs @@ -38,6 +38,7 @@ using SteamKit2; namespace ArchiSteamFarm { internal static class Program { + internal static string NetworkGroup { get; private set; } internal static bool ProcessRequired { get; private set; } internal static bool RestartAllowed { get; private set; } = true; internal static bool ShutdownSequenceInitialized { get; private set; } @@ -92,6 +93,16 @@ namespace ArchiSteamFarm { ArchiCryptoHelper.SetEncryptionKey(cryptKey); } + private static void HandleNetworkGroupArgument(string networkGroup) { + if (string.IsNullOrEmpty(networkGroup)) { + ASF.ArchiLogger.LogNullError(nameof(networkGroup)); + + return; + } + + NetworkGroup = networkGroup; + } + private static void HandlePathArgument(string path) { if (string.IsNullOrEmpty(path)) { ASF.ArchiLogger.LogNullError(nameof(path)); @@ -457,6 +468,12 @@ namespace ArchiSteamFarm { } try { + string envNetworkGroup = Environment.GetEnvironmentVariable(SharedInfo.EnvironmentVariableNetworkGroup); + + if (!string.IsNullOrEmpty(envNetworkGroup)) { + HandleNetworkGroupArgument(envNetworkGroup); + } + string envPath = Environment.GetEnvironmentVariable(SharedInfo.EnvironmentVariablePath); if (!string.IsNullOrEmpty(envPath)) { @@ -466,18 +483,28 @@ namespace ArchiSteamFarm { ASF.ArchiLogger.LogGenericException(e); } + bool networkGroupNext = false; bool pathNext = false; foreach (string arg in args) { switch (arg) { + case "--network-group" when !networkGroupNext: + networkGroupNext = true; + + break; case "--path" when !pathNext: pathNext = true; break; default: - if (pathNext) { + if (networkGroupNext) { + networkGroupNext = false; + HandleNetworkGroupArgument(arg); + } else if (pathNext) { pathNext = false; HandlePathArgument(arg); + } else if ((arg.Length > 16) && arg.StartsWith("--network-group=", StringComparison.Ordinal)) { + HandleNetworkGroupArgument(arg.Substring(7)); } else if ((arg.Length > 7) && arg.StartsWith("--path=", StringComparison.Ordinal)) { HandlePathArgument(arg.Substring(7)); } diff --git a/ArchiSteamFarm/SharedInfo.cs b/ArchiSteamFarm/SharedInfo.cs index 4cb996ed7..269eab6ef 100644 --- a/ArchiSteamFarm/SharedInfo.cs +++ b/ArchiSteamFarm/SharedInfo.cs @@ -38,6 +38,7 @@ namespace ArchiSteamFarm { internal const string DatabaseExtension = ".db"; internal const string DebugDirectory = "debug"; internal const string EnvironmentVariableCryptKey = ASF + "_CRYPTKEY"; + internal const string EnvironmentVariableNetworkGroup = ASF + "_NETWORK_GROUP"; internal const string EnvironmentVariablePath = ASF + "_PATH"; internal const string GithubReleaseURL = "https://api.github.com/repos/" + GithubRepo + "/releases"; internal const string GithubRepo = "JustArchiNET/" + AssemblyName;