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();