Browse Source

add gitattributes, run unix2dos to unify line ending

tags/4.2.0.0
Student Main 4 years ago
parent
commit
60321826fc
10 changed files with 1584 additions and 1580 deletions
  1. +4
    -0
      .gitattributes
  2. +533
    -533
      shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
  3. +165
    -165
      shadowsocks-csharp/Controller/Service/Sip003Plugin.cs
  4. +99
    -99
      shadowsocks-csharp/Program.cs
  5. +205
    -205
      shadowsocks-csharp/Proxy/HttpProxy.cs
  6. +180
    -180
      shadowsocks-csharp/Util/ProcessManagement/Job.cs
  7. +265
    -265
      shadowsocks-csharp/Util/Sockets/WrappedSocket.cs
  8. +78
    -78
      shadowsocks-csharp/View/ConfigForm.Designer.cs
  9. +13
    -13
      shadowsocks-csharp/View/MenuViewController.cs
  10. +42
    -42
      shadowsocks-csharp/View/ProxyForm.Designer.cs

+ 4
- 0
.gitattributes View File

@@ -0,0 +1,4 @@
* text=auto

# geosite database
*.dat binary

+ 533
- 533
shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
File diff suppressed because it is too large
View File


+ 165
- 165
shadowsocks-csharp/Controller/Service/Sip003Plugin.cs View File

@@ -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;
}
}
}
}

+ 99
- 99
shadowsocks-csharp/Program.cs View File

@@ -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


+ 205
- 205
shadowsocks-csharp/Proxy/HttpProxy.cs View File

@@ -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;
}
}
}

+ 180
- 180
shadowsocks-csharp/Util/ProcessManagement/Job.cs View File

@@ -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
}

+ 265
- 265
shadowsocks-csharp/Util/Sockets/WrappedSocket.cs View File

@@ -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);
}
}
}

+ 78
- 78
shadowsocks-csharp/View/ConfigForm.Designer.cs View File

@@ -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;
}
}

+ 13
- 13
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -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)


+ 42
- 42
shadowsocks-csharp/View/ProxyForm.Designer.cs View File

@@ -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;
}
}
}

Loading…
Cancel
Save