@@ -0,0 +1,4 @@ | |||
* text=auto | |||
# geosite database | |||
*.dat binary |
@@ -1,110 +1,110 @@ | |||
using System; | |||
using System.Collections.Specialized; | |||
using System.Diagnostics; | |||
using System.IO; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Reflection; | |||
using Shadowsocks.Model; | |||
using Shadowsocks.Util.ProcessManagement; | |||
namespace Shadowsocks.Controller.Service | |||
{ | |||
// https://github.com/shadowsocks/shadowsocks-org/wiki/Plugin | |||
public sealed class Sip003Plugin : IDisposable | |||
{ | |||
public IPEndPoint LocalEndPoint { get; private set; } | |||
public int ProcessId => _started ? _pluginProcess.Id : 0; | |||
private readonly object _startProcessLock = new object(); | |||
private readonly Job _pluginJob; | |||
private readonly Process _pluginProcess; | |||
private bool _started; | |||
private bool _disposed; | |||
public static Sip003Plugin CreateIfConfigured(Server server, bool showPluginOutput) | |||
{ | |||
if (server == null) | |||
{ | |||
throw new ArgumentNullException(nameof(server)); | |||
} | |||
if (string.IsNullOrWhiteSpace(server.plugin)) | |||
{ | |||
return null; | |||
} | |||
return new Sip003Plugin( | |||
server.plugin, | |||
server.plugin_opts, | |||
server.plugin_args, | |||
server.server, | |||
server.server_port, | |||
showPluginOutput); | |||
} | |||
private Sip003Plugin(string plugin, string pluginOpts, string pluginArgs, string serverAddress, int serverPort, bool showPluginOutput) | |||
{ | |||
if (plugin == null) throw new ArgumentNullException(nameof(plugin)); | |||
if (string.IsNullOrWhiteSpace(serverAddress)) | |||
{ | |||
throw new ArgumentException("Value cannot be null or whitespace.", nameof(serverAddress)); | |||
} | |||
if (serverPort <= 0 || serverPort > 65535) | |||
{ | |||
throw new ArgumentOutOfRangeException("serverPort"); | |||
} | |||
var appPath = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath); | |||
_pluginProcess = new Process | |||
{ | |||
StartInfo = new ProcessStartInfo | |||
{ | |||
FileName = plugin, | |||
Arguments = pluginArgs, | |||
UseShellExecute = false, | |||
CreateNoWindow = !showPluginOutput, | |||
ErrorDialog = false, | |||
WindowStyle = ProcessWindowStyle.Hidden, | |||
WorkingDirectory = appPath ?? Environment.CurrentDirectory, | |||
Environment = | |||
{ | |||
["SS_REMOTE_HOST"] = serverAddress, | |||
["SS_REMOTE_PORT"] = serverPort.ToString(), | |||
["SS_PLUGIN_OPTIONS"] = pluginOpts | |||
} | |||
} | |||
}; | |||
_pluginJob = new Job(); | |||
} | |||
public bool StartIfNeeded() | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
lock (_startProcessLock) | |||
{ | |||
if (_started && !_pluginProcess.HasExited) | |||
{ | |||
return false; | |||
} | |||
var localPort = GetNextFreeTcpPort(); | |||
LocalEndPoint = new IPEndPoint(IPAddress.Loopback, localPort); | |||
_pluginProcess.StartInfo.Environment["SS_LOCAL_HOST"] = LocalEndPoint.Address.ToString(); | |||
_pluginProcess.StartInfo.Environment["SS_LOCAL_PORT"] = LocalEndPoint.Port.ToString(); | |||
_pluginProcess.StartInfo.Arguments = ExpandEnvironmentVariables(_pluginProcess.StartInfo.Arguments, _pluginProcess.StartInfo.EnvironmentVariables); | |||
using System; | |||
using System.Collections.Specialized; | |||
using System.Diagnostics; | |||
using System.IO; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Reflection; | |||
using Shadowsocks.Model; | |||
using Shadowsocks.Util.ProcessManagement; | |||
namespace Shadowsocks.Controller.Service | |||
{ | |||
// https://github.com/shadowsocks/shadowsocks-org/wiki/Plugin | |||
public sealed class Sip003Plugin : IDisposable | |||
{ | |||
public IPEndPoint LocalEndPoint { get; private set; } | |||
public int ProcessId => _started ? _pluginProcess.Id : 0; | |||
private readonly object _startProcessLock = new object(); | |||
private readonly Job _pluginJob; | |||
private readonly Process _pluginProcess; | |||
private bool _started; | |||
private bool _disposed; | |||
public static Sip003Plugin CreateIfConfigured(Server server, bool showPluginOutput) | |||
{ | |||
if (server == null) | |||
{ | |||
throw new ArgumentNullException(nameof(server)); | |||
} | |||
if (string.IsNullOrWhiteSpace(server.plugin)) | |||
{ | |||
return null; | |||
} | |||
return new Sip003Plugin( | |||
server.plugin, | |||
server.plugin_opts, | |||
server.plugin_args, | |||
server.server, | |||
server.server_port, | |||
showPluginOutput); | |||
} | |||
private Sip003Plugin(string plugin, string pluginOpts, string pluginArgs, string serverAddress, int serverPort, bool showPluginOutput) | |||
{ | |||
if (plugin == null) throw new ArgumentNullException(nameof(plugin)); | |||
if (string.IsNullOrWhiteSpace(serverAddress)) | |||
{ | |||
throw new ArgumentException("Value cannot be null or whitespace.", nameof(serverAddress)); | |||
} | |||
if (serverPort <= 0 || serverPort > 65535) | |||
{ | |||
throw new ArgumentOutOfRangeException("serverPort"); | |||
} | |||
var appPath = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath); | |||
_pluginProcess = new Process | |||
{ | |||
StartInfo = new ProcessStartInfo | |||
{ | |||
FileName = plugin, | |||
Arguments = pluginArgs, | |||
UseShellExecute = false, | |||
CreateNoWindow = !showPluginOutput, | |||
ErrorDialog = false, | |||
WindowStyle = ProcessWindowStyle.Hidden, | |||
WorkingDirectory = appPath ?? Environment.CurrentDirectory, | |||
Environment = | |||
{ | |||
["SS_REMOTE_HOST"] = serverAddress, | |||
["SS_REMOTE_PORT"] = serverPort.ToString(), | |||
["SS_PLUGIN_OPTIONS"] = pluginOpts | |||
} | |||
} | |||
}; | |||
_pluginJob = new Job(); | |||
} | |||
public bool StartIfNeeded() | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
lock (_startProcessLock) | |||
{ | |||
if (_started && !_pluginProcess.HasExited) | |||
{ | |||
return false; | |||
} | |||
var localPort = GetNextFreeTcpPort(); | |||
LocalEndPoint = new IPEndPoint(IPAddress.Loopback, localPort); | |||
_pluginProcess.StartInfo.Environment["SS_LOCAL_HOST"] = LocalEndPoint.Address.ToString(); | |||
_pluginProcess.StartInfo.Environment["SS_LOCAL_PORT"] = LocalEndPoint.Port.ToString(); | |||
_pluginProcess.StartInfo.Arguments = ExpandEnvironmentVariables(_pluginProcess.StartInfo.Arguments, _pluginProcess.StartInfo.EnvironmentVariables); | |||
try | |||
{ | |||
_pluginProcess.Start(); | |||
} | |||
catch (System.ComponentModel.Win32Exception ex) | |||
} | |||
catch (System.ComponentModel.Win32Exception ex) | |||
{ | |||
// do not use File.Exists(...), it can not handle the scenarios when the plugin file is in system environment path. | |||
// https://docs.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values | |||
@@ -115,65 +115,65 @@ namespace Shadowsocks.Controller.Service | |||
throw new FileNotFoundException(I18N.GetString("Cannot find the plugin program file"), _pluginProcess.StartInfo.FileName, ex); | |||
} | |||
throw new ApplicationException(I18N.GetString("Plugin Program"), ex); | |||
} | |||
_pluginJob.AddProcess(_pluginProcess.Handle); | |||
_started = true; | |||
} | |||
return true; | |||
} | |||
public string ExpandEnvironmentVariables(string name, StringDictionary environmentVariables = null) | |||
{ | |||
// Expand the environment variables from the new process itself | |||
if (environmentVariables != null) | |||
{ | |||
foreach(string key in environmentVariables.Keys) | |||
{ | |||
name = name.Replace($"%{key}%", environmentVariables[key], StringComparison.OrdinalIgnoreCase); | |||
} | |||
} | |||
// Also expand the environment variables from current main process (system) | |||
name = Environment.ExpandEnvironmentVariables(name); | |||
return name; | |||
} | |||
static int GetNextFreeTcpPort() | |||
{ | |||
var l = new TcpListener(IPAddress.Loopback, 0); | |||
l.Start(); | |||
int port = ((IPEndPoint)l.LocalEndpoint).Port; | |||
l.Stop(); | |||
return port; | |||
} | |||
public void Dispose() | |||
{ | |||
if (_disposed) | |||
{ | |||
return; | |||
} | |||
try | |||
{ | |||
if (!_pluginProcess.HasExited) | |||
{ | |||
_pluginProcess.Kill(); | |||
_pluginProcess.WaitForExit(); | |||
} | |||
} | |||
catch (Exception) { } | |||
finally | |||
{ | |||
try | |||
{ | |||
_pluginProcess.Dispose(); | |||
_pluginJob.Dispose(); | |||
} | |||
catch (Exception) { } | |||
_disposed = true; | |||
} | |||
} | |||
} | |||
} | |||
_pluginJob.AddProcess(_pluginProcess.Handle); | |||
_started = true; | |||
} | |||
return true; | |||
} | |||
public string ExpandEnvironmentVariables(string name, StringDictionary environmentVariables = null) | |||
{ | |||
// Expand the environment variables from the new process itself | |||
if (environmentVariables != null) | |||
{ | |||
foreach(string key in environmentVariables.Keys) | |||
{ | |||
name = name.Replace($"%{key}%", environmentVariables[key], StringComparison.OrdinalIgnoreCase); | |||
} | |||
} | |||
// Also expand the environment variables from current main process (system) | |||
name = Environment.ExpandEnvironmentVariables(name); | |||
return name; | |||
} | |||
static int GetNextFreeTcpPort() | |||
{ | |||
var l = new TcpListener(IPAddress.Loopback, 0); | |||
l.Start(); | |||
int port = ((IPEndPoint)l.LocalEndpoint).Port; | |||
l.Stop(); | |||
return port; | |||
} | |||
public void Dispose() | |||
{ | |||
if (_disposed) | |||
{ | |||
return; | |||
} | |||
try | |||
{ | |||
if (!_pluginProcess.HasExited) | |||
{ | |||
_pluginProcess.Kill(); | |||
_pluginProcess.WaitForExit(); | |||
} | |||
} | |||
catch (Exception) { } | |||
finally | |||
{ | |||
try | |||
{ | |||
_pluginProcess.Dispose(); | |||
_pluginJob.Dispose(); | |||
} | |||
catch (Exception) { } | |||
_disposed = true; | |||
} | |||
} | |||
} | |||
} |
@@ -1,26 +1,26 @@ | |||
using Microsoft.Win32; | |||
using Microsoft.Win32; | |||
using NLog; | |||
using Shadowsocks.Controller; | |||
using Shadowsocks.Controller.Hotkeys; | |||
using Shadowsocks.Util; | |||
using Shadowsocks.View; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.IO; | |||
using System.IO.Pipes; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using System.Windows.Forms; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.IO; | |||
using System.IO.Pipes; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using System.Windows.Forms; | |||
namespace Shadowsocks | |||
{ | |||
internal static class Program | |||
internal static class Program | |||
{ | |||
private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | |||
private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | |||
public static ShadowsocksController MainController { get; private set; } | |||
public static MenuViewController MenuController { get; private set; } | |||
public static string[] Args { get; private set; } | |||
@@ -29,15 +29,15 @@ namespace Shadowsocks | |||
/// </summary> | |||
/// </summary> | |||
[STAThread] | |||
private static void Main(string[] args) | |||
private static void Main(string[] args) | |||
{ | |||
Directory.SetCurrentDirectory(Application.StartupPath); | |||
// todo: initialize the NLog configuartion | |||
Model.NLogConfig.TouchAndApplyNLogConfig(); | |||
// .NET Framework 4.7.2 on Win7 compatibility | |||
ServicePointManager.SecurityProtocol |= | |||
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; | |||
ServicePointManager.SecurityProtocol |= | |||
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; | |||
// store args for further use | |||
Args = args; | |||
@@ -59,54 +59,54 @@ namespace Shadowsocks | |||
} | |||
return; | |||
} | |||
string pipename = $"Shadowsocks\\{Application.StartupPath.GetHashCode()}"; | |||
string pipename = $"Shadowsocks\\{Application.StartupPath.GetHashCode()}"; | |||
string addedUrl = null; | |||
using (NamedPipeClientStream pipe = new NamedPipeClientStream(pipename)) | |||
string addedUrl = null; | |||
using (NamedPipeClientStream pipe = new NamedPipeClientStream(pipename)) | |||
{ | |||
bool pipeExist = false; | |||
try | |||
{ | |||
pipe.Connect(10); | |||
pipeExist = true; | |||
} | |||
catch (TimeoutException) | |||
{ | |||
pipeExist = false; | |||
} | |||
// TODO: switch to better argv parser when it's getting complicate | |||
List<string> alist = Args.ToList(); | |||
// check --open-url param | |||
int urlidx = alist.IndexOf("--open-url") + 1; | |||
if (urlidx > 0) | |||
{ | |||
if (Args.Length <= urlidx) | |||
{ | |||
return; | |||
} | |||
// --open-url exist, and no other instance, add it later | |||
if (!pipeExist) | |||
{ | |||
addedUrl = Args[urlidx]; | |||
} | |||
// has other instance, send url via pipe then exit | |||
else | |||
{ | |||
byte[] b = Encoding.UTF8.GetBytes(Args[urlidx]); | |||
byte[] opAddUrl = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(1)); | |||
byte[] blen = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(b.Length)); | |||
pipe.Write(opAddUrl, 0, 4); // opcode addurl | |||
pipe.Write(blen, 0, 4); | |||
pipe.Write(b, 0, b.Length); | |||
pipe.Close(); | |||
return; | |||
} | |||
} | |||
// has another instance, and no need to communicate with it return | |||
else if (pipeExist) | |||
bool pipeExist = false; | |||
try | |||
{ | |||
pipe.Connect(10); | |||
pipeExist = true; | |||
} | |||
catch (TimeoutException) | |||
{ | |||
pipeExist = false; | |||
} | |||
// TODO: switch to better argv parser when it's getting complicate | |||
List<string> alist = Args.ToList(); | |||
// check --open-url param | |||
int urlidx = alist.IndexOf("--open-url") + 1; | |||
if (urlidx > 0) | |||
{ | |||
if (Args.Length <= urlidx) | |||
{ | |||
return; | |||
} | |||
// --open-url exist, and no other instance, add it later | |||
if (!pipeExist) | |||
{ | |||
addedUrl = Args[urlidx]; | |||
} | |||
// has other instance, send url via pipe then exit | |||
else | |||
{ | |||
byte[] b = Encoding.UTF8.GetBytes(Args[urlidx]); | |||
byte[] opAddUrl = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(1)); | |||
byte[] blen = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(b.Length)); | |||
pipe.Write(opAddUrl, 0, 4); // opcode addurl | |||
pipe.Write(blen, 0, 4); | |||
pipe.Write(b, 0, b.Length); | |||
pipe.Close(); | |||
return; | |||
} | |||
} | |||
// has another instance, and no need to communicate with it return | |||
else if (pipeExist) | |||
{ | |||
Process[] oldProcesses = Process.GetProcessesByName("Shadowsocks"); | |||
if (oldProcesses.Length > 0) | |||
@@ -119,43 +119,43 @@ namespace Shadowsocks | |||
I18N.GetString("Shadowsocks is already running.")); | |||
return; | |||
} | |||
} | |||
Utils.ReleaseMemory(true); | |||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); | |||
// handle UI exceptions | |||
Application.ThreadException += Application_ThreadException; | |||
// handle non-UI exceptions | |||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; | |||
Application.ApplicationExit += Application_ApplicationExit; | |||
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; | |||
Application.EnableVisualStyles(); | |||
Application.SetCompatibleTextRenderingDefault(false); | |||
AutoStartup.RegisterForRestart(true); | |||
Directory.SetCurrentDirectory(Application.StartupPath); | |||
} | |||
Utils.ReleaseMemory(true); | |||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); | |||
// handle UI exceptions | |||
Application.ThreadException += Application_ThreadException; | |||
// handle non-UI exceptions | |||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; | |||
Application.ApplicationExit += Application_ApplicationExit; | |||
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; | |||
Application.EnableVisualStyles(); | |||
Application.SetCompatibleTextRenderingDefault(false); | |||
AutoStartup.RegisterForRestart(true); | |||
Directory.SetCurrentDirectory(Application.StartupPath); | |||
#if DEBUG | |||
// truncate privoxy log file while debugging | |||
string privoxyLogFilename = Utils.GetTempPath("privoxy.log"); | |||
if (File.Exists(privoxyLogFilename)) | |||
using (new FileStream(privoxyLogFilename, FileMode.Truncate)) { } | |||
// truncate privoxy log file while debugging | |||
string privoxyLogFilename = Utils.GetTempPath("privoxy.log"); | |||
if (File.Exists(privoxyLogFilename)) | |||
using (new FileStream(privoxyLogFilename, FileMode.Truncate)) { } | |||
#endif | |||
MainController = new ShadowsocksController(); | |||
MenuController = new MenuViewController(MainController); | |||
HotKeys.Init(MainController); | |||
MainController.Start(); | |||
NamedPipeServer namedPipeServer = new NamedPipeServer(); | |||
Task.Run(() => namedPipeServer.Run(pipename)); | |||
namedPipeServer.AddUrlRequested += (_1, e) => MainController.AskAddServerBySSURL(e.Url); | |||
if (!addedUrl.IsNullOrEmpty()) | |||
{ | |||
MainController.AskAddServerBySSURL(addedUrl); | |||
} | |||
Application.Run(); | |||
MainController = new ShadowsocksController(); | |||
MenuController = new MenuViewController(MainController); | |||
HotKeys.Init(MainController); | |||
MainController.Start(); | |||
NamedPipeServer namedPipeServer = new NamedPipeServer(); | |||
Task.Run(() => namedPipeServer.Run(pipename)); | |||
namedPipeServer.AddUrlRequested += (_1, e) => MainController.AskAddServerBySSURL(e.Url); | |||
if (!addedUrl.IsNullOrEmpty()) | |||
{ | |||
MainController.AskAddServerBySSURL(addedUrl); | |||
} | |||
Application.Run(); | |||
} | |||
private static int exited = 0; | |||
@@ -193,7 +193,7 @@ namespace Shadowsocks | |||
logger.Info("os wake up"); | |||
if (MainController != null) | |||
{ | |||
Task.Factory.StartNew(() => | |||
Task.Factory.StartNew(() => | |||
{ | |||
Thread.Sleep(10 * 1000); | |||
try | |||
@@ -1,212 +1,212 @@ | |||
using System; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Text; | |||
using System.Text.RegularExpressions; | |||
using System.Threading; | |||
using System; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Text; | |||
using System.Text.RegularExpressions; | |||
using System.Threading; | |||
using NLog; | |||
using Shadowsocks.Controller; | |||
using Shadowsocks.Util.Sockets; | |||
namespace Shadowsocks.Proxy | |||
{ | |||
public class HttpProxy : IProxy | |||
{ | |||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||
private class FakeAsyncResult : IAsyncResult | |||
{ | |||
public readonly HttpState innerState; | |||
private readonly IAsyncResult r; | |||
public FakeAsyncResult(IAsyncResult orig, HttpState state) | |||
{ | |||
r = orig; | |||
innerState = state; | |||
} | |||
public bool IsCompleted => r.IsCompleted; | |||
public WaitHandle AsyncWaitHandle => r.AsyncWaitHandle; | |||
public object AsyncState => innerState.AsyncState; | |||
public bool CompletedSynchronously => r.CompletedSynchronously; | |||
} | |||
private class HttpState | |||
{ | |||
public AsyncCallback Callback { get; set; } | |||
public object AsyncState { get; set; } | |||
public int BytesToRead; | |||
public Exception ex { get; set; } | |||
} | |||
public EndPoint LocalEndPoint => _remote.LocalEndPoint; | |||
public EndPoint ProxyEndPoint { get; private set; } | |||
public EndPoint DestEndPoint { get; private set; } | |||
private readonly WrappedSocket _remote = new WrappedSocket(); | |||
public void BeginConnectProxy(EndPoint remoteEP, AsyncCallback callback, object state) | |||
{ | |||
ProxyEndPoint = remoteEP; | |||
_remote.BeginConnect(remoteEP, callback, state); | |||
} | |||
public void EndConnectProxy(IAsyncResult asyncResult) | |||
{ | |||
_remote.EndConnect(asyncResult); | |||
_remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | |||
} | |||
private const string HTTP_CRLF = "\r\n"; | |||
private const string HTTP_CONNECT_TEMPLATE = | |||
"CONNECT {0} HTTP/1.1" + HTTP_CRLF + | |||
"Host: {0}" + HTTP_CRLF + | |||
"Proxy-Connection: keep-alive" + HTTP_CRLF + | |||
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36" + HTTP_CRLF + | |||
"{1}" + // Proxy-Authorization if any | |||
"" + HTTP_CRLF; // End with an empty line | |||
private const string PROXY_AUTH_TEMPLATE = "Proxy-Authorization: Basic {0}" + HTTP_CRLF; | |||
public void BeginConnectDest(EndPoint destEndPoint, AsyncCallback callback, object state, NetworkCredential auth = null) | |||
{ | |||
DestEndPoint = destEndPoint; | |||
using Shadowsocks.Controller; | |||
using Shadowsocks.Util.Sockets; | |||
namespace Shadowsocks.Proxy | |||
{ | |||
public class HttpProxy : IProxy | |||
{ | |||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||
private class FakeAsyncResult : IAsyncResult | |||
{ | |||
public readonly HttpState innerState; | |||
private readonly IAsyncResult r; | |||
public FakeAsyncResult(IAsyncResult orig, HttpState state) | |||
{ | |||
r = orig; | |||
innerState = state; | |||
} | |||
public bool IsCompleted => r.IsCompleted; | |||
public WaitHandle AsyncWaitHandle => r.AsyncWaitHandle; | |||
public object AsyncState => innerState.AsyncState; | |||
public bool CompletedSynchronously => r.CompletedSynchronously; | |||
} | |||
private class HttpState | |||
{ | |||
public AsyncCallback Callback { get; set; } | |||
public object AsyncState { get; set; } | |||
public int BytesToRead; | |||
public Exception ex { get; set; } | |||
} | |||
public EndPoint LocalEndPoint => _remote.LocalEndPoint; | |||
public EndPoint ProxyEndPoint { get; private set; } | |||
public EndPoint DestEndPoint { get; private set; } | |||
private readonly WrappedSocket _remote = new WrappedSocket(); | |||
public void BeginConnectProxy(EndPoint remoteEP, AsyncCallback callback, object state) | |||
{ | |||
ProxyEndPoint = remoteEP; | |||
_remote.BeginConnect(remoteEP, callback, state); | |||
} | |||
public void EndConnectProxy(IAsyncResult asyncResult) | |||
{ | |||
_remote.EndConnect(asyncResult); | |||
_remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | |||
} | |||
private const string HTTP_CRLF = "\r\n"; | |||
private const string HTTP_CONNECT_TEMPLATE = | |||
"CONNECT {0} HTTP/1.1" + HTTP_CRLF + | |||
"Host: {0}" + HTTP_CRLF + | |||
"Proxy-Connection: keep-alive" + HTTP_CRLF + | |||
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36" + HTTP_CRLF + | |||
"{1}" + // Proxy-Authorization if any | |||
"" + HTTP_CRLF; // End with an empty line | |||
private const string PROXY_AUTH_TEMPLATE = "Proxy-Authorization: Basic {0}" + HTTP_CRLF; | |||
public void BeginConnectDest(EndPoint destEndPoint, AsyncCallback callback, object state, NetworkCredential auth = null) | |||
{ | |||
DestEndPoint = destEndPoint; | |||
String authInfo = ""; | |||
if (auth != null) | |||
{ | |||
string authKey = Convert.ToBase64String(Encoding.UTF8.GetBytes(auth.UserName + ":" + auth.Password)); | |||
authInfo = string.Format(PROXY_AUTH_TEMPLATE, authKey); | |||
} | |||
string request = string.Format(HTTP_CONNECT_TEMPLATE, destEndPoint, authInfo); | |||
var b = Encoding.UTF8.GetBytes(request); | |||
var st = new HttpState(); | |||
st.Callback = callback; | |||
st.AsyncState = state; | |||
_remote.BeginSend(b, 0, b.Length, 0, HttpRequestSendCallback, st); | |||
} | |||
public void EndConnectDest(IAsyncResult asyncResult) | |||
{ | |||
var state = ((FakeAsyncResult)asyncResult).innerState; | |||
if (state.ex != null) | |||
{ | |||
throw state.ex; | |||
} | |||
} | |||
public void BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, | |||
object state) | |||
{ | |||
_remote.BeginSend(buffer, offset, size, socketFlags, callback, state); | |||
} | |||
public int EndSend(IAsyncResult asyncResult) | |||
{ | |||
return _remote.EndSend(asyncResult); | |||
} | |||
public void BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, | |||
object state) | |||
{ | |||
_remote.BeginReceive(buffer, offset, size, socketFlags, callback, state); | |||
} | |||
public int EndReceive(IAsyncResult asyncResult) | |||
{ | |||
return _remote.EndReceive(asyncResult); | |||
} | |||
public void Shutdown(SocketShutdown how) | |||
{ | |||
_remote.Shutdown(how); | |||
} | |||
public void Close() | |||
{ | |||
_remote.Dispose(); | |||
} | |||
private void HttpRequestSendCallback(IAsyncResult ar) | |||
{ | |||
var state = (HttpState) ar.AsyncState; | |||
try | |||
{ | |||
_remote.EndSend(ar); | |||
// start line read | |||
new LineReader(_remote, OnLineRead, OnException, OnFinish, Encoding.UTF8, HTTP_CRLF, 1024, new FakeAsyncResult(ar, state)); | |||
} | |||
catch (Exception ex) | |||
{ | |||
state.ex = ex; | |||
state.Callback?.Invoke(new FakeAsyncResult(ar, state)); | |||
} | |||
} | |||
private void OnFinish(byte[] lastBytes, int index, int length, object state) | |||
{ | |||
var st = (FakeAsyncResult)state; | |||
if (st.innerState.ex == null) | |||
{ | |||
if (!_established) | |||
{ | |||
st.innerState.ex = new Exception(I18N.GetString("Proxy request failed")); | |||
} | |||
// TODO: save last bytes | |||
} | |||
st.innerState.Callback?.Invoke(st); | |||
} | |||
private void OnException(Exception ex, object state) | |||
{ | |||
var st = (FakeAsyncResult) state; | |||
st.innerState.ex = ex; | |||
} | |||
private static readonly Regex HttpRespondHeaderRegex = new Regex(@"^(HTTP/1\.\d) (\d{3}) (.+)$", RegexOptions.Compiled); | |||
private int _respondLineCount = 0; | |||
private bool _established = false; | |||
private bool OnLineRead(string line, object state) | |||
{ | |||
logger.Trace(line); | |||
if (_respondLineCount == 0) | |||
{ | |||
var m = HttpRespondHeaderRegex.Match(line); | |||
if (m.Success) | |||
{ | |||
var resultCode = m.Groups[2].Value; | |||
if ("200" != resultCode) | |||
{ | |||
return true; | |||
} | |||
_established = true; | |||
} | |||
} | |||
else | |||
{ | |||
if (line.IsNullOrEmpty()) | |||
{ | |||
return true; | |||
} | |||
} | |||
_respondLineCount++; | |||
return false; | |||
} | |||
} | |||
} | |||
string request = string.Format(HTTP_CONNECT_TEMPLATE, destEndPoint, authInfo); | |||
var b = Encoding.UTF8.GetBytes(request); | |||
var st = new HttpState(); | |||
st.Callback = callback; | |||
st.AsyncState = state; | |||
_remote.BeginSend(b, 0, b.Length, 0, HttpRequestSendCallback, st); | |||
} | |||
public void EndConnectDest(IAsyncResult asyncResult) | |||
{ | |||
var state = ((FakeAsyncResult)asyncResult).innerState; | |||
if (state.ex != null) | |||
{ | |||
throw state.ex; | |||
} | |||
} | |||
public void BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, | |||
object state) | |||
{ | |||
_remote.BeginSend(buffer, offset, size, socketFlags, callback, state); | |||
} | |||
public int EndSend(IAsyncResult asyncResult) | |||
{ | |||
return _remote.EndSend(asyncResult); | |||
} | |||
public void BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, | |||
object state) | |||
{ | |||
_remote.BeginReceive(buffer, offset, size, socketFlags, callback, state); | |||
} | |||
public int EndReceive(IAsyncResult asyncResult) | |||
{ | |||
return _remote.EndReceive(asyncResult); | |||
} | |||
public void Shutdown(SocketShutdown how) | |||
{ | |||
_remote.Shutdown(how); | |||
} | |||
public void Close() | |||
{ | |||
_remote.Dispose(); | |||
} | |||
private void HttpRequestSendCallback(IAsyncResult ar) | |||
{ | |||
var state = (HttpState) ar.AsyncState; | |||
try | |||
{ | |||
_remote.EndSend(ar); | |||
// start line read | |||
new LineReader(_remote, OnLineRead, OnException, OnFinish, Encoding.UTF8, HTTP_CRLF, 1024, new FakeAsyncResult(ar, state)); | |||
} | |||
catch (Exception ex) | |||
{ | |||
state.ex = ex; | |||
state.Callback?.Invoke(new FakeAsyncResult(ar, state)); | |||
} | |||
} | |||
private void OnFinish(byte[] lastBytes, int index, int length, object state) | |||
{ | |||
var st = (FakeAsyncResult)state; | |||
if (st.innerState.ex == null) | |||
{ | |||
if (!_established) | |||
{ | |||
st.innerState.ex = new Exception(I18N.GetString("Proxy request failed")); | |||
} | |||
// TODO: save last bytes | |||
} | |||
st.innerState.Callback?.Invoke(st); | |||
} | |||
private void OnException(Exception ex, object state) | |||
{ | |||
var st = (FakeAsyncResult) state; | |||
st.innerState.ex = ex; | |||
} | |||
private static readonly Regex HttpRespondHeaderRegex = new Regex(@"^(HTTP/1\.\d) (\d{3}) (.+)$", RegexOptions.Compiled); | |||
private int _respondLineCount = 0; | |||
private bool _established = false; | |||
private bool OnLineRead(string line, object state) | |||
{ | |||
logger.Trace(line); | |||
if (_respondLineCount == 0) | |||
{ | |||
var m = HttpRespondHeaderRegex.Match(line); | |||
if (m.Success) | |||
{ | |||
var resultCode = m.Groups[2].Value; | |||
if ("200" != resultCode) | |||
{ | |||
return true; | |||
} | |||
_established = true; | |||
} | |||
} | |||
else | |||
{ | |||
if (line.IsNullOrEmpty()) | |||
{ | |||
return true; | |||
} | |||
} | |||
_respondLineCount++; | |||
return false; | |||
} | |||
} | |||
} |
@@ -1,182 +1,182 @@ | |||
using System; | |||
using System.Diagnostics; | |||
using System.Runtime.InteropServices; | |||
using System; | |||
using System.Diagnostics; | |||
using System.Runtime.InteropServices; | |||
using NLog; | |||
using Shadowsocks.Controller; | |||
namespace Shadowsocks.Util.ProcessManagement | |||
{ | |||
/* | |||
* See: | |||
* http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net | |||
*/ | |||
public class Job : IDisposable | |||
{ | |||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||
private IntPtr handle = IntPtr.Zero; | |||
public Job() | |||
{ | |||
handle = CreateJobObject(IntPtr.Zero, null); | |||
var extendedInfoPtr = IntPtr.Zero; | |||
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION | |||
{ | |||
LimitFlags = 0x2000 | |||
}; | |||
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION | |||
{ | |||
BasicLimitInformation = info | |||
}; | |||
try | |||
{ | |||
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); | |||
extendedInfoPtr = Marshal.AllocHGlobal(length); | |||
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); | |||
if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, | |||
(uint) length)) | |||
throw new Exception(string.Format("Unable to set information. Error: {0}", | |||
Marshal.GetLastWin32Error())); | |||
} | |||
finally | |||
{ | |||
if (extendedInfoPtr != IntPtr.Zero) | |||
{ | |||
Marshal.FreeHGlobal(extendedInfoPtr); | |||
extendedInfoPtr = IntPtr.Zero; | |||
} | |||
} | |||
} | |||
public bool AddProcess(IntPtr processHandle) | |||
{ | |||
var succ = AssignProcessToJobObject(handle, processHandle); | |||
if (!succ) | |||
{ | |||
logger.Error("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); | |||
} | |||
return succ; | |||
} | |||
public bool AddProcess(int processId) | |||
{ | |||
return AddProcess(Process.GetProcessById(processId).Handle); | |||
} | |||
#region IDisposable | |||
private bool disposed; | |||
public void Dispose() | |||
{ | |||
Dispose(true); | |||
GC.SuppressFinalize(this); | |||
} | |||
protected virtual void Dispose(bool disposing) | |||
{ | |||
if (disposed) return; | |||
disposed = true; | |||
using Shadowsocks.Controller; | |||
namespace Shadowsocks.Util.ProcessManagement | |||
{ | |||
/* | |||
* See: | |||
* http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net | |||
*/ | |||
public class Job : IDisposable | |||
{ | |||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||
private IntPtr handle = IntPtr.Zero; | |||
public Job() | |||
{ | |||
handle = CreateJobObject(IntPtr.Zero, null); | |||
var extendedInfoPtr = IntPtr.Zero; | |||
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION | |||
{ | |||
LimitFlags = 0x2000 | |||
}; | |||
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION | |||
{ | |||
BasicLimitInformation = info | |||
}; | |||
try | |||
{ | |||
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); | |||
extendedInfoPtr = Marshal.AllocHGlobal(length); | |||
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); | |||
if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, | |||
(uint) length)) | |||
throw new Exception(string.Format("Unable to set information. Error: {0}", | |||
Marshal.GetLastWin32Error())); | |||
} | |||
finally | |||
{ | |||
if (extendedInfoPtr != IntPtr.Zero) | |||
{ | |||
Marshal.FreeHGlobal(extendedInfoPtr); | |||
extendedInfoPtr = IntPtr.Zero; | |||
} | |||
} | |||
} | |||
public bool AddProcess(IntPtr processHandle) | |||
{ | |||
var succ = AssignProcessToJobObject(handle, processHandle); | |||
if (!succ) | |||
{ | |||
logger.Error("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); | |||
} | |||
return succ; | |||
} | |||
public bool AddProcess(int processId) | |||
{ | |||
return AddProcess(Process.GetProcessById(processId).Handle); | |||
} | |||
#region IDisposable | |||
private bool disposed; | |||
public void Dispose() | |||
{ | |||
Dispose(true); | |||
GC.SuppressFinalize(this); | |||
} | |||
protected virtual void Dispose(bool disposing) | |||
{ | |||
if (disposed) return; | |||
disposed = true; | |||
if (disposing) | |||
{ | |||
// no managed objects to free | |||
} | |||
if (handle != IntPtr.Zero) | |||
{ | |||
CloseHandle(handle); | |||
handle = IntPtr.Zero; | |||
} | |||
} | |||
~Job() | |||
{ | |||
Dispose(false); | |||
} | |||
#endregion | |||
#region Interop | |||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)] | |||
private static extern IntPtr CreateJobObject(IntPtr a, string lpName); | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength); | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
private static extern bool CloseHandle(IntPtr hObject); | |||
#endregion | |||
} | |||
#region Helper classes | |||
[StructLayout(LayoutKind.Sequential)] | |||
struct IO_COUNTERS | |||
{ | |||
public UInt64 ReadOperationCount; | |||
public UInt64 WriteOperationCount; | |||
public UInt64 OtherOperationCount; | |||
public UInt64 ReadTransferCount; | |||
public UInt64 WriteTransferCount; | |||
public UInt64 OtherTransferCount; | |||
} | |||
[StructLayout(LayoutKind.Sequential)] | |||
struct JOBOBJECT_BASIC_LIMIT_INFORMATION | |||
{ | |||
public Int64 PerProcessUserTimeLimit; | |||
public Int64 PerJobUserTimeLimit; | |||
public UInt32 LimitFlags; | |||
public UIntPtr MinimumWorkingSetSize; | |||
public UIntPtr MaximumWorkingSetSize; | |||
public UInt32 ActiveProcessLimit; | |||
public UIntPtr Affinity; | |||
public UInt32 PriorityClass; | |||
public UInt32 SchedulingClass; | |||
} | |||
[StructLayout(LayoutKind.Sequential)] | |||
public struct SECURITY_ATTRIBUTES | |||
{ | |||
public UInt32 nLength; | |||
public IntPtr lpSecurityDescriptor; | |||
public Int32 bInheritHandle; | |||
} | |||
[StructLayout(LayoutKind.Sequential)] | |||
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION | |||
{ | |||
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; | |||
public IO_COUNTERS IoInfo; | |||
public UIntPtr ProcessMemoryLimit; | |||
public UIntPtr JobMemoryLimit; | |||
public UIntPtr PeakProcessMemoryUsed; | |||
public UIntPtr PeakJobMemoryUsed; | |||
} | |||
public enum JobObjectInfoType | |||
{ | |||
AssociateCompletionPortInformation = 7, | |||
BasicLimitInformation = 2, | |||
BasicUIRestrictions = 4, | |||
EndOfJobTimeInformation = 6, | |||
ExtendedLimitInformation = 9, | |||
SecurityLimitInformation = 5, | |||
GroupInformation = 11 | |||
} | |||
#endregion | |||
} | |||
{ | |||
// no managed objects to free | |||
} | |||
if (handle != IntPtr.Zero) | |||
{ | |||
CloseHandle(handle); | |||
handle = IntPtr.Zero; | |||
} | |||
} | |||
~Job() | |||
{ | |||
Dispose(false); | |||
} | |||
#endregion | |||
#region Interop | |||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)] | |||
private static extern IntPtr CreateJobObject(IntPtr a, string lpName); | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength); | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
private static extern bool CloseHandle(IntPtr hObject); | |||
#endregion | |||
} | |||
#region Helper classes | |||
[StructLayout(LayoutKind.Sequential)] | |||
struct IO_COUNTERS | |||
{ | |||
public UInt64 ReadOperationCount; | |||
public UInt64 WriteOperationCount; | |||
public UInt64 OtherOperationCount; | |||
public UInt64 ReadTransferCount; | |||
public UInt64 WriteTransferCount; | |||
public UInt64 OtherTransferCount; | |||
} | |||
[StructLayout(LayoutKind.Sequential)] | |||
struct JOBOBJECT_BASIC_LIMIT_INFORMATION | |||
{ | |||
public Int64 PerProcessUserTimeLimit; | |||
public Int64 PerJobUserTimeLimit; | |||
public UInt32 LimitFlags; | |||
public UIntPtr MinimumWorkingSetSize; | |||
public UIntPtr MaximumWorkingSetSize; | |||
public UInt32 ActiveProcessLimit; | |||
public UIntPtr Affinity; | |||
public UInt32 PriorityClass; | |||
public UInt32 SchedulingClass; | |||
} | |||
[StructLayout(LayoutKind.Sequential)] | |||
public struct SECURITY_ATTRIBUTES | |||
{ | |||
public UInt32 nLength; | |||
public IntPtr lpSecurityDescriptor; | |||
public Int32 bInheritHandle; | |||
} | |||
[StructLayout(LayoutKind.Sequential)] | |||
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION | |||
{ | |||
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; | |||
public IO_COUNTERS IoInfo; | |||
public UIntPtr ProcessMemoryLimit; | |||
public UIntPtr JobMemoryLimit; | |||
public UIntPtr PeakProcessMemoryUsed; | |||
public UIntPtr PeakJobMemoryUsed; | |||
} | |||
public enum JobObjectInfoType | |||
{ | |||
AssociateCompletionPortInformation = 7, | |||
BasicLimitInformation = 2, | |||
BasicUIRestrictions = 4, | |||
EndOfJobTimeInformation = 6, | |||
ExtendedLimitInformation = 9, | |||
SecurityLimitInformation = 5, | |||
GroupInformation = 11 | |||
} | |||
#endregion | |||
} |
@@ -1,268 +1,268 @@ | |||
using System; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Threading; | |||
namespace Shadowsocks.Util.Sockets | |||
{ | |||
/* | |||
* A wrapped socket class which support both ipv4 and ipv6 based on the | |||
* connected remote endpoint. | |||
* | |||
* If the server address is host name, then it may have both ipv4 and ipv6 address | |||
* after resolving. The main idea is we don't want to resolve and choose the address | |||
* by ourself. Instead, Socket.ConnectAsync() do handle this thing internally by trying | |||
* each address and returning an established socket connection. | |||
*/ | |||
public class WrappedSocket | |||
{ | |||
public EndPoint LocalEndPoint => _activeSocket?.LocalEndPoint; | |||
// Only used during connection and close, so it won't cost too much. | |||
private SpinLock _socketSyncLock = new SpinLock(); | |||
private bool _disposed; | |||
private bool Connected => _activeSocket != null; | |||
private Socket _activeSocket; | |||
public void BeginConnect(EndPoint remoteEP, AsyncCallback callback, object state) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (Connected) | |||
{ | |||
throw new SocketException((int) SocketError.IsConnected); | |||
} | |||
var arg = new SocketAsyncEventArgs(); | |||
arg.RemoteEndPoint = remoteEP; | |||
arg.Completed += OnTcpConnectCompleted; | |||
arg.UserToken = new TcpUserToken(callback, state); | |||
using System; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Threading; | |||
namespace Shadowsocks.Util.Sockets | |||
{ | |||
/* | |||
* A wrapped socket class which support both ipv4 and ipv6 based on the | |||
* connected remote endpoint. | |||
* | |||
* If the server address is host name, then it may have both ipv4 and ipv6 address | |||
* after resolving. The main idea is we don't want to resolve and choose the address | |||
* by ourself. Instead, Socket.ConnectAsync() do handle this thing internally by trying | |||
* each address and returning an established socket connection. | |||
*/ | |||
public class WrappedSocket | |||
{ | |||
public EndPoint LocalEndPoint => _activeSocket?.LocalEndPoint; | |||
// Only used during connection and close, so it won't cost too much. | |||
private SpinLock _socketSyncLock = new SpinLock(); | |||
private bool _disposed; | |||
private bool Connected => _activeSocket != null; | |||
private Socket _activeSocket; | |||
public void BeginConnect(EndPoint remoteEP, AsyncCallback callback, object state) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (Connected) | |||
{ | |||
throw new SocketException((int) SocketError.IsConnected); | |||
} | |||
var arg = new SocketAsyncEventArgs(); | |||
arg.RemoteEndPoint = remoteEP; | |||
arg.Completed += OnTcpConnectCompleted; | |||
arg.UserToken = new TcpUserToken(callback, state); | |||
if(!Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, arg)) | |||
{ | |||
OnTcpConnectCompleted(this, arg); | |||
} | |||
} | |||
private class FakeAsyncResult : IAsyncResult | |||
{ | |||
public bool IsCompleted { get; } = true; | |||
public WaitHandle AsyncWaitHandle { get; } = null; | |||
public object AsyncState { get; set; } | |||
public bool CompletedSynchronously { get; } = true; | |||
public Exception InternalException { get; set; } = null; | |||
} | |||
private class TcpUserToken | |||
{ | |||
public AsyncCallback Callback { get; } | |||
public object AsyncState { get; } | |||
public TcpUserToken(AsyncCallback callback, object state) | |||
{ | |||
Callback = callback; | |||
AsyncState = state; | |||
} | |||
} | |||
private void OnTcpConnectCompleted(object sender, SocketAsyncEventArgs args) | |||
{ | |||
using (args) | |||
{ | |||
args.Completed -= OnTcpConnectCompleted; | |||
var token = (TcpUserToken) args.UserToken; | |||
if (args.SocketError != SocketError.Success) | |||
{ | |||
var ex = args.ConnectByNameError ?? new SocketException((int) args.SocketError); | |||
var r = new FakeAsyncResult() | |||
{ | |||
AsyncState = token.AsyncState, | |||
InternalException = ex | |||
}; | |||
token.Callback(r); | |||
} | |||
else | |||
{ | |||
var lockTaken = false; | |||
if (!_socketSyncLock.IsHeldByCurrentThread) | |||
{ | |||
_socketSyncLock.TryEnter(ref lockTaken); | |||
} | |||
try | |||
{ | |||
if (Connected) | |||
{ | |||
args.ConnectSocket.FullClose(); | |||
} | |||
else | |||
{ | |||
_activeSocket = args.ConnectSocket; | |||
if (_disposed) | |||
{ | |||
_activeSocket.FullClose(); | |||
} | |||
var r = new FakeAsyncResult() | |||
{ | |||
AsyncState = token.AsyncState | |||
}; | |||
token.Callback(r); | |||
} | |||
} | |||
finally | |||
{ | |||
if (lockTaken) | |||
{ | |||
_socketSyncLock.Exit(); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
public void EndConnect(IAsyncResult asyncResult) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
var r = asyncResult as FakeAsyncResult; | |||
if (r == null) | |||
{ | |||
throw new ArgumentException("Invalid asyncResult.", nameof(asyncResult)); | |||
} | |||
if (r.InternalException != null) | |||
{ | |||
throw r.InternalException; | |||
} | |||
} | |||
public void Dispose() | |||
{ | |||
if (_disposed) | |||
{ | |||
return; | |||
} | |||
var lockTaken = false; | |||
if (!_socketSyncLock.IsHeldByCurrentThread) | |||
{ | |||
_socketSyncLock.TryEnter(ref lockTaken); | |||
} | |||
try | |||
{ | |||
_disposed = true; | |||
_activeSocket?.FullClose(); | |||
} | |||
finally | |||
{ | |||
if (lockTaken) | |||
{ | |||
_socketSyncLock.Exit(); | |||
} | |||
} | |||
} | |||
public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, | |||
AsyncCallback callback, | |||
object state) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int) SocketError.NotConnected); | |||
} | |||
return _activeSocket.BeginSend(buffer, offset, size, socketFlags, callback, state); | |||
} | |||
public int EndSend(IAsyncResult asyncResult) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int) SocketError.NotConnected); | |||
} | |||
return _activeSocket.EndSend(asyncResult); | |||
} | |||
public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, | |||
AsyncCallback callback, | |||
object state) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int) SocketError.NotConnected); | |||
} | |||
return _activeSocket.BeginReceive(buffer, offset, size, socketFlags, callback, state); | |||
} | |||
public int EndReceive(IAsyncResult asyncResult) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int) SocketError.NotConnected); | |||
} | |||
return _activeSocket.EndReceive(asyncResult); | |||
} | |||
public void Shutdown(SocketShutdown how) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
return; | |||
} | |||
_activeSocket.Shutdown(how); | |||
} | |||
public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue) | |||
{ | |||
SetSocketOption(optionLevel, optionName, optionValue ? 1 : 0); | |||
} | |||
public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int)SocketError.NotConnected); | |||
} | |||
_activeSocket.SetSocketOption(optionLevel, optionName, optionValue); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
private class FakeAsyncResult : IAsyncResult | |||
{ | |||
public bool IsCompleted { get; } = true; | |||
public WaitHandle AsyncWaitHandle { get; } = null; | |||
public object AsyncState { get; set; } | |||
public bool CompletedSynchronously { get; } = true; | |||
public Exception InternalException { get; set; } = null; | |||
} | |||
private class TcpUserToken | |||
{ | |||
public AsyncCallback Callback { get; } | |||
public object AsyncState { get; } | |||
public TcpUserToken(AsyncCallback callback, object state) | |||
{ | |||
Callback = callback; | |||
AsyncState = state; | |||
} | |||
} | |||
private void OnTcpConnectCompleted(object sender, SocketAsyncEventArgs args) | |||
{ | |||
using (args) | |||
{ | |||
args.Completed -= OnTcpConnectCompleted; | |||
var token = (TcpUserToken) args.UserToken; | |||
if (args.SocketError != SocketError.Success) | |||
{ | |||
var ex = args.ConnectByNameError ?? new SocketException((int) args.SocketError); | |||
var r = new FakeAsyncResult() | |||
{ | |||
AsyncState = token.AsyncState, | |||
InternalException = ex | |||
}; | |||
token.Callback(r); | |||
} | |||
else | |||
{ | |||
var lockTaken = false; | |||
if (!_socketSyncLock.IsHeldByCurrentThread) | |||
{ | |||
_socketSyncLock.TryEnter(ref lockTaken); | |||
} | |||
try | |||
{ | |||
if (Connected) | |||
{ | |||
args.ConnectSocket.FullClose(); | |||
} | |||
else | |||
{ | |||
_activeSocket = args.ConnectSocket; | |||
if (_disposed) | |||
{ | |||
_activeSocket.FullClose(); | |||
} | |||
var r = new FakeAsyncResult() | |||
{ | |||
AsyncState = token.AsyncState | |||
}; | |||
token.Callback(r); | |||
} | |||
} | |||
finally | |||
{ | |||
if (lockTaken) | |||
{ | |||
_socketSyncLock.Exit(); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
public void EndConnect(IAsyncResult asyncResult) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
var r = asyncResult as FakeAsyncResult; | |||
if (r == null) | |||
{ | |||
throw new ArgumentException("Invalid asyncResult.", nameof(asyncResult)); | |||
} | |||
if (r.InternalException != null) | |||
{ | |||
throw r.InternalException; | |||
} | |||
} | |||
public void Dispose() | |||
{ | |||
if (_disposed) | |||
{ | |||
return; | |||
} | |||
var lockTaken = false; | |||
if (!_socketSyncLock.IsHeldByCurrentThread) | |||
{ | |||
_socketSyncLock.TryEnter(ref lockTaken); | |||
} | |||
try | |||
{ | |||
_disposed = true; | |||
_activeSocket?.FullClose(); | |||
} | |||
finally | |||
{ | |||
if (lockTaken) | |||
{ | |||
_socketSyncLock.Exit(); | |||
} | |||
} | |||
} | |||
public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, | |||
AsyncCallback callback, | |||
object state) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int) SocketError.NotConnected); | |||
} | |||
return _activeSocket.BeginSend(buffer, offset, size, socketFlags, callback, state); | |||
} | |||
public int EndSend(IAsyncResult asyncResult) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int) SocketError.NotConnected); | |||
} | |||
return _activeSocket.EndSend(asyncResult); | |||
} | |||
public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, | |||
AsyncCallback callback, | |||
object state) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int) SocketError.NotConnected); | |||
} | |||
return _activeSocket.BeginReceive(buffer, offset, size, socketFlags, callback, state); | |||
} | |||
public int EndReceive(IAsyncResult asyncResult) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int) SocketError.NotConnected); | |||
} | |||
return _activeSocket.EndReceive(asyncResult); | |||
} | |||
public void Shutdown(SocketShutdown how) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
return; | |||
} | |||
_activeSocket.Shutdown(how); | |||
} | |||
public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue) | |||
{ | |||
SetSocketOption(optionLevel, optionName, optionValue ? 1 : 0); | |||
} | |||
public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue) | |||
{ | |||
if (_disposed) | |||
{ | |||
throw new ObjectDisposedException(GetType().FullName); | |||
} | |||
if (!Connected) | |||
{ | |||
throw new SocketException((int)SocketError.NotConnected); | |||
} | |||
_activeSocket.SetSocketOption(optionLevel, optionName, optionValue); | |||
} | |||
} | |||
} |
@@ -1,33 +1,33 @@ | |||
namespace Shadowsocks.View | |||
{ | |||
partial class ConfigForm | |||
{ | |||
/// <summary> | |||
/// Required designer variable. | |||
/// </summary> | |||
private System.ComponentModel.IContainer components = null; | |||
/// <summary> | |||
/// Clean up any resources being used. | |||
/// </summary> | |||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> | |||
protected override void Dispose(bool disposing) | |||
{ | |||
if (disposing && (components != null)) | |||
{ | |||
components.Dispose(); | |||
} | |||
base.Dispose(disposing); | |||
} | |||
#region Windows Form Designer generated code | |||
/// <summary> | |||
/// Required method for Designer support - do not modify | |||
/// the contents of this method with the code editor. | |||
/// </summary> | |||
private void InitializeComponent() | |||
{ | |||
namespace Shadowsocks.View | |||
{ | |||
partial class ConfigForm | |||
{ | |||
/// <summary> | |||
/// Required designer variable. | |||
/// </summary> | |||
private System.ComponentModel.IContainer components = null; | |||
/// <summary> | |||
/// Clean up any resources being used. | |||
/// </summary> | |||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> | |||
protected override void Dispose(bool disposing) | |||
{ | |||
if (disposing && (components != null)) | |||
{ | |||
components.Dispose(); | |||
} | |||
base.Dispose(disposing); | |||
} | |||
#region Windows Form Designer generated code | |||
/// <summary> | |||
/// Required method for Designer support - do not modify | |||
/// the contents of this method with the code editor. | |||
/// </summary> | |||
private void InitializeComponent() | |||
{ | |||
this.components = new System.ComponentModel.Container(); | |||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); | |||
this.PluginOptionsLabel = new System.Windows.Forms.Label(); | |||
@@ -672,51 +672,51 @@ | |||
this.ResumeLayout(false); | |||
this.PerformLayout(); | |||
} | |||
#endregion | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; | |||
private System.Windows.Forms.Label IPLabel; | |||
private System.Windows.Forms.Label ServerPortLabel; | |||
private System.Windows.Forms.Label PasswordLabel; | |||
private System.Windows.Forms.TextBox IPTextBox; | |||
private System.Windows.Forms.TextBox ServerPortTextBox; | |||
private System.Windows.Forms.Label EncryptionLabel; | |||
private System.Windows.Forms.ComboBox EncryptionSelect; | |||
private System.Windows.Forms.Panel panel2; | |||
private System.Windows.Forms.Button OKButton; | |||
private System.Windows.Forms.Button MyCancelButton; | |||
private System.Windows.Forms.Button ApplyButton; | |||
private System.Windows.Forms.Button DeleteButton; | |||
private System.Windows.Forms.Button AddButton; | |||
private System.Windows.Forms.GroupBox ServerGroupBox; | |||
private System.Windows.Forms.ListBox ServersListBox; | |||
private System.Windows.Forms.TextBox RemarksTextBox; | |||
private System.Windows.Forms.Label RemarksLabel; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5; | |||
private System.Windows.Forms.TextBox ProxyPortTextBox; | |||
private System.Windows.Forms.Label ProxyPortLabel; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6; | |||
private System.Windows.Forms.Button MoveDownButton; | |||
private System.Windows.Forms.Button MoveUpButton; | |||
private System.Windows.Forms.Button DuplicateButton; | |||
private System.Windows.Forms.Label TimeoutLabel; | |||
private System.Windows.Forms.TextBox TimeoutTextBox; | |||
private System.Windows.Forms.Label PluginOptionsLabel; | |||
private System.Windows.Forms.TextBox PluginTextBox; | |||
private System.Windows.Forms.Label PluginLabel; | |||
private System.Windows.Forms.TextBox PluginOptionsTextBox; | |||
private System.Windows.Forms.CheckBox ShowPasswdCheckBox; | |||
private System.Windows.Forms.TextBox PasswordTextBox; | |||
private System.Windows.Forms.TextBox PluginArgumentsTextBox; | |||
private System.Windows.Forms.Label PluginArgumentsLabel; | |||
private System.Windows.Forms.ToolTip toolTip1; | |||
private System.Windows.Forms.CheckBox PortableModeCheckBox; | |||
private System.Windows.Forms.CheckBox NeedPluginArgCheckBox; | |||
} | |||
} | |||
} | |||
#endregion | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; | |||
private System.Windows.Forms.Label IPLabel; | |||
private System.Windows.Forms.Label ServerPortLabel; | |||
private System.Windows.Forms.Label PasswordLabel; | |||
private System.Windows.Forms.TextBox IPTextBox; | |||
private System.Windows.Forms.TextBox ServerPortTextBox; | |||
private System.Windows.Forms.Label EncryptionLabel; | |||
private System.Windows.Forms.ComboBox EncryptionSelect; | |||
private System.Windows.Forms.Panel panel2; | |||
private System.Windows.Forms.Button OKButton; | |||
private System.Windows.Forms.Button MyCancelButton; | |||
private System.Windows.Forms.Button ApplyButton; | |||
private System.Windows.Forms.Button DeleteButton; | |||
private System.Windows.Forms.Button AddButton; | |||
private System.Windows.Forms.GroupBox ServerGroupBox; | |||
private System.Windows.Forms.ListBox ServersListBox; | |||
private System.Windows.Forms.TextBox RemarksTextBox; | |||
private System.Windows.Forms.Label RemarksLabel; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5; | |||
private System.Windows.Forms.TextBox ProxyPortTextBox; | |||
private System.Windows.Forms.Label ProxyPortLabel; | |||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6; | |||
private System.Windows.Forms.Button MoveDownButton; | |||
private System.Windows.Forms.Button MoveUpButton; | |||
private System.Windows.Forms.Button DuplicateButton; | |||
private System.Windows.Forms.Label TimeoutLabel; | |||
private System.Windows.Forms.TextBox TimeoutTextBox; | |||
private System.Windows.Forms.Label PluginOptionsLabel; | |||
private System.Windows.Forms.TextBox PluginTextBox; | |||
private System.Windows.Forms.Label PluginLabel; | |||
private System.Windows.Forms.TextBox PluginOptionsTextBox; | |||
private System.Windows.Forms.CheckBox ShowPasswdCheckBox; | |||
private System.Windows.Forms.TextBox PasswordTextBox; | |||
private System.Windows.Forms.TextBox PluginArgumentsTextBox; | |||
private System.Windows.Forms.Label PluginArgumentsLabel; | |||
private System.Windows.Forms.ToolTip toolTip1; | |||
private System.Windows.Forms.CheckBox PortableModeCheckBox; | |||
private System.Windows.Forms.CheckBox NeedPluginArgCheckBox; | |||
} | |||
} | |||
@@ -36,7 +36,7 @@ namespace Shadowsocks.View | |||
private ContextMenu contextMenu1; | |||
private MenuItem disableItem; | |||
private MenuItem AutoStartupItem; | |||
private MenuItem ProtocolHandlerItem; | |||
private MenuItem ProtocolHandlerItem; | |||
private MenuItem ShareOverLANItem; | |||
private MenuItem SeperatorItem; | |||
private MenuItem ConfigItem; | |||
@@ -316,7 +316,7 @@ namespace Shadowsocks.View | |||
this.proxyItem = CreateMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)), | |||
new MenuItem("-"), | |||
this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)), | |||
this.ProtocolHandlerItem = CreateMenuItem("Associate ss:// Links", new EventHandler(this.ProtocolHandlerItem_Click)), | |||
this.ProtocolHandlerItem = CreateMenuItem("Associate ss:// Links", new EventHandler(this.ProtocolHandlerItem_Click)), | |||
this.ShareOverLANItem = CreateMenuItem("Allow other Devices to connect", new EventHandler(this.ShareOverLANItem_Click)), | |||
new MenuItem("-"), | |||
this.hotKeyItem = CreateMenuItem("Edit Hotkeys...", new EventHandler(this.hotKeyItem_Click)), | |||
@@ -444,7 +444,7 @@ namespace Shadowsocks.View | |||
VerboseLoggingToggleItem.Checked = config.isVerboseLogging; | |||
ShowPluginOutputToggleItem.Checked = config.showPluginOutput; | |||
AutoStartupItem.Checked = AutoStartup.Check(); | |||
ProtocolHandlerItem.Checked = ProtocolHandler.Check(); | |||
ProtocolHandlerItem.Checked = ProtocolHandler.Check(); | |||
onlinePACItem.Checked = onlinePACItem.Enabled && config.useOnlinePac; | |||
localPACItem.Checked = !onlinePACItem.Checked; | |||
secureLocalPacUrlToggleItem.Checked = config.secureLocalPac; | |||
@@ -847,16 +847,16 @@ namespace Shadowsocks.View | |||
{ | |||
MessageBox.Show(I18N.GetString("Failed to update registry")); | |||
} | |||
LoadCurrentConfiguration(); | |||
} | |||
private void ProtocolHandlerItem_Click(object sender, EventArgs e) | |||
{ | |||
ProtocolHandlerItem.Checked = !ProtocolHandlerItem.Checked; | |||
if (!ProtocolHandler.Set(ProtocolHandlerItem.Checked)) | |||
{ | |||
MessageBox.Show(I18N.GetString("Failed to update registry")); | |||
} | |||
LoadCurrentConfiguration(); | |||
LoadCurrentConfiguration(); | |||
} | |||
private void ProtocolHandlerItem_Click(object sender, EventArgs e) | |||
{ | |||
ProtocolHandlerItem.Checked = !ProtocolHandlerItem.Checked; | |||
if (!ProtocolHandler.Set(ProtocolHandlerItem.Checked)) | |||
{ | |||
MessageBox.Show(I18N.GetString("Failed to update registry")); | |||
} | |||
LoadCurrentConfiguration(); | |||
} | |||
private void LocalPACItem_Click(object sender, EventArgs e) | |||
@@ -1,33 +1,33 @@ | |||
namespace Shadowsocks.View | |||
{ | |||
partial class ProxyForm | |||
{ | |||
/// <summary> | |||
/// Required designer variable. | |||
/// </summary> | |||
private System.ComponentModel.IContainer components = null; | |||
/// <summary> | |||
/// Clean up any resources being used. | |||
/// </summary> | |||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> | |||
protected override void Dispose(bool disposing) | |||
{ | |||
if (disposing && (components != null)) | |||
{ | |||
components.Dispose(); | |||
} | |||
base.Dispose(disposing); | |||
} | |||
#region Windows Form Designer generated code | |||
/// <summary> | |||
/// Required method for Designer support - do not modify | |||
/// the contents of this method with the code editor. | |||
/// </summary> | |||
private void InitializeComponent() | |||
{ | |||
namespace Shadowsocks.View | |||
{ | |||
partial class ProxyForm | |||
{ | |||
/// <summary> | |||
/// Required designer variable. | |||
/// </summary> | |||
private System.ComponentModel.IContainer components = null; | |||
/// <summary> | |||
/// Clean up any resources being used. | |||
/// </summary> | |||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> | |||
protected override void Dispose(bool disposing) | |||
{ | |||
if (disposing && (components != null)) | |||
{ | |||
components.Dispose(); | |||
} | |||
base.Dispose(disposing); | |||
} | |||
#region Windows Form Designer generated code | |||
/// <summary> | |||
/// Required method for Designer support - do not modify | |||
/// the contents of this method with the code editor. | |||
/// </summary> | |||
private void InitializeComponent() | |||
{ | |||
this.MyCancelButton = new System.Windows.Forms.Button(); | |||
this.OKButton = new System.Windows.Forms.Button(); | |||
this.UseProxyCheckBox = new System.Windows.Forms.CheckBox(); | |||
@@ -307,17 +307,17 @@ | |||
this.flowLayoutPanel1.ResumeLayout(false); | |||
this.ResumeLayout(false); | |||
} | |||
#endregion | |||
private System.Windows.Forms.CheckBox UseProxyCheckBox; | |||
private System.Windows.Forms.Label ProxyAddrLabel; | |||
private System.Windows.Forms.TextBox ProxyServerTextBox; | |||
private System.Windows.Forms.Label ProxyPortLabel; | |||
private System.Windows.Forms.TextBox ProxyPortTextBox; | |||
private System.Windows.Forms.Button MyCancelButton; | |||
private System.Windows.Forms.Button OKButton; | |||
private System.Windows.Forms.Label ProxyTypeLabel; | |||
} | |||
#endregion | |||
private System.Windows.Forms.CheckBox UseProxyCheckBox; | |||
private System.Windows.Forms.Label ProxyAddrLabel; | |||
private System.Windows.Forms.TextBox ProxyServerTextBox; | |||
private System.Windows.Forms.Label ProxyPortLabel; | |||
private System.Windows.Forms.TextBox ProxyPortTextBox; | |||
private System.Windows.Forms.Button MyCancelButton; | |||
private System.Windows.Forms.Button OKButton; | |||
private System.Windows.Forms.Label ProxyTypeLabel; | |||
private System.Windows.Forms.ComboBox ProxyTypeComboBox; | |||
private System.Windows.Forms.TextBox ProxyTimeoutTextBox; | |||
private System.Windows.Forms.Label ProxyTimeoutLabel; | |||
@@ -329,5 +329,5 @@ | |||
private System.Windows.Forms.CheckBox UseAuthCheckBox; | |||
private System.Windows.Forms.TextBox AuthUserTextBox; | |||
private System.Windows.Forms.TextBox AuthPwdTextBox; | |||
} | |||
} | |||
} |