Browse Source

Add HTTP proxy support in forward proxy (#745)

* Add HTTP proxy support in forward proxy

Signed-off-by: noisyfox <timemanager.rick@gmail.com>

* Typo

* Throw exception if forward proxy not supported.
tags/3.3.2
Noisyfox Syrone Wong 8 years ago
parent
commit
35fc73b58b
13 changed files with 532 additions and 23 deletions
  1. +11
    -1
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  2. +2
    -1
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  3. +2
    -1
      shadowsocks-csharp/Data/cn.txt
  4. +2
    -1
      shadowsocks-csharp/Data/zh_tw.txt
  5. +5
    -0
      shadowsocks-csharp/Model/Configuration.cs
  6. +6
    -4
      shadowsocks-csharp/Model/ProxyConfig.cs
  7. +199
    -0
      shadowsocks-csharp/Proxy/HttpProxy.cs
  8. +6
    -6
      shadowsocks-csharp/Proxy/Socks5Proxy.cs
  9. +231
    -0
      shadowsocks-csharp/Util/Sockets/LineReader.cs
  10. +1
    -1
      shadowsocks-csharp/View/MenuViewController.cs
  11. +58
    -7
      shadowsocks-csharp/View/ProxyForm.Designer.cs
  12. +7
    -1
      shadowsocks-csharp/View/ProxyForm.cs
  13. +2
    -0
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 11
- 1
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -420,7 +420,17 @@ namespace Shadowsocks.Controller
EndPoint proxyEP;
if (_config.proxy.useProxy)
{
remote = new Socks5Proxy();
switch (_config.proxy.proxyType)
{
case ProxyConfig.PROXY_SOCKS5:
remote = new Socks5Proxy();
break;
case ProxyConfig.PROXY_HTTP:
remote = new HttpProxy();
break;
default:
throw new NotSupportedException("Unknown forward proxy.");
}
proxyEP = SocketUtil.GetEndPoint(_config.proxy.proxyServer, _config.proxy.proxyPort);
}
else


+ 2
- 1
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -221,9 +221,10 @@ namespace Shadowsocks.Controller
SaveConfig(_config);
}
public void EnableProxy(string proxy, int port)
public void EnableProxy(int type, string proxy, int port)
{
_config.proxy.useProxy = true;
_config.proxy.proxyType = type;
_config.proxy.proxyServer = proxy;
_config.proxy.proxyPort = port;
SaveConfig(_config);


+ 2
- 1
shadowsocks-csharp/Data/cn.txt View File

@@ -12,7 +12,7 @@ Servers=服务器
Edit Servers...=编辑服务器...
Statistics Config...=统计配置...
Start on Boot=开机启动
SOCKS5 Proxy...=SOCKS5代理设置...
Forward Proxy...=正向代理设置...
Allow Clients from LAN=允许来自局域网的连接
Local PAC=使用本地 PAC
Online PAC=使用在线 PAC
@@ -58,6 +58,7 @@ Move D&own=下移(&O)
Edit Proxy=代理设置
Use Proxy=使用代理
Proxy Type=代理类型
Proxy Addr=代理地址
Proxy Port=代理端口


+ 2
- 1
shadowsocks-csharp/Data/zh_tw.txt View File

@@ -12,7 +12,7 @@ Servers=伺服器
Edit Servers...=編輯伺服器...
Statistics Config...=統計配置...
Start on Boot=開機啟動
SOCKS5 Proxy...=SOCKS5代理設置...
Forward Proxy...=正向代理設置...
Allow Clients from LAN=允許來自區域網路的連接
Local PAC=使用本地 PAC
Online PAC=使用在線 PAC
@@ -58,6 +58,7 @@ Move D&own=下移(&O)

Edit Proxy=代理設置
Use Proxy=使用代理
Proxy Type=代理類別
Proxy Addr=代理位址
Proxy Port=代理連接埠



+ 5
- 0
shadowsocks-csharp/Model/Configuration.cs View File

@@ -63,6 +63,11 @@ namespace Shadowsocks.Model
config.proxy = new ProxyConfig();
if (config.hotkey == null)
config.hotkey = new HotkeyConfig();
if (config.proxy.proxyType < ProxyConfig.PROXY_SOCKS5 || config.proxy.proxyType > ProxyConfig.PROXY_HTTP)
{
config.proxy.proxyType = ProxyConfig.PROXY_SOCKS5;
}
return config;
}
catch (Exception e)


+ 6
- 4
shadowsocks-csharp/Model/ProxyConfig.cs View File

@@ -1,20 +1,22 @@
using Shadowsocks.View;
using System;
using System.Drawing;
using System.Windows.Forms;
using System;
namespace Shadowsocks.Model
{
[Serializable]
public class ProxyConfig
{
public const int PROXY_SOCKS5 = 0;
public const int PROXY_HTTP = 1;
public bool useProxy;
public int proxyType;
public string proxyServer;
public int proxyPort;
public ProxyConfig()
{
useProxy = false;
proxyType = PROXY_SOCKS5;
proxyServer = "";
proxyPort = 0;
}


+ 199
- 0
shadowsocks-csharp/Proxy/HttpProxy.cs View File

@@ -0,0 +1,199 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Shadowsocks.Controller;
using Shadowsocks.Util.Sockets;

namespace Shadowsocks.Proxy
{
public class HttpProxy : IProxy
{
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/51.0.2704.103 Safari/537.36" + HTTP_CRLF +
"" + HTTP_CRLF; // End with an empty line

public void BeginConnectDest(EndPoint destEndPoint, AsyncCallback callback, object state)
{
DestEndPoint = destEndPoint;
string request = string.Format(HTTP_CONNECT_TEMPLATE, destEndPoint);

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)
{
// TODO: save last bytes
var st = (FakeAsyncResult)state;

if (!_established)
{
st.innerState.ex = new Exception(I18N.GetString("Proxy request failed"));
}
st.innerState.Callback?.Invoke(st);
}

private void OnException(Exception ex, object state)
{
var st = (FakeAsyncResult) state;

st.innerState.ex = ex;
st.innerState.Callback?.Invoke(st);
}

private static readonly Regex HttpRespondHeaderRegex = new Regex(@"^(HTTP/1\.\d) (\d{3}) (.+)$");
private int _respondLineCount = 0;
private bool _established = false;

private bool OnLineRead(string line, object state)
{
Logging.Debug(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;
}
}
}

+ 6
- 6
shadowsocks-csharp/Proxy/Socks5Proxy.cs View File

@@ -39,7 +39,7 @@ namespace Shadowsocks.Proxy
public Exception ex { get; set; }
}

private WrappedSocket _remote = new WrappedSocket();
private readonly WrappedSocket _remote = new WrappedSocket();

private const int Socks5PktMaxSize = 4 + 16 + 2;
private readonly byte[] _receiveBuffer = new byte[Socks5PktMaxSize];
@@ -124,7 +124,7 @@ namespace Shadowsocks.Proxy
st.Callback = callback;
st.AsyncState = state;

_remote?.BeginSend(request, 0, request.Length, 0, Socks5RequestSendCallback, st);
_remote.BeginSend(request, 0, request.Length, 0, Socks5RequestSendCallback, st);
}

public void EndConnectDest(IAsyncResult asyncResult)
@@ -140,7 +140,7 @@ namespace Shadowsocks.Proxy
public void BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback,
object state)
{
_remote?.BeginSend(buffer, offset, size, socketFlags, callback, state);
_remote.BeginSend(buffer, offset, size, socketFlags, callback, state);
}

public int EndSend(IAsyncResult asyncResult)
@@ -151,7 +151,7 @@ namespace Shadowsocks.Proxy
public void BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback,
object state)
{
_remote?.BeginReceive(buffer, offset, size, socketFlags, callback, state);
_remote.BeginReceive(buffer, offset, size, socketFlags, callback, state);
}

public int EndReceive(IAsyncResult asyncResult)
@@ -161,12 +161,12 @@ namespace Shadowsocks.Proxy

public void Shutdown(SocketShutdown how)
{
_remote?.Shutdown(how);
_remote.Shutdown(how);
}

public void Close()
{
_remote?.Dispose();
_remote.Dispose();
}



+ 231
- 0
shadowsocks-csharp/Util/Sockets/LineReader.cs View File

@@ -0,0 +1,231 @@
using System;
using System.Text;

namespace Shadowsocks.Util.Sockets
{
public class LineReader
{
private readonly WrappedSocket _socket;
private readonly Func<string, object, bool> _onLineRead;
private readonly Action<Exception, object> _onException;
private readonly Action<byte[], int, int, object> _onFinish;
private readonly Encoding _encoding;
// private readonly string _delimiter;
private readonly byte[] _delimiterBytes;
private readonly int[] _delimiterSearchCharTable;
private readonly int[] _delimiterSearchOffsetTable;
private readonly object _state;

private readonly byte[] _lineBuffer;

private int _bufferIndex;

public LineReader(WrappedSocket socket, Func<string, object, bool> onLineRead, Action<Exception, object> onException,
Action<byte[], int, int, object> onFinish, Encoding encoding, string delimiter, int maxLineBytes, object state)
{
if (socket == null)
{
throw new ArgumentNullException(nameof(socket));
}
if (onLineRead == null)
{
throw new ArgumentNullException(nameof(onLineRead));
}
if (encoding == null)
{
throw new ArgumentNullException(nameof(encoding));
}
if (delimiter == null)
{
throw new ArgumentNullException(nameof(delimiter));
}

_socket = socket;
_onLineRead = onLineRead;
_onException = onException;
_onFinish = onFinish;
_encoding = encoding;
// _delimiter = delimiter;
_state = state;

// decode delimiter
_delimiterBytes = encoding.GetBytes(delimiter);

if (_delimiterBytes.Length == 0)
{
throw new ArgumentException("Too short!", nameof(delimiter));
}

if (maxLineBytes < _delimiterBytes.Length)
{
throw new ArgumentException("Too small!", nameof(maxLineBytes));
}

_delimiterSearchCharTable = MakeCharTable(_delimiterBytes);
_delimiterSearchOffsetTable = MakeOffsetTable(_delimiterBytes);

_lineBuffer = new byte[maxLineBytes];

// start reading
socket.BeginReceive(_lineBuffer, 0, maxLineBytes, 0, ReceiveCallback, 0);
}

private void ReceiveCallback(IAsyncResult ar)
{
int length = (int)ar.AsyncState;
try
{
var bytesRead = _socket.EndReceive(ar);

if (bytesRead == 0)
{
OnFinish(length);
return;
}

length += bytesRead;

int i;
while ((i = IndexOf(_lineBuffer, _bufferIndex, length, _delimiterBytes, _delimiterSearchOffsetTable,
_delimiterSearchCharTable)) != -1)
{
var decodeLen = i - _bufferIndex;
string line = _encoding.GetString(_lineBuffer, _bufferIndex, decodeLen);

_bufferIndex = i + _delimiterBytes.Length;
length -= decodeLen;
length -= _delimiterBytes.Length;

var stop = _onLineRead(line, _state);
if (stop)
{
OnFinish(length);
return;
}
}
if (length == _lineBuffer.Length)
{
OnException(new IndexOutOfRangeException("LineBuffer full! Try increace maxLineBytes!"));
OnFinish(length);

return;
}

if (_bufferIndex > 0)
{
Buffer.BlockCopy(_lineBuffer, _bufferIndex, _lineBuffer, 0, length);
_bufferIndex = 0;
}

_socket.BeginReceive(_lineBuffer, length, _lineBuffer.Length - length, 0, ReceiveCallback, length);
}
catch (Exception ex)
{
OnException(ex);
OnFinish(length);
}
}

private void OnException(Exception ex)
{
_onException?.Invoke(ex, _state);
}

private void OnFinish(int length)
{
_onFinish?.Invoke(_lineBuffer, _bufferIndex, length, _state);
}

#region Boyer-Moore string search

public static int IndexOf(byte[] haystack, int index, int length, byte[] needle, int[] offsetTable, int[] charTable)
{
var end = index + length;
for (int i = needle.Length - 1 + index, j; i < end;)
{
for (j = needle.Length - 1; needle[j] == haystack[i]; --i, --j)
{
if (j == 0)
{
return i;
}
}
// i += needle.length - j; // For naive method
i += Math.Max(offsetTable[needle.Length - 1 - j], charTable[haystack[i]]);
}
return -1;
}

/**
* Makes the jump table based on the mismatched character information.
*/
private static int[] MakeCharTable(byte[] needle)
{
const int ALPHABET_SIZE = 256;
int[] table = new int[ALPHABET_SIZE];
for (int i = 0; i < table.Length; ++i)
{
table[i] = needle.Length;
}
for (int i = 0; i < needle.Length - 1; ++i)
{
table[needle[i]] = needle.Length - 1 - i;
}
return table;
}

/**
* Makes the jump table based on the scan offset which mismatch occurs.
*/
private static int[] MakeOffsetTable(byte[] needle)
{
int[] table = new int[needle.Length];
int lastPrefixPosition = needle.Length;
for (int i = needle.Length - 1; i >= 0; --i)
{
if (IsPrefix(needle, i + 1))
{
lastPrefixPosition = i + 1;
}
table[needle.Length - 1 - i] = lastPrefixPosition - i + needle.Length - 1;
}
for (int i = 0; i < needle.Length - 1; ++i)
{
int slen = SuffixLength(needle, i);
table[slen] = needle.Length - 1 - i + slen;
}
return table;
}

/**
* Is needle[p:end] a prefix of needle?
*/
private static bool IsPrefix(byte[] needle, int p)
{
for (int i = p, j = 0; i < needle.Length; ++i, ++j)
{
if (needle[i] != needle[j])
{
return false;
}
}
return true;
}

/**
* Returns the maximum length of the substring ends at p and is a suffix.
*/
private static int SuffixLength(byte[] needle, int p)
{
int len = 0;
for (int i = p, j = needle.Length - 1;
i >= 0 && needle[i] == needle[j]; --i, --j)
{
len += 1;
}
return len;
}

#endregion
}
}

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

@@ -271,7 +271,7 @@ namespace Shadowsocks.View
this.editGFWUserRuleItem = CreateMenuItem("Edit User Rule for GFWList...", new EventHandler(this.EditUserRuleFileForGFWListItem_Click)),
this.editOnlinePACItem = CreateMenuItem("Edit Online PAC URL...", new EventHandler(this.UpdateOnlinePACURLItem_Click)),
}),
this.proxyItem = CreateMenuItem("SOCKS5 Proxy...", new EventHandler(this.proxyItem_Click)),
this.proxyItem = CreateMenuItem("Forward Proxy...", new EventHandler(this.proxyItem_Click)),
new MenuItem("-"),
this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)),
this.ShareOverLANItem = CreateMenuItem("Allow Clients from LAN", new EventHandler(this.ShareOverLANItem_Click)),


+ 58
- 7
shadowsocks-csharp/View/ProxyForm.Designer.cs View File

@@ -38,9 +38,13 @@
this.ProxyServerTextBox = new System.Windows.Forms.TextBox();
this.ProxyPortLable = new System.Windows.Forms.Label();
this.ProxyPortTextBox = new System.Windows.Forms.TextBox();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.ProxyTypeLabel = new System.Windows.Forms.Label();
this.ProxyTypeComboBox = new System.Windows.Forms.ComboBox();
this.tableLayoutPanel1.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
@@ -49,16 +53,18 @@
this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.UseProxyCheckBox, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel4, 0, 1);
this.tableLayoutPanel1.Location = new System.Drawing.Point(15, 15);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 3;
this.tableLayoutPanel1.RowCount = 4;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(395, 87);
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(395, 123);
this.tableLayoutPanel1.TabIndex = 0;
//
// tableLayoutPanel3
@@ -72,7 +78,7 @@
this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0);
this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right;
this.tableLayoutPanel3.Location = new System.Drawing.Point(236, 58);
this.tableLayoutPanel3.Location = new System.Drawing.Point(236, 94);
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 1;
@@ -129,10 +135,11 @@
this.tableLayoutPanel2.Controls.Add(this.ProxyServerTextBox, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.ProxyPortLable, 2, 0);
this.tableLayoutPanel2.Controls.Add(this.ProxyPortTextBox, 3, 0);
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 25);
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 61);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 1;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(389, 27);
this.tableLayoutPanel2.TabIndex = 1;
//
@@ -174,6 +181,45 @@
this.ProxyPortTextBox.TabIndex = 3;
this.ProxyPortTextBox.WordWrap = false;
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.AutoSize = true;
this.tableLayoutPanel4.ColumnCount = 2;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.Controls.Add(this.ProxyTypeLabel, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.ProxyTypeComboBox, 1, 0);
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 25);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 1;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.Size = new System.Drawing.Size(198, 30);
this.tableLayoutPanel4.TabIndex = 10;
//
// ProxyTypeLabel
//
this.ProxyTypeLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.ProxyTypeLabel.AutoSize = true;
this.ProxyTypeLabel.Location = new System.Drawing.Point(3, 9);
this.ProxyTypeLabel.Name = "ProxyTypeLabel";
this.ProxyTypeLabel.Size = new System.Drawing.Size(65, 12);
this.ProxyTypeLabel.TabIndex = 1;
this.ProxyTypeLabel.Text = "Proxy Type";
//
// ProxyTypeComboBox
//
this.ProxyTypeComboBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ProxyTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.ProxyTypeComboBox.FormattingEnabled = true;
this.ProxyTypeComboBox.Items.AddRange(new object[] {
"SOCKS5",
"HTTP"});
this.ProxyTypeComboBox.Location = new System.Drawing.Point(74, 5);
this.ProxyTypeComboBox.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5);
this.ProxyTypeComboBox.Name = "ProxyTypeComboBox";
this.ProxyTypeComboBox.Size = new System.Drawing.Size(121, 20);
this.ProxyTypeComboBox.TabIndex = 2;
//
// ProxyForm
//
this.AcceptButton = this.OKButton;
@@ -182,7 +228,7 @@
this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.CancelButton = this.MyCancelButton;
this.ClientSize = new System.Drawing.Size(441, 149);
this.ClientSize = new System.Drawing.Size(441, 165);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
@@ -197,6 +243,8 @@
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.tableLayoutPanel4.ResumeLayout(false);
this.tableLayoutPanel4.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();

@@ -214,5 +262,8 @@
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.Button MyCancelButton;
private System.Windows.Forms.Button OKButton;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
private System.Windows.Forms.Label ProxyTypeLabel;
private System.Windows.Forms.ComboBox ProxyTypeComboBox;
}
}

+ 7
- 1
shadowsocks-csharp/View/ProxyForm.cs View File

@@ -32,6 +32,7 @@ namespace Shadowsocks.View
private void UpdateTexts()
{
UseProxyCheckBox.Text = I18N.GetString("Use Proxy");
ProxyTypeLabel.Text = I18N.GetString("Proxy Type");
ProxyAddrLabel.Text = I18N.GetString("Proxy Addr");
ProxyPortLable.Text = I18N.GetString("Proxy Port");
OKButton.Text = I18N.GetString("OK");
@@ -50,6 +51,7 @@ namespace Shadowsocks.View
UseProxyCheckBox.Checked = _modifiedConfiguration.useProxy;
ProxyServerTextBox.Text = _modifiedConfiguration.proxyServer;
ProxyPortTextBox.Text = _modifiedConfiguration.proxyPort.ToString();
ProxyTypeComboBox.SelectedIndex = _modifiedConfiguration.proxyType;
}
private void OKButton_Click(object sender, EventArgs e)
@@ -58,12 +60,13 @@ namespace Shadowsocks.View
{
try
{
var type = ProxyTypeComboBox.SelectedIndex;
var proxy = ProxyServerTextBox.Text;
var port = int.Parse(ProxyPortTextBox.Text);
Configuration.CheckServer(proxy);
Configuration.CheckPort(port);
controller.EnableProxy(proxy, port);
controller.EnableProxy(type, proxy, port);
}
catch (FormatException)
{
@@ -82,6 +85,7 @@ namespace Shadowsocks.View
}
_modifiedConfiguration.useProxy = UseProxyCheckBox.Checked;
_modifiedConfiguration.proxyType = ProxyTypeComboBox.SelectedIndex;
_modifiedConfiguration.proxyServer = ProxyServerTextBox.Text;
var tmpProxyPort = 0;
int.TryParse(ProxyPortTextBox.Text, out tmpProxyPort);
@@ -112,6 +116,7 @@ namespace Shadowsocks.View
{
ProxyServerTextBox.Enabled = true;
ProxyPortTextBox.Enabled = true;
ProxyTypeComboBox.Enabled = true;
}
else
{
@@ -119,6 +124,7 @@ namespace Shadowsocks.View
ProxyPortTextBox.Clear();
ProxyServerTextBox.Enabled = false;
ProxyPortTextBox.Enabled = false;
ProxyTypeComboBox.Enabled = false;
}
}
}


+ 2
- 0
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -146,6 +146,7 @@
<Compile Include="Model\HotKeyConfig.cs" />
<Compile Include="Model\ProxyConfig.cs" />
<Compile Include="Proxy\DirectConnect.cs" />
<Compile Include="Proxy\HttpProxy.cs" />
<Compile Include="Proxy\IProxy.cs" />
<Compile Include="Controller\Service\AvailabilityStatistics.cs" />
<Compile Include="Controller\Strategy\HighAvailabilityStrategy.cs" />
@@ -186,6 +187,7 @@
<Compile Include="Util\Hotkeys.cs" />
<Compile Include="Util\ProcessManagement\Job.cs" />
<Compile Include="Util\ProcessManagement\ThreadUtil.cs" />
<Compile Include="Util\Sockets\LineReader.cs" />
<Compile Include="Util\Sockets\SocketUtil.cs" />
<Compile Include="Util\Sockets\WrappedSocket.cs" />
<Compile Include="Util\Util.cs" />


Loading…
Cancel
Save