From 23b90b8697198de489060bc4c45018b89edcdc70 Mon Sep 17 00:00:00 2001 From: Christopher Meng Date: Mon, 17 Aug 2015 08:43:03 +0800 Subject: [PATCH 01/16] Add gfwlist links Various fixes accompanied. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bcd3f5cf..ae480278 100644 --- a/README.md +++ b/README.md @@ -7,30 +7,30 @@ Shadowsocks for Windows 1. System proxy configuration 2. PAC mode and global mode -3. GFWList and user rules +3. [GFWList](https://github.com/gfwlist/gfwlist) and user rules 4. Supports HTTP proxy 5. Supports server auto switching 6. Supports UDP relay (see Usage) #### Download -Download a [latest release]. +Download the [latest release]. #### Basic 1. Find Shadowsocks icon in the notification tray 2. You can add multiple servers in servers menu -3. Select Enable System Proxy menu to enable system proxy. Please disable other +3. Select `Enable System Proxy` menu to enable system proxy. Please disable other proxy addons in your browser, or set them to use system proxy 4. You can also configure your browser proxy manually if you don't want to enable system proxy. Set Socks5 or HTTP proxy to 127.0.0.1:1080. You can change this -port in Server -> Edit Servers +port in `Servers -> Edit Servers` #### PAC 1. You can change PAC rules by editing the PAC file. When you save the PAC file with any editor, Shadowsocks will notify browsers about the change automatically -2. You can also update PAC file from GFWList (maintained by 3rd party) +2. You can also update PAC file from [GFWList](https://github.com/gfwlist/gfwlist) (maintained by 3rd party) 3. You can also use online PAC URL #### Server Auto Switching @@ -44,7 +44,7 @@ with any editor, Shadowsocks will notify browsers about the change automatically #### UDP For UDP, you need to use SocksCap or ProxyCap to force programs you want -to proxy to tunnel over Shadowsocks +to be proxied to tunnel over Shadowsocks #### Develop From 1b8584e6e14b3d678e660bb512f1706ff01856a4 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 10:57:59 +0800 Subject: [PATCH 02/16] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ae480278..4dedf567 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Shadowsocks for Windows 1. System proxy configuration 2. PAC mode and global mode -3. [GFWList](https://github.com/gfwlist/gfwlist) and user rules +3. [GFWList] and user rules 4. Supports HTTP proxy 5. Supports server auto switching 6. Supports UDP relay (see Usage) @@ -30,7 +30,7 @@ port in `Servers -> Edit Servers` 1. You can change PAC rules by editing the PAC file. When you save the PAC file with any editor, Shadowsocks will notify browsers about the change automatically -2. You can also update PAC file from [GFWList](https://github.com/gfwlist/gfwlist) (maintained by 3rd party) +2. You can also update PAC file from [GFWList] (maintained by 3rd party) 3. You can also use online PAC URL #### Server Auto Switching @@ -58,3 +58,4 @@ GPLv3 [Appveyor]: https://ci.appveyor.com/project/clowwindy/shadowsocks-csharp [Build Status]: https://ci.appveyor.com/api/projects/status/gknc8l1lxy423ehv/branch/master [latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases +[GFWList]: https://github.com/gfwlist/gfwlist From 7978817492119307cd35d4ba5940c8337edfddb2 Mon Sep 17 00:00:00 2001 From: icylogic Date: Mon, 17 Aug 2015 11:32:03 +0800 Subject: [PATCH 03/16] fixed #280, log "No such host is known" and other PingException --- .../Controller/Service/AvailabilityStatistics.cs | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs index 5a95dbc2..0d8463a6 100644 --- a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs +++ b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs @@ -67,14 +67,21 @@ namespace Shadowsocks.Controller string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //ICMP echo. we can also set options and special bytes //seems no need to use SendPingAsync - PingReply reply = ping.Send(server.server, Timeout); - state.data = new List>(); - state.data.Add(new KeyValuePair("Timestamp", timestamp)); - state.data.Add(new KeyValuePair("Server", server.FriendlyName())); - state.data.Add(new KeyValuePair("Status", reply.Status.ToString())); - state.data.Add(new KeyValuePair("RoundtripTime", reply.RoundtripTime.ToString())); - //state.data.Add(new KeyValuePair("data", reply.Buffer.ToString())); // The data of reply - Append(state.data); + try + { + PingReply reply = ping.Send(server.server, Timeout); + state.data = new List>(); + state.data.Add(new KeyValuePair("Timestamp", timestamp)); + state.data.Add(new KeyValuePair("Server", server.FriendlyName())); + state.data.Add(new KeyValuePair("Status", reply.Status.ToString())); + state.data.Add(new KeyValuePair("RoundtripTime", reply.RoundtripTime.ToString())); + //state.data.Add(new KeyValuePair("data", reply.Buffer.ToString())); // The data of reply + Append(state.data); + } + catch (Exception e) + { + Logging.LogUsefulException(e); + } } } } From 9522d1d17b6ac52e93541d47a174ce0437a73600 Mon Sep 17 00:00:00 2001 From: Pink Floyd Date: Mon, 17 Aug 2015 17:24:35 +0800 Subject: [PATCH 04/16] Update UpdateChecker.cs Update UpdateURL --- shadowsocks-csharp/Controller/Service/UpdateChecker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index c6f65121..0ab86dd7 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -12,7 +12,7 @@ namespace Shadowsocks.Controller { public class UpdateChecker { - private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-csharp/releases"; + private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-windows/releases"; public string LatestVersionNumber; public string LatestVersionURL; From ab38538b343d200f0dc1840bf9a65ad268139306 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 19:49:49 -0700 Subject: [PATCH 05/16] allow multiple instances --- shadowsocks-csharp/Data/cn.txt | 4 ++++ shadowsocks-csharp/Program.cs | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index b4c7a6ee..751d1101 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -19,6 +19,7 @@ Update Local PAC from GFWList=从 GFWList 更新本地 PAC Edit User Rule for GFWList...=编辑 GFWList 的用户规则... Show QRCode...=显示二维码... Scan QRCode from Screen...=扫描屏幕上的二维码... +Availability Statistics=统计可用性 Show Logs...=显示日志... About...=关于... Quit=退出 @@ -72,6 +73,9 @@ Failed to update PAC file =更新 PAC 文件失败 PAC updated=更新 PAC 成功 No updates found. Please report to GFWList if you have problems with it.=未发现更新。如有问题请提交给 GFWList。 No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置 +Shadowsocks is already running.=Shadowsocks 已经在运行。 +Find Shadowsocks icon in your notify tray.=请在任务栏里寻找 Shadowsocks 图标。 +If you want to start multiple Shadowsocks, make a copy in another directory.=如果想启动多份,可以另外复制一份到别的目录。 Failed to decode QRCode=无法解析二维码 Failed to update registry=无法修改注册表 System Proxy On: =系统代理已启用: diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 8ca485d7..f840106a 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -19,7 +19,7 @@ namespace Shadowsocks static void Main() { Util.Utils.ReleaseMemory(); - using (Mutex mutex = new Mutex(false, "Global\\" + "71981632-A427-497F-AB91-241CD227EC1F")) + using (Mutex mutex = new Mutex(false, "Global\\Shadowsocks_" + Application.StartupPath.GetHashCode())) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); @@ -31,7 +31,9 @@ namespace Shadowsocks { Process oldProcess = oldProcesses[0]; } - MessageBox.Show("Shadowsocks is already running.\n\nFind Shadowsocks icon in your notify tray."); + MessageBox.Show(I18N.GetString("Find Shadowsocks icon in your notify tray.") + "\n" + + I18N.GetString("If you want to start multiple Shadowsocks, make a copy in another directory."), + I18N.GetString("Shadowsocks is already running.")); return; } Directory.SetCurrentDirectory(Application.StartupPath); From 05726cdb67e43d3e0bc7246aac0dc05e733b2ee2 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 20:00:24 -0700 Subject: [PATCH 06/16] revert part of #257 --- shadowsocks-csharp/Controller/System/SystemProxy.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/shadowsocks-csharp/Controller/System/SystemProxy.cs b/shadowsocks-csharp/Controller/System/SystemProxy.cs index 84a26d06..74e4beb4 100644 --- a/shadowsocks-csharp/Controller/System/SystemProxy.cs +++ b/shadowsocks-csharp/Controller/System/SystemProxy.cs @@ -56,18 +56,14 @@ namespace Shadowsocks.Controller pacUrl = "http://127.0.0.1:" + config.localPort.ToString() + "/pac?t=" + GetTimestamp(DateTime.Now); registry.SetValue("ProxyEnable", 0); var readProxyServer = registry.GetValue("ProxyServer"); - if (readProxyServer != null && readProxyServer.Equals("127.0.0.1:" + config.localPort.ToString())) - registry.SetValue("ProxyServer", ""); + registry.SetValue("ProxyServer", ""); registry.SetValue("AutoConfigURL", pacUrl); } } else { registry.SetValue("ProxyEnable", 0); - if (global) - { - registry.SetValue("ProxyServer", ""); - } + registry.SetValue("ProxyServer", ""); registry.SetValue("AutoConfigURL", ""); } //Set AutoDetectProxy Off From e84825c25d09047093fcdbec6b0332065c32449c Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 20:19:21 -0700 Subject: [PATCH 07/16] fix a path problem --- shadowsocks-csharp/Controller/Service/PolipoRunner.cs | 7 +++++-- shadowsocks-csharp/Controller/Service/UpdateChecker.cs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/PolipoRunner.cs b/shadowsocks-csharp/Controller/Service/PolipoRunner.cs index 261436be..9581e05f 100644 --- a/shadowsocks-csharp/Controller/Service/PolipoRunner.cs +++ b/shadowsocks-csharp/Controller/Service/PolipoRunner.cs @@ -65,10 +65,13 @@ namespace Shadowsocks.Controller polipoConfig = polipoConfig.Replace("__POLIPO_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1"); FileManager.ByteArrayToFile(temppath + "/privoxy.conf", System.Text.Encoding.UTF8.GetBytes(polipoConfig)); + if (!(temppath.EndsWith("\\") || temppath.EndsWith("/"))) { + temppath = temppath + "\\"; + } _process = new Process(); // Configure the process using the StartInfo properties. - _process.StartInfo.FileName = temppath + "/ss_privoxy.exe"; - _process.StartInfo.Arguments = " \"" + temppath + "/privoxy.conf\""; + _process.StartInfo.FileName = temppath + "ss_privoxy.exe"; + _process.StartInfo.Arguments = " \"" + temppath + "privoxy.conf\""; _process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; _process.StartInfo.UseShellExecute = true; _process.StartInfo.CreateNoWindow = true; diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index 0ab86dd7..22aa2916 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -18,7 +18,7 @@ namespace Shadowsocks.Controller public string LatestVersionURL; public event EventHandler NewVersionFound; - public const string Version = "2.5.4"; + public const string Version = "2.5.5"; public void CheckUpdate(Configuration config) { From fe692f89e1d68fefd564bffd1432d2622f237a05 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 20:46:51 +0800 Subject: [PATCH 08/16] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4dedf567..ae78f59b 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Shadowsocks for Windows [![Build Status]][Appveyor] +[中文说明] + #### Features 1. System proxy configuration @@ -59,3 +61,4 @@ GPLv3 [Build Status]: https://ci.appveyor.com/api/projects/status/gknc8l1lxy423ehv/branch/master [latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases [GFWList]: https://github.com/gfwlist/gfwlist +[中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E From 85dc46d11e4e7e7809eee795e6a68eb6b43b4932 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 20:55:01 +0800 Subject: [PATCH 09/16] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index ae78f59b..c97461fe 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,15 @@ with any editor, Shadowsocks will notify browsers about the change automatically For UDP, you need to use SocksCap or ProxyCap to force programs you want to be proxied to tunnel over Shadowsocks +#### Multiple Instances + +If you want to manage multiple servers using other tools like SwitchyOmega, +you can start multiple Shadowsocks instances. To avoid configuration conflicts, +copy Shadowsocks to a new directory and choose a different local port. + +Also, make sure to use `SOCKS5` proxy in SwitchyOmega, since we have only +one HTTP proxy instance. + #### Develop Visual Studio 2015 is required. From 3b90b2124f68cb855064e863ddd9b660602144aa Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Aug 2015 21:03:11 +0800 Subject: [PATCH 10/16] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c97461fe..54d604bf 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ copy Shadowsocks to a new directory and choose a different local port. Also, make sure to use `SOCKS5` proxy in SwitchyOmega, since we have only one HTTP proxy instance. +#### Server Configuration + +Please visit [Servers] for more information. + #### Develop Visual Studio 2015 is required. @@ -70,4 +74,5 @@ GPLv3 [Build Status]: https://ci.appveyor.com/api/projects/status/gknc8l1lxy423ehv/branch/master [latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases [GFWList]: https://github.com/gfwlist/gfwlist +[Servers]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#linux--server-side [中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E From 71bd0d2b5af0fdcedfdbbd2ef266d3f099f823ad Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 04:25:27 -0700 Subject: [PATCH 11/16] improve user experience for some users --- shadowsocks-csharp/Controller/Service/PACServer.cs | 2 +- .../Controller/ShadowsocksController.cs | 4 ++-- shadowsocks-csharp/Program.cs | 2 +- shadowsocks-csharp/Util/Util.cs | 27 +++++++++++++++++++--- shadowsocks-csharp/View/MenuViewController.cs | 2 +- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs index 038ead8c..e915681e 100644 --- a/shadowsocks-csharp/Controller/Service/PACServer.cs +++ b/shadowsocks-csharp/Controller/Service/PACServer.cs @@ -146,7 +146,7 @@ Connection: Close ", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac; byte[] response = System.Text.Encoding.UTF8.GetBytes(text); socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket); - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(true); } catch (Exception e) { diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index aac1419a..b02771f1 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -360,7 +360,7 @@ namespace Shadowsocks.Controller } UpdateSystemProxy(); - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(true); } @@ -417,7 +417,7 @@ namespace Shadowsocks.Controller { while (true) { - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(false); Thread.Sleep(30 * 1000); } } diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index f840106a..cb40cb23 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -18,7 +18,7 @@ namespace Shadowsocks [STAThread] static void Main() { - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(true); using (Mutex mutex = new Mutex(false, "Global\\Shadowsocks_" + Application.StartupPath.GetHashCode())) { Application.EnableVisualStyles(); diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index 15463a3a..004128af 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -10,7 +10,7 @@ namespace Shadowsocks.Util { public class Utils { - public static void ReleaseMemory() + public static void ReleaseMemory(bool removePages) { // release any unused pages // making the numbers look good in task manager @@ -20,8 +20,29 @@ namespace Shadowsocks.Util // which is part of user experience GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); - SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, - (UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF); + if (removePages) + { + // as some users have pointed out + // removing pages from working set will cause some IO + // which lowered user experience for another group of users + // + // so we do 2 more things here to satisfy them: + // 1. only remove pages once when configuration is changed + // 2. add more comments here to tell users that calling + // this function will not be more frequent than + // IM apps writing chat logs, or web browsers writing cache files + // if they're so concerned about their disk, they should + // uninstall all IM apps and web browsers + // + // please open an issue if you're worried about anything else in your computer + // no matter it's GPU performance, monitor contrast, audio fidelity + // or anything else in the task manager + // we'll do as much as we can to help you + // + // just kidding + SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, + (UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF); + } } public static string UnGzip(byte[] buf) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index b8c9bb81..5081ec35 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -322,7 +322,7 @@ namespace Shadowsocks.View void configForm_FormClosed(object sender, FormClosedEventArgs e) { configForm = null; - Util.Utils.ReleaseMemory(); + Util.Utils.ReleaseMemory(true); ShowFirstTimeBalloon(); } From 590322bca2b1b0b305674799901d8fe9c1c4385c Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 05:07:04 +0800 Subject: [PATCH 12/16] fix some translation --- shadowsocks-csharp/Data/cn.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 751d1101..92cc868c 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -75,8 +75,8 @@ No updates found. Please report to GFWList if you have problems with it.=未发 No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置 Shadowsocks is already running.=Shadowsocks 已经在运行。 Find Shadowsocks icon in your notify tray.=请在任务栏里寻找 Shadowsocks 图标。 -If you want to start multiple Shadowsocks, make a copy in another directory.=如果想启动多份,可以另外复制一份到别的目录。 +If you want to start multiple Shadowsocks, make a copy in another directory.=如果想同时启动多份,可以另外复制一份到别的目录。 Failed to decode QRCode=无法解析二维码 Failed to update registry=无法修改注册表 System Proxy On: =系统代理已启用: -Running: Port {0}=正在运行:端口 {0} \ No newline at end of file +Running: Port {0}=正在运行:端口 {0} From 63b31f5abaad3db3df4ae0a9913004c518906ad8 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 05:07:38 +0800 Subject: [PATCH 13/16] fix translation --- shadowsocks-csharp/Data/cn.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 92cc868c..9dc07328 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -75,7 +75,7 @@ No updates found. Please report to GFWList if you have problems with it.=未发 No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置 Shadowsocks is already running.=Shadowsocks 已经在运行。 Find Shadowsocks icon in your notify tray.=请在任务栏里寻找 Shadowsocks 图标。 -If you want to start multiple Shadowsocks, make a copy in another directory.=如果想同时启动多份,可以另外复制一份到别的目录。 +If you want to start multiple Shadowsocks, make a copy in another directory.=如果想同时启动多个,可以另外复制一份到别的目录。 Failed to decode QRCode=无法解析二维码 Failed to update registry=无法修改注册表 System Proxy On: =系统代理已启用: From f33fb04b892509854899b6603ff2e0f29d997ecf Mon Sep 17 00:00:00 2001 From: kimw Date: Tue, 18 Aug 2015 23:44:17 +0800 Subject: [PATCH 14/16] support customize the server order --- shadowsocks-csharp/Data/cn.txt | 2 + shadowsocks-csharp/View/ConfigForm.Designer.cs | 54 ++++++++++++++++++- shadowsocks-csharp/View/ConfigForm.cs | 72 +++++++++++++++++++++++--- shadowsocks-csharp/View/ConfigForm.resx | 4 +- 4 files changed, 121 insertions(+), 11 deletions(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 9dc07328..fd09606d 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -42,6 +42,8 @@ Remarks=备注 OK=确定 Cancel=取消 New server=未配置的服务器 +Move &Up=上移 +Move D&own=下移 # QRCode Form diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 83dae64a..f8b5940a 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -47,6 +47,9 @@ this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServersListBox = new System.Windows.Forms.ListBox(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel(); + this.MoveDownButton = new System.Windows.Forms.Button(); + this.MoveUpButton = new System.Windows.Forms.Button(); this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel(); this.ProxyPortTextBox = new System.Windows.Forms.TextBox(); this.ProxyPortLabel = new System.Windows.Forms.Label(); @@ -55,6 +58,7 @@ this.tableLayoutPanel1.SuspendLayout(); this.ServerGroupBox.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); + this.tableLayoutPanel6.SuspendLayout(); this.tableLayoutPanel5.SuspendLayout(); this.tableLayoutPanel3.SuspendLayout(); this.tableLayoutPanel4.SuspendLayout(); @@ -184,7 +188,7 @@ // // EncryptionSelect // - this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.EncryptionSelect.FormattingEnabled = true; @@ -281,6 +285,7 @@ // this.ServersListBox.FormattingEnabled = true; this.ServersListBox.IntegralHeight = false; + this.ServersListBox.ItemHeight = 12; this.ServersListBox.Location = new System.Drawing.Point(0, 0); this.ServersListBox.Margin = new System.Windows.Forms.Padding(0); this.ServersListBox.Name = "ServersListBox"; @@ -295,6 +300,7 @@ this.tableLayoutPanel2.ColumnCount = 2; this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel6, 0, 2); this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel5, 1, 1); this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 1, 2); this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0); @@ -310,6 +316,48 @@ this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 238); this.tableLayoutPanel2.TabIndex = 7; // + // tableLayoutPanel6 + // + this.tableLayoutPanel6.AutoSize = true; + this.tableLayoutPanel6.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel6.ColumnCount = 2; + this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel6.Controls.Add(this.MoveDownButton, 1, 0); + this.tableLayoutPanel6.Controls.Add(this.MoveUpButton, 0, 0); + this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Top; + this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 211); + this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel6.Name = "tableLayoutPanel6"; + this.tableLayoutPanel6.RowCount = 1; + this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel6.Size = new System.Drawing.Size(166, 32); + this.tableLayoutPanel6.TabIndex = 10; + // + // MoveDownButton + // + this.MoveDownButton.Dock = System.Windows.Forms.DockStyle.Right; + this.MoveDownButton.Location = new System.Drawing.Point(86, 6); + this.MoveDownButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3); + this.MoveDownButton.Name = "MoveDownButton"; + this.MoveDownButton.Size = new System.Drawing.Size(80, 23); + this.MoveDownButton.TabIndex = 7; + this.MoveDownButton.Text = "Move D&own"; + this.MoveDownButton.UseVisualStyleBackColor = true; + this.MoveDownButton.Click += new System.EventHandler(this.MoveDownButton_Click); + // + // MoveUpButton + // + this.MoveUpButton.Dock = System.Windows.Forms.DockStyle.Left; + this.MoveUpButton.Location = new System.Drawing.Point(0, 6); + this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3); + this.MoveUpButton.Name = "MoveUpButton"; + this.MoveUpButton.Size = new System.Drawing.Size(80, 23); + this.MoveUpButton.TabIndex = 6; + this.MoveUpButton.Text = "Move &Up"; + this.MoveUpButton.UseVisualStyleBackColor = true; + this.MoveUpButton.Click += new System.EventHandler(this.MoveUpButton_Click); + // // tableLayoutPanel5 // this.tableLayoutPanel5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) @@ -418,6 +466,7 @@ this.ServerGroupBox.PerformLayout(); this.tableLayoutPanel2.ResumeLayout(false); this.tableLayoutPanel2.PerformLayout(); + this.tableLayoutPanel6.ResumeLayout(false); this.tableLayoutPanel5.ResumeLayout(false); this.tableLayoutPanel5.PerformLayout(); this.tableLayoutPanel3.ResumeLayout(false); @@ -453,6 +502,9 @@ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5; private System.Windows.Forms.TextBox ProxyPortTextBox; private System.Windows.Forms.Label ProxyPortLabel; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6; + private System.Windows.Forms.Button MoveDownButton; + private System.Windows.Forms.Button MoveUpButton; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 675aa23e..edcb405e 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -51,6 +51,8 @@ namespace Shadowsocks.View ServerGroupBox.Text = I18N.GetString("Server"); OKButton.Text = I18N.GetString("OK"); MyCancelButton.Text = I18N.GetString("Cancel"); + MoveUpButton.Text = I18N.GetString("Move &Up"); + MoveDownButton.Text = I18N.GetString("Move D&own"); this.Text = I18N.GetString("Edit Servers"); } @@ -58,7 +60,7 @@ namespace Shadowsocks.View { LoadCurrentConfiguration(); } - + private void ShowWindow() { this.Opacity = 1; @@ -87,7 +89,7 @@ namespace Shadowsocks.View Configuration.CheckLocalPort(localPort); _modifiedConfiguration.configs[_oldSelectedIndex] = server; _modifiedConfiguration.localPort = localPort; - + return true; } catch (FormatException) @@ -113,12 +115,6 @@ namespace Shadowsocks.View ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString(); EncryptionSelect.Text = server.method ?? "aes-256-cfb"; RemarksTextBox.Text = server.remarks; - ServerGroupBox.Visible = true; - //IPTextBox.Focus(); - } - else - { - ServerGroupBox.Visible = false; } } @@ -141,6 +137,7 @@ namespace Shadowsocks.View _oldSelectedIndex = 0; } ServersListBox.SelectedIndex = _oldSelectedIndex; + UpdateMoveUpAndDownButton(); LoadSelectedServer(); } @@ -162,6 +159,7 @@ namespace Shadowsocks.View ServersListBox.SelectedIndex = _oldSelectedIndex; return; } + UpdateMoveUpAndDownButton(); LoadSelectedServer(); _oldSelectedIndex = ServersListBox.SelectedIndex; } @@ -208,7 +206,9 @@ namespace Shadowsocks.View MessageBox.Show(I18N.GetString("Please add at least one server")); return; } + int index = _modifiedConfiguration.index; controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort); + controller.SelectServerIndex(index); this.Close(); } @@ -227,5 +227,61 @@ namespace Shadowsocks.View controller.ConfigChanged -= controller_ConfigChanged; } + private void MoveConfigItem(int step) + { + int index = ServersListBox.SelectedIndex; + Server server = _modifiedConfiguration.configs[index]; + object item = ServersListBox.SelectedItem; + + _modifiedConfiguration.configs.Remove(server); + _modifiedConfiguration.configs.Insert(index + step, server); + _modifiedConfiguration.index += step; + + ServersListBox.BeginUpdate(); + _oldSelectedIndex = index + step; + ServersListBox.Items.Remove(item); + ServersListBox.Items.Insert(index + step, item); + ServersListBox.SelectedIndex = index + step; + ServersListBox.EndUpdate(); + + UpdateMoveUpAndDownButton(); + } + + private void UpdateMoveUpAndDownButton() + { + if (ServersListBox.SelectedIndex == 0) + { + MoveUpButton.Enabled = false; + } + else + { + MoveUpButton.Enabled = true; + } + if (ServersListBox.SelectedIndex == ServersListBox.Items.Count - 1) + { + MoveDownButton.Enabled = false; + } + else + { + MoveDownButton.Enabled = true; + } + } + + private void MoveUpButton_Click(object sender, EventArgs e) + { + if (ServersListBox.SelectedIndex > 0) + { + MoveConfigItem(-1); // -1 means move backward + } + } + + private void MoveDownButton_Click(object sender, EventArgs e) + { + if (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1) + { + MoveConfigItem(+1); // +1 means move forward + } + } + } } diff --git a/shadowsocks-csharp/View/ConfigForm.resx b/shadowsocks-csharp/View/ConfigForm.resx index ff31a6db..c7e0d4bd 100755 --- a/shadowsocks-csharp/View/ConfigForm.resx +++ b/shadowsocks-csharp/View/ConfigForm.resx @@ -112,9 +112,9 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 \ No newline at end of file From 3bc77d212a711d9482a864b49eae59203a79340b Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 20:58:53 -0700 Subject: [PATCH 15/16] reduce cache size --- shadowsocks-csharp/Controller/Service/TCPRelay.cs | 22 +++++- shadowsocks-csharp/Encryption/SodiumEncryptor.cs | 86 ++++++++++++----------- 2 files changed, 65 insertions(+), 43 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 5c9de444..3fc27e39 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -14,9 +14,16 @@ namespace Shadowsocks.Controller class TCPRelay : Listener.Service { private ShadowsocksController _controller; + + public ISet Handlers + { + get; set; + } + public TCPRelay(ShadowsocksController controller) { this._controller = controller; + this.Handlers = new HashSet(); } public bool Handle(byte[] firstPacket, int length, Socket socket, object state) @@ -33,8 +40,14 @@ namespace Shadowsocks.Controller Handler handler = new Handler(); handler.connection = socket; handler.controller = _controller; + handler.relay = this; handler.Start(firstPacket, length); + lock (this.Handlers) + { + this.Handlers.Add(handler); + Logging.Debug($"connections: {Handlers.Count}"); + } return true; } } @@ -48,6 +61,8 @@ namespace Shadowsocks.Controller public Socket remote; public Socket connection; public ShadowsocksController controller; + public TCPRelay relay; + private int retryCount = 0; private bool connected; @@ -55,7 +70,7 @@ namespace Shadowsocks.Controller private byte[] _firstPacket; private int _firstPacketLength; // Size of receive buffer. - public const int RecvSize = 16384; + public const int RecvSize = 8192; public const int BufferSize = RecvSize + 32; private int totalRead = 0; @@ -108,6 +123,11 @@ namespace Shadowsocks.Controller public void Close() { + lock (relay.Handlers) + { + Logging.Debug($"connections: {relay.Handlers.Count}"); + relay.Handlers.Remove(this); + } lock (this) { if (closed) diff --git a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs index 5d6165eb..af51d0ac 100755 --- a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs +++ b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; namespace Shadowsocks.Encryption { @@ -12,19 +13,17 @@ namespace Shadowsocks.Encryption const int SODIUM_BLOCK_SIZE = 64; + static byte[] sodiumBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; + protected int _encryptBytesRemaining; protected int _decryptBytesRemaining; protected ulong _encryptIC; protected ulong _decryptIC; - protected byte[] _encryptBuf; - protected byte[] _decryptBuf; public SodiumEncryptor(string method, string password) : base(method, password) { InitKey(method, password); - _encryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; - _decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; } private static Dictionary _ciphers = new Dictionary { @@ -47,48 +46,51 @@ namespace Shadowsocks.Encryption // TODO write a unidirection cipher so we don't have to if if if int bytesRemaining; ulong ic; - byte[] sodiumBuf; byte[] iv; - if (isCipher) - { - bytesRemaining = _encryptBytesRemaining; - ic = _encryptIC; - sodiumBuf = _encryptBuf; - iv = _encryptIV; - } - else - { - bytesRemaining = _decryptBytesRemaining; - ic = _decryptIC; - sodiumBuf = _decryptBuf; - iv = _decryptIV; - } - int padding = bytesRemaining; - Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length); - switch (_cipher) + // I'm tired. just add a big lock + // let's optimize for RAM instead of CPU + lock(sodiumBuf) { - case CIPHER_SALSA20: - Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); - break; - case CIPHER_CHACHA20: - Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); - break; - } - Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length); - padding += length; - ic += (ulong)padding / SODIUM_BLOCK_SIZE; - bytesRemaining = padding % SODIUM_BLOCK_SIZE; + if (isCipher) + { + bytesRemaining = _encryptBytesRemaining; + ic = _encryptIC; + iv = _encryptIV; + } + else + { + bytesRemaining = _decryptBytesRemaining; + ic = _decryptIC; + iv = _decryptIV; + } + int padding = bytesRemaining; + Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length); - if (isCipher) - { - _encryptBytesRemaining = bytesRemaining; - _encryptIC = ic; - } - else - { - _decryptBytesRemaining = bytesRemaining; - _decryptIC = ic; + switch (_cipher) + { + case CIPHER_SALSA20: + Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); + break; + case CIPHER_CHACHA20: + Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); + break; + } + Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length); + padding += length; + ic += (ulong)padding / SODIUM_BLOCK_SIZE; + bytesRemaining = padding % SODIUM_BLOCK_SIZE; + + if (isCipher) + { + _encryptBytesRemaining = bytesRemaining; + _encryptIC = ic; + } + else + { + _decryptBytesRemaining = bytesRemaining; + _decryptIC = ic; + } } } From 750ee4fa5ffb2e7dd63f675438e6296333410553 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 18 Aug 2015 21:31:50 -0700 Subject: [PATCH 16/16] add handler timeout --- shadowsocks-csharp/Controller/Service/TCPRelay.cs | 26 ++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 3fc27e39..667a11a6 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -14,6 +14,7 @@ namespace Shadowsocks.Controller class TCPRelay : Listener.Service { private ShadowsocksController _controller; + private DateTime _lastSweepTime; public ISet Handlers { @@ -24,6 +25,7 @@ namespace Shadowsocks.Controller { this._controller = controller; this.Handlers = new HashSet(); + this._lastSweepTime = DateTime.Now; } public bool Handle(byte[] firstPacket, int length, Socket socket, object state) @@ -43,12 +45,30 @@ namespace Shadowsocks.Controller handler.relay = this; handler.Start(firstPacket, length); + IList handlersToClose = new List(); lock (this.Handlers) { this.Handlers.Add(handler); Logging.Debug($"connections: {Handlers.Count}"); + DateTime now = DateTime.Now; + if (now - _lastSweepTime > TimeSpan.FromSeconds(1)) + { + _lastSweepTime = now; + foreach (Handler handler1 in this.Handlers) + { + if (now - handler1.lastActivity > TimeSpan.FromSeconds(1800)) + { + handlersToClose.Add(handler1); + } + } + } + } + foreach (Handler handler1 in handlersToClose) + { + Logging.Debug("Closing timed out connection"); + handler1.Close(); } - return true; + return true; } } @@ -63,6 +83,8 @@ namespace Shadowsocks.Controller public ShadowsocksController controller; public TCPRelay relay; + public DateTime lastActivity; + private int retryCount = 0; private bool connected; @@ -111,6 +133,7 @@ namespace Shadowsocks.Controller this._firstPacket = firstPacket; this._firstPacketLength = length; this.HandshakeReceive(); + this.lastActivity = DateTime.Now; } private void CheckClose() @@ -505,6 +528,7 @@ namespace Shadowsocks.Controller if (bytesRead > 0) { + this.lastActivity = DateTime.Now; int bytesToSend; lock (decryptionLock) {