From 1d89e9bc6d7b198a884a3a08d6794c345190b958 Mon Sep 17 00:00:00 2001 From: Student Main Date: Fri, 5 Jun 2020 16:03:48 +0800 Subject: [PATCH 1/5] Server.FriendlyName()->Server.ToString() --- .../Controller/Service/AvailabilityStatistics.cs | 12 ++++++------ shadowsocks-csharp/Controller/Service/TCPRelay.cs | 4 ++-- .../Controller/Strategy/HighAvailabilityStrategy.cs | 12 ++++++------ .../Controller/Strategy/StatisticsStrategy.cs | 4 ++-- shadowsocks-csharp/Model/Server.cs | 7 +++---- shadowsocks-csharp/View/ConfigForm.cs | 4 ++-- shadowsocks-csharp/View/MenuViewController.cs | 4 ++-- shadowsocks-csharp/View/QRCodeForm.cs | 2 +- 8 files changed, 24 insertions(+), 25 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs index 5740954b..f6d9a3d6 100644 --- a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs +++ b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs @@ -238,7 +238,7 @@ namespace Shadowsocks.Controller { AppendRecord(server.Identifier(), record); } - logger.Debug($"Ping {server.FriendlyName()} {e.RoundtripTime.Count} times, {(100 - record.PackageLoss * 100)}% packages loss, min {record.MinResponse} ms, max {record.MaxResponse} ms, avg {record.AverageResponse} ms"); + logger.Debug($"Ping {server} {e.RoundtripTime.Count} times, {(100 - record.PackageLoss * 100)}% packages loss, min {record.MinResponse} ms, max {record.MaxResponse} ms, avg {record.AverageResponse} ms"); if (Interlocked.Decrement(ref state.counter) == 0) { Save(); @@ -450,7 +450,7 @@ namespace Shadowsocks.Controller { try { - logger.Debug($"Ping {server.FriendlyName()}"); + logger.Debug($"Ping {server}"); if (ip == null) { ip = Dns.GetHostAddresses(server.server) @@ -466,7 +466,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - logger.Error($"An exception occured while eveluating {server.FriendlyName()}"); + logger.Error($"An exception occured while eveluating {server}"); logger.LogUsefulException(e); FireCompleted(e, userstate); } @@ -478,19 +478,19 @@ namespace Shadowsocks.Controller { if (e.Reply.Status == IPStatus.Success) { - logger.Debug($"Ping {server.FriendlyName()} {e.Reply.RoundtripTime} ms"); + logger.Debug($"Ping {server} {e.Reply.RoundtripTime} ms"); RoundtripTime.Add((int?)e.Reply.RoundtripTime); } else { - logger.Debug($"Ping {server.FriendlyName()} timeout"); + logger.Debug($"Ping {server} timeout"); RoundtripTime.Add(null); } TestNext(e.UserState); } catch (Exception ex) { - logger.Error($"An exception occured while eveluating {server.FriendlyName()}"); + logger.Error($"An exception occured while eveluating {server}"); logger.LogUsefulException(ex); FireCompleted(ex, e.UserState); } diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 0653d8dd..f971c5a2 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -803,7 +803,7 @@ namespace Shadowsocks.Controller AsyncSession session = timer.Session; Server server = timer.Server; OnFailed?.Invoke(this, new SSRelayEventArgs(_server)); - Logger.Info($"{server.FriendlyName()} timed out"); + Logger.Info($"{server.ToString()} timed out"); session.Remote.Close(); Close(); } @@ -830,7 +830,7 @@ namespace Shadowsocks.Controller _destConnected = true; - Logger.Debug($"Socket connected to ss server: {_server.FriendlyName()}"); + Logger.Debug($"Socket connected to ss server: {_server.ToString()}"); TimeSpan latency = DateTime.Now - _startConnectTime; diff --git a/shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs b/shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs index 61356543..d19ea24a 100644 --- a/shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs +++ b/shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs @@ -114,7 +114,7 @@ namespace Shadowsocks.Controller.Strategy 100 * 1000 * Math.Min(5 * 60, (now - status.lastFailure).TotalSeconds) -2 * 5 * (Math.Min(2000, status.latency.TotalMilliseconds) / (1 + (now - status.lastTimeDetectLatency).TotalSeconds / 30 / 10) + -0.5 * 200 * Math.Min(5, (status.lastRead - status.lastWrite).TotalSeconds)); - logger.Debug(String.Format("server: {0} latency:{1} score: {2}", status.server.FriendlyName(), status.latency, status.score)); + logger.Debug(String.Format("server: {0} latency:{1} score: {2}", status.server.ToString(), status.latency, status.score)); } ServerStatus max = null; foreach (var status in servers) @@ -136,14 +136,14 @@ namespace Shadowsocks.Controller.Strategy if (_currentServer == null || max.score - _currentServer.score > 200) { _currentServer = max; - logger.Info($"HA switching to server: {_currentServer.server.FriendlyName()}"); + logger.Info($"HA switching to server: {_currentServer.server.ToString()}"); } } } public void UpdateLatency(Model.Server server, TimeSpan latency) { - logger.Debug($"latency: {server.FriendlyName()} {latency}"); + logger.Debug($"latency: {server.ToString()} {latency}"); ServerStatus status; if (_serverStatus.TryGetValue(server, out status)) @@ -155,7 +155,7 @@ namespace Shadowsocks.Controller.Strategy public void UpdateLastRead(Model.Server server) { - logger.Debug($"last read: {server.FriendlyName()}"); + logger.Debug($"last read: {server.ToString()}"); ServerStatus status; if (_serverStatus.TryGetValue(server, out status)) @@ -166,7 +166,7 @@ namespace Shadowsocks.Controller.Strategy public void UpdateLastWrite(Model.Server server) { - logger.Debug($"last write: {server.FriendlyName()}"); + logger.Debug($"last write: {server.ToString()}"); ServerStatus status; if (_serverStatus.TryGetValue(server, out status)) @@ -177,7 +177,7 @@ namespace Shadowsocks.Controller.Strategy public void SetFailure(Model.Server server) { - logger.Debug($"failure: {server.FriendlyName()}"); + logger.Debug($"failure: {server.ToString()}"); ServerStatus status; if (_serverStatus.TryGetValue(server, out status)) diff --git a/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs b/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs index 57f37989..a2d9bfc7 100644 --- a/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs +++ b/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs @@ -109,7 +109,7 @@ namespace Shadowsocks.Controller.Strategy var bestResult = serversWithStatistics .Aggregate((server1, server2) => server1.score > server2.score ? server1 : server2); - LogWhenEnabled($"Switch to server: {bestResult.server.FriendlyName()} by statistics: score {bestResult.score}"); + LogWhenEnabled($"Switch to server: {bestResult.server.ToString()} by statistics: score {bestResult.score}"); _currentServer = bestResult.server; } catch (Exception e) @@ -147,7 +147,7 @@ namespace Shadowsocks.Controller.Strategy public void SetFailure(Server server) { - logger.Debug($"failure: {server.FriendlyName()}"); + logger.Debug($"failure: {server.ToString()}"); } public void UpdateLastRead(Server server) diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index 6e08f50e..f23cfd41 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -15,9 +15,8 @@ namespace Shadowsocks.Model public const int DefaultPort = 8388; #region ParseLegacyURL - public static readonly Regex - UrlFinder = new Regex(@"ss://(?[A-Za-z0-9+-/=_]+)(?:#(?\S+))?", RegexOptions.IgnoreCase), - DetailsParser = new Regex(@"^((?.+?):(?.*)@(?.+?):(?\d+?))$", RegexOptions.IgnoreCase); + private static readonly Regex UrlFinder = new Regex(@"ss://(?[A-Za-z0-9+-/=_]+)(?:#(?\S+))?", RegexOptions.IgnoreCase); + private static readonly Regex DetailsParser = new Regex(@"^((?.+?):(?.*)@(?.+?):(?\d+?))$", RegexOptions.IgnoreCase); #endregion ParseLegacyURL private const int DefaultServerTimeoutSec = 5; @@ -44,7 +43,7 @@ namespace Shadowsocks.Model return server == o2.server && server_port == o2.server_port; } - public string FriendlyName() + public override string ToString() { if (server.IsNullOrEmpty()) { diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index aa337e6e..47335b05 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -427,7 +427,7 @@ namespace Shadowsocks.View ServersListBox.Items.Clear(); foreach (Server server in configuration.configs) { - ServersListBox.Items.Add(server.FriendlyName()); + ServersListBox.Items.Add(server.ToString()); } } @@ -502,7 +502,7 @@ namespace Shadowsocks.View } if (_lastSelectedIndex >= 0 && _lastSelectedIndex < _modifiedConfiguration.configs.Count) { - ServersListBox.Items[_lastSelectedIndex] = _modifiedConfiguration.configs[_lastSelectedIndex].FriendlyName(); + ServersListBox.Items[_lastSelectedIndex] = _modifiedConfiguration.configs[_lastSelectedIndex].ToString(); } UpdateButtons(); LoadSelectedServerDetails(); diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 89fde38a..64923b4b 100644 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -172,7 +172,7 @@ namespace Shadowsocks.View } else { - serverInfo = config.GetCurrentServer().FriendlyName(); + serverInfo = config.GetCurrentServer().ToString(); } // show more info by hacking the P/Invoke declaration for NOTIFYICONDATA inside Windows Forms string text = I18N.GetString("Shadowsocks") + " " + UpdateChecker.Version + "\n" + @@ -478,7 +478,7 @@ namespace Shadowsocks.View { if (Configuration.ChecksServer(server)) { - MenuItem item = new MenuItem(server.FriendlyName()); + MenuItem item = new MenuItem(server.ToString()); item.Tag = configuration.configs.FindIndex(s => s == server); item.Click += AServerItem_Click; items.Add(strategyCount + serverCount, item); diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index 3275f378..9d178500 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -67,7 +67,7 @@ namespace Shadowsocks.View var servers = Configuration.Load(); var serverDatas = servers.configs.Select( server => - new KeyValuePair(ShadowsocksController.GetServerURL(server), server.FriendlyName()) + new KeyValuePair(ShadowsocksController.GetServerURL(server), server.ToString()) ).ToList(); listBox1.DataSource = serverDatas; From b1d80279525c73813fabdf786ecb0a004e300bdb Mon Sep 17 00:00:00 2001 From: Student Main Date: Fri, 5 Jun 2020 16:04:31 +0800 Subject: [PATCH 2/5] move url generation into Server class --- .../Controller/ShadowsocksController.cs | 43 +------------ shadowsocks-csharp/Model/Server.cs | 62 ++++++++++++++++--- shadowsocks-csharp/View/QRCodeForm.cs | 2 +- test/UrlTest.cs | 2 +- 4 files changed, 57 insertions(+), 52 deletions(-) diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index ea1382d9..182f1bb3 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -371,48 +371,7 @@ namespace Shadowsocks.Controller public string GetServerURLForCurrentServer() { - Server server = GetCurrentServer(); - return GetServerURL(server); - } - - public static string GetServerURL(Server server) - { - string tag = string.Empty; - string url = string.Empty; - - if (string.IsNullOrWhiteSpace(server.plugin)) - { - // For backwards compatiblity, if no plugin, use old url format - string parts = $"{server.method}:{server.password}@{server.server}:{server.server_port}"; - string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); - url = base64; - } - else - { - // SIP002 - string parts = $"{server.method}:{server.password}"; - string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); - string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('='); - - string pluginPart = server.plugin; - if (!string.IsNullOrWhiteSpace(server.plugin_opts)) - { - pluginPart += ";" + server.plugin_opts; - } - - url = string.Format( - "{0}@{1}:{2}/?plugin={3}", - websafeBase64, - server.FormatHostName(server.server), - server.server_port, - HttpUtility.UrlEncode(pluginPart, Encoding.UTF8)); - } - - if (!server.remarks.IsNullOrEmpty()) - { - tag = $"#{HttpUtility.UrlEncode(server.remarks, Encoding.UTF8)}"; - } - return $"ss://{url}{tag}"; + return GetCurrentServer().URL; } public void UpdatePACFromGeosite() diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index f23cfd41..1f5cf828 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -50,21 +50,67 @@ namespace Shadowsocks.Model return I18N.GetString("New server"); } - string serverStr = $"{FormatHostName(server)}:{server_port}"; + string serverStr = $"{FormalHostName}:{server_port}"; return remarks.IsNullOrEmpty() ? serverStr : $"{remarks} ({serverStr})"; } - public string FormatHostName(string hostName) + public string URL { - // CheckHostName() won't do a real DNS lookup - switch (Uri.CheckHostName(hostName)) + get { - case UriHostNameType.IPv6: // Add square bracket when IPv6 (RFC3986) - return $"[{hostName}]"; - default: // IPv4 or domain name - return hostName; + string tag = string.Empty; + string url = string.Empty; + + if (string.IsNullOrWhiteSpace(plugin)) + { + // For backwards compatiblity, if no plugin, use old url format + string parts = $"{method}:{password}@{server}:{server_port}"; + string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); + url = base64; + } + else + { + // SIP002 + string parts = $"{method}:{password}"; + string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); + string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('='); + + string pluginPart = plugin; + if (!string.IsNullOrWhiteSpace(plugin_opts)) + { + pluginPart += ";" + plugin_opts; + } + + url = string.Format( + "{0}@{1}:{2}/?plugin={3}", + websafeBase64, + FormalHostName, + server_port, + HttpUtility.UrlEncode(pluginPart, Encoding.UTF8)); + } + + if (!remarks.IsNullOrEmpty()) + { + tag = $"#{HttpUtility.UrlEncode(remarks, Encoding.UTF8)}"; + } + return $"ss://{url}{tag}"; + } + } + + public string FormalHostName + { + get + { + // CheckHostName() won't do a real DNS lookup + switch (Uri.CheckHostName(server)) + { + case UriHostNameType.IPv6: // Add square bracket when IPv6 (RFC3986) + return $"[{server}]"; + default: // IPv4 or domain name + return server; + } } } diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index 9d178500..44483a89 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -67,7 +67,7 @@ namespace Shadowsocks.View var servers = Configuration.Load(); var serverDatas = servers.configs.Select( server => - new KeyValuePair(ShadowsocksController.GetServerURL(server), server.ToString()) + new KeyValuePair(server.URL, server.ToString()) ).ToList(); listBox1.DataSource = serverDatas; diff --git a/test/UrlTest.cs b/test/UrlTest.cs index 1080bf93..2b37bc55 100644 --- a/test/UrlTest.cs +++ b/test/UrlTest.cs @@ -243,7 +243,7 @@ namespace Shadowsocks.Test string expected = testCase.Key; Server config = testCase.Value; - var actual = ShadowsocksController.GetServerURL(config); + var actual = config.URL; Assert.AreEqual(expected, actual); } } From f3c4dfb106be2896789279c91e6e654fc02f3871 Mon Sep 17 00:00:00 2001 From: Student Main Date: Fri, 5 Jun 2020 16:04:58 +0800 Subject: [PATCH 3/5] switch legacy url generation by hidden flag in config --- .../Controller/ShadowsocksController.cs | 2 +- shadowsocks-csharp/Model/Configuration.cs | 6 ++ shadowsocks-csharp/Model/Server.cs | 61 ++++++++++--------- shadowsocks-csharp/View/QRCodeForm.cs | 8 +-- test/UrlTest.cs | 2 +- 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 182f1bb3..e24ae4d2 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -371,7 +371,7 @@ namespace Shadowsocks.Controller public string GetServerURLForCurrentServer() { - return GetCurrentServer().URL; + return GetCurrentServer().GetURL(_config.generateLegacyUrl); } public void UpdatePACFromGeosite() diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index 0485ff3b..aa393c64 100644 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -24,11 +24,13 @@ namespace Shadowsocks.Model public bool enabled; public bool shareOverLan; public bool isDefault; + // hidden public bool isIPv6Enabled = false; public int localPort; public bool portableMode = true; public bool showPluginOutput; public string pacUrl; + // geosite config is hidden public string geositeUrl; public string geositeGroup = "geolocation-!cn"; public bool geositeBlacklistMode = true; @@ -39,6 +41,10 @@ namespace Shadowsocks.Model public bool autoCheckUpdate; public bool checkPreRelease; public bool isVerboseLogging; + + // hidden config + public bool generateLegacyUrl = false; + //public NLogConfig.LogLevel logLevel; public LogViewerConfig logViewer; public ProxyConfig proxy; diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index 1f5cf828..40909615 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -56,47 +56,50 @@ namespace Shadowsocks.Model : $"{remarks} ({serverStr})"; } - public string URL + public string GetURL(bool legacyUrl = false) { - get - { - string tag = string.Empty; - string url = string.Empty; + string tag = string.Empty; + string url = string.Empty; - if (string.IsNullOrWhiteSpace(plugin)) - { - // For backwards compatiblity, if no plugin, use old url format - string parts = $"{method}:{password}@{server}:{server_port}"; - string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); - url = base64; - } - else + if (legacyUrl && string.IsNullOrWhiteSpace(plugin)) + { + // For backwards compatiblity, if no plugin, use old url format + string parts = $"{method}:{password}@{server}:{server_port}"; + string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); + url = base64; + } + else + { + // SIP002 + string parts = $"{method}:{password}"; + string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); + string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('='); + + url = string.Format( + "{0}@{1}:{2}/", + websafeBase64, + FormalHostName, + server_port + ); + + if (!plugin.IsNullOrWhiteSpace()) { - // SIP002 - string parts = $"{method}:{password}"; - string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts)); - string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('='); string pluginPart = plugin; if (!string.IsNullOrWhiteSpace(plugin_opts)) { pluginPart += ";" + plugin_opts; } - - url = string.Format( - "{0}@{1}:{2}/?plugin={3}", - websafeBase64, - FormalHostName, - server_port, - HttpUtility.UrlEncode(pluginPart, Encoding.UTF8)); + string pluginQuery = "?plugin=" + HttpUtility.UrlEncode(pluginPart, Encoding.UTF8); + url += pluginQuery; } + } - if (!remarks.IsNullOrEmpty()) - { - tag = $"#{HttpUtility.UrlEncode(remarks, Encoding.UTF8)}"; - } - return $"ss://{url}{tag}"; + if (!remarks.IsNullOrEmpty()) + { + tag = $"#{HttpUtility.UrlEncode(remarks, Encoding.UTF8)}"; } + return $"ss://{url}{tag}"; } public string FormalHostName diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index 44483a89..d8fc8c60 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -64,14 +64,14 @@ namespace Shadowsocks.View private void QRCodeForm_Load(object sender, EventArgs e) { - var servers = Configuration.Load(); - var serverDatas = servers.configs.Select( + Configuration config = Configuration.Load(); + List> serverDatas = config.configs.Select( server => - new KeyValuePair(server.URL, server.ToString()) + new KeyValuePair(server.GetURL(config.generateLegacyUrl), server.ToString()) ).ToList(); listBox1.DataSource = serverDatas; - var selectIndex = serverDatas.FindIndex(serverData => serverData.Key.StartsWith(code)); + int selectIndex = serverDatas.FindIndex(serverData => serverData.Key.StartsWith(code)); if (selectIndex >= 0) listBox1.SetSelected(selectIndex, true); } diff --git a/test/UrlTest.cs b/test/UrlTest.cs index 2b37bc55..77f0626c 100644 --- a/test/UrlTest.cs +++ b/test/UrlTest.cs @@ -243,7 +243,7 @@ namespace Shadowsocks.Test string expected = testCase.Key; Server config = testCase.Value; - var actual = config.URL; + var actual = config.GetURL(true); Assert.AreEqual(expected, actual); } } From 19633585247bfb8aad3ec71c38c6aa1bf3de1e17 Mon Sep 17 00:00:00 2001 From: Student Main Date: Fri, 5 Jun 2020 16:14:37 +0800 Subject: [PATCH 4/5] add Server.ParseURL, which parse single server url --- shadowsocks-csharp/Model/Server.cs | 125 +++++++++++++++-------------- 1 file changed, 64 insertions(+), 61 deletions(-) diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index 40909615..3e8ea2e7 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -5,6 +5,7 @@ using System.Text; using System.Web; using Shadowsocks.Controller; using System.Text.RegularExpressions; +using System.Linq; namespace Shadowsocks.Model { @@ -162,79 +163,81 @@ namespace Shadowsocks.Model return server; } - public static List GetServers(string ssURL) + public static Server ParseURL(string serverUrl) { - var serverUrls = ssURL.Split('\r', '\n', ' '); + string _serverUrl = serverUrl.Trim(); + if (!_serverUrl.BeginWith("ss://", StringComparison.InvariantCultureIgnoreCase)) + { + return null; + } - List servers = new List(); - foreach (string serverUrl in serverUrls) + Server legacyServer = ParseLegacyURL(serverUrl); + if (legacyServer != null) //legacy + { + return legacyServer; + } + else //SIP002 { - string _serverUrl = serverUrl.Trim(); - if (!_serverUrl.BeginWith("ss://", StringComparison.InvariantCultureIgnoreCase)) + Uri parsedUrl; + try { - continue; + parsedUrl = new Uri(serverUrl); } - - Server legacyServer = ParseLegacyURL(serverUrl); - if (legacyServer != null) //legacy + catch (UriFormatException) { - servers.Add(legacyServer); + return null; } - else //SIP002 + Server server = new Server { - Uri parsedUrl; - try - { - parsedUrl = new Uri(serverUrl); - } - catch (UriFormatException) - { - continue; - } - Server server = new Server - { - remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped), - server = parsedUrl.IdnHost, - server_port = parsedUrl.Port, - }; - - // parse base64 UserInfo - string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped); - string base64 = rawUserInfo.Replace('-', '+').Replace('_', '/'); // Web-safe base64 to normal base64 - string userInfo = ""; - try - { - userInfo = Encoding.UTF8.GetString(Convert.FromBase64String( - base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))); - } - catch (FormatException) - { - continue; - } - string[] userInfoParts = userInfo.Split(new char[] { ':' }, 2); - if (userInfoParts.Length != 2) - { - continue; - } - server.method = userInfoParts[0]; - server.password = userInfoParts[1]; - - NameValueCollection queryParameters = HttpUtility.ParseQueryString(parsedUrl.Query); - string[] pluginParts = (queryParameters["plugin"] ?? "").Split(new[] { ';' }, 2); - if (pluginParts.Length > 0) - { - server.plugin = pluginParts[0] ?? ""; - } + remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped), + server = parsedUrl.IdnHost, + server_port = parsedUrl.Port, + }; + + // parse base64 UserInfo + string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped); + string base64 = rawUserInfo.Replace('-', '+').Replace('_', '/'); // Web-safe base64 to normal base64 + string userInfo = ""; + try + { + userInfo = Encoding.UTF8.GetString(Convert.FromBase64String( + base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '='))); + } + catch (FormatException) + { + return null; + } + string[] userInfoParts = userInfo.Split(new char[] { ':' }, 2); + if (userInfoParts.Length != 2) + { + return null; + } + server.method = userInfoParts[0]; + server.password = userInfoParts[1]; - if (pluginParts.Length > 1) - { - server.plugin_opts = pluginParts[1] ?? ""; - } + NameValueCollection queryParameters = HttpUtility.ParseQueryString(parsedUrl.Query); + string[] pluginParts = (queryParameters["plugin"] ?? "").Split(new[] { ';' }, 2); + if (pluginParts.Length > 0) + { + server.plugin = pluginParts[0] ?? ""; + } - servers.Add(server); + if (pluginParts.Length > 1) + { + server.plugin_opts = pluginParts[1] ?? ""; } + + return server; } - return servers; + } + + public static List GetServers(string ssURL) + { + return ssURL + .Split('\r', '\n', ' ') + .Select(u => ParseURL(u)) + .Where(s => s != null) + .ToList(); } public string Identifier() From f6fcab40ad690e1738c2105ab33c95982d4dca53 Mon Sep 17 00:00:00 2001 From: Student Main Date: Fri, 19 Jun 2020 00:42:43 +0800 Subject: [PATCH 5/5] cleaning in Configuration.cs --- shadowsocks-csharp/Model/Configuration.cs | 36 +++++++++-------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index aa393c64..f712653e 100644 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -11,7 +11,7 @@ namespace Shadowsocks.Model public class Configuration { [JsonIgnore] - private static Logger logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); public string version; @@ -24,16 +24,10 @@ namespace Shadowsocks.Model public bool enabled; public bool shareOverLan; public bool isDefault; - // hidden - public bool isIPv6Enabled = false; public int localPort; public bool portableMode = true; public bool showPluginOutput; public string pacUrl; - // geosite config is hidden - public string geositeUrl; - public string geositeGroup = "geolocation-!cn"; - public bool geositeBlacklistMode = true; public bool useOnlinePac; public bool secureLocalPac = true; @@ -42,8 +36,13 @@ namespace Shadowsocks.Model public bool checkPreRelease; public bool isVerboseLogging; - // hidden config - public bool generateLegacyUrl = false; + // hidden options + public bool isIPv6Enabled = false; // for experimental ipv6 support + public bool generateLegacyUrl = false; // for pre-sip002 url compatibility + public string geositeUrl; // for custom geosite source (and rule group) + public string geositeGroup = "geolocation-!cn"; + public bool geositeBlacklistMode = true; + //public NLogConfig.LogLevel logLevel; public LogViewerConfig logViewer; @@ -54,11 +53,10 @@ namespace Shadowsocks.Model NLogConfig nLogConfig; private static readonly string CONFIG_FILE = "gui-config.json"; - private static readonly NLogConfig.LogLevel verboseLogLevel = #if DEBUG - NLogConfig.LogLevel.Trace; + private static readonly NLogConfig.LogLevel verboseLogLevel = NLogConfig.LogLevel.Trace; #else - NLogConfig.LogLevel.Debug; + private static readonly NLogConfig.LogLevel verboseLogLevel = NLogConfig.LogLevel.Debug; #endif @@ -200,9 +198,9 @@ namespace Shadowsocks.Model sw.Flush(); } try - { - // apply changs to NLog.config - config.nLogConfig.SetLogLevel(config.isVerboseLogging? verboseLogLevel : NLogConfig.LogLevel.Info); + { + // apply changes to NLog.config + config.nLogConfig.SetLogLevel(config.isVerboseLogging ? verboseLogLevel : NLogConfig.LogLevel.Info); NLogConfig.SaveXML(config.nLogConfig); } catch (Exception e) @@ -218,7 +216,7 @@ namespace Shadowsocks.Model public static Server AddDefaultServerOrServer(Configuration config, Server server = null, int? index = null) { - if (config != null && config.configs != null) + if (config?.configs != null) { server = (server ?? GetDefaultServer()); @@ -237,12 +235,6 @@ namespace Shadowsocks.Model return new Server(); } - private static void Assert(bool condition) - { - if (!condition) - throw new Exception(I18N.GetString("assertion failure")); - } - public static void CheckPort(int port) { if (port <= 0 || port > 65535)