@@ -1,3 +1,6 @@ | |||||
2.2.1 2015-01-18 | |||||
- Fix QR Code compatibility | |||||
2.2 2015-01-14 | 2.2 2015-01-14 | ||||
- Support updating PAC from GFWList | - Support updating PAC from GFWList | ||||
- Support adding server by scanning QR Code | - Support adding server by scanning QR Code | ||||
@@ -20,6 +20,8 @@ a pull request, or ask some of your friends to do so. | |||||
3. We don't answer questions of any other types here. Since very few people | 3. We don't answer questions of any other types here. Since very few people | ||||
are watching the issue tracker here, you'll probably get no help from here. | are watching the issue tracker here, you'll probably get no help from here. | ||||
Read [Troubleshooting] and get help from forums or [mailing lists]. | Read [Troubleshooting] and get help from forums or [mailing lists]. | ||||
4. Issues in languages other than English will be Google translated into English | |||||
later. | |||||
[Troubleshooting]: https://github.com/clowwindy/shadowsocks/wiki/Troubleshooting | [Troubleshooting]: https://github.com/clowwindy/shadowsocks/wiki/Troubleshooting | ||||
@@ -23,11 +23,10 @@ For >= Windows 8, download Shadowsocks-win-dotnet4.0-x.x.x.zip, unless you have | |||||
1. Find Shadowsocks icon in notification tray | 1. Find Shadowsocks icon in notification tray | ||||
2. You can add multiple servers in servers menu | 2. You can add multiple servers in servers menu | ||||
3. Select Enable menu to enable system proxy | |||||
4. Leave Enable menu unchecked, Shadowsocks will still provide an HTTP proxy at 127.0.0.1:8123 | |||||
5. After you saved PAC file with any editor, Shadowsocks will notify browsers | |||||
3. Select Enable System Proxy menu to enable system proxy | |||||
4. After you saved PAC file with any editor, Shadowsocks will notify browsers | |||||
about the change automatically | about the change automatically | ||||
6. Please disable other proxy addons in your browser, or set them to use | |||||
5. Please disable other proxy addons in your browser, or set them to use | |||||
system proxy | system proxy | ||||
### Develop | ### Develop | ||||
@@ -6,6 +6,7 @@ using System.IO; | |||||
using Shadowsocks.Properties; | using Shadowsocks.Properties; | ||||
using SimpleJson; | using SimpleJson; | ||||
using Shadowsocks.Util; | using Shadowsocks.Util; | ||||
using Shadowsocks.Model; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
@@ -42,10 +43,10 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
public void UpdatePACFromGFWList() | |||||
public void UpdatePACFromGFWList(Configuration config) | |||||
{ | { | ||||
WebClient http = new WebClient(); | WebClient http = new WebClient(); | ||||
http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), 8123); | |||||
http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort); | |||||
http.DownloadStringCompleted += http_DownloadStringCompleted; | http.DownloadStringCompleted += http_DownloadStringCompleted; | ||||
http.DownloadStringAsync(new Uri(GFWLIST_URL)); | http.DownloadStringAsync(new Uri(GFWLIST_URL)); | ||||
} | } | ||||
@@ -0,0 +1,143 @@ | |||||
using Shadowsocks.Model; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Net; | |||||
using System.Net.Sockets; | |||||
using System.Text; | |||||
namespace Shadowsocks.Controller | |||||
{ | |||||
public class Listener | |||||
{ | |||||
public interface Service | |||||
{ | |||||
bool Handle(byte[] firstPacket, int length, Socket socket); | |||||
} | |||||
Configuration _config; | |||||
bool _shareOverLAN; | |||||
Socket _socket; | |||||
IList<Service> _services; | |||||
public Listener(IList<Service> services) | |||||
{ | |||||
this._services = services; | |||||
} | |||||
public void Start(Configuration config) | |||||
{ | |||||
this._config = config; | |||||
this._shareOverLAN = config.shareOverLan; | |||||
try | |||||
{ | |||||
// Create a TCP/IP socket. | |||||
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); | |||||
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); | |||||
IPEndPoint localEndPoint = null; | |||||
if (_shareOverLAN) | |||||
{ | |||||
localEndPoint = new IPEndPoint(IPAddress.Any, _config.localPort); | |||||
} | |||||
else | |||||
{ | |||||
localEndPoint = new IPEndPoint(IPAddress.Loopback, _config.localPort); | |||||
} | |||||
// Bind the socket to the local endpoint and listen for incoming connections. | |||||
_socket.Bind(localEndPoint); | |||||
_socket.Listen(1024); | |||||
// Start an asynchronous socket to listen for connections. | |||||
Console.WriteLine("Shadowsocks started"); | |||||
_socket.BeginAccept( | |||||
new AsyncCallback(AcceptCallback), | |||||
_socket); | |||||
} | |||||
catch (SocketException) | |||||
{ | |||||
_socket.Close(); | |||||
throw; | |||||
} | |||||
} | |||||
public void Stop() | |||||
{ | |||||
if (_socket != null) | |||||
{ | |||||
_socket.Close(); | |||||
_socket = null; | |||||
} | |||||
} | |||||
public void AcceptCallback(IAsyncResult ar) | |||||
{ | |||||
Socket listener = (Socket)ar.AsyncState; | |||||
try | |||||
{ | |||||
Socket conn = listener.EndAccept(ar); | |||||
byte[] buf = new byte[4096]; | |||||
object[] state = new object[] { | |||||
conn, | |||||
buf | |||||
}; | |||||
conn.BeginReceive(buf, 0, buf.Length, 0, | |||||
new AsyncCallback(ReceiveCallback), state); | |||||
} | |||||
catch (ObjectDisposedException) | |||||
{ | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
} | |||||
finally | |||||
{ | |||||
try | |||||
{ | |||||
listener.BeginAccept( | |||||
new AsyncCallback(AcceptCallback), | |||||
listener); | |||||
} | |||||
catch (ObjectDisposedException) | |||||
{ | |||||
// do nothing | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
} | |||||
} | |||||
} | |||||
private void ReceiveCallback(IAsyncResult ar) | |||||
{ | |||||
object[] state = (object[])ar.AsyncState; | |||||
Socket conn = (Socket)state[0]; | |||||
byte[] buf = (byte[])state[1]; | |||||
try | |||||
{ | |||||
int bytesRead = conn.EndReceive(ar); | |||||
foreach (Service service in _services) | |||||
{ | |||||
if (service.Handle(buf, bytesRead, conn)) | |||||
{ | |||||
return; | |||||
} | |||||
} | |||||
// no service found for this | |||||
// shouldn't happen | |||||
conn.Close(); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
conn.Close(); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -9,105 +9,43 @@ using Shadowsocks.Model; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
class Local | |||||
class Local : Listener.Service | |||||
{ | { | ||||
private Server _server; | |||||
private bool _shareOverLAN; | |||||
//private Encryptor encryptor; | |||||
Socket _listener; | |||||
private Configuration _config; | |||||
public Local(Configuration config) | public Local(Configuration config) | ||||
{ | { | ||||
this._server = config.GetCurrentServer(); | |||||
_shareOverLAN = config.shareOverLan; | |||||
//this.encryptor = new Encryptor(config.method, config.password); | |||||
this._config = config; | |||||
} | } | ||||
public void Start() | |||||
public bool Handle(byte[] firstPacket, int length, Socket socket) | |||||
{ | { | ||||
try | |||||
if (length < 2 || firstPacket[0] != 5) | |||||
{ | { | ||||
// 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 (_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); | |||||
_listener.Listen(100); | |||||
// Start an asynchronous socket to listen for connections. | |||||
Console.WriteLine("Shadowsocks started"); | |||||
_listener.BeginAccept( | |||||
new AsyncCallback(AcceptCallback), | |||||
_listener); | |||||
} | |||||
catch(SocketException) | |||||
{ | |||||
_listener.Close(); | |||||
throw; | |||||
return false; | |||||
} | } | ||||
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | |||||
Handler handler = new Handler(); | |||||
handler.connection = socket; | |||||
Server server = _config.GetCurrentServer(); | |||||
handler.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password); | |||||
handler.server = server; | |||||
handler.Start(firstPacket, length); | |||||
return true; | |||||
} | } | ||||
public void Stop() | |||||
{ | |||||
_listener.Close(); | |||||
} | |||||
public void AcceptCallback(IAsyncResult ar) | |||||
{ | |||||
Socket listener = (Socket)ar.AsyncState; | |||||
try | |||||
{ | |||||
Socket conn = listener.EndAccept(ar); | |||||
conn.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | |||||
Handler handler = new Handler(); | |||||
handler.connection = conn; | |||||
handler.encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password); | |||||
handler.config = _server; | |||||
handler.Start(); | |||||
} | |||||
catch | |||||
{ | |||||
//Console.WriteLine(e.Message); | |||||
} | |||||
finally | |||||
{ | |||||
try | |||||
{ | |||||
listener.BeginAccept( | |||||
new AsyncCallback(AcceptCallback), | |||||
listener); | |||||
} | |||||
catch | |||||
{ | |||||
//Console.WriteLine(e.Message); | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
class Handler | class Handler | ||||
{ | { | ||||
//public Encryptor encryptor; | //public Encryptor encryptor; | ||||
public IEncryptor encryptor; | public IEncryptor encryptor; | ||||
public Server config; | |||||
public Server server; | |||||
// Client socket. | // Client socket. | ||||
public Socket remote; | public Socket remote; | ||||
public Socket connection; | public Socket connection; | ||||
private byte[] _firstPacket; | |||||
private int _firstPacketLength; | |||||
// Size of receive buffer. | // Size of receive buffer. | ||||
public const int RecvSize = 16384; | public const int RecvSize = 16384; | ||||
public const int BufferSize = RecvSize + 32; | public const int BufferSize = RecvSize + 32; | ||||
@@ -128,19 +66,21 @@ namespace Shadowsocks.Controller | |||||
private object encryptionLock = new object(); | private object encryptionLock = new object(); | ||||
private object decryptionLock = new object(); | private object decryptionLock = new object(); | ||||
public void Start() | |||||
public void Start(byte[] firstPacket, int length) | |||||
{ | { | ||||
this._firstPacket = firstPacket; | |||||
this._firstPacketLength = length; | |||||
try | try | ||||
{ | { | ||||
// TODO async resolving | // TODO async resolving | ||||
IPAddress ipAddress; | IPAddress ipAddress; | ||||
bool parsed = IPAddress.TryParse(config.server, out ipAddress); | |||||
bool parsed = IPAddress.TryParse(server.server, out ipAddress); | |||||
if (!parsed) | if (!parsed) | ||||
{ | { | ||||
IPHostEntry ipHostInfo = Dns.GetHostEntry(config.server); | |||||
IPHostEntry ipHostInfo = Dns.GetHostEntry(server.server); | |||||
ipAddress = ipHostInfo.AddressList[0]; | ipAddress = ipHostInfo.AddressList[0]; | ||||
} | } | ||||
IPEndPoint remoteEP = new IPEndPoint(ipAddress, config.server_port); | |||||
IPEndPoint remoteEP = new IPEndPoint(ipAddress, server.server_port); | |||||
remote = new Socket(ipAddress.AddressFamily, | remote = new Socket(ipAddress.AddressFamily, | ||||
@@ -240,33 +180,15 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
try | try | ||||
{ | { | ||||
connection.BeginReceive(connetionRecvBuffer, 0, 256, 0, | |||||
new AsyncCallback(HandshakeReceiveCallback), null); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void HandshakeReceiveCallback(IAsyncResult ar) | |||||
{ | |||||
if (closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
int bytesRead = connection.EndReceive(ar); | |||||
int bytesRead = _firstPacketLength; | |||||
if (bytesRead > 1) | if (bytesRead > 1) | ||||
{ | { | ||||
byte[] response = { 5, 0 }; | byte[] response = { 5, 0 }; | ||||
if (connetionRecvBuffer[0] != 5) | |||||
if (_firstPacket[0] != 5) | |||||
{ | { | ||||
// reject socks 4 | // reject socks 4 | ||||
response = new byte[]{ 0, 91 }; | |||||
response = new byte[] { 0, 91 }; | |||||
Console.WriteLine("socks 5 protocol error"); | Console.WriteLine("socks 5 protocol error"); | ||||
} | } | ||||
connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null); | connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null); | ||||
@@ -12,59 +12,73 @@ using System.Text; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
class PACServer | |||||
class PACServer : Listener.Service | |||||
{ | { | ||||
private static int PORT = 8093; | |||||
public static string PAC_FILE = "pac.txt"; | public static string PAC_FILE = "pac.txt"; | ||||
private static Configuration config; | |||||
Socket _listener; | |||||
FileSystemWatcher watcher; | FileSystemWatcher watcher; | ||||
private Configuration _config; | |||||
public event EventHandler PACFileChanged; | public event EventHandler PACFileChanged; | ||||
public void Start(Configuration configuration) | |||||
public PACServer() | |||||
{ | |||||
this.WatchPacFile(); | |||||
} | |||||
public void UpdateConfiguration(Configuration config) | |||||
{ | |||||
this._config = config; | |||||
} | |||||
public bool Handle(byte[] firstPacket, int length, Socket socket) | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
config = configuration; | |||||
// 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) | |||||
string request = Encoding.UTF8.GetString(firstPacket, 0, length); | |||||
string[] lines = request.Split('\r', '\n'); | |||||
bool hostMatch = false, pathMatch = false, useSocks = false; | |||||
foreach (string line in lines) | |||||
{ | { | ||||
localEndPoint = new IPEndPoint(IPAddress.Any, PORT); | |||||
string[] kv = line.Split(new char[]{':'}, 2); | |||||
if (kv.Length == 2) | |||||
{ | |||||
if (kv[0] == "Host") | |||||
{ | |||||
if (kv[1].Trim() == ((IPEndPoint)socket.LocalEndPoint).ToString()) | |||||
{ | |||||
hostMatch = true; | |||||
} | |||||
} | |||||
else if (kv[0] == "User-Agent") | |||||
{ | |||||
if (kv[1].IndexOf("Chrome") >= 0) | |||||
{ | |||||
useSocks = true; | |||||
} | |||||
} | |||||
} | |||||
else if (kv.Length == 1) | |||||
{ | |||||
if (line.IndexOf("pac") >= 0) | |||||
{ | |||||
pathMatch = true; | |||||
} | |||||
} | |||||
} | } | ||||
else | |||||
if (hostMatch && pathMatch) | |||||
{ | { | ||||
localEndPoint = new IPEndPoint(IPAddress.Loopback, PORT); | |||||
SendResponse(firstPacket, length, socket, useSocks); | |||||
return true; | |||||
} | } | ||||
// 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(); | |||||
return false; | |||||
} | } | ||||
catch (SocketException) | |||||
catch (ArgumentException) | |||||
{ | { | ||||
_listener.Close(); | |||||
throw; | |||||
return false; | |||||
} | } | ||||
} | } | ||||
public void Stop() | |||||
{ | |||||
if (_listener != null) | |||||
{ | |||||
_listener.Close(); | |||||
_listener = null; | |||||
} | |||||
} | |||||
public string TouchPACFile() | public string TouchPACFile() | ||||
{ | { | ||||
@@ -79,50 +93,6 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
// we don't even use it | |||||
static byte[] requestBuf = new byte[2048]; | |||||
public void AcceptCallback(IAsyncResult ar) | |||||
{ | |||||
Socket listener = (Socket)ar.AsyncState; | |||||
try | |||||
{ | |||||
Socket conn = listener.EndAccept(ar); | |||||
object[] state = new object[] { | |||||
conn, | |||||
requestBuf | |||||
}; | |||||
conn.BeginReceive(requestBuf, 0, requestBuf.Length, 0, | |||||
new AsyncCallback(ReceiveCallback), state); | |||||
} | |||||
catch (ObjectDisposedException) | |||||
{ | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
} | |||||
finally | |||||
{ | |||||
try | |||||
{ | |||||
listener.BeginAccept( | |||||
new AsyncCallback(AcceptCallback), | |||||
listener); | |||||
} | |||||
catch (ObjectDisposedException) | |||||
{ | |||||
// do nothing | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
} | |||||
} | |||||
} | |||||
private string GetPACContent() | private string GetPACContent() | ||||
{ | { | ||||
if (File.Exists(PAC_FILE)) | if (File.Exists(PAC_FILE)) | ||||
@@ -135,46 +105,33 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
private void ReceiveCallback(IAsyncResult ar) | |||||
public void SendResponse(byte[] firstPacket, int length, Socket socket, bool useSocks) | |||||
{ | { | ||||
object[] state = (object[])ar.AsyncState; | |||||
Socket conn = (Socket)state[0]; | |||||
byte[] requestBuf = (byte[])state[1]; | |||||
try | try | ||||
{ | { | ||||
int bytesRead = conn.EndReceive(ar); | |||||
string pac = GetPACContent(); | string pac = GetPACContent(); | ||||
IPEndPoint localEndPoint = (IPEndPoint)conn.LocalEndPoint; | |||||
IPEndPoint localEndPoint = (IPEndPoint)socket.LocalEndPoint; | |||||
string proxy = GetPACAddress(requestBuf, localEndPoint); | |||||
string proxy = GetPACAddress(firstPacket, length, localEndPoint, useSocks); | |||||
pac = pac.Replace("__PROXY__", proxy); | pac = pac.Replace("__PROXY__", proxy); | ||||
if (bytesRead > 0) | |||||
{ | |||||
string text = String.Format(@"HTTP/1.1 200 OK | |||||
string text = String.Format(@"HTTP/1.1 200 OK | |||||
Server: Shadowsocks | Server: Shadowsocks | ||||
Content-Type: application/x-ns-proxy-autoconfig | Content-Type: application/x-ns-proxy-autoconfig | ||||
Content-Length: {0} | Content-Length: {0} | ||||
Connection: Close | Connection: Close | ||||
", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac; | ", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac; | ||||
byte[] response = System.Text.Encoding.UTF8.GetBytes(text); | |||||
conn.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), conn); | |||||
Util.Utils.ReleaseMemory(); | |||||
} | |||||
else | |||||
{ | |||||
conn.Close(); | |||||
} | |||||
byte[] response = System.Text.Encoding.UTF8.GetBytes(text); | |||||
socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket); | |||||
Util.Utils.ReleaseMemory(); | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine(e); | Console.WriteLine(e); | ||||
conn.Close(); | |||||
socket.Close(); | |||||
} | } | ||||
} | } | ||||
@@ -213,9 +170,8 @@ Connection: Close | |||||
} | } | ||||
} | } | ||||
private string GetPACAddress(byte[] requestBuf, IPEndPoint localEndPoint) | |||||
private string GetPACAddress(byte[] requestBuf, int length, IPEndPoint localEndPoint, bool useSocks) | |||||
{ | { | ||||
string proxy = "PROXY " + localEndPoint.Address + ":8123;"; | |||||
//try | //try | ||||
//{ | //{ | ||||
// string requestString = Encoding.UTF8.GetString(requestBuf); | // string requestString = Encoding.UTF8.GetString(requestBuf); | ||||
@@ -229,7 +185,7 @@ Connection: Close | |||||
//{ | //{ | ||||
// Console.WriteLine(e); | // Console.WriteLine(e); | ||||
//} | //} | ||||
return proxy; | |||||
return (useSocks ? "SOCKS5 " : "PROXY ") + localEndPoint.Address + ":" + this._config.localPort + ";"; | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -6,6 +6,8 @@ using System.Diagnostics; | |||||
using System.IO; | using System.IO; | ||||
using System.IO.Compression; | using System.IO.Compression; | ||||
using System.Text; | using System.Text; | ||||
using System.Net.NetworkInformation; | |||||
using System.Net; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
@@ -13,6 +15,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
private Process _process; | private Process _process; | ||||
private static string temppath; | private static string temppath; | ||||
private int _runningPort; | |||||
static PolipoRunner() | static PolipoRunner() | ||||
{ | { | ||||
@@ -27,6 +30,14 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
public int RunningPort | |||||
{ | |||||
get | |||||
{ | |||||
return _runningPort; | |||||
} | |||||
} | |||||
public void Start(Configuration configuration) | public void Start(Configuration configuration) | ||||
{ | { | ||||
Server server = configuration.GetCurrentServer(); | Server server = configuration.GetCurrentServer(); | ||||
@@ -45,8 +56,10 @@ namespace Shadowsocks.Controller | |||||
Console.WriteLine(e.ToString()); | Console.WriteLine(e.ToString()); | ||||
} | } | ||||
} | } | ||||
string polipoConfig = Resources.polipo_config; | |||||
polipoConfig = polipoConfig.Replace("__SOCKS_PORT__", server.local_port.ToString()); | |||||
string polipoConfig = Resources.polipo_config; | |||||
_runningPort = this.GetFreePort(); | |||||
polipoConfig = polipoConfig.Replace("__SOCKS_PORT__", configuration.localPort.ToString()); | |||||
polipoConfig = polipoConfig.Replace("__POLIPO_BIND_PORT__", _runningPort.ToString()); | |||||
polipoConfig = polipoConfig.Replace("__POLIPO_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1"); | 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.ByteArrayToFile(temppath + "/polipo.conf", System.Text.Encoding.UTF8.GetBytes(polipoConfig)); | ||||
@@ -79,5 +92,35 @@ namespace Shadowsocks.Controller | |||||
_process = null; | _process = null; | ||||
} | } | ||||
} | } | ||||
private int GetFreePort() | |||||
{ | |||||
int defaultPort = 8123; | |||||
try | |||||
{ | |||||
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties(); | |||||
IPEndPoint[] tcpEndPoints = properties.GetActiveTcpListeners(); | |||||
List<int> usedPorts = new List<int>(); | |||||
foreach (IPEndPoint endPoint in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()) | |||||
{ | |||||
usedPorts.Add(endPoint.Port); | |||||
} | |||||
for (int port = defaultPort; port <= 65535; port++) | |||||
{ | |||||
if (!usedPorts.Contains(port)) | |||||
{ | |||||
return port; | |||||
} | |||||
} | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
// in case access denied | |||||
Logging.LogUsefulException(e); | |||||
return defaultPort; | |||||
} | |||||
throw new Exception("No free port found."); | |||||
} | |||||
} | } | ||||
} | } |
@@ -0,0 +1,264 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Net; | |||||
using System.Net.Sockets; | |||||
using System.Text; | |||||
namespace Shadowsocks.Controller | |||||
{ | |||||
class PortForwarder : Listener.Service | |||||
{ | |||||
int _targetPort; | |||||
public PortForwarder(int targetPort) | |||||
{ | |||||
this._targetPort = targetPort; | |||||
} | |||||
public bool Handle(byte[] firstPacket, int length, Socket socket) | |||||
{ | |||||
new Handler().Start(firstPacket, length, socket, this._targetPort); | |||||
return true; | |||||
} | |||||
class Handler | |||||
{ | |||||
private byte[] _firstPacket; | |||||
private int _firstPacketLength; | |||||
private Socket _local; | |||||
private Socket _remote; | |||||
private bool _closed = false; | |||||
private bool _localShutdown = false; | |||||
private bool _remoteShutdown = false; | |||||
public const int RecvSize = 16384; | |||||
// remote receive buffer | |||||
private byte[] remoteRecvBuffer = new byte[RecvSize]; | |||||
// connection receive buffer | |||||
private byte[] connetionRecvBuffer = new byte[RecvSize]; | |||||
public void Start(byte[] firstPacket, int length, Socket socket, int targetPort) | |||||
{ | |||||
this._firstPacket = firstPacket; | |||||
this._firstPacketLength = length; | |||||
this._local = socket; | |||||
try | |||||
{ | |||||
// TODO async resolving | |||||
IPAddress ipAddress; | |||||
bool parsed = IPAddress.TryParse("127.0.0.1", out ipAddress); | |||||
IPEndPoint remoteEP = new IPEndPoint(ipAddress, targetPort); | |||||
_remote = new Socket(ipAddress.AddressFamily, | |||||
SocketType.Stream, ProtocolType.Tcp); | |||||
_remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | |||||
// Connect to the remote endpoint. | |||||
_remote.BeginConnect(remoteEP, | |||||
new AsyncCallback(ConnectCallback), null); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void ConnectCallback(IAsyncResult ar) | |||||
{ | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
_remote.EndConnect(ar); | |||||
HandshakeReceive(); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void HandshakeReceive() | |||||
{ | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
_remote.BeginSend(_firstPacket, 0, _firstPacketLength, 0, new AsyncCallback(StartPipe), null); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void StartPipe(IAsyncResult ar) | |||||
{ | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
_remote.EndSend(ar); | |||||
_remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0, | |||||
new AsyncCallback(PipeRemoteReceiveCallback), null); | |||||
_local.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, | |||||
new AsyncCallback(PipeConnectionReceiveCallback), null); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void PipeRemoteReceiveCallback(IAsyncResult ar) | |||||
{ | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
int bytesRead = _remote.EndReceive(ar); | |||||
if (bytesRead > 0) | |||||
{ | |||||
_local.BeginSend(remoteRecvBuffer, 0, bytesRead, 0, new AsyncCallback(PipeConnectionSendCallback), null); | |||||
} | |||||
else | |||||
{ | |||||
//Console.WriteLine("bytesRead: " + bytesRead.ToString()); | |||||
_local.Shutdown(SocketShutdown.Send); | |||||
_localShutdown = true; | |||||
CheckClose(); | |||||
} | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void PipeConnectionReceiveCallback(IAsyncResult ar) | |||||
{ | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
int bytesRead = _local.EndReceive(ar); | |||||
if (bytesRead > 0) | |||||
{ | |||||
_remote.BeginSend(connetionRecvBuffer, 0, bytesRead, 0, new AsyncCallback(PipeRemoteSendCallback), null); | |||||
} | |||||
else | |||||
{ | |||||
_remote.Shutdown(SocketShutdown.Send); | |||||
_remoteShutdown = true; | |||||
CheckClose(); | |||||
} | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void PipeRemoteSendCallback(IAsyncResult ar) | |||||
{ | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
_remote.EndSend(ar); | |||||
_local.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0, | |||||
new AsyncCallback(PipeConnectionReceiveCallback), null); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void PipeConnectionSendCallback(IAsyncResult ar) | |||||
{ | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
_local.EndSend(ar); | |||||
_remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0, | |||||
new AsyncCallback(PipeRemoteReceiveCallback), null); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
this.Close(); | |||||
} | |||||
} | |||||
private void CheckClose() | |||||
{ | |||||
if (_localShutdown && _remoteShutdown) | |||||
{ | |||||
this.Close(); | |||||
} | |||||
} | |||||
public void Close() | |||||
{ | |||||
lock (this) | |||||
{ | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
_closed = true; | |||||
} | |||||
if (_local != null) | |||||
{ | |||||
try | |||||
{ | |||||
_local.Shutdown(SocketShutdown.Both); | |||||
_local.Close(); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
} | |||||
} | |||||
if (_remote != null) | |||||
{ | |||||
try | |||||
{ | |||||
_remote.Shutdown(SocketShutdown.Both); | |||||
_remote.Close(); | |||||
} | |||||
catch (SocketException e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -17,8 +17,8 @@ namespace Shadowsocks.Controller | |||||
private Thread _ramThread; | private Thread _ramThread; | ||||
private Local local; | |||||
private PACServer pacServer; | |||||
private Listener _listener; | |||||
private PACServer _pacServer; | |||||
private Configuration _config; | private Configuration _config; | ||||
private PolipoRunner polipoRunner; | private PolipoRunner polipoRunner; | ||||
private GFWListUpdater gfwListUpdater; | private GFWListUpdater gfwListUpdater; | ||||
@@ -74,9 +74,10 @@ namespace Shadowsocks.Controller | |||||
return Configuration.Load(); | return Configuration.Load(); | ||||
} | } | ||||
public void SaveServers(List<Server> servers) | |||||
public void SaveServers(List<Server> servers, int localPort) | |||||
{ | { | ||||
_config.configs = servers; | _config.configs = servers; | ||||
_config.localPort = localPort; | |||||
SaveConfig(_config); | SaveConfig(_config); | ||||
} | } | ||||
@@ -142,9 +143,9 @@ namespace Shadowsocks.Controller | |||||
return; | return; | ||||
} | } | ||||
stopped = true; | stopped = true; | ||||
if (local != null) | |||||
if (_listener != null) | |||||
{ | { | ||||
local.Stop(); | |||||
_listener.Stop(); | |||||
} | } | ||||
if (polipoRunner != null) | if (polipoRunner != null) | ||||
{ | { | ||||
@@ -152,13 +153,13 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
if (_config.enabled) | if (_config.enabled) | ||||
{ | { | ||||
SystemProxy.Disable(); | |||||
SystemProxy.Update(_config, true); | |||||
} | } | ||||
} | } | ||||
public void TouchPACFile() | public void TouchPACFile() | ||||
{ | { | ||||
string pacFilename = pacServer.TouchPACFile(); | |||||
string pacFilename = _pacServer.TouchPACFile(); | |||||
if (PACFileReadyToOpen != null) | if (PACFileReadyToOpen != null) | ||||
{ | { | ||||
PACFileReadyToOpen(this, new PathEventArgs() { Path = pacFilename }); | PACFileReadyToOpen(this, new PathEventArgs() { Path = pacFilename }); | ||||
@@ -177,7 +178,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
if (gfwListUpdater != null) | if (gfwListUpdater != null) | ||||
{ | { | ||||
gfwListUpdater.UpdatePACFromGFWList(); | |||||
gfwListUpdater.UpdatePACFromGFWList(_config); | |||||
} | } | ||||
} | } | ||||
@@ -190,11 +191,12 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
polipoRunner = new PolipoRunner(); | polipoRunner = new PolipoRunner(); | ||||
} | } | ||||
if (pacServer == null) | |||||
if (_pacServer == null) | |||||
{ | { | ||||
pacServer = new PACServer(); | |||||
pacServer.PACFileChanged += pacServer_PACFileChanged; | |||||
_pacServer = new PACServer(); | |||||
_pacServer.PACFileChanged += pacServer_PACFileChanged; | |||||
} | } | ||||
_pacServer.UpdateConfiguration(_config); | |||||
if (gfwListUpdater == null) | if (gfwListUpdater == null) | ||||
{ | { | ||||
gfwListUpdater = new GFWListUpdater(); | gfwListUpdater = new GFWListUpdater(); | ||||
@@ -202,11 +204,9 @@ namespace Shadowsocks.Controller | |||||
gfwListUpdater.Error += pacServer_PACUpdateError; | gfwListUpdater.Error += pacServer_PACUpdateError; | ||||
} | } | ||||
pacServer.Stop(); | |||||
if (local != null) | |||||
if (_listener != null) | |||||
{ | { | ||||
local.Stop(); | |||||
_listener.Stop(); | |||||
} | } | ||||
// don't put polipoRunner.Start() before pacServer.Stop() | // don't put polipoRunner.Start() before pacServer.Stop() | ||||
@@ -218,9 +218,13 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
polipoRunner.Start(_config); | polipoRunner.Start(_config); | ||||
local = new Local(_config); | |||||
local.Start(); | |||||
pacServer.Start(_config); | |||||
Local local = new Local(_config); | |||||
List<Listener.Service> services = new List<Listener.Service>(); | |||||
services.Add(local); | |||||
services.Add(_pacServer); | |||||
services.Add(new PortForwarder(polipoRunner.RunningPort)); | |||||
_listener = new Listener(services); | |||||
_listener.Start(_config); | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
@@ -259,7 +263,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
if (_config.enabled) | if (_config.enabled) | ||||
{ | { | ||||
SystemProxy.Enable(_config.global); | |||||
SystemProxy.Update(_config, false); | |||||
_systemProxyIsDirty = true; | _systemProxyIsDirty = true; | ||||
} | } | ||||
else | else | ||||
@@ -267,7 +271,7 @@ namespace Shadowsocks.Controller | |||||
// only switch it off if we have switched it on | // only switch it off if we have switched it on | ||||
if (_systemProxyIsDirty) | if (_systemProxyIsDirty) | ||||
{ | { | ||||
SystemProxy.Disable(); | |||||
SystemProxy.Update(_config, false); | |||||
_systemProxyIsDirty = false; | _systemProxyIsDirty = false; | ||||
} | } | ||||
} | } | ||||
@@ -5,6 +5,7 @@ using System.Collections.Generic; | |||||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
using System.Text; | using System.Text; | ||||
using System.IO; | using System.IO; | ||||
using Shadowsocks.Model; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
@@ -25,24 +26,39 @@ namespace Shadowsocks.Controller | |||||
_refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0); | _refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0); | ||||
} | } | ||||
public static void Enable(bool global) | |||||
public static void Update(Configuration config, bool forceDisable) | |||||
{ | { | ||||
bool global = config.global; | |||||
bool enabled = config.enabled; | |||||
if (forceDisable) | |||||
{ | |||||
enabled = false; | |||||
} | |||||
try | try | ||||
{ | { | ||||
RegistryKey registry = | RegistryKey registry = | ||||
Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", | Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", | ||||
true); | true); | ||||
if (global) | |||||
if (enabled) | |||||
{ | { | ||||
registry.SetValue("ProxyEnable", 1); | |||||
registry.SetValue("ProxyServer", "127.0.0.1:8123"); | |||||
registry.SetValue("AutoConfigURL", ""); | |||||
if (global) | |||||
{ | |||||
registry.SetValue("ProxyEnable", 1); | |||||
registry.SetValue("ProxyServer", "127.0.0.1:" + config.localPort.ToString()); | |||||
registry.SetValue("AutoConfigURL", ""); | |||||
} | |||||
else | |||||
{ | |||||
registry.SetValue("ProxyEnable", 0); | |||||
registry.SetValue("ProxyServer", ""); | |||||
registry.SetValue("AutoConfigURL", "http://127.0.0.1:" + config.localPort.ToString() + "/pac?t=" + GetTimestamp(DateTime.Now)); | |||||
} | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
registry.SetValue("ProxyEnable", 0); | registry.SetValue("ProxyEnable", 0); | ||||
registry.SetValue("ProxyServer", ""); | registry.SetValue("ProxyServer", ""); | ||||
registry.SetValue("AutoConfigURL", "http://127.0.0.1:8093/pac?t=" + GetTimestamp(DateTime.Now)); | |||||
registry.SetValue("AutoConfigURL", ""); | |||||
} | } | ||||
SystemProxy.NotifyIE(); | SystemProxy.NotifyIE(); | ||||
//Must Notify IE first, or the connections do not chanage | //Must Notify IE first, or the connections do not chanage | ||||
@@ -56,27 +72,6 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
public static void Disable() | |||||
{ | |||||
try | |||||
{ | |||||
RegistryKey registry = | |||||
Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", | |||||
true); | |||||
registry.SetValue("ProxyEnable", 0); | |||||
registry.SetValue("ProxyServer", ""); | |||||
registry.SetValue("AutoConfigURL", ""); | |||||
SystemProxy.NotifyIE(); | |||||
CopyProxySettingFromLan(); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
// TODO this should be moved into views | |||||
MessageBox.Show(I18N.GetString("Failed to update registry")); | |||||
} | |||||
} | |||||
private static void CopyProxySettingFromLan() | private static void CopyProxySettingFromLan() | ||||
{ | { | ||||
RegistryKey registry = | RegistryKey registry = | ||||
@@ -1,4 +1,5 @@ | |||||
using System; | |||||
using Shadowsocks.Model; | |||||
using System; | |||||
using System.Collections; | using System.Collections; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Net; | using System.Net; | ||||
@@ -17,13 +18,13 @@ namespace Shadowsocks.Controller | |||||
public string LatestVersionURL; | public string LatestVersionURL; | ||||
public event EventHandler NewVersionFound; | public event EventHandler NewVersionFound; | ||||
public const string Version = "2.2"; | |||||
public const string Version = "2.3"; | |||||
public void CheckUpdate() | |||||
public void CheckUpdate(Configuration config) | |||||
{ | { | ||||
// TODO test failures | // TODO test failures | ||||
WebClient http = new WebClient(); | WebClient http = new WebClient(); | ||||
http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), 8123); | |||||
http.Proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort); | |||||
http.DownloadStringCompleted += http_DownloadStringCompleted; | http.DownloadStringCompleted += http_DownloadStringCompleted; | ||||
http.DownloadStringAsync(new Uri(UpdateURL)); | http.DownloadStringAsync(new Uri(UpdateURL)); | ||||
} | } | ||||
@@ -74,6 +75,10 @@ namespace Shadowsocks.Controller | |||||
private bool IsNewVersion(string url) | private bool IsNewVersion(string url) | ||||
{ | { | ||||
if (url.IndexOf("prerelease") >= 0) | |||||
{ | |||||
return false; | |||||
} | |||||
// check dotnet 4.0 | // check dotnet 4.0 | ||||
AssemblyName[] references = Assembly.GetExecutingAssembly().GetReferencedAssemblies(); | AssemblyName[] references = Assembly.GetExecutingAssembly().GetReferencedAssemblies(); | ||||
Version dotNetVersion = Environment.Version; | Version dotNetVersion = Environment.Version; | ||||
@@ -1,5 +1,5 @@ | |||||
Shadowsocks=Shadowsocks | Shadowsocks=Shadowsocks | ||||
Enable=启用代理 | |||||
Enable System Proxy=启用系统代理 | |||||
Mode=代理模式 | Mode=代理模式 | ||||
PAC=PAC 模式 | PAC=PAC 模式 | ||||
Global=全局模式 | Global=全局模式 | ||||
@@ -1,4 +1,5 @@ | |||||
proxyAddress = "__POLIPO_BIND_IP__" | |||||
proxyAddress = "__POLIPO_BIND_IP__" | |||||
proxyPort = 8123 | |||||
socksParentProxy = "127.0.0.1:__SOCKS_PORT__" | socksParentProxy = "127.0.0.1:__SOCKS_PORT__" | ||||
socksProxyType = socks5 | socksProxyType = socks5 | ||||
@@ -16,6 +16,7 @@ namespace Shadowsocks.Model | |||||
public bool enabled; | public bool enabled; | ||||
public bool shareOverLan; | public bool shareOverLan; | ||||
public bool isDefault; | public bool isDefault; | ||||
public int localPort; | |||||
private static string CONFIG_FILE = "gui-config.json"; | private static string CONFIG_FILE = "gui-config.json"; | ||||
@@ -33,7 +34,6 @@ namespace Shadowsocks.Model | |||||
public static void CheckServer(Server server) | public static void CheckServer(Server server) | ||||
{ | { | ||||
CheckPort(server.local_port); | |||||
CheckPort(server.server_port); | CheckPort(server.server_port); | ||||
CheckPassword(server.password); | CheckPassword(server.password); | ||||
CheckServer(server.server); | CheckServer(server.server); | ||||
@@ -46,6 +46,10 @@ namespace Shadowsocks.Model | |||||
string configContent = File.ReadAllText(CONFIG_FILE); | string configContent = File.ReadAllText(CONFIG_FILE); | ||||
Configuration config = SimpleJson.SimpleJson.DeserializeObject<Configuration>(configContent, new JsonSerializerStrategy()); | Configuration config = SimpleJson.SimpleJson.DeserializeObject<Configuration>(configContent, new JsonSerializerStrategy()); | ||||
config.isDefault = false; | config.isDefault = false; | ||||
if (config.localPort == 0) | |||||
{ | |||||
config.localPort = 1080; | |||||
} | |||||
return config; | return config; | ||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
@@ -58,6 +62,7 @@ namespace Shadowsocks.Model | |||||
{ | { | ||||
index = 0, | index = 0, | ||||
isDefault = true, | isDefault = true, | ||||
localPort = 1080, | |||||
configs = new List<Server>() | configs = new List<Server>() | ||||
{ | { | ||||
GetDefaultServer() | GetDefaultServer() | ||||
@@ -105,7 +110,7 @@ namespace Shadowsocks.Model | |||||
} | } | ||||
} | } | ||||
private static void CheckPort(int port) | |||||
public static void CheckPort(int port) | |||||
{ | { | ||||
if (port <= 0 || port > 65535) | if (port <= 0 || port > 65535) | ||||
{ | { | ||||
@@ -1,4 +1,4 @@ | |||||
using System; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
using System.IO; | using System.IO; | ||||
@@ -14,7 +14,6 @@ namespace Shadowsocks.Model | |||||
{ | { | ||||
public string server; | public string server; | ||||
public int server_port; | public int server_port; | ||||
public int local_port; | |||||
public string password; | public string password; | ||||
public string method; | public string method; | ||||
public string remarks; | public string remarks; | ||||
@@ -39,7 +38,6 @@ namespace Shadowsocks.Model | |||||
{ | { | ||||
this.server = ""; | this.server = ""; | ||||
this.server_port = 8388; | this.server_port = 8388; | ||||
this.local_port = 1080; | |||||
this.method = "aes-256-cfb"; | this.method = "aes-256-cfb"; | ||||
this.password = ""; | this.password = ""; | ||||
this.remarks = ""; | this.remarks = ""; | ||||
@@ -50,7 +48,8 @@ namespace Shadowsocks.Model | |||||
string[] r1 = Regex.Split(ssURL, "ss://", RegexOptions.IgnoreCase); | string[] r1 = Regex.Split(ssURL, "ss://", RegexOptions.IgnoreCase); | ||||
string base64 = r1[1].ToString(); | string base64 = r1[1].ToString(); | ||||
byte[] bytes = null; | byte[] bytes = null; | ||||
for (var i = 0; i < 3; i++) { | |||||
for (var i = 0; i < 3; i++) | |||||
{ | |||||
try | try | ||||
{ | { | ||||
bytes = System.Convert.FromBase64String(base64); | bytes = System.Convert.FromBase64String(base64); | ||||
@@ -64,11 +63,25 @@ namespace Shadowsocks.Model | |||||
{ | { | ||||
throw new FormatException(); | throw new FormatException(); | ||||
} | } | ||||
string[] parts = Encoding.UTF8.GetString(bytes).Split(new char[2] { ':', '@' }); | |||||
this.method = parts[0].ToString(); | |||||
this.password = parts[1].ToString(); | |||||
this.server = parts[2].ToString(); | |||||
this.server_port = int.Parse(parts[3].ToString()); | |||||
try | |||||
{ | |||||
string data = Encoding.UTF8.GetString(bytes); | |||||
int indexLastAt = data.LastIndexOf('@'); | |||||
string afterAt = data.Substring(indexLastAt + 1); | |||||
int indexLastColon = afterAt.LastIndexOf(':'); | |||||
this.server_port = int.Parse(afterAt.Substring(indexLastColon + 1)); | |||||
this.server = afterAt.Substring(0, indexLastColon); | |||||
string beforeAt = data.Substring(0, indexLastAt); | |||||
string[] parts = beforeAt.Split(new[] { ':' }); | |||||
this.method = parts[0]; | |||||
this.password = parts[1]; | |||||
} | |||||
catch (IndexOutOfRangeException) | |||||
{ | |||||
throw new FormatException(); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -33,8 +33,6 @@ | |||||
this.RemarksLabel = new System.Windows.Forms.Label(); | this.RemarksLabel = new System.Windows.Forms.Label(); | ||||
this.IPLabel = new System.Windows.Forms.Label(); | this.IPLabel = new System.Windows.Forms.Label(); | ||||
this.ServerPortLabel = new System.Windows.Forms.Label(); | this.ServerPortLabel = new System.Windows.Forms.Label(); | ||||
this.ProxyPortTextBox = new System.Windows.Forms.TextBox(); | |||||
this.ProxyPortLabel = new System.Windows.Forms.Label(); | |||||
this.PasswordLabel = new System.Windows.Forms.Label(); | this.PasswordLabel = new System.Windows.Forms.Label(); | ||||
this.IPTextBox = new System.Windows.Forms.TextBox(); | this.IPTextBox = new System.Windows.Forms.TextBox(); | ||||
this.ServerPortTextBox = new System.Windows.Forms.TextBox(); | this.ServerPortTextBox = new System.Windows.Forms.TextBox(); | ||||
@@ -49,11 +47,15 @@ | |||||
this.ServerGroupBox = new System.Windows.Forms.GroupBox(); | this.ServerGroupBox = new System.Windows.Forms.GroupBox(); | ||||
this.ServersListBox = new System.Windows.Forms.ListBox(); | this.ServersListBox = new System.Windows.Forms.ListBox(); | ||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); | this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); | ||||
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel(); | |||||
this.ProxyPortTextBox = new System.Windows.Forms.TextBox(); | |||||
this.ProxyPortLabel = new System.Windows.Forms.Label(); | |||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); | this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); | ||||
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); | this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); | ||||
this.tableLayoutPanel1.SuspendLayout(); | this.tableLayoutPanel1.SuspendLayout(); | ||||
this.ServerGroupBox.SuspendLayout(); | this.ServerGroupBox.SuspendLayout(); | ||||
this.tableLayoutPanel2.SuspendLayout(); | this.tableLayoutPanel2.SuspendLayout(); | ||||
this.tableLayoutPanel5.SuspendLayout(); | |||||
this.tableLayoutPanel3.SuspendLayout(); | this.tableLayoutPanel3.SuspendLayout(); | ||||
this.tableLayoutPanel4.SuspendLayout(); | this.tableLayoutPanel4.SuspendLayout(); | ||||
this.SuspendLayout(); | this.SuspendLayout(); | ||||
@@ -69,8 +71,6 @@ | |||||
this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 5); | this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 5); | ||||
this.tableLayoutPanel1.Controls.Add(this.IPLabel, 0, 0); | this.tableLayoutPanel1.Controls.Add(this.IPLabel, 0, 0); | ||||
this.tableLayoutPanel1.Controls.Add(this.ServerPortLabel, 0, 1); | this.tableLayoutPanel1.Controls.Add(this.ServerPortLabel, 0, 1); | ||||
this.tableLayoutPanel1.Controls.Add(this.ProxyPortTextBox, 1, 4); | |||||
this.tableLayoutPanel1.Controls.Add(this.ProxyPortLabel, 0, 4); | |||||
this.tableLayoutPanel1.Controls.Add(this.PasswordLabel, 0, 2); | this.tableLayoutPanel1.Controls.Add(this.PasswordLabel, 0, 2); | ||||
this.tableLayoutPanel1.Controls.Add(this.IPTextBox, 1, 0); | this.tableLayoutPanel1.Controls.Add(this.IPTextBox, 1, 0); | ||||
this.tableLayoutPanel1.Controls.Add(this.ServerPortTextBox, 1, 1); | this.tableLayoutPanel1.Controls.Add(this.ServerPortTextBox, 1, 1); | ||||
@@ -88,13 +88,13 @@ | |||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | ||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | ||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | ||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(238, 163); | |||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(238, 137); | |||||
this.tableLayoutPanel1.TabIndex = 0; | this.tableLayoutPanel1.TabIndex = 0; | ||||
// | // | ||||
// RemarksTextBox | // RemarksTextBox | ||||
// | // | ||||
this.RemarksTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); | this.RemarksTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); | ||||
this.RemarksTextBox.Location = new System.Drawing.Point(72, 137); | |||||
this.RemarksTextBox.Location = new System.Drawing.Point(72, 111); | |||||
this.RemarksTextBox.MaxLength = 32; | this.RemarksTextBox.MaxLength = 32; | ||||
this.RemarksTextBox.Name = "RemarksTextBox"; | this.RemarksTextBox.Name = "RemarksTextBox"; | ||||
this.RemarksTextBox.Size = new System.Drawing.Size(160, 20); | this.RemarksTextBox.Size = new System.Drawing.Size(160, 20); | ||||
@@ -105,7 +105,7 @@ | |||||
// | // | ||||
this.RemarksLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; | this.RemarksLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; | ||||
this.RemarksLabel.AutoSize = true; | this.RemarksLabel.AutoSize = true; | ||||
this.RemarksLabel.Location = new System.Drawing.Point(17, 140); | |||||
this.RemarksLabel.Location = new System.Drawing.Point(17, 114); | |||||
this.RemarksLabel.Name = "RemarksLabel"; | this.RemarksLabel.Name = "RemarksLabel"; | ||||
this.RemarksLabel.Size = new System.Drawing.Size(49, 13); | this.RemarksLabel.Size = new System.Drawing.Size(49, 13); | ||||
this.RemarksLabel.TabIndex = 9; | this.RemarksLabel.TabIndex = 9; | ||||
@@ -131,26 +131,6 @@ | |||||
this.ServerPortLabel.TabIndex = 1; | this.ServerPortLabel.TabIndex = 1; | ||||
this.ServerPortLabel.Text = "Server Port"; | this.ServerPortLabel.Text = "Server Port"; | ||||
// | // | ||||
// ProxyPortTextBox | |||||
// | |||||
this.ProxyPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); | |||||
this.ProxyPortTextBox.Location = new System.Drawing.Point(72, 111); | |||||
this.ProxyPortTextBox.MaxLength = 10; | |||||
this.ProxyPortTextBox.Name = "ProxyPortTextBox"; | |||||
this.ProxyPortTextBox.Size = new System.Drawing.Size(160, 20); | |||||
this.ProxyPortTextBox.TabIndex = 4; | |||||
this.ProxyPortTextBox.WordWrap = false; | |||||
// | |||||
// ProxyPortLabel | |||||
// | |||||
this.ProxyPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; | |||||
this.ProxyPortLabel.AutoSize = true; | |||||
this.ProxyPortLabel.Location = new System.Drawing.Point(11, 114); | |||||
this.ProxyPortLabel.Name = "ProxyPortLabel"; | |||||
this.ProxyPortLabel.Size = new System.Drawing.Size(55, 13); | |||||
this.ProxyPortLabel.TabIndex = 3; | |||||
this.ProxyPortLabel.Text = "Proxy Port"; | |||||
// | |||||
// PasswordLabel | // PasswordLabel | ||||
// | // | ||||
this.PasswordLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; | this.PasswordLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; | ||||
@@ -292,7 +272,7 @@ | |||||
this.ServerGroupBox.Location = new System.Drawing.Point(178, 0); | this.ServerGroupBox.Location = new System.Drawing.Point(178, 0); | ||||
this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(12, 0, 0, 0); | this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(12, 0, 0, 0); | ||||
this.ServerGroupBox.Name = "ServerGroupBox"; | this.ServerGroupBox.Name = "ServerGroupBox"; | ||||
this.ServerGroupBox.Size = new System.Drawing.Size(249, 200); | |||||
this.ServerGroupBox.Size = new System.Drawing.Size(249, 174); | |||||
this.ServerGroupBox.TabIndex = 6; | this.ServerGroupBox.TabIndex = 6; | ||||
this.ServerGroupBox.TabStop = false; | this.ServerGroupBox.TabStop = false; | ||||
this.ServerGroupBox.Text = "Server"; | this.ServerGroupBox.Text = "Server"; | ||||
@@ -315,6 +295,7 @@ | |||||
this.tableLayoutPanel2.ColumnCount = 2; | this.tableLayoutPanel2.ColumnCount = 2; | ||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); | this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); | ||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); | this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); | ||||
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel5, 1, 1); | |||||
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 1, 2); | this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 1, 2); | ||||
this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0); | this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0); | ||||
this.tableLayoutPanel2.Controls.Add(this.ServerGroupBox, 1, 0); | this.tableLayoutPanel2.Controls.Add(this.ServerGroupBox, 1, 0); | ||||
@@ -326,9 +307,53 @@ | |||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); | this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); | ||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); | this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); | ||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); | this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); | ||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 264); | |||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 238); | |||||
this.tableLayoutPanel2.TabIndex = 7; | this.tableLayoutPanel2.TabIndex = 7; | ||||
// | // | ||||
// tableLayoutPanel5 | |||||
// | |||||
this.tableLayoutPanel5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||||
| System.Windows.Forms.AnchorStyles.Right))); | |||||
this.tableLayoutPanel5.AutoSize = true; | |||||
this.tableLayoutPanel5.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; | |||||
this.tableLayoutPanel5.ColumnCount = 2; | |||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); | |||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); | |||||
this.tableLayoutPanel5.Controls.Add(this.ProxyPortTextBox, 1, 0); | |||||
this.tableLayoutPanel5.Controls.Add(this.ProxyPortLabel, 0, 0); | |||||
this.tableLayoutPanel5.Location = new System.Drawing.Point(241, 174); | |||||
this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0); | |||||
this.tableLayoutPanel5.Name = "tableLayoutPanel5"; | |||||
this.tableLayoutPanel5.Padding = new System.Windows.Forms.Padding(3); | |||||
this.tableLayoutPanel5.RowCount = 1; | |||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle()); | |||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26F)); | |||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26F)); | |||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26F)); | |||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26F)); | |||||
this.tableLayoutPanel5.Size = new System.Drawing.Size(186, 32); | |||||
this.tableLayoutPanel5.TabIndex = 9; | |||||
// | |||||
// ProxyPortTextBox | |||||
// | |||||
this.ProxyPortTextBox.Anchor = System.Windows.Forms.AnchorStyles.Left; | |||||
this.ProxyPortTextBox.Location = new System.Drawing.Point(67, 6); | |||||
this.ProxyPortTextBox.MaxLength = 10; | |||||
this.ProxyPortTextBox.Name = "ProxyPortTextBox"; | |||||
this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 20); | |||||
this.ProxyPortTextBox.TabIndex = 4; | |||||
this.ProxyPortTextBox.WordWrap = false; | |||||
// | |||||
// ProxyPortLabel | |||||
// | |||||
this.ProxyPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; | |||||
this.ProxyPortLabel.AutoSize = true; | |||||
this.ProxyPortLabel.Location = new System.Drawing.Point(6, 9); | |||||
this.ProxyPortLabel.Name = "ProxyPortLabel"; | |||||
this.ProxyPortLabel.Size = new System.Drawing.Size(55, 13); | |||||
this.ProxyPortLabel.TabIndex = 3; | |||||
this.ProxyPortLabel.Text = "Proxy Port"; | |||||
// | |||||
// tableLayoutPanel3 | // tableLayoutPanel3 | ||||
// | // | ||||
this.tableLayoutPanel3.AutoSize = true; | this.tableLayoutPanel3.AutoSize = true; | ||||
@@ -340,7 +365,7 @@ | |||||
this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0); | this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0); | ||||
this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0); | this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0); | ||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right; | this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right; | ||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(268, 235); | |||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(268, 209); | |||||
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3); | this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3); | ||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3"; | this.tableLayoutPanel3.Name = "tableLayoutPanel3"; | ||||
this.tableLayoutPanel3.RowCount = 1; | this.tableLayoutPanel3.RowCount = 1; | ||||
@@ -358,7 +383,7 @@ | |||||
this.tableLayoutPanel4.Controls.Add(this.DeleteButton, 1, 0); | this.tableLayoutPanel4.Controls.Add(this.DeleteButton, 1, 0); | ||||
this.tableLayoutPanel4.Controls.Add(this.AddButton, 0, 0); | this.tableLayoutPanel4.Controls.Add(this.AddButton, 0, 0); | ||||
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Top; | this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Top; | ||||
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 200); | |||||
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 174); | |||||
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0); | this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0); | ||||
this.tableLayoutPanel4.Name = "tableLayoutPanel4"; | this.tableLayoutPanel4.Name = "tableLayoutPanel4"; | ||||
this.tableLayoutPanel4.RowCount = 1; | this.tableLayoutPanel4.RowCount = 1; | ||||
@@ -393,6 +418,8 @@ | |||||
this.ServerGroupBox.PerformLayout(); | this.ServerGroupBox.PerformLayout(); | ||||
this.tableLayoutPanel2.ResumeLayout(false); | this.tableLayoutPanel2.ResumeLayout(false); | ||||
this.tableLayoutPanel2.PerformLayout(); | this.tableLayoutPanel2.PerformLayout(); | ||||
this.tableLayoutPanel5.ResumeLayout(false); | |||||
this.tableLayoutPanel5.PerformLayout(); | |||||
this.tableLayoutPanel3.ResumeLayout(false); | this.tableLayoutPanel3.ResumeLayout(false); | ||||
this.tableLayoutPanel4.ResumeLayout(false); | this.tableLayoutPanel4.ResumeLayout(false); | ||||
this.ResumeLayout(false); | this.ResumeLayout(false); | ||||
@@ -406,11 +433,9 @@ | |||||
private System.Windows.Forms.Label IPLabel; | private System.Windows.Forms.Label IPLabel; | ||||
private System.Windows.Forms.Label ServerPortLabel; | private System.Windows.Forms.Label ServerPortLabel; | ||||
private System.Windows.Forms.Label PasswordLabel; | private System.Windows.Forms.Label PasswordLabel; | ||||
private System.Windows.Forms.Label ProxyPortLabel; | |||||
private System.Windows.Forms.TextBox IPTextBox; | private System.Windows.Forms.TextBox IPTextBox; | ||||
private System.Windows.Forms.TextBox ServerPortTextBox; | private System.Windows.Forms.TextBox ServerPortTextBox; | ||||
private System.Windows.Forms.TextBox PasswordTextBox; | private System.Windows.Forms.TextBox PasswordTextBox; | ||||
private System.Windows.Forms.TextBox ProxyPortTextBox; | |||||
private System.Windows.Forms.Label EncryptionLabel; | private System.Windows.Forms.Label EncryptionLabel; | ||||
private System.Windows.Forms.ComboBox EncryptionSelect; | private System.Windows.Forms.ComboBox EncryptionSelect; | ||||
private System.Windows.Forms.Panel panel2; | private System.Windows.Forms.Panel panel2; | ||||
@@ -425,6 +450,9 @@ | |||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; | ||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; | ||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; | ||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5; | |||||
private System.Windows.Forms.TextBox ProxyPortTextBox; | |||||
private System.Windows.Forms.Label ProxyPortLabel; | |||||
} | } | ||||
} | } | ||||
@@ -79,12 +79,14 @@ namespace Shadowsocks.View | |||||
server = IPTextBox.Text, | server = IPTextBox.Text, | ||||
server_port = int.Parse(ServerPortTextBox.Text), | server_port = int.Parse(ServerPortTextBox.Text), | ||||
password = PasswordTextBox.Text, | password = PasswordTextBox.Text, | ||||
local_port = int.Parse(ProxyPortTextBox.Text), | |||||
method = EncryptionSelect.Text, | method = EncryptionSelect.Text, | ||||
remarks = RemarksTextBox.Text | remarks = RemarksTextBox.Text | ||||
}; | }; | ||||
int localPort = int.Parse(ProxyPortTextBox.Text); | |||||
Configuration.CheckServer(server); | Configuration.CheckServer(server); | ||||
Configuration.CheckPort(localPort); | |||||
_modifiedConfiguration.configs[_oldSelectedIndex] = server; | _modifiedConfiguration.configs[_oldSelectedIndex] = server; | ||||
_modifiedConfiguration.localPort = localPort; | |||||
return true; | return true; | ||||
} | } | ||||
@@ -108,7 +110,7 @@ namespace Shadowsocks.View | |||||
IPTextBox.Text = server.server; | IPTextBox.Text = server.server; | ||||
ServerPortTextBox.Text = server.server_port.ToString(); | ServerPortTextBox.Text = server.server_port.ToString(); | ||||
PasswordTextBox.Text = server.password; | PasswordTextBox.Text = server.password; | ||||
ProxyPortTextBox.Text = server.local_port.ToString(); | |||||
ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString(); | |||||
EncryptionSelect.Text = server.method ?? "aes-256-cfb"; | EncryptionSelect.Text = server.method ?? "aes-256-cfb"; | ||||
RemarksTextBox.Text = server.remarks; | RemarksTextBox.Text = server.remarks; | ||||
ServerGroupBox.Visible = true; | ServerGroupBox.Visible = true; | ||||
@@ -202,7 +204,7 @@ namespace Shadowsocks.View | |||||
MessageBox.Show(I18N.GetString("Please add at least one server")); | MessageBox.Show(I18N.GetString("Please add at least one server")); | ||||
return; | return; | ||||
} | } | ||||
controller.SaveServers(_modifiedConfiguration.configs); | |||||
controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort); | |||||
this.Close(); | this.Close(); | ||||
} | } | ||||
@@ -63,7 +63,7 @@ namespace Shadowsocks.View | |||||
LoadCurrentConfiguration(); | LoadCurrentConfiguration(); | ||||
updateChecker.CheckUpdate(); | |||||
updateChecker.CheckUpdate(controller.GetConfiguration()); | |||||
if (controller.GetConfiguration().isDefault) | if (controller.GetConfiguration().isDefault) | ||||
{ | { | ||||
@@ -131,7 +131,7 @@ namespace Shadowsocks.View | |||||
private void LoadMenu() | private void LoadMenu() | ||||
{ | { | ||||
this.contextMenu1 = new ContextMenu(new MenuItem[] { | this.contextMenu1 = new ContextMenu(new MenuItem[] { | ||||
this.enableItem = CreateMenuItem("Enable", new EventHandler(this.EnableItem_Click)), | |||||
this.enableItem = CreateMenuItem("Enable System Proxy", new EventHandler(this.EnableItem_Click)), | |||||
CreateMenuGroup("Mode", new MenuItem[] { | CreateMenuGroup("Mode", new MenuItem[] { | ||||
this.PACModeItem = CreateMenuItem("PAC", new EventHandler(this.PACModeItem_Click)), | this.PACModeItem = CreateMenuItem("PAC", new EventHandler(this.PACModeItem_Click)), | ||||
this.globalModeItem = CreateMenuItem("Global", new EventHandler(this.GlobalModeItem_Click)) | this.globalModeItem = CreateMenuItem("Global", new EventHandler(this.GlobalModeItem_Click)) | ||||
@@ -127,7 +127,9 @@ | |||||
<Compile Include="Controller\FileManager.cs" /> | <Compile Include="Controller\FileManager.cs" /> | ||||
<Compile Include="Controller\GFWListUpdater.cs" /> | <Compile Include="Controller\GFWListUpdater.cs" /> | ||||
<Compile Include="Controller\I18N.cs" /> | <Compile Include="Controller\I18N.cs" /> | ||||
<Compile Include="Controller\Listener.cs" /> | |||||
<Compile Include="Controller\Logging.cs" /> | <Compile Include="Controller\Logging.cs" /> | ||||
<Compile Include="Controller\PortForwarder.cs" /> | |||||
<Compile Include="Controller\UpdateChecker.cs" /> | <Compile Include="Controller\UpdateChecker.cs" /> | ||||
<Compile Include="Encryption\EncryptorBase.cs" /> | <Compile Include="Encryption\EncryptorBase.cs" /> | ||||
<Compile Include="Encryption\EncryptorFactory.cs" /> | <Compile Include="Encryption\EncryptorFactory.cs" /> | ||||