From 492869fd5c9e423957a54aa606f24d6ea7541078 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 11:56:30 +0800 Subject: [PATCH 01/20] move log to temp path --- shadowsocks-csharp/Controller/Logging.cs | 34 ++++++++++++++++++++++++++ shadowsocks-csharp/Program.cs | 14 +---------- shadowsocks-csharp/View/ConfigForm.Designer.cs | 15 +++++++++--- shadowsocks-csharp/View/ConfigForm.cs | 7 ++++++ shadowsocks-csharp/shadowsocks-csharp.csproj | 1 + 5 files changed, 55 insertions(+), 16 deletions(-) create mode 100755 shadowsocks-csharp/Controller/Logging.cs diff --git a/shadowsocks-csharp/Controller/Logging.cs b/shadowsocks-csharp/Controller/Logging.cs new file mode 100755 index 00000000..58a994f5 --- /dev/null +++ b/shadowsocks-csharp/Controller/Logging.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Shadowsocks.Controller +{ + public class Logging + { + public static string LogFile; + + public static bool OpenLogFile() + { + try + { + string temppath = Path.GetTempPath(); + LogFile = Path.Combine(temppath, "shadowsocks.log"); + FileStream fs = new FileStream(LogFile, FileMode.Append); + TextWriter tmp = Console.Out; + StreamWriter sw = new StreamWriter(fs); + sw.AutoFlush = true; + Console.SetOut(sw); + Console.SetError(sw); + + return true; + } + catch (IOException e) + { + Console.WriteLine(e.ToString()); + return false; + } + } + } +} diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 516bdf80..a42a97ae 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -47,19 +47,7 @@ namespace Shadowsocks } LoadLibrary(dllPath); - try - { - FileStream fs = new FileStream("shadowsocks.log", FileMode.Append); - TextWriter tmp = Console.Out; - StreamWriter sw = new StreamWriter(fs); - sw.AutoFlush = true; - Console.SetOut(sw); - Console.SetError(sw); - } - catch (IOException e) - { - Console.WriteLine(e.ToString()); - } + Logging.OpenLogFile(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShadowsocksController controller = new ShadowsocksController(); diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index b2d20a84..7fb5c9a5 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -64,6 +64,7 @@ this.AddButton = new System.Windows.Forms.Button(); this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServersListBox = new System.Windows.Forms.ListBox(); + this.ShowLogItem = new System.Windows.Forms.MenuItem(); this.tableLayoutPanel1.SuspendLayout(); this.panel1.SuspendLayout(); this.panel3.SuspendLayout(); @@ -289,6 +290,7 @@ this.menuItem4, this.editPACFileItem, this.QRCodeItem, + this.ShowLogItem, this.aboutItem, this.menuItem3, this.quitItem}); @@ -337,18 +339,18 @@ // // aboutItem // - this.aboutItem.Index = 5; + this.aboutItem.Index = 6; this.aboutItem.Text = "About..."; this.aboutItem.Click += new System.EventHandler(this.AboutItem_Click); // // menuItem3 // - this.menuItem3.Index = 6; + this.menuItem3.Index = 7; this.menuItem3.Text = "-"; // // quitItem // - this.quitItem.Index = 7; + this.quitItem.Index = 8; this.quitItem.Text = "&Quit"; this.quitItem.Click += new System.EventHandler(this.Quit_Click); // @@ -402,6 +404,12 @@ this.ServersListBox.TabIndex = 5; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // + // ShowLogItem + // + this.ShowLogItem.Index = 5; + this.ShowLogItem.Text = "Show Logs..."; + this.ShowLogItem.Click += new System.EventHandler(this.ShowLogItem_Click); + // // ConfigForm // this.AcceptButton = this.OKButton; @@ -471,6 +479,7 @@ private System.Windows.Forms.TextBox RemarksTextBox; private System.Windows.Forms.Label label6; private System.Windows.Forms.MenuItem QRCodeItem; + private System.Windows.Forms.MenuItem ShowLogItem; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 51079ed9..9ba3d032 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -298,6 +298,13 @@ namespace Shadowsocks.View controller.SaveConfig(configuration); } + private void ShowLogItem_Click(object sender, EventArgs e) + { + string argument = Logging.LogFile; + + System.Diagnostics.Process.Start("notepad.exe", argument); + } + private void ConfigForm_Shown(object sender, EventArgs e) { IPTextBox.Focus(); diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index c1c08d22..ab31982a 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -68,6 +68,7 @@ + From e4ff27a1fc1787983d150a43573227f679c685c0 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 13:31:33 +0800 Subject: [PATCH 02/20] share over LAN --- shadowsocks-csharp/Controller/Local.cs | 44 +++++++-------- shadowsocks-csharp/Controller/PACServer.cs | 63 +++++++++++++++------- shadowsocks-csharp/Controller/PolipoRunner.cs | 9 ++-- .../Controller/ShadowsocksController.cs | 24 +++++++-- shadowsocks-csharp/Data/polipo_config.txt | 2 +- shadowsocks-csharp/Model/Configuration.cs | 1 + shadowsocks-csharp/View/ConfigForm.Designer.cs | 37 ++++++++----- shadowsocks-csharp/View/ConfigForm.cs | 13 +++++ 8 files changed, 124 insertions(+), 69 deletions(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index cace2f57..baf535c3 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -11,12 +11,14 @@ namespace Shadowsocks.Controller class Local { - private Server config; + private Server _server; + private bool _shareOverLAN; //private Encryptor encryptor; Socket _listener; - public Local(Server config) + public Local(Configuration config) { - this.config = config; + this._server = config.GetCurrentServer(); + _shareOverLAN = config.shareOverLan; //this.encryptor = new Encryptor(config.method, config.password); } @@ -25,9 +27,17 @@ namespace Shadowsocks.Controller try { // Create a TCP/IP socket. - _listener = new Socket(AddressFamily.InterNetwork, - SocketType.Stream, ProtocolType.Tcp); - IPEndPoint localEndPoint = new IPEndPoint(0, config.local_port); + _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + IPEndPoint localEndPoint = null; + if (_shareOverLAN) + { + localEndPoint = new IPEndPoint(IPAddress.Any, _server.local_port); + } + else + { + localEndPoint = new IPEndPoint(IPAddress.Loopback, _server.local_port); + } // Bind the socket to the local endpoint and listen for incoming connections. _listener.Bind(localEndPoint); @@ -58,37 +68,19 @@ namespace Shadowsocks.Controller { try { - - // Get the socket that handles the client request. Socket listener = (Socket)ar.AsyncState; - //if (!listener.Connected) - //{ - // return; - //} - Socket conn = listener.EndAccept(ar); listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); - // Create the state object. Handler handler = new Handler(); handler.connection = conn; - //if (encryptor.method == "table") - //{ - // handler.encryptor = encryptor; - //} - //else - //{ - // handler.encryptor = new Encryptor(config.method, config.password); - //} - handler.encryptor = EncryptorFactory.GetEncryptor(config.method, config.password); - handler.config = config; + handler.encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); + handler.config = _server; handler.Start(); - //handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, - // new AsyncCallback(ReadCallback), state); } catch { diff --git a/shadowsocks-csharp/Controller/PACServer.cs b/shadowsocks-csharp/Controller/PACServer.cs index eab2ff60..422089dc 100755 --- a/shadowsocks-csharp/Controller/PACServer.cs +++ b/shadowsocks-csharp/Controller/PACServer.cs @@ -1,4 +1,5 @@ -using Shadowsocks.Properties; +using Shadowsocks.Model; +using Shadowsocks.Properties; using System; using System.Collections.Generic; using System.Diagnostics; @@ -12,28 +13,51 @@ namespace Shadowsocks.Controller { class PACServer { + private static int PORT = 8090; private static string PAC_FILE = "pac.txt"; - Socket listener; + Socket _listener; FileSystemWatcher watcher; public event EventHandler PACFileChanged; - public void Start() + public void Start(Configuration configuration) { - // Create a TCP/IP socket. - listener = new Socket(AddressFamily.InterNetwork, - SocketType.Stream, ProtocolType.Tcp); - IPEndPoint localEndPoint = new IPEndPoint(0, 8090); - - // Bind the socket to the local endpoint and listen for incoming connections. - listener.Bind(localEndPoint); - listener.Listen(100); - listener.BeginAccept( - new AsyncCallback(AcceptCallback), - listener); - - WatchPacFile(); + try + { + // Create a TCP/IP socket. + _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + IPEndPoint localEndPoint = null; + if (configuration.shareOverLan) + { + localEndPoint = new IPEndPoint(IPAddress.Any, PORT); + } + else + { + localEndPoint = new IPEndPoint(IPAddress.Loopback, PORT); + } + + // Bind the socket to the local endpoint and listen for incoming connections. + _listener.Bind(localEndPoint); + _listener.Listen(100); + _listener.BeginAccept( + new AsyncCallback(AcceptCallback), + _listener); + + WatchPacFile(); + } + catch (SocketException) + { + _listener.Close(); + throw; + } + } + + public void Stop() + { + _listener.Close(); + _listener = null; } public string TouchPACFile() @@ -55,10 +79,10 @@ namespace Shadowsocks.Controller try { Socket listener = (Socket)ar.AsyncState; + Socket conn = listener.EndAccept(ar); listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); - Socket conn = listener.EndAccept(ar); conn.BeginReceive(new byte[1024], 0, 1024, 0, new AsyncCallback(ReceiveCallback), conn); @@ -92,7 +116,6 @@ namespace Shadowsocks.Controller return System.Text.Encoding.UTF8.GetString(buffer, 0, n); } } - WatchPacFile(); } private void ReceiveCallback(IAsyncResult ar) @@ -104,7 +127,9 @@ namespace Shadowsocks.Controller string pac = GetPACContent(); - string proxy = "PROXY 127.0.0.1:8123;"; + IPEndPoint localEndPoint = (IPEndPoint)conn.LocalEndPoint; + + string proxy = "PROXY " + localEndPoint.Address + ":8123;"; pac = pac.Replace("__PROXY__", proxy); diff --git a/shadowsocks-csharp/Controller/PolipoRunner.cs b/shadowsocks-csharp/Controller/PolipoRunner.cs index 9f3c2187..f940a3c5 100755 --- a/shadowsocks-csharp/Controller/PolipoRunner.cs +++ b/shadowsocks-csharp/Controller/PolipoRunner.cs @@ -13,8 +13,9 @@ namespace Shadowsocks.Controller { private Process _process; - public void Start(Server config) + public void Start(Configuration configuration) { + Server server = configuration.GetCurrentServer(); if (_process == null) { Process[] existingPolipo = Process.GetProcessesByName("ss_polipo"); @@ -31,8 +32,9 @@ namespace Shadowsocks.Controller } } string temppath = Path.GetTempPath(); - string polipoConfig = Resources.polipo_config; - polipoConfig = polipoConfig.Replace("__SOCKS_PORT__", config.local_port.ToString()); + string polipoConfig = Resources.polipo_config; + polipoConfig = polipoConfig.Replace("__SOCKS_PORT__", server.local_port.ToString()); + polipoConfig = polipoConfig.Replace("__POLIPO_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1"); FileManager.ByteArrayToFile(temppath + "/polipo.conf", System.Text.Encoding.UTF8.GetBytes(polipoConfig)); FileManager.UncompressFile(temppath + "/ss_polipo.exe", Resources.polipo_exe); @@ -45,7 +47,6 @@ namespace Shadowsocks.Controller _process.StartInfo.CreateNoWindow = true; _process.StartInfo.RedirectStandardOutput = true; _process.StartInfo.RedirectStandardError = true; - //process.StandardOutput _process.Start(); } } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 5af0bf38..b7e09b6b 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; namespace Shadowsocks.Controller { @@ -25,6 +26,7 @@ namespace Shadowsocks.Controller public event EventHandler ConfigChanged; public event EventHandler EnableStatusChanged; + public event EventHandler ShareOverLANStatusChanged; // when user clicked Edit PAC, and PAC file has already created public event EventHandler PACFileReadyToOpen; @@ -33,14 +35,14 @@ namespace Shadowsocks.Controller { _config = Configuration.Load(); polipoRunner = new PolipoRunner(); - polipoRunner.Start(_config.GetCurrentServer()); - local = new Local(_config.GetCurrentServer()); + polipoRunner.Start(_config); + local = new Local(_config); try { local.Start(); pacServer = new PACServer(); pacServer.PACFileChanged += pacServer_PACFileChanged; - pacServer.Start(); + pacServer.Start(_config); } catch (Exception e) { @@ -58,9 +60,9 @@ namespace Shadowsocks.Controller local.Stop(); polipoRunner.Stop(); - polipoRunner.Start(_config.GetCurrentServer()); + polipoRunner.Start(_config); - local = new Local(_config.GetCurrentServer()); + local = new Local(_config); local.Start(); if (ConfigChanged != null) @@ -92,6 +94,18 @@ namespace Shadowsocks.Controller } } + public void ToggleShareOverLAN(bool enabled) + { + _config.shareOverLan = enabled; + SaveConfig(_config); + pacServer.Stop(); + pacServer.Start(_config); + if (ShareOverLANStatusChanged != null) + { + ShareOverLANStatusChanged(this, new EventArgs()); + } + } + public void Stop() { if (stopped) diff --git a/shadowsocks-csharp/Data/polipo_config.txt b/shadowsocks-csharp/Data/polipo_config.txt index 7f75652b..fc500543 100755 --- a/shadowsocks-csharp/Data/polipo_config.txt +++ b/shadowsocks-csharp/Data/polipo_config.txt @@ -1,4 +1,4 @@ -proxyAddress = "127.0.0.1" +proxyAddress = "__POLIPO_BIND_IP__" socksParentProxy = "127.0.0.1:__SOCKS_PORT__" socksProxyType = socks5 diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index c45bb9f4..65b0a3b6 100755 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -15,6 +15,7 @@ namespace Shadowsocks.Model public List configs; public int index; public bool enabled; + public bool shareOverLan; public bool isDefault; private static string CONFIG_FILE = "gui-config.json"; diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index 7fb5c9a5..d01fc436 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -50,12 +50,14 @@ this.panel1 = new System.Windows.Forms.Panel(); this.contextMenu1 = new System.Windows.Forms.ContextMenu(); this.enableItem = new System.Windows.Forms.MenuItem(); + this.ShareOverLANItem = new System.Windows.Forms.MenuItem(); this.ServersItem = new System.Windows.Forms.MenuItem(); this.SeperatorItem = new System.Windows.Forms.MenuItem(); this.ConfigItem = new System.Windows.Forms.MenuItem(); this.menuItem4 = new System.Windows.Forms.MenuItem(); this.editPACFileItem = new System.Windows.Forms.MenuItem(); this.QRCodeItem = new System.Windows.Forms.MenuItem(); + this.ShowLogItem = new System.Windows.Forms.MenuItem(); this.aboutItem = new System.Windows.Forms.MenuItem(); this.menuItem3 = new System.Windows.Forms.MenuItem(); this.quitItem = new System.Windows.Forms.MenuItem(); @@ -64,7 +66,6 @@ this.AddButton = new System.Windows.Forms.Button(); this.ServerGroupBox = new System.Windows.Forms.GroupBox(); this.ServersListBox = new System.Windows.Forms.ListBox(); - this.ShowLogItem = new System.Windows.Forms.MenuItem(); this.tableLayoutPanel1.SuspendLayout(); this.panel1.SuspendLayout(); this.panel3.SuspendLayout(); @@ -286,6 +287,7 @@ // this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.enableItem, + this.ShareOverLANItem, this.ServersItem, this.menuItem4, this.editPACFileItem, @@ -301,9 +303,15 @@ this.enableItem.Text = "&Enable"; this.enableItem.Click += new System.EventHandler(this.EnableItem_Click); // + // ShareOverLANItem + // + this.ShareOverLANItem.Index = 1; + this.ShareOverLANItem.Text = "Share over LAN"; + this.ShareOverLANItem.Click += new System.EventHandler(this.ShareOverLANItem_Click); + // // ServersItem // - this.ServersItem.Index = 1; + this.ServersItem.Index = 2; this.ServersItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.SeperatorItem, this.ConfigItem}); @@ -322,35 +330,41 @@ // // menuItem4 // - this.menuItem4.Index = 2; + this.menuItem4.Index = 3; this.menuItem4.Text = "-"; // // editPACFileItem // - this.editPACFileItem.Index = 3; + this.editPACFileItem.Index = 4; this.editPACFileItem.Text = "Edit &PAC File..."; this.editPACFileItem.Click += new System.EventHandler(this.EditPACFileItem_Click); // // QRCodeItem // - this.QRCodeItem.Index = 4; + this.QRCodeItem.Index = 5; this.QRCodeItem.Text = "Show &QRCode..."; this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click); // + // ShowLogItem + // + this.ShowLogItem.Index = 6; + this.ShowLogItem.Text = "Show Logs..."; + this.ShowLogItem.Click += new System.EventHandler(this.ShowLogItem_Click); + // // aboutItem // - this.aboutItem.Index = 6; + this.aboutItem.Index = 7; this.aboutItem.Text = "About..."; this.aboutItem.Click += new System.EventHandler(this.AboutItem_Click); // // menuItem3 // - this.menuItem3.Index = 7; + this.menuItem3.Index = 8; this.menuItem3.Text = "-"; // // quitItem // - this.quitItem.Index = 8; + this.quitItem.Index = 9; this.quitItem.Text = "&Quit"; this.quitItem.Click += new System.EventHandler(this.Quit_Click); // @@ -404,12 +418,6 @@ this.ServersListBox.TabIndex = 5; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // - // ShowLogItem - // - this.ShowLogItem.Index = 5; - this.ShowLogItem.Text = "Show Logs..."; - this.ShowLogItem.Click += new System.EventHandler(this.ShowLogItem_Click); - // // ConfigForm // this.AcceptButton = this.OKButton; @@ -480,6 +488,7 @@ private System.Windows.Forms.Label label6; private System.Windows.Forms.MenuItem QRCodeItem; private System.Windows.Forms.MenuItem ShowLogItem; + private System.Windows.Forms.MenuItem ShareOverLANItem; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 9ba3d032..dfaf4b36 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -28,6 +28,7 @@ namespace Shadowsocks.View controller.EnableStatusChanged += controller_EnableStatusChanged; controller.ConfigChanged += controller_ConfigChanged; controller.PACFileReadyToOpen += controller_PACFileReadyToOpen; + controller.ShareOverLANStatusChanged += controller_ShareOverLANStatusChanged; LoadCurrentConfiguration(); } @@ -42,6 +43,11 @@ namespace Shadowsocks.View enableItem.Checked = controller.GetConfiguration().enabled; } + void controller_ShareOverLANStatusChanged(object sender, EventArgs e) + { + ShareOverLANItem.Checked = controller.GetConfiguration().shareOverLan; + } + void controller_PACFileReadyToOpen(object sender, ShadowsocksController.PathEventArgs e) { string argument = @"/select, " + e.Path; @@ -129,6 +135,7 @@ namespace Shadowsocks.View UpdateServersMenu(); enableItem.Checked = modifiedConfiguration.enabled; + ShareOverLANItem.Checked = modifiedConfiguration.shareOverLan; } private void UpdateServersMenu() @@ -285,6 +292,12 @@ namespace Shadowsocks.View controller.ToggleEnable(enableItem.Checked); } + private void ShareOverLANItem_Click(object sender, EventArgs e) + { + ShareOverLANItem.Checked = !ShareOverLANItem.Checked; + controller.ToggleShareOverLAN(ShareOverLANItem.Checked); + } + private void EditPACFileItem_Click(object sender, EventArgs e) { controller.TouchPACFile(); From 59502c1984071ac0b73c2a5c08bdaa1556e87d26 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 13:50:49 +0800 Subject: [PATCH 03/20] fix UseShellExecute problem --- shadowsocks-csharp/Controller/PolipoRunner.cs | 6 +++--- shadowsocks-csharp/Controller/ShadowsocksController.cs | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/shadowsocks-csharp/Controller/PolipoRunner.cs b/shadowsocks-csharp/Controller/PolipoRunner.cs index f940a3c5..de1c3c3a 100755 --- a/shadowsocks-csharp/Controller/PolipoRunner.cs +++ b/shadowsocks-csharp/Controller/PolipoRunner.cs @@ -43,10 +43,10 @@ namespace Shadowsocks.Controller _process.StartInfo.FileName = temppath + "/ss_polipo.exe"; _process.StartInfo.Arguments = "-c \"" + temppath + "/polipo.conf\""; _process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; - _process.StartInfo.UseShellExecute = false; + _process.StartInfo.UseShellExecute = true; _process.StartInfo.CreateNoWindow = true; - _process.StartInfo.RedirectStandardOutput = true; - _process.StartInfo.RedirectStandardError = true; + //_process.StartInfo.RedirectStandardOutput = true; + //_process.StartInfo.RedirectStandardError = true; _process.Start(); } } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index b7e09b6b..43af496a 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -58,12 +58,19 @@ namespace Shadowsocks.Controller // some logic in configuration updated the config when saving, we need to read it again _config = Configuration.Load(); + pacServer.Stop(); local.Stop(); + + // don't put polipoRunner.Start() before pacServer.Stop() + // or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1 + // though UseShellExecute is set to true now + // http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open polipoRunner.Stop(); polipoRunner.Start(_config); local = new Local(_config); local.Start(); + pacServer.Start(_config); if (ConfigChanged != null) { @@ -98,8 +105,6 @@ namespace Shadowsocks.Controller { _config.shareOverLan = enabled; SaveConfig(_config); - pacServer.Stop(); - pacServer.Start(_config); if (ShareOverLANStatusChanged != null) { ShareOverLANStatusChanged(this, new EventArgs()); From 7faf2c992b3e1849a567c7fed09bfda5ce629a5a Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 14:01:26 +0800 Subject: [PATCH 04/20] do not expose SaveConfig to Views --- .../Controller/ShadowsocksController.cs | 65 +++++++++++++--------- shadowsocks-csharp/View/ConfigForm.Designer.cs | 2 +- shadowsocks-csharp/View/ConfigForm.cs | 6 +- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 43af496a..e6e80d05 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -52,32 +52,6 @@ namespace Shadowsocks.Controller UpdateSystemProxy(); } - public void SaveConfig(Configuration newConfig) - { - Configuration.Save(newConfig); - // some logic in configuration updated the config when saving, we need to read it again - _config = Configuration.Load(); - - pacServer.Stop(); - local.Stop(); - - // don't put polipoRunner.Start() before pacServer.Stop() - // or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1 - // though UseShellExecute is set to true now - // http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open - polipoRunner.Stop(); - polipoRunner.Start(_config); - - local = new Local(_config); - local.Start(); - pacServer.Start(_config); - - if (ConfigChanged != null) - { - ConfigChanged(this, new EventArgs()); - } - } - public Server GetCurrentServer() { return _config.GetCurrentServer(); @@ -89,6 +63,11 @@ namespace Shadowsocks.Controller return Configuration.Load(); } + public void SaveServers(List servers) + { + _config.configs = servers; + SaveConfig(_config); + } public void ToggleEnable(bool enabled) { @@ -111,6 +90,12 @@ namespace Shadowsocks.Controller } } + public void SelectServerIndex(int index) + { + _config.index = index; + SaveConfig(_config); + } + public void Stop() { if (stopped) @@ -143,6 +128,34 @@ namespace Shadowsocks.Controller return "ss://" + base64; } + + protected void SaveConfig(Configuration newConfig) + { + Configuration.Save(newConfig); + // some logic in configuration updated the config when saving, we need to read it again + _config = Configuration.Load(); + + pacServer.Stop(); + local.Stop(); + + // don't put polipoRunner.Start() before pacServer.Stop() + // or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1 + // though UseShellExecute is set to true now + // http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open + polipoRunner.Stop(); + polipoRunner.Start(_config); + + local = new Local(_config); + local.Start(); + pacServer.Start(_config); + + if (ConfigChanged != null) + { + ConfigChanged(this, new EventArgs()); + } + } + + private void UpdateSystemProxy() { if (_config.enabled) diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index d01fc436..cf874286 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -436,7 +436,7 @@ this.MaximizeBox = false; this.Name = "ConfigForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Shadowsocks"; + this.Text = "Edit Servers"; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ConfigForm_FormClosed); this.Load += new System.EventHandler(this.ConfigForm_Load); this.Shown += new System.EventHandler(this.ConfigForm_Shown); diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index dfaf4b36..2a7e5db2 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -258,7 +258,7 @@ namespace Shadowsocks.View MessageBox.Show("Please add at least one server"); return; } - controller.SaveConfig(modifiedConfiguration); + controller.SaveServers(modifiedConfiguration.configs); this.Hide(); ShowFirstTimeBalloon(); } @@ -306,9 +306,7 @@ namespace Shadowsocks.View private void AServerItem_Click(object sender, EventArgs e) { MenuItem item = (MenuItem)sender; - Configuration configuration = controller.GetConfiguration(); - configuration.index = (int)item.Tag; - controller.SaveConfig(configuration); + controller.SelectServerIndex((int)item.Tag); } private void ShowLogItem_Click(object sender, EventArgs e) From 40efee471d6c6340508691078137195a33730d3d Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 14:57:58 +0800 Subject: [PATCH 05/20] refine qrcode --- shadowsocks-csharp/View/QRCodeForm.cs | 60 ++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index 0a0ec840..a7b42daf 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -25,35 +25,51 @@ namespace Shadowsocks.View private void GenQR(string ssconfig) { string qrText = ssconfig; - QRCode4CS.QRCode qrCoded = new QRCode4CS.QRCode(6, QRErrorCorrectLevel.H); - qrCoded.AddData(qrText); - qrCoded.Make(); - int blockSize = 5; - Bitmap drawArea = new Bitmap((qrCoded.GetModuleCount() * blockSize), (qrCoded.GetModuleCount() * blockSize)); - for (int row = 0; row < qrCoded.GetModuleCount(); row++) + QRCode4CS.Options options = new QRCode4CS.Options(); + options.Text = qrText; + QRCode4CS.QRCode qrCoded = null; + bool success = false; + foreach (var level in new QRErrorCorrectLevel[]{QRErrorCorrectLevel.H, QRErrorCorrectLevel.Q, QRErrorCorrectLevel.M, QRErrorCorrectLevel.L}) { - for (int col = 0; col < qrCoded.GetModuleCount(); col++) + for (int i = 3; i < 10; i++) { - bool isDark = qrCoded.IsDark(row, col); - if (isDark) + try { - for (int y = 0; y < blockSize; y++) - { - int myCol = (blockSize * (col - 1)) + (y + blockSize); - for (int x = 0; x < blockSize; x++) - { - drawArea.SetPixel((blockSize * (row - 1)) + (x + blockSize), myCol, Color.Black); - } - } + options.TypeNumber = i; + options.CorrectLevel = level; + qrCoded = new QRCode4CS.QRCode(options); + qrCoded.Make(); + success = true; + break; + } + catch + { + qrCoded = null; + continue; } - else + } + if (success) + break; + } + if (qrCoded == null) + { + return; + } + int blockSize = Math.Max(200 / qrCoded.GetModuleCount(), 1); + Bitmap drawArea = new Bitmap((qrCoded.GetModuleCount() * blockSize), (qrCoded.GetModuleCount() * blockSize)); + using (Graphics g = Graphics.FromImage(drawArea)) + { + g.Clear(Color.White); + using (Brush b = new SolidBrush(Color.Black)) + { + for (int row = 0; row < qrCoded.GetModuleCount(); row++) { - for (int y = 0; y < blockSize; y++) + for (int col = 0; col < qrCoded.GetModuleCount(); col++) { - int myCol = (blockSize * (col - 1)) + (y + blockSize); - for (int x = 0; x < blockSize; x++) + bool isDark = qrCoded.IsDark(row, col); + if (isDark) { - drawArea.SetPixel((blockSize * (row - 1)) + (x + blockSize), myCol, Color.White); + g.FillRectangle(b, blockSize * row, blockSize * col, blockSize, blockSize); } } } From 212cf6b11aed9f814f54ae0aec963d04730e53f3 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 15:02:03 +0800 Subject: [PATCH 06/20] lint code --- shadowsocks-csharp/View/QRCodeForm.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index a7b42daf..12c5b6fd 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -66,8 +66,7 @@ namespace Shadowsocks.View { for (int col = 0; col < qrCoded.GetModuleCount(); col++) { - bool isDark = qrCoded.IsDark(row, col); - if (isDark) + if (qrCoded.IsDark(row, col)) { g.FillRectangle(b, blockSize * row, blockSize * col, blockSize, blockSize); } From 08ee6172bdd52ab6d31801d3ee1f57d0093fea82 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 15:40:12 +0800 Subject: [PATCH 07/20] update CHANGES --- CHANGES | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index b7838460..0a52a4a2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,12 +1,17 @@ -2.0.4 +2.0.5 2014-11-09 +- Fix QRCode size +- Share over LAN option +- Log to temp path instead + +2.0.4 2014-11-09 - Try to fix data corruption - Remove all configuration except x86 -2.0.3 +2.0.3 2014-11-08 - Support QRCode generation - Fix compatibility issues with some Chrome version -2.0.2 +2.0.2 2014-11-08 - Add remarks - Fix error when polipo is killed From 0bcf4324d22113d9604e5c7d3ef472a00a030b7f Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 15:42:03 +0800 Subject: [PATCH 08/20] bump --- shadowsocks-csharp/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Properties/AssemblyInfo.cs b/shadowsocks-csharp/Properties/AssemblyInfo.cs index 02c3eba7..7351ffd1 100755 --- a/shadowsocks-csharp/Properties/AssemblyInfo.cs +++ b/shadowsocks-csharp/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, // 方法是按如下所示使用“*”: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.4")] +[assembly: AssemblyVersion("2.0.5")] // [assembly: AssemblyFileVersion("2.0.0")] From e0780c0ff80afd970b161fda20806da029910ce5 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 17:35:44 +0800 Subject: [PATCH 09/20] version check --- .gitignore | 5 +- shadowsocks-csharp.sln | 9 ++ shadowsocks-csharp/Controller/UpdateChecker.cs | 152 +++++++++++++++++++++ .../Properties/Resources.Designer.cs | 2 +- shadowsocks-csharp/View/ConfigForm.cs | 21 +++ shadowsocks-csharp/shadowsocks-csharp.csproj | 7 +- test/Properties/AssemblyInfo.cs | 36 +++++ test/UnitTest.cs | 22 +++ test/test.csproj | 81 +++++++++++ 9 files changed, 329 insertions(+), 6 deletions(-) create mode 100755 shadowsocks-csharp/Controller/UpdateChecker.cs create mode 100755 test/Properties/AssemblyInfo.cs create mode 100755 test/UnitTest.cs create mode 100755 test/test.csproj diff --git a/.gitignore b/.gitignore index dba5eabd..82c89bb5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ Backup/ -shadowsocks-csharp/bin/ -shadowsocks-csharp/obj/ +bin/ +obj/ shadowsocks-csharp/shadowsocks-csharp.csproj.user +TestResults *.suo diff --git a/shadowsocks-csharp.sln b/shadowsocks-csharp.sln index 46bde1a8..83869ae2 100755 --- a/shadowsocks-csharp.sln +++ b/shadowsocks-csharp.sln @@ -3,6 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2012 for Windows Desktop Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shadowsocks-csharp", "shadowsocks-csharp\shadowsocks-csharp.csproj", "{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{45913187-0685-4903-B250-DCEF0479CD86}" + ProjectSection(ProjectDependencies) = postProject + {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062} = {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 @@ -14,6 +19,10 @@ Global {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Deploy.0 = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.ActiveCfg = Release|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.Build.0 = Release|x86 + {45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.ActiveCfg = Debug|x86 + {45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.Build.0 = Debug|x86 + {45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.ActiveCfg = Release|x86 + {45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/shadowsocks-csharp/Controller/UpdateChecker.cs b/shadowsocks-csharp/Controller/UpdateChecker.cs new file mode 100755 index 00000000..b731013d --- /dev/null +++ b/shadowsocks-csharp/Controller/UpdateChecker.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; + +namespace Shadowsocks.Controller +{ + public class UpdateChecker + { + private const string UpdateURL = "https://sourceforge.net/api/file/index/project-id/1817190/path/dist/mtime/desc/limit/10/rss"; + + public string LatestVersionNumber; + public string LatestVersionURL; + public event EventHandler NewVersionFound; + + public void CheckUpdate() + { + // TODO test failures + WebClient http = new WebClient(); + http.DownloadStringCompleted += http_DownloadStringCompleted; + http.DownloadStringAsync(new Uri(UpdateURL)); + } + + public static int CompareVersion(string l, string r) + { + var ls = l.Split('.'); + var rs = r.Split('.'); + for (int i = 0; i < Math.Max(ls.Length, rs.Length); i++) + { + int lp = (i < ls.Length) ? int.Parse(ls[i]) : 0; + int rp = (i < rs.Length) ? int.Parse(rs[i]) : 0; + if (lp != rp) + { + return lp - rp; + } + } + return 0; + } + + public class VersionComparer : IComparer + { + // Calls CaseInsensitiveComparer.Compare with the parameters reversed. + public int Compare(string x, string y) + { + return CompareVersion(ParseVersionFromURL(x), ParseVersionFromURL(y)); + } + + } + + private static string ParseVersionFromURL(string url) + { + Match match = Regex.Match(url, @".*Shadowsocks-win.*?-([\d\.]+)\.\w+", RegexOptions.IgnoreCase); + if (match.Success) + { + if (match.Groups.Count == 2) + { + return match.Groups[1].Value; + } + } + return null; + } + + private void SortVersions(List versions) + { + versions.Sort(new VersionComparer()); + } + + private bool IsNewVersion(string url) + { + // check dotnet 4.0 + AssemblyName[] references = Assembly.GetExecutingAssembly().GetReferencedAssemblies(); + Version dotNetVersion = Environment.Version; + foreach (AssemblyName reference in references) + { + if (reference.Name == "mscorlib") + { + dotNetVersion = reference.Version; + } + } + if (dotNetVersion.Major >= 4) + { + if (url.IndexOf("dotnet4.0") < 0) + { + return false; + } + } + else + { + if (url.IndexOf("dotnet4.0") >= 0) + { + return false; + } + } + string version = ParseVersionFromURL(url); + if (version == null) + { + return false; + } + string currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + + return CompareVersion(version, currentVersion) > 0; + } + + private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) + { + try + { + string response = e.Result; + + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(response); + XmlNodeList elements = xmlDoc.GetElementsByTagName("media:content"); + List versions = new List(); + foreach (XmlNode el in elements) + { + foreach (XmlAttribute attr in el.Attributes) + { + if (attr.Name == "url") + { + Console.WriteLine(attr.Value); + if (IsNewVersion(attr.Value)) + { + versions.Add(attr.Value); + } + } + } + } + if (versions.Count == 0) + { + return; + } + // sort versions + SortVersions(versions); + LatestVersionURL = versions[versions.Count - 1]; + LatestVersionNumber = ParseVersionFromURL(LatestVersionURL); + if (NewVersionFound != null) + { + NewVersionFound(this, new EventArgs()); + } + } + catch (Exception ex) + { + Console.Write(ex.ToString()); + return; + } + } + } +} diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index 8c4f781e..d292578d 100755 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -71,7 +71,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to proxyAddress = "127.0.0.1" + /// Looks up a localized string similar to proxyAddress = "__POLIPO_BIND_IP__" /// ///socksParentProxy = "127.0.0.1:__SOCKS_PORT__" ///socksProxyType = socks5 diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 2a7e5db2..8bd980b8 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -13,6 +13,7 @@ namespace Shadowsocks.View public partial class ConfigForm : Form { private ShadowsocksController controller; + private UpdateChecker updateChecker; // this is a copy of configuration that we are working on private Configuration modifiedConfiguration; @@ -30,6 +31,9 @@ namespace Shadowsocks.View controller.PACFileReadyToOpen += controller_PACFileReadyToOpen; controller.ShareOverLANStatusChanged += controller_ShareOverLANStatusChanged; + this.updateChecker = new UpdateChecker(); + updateChecker.NewVersionFound += updateChecker_NewVersionFound; + LoadCurrentConfiguration(); } @@ -55,6 +59,21 @@ namespace Shadowsocks.View System.Diagnostics.Process.Start("explorer.exe", argument); } + void updateChecker_NewVersionFound(object sender, EventArgs e) + { + notifyIcon1.BalloonTipTitle = "Shadowsocks " + updateChecker.LatestVersionNumber + " Update Found"; + notifyIcon1.BalloonTipText = "You can click here to download"; + notifyIcon1.BalloonTipIcon = ToolTipIcon.Info; + notifyIcon1.BalloonTipClicked += notifyIcon1_BalloonTipClicked; + notifyIcon1.ShowBalloonTip(5000); + isFirstRun = false; + } + + void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) + { + Process.Start(updateChecker.LatestVersionURL); + } + private void ShowWindow() { @@ -176,6 +195,7 @@ namespace Shadowsocks.View { isFirstRun = true; } + updateChecker.CheckUpdate(); } private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e) @@ -242,6 +262,7 @@ namespace Shadowsocks.View { notifyIcon1.BalloonTipTitle = "Shadowsocks is here"; notifyIcon1.BalloonTipText = "You can turn on/off Shadowsocks in the context menu"; + notifyIcon1.BalloonTipIcon = ToolTipIcon.Info; notifyIcon1.ShowBalloonTip(0); isFirstRun = false; } diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index ab31982a..08ebf02c 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -10,7 +10,7 @@ Properties Shadowsocks Shadowsocks - v2.0 + v4.0 512 @@ -21,8 +21,7 @@ 3.5 - - + Client publish\ true Disk @@ -63,12 +62,14 @@ + + diff --git a/test/Properties/AssemblyInfo.cs b/test/Properties/AssemblyInfo.cs new file mode 100755 index 00000000..2918bf7a --- /dev/null +++ b/test/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("test")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f74e87ac-7e3a-444b-a1d9-8b91a674c60f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/test/UnitTest.cs b/test/UnitTest.cs new file mode 100755 index 00000000..c23f4c75 --- /dev/null +++ b/test/UnitTest.cs @@ -0,0 +1,22 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Shadowsocks.Controller; + +namespace test +{ + [TestClass] + public class UnitTest + { + [TestMethod] + public void TestCompareVersion() + { + Assert.IsTrue(UpdateChecker.CompareVersion("2.3.1.0", "2.3.1") == 0); + Assert.IsTrue(UpdateChecker.CompareVersion("1.2", "1.3") < 0); + Assert.IsTrue(UpdateChecker.CompareVersion("1.3", "1.2") > 0); + Assert.IsTrue(UpdateChecker.CompareVersion("1.3", "1.3") == 0); + Assert.IsTrue(UpdateChecker.CompareVersion("1.2.1", "1.2") > 0); + Assert.IsTrue(UpdateChecker.CompareVersion("2.3.1", "2.4") < 0); + Assert.IsTrue(UpdateChecker.CompareVersion("1.3.2", "1.3.1") > 0); + } + } +} diff --git a/test/test.csproj b/test/test.csproj new file mode 100755 index 00000000..235846d0 --- /dev/null +++ b/test/test.csproj @@ -0,0 +1,81 @@ + + + + Debug + AnyCPU + {45913187-0685-4903-B250-DCEF0479CD86} + Library + Properties + test + test + v4.5 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + bin\x86\Debug\ + x86 + + + bin\x86\Release\ + x86 + + + + + + + + + + + + + + + + + + + + + + + {8c02d2f7-7cdb-4d55-9f25-cd03ef4aa062} + shadowsocks-csharp + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file From cfb56c22ae31a7388ae05485e5674f47f0225f77 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 17:40:59 +0800 Subject: [PATCH 10/20] back to 2.0 --- shadowsocks-csharp/shadowsocks-csharp.csproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 08ebf02c..b648b831 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -10,7 +10,7 @@ Properties Shadowsocks Shadowsocks - v4.0 + v2.0 512 @@ -21,7 +21,8 @@ 3.5 - Client + + publish\ true Disk From 3b2976950a50873f25e86e7072c1533c868adf7f Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 19:02:26 +0800 Subject: [PATCH 11/20] add comments about .net 4.0 crash --- README.md | 3 +++ shadowsocks-csharp/Controller/Local.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f52c919..6ea9efc5 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,9 @@ For Windows 7 and older, please download Shadowsocks-win-x.x.x.zip. For Windows 8.1 and newer, please download Shadowsocks-win-dotnet4.0-x.x.x.zip. +Notice there's a bug on .Net 4.0 version. If you encounter crashes, try using +.Net 2.0 version. Please help us resolve this issue if you have any clue. + ### Usage 1. Find Shadowsocks icon in notification tray diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index baf535c3..7bd0fb98 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -314,7 +314,7 @@ namespace Shadowsocks.Controller } else { - Console.WriteLine("bytesRead: " + bytesRead.ToString()); + //Console.WriteLine("bytesRead: " + bytesRead.ToString()); this.Close(); } } From 1ecd7daac8b88c05a6c9cb02f92e2d4152046e82 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 19:16:02 +0800 Subject: [PATCH 12/20] add lock for Close() --- shadowsocks-csharp/Controller/Local.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index 7bd0fb98..924cfbad 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -144,11 +144,14 @@ namespace Shadowsocks.Controller public void Close() { - if (closed) + lock (this) { - return; + if (closed) + { + return; + } + closed = true; } - closed = true; if (connection != null) { try From 2477fb816ad84987716b646eb73be61d71d3e643 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 19:54:56 +0800 Subject: [PATCH 13/20] add locks to all encryption contexts --- shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs | 236 +++++++++++++----------- shadowsocks-csharp/Properties/AssemblyInfo.cs | 2 +- shadowsocks-csharp/shadowsocks-csharp.csproj | 2 +- 3 files changed, 132 insertions(+), 108 deletions(-) diff --git a/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs b/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs index fdd7ce19..3b00c6cb 100755 --- a/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs +++ b/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs @@ -103,56 +103,59 @@ namespace Shadowsocks.Encrypt private void InitCipher(ref byte[] ctx, byte[] iv, bool isCipher) { ctx = new byte[_cipherInfo[3]]; - byte[] realkey; - if (_method == "rc4-md5") + lock (ctx) { - byte[] temp = new byte[keyLen + ivLen]; - realkey = new byte[keyLen]; - Array.Copy(_key, 0, temp, 0, keyLen); - Array.Copy(iv, 0, temp, keyLen, ivLen); - realkey = MD5.Create().ComputeHash(temp); - } - else - { - realkey = _key; - } - if (_cipher == CIPHER_AES) - { - PolarSSL.aes_init(ctx); - // PolarSSL takes key length by bit - // since we'll use CFB mode, here we both do enc, not dec - PolarSSL.aes_setkey_enc(ctx, realkey, keyLen * 8); - if (isCipher) + byte[] realkey; + if (_method == "rc4-md5") { - _encryptIV = new byte[ivLen]; - Array.Copy(iv, _encryptIV, ivLen); + byte[] temp = new byte[keyLen + ivLen]; + realkey = new byte[keyLen]; + Array.Copy(_key, 0, temp, 0, keyLen); + Array.Copy(iv, 0, temp, keyLen, ivLen); + realkey = MD5.Create().ComputeHash(temp); } else { - _decryptIV = new byte[ivLen]; - Array.Copy(iv, _decryptIV, ivLen); + realkey = _key; } - } - else if (_cipher == CIPHER_BF) - { - PolarSSL.blowfish_init(ctx); - // PolarSSL takes key length by bit - PolarSSL.blowfish_setkey(ctx, realkey, keyLen * 8); - if (isCipher) + if (_cipher == CIPHER_AES) { - _encryptIV = new byte[ivLen]; - Array.Copy(iv, _encryptIV, ivLen); + PolarSSL.aes_init(ctx); + // PolarSSL takes key length by bit + // since we'll use CFB mode, here we both do enc, not dec + PolarSSL.aes_setkey_enc(ctx, realkey, keyLen * 8); + if (isCipher) + { + _encryptIV = new byte[ivLen]; + Array.Copy(iv, _encryptIV, ivLen); + } + else + { + _decryptIV = new byte[ivLen]; + Array.Copy(iv, _decryptIV, ivLen); + } } - else + else if (_cipher == CIPHER_BF) { - _decryptIV = new byte[ivLen]; - Array.Copy(iv, _decryptIV, ivLen); + PolarSSL.blowfish_init(ctx); + // PolarSSL takes key length by bit + PolarSSL.blowfish_setkey(ctx, realkey, keyLen * 8); + if (isCipher) + { + _encryptIV = new byte[ivLen]; + Array.Copy(iv, _encryptIV, ivLen); + } + else + { + _decryptIV = new byte[ivLen]; + Array.Copy(iv, _decryptIV, ivLen); + } + } + else if (_cipher == CIPHER_RC4) + { + PolarSSL.arc4_init(ctx); + PolarSSL.arc4_setup(ctx, realkey, keyLen); } - } - else if (_cipher == CIPHER_RC4) - { - PolarSSL.arc4_init(ctx); - PolarSSL.arc4_setup(ctx, realkey, keyLen); } } @@ -170,36 +173,42 @@ namespace Shadowsocks.Encrypt lock (tempbuf) { // C# could be multi-threaded + lock (_encryptCtx) + { + switch (_cipher) + { + case CIPHER_AES: + PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); + break; + case CIPHER_BF: + PolarSSL.blowfish_crypt_cfb64(_encryptCtx, PolarSSL.BLOWFISH_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); + break; + case CIPHER_RC4: + PolarSSL.arc4_crypt(_encryptCtx, length, buf, tempbuf); + break; + } + outlength = length + ivLen; + Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, outlength); + } + } + } + else + { + outlength = length; + lock (_encryptCtx) + { switch (_cipher) { case CIPHER_AES: - PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); + PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, outbuf); break; case CIPHER_BF: - PolarSSL.blowfish_crypt_cfb64(_encryptCtx, PolarSSL.BLOWFISH_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, tempbuf); + PolarSSL.blowfish_crypt_cfb64(_encryptCtx, PolarSSL.BLOWFISH_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, outbuf); break; case CIPHER_RC4: - PolarSSL.arc4_crypt(_encryptCtx, length, buf, tempbuf); + PolarSSL.arc4_crypt(_encryptCtx, length, buf, outbuf); break; } - outlength = length + ivLen; - Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, outlength); - } - } - else - { - outlength = length; - switch (_cipher) - { - case CIPHER_AES: - PolarSSL.aes_crypt_cfb128(_encryptCtx, PolarSSL.AES_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, outbuf); - break; - case CIPHER_BF: - PolarSSL.blowfish_crypt_cfb64(_encryptCtx, PolarSSL.BLOWFISH_ENCRYPT, length, ref _encryptIVOffset, _encryptIV, buf, outbuf); - break; - case CIPHER_RC4: - PolarSSL.arc4_crypt(_encryptCtx, length, buf, outbuf); - break; } } } @@ -214,36 +223,42 @@ namespace Shadowsocks.Encrypt { // C# could be multi-threaded Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen); + lock (_decryptCtx) + { + switch (_cipher) + { + case CIPHER_AES: + PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); + break; + case CIPHER_BF: + PolarSSL.blowfish_crypt_cfb64(_decryptCtx, PolarSSL.BLOWFISH_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); + break; + case CIPHER_RC4: + PolarSSL.arc4_crypt(_decryptCtx, length - ivLen, tempbuf, outbuf); + break; + } + } + } + } + else + { + outlength = length; + lock (_decryptCtx) + { switch (_cipher) { case CIPHER_AES: - PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); + PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length, ref _decryptIVOffset, _decryptIV, buf, outbuf); break; case CIPHER_BF: - PolarSSL.blowfish_crypt_cfb64(_decryptCtx, PolarSSL.BLOWFISH_DECRYPT, length - ivLen, ref _decryptIVOffset, _decryptIV, tempbuf, outbuf); + PolarSSL.blowfish_crypt_cfb64(_decryptCtx, PolarSSL.BLOWFISH_DECRYPT, length, ref _decryptIVOffset, _decryptIV, buf, outbuf); break; case CIPHER_RC4: - PolarSSL.arc4_crypt(_decryptCtx, length - ivLen, tempbuf, outbuf); + PolarSSL.arc4_crypt(_decryptCtx, length, buf, outbuf); break; } } } - else - { - outlength = length; - switch (_cipher) - { - case CIPHER_AES: - PolarSSL.aes_crypt_cfb128(_decryptCtx, PolarSSL.AES_DECRYPT, length, ref _decryptIVOffset, _decryptIV, buf, outbuf); - break; - case CIPHER_BF: - PolarSSL.blowfish_crypt_cfb64(_decryptCtx, PolarSSL.BLOWFISH_DECRYPT, length, ref _decryptIVOffset, _decryptIV, buf, outbuf); - break; - case CIPHER_RC4: - PolarSSL.arc4_crypt(_decryptCtx, length, buf, outbuf); - break; - } - } } #region IDisposable @@ -262,46 +277,55 @@ namespace Shadowsocks.Encrypt protected virtual void Dispose(bool disposing) { - if (!_disposed) + lock (this) { - if (disposing) + if (_disposed) { - + return; } + _disposed = true; + } + if (disposing) + { if (_encryptCtx != null) { - switch (_cipher) + lock (_encryptCtx) { - case CIPHER_AES: - PolarSSL.aes_free(_encryptCtx); - break; - case CIPHER_BF: - PolarSSL.blowfish_free(_encryptCtx); - break; - case CIPHER_RC4: - PolarSSL.arc4_free(_encryptCtx); - break; + switch (_cipher) + { + case CIPHER_AES: + PolarSSL.aes_free(_encryptCtx); + break; + case CIPHER_BF: + PolarSSL.blowfish_free(_encryptCtx); + break; + case CIPHER_RC4: + PolarSSL.arc4_free(_encryptCtx); + break; + } + _encryptCtx = null; } } if (_decryptCtx != null) { - switch (_cipher) + lock (_decryptCtx) { - case CIPHER_AES: - PolarSSL.aes_free(_decryptCtx); - break; - case CIPHER_BF: - PolarSSL.blowfish_free(_decryptCtx); - break; - case CIPHER_RC4: - PolarSSL.arc4_free(_decryptCtx); - break; + switch (_cipher) + { + case CIPHER_AES: + PolarSSL.aes_free(_decryptCtx); + break; + case CIPHER_BF: + PolarSSL.blowfish_free(_decryptCtx); + break; + case CIPHER_RC4: + PolarSSL.arc4_free(_decryptCtx); + break; + } + _decryptCtx = null; } } - _encryptCtx = null; - _decryptCtx = null; - _disposed = true; } } #endregion diff --git a/shadowsocks-csharp/Properties/AssemblyInfo.cs b/shadowsocks-csharp/Properties/AssemblyInfo.cs index 7351ffd1..b09c3e51 100755 --- a/shadowsocks-csharp/Properties/AssemblyInfo.cs +++ b/shadowsocks-csharp/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, // 方法是按如下所示使用“*”: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.5")] +[assembly: AssemblyVersion("2.0.6")] // [assembly: AssemblyFileVersion("2.0.0")] diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index b648b831..d19fbc98 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -10,7 +10,7 @@ Properties Shadowsocks Shadowsocks - v2.0 + v4.0 512 From ac4748d6bfb02e41b1fbbc30163295b622a3e0c5 Mon Sep 17 00:00:00 2001 From: wzxjohn Date: Sun, 9 Nov 2014 04:39:57 +0800 Subject: [PATCH 14/20] lint code --- shadowsocks-csharp/Controller/Local.cs | 28 ++++----- .../Controller/ShadowsocksController.cs | 4 +- shadowsocks-csharp/Program.cs | 1 - .../Properties/Resources.Designer.cs | 12 ++-- shadowsocks-csharp/View/ConfigForm.Designer.cs | 1 + shadowsocks-csharp/View/ConfigForm.cs | 73 +++++++++++----------- 6 files changed, 60 insertions(+), 59 deletions(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index 924cfbad..8eb2384b 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -224,7 +224,7 @@ namespace Shadowsocks.Controller // reject socks 4 response = new byte[]{ 0, 91 }; } - connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(handshakeSendCallback), null); + connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null); } else { @@ -238,7 +238,7 @@ namespace Shadowsocks.Controller } } - private void handshakeSendCallback(IAsyncResult ar) + private void HandshakeSendCallback(IAsyncResult ar) { try { @@ -270,7 +270,7 @@ namespace Shadowsocks.Controller if (bytesRead > 0) { byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 }; - connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(startPipe), null); + connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(StartPipe), null); } else { @@ -285,15 +285,15 @@ namespace Shadowsocks.Controller } - private void startPipe(IAsyncResult ar) + private void StartPipe(IAsyncResult ar) { try { connection.EndReceive(ar); remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0, - new AsyncCallback(pipeRemoteReceiveCallback), null); + new AsyncCallback(PipeRemoteReceiveCallback), null); connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, - new AsyncCallback(pipeConnectionReceiveCallback), null); + new AsyncCallback(PipeConnectionReceiveCallback), null); } catch (Exception e) { @@ -302,7 +302,7 @@ namespace Shadowsocks.Controller } } - private void pipeRemoteReceiveCallback(IAsyncResult ar) + private void PipeRemoteReceiveCallback(IAsyncResult ar) { try @@ -313,7 +313,7 @@ namespace Shadowsocks.Controller { int bytesToSend; encryptor.Decrypt(remoteRecvBuffer, bytesRead, remoteSendBuffer, out bytesToSend); - connection.BeginSend(remoteSendBuffer, 0, bytesToSend, 0, new AsyncCallback(pipeConnectionSendCallback), null); + connection.BeginSend(remoteSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeConnectionSendCallback), null); } else { @@ -328,7 +328,7 @@ namespace Shadowsocks.Controller } } - private void pipeConnectionReceiveCallback(IAsyncResult ar) + private void PipeConnectionReceiveCallback(IAsyncResult ar) { try @@ -339,7 +339,7 @@ namespace Shadowsocks.Controller { int bytesToSend; encryptor.Encrypt(connetionRecvBuffer, bytesRead, connetionSendBuffer, out bytesToSend); - remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(pipeRemoteSendCallback), null); + remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null); } else { @@ -353,13 +353,13 @@ namespace Shadowsocks.Controller } } - private void pipeRemoteSendCallback(IAsyncResult ar) + private void PipeRemoteSendCallback(IAsyncResult ar) { try { remote.EndSend(ar); connection.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0, - new AsyncCallback(pipeConnectionReceiveCallback), null); + new AsyncCallback(PipeConnectionReceiveCallback), null); } catch (Exception e) { @@ -368,13 +368,13 @@ namespace Shadowsocks.Controller } } - private void pipeConnectionSendCallback(IAsyncResult ar) + private void PipeConnectionSendCallback(IAsyncResult ar) { try { connection.EndSend(ar); remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0, - new AsyncCallback(pipeRemoteReceiveCallback), null); + new AsyncCallback(PipeRemoteReceiveCallback), null); } catch (Exception e) { diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index e6e80d05..b28e2105 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -1,4 +1,5 @@ -using Shadowsocks.Model; +using System.IO; +using Shadowsocks.Model; using System; using System.Collections.Generic; using System.Text; @@ -172,6 +173,5 @@ namespace Shadowsocks.Controller { UpdateSystemProxy(); } - } } diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index a42a97ae..c90f089b 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -54,7 +54,6 @@ namespace Shadowsocks // TODO run without a main form to save RAM Application.Run(new ConfigForm(controller)); - } } } diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index d292578d..45ab16d9 100755 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -71,12 +71,12 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to proxyAddress = "__POLIPO_BIND_IP__" - /// - ///socksParentProxy = "127.0.0.1:__SOCKS_PORT__" - ///socksProxyType = socks5 - ///diskCacheRoot = "" - ///localDocumentRoot = "" + /// Looks up a localized string similar to proxyAddress = "__POLIPO_BIND_IP__" + /// + ///socksParentProxy = "127.0.0.1:__SOCKS_PORT__" + ///socksProxyType = socks5 + ///diskCacheRoot = "" + ///localDocumentRoot = "" ///. /// internal static string polipo_config { diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index cf874286..c1187c04 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -434,6 +434,7 @@ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; + this.MinimizeBox = false; this.Name = "ConfigForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Edit Servers"; diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 8bd980b8..e4cfda2b 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -16,9 +16,9 @@ namespace Shadowsocks.View private UpdateChecker updateChecker; // this is a copy of configuration that we are working on - private Configuration modifiedConfiguration; - private int oldSelectedIndex = -1; - private bool isFirstRun; + private Configuration _modifiedConfiguration; + private int _oldSelectedIndex = -1; + private bool _isFirstRun; public ConfigForm(ShadowsocksController controller) { @@ -66,7 +66,7 @@ namespace Shadowsocks.View notifyIcon1.BalloonTipIcon = ToolTipIcon.Info; notifyIcon1.BalloonTipClicked += notifyIcon1_BalloonTipClicked; notifyIcon1.ShowBalloonTip(5000); - isFirstRun = false; + _isFirstRun = false; } void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) @@ -86,7 +86,7 @@ namespace Shadowsocks.View { try { - if (oldSelectedIndex == -1 || oldSelectedIndex >= modifiedConfiguration.configs.Count) + if (_oldSelectedIndex == -1 || _oldSelectedIndex >= _modifiedConfiguration.configs.Count) { return true; } @@ -100,7 +100,8 @@ namespace Shadowsocks.View remarks = RemarksTextBox.Text }; Configuration.CheckServer(server); - modifiedConfiguration.configs[oldSelectedIndex] = server; + _modifiedConfiguration.configs[_oldSelectedIndex] = server; + return true; } catch (FormatException) @@ -116,15 +117,15 @@ namespace Shadowsocks.View private void LoadSelectedServer() { - if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < modifiedConfiguration.configs.Count) + if (ServersListBox.SelectedIndex >= 0 && ServersListBox.SelectedIndex < _modifiedConfiguration.configs.Count) { - Server server = modifiedConfiguration.configs[ServersListBox.SelectedIndex]; + Server server = _modifiedConfiguration.configs[ServersListBox.SelectedIndex]; IPTextBox.Text = server.server; ServerPortTextBox.Text = server.server_port.ToString(); PasswordTextBox.Text = server.password; ProxyPortTextBox.Text = server.local_port.ToString(); - EncryptionSelect.Text = server.method == null ? "aes-256-cfb" : server.method; + EncryptionSelect.Text = server.method ?? "aes-256-cfb"; RemarksTextBox.Text = server.remarks; ServerGroupBox.Visible = true; //IPTextBox.Focus(); @@ -138,7 +139,7 @@ namespace Shadowsocks.View private void LoadConfiguration(Configuration configuration) { ServersListBox.Items.Clear(); - foreach (Server server in modifiedConfiguration.configs) + foreach (Server server in _modifiedConfiguration.configs) { ServersListBox.Items.Add(string.IsNullOrEmpty(server.server) ? "New server" : string.IsNullOrEmpty(server.remarks)? server.server + ":" + server.server_port : server.server + ":" + server.server_port + " (" + server.remarks + ")"); } @@ -146,15 +147,15 @@ namespace Shadowsocks.View private void LoadCurrentConfiguration() { - modifiedConfiguration = controller.GetConfiguration(); - LoadConfiguration(modifiedConfiguration); - oldSelectedIndex = modifiedConfiguration.index; - ServersListBox.SelectedIndex = modifiedConfiguration.index; + _modifiedConfiguration = controller.GetConfiguration(); + LoadConfiguration(_modifiedConfiguration); + _oldSelectedIndex = _modifiedConfiguration.index; + ServersListBox.SelectedIndex = _modifiedConfiguration.index; LoadSelectedServer(); UpdateServersMenu(); - enableItem.Checked = modifiedConfiguration.enabled; - ShareOverLANItem.Checked = modifiedConfiguration.shareOverLan; + enableItem.Checked = _modifiedConfiguration.enabled; + ShareOverLANItem.Checked = _modifiedConfiguration.shareOverLan; } private void UpdateServersMenu() @@ -193,14 +194,14 @@ namespace Shadowsocks.View } else { - isFirstRun = true; + _isFirstRun = true; } updateChecker.CheckUpdate(); } private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e) { - if (oldSelectedIndex == ServersListBox.SelectedIndex) + if (_oldSelectedIndex == ServersListBox.SelectedIndex) { // we are moving back to oldSelectedIndex or doing a force move return; @@ -208,11 +209,11 @@ namespace Shadowsocks.View if (!SaveOldSelectedServer()) { // why this won't cause stack overflow? - ServersListBox.SelectedIndex = oldSelectedIndex; + ServersListBox.SelectedIndex = _oldSelectedIndex; return; } LoadSelectedServer(); - oldSelectedIndex = ServersListBox.SelectedIndex; + _oldSelectedIndex = ServersListBox.SelectedIndex; } private void AddButton_Click(object sender, EventArgs e) @@ -222,27 +223,27 @@ namespace Shadowsocks.View return; } Server server = Configuration.GetDefaultServer(); - modifiedConfiguration.configs.Add(server); - LoadConfiguration(modifiedConfiguration); - ServersListBox.SelectedIndex = modifiedConfiguration.configs.Count - 1; - oldSelectedIndex = ServersListBox.SelectedIndex; + _modifiedConfiguration.configs.Add(server); + LoadConfiguration(_modifiedConfiguration); + ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1; + _oldSelectedIndex = ServersListBox.SelectedIndex; } private void DeleteButton_Click(object sender, EventArgs e) { - oldSelectedIndex = ServersListBox.SelectedIndex; - if (oldSelectedIndex >= 0 && oldSelectedIndex < modifiedConfiguration.configs.Count) + _oldSelectedIndex = ServersListBox.SelectedIndex; + if (_oldSelectedIndex >= 0 && _oldSelectedIndex < _modifiedConfiguration.configs.Count) { - modifiedConfiguration.configs.RemoveAt(oldSelectedIndex); + _modifiedConfiguration.configs.RemoveAt(_oldSelectedIndex); } - if (oldSelectedIndex >= modifiedConfiguration.configs.Count) + if (_oldSelectedIndex >= _modifiedConfiguration.configs.Count) { // can be -1 - oldSelectedIndex = modifiedConfiguration.configs.Count - 1; + _oldSelectedIndex = _modifiedConfiguration.configs.Count - 1; } - ServersListBox.SelectedIndex = oldSelectedIndex; - LoadConfiguration(modifiedConfiguration); - ServersListBox.SelectedIndex = oldSelectedIndex; + ServersListBox.SelectedIndex = _oldSelectedIndex; + LoadConfiguration(_modifiedConfiguration); + ServersListBox.SelectedIndex = _oldSelectedIndex; LoadSelectedServer(); } @@ -258,13 +259,13 @@ namespace Shadowsocks.View private void ShowFirstTimeBalloon() { - if (isFirstRun) + if (_isFirstRun) { notifyIcon1.BalloonTipTitle = "Shadowsocks is here"; notifyIcon1.BalloonTipText = "You can turn on/off Shadowsocks in the context menu"; notifyIcon1.BalloonTipIcon = ToolTipIcon.Info; notifyIcon1.ShowBalloonTip(0); - isFirstRun = false; + _isFirstRun = false; } } @@ -274,12 +275,12 @@ namespace Shadowsocks.View { return; } - if (modifiedConfiguration.configs.Count == 0) + if (_modifiedConfiguration.configs.Count == 0) { MessageBox.Show("Please add at least one server"); return; } - controller.SaveServers(modifiedConfiguration.configs); + controller.SaveServers(_modifiedConfiguration.configs); this.Hide(); ShowFirstTimeBalloon(); } From a46b7d90c98403ce54a44862a9edea4b3516a30d Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 23:36:58 +0800 Subject: [PATCH 15/20] back to 2.0 --- README.md | 5 ++--- shadowsocks-csharp/Properties/Resources.Designer.cs | 12 ++++++------ shadowsocks-csharp/shadowsocks-csharp.csproj | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6ea9efc5..ce927d41 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Shadowsocks for Windows [![Build Status]][Appveyor] +Currently beta. Please file an issue if you find any bugs. + ### Features 1. Native Windows UI @@ -20,9 +22,6 @@ For Windows 7 and older, please download Shadowsocks-win-x.x.x.zip. For Windows 8.1 and newer, please download Shadowsocks-win-dotnet4.0-x.x.x.zip. -Notice there's a bug on .Net 4.0 version. If you encounter crashes, try using -.Net 2.0 version. Please help us resolve this issue if you have any clue. - ### Usage 1. Find Shadowsocks icon in notification tray diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index 45ab16d9..d292578d 100755 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -71,12 +71,12 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to proxyAddress = "__POLIPO_BIND_IP__" - /// - ///socksParentProxy = "127.0.0.1:__SOCKS_PORT__" - ///socksProxyType = socks5 - ///diskCacheRoot = "" - ///localDocumentRoot = "" + /// Looks up a localized string similar to proxyAddress = "__POLIPO_BIND_IP__" + /// + ///socksParentProxy = "127.0.0.1:__SOCKS_PORT__" + ///socksProxyType = socks5 + ///diskCacheRoot = "" + ///localDocumentRoot = "" ///. /// internal static string polipo_config { diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index d19fbc98..b648b831 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -10,7 +10,7 @@ Properties Shadowsocks Shadowsocks - v4.0 + v2.0 512 From 1297af77fc3c3e82a2e0906686a9bea49aa757c1 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 9 Nov 2014 23:59:53 +0800 Subject: [PATCH 16/20] check disposed in encryption #46 #42 --- shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs b/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs index 3b00c6cb..68293a8a 100755 --- a/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs +++ b/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs @@ -175,6 +175,10 @@ namespace Shadowsocks.Encrypt // C# could be multi-threaded lock (_encryptCtx) { + if (_disposed) + { + throw new ObjectDisposedException(this.ToString()); + } switch (_cipher) { case CIPHER_AES: @@ -197,6 +201,10 @@ namespace Shadowsocks.Encrypt outlength = length; lock (_encryptCtx) { + if (_disposed) + { + throw new ObjectDisposedException(this.ToString()); + } switch (_cipher) { case CIPHER_AES: @@ -225,6 +233,10 @@ namespace Shadowsocks.Encrypt Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen); lock (_decryptCtx) { + if (_disposed) + { + throw new ObjectDisposedException(this.ToString()); + } switch (_cipher) { case CIPHER_AES: @@ -245,6 +257,10 @@ namespace Shadowsocks.Encrypt outlength = length; lock (_decryptCtx) { + if (_disposed) + { + throw new ObjectDisposedException(this.ToString()); + } switch (_cipher) { case CIPHER_AES: @@ -304,7 +320,6 @@ namespace Shadowsocks.Encrypt PolarSSL.arc4_free(_encryptCtx); break; } - _encryptCtx = null; } } if (_decryptCtx != null) @@ -323,7 +338,6 @@ namespace Shadowsocks.Encrypt PolarSSL.arc4_free(_decryptCtx); break; } - _decryptCtx = null; } } } From 8d9375ac110a5c7d6d8f8b4f811ee9d184d7a2a0 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 10 Nov 2014 00:42:23 +0800 Subject: [PATCH 17/20] add nodelay --- shadowsocks-csharp/Controller/Local.cs | 2 ++ shadowsocks-csharp/Controller/UpdateChecker.cs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index 8eb2384b..4df401ce 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -70,6 +70,7 @@ namespace Shadowsocks.Controller { Socket listener = (Socket)ar.AsyncState; Socket conn = listener.EndAccept(ar); + conn.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); listener.BeginAccept( new AsyncCallback(AcceptCallback), @@ -130,6 +131,7 @@ namespace Shadowsocks.Controller remote = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + remote.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); // Connect to the remote endpoint. remote.BeginConnect(remoteEP, diff --git a/shadowsocks-csharp/Controller/UpdateChecker.cs b/shadowsocks-csharp/Controller/UpdateChecker.cs index b731013d..046ae941 100755 --- a/shadowsocks-csharp/Controller/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/UpdateChecker.cs @@ -121,7 +121,6 @@ namespace Shadowsocks.Controller { if (attr.Name == "url") { - Console.WriteLine(attr.Value); if (IsNewVersion(attr.Value)) { versions.Add(attr.Value); From 0461e2ca89f924bb0c21187a030002e255983cf9 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 10 Nov 2014 02:42:06 +0800 Subject: [PATCH 18/20] try fixing shutdown --- shadowsocks-csharp/Controller/Local.cs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index 4df401ce..ed769215 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -112,6 +112,9 @@ namespace Shadowsocks.Controller public byte[] connetionSendBuffer = new byte[BufferSize]; // Received data string. public StringBuilder sb = new StringBuilder(); + + private bool connectionShutdown = false; + private bool remoteShutdown = false; private bool closed = false; public void Start() @@ -144,6 +147,14 @@ namespace Shadowsocks.Controller } } + private void CheckClose() + { + if (connectionShutdown && remoteShutdown) + { + this.Close(); + } + } + public void Close() { lock (this) @@ -158,7 +169,8 @@ namespace Shadowsocks.Controller { try { - connection.Shutdown(SocketShutdown.Send); + connection.Shutdown(SocketShutdown.Both); + connection.Close(); } catch (Exception e) { @@ -169,7 +181,8 @@ namespace Shadowsocks.Controller { try { - remote.Shutdown(SocketShutdown.Send); + remote.Shutdown(SocketShutdown.Both); + remote.Close(); } catch (SocketException e) { @@ -320,7 +333,9 @@ namespace Shadowsocks.Controller else { //Console.WriteLine("bytesRead: " + bytesRead.ToString()); - this.Close(); + connection.Shutdown(SocketShutdown.Send); + connectionShutdown = true; + CheckClose(); } } catch (Exception e) @@ -345,7 +360,9 @@ namespace Shadowsocks.Controller } else { - this.Close(); + remote.Shutdown(SocketShutdown.Send); + remoteShutdown = true; + CheckClose(); } } catch (Exception e) From 5c2a93e9010e37b0c45f9fc0537171603ac331c9 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 10 Nov 2014 03:02:31 +0800 Subject: [PATCH 19/20] use a fixed GUID --- shadowsocks-csharp/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index c90f089b..35356d78 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -23,7 +23,7 @@ namespace Shadowsocks [STAThread] static void Main() { - using (Mutex mutex = new Mutex(false, "Global\\" + Assembly.GetExecutingAssembly().GetType().GUID.ToString())) + using (Mutex mutex = new Mutex(false, "Global\\" + "71981632-A427-497F-AB91-241CD227EC1F")) { if (!mutex.WaitOne(0, false)) { From b6da609cff56c398379b9198bb44e4f4dfc32941 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 10 Nov 2014 03:18:37 +0800 Subject: [PATCH 20/20] update update notification --- shadowsocks-csharp/View/ConfigForm.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index e4cfda2b..2629dc13 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -62,7 +62,7 @@ namespace Shadowsocks.View void updateChecker_NewVersionFound(object sender, EventArgs e) { notifyIcon1.BalloonTipTitle = "Shadowsocks " + updateChecker.LatestVersionNumber + " Update Found"; - notifyIcon1.BalloonTipText = "You can click here to download"; + notifyIcon1.BalloonTipText = "Click here to download"; notifyIcon1.BalloonTipIcon = ToolTipIcon.Info; notifyIcon1.BalloonTipClicked += notifyIcon1_BalloonTipClicked; notifyIcon1.ShowBalloonTip(5000);