From 6ca395795c373118d0d1a7389dee2faeb2f34ed8 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Fri, 8 Jul 2022 19:16:29 +0200 Subject: [PATCH] Move network group logic into plugins core This will allow plugin creators to make use of network groups --- ArchiSteamFarm/Core/ASF.cs | 32 +++++++++------------------ ArchiSteamFarm/Plugins/PluginsCore.cs | 17 ++++++++++++++ 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/ArchiSteamFarm/Core/ASF.cs b/ArchiSteamFarm/Core/ASF.cs index 6bfccab2b..978ff9517 100644 --- a/ArchiSteamFarm/Core/ASF.cs +++ b/ArchiSteamFarm/Core/ASF.cs @@ -422,30 +422,18 @@ public static class ASF { throw new InvalidOperationException(nameof(GlobalConfig)); } - // The only purpose of using hashing 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, SHA256 is sufficient for our case, as it generates alphanumeric characters only, and is barely 256-bit long. We don't need any kind of complex cryptography or collision detection here, any hashing will do, and the shorter the better - string networkGroupText = ""; - - if (!string.IsNullOrEmpty(Program.NetworkGroup)) { - // ReSharper disable once RedundantSuppressNullableWarningExpression - required for .NET Framework - networkGroupText = $"-{Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(Program.NetworkGroup!)))}"; - } else if (!string.IsNullOrEmpty(GlobalConfig.WebProxyText)) { - networkGroupText = $"-{Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(GlobalConfig.WebProxyText!)))}"; - } - - ConfirmationsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(ConfirmationsSemaphore)}{networkGroupText}").ConfigureAwait(false); - GiftsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(GiftsSemaphore)}{networkGroupText}").ConfigureAwait(false); - InventorySemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(InventorySemaphore)}{networkGroupText}").ConfigureAwait(false); - LoginRateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(LoginRateLimitingSemaphore)}{networkGroupText}").ConfigureAwait(false); - LoginSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(LoginSemaphore)}{networkGroupText}").ConfigureAwait(false); - RateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore($"{nameof(RateLimitingSemaphore)}{networkGroupText}").ConfigureAwait(false); + ConfirmationsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(ConfirmationsSemaphore)).ConfigureAwait(false); + GiftsSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(GiftsSemaphore)).ConfigureAwait(false); + InventorySemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(InventorySemaphore)).ConfigureAwait(false); + LoginRateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(LoginRateLimitingSemaphore)).ConfigureAwait(false); + LoginSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(LoginSemaphore)).ConfigureAwait(false); + RateLimitingSemaphore ??= await PluginsCore.GetCrossProcessSemaphore(nameof(RateLimitingSemaphore)).ConfigureAwait(false); WebLimitingSemaphores ??= new Dictionary(4) { - { ArchiWebHandler.SteamCommunityURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(ArchiWebHandler.SteamCommunityURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { ArchiWebHandler.SteamHelpURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(ArchiWebHandler.SteamHelpURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { ArchiWebHandler.SteamStoreURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(ArchiWebHandler.SteamStoreURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, - { WebAPI.DefaultBaseAddress, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}{networkGroupText}-{nameof(WebAPI)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) } + { ArchiWebHandler.SteamCommunityURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}-{nameof(ArchiWebHandler.SteamCommunityURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { ArchiWebHandler.SteamHelpURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}-{nameof(ArchiWebHandler.SteamHelpURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { ArchiWebHandler.SteamStoreURL, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}-{nameof(ArchiWebHandler.SteamStoreURL)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }, + { WebAPI.DefaultBaseAddress, (await PluginsCore.GetCrossProcessSemaphore($"{nameof(ArchiWebHandler)}-{nameof(WebAPI)}").ConfigureAwait(false), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) } }.ToImmutableDictionary(); } diff --git a/ArchiSteamFarm/Plugins/PluginsCore.cs b/ArchiSteamFarm/Plugins/PluginsCore.cs index 64d00013c..a91b30ec2 100644 --- a/ArchiSteamFarm/Plugins/PluginsCore.cs +++ b/ArchiSteamFarm/Plugins/PluginsCore.cs @@ -31,6 +31,8 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; +using System.Security.Cryptography; +using System.Text; using System.Threading.Tasks; using ArchiSteamFarm.Core; using ArchiSteamFarm.Helpers; @@ -40,6 +42,7 @@ using ArchiSteamFarm.Steam; using ArchiSteamFarm.Steam.Data; using ArchiSteamFarm.Steam.Exchange; using ArchiSteamFarm.Steam.Integration.Callbacks; +using ArchiSteamFarm.Storage; using JetBrains.Annotations; using Newtonsoft.Json.Linq; using SteamKit2; @@ -58,8 +61,22 @@ internal static class PluginsCore { throw new ArgumentNullException(nameof(objectName)); } + if (ASF.GlobalConfig == null) { + throw new InvalidOperationException(nameof(ASF.GlobalConfig)); + } + string resourceName = OS.GetOsResourceName(objectName); + // The only purpose of using hashing 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, SHA256 is sufficient for our case, as it generates alphanumeric characters only, and is barely 256-bit long. We don't need any kind of complex cryptography or collision detection here, any hashing will do, and the shorter the better + if (!string.IsNullOrEmpty(Program.NetworkGroup)) { + // ReSharper disable once RedundantSuppressNullableWarningExpression - required for .NET Framework + resourceName += $"-{Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(Program.NetworkGroup!)))}"; + } else if (!string.IsNullOrEmpty(ASF.GlobalConfig.WebProxyText)) { + resourceName += $"-{Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(ASF.GlobalConfig.WebProxyText!)))}"; + } + if ((ActivePlugins == null) || (ActivePlugins.Count == 0)) { return new CrossProcessFileBasedSemaphore(resourceName); }