Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3895446715 | ||
|
|
c68283430a | ||
|
|
13ae8461d9 | ||
|
|
29afe43414 | ||
|
|
391b1de2cf | ||
|
|
8d2574b003 | ||
|
|
8e1c2193e4 | ||
|
|
86bf0b3b2c | ||
|
|
72ea01d566 | ||
|
|
b4699492ad | ||
|
|
2fdb26c063 | ||
|
|
0f72ba1e48 | ||
|
|
968c9deca0 | ||
|
|
879163dc2b | ||
|
|
b07a9ef3b0 | ||
|
|
c095030041 | ||
|
|
b8858c4f8d | ||
|
|
726200c0f1 | ||
|
|
765720dbd9 | ||
|
|
c767f55b3c | ||
|
|
14381cf887 | ||
|
|
e8fd92b9f7 | ||
|
|
99fe540e53 | ||
|
|
cec6f79e7e | ||
|
|
7ab5eae64c | ||
|
|
b1ebfe7772 | ||
|
|
f6085d9362 | ||
|
|
0b6dd0d653 | ||
|
|
7081819390 | ||
|
|
1df5e4eb8a | ||
|
|
758c497eba | ||
|
|
3e1044fc41 | ||
|
|
feaf7f70d0 | ||
|
|
e21eac1e40 | ||
|
|
750ee4fa5f | ||
|
|
3bc77d212a | ||
|
|
b623216af3 | ||
|
|
f33fb04b89 | ||
|
|
63b31f5aba | ||
|
|
590322bca2 | ||
|
|
71bd0d2b5a | ||
|
|
3b90b2124f | ||
|
|
85dc46d11e | ||
|
|
fe692f89e1 | ||
|
|
e84825c25d | ||
|
|
05726cdb67 | ||
|
|
ab38538b34 | ||
|
|
4f92fabc88 | ||
|
|
9522d1d17b | ||
|
|
36c61b7dd5 | ||
|
|
90f8b1257a | ||
|
|
7978817492 | ||
|
|
1b8584e6e1 | ||
|
|
9085480d0b | ||
|
|
23b90b8697 | ||
|
|
2449d2a5df | ||
|
|
e8cbd92a8e | ||
|
|
b4647e5b15 | ||
|
|
7d2c292034 | ||
|
|
cd49ca88a2 | ||
|
|
a3f724a1dc |
@@ -1,3 +1,25 @@
|
|||||||
|
2.5.8 2015-09-20
|
||||||
|
- Update GFWList url
|
||||||
|
|
||||||
|
2.5.7 2015-09-19
|
||||||
|
- Fix repeated IV
|
||||||
|
|
||||||
|
2.5.6 2015-08-19
|
||||||
|
- Add portable mode. Create shadowsocks_portable_mode.txt to use it
|
||||||
|
- Support server reorder
|
||||||
|
|
||||||
|
2.5.5 2015-08-17
|
||||||
|
- Fix crash when enabling Availability Statistics and some servers can not be resolved
|
||||||
|
- Allow multiple instances
|
||||||
|
- Other fixes
|
||||||
|
|
||||||
|
2.5.4 2015-08-16
|
||||||
|
- Hide Privoxy icon
|
||||||
|
|
||||||
|
2.5.3 2015-08-16
|
||||||
|
- Replace Polipo with Privoxy
|
||||||
|
- Add Choose by Total Packet Loss
|
||||||
|
|
||||||
2.5.2 2015-08-04
|
2.5.2 2015-08-04
|
||||||
- Add log viewer
|
- Add log viewer
|
||||||
|
|
||||||
|
|||||||
@@ -3,48 +3,68 @@ Shadowsocks for Windows
|
|||||||
|
|
||||||
[![Build Status]][Appveyor]
|
[![Build Status]][Appveyor]
|
||||||
|
|
||||||
|
[中文说明]
|
||||||
|
|
||||||
#### Features
|
#### Features
|
||||||
|
|
||||||
1. System proxy configuration
|
1. System proxy configuration
|
||||||
2. PAC mode and global mode
|
2. PAC mode and global mode
|
||||||
3. GFWList and user rules
|
3. [GFWList] and user rules
|
||||||
4. Supports HTTP proxy
|
4. Supports HTTP proxy
|
||||||
5. Supports server auto switching
|
5. Supports server auto switching
|
||||||
6. Supports UDP relay (see Usage)
|
6. Supports UDP relay (see Usage)
|
||||||
|
|
||||||
#### Download
|
#### Download
|
||||||
|
|
||||||
Download a [latest release].
|
Download the [latest release].
|
||||||
|
|
||||||
Notice: .Net 2.0 doesn't work well on Windows 10. We no longer support .Net 2.0. Both Shadowsocks-win-xxx.zip and Shadowsocks-win-dotnet4.0-xxx.zip are exactly the same file now. If you use Windows XP or 7, please install .Net 4.0 or higher.
|
|
||||||
|
|
||||||
#### Basic
|
#### Basic
|
||||||
|
|
||||||
1. Find Shadowsocks icon in the notification tray
|
1. Find Shadowsocks icon in the notification tray
|
||||||
2. You can add multiple servers in servers menu
|
2. You can add multiple servers in servers menu
|
||||||
3. Select Enable System Proxy menu to enable system proxy. Please disable other
|
3. Select `Enable System Proxy` menu to enable system proxy. Please disable other
|
||||||
proxy addons in your browser, or set them to use system proxy
|
proxy addons in your browser, or set them to use system proxy
|
||||||
4. You can also configure your browser proxy manually if you don't want to enable
|
4. You can also configure your browser proxy manually if you don't want to enable
|
||||||
system proxy. Set Socks5 or HTTP proxy to 127.0.0.1:1080. You can change this
|
system proxy. Set Socks5 or HTTP proxy to 127.0.0.1:1080. You can change this
|
||||||
port in Server -> Edit Servers
|
port in `Servers -> Edit Servers`
|
||||||
|
|
||||||
#### PAC
|
#### PAC
|
||||||
|
|
||||||
1. You can change PAC rules by editing the PAC file. When you save the PAC file
|
1. You can change PAC rules by editing the PAC file. When you save the PAC file
|
||||||
with any editor, Shadowsocks will notify browsers about the change automatically
|
with any editor, Shadowsocks will notify browsers about the change automatically
|
||||||
2. You can also update PAC file from GFWList (maintained by 3rd party)
|
2. You can also update PAC file from [GFWList] (maintained by 3rd party)
|
||||||
3. You can also use online PAC URL
|
3. You can also use online PAC URL
|
||||||
|
|
||||||
#### Server Auto Switching
|
#### Server Auto Switching
|
||||||
|
|
||||||
1. Load balance: choosing server randomly
|
1. Load balance: choosing server randomly
|
||||||
2. High availability: choosing the best server (low latency and packet loss)
|
2. High availability: choosing the best server (low latency and packet loss)
|
||||||
3. Write your own strategy by implement IStrategy interface and send us a pull request!
|
3. Choose By Total Package Loss: ping and choose. Please also enable
|
||||||
|
`Availability Statistics` in the menu if you want to use this
|
||||||
|
4. Write your own strategy by implement IStrategy interface and send us a pull request!
|
||||||
|
|
||||||
#### UDP
|
#### UDP
|
||||||
|
|
||||||
For UDP, you need to use SocksCap or ProxyCap to force programs you want
|
For UDP, you need to use SocksCap or ProxyCap to force programs you want
|
||||||
to proxy to tunnel over Shadowsocks
|
to be proxied to tunnel over Shadowsocks
|
||||||
|
|
||||||
|
#### Multiple Instances
|
||||||
|
|
||||||
|
If you want to manage multiple servers using other tools like SwitchyOmega,
|
||||||
|
you can start multiple Shadowsocks instances. To avoid configuration conflicts,
|
||||||
|
copy Shadowsocks to a new directory and choose a different local port.
|
||||||
|
|
||||||
|
Also, make sure to use `SOCKS5` proxy in SwitchyOmega, since we have only
|
||||||
|
one HTTP proxy instance.
|
||||||
|
|
||||||
|
#### Server Configuration
|
||||||
|
|
||||||
|
Please visit [Servers] for more information.
|
||||||
|
|
||||||
|
#### Portable Mode
|
||||||
|
|
||||||
|
If you want to put all temporary files into shadowsocks/temp folder instead of
|
||||||
|
system temp folder, create a `shadowsocks_portable_mode.txt` into shadowsocks folder.
|
||||||
|
|
||||||
#### Develop
|
#### Develop
|
||||||
|
|
||||||
@@ -55,6 +75,9 @@ Visual Studio 2015 is required.
|
|||||||
GPLv3
|
GPLv3
|
||||||
|
|
||||||
|
|
||||||
[Appveyor]: https://ci.appveyor.com/project/clowwindy/shadowsocks-csharp
|
[Appveyor]: https://ci.appveyor.com/project/icylogic/shadowsocks-windows-l9mwe
|
||||||
[Build Status]: https://ci.appveyor.com/api/projects/status/gknc8l1lxy423ehv/branch/master
|
[Build Status]: https://ci.appveyor.com/api/projects/status/ytllr9yjkbpc2tu2/branch/master
|
||||||
[latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases
|
[latest release]: https://github.com/shadowsocks/shadowsocks-csharp/releases
|
||||||
|
[GFWList]: https://github.com/gfwlist/gfwlist
|
||||||
|
[Servers]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#linux--server-side
|
||||||
|
[中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Shadowsocks.Controller
|
|||||||
static I18N()
|
static I18N()
|
||||||
{
|
{
|
||||||
Strings = new Dictionary<string, string>();
|
Strings = new Dictionary<string, string>();
|
||||||
|
|
||||||
if (System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag.ToLowerInvariant().StartsWith("zh"))
|
if (System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag.ToLowerInvariant().StartsWith("zh"))
|
||||||
{
|
{
|
||||||
string[] lines = Regex.Split(Resources.cn, "\r\n|\r|\n");
|
string[] lines = Regex.Split(Resources.cn, "\r\n|\r|\n");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Shadowsocks.Util;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
@@ -14,14 +15,14 @@ namespace Shadowsocks.Controller
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string temppath = Path.GetTempPath();
|
string temppath = Utils.GetTempPath();
|
||||||
LogFile = Path.Combine(temppath, "shadowsocks.log");
|
LogFile = Path.Combine(temppath, "shadowsocks.log");
|
||||||
FileStream fs = new FileStream(LogFile, FileMode.Append);
|
FileStream fs = new FileStream(LogFile, FileMode.Append);
|
||||||
StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs);
|
StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs);
|
||||||
sw.AutoFlush = true;
|
sw.AutoFlush = true;
|
||||||
Console.SetOut(sw);
|
Console.SetOut(sw);
|
||||||
Console.SetError(sw);
|
Console.SetError(sw);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
@@ -71,7 +72,6 @@ namespace Shadowsocks.Controller
|
|||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simply extended System.IO.StreamWriter for adding timestamp workaround
|
// Simply extended System.IO.StreamWriter for adding timestamp workaround
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Net.NetworkInformation;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Shadowsocks.Model;
|
using Shadowsocks.Model;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Shadowsocks.Util;
|
||||||
|
|
||||||
namespace Shadowsocks.Controller
|
namespace Shadowsocks.Controller
|
||||||
{
|
{
|
||||||
@@ -25,7 +26,7 @@ namespace Shadowsocks.Controller
|
|||||||
//static constructor to initialize every public static fields before refereced
|
//static constructor to initialize every public static fields before refereced
|
||||||
static AvailabilityStatistics()
|
static AvailabilityStatistics()
|
||||||
{
|
{
|
||||||
string temppath = Path.GetTempPath();
|
string temppath = Utils.GetTempPath();
|
||||||
AvailabilityStatisticsFile = Path.Combine(temppath, StatisticsFilesName);
|
AvailabilityStatisticsFile = Path.Combine(temppath, StatisticsFilesName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,14 +68,22 @@ namespace Shadowsocks.Controller
|
|||||||
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
//ICMP echo. we can also set options and special bytes
|
//ICMP echo. we can also set options and special bytes
|
||||||
//seems no need to use SendPingAsync
|
//seems no need to use SendPingAsync
|
||||||
PingReply reply = ping.Send(server.server, Timeout);
|
try
|
||||||
state.data = new List<KeyValuePair<string, string>>();
|
{
|
||||||
state.data.Add(new KeyValuePair<string, string>("Timestamp", timestamp));
|
PingReply reply = ping.Send(server.server, Timeout);
|
||||||
state.data.Add(new KeyValuePair<string, string>("Server", server.FriendlyName()));
|
state.data = new List<KeyValuePair<string, string>>();
|
||||||
state.data.Add(new KeyValuePair<string, string>("Status", reply.Status.ToString()));
|
state.data.Add(new KeyValuePair<string, string>("Timestamp", timestamp));
|
||||||
state.data.Add(new KeyValuePair<string, string>("RoundtripTime", reply.RoundtripTime.ToString()));
|
state.data.Add(new KeyValuePair<string, string>("Server", server.FriendlyName()));
|
||||||
//state.data.Add(new KeyValuePair<string, string>("data", reply.Buffer.ToString())); // The data of reply
|
state.data.Add(new KeyValuePair<string, string>("Status", reply.Status.ToString()));
|
||||||
Append(state.data);
|
state.data.Add(new KeyValuePair<string, string>("RoundtripTime", reply.RoundtripTime.ToString()));
|
||||||
|
//state.data.Add(new KeyValuePair<string, string>("data", reply.Buffer.ToString())); // The data of reply
|
||||||
|
Append(state.data);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"An exception occured when eveluating {server.FriendlyName()}");
|
||||||
|
Logging.LogUsefulException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Shadowsocks.Controller
|
|||||||
{
|
{
|
||||||
public class GFWListUpdater
|
public class GFWListUpdater
|
||||||
{
|
{
|
||||||
private const string GFWLIST_URL = "https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt";
|
private const string GFWLIST_URL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt";
|
||||||
|
|
||||||
private static string PAC_FILE = PACServer.PAC_FILE;
|
private static string PAC_FILE = PACServer.PAC_FILE;
|
||||||
|
|
||||||
@@ -97,4 +97,4 @@ namespace Shadowsocks.Controller
|
|||||||
return valid_lines;
|
return valid_lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ namespace Shadowsocks.Controller
|
|||||||
_udpSocket.Bind(localEndPoint);
|
_udpSocket.Bind(localEndPoint);
|
||||||
_tcpSocket.Listen(1024);
|
_tcpSocket.Listen(1024);
|
||||||
|
|
||||||
|
|
||||||
// Start an asynchronous socket to listen for connections.
|
// Start an asynchronous socket to listen for connections.
|
||||||
Console.WriteLine("Shadowsocks started");
|
Console.WriteLine("Shadowsocks started");
|
||||||
_tcpSocket.BeginAccept(
|
_tcpSocket.BeginAccept(
|
||||||
@@ -185,7 +184,6 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void ReceiveCallback(IAsyncResult ar)
|
private void ReceiveCallback(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
object[] state = (object[])ar.AsyncState;
|
object[] state = (object[])ar.AsyncState;
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public string TouchPACFile()
|
public string TouchPACFile()
|
||||||
{
|
{
|
||||||
if (File.Exists(PAC_FILE))
|
if (File.Exists(PAC_FILE))
|
||||||
@@ -146,7 +145,7 @@ Connection: Close
|
|||||||
", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac;
|
", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac;
|
||||||
byte[] response = System.Text.Encoding.UTF8.GetBytes(text);
|
byte[] response = System.Text.Encoding.UTF8.GetBytes(text);
|
||||||
socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket);
|
socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket);
|
||||||
Util.Utils.ReleaseMemory();
|
Util.Utils.ReleaseMemory(true);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using System.Text;
|
|||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Shadowsocks.Util;
|
||||||
|
|
||||||
namespace Shadowsocks.Controller
|
namespace Shadowsocks.Controller
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,7 @@ namespace Shadowsocks.Controller
|
|||||||
|
|
||||||
static PolipoRunner()
|
static PolipoRunner()
|
||||||
{
|
{
|
||||||
temppath = Path.GetTempPath();
|
temppath = Utils.GetTempPath();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FileManager.UncompressFile(temppath + "/ss_privoxy.exe", Resources.privoxy_exe);
|
FileManager.UncompressFile(temppath + "/ss_privoxy.exe", Resources.privoxy_exe);
|
||||||
@@ -65,10 +66,13 @@ namespace Shadowsocks.Controller
|
|||||||
polipoConfig = polipoConfig.Replace("__POLIPO_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1");
|
polipoConfig = polipoConfig.Replace("__POLIPO_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1");
|
||||||
FileManager.ByteArrayToFile(temppath + "/privoxy.conf", System.Text.Encoding.UTF8.GetBytes(polipoConfig));
|
FileManager.ByteArrayToFile(temppath + "/privoxy.conf", System.Text.Encoding.UTF8.GetBytes(polipoConfig));
|
||||||
|
|
||||||
|
if (!(temppath.EndsWith("\\") || temppath.EndsWith("/"))) {
|
||||||
|
temppath = temppath + "\\";
|
||||||
|
}
|
||||||
_process = new Process();
|
_process = new Process();
|
||||||
// Configure the process using the StartInfo properties.
|
// Configure the process using the StartInfo properties.
|
||||||
_process.StartInfo.FileName = temppath + "/ss_privoxy.exe";
|
_process.StartInfo.FileName = temppath + "ss_privoxy.exe";
|
||||||
_process.StartInfo.Arguments = " \"" + temppath + "/privoxy.conf\"";
|
_process.StartInfo.Arguments = " \"" + temppath + "privoxy.conf\"";
|
||||||
_process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
_process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
_process.StartInfo.UseShellExecute = true;
|
_process.StartInfo.UseShellExecute = true;
|
||||||
_process.StartInfo.CreateNoWindow = true;
|
_process.StartInfo.CreateNoWindow = true;
|
||||||
@@ -144,7 +148,6 @@ namespace Shadowsocks.Controller
|
|||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
|
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
|
||||||
|
|
||||||
|
|
||||||
public void RefreshTrayArea()
|
public void RefreshTrayArea()
|
||||||
{
|
{
|
||||||
IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null);
|
IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null);
|
||||||
@@ -161,7 +164,6 @@ namespace Shadowsocks.Controller
|
|||||||
RefreshTrayArea(notificationAreaHandle);
|
RefreshTrayArea(notificationAreaHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void RefreshTrayArea(IntPtr windowHandle)
|
private static void RefreshTrayArea(IntPtr windowHandle)
|
||||||
{
|
{
|
||||||
const uint wmMousemove = 0x0200;
|
const uint wmMousemove = 0x0200;
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void StartPipe(IAsyncResult ar)
|
private void StartPipe(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
if (_closed)
|
if (_closed)
|
||||||
|
|||||||
@@ -14,9 +14,18 @@ namespace Shadowsocks.Controller
|
|||||||
class TCPRelay : Listener.Service
|
class TCPRelay : Listener.Service
|
||||||
{
|
{
|
||||||
private ShadowsocksController _controller;
|
private ShadowsocksController _controller;
|
||||||
|
private DateTime _lastSweepTime;
|
||||||
|
|
||||||
|
public ISet<Handler> Handlers
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
public TCPRelay(ShadowsocksController controller)
|
public TCPRelay(ShadowsocksController controller)
|
||||||
{
|
{
|
||||||
this._controller = controller;
|
this._controller = controller;
|
||||||
|
this.Handlers = new HashSet<Handler>();
|
||||||
|
this._lastSweepTime = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Handle(byte[] firstPacket, int length, Socket socket, object state)
|
public bool Handle(byte[] firstPacket, int length, Socket socket, object state)
|
||||||
@@ -33,9 +42,33 @@ namespace Shadowsocks.Controller
|
|||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
handler.connection = socket;
|
handler.connection = socket;
|
||||||
handler.controller = _controller;
|
handler.controller = _controller;
|
||||||
|
handler.relay = this;
|
||||||
|
|
||||||
handler.Start(firstPacket, length);
|
handler.Start(firstPacket, length);
|
||||||
return true;
|
IList<Handler> handlersToClose = new List<Handler>();
|
||||||
|
lock (this.Handlers)
|
||||||
|
{
|
||||||
|
this.Handlers.Add(handler);
|
||||||
|
Logging.Debug($"connections: {Handlers.Count}");
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
if (now - _lastSweepTime > TimeSpan.FromSeconds(1))
|
||||||
|
{
|
||||||
|
_lastSweepTime = now;
|
||||||
|
foreach (Handler handler1 in this.Handlers)
|
||||||
|
{
|
||||||
|
if (now - handler1.lastActivity > TimeSpan.FromSeconds(900))
|
||||||
|
{
|
||||||
|
handlersToClose.Add(handler1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (Handler handler1 in handlersToClose)
|
||||||
|
{
|
||||||
|
Logging.Debug("Closing timed out connection");
|
||||||
|
handler1.Close();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +81,10 @@ namespace Shadowsocks.Controller
|
|||||||
public Socket remote;
|
public Socket remote;
|
||||||
public Socket connection;
|
public Socket connection;
|
||||||
public ShadowsocksController controller;
|
public ShadowsocksController controller;
|
||||||
|
public TCPRelay relay;
|
||||||
|
|
||||||
|
public DateTime lastActivity;
|
||||||
|
|
||||||
private int retryCount = 0;
|
private int retryCount = 0;
|
||||||
private bool connected;
|
private bool connected;
|
||||||
|
|
||||||
@@ -55,7 +92,7 @@ namespace Shadowsocks.Controller
|
|||||||
private byte[] _firstPacket;
|
private byte[] _firstPacket;
|
||||||
private int _firstPacketLength;
|
private int _firstPacketLength;
|
||||||
// Size of receive buffer.
|
// Size of receive buffer.
|
||||||
public const int RecvSize = 16384;
|
public const int RecvSize = 8192;
|
||||||
public const int BufferSize = RecvSize + 32;
|
public const int BufferSize = RecvSize + 32;
|
||||||
|
|
||||||
private int totalRead = 0;
|
private int totalRead = 0;
|
||||||
@@ -74,7 +111,7 @@ namespace Shadowsocks.Controller
|
|||||||
private bool connectionShutdown = false;
|
private bool connectionShutdown = false;
|
||||||
private bool remoteShutdown = false;
|
private bool remoteShutdown = false;
|
||||||
private bool closed = false;
|
private bool closed = false;
|
||||||
|
|
||||||
private object encryptionLock = new object();
|
private object encryptionLock = new object();
|
||||||
private object decryptionLock = new object();
|
private object decryptionLock = new object();
|
||||||
|
|
||||||
@@ -96,6 +133,7 @@ namespace Shadowsocks.Controller
|
|||||||
this._firstPacket = firstPacket;
|
this._firstPacket = firstPacket;
|
||||||
this._firstPacketLength = length;
|
this._firstPacketLength = length;
|
||||||
this.HandshakeReceive();
|
this.HandshakeReceive();
|
||||||
|
this.lastActivity = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckClose()
|
private void CheckClose()
|
||||||
@@ -108,6 +146,11 @@ namespace Shadowsocks.Controller
|
|||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
|
lock (relay.Handlers)
|
||||||
|
{
|
||||||
|
Logging.Debug($"connections: {relay.Handlers.Count}");
|
||||||
|
relay.Handlers.Remove(this);
|
||||||
|
}
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (closed)
|
if (closed)
|
||||||
@@ -152,7 +195,6 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void HandshakeReceive()
|
private void HandshakeReceive()
|
||||||
{
|
{
|
||||||
if (closed)
|
if (closed)
|
||||||
@@ -222,7 +264,7 @@ namespace Shadowsocks.Controller
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
int bytesRead = connection.EndReceive(ar);
|
int bytesRead = connection.EndReceive(ar);
|
||||||
|
|
||||||
if (bytesRead >= 3)
|
if (bytesRead >= 3)
|
||||||
{
|
{
|
||||||
command = connetionRecvBuffer[1];
|
command = connetionRecvBuffer[1];
|
||||||
@@ -272,7 +314,6 @@ namespace Shadowsocks.Controller
|
|||||||
|
|
||||||
private void ReadAll(IAsyncResult ar)
|
private void ReadAll(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (closed)
|
if (closed)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -347,7 +388,6 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
IPEndPoint remoteEP = new IPEndPoint(ipAddress, server.server_port);
|
IPEndPoint remoteEP = new IPEndPoint(ipAddress, server.server_port);
|
||||||
|
|
||||||
|
|
||||||
remote = new Socket(ipAddress.AddressFamily,
|
remote = new Socket(ipAddress.AddressFamily,
|
||||||
SocketType.Stream, ProtocolType.Tcp);
|
SocketType.Stream, ProtocolType.Tcp);
|
||||||
remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
|
remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
|
||||||
@@ -485,6 +525,7 @@ namespace Shadowsocks.Controller
|
|||||||
|
|
||||||
if (bytesRead > 0)
|
if (bytesRead > 0)
|
||||||
{
|
{
|
||||||
|
this.lastActivity = DateTime.Now;
|
||||||
int bytesToSend;
|
int bytesToSend;
|
||||||
lock (decryptionLock)
|
lock (decryptionLock)
|
||||||
{
|
{
|
||||||
@@ -548,7 +589,6 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null);
|
remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null);
|
||||||
|
|
||||||
|
|
||||||
IStrategy strategy = controller.GetCurrentStrategy();
|
IStrategy strategy = controller.GetCurrentStrategy();
|
||||||
if (strategy != null)
|
if (strategy != null)
|
||||||
{
|
{
|
||||||
@@ -607,5 +647,4 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,9 +108,11 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
|
// TODO: handle the ObjectDisposedException
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
// TODO: need more think about handle other Exceptions, or should remove this catch().
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -124,9 +126,11 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
|
// TODO: handle the ObjectDisposedException
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
// TODO: need more think about handle other Exceptions, or should remove this catch().
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -134,6 +138,8 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// cc by-sa 3.0 http://stackoverflow.com/a/3719378/1124054
|
// cc by-sa 3.0 http://stackoverflow.com/a/3719378/1124054
|
||||||
class LRUCache<K, V> where V : UDPRelay.UDPHandler
|
class LRUCache<K, V> where V : UDPRelay.UDPHandler
|
||||||
{
|
{
|
||||||
@@ -196,5 +202,4 @@ namespace Shadowsocks.Controller
|
|||||||
public K key;
|
public K key;
|
||||||
public V value;
|
public V value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ namespace Shadowsocks.Controller
|
|||||||
{
|
{
|
||||||
public class UpdateChecker
|
public class UpdateChecker
|
||||||
{
|
{
|
||||||
private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-csharp/releases";
|
private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-windows/releases";
|
||||||
|
|
||||||
public string LatestVersionNumber;
|
public string LatestVersionNumber;
|
||||||
public string LatestVersionURL;
|
public string LatestVersionURL;
|
||||||
public event EventHandler NewVersionFound;
|
public event EventHandler NewVersionFound;
|
||||||
|
|
||||||
public const string Version = "2.5.3";
|
public const string Version = "2.5.8";
|
||||||
|
|
||||||
public void CheckUpdate(Configuration config)
|
public void CheckUpdate(Configuration config)
|
||||||
{
|
{
|
||||||
@@ -53,7 +53,6 @@ namespace Shadowsocks.Controller
|
|||||||
{
|
{
|
||||||
return CompareVersion(ParseVersionFromURL(x), ParseVersionFromURL(y));
|
return CompareVersion(ParseVersionFromURL(x), ParseVersionFromURL(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ParseVersionFromURL(string url)
|
private static string ParseVersionFromURL(string url)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Shadowsocks.Controller
|
|||||||
public event EventHandler EnableStatusChanged;
|
public event EventHandler EnableStatusChanged;
|
||||||
public event EventHandler EnableGlobalChanged;
|
public event EventHandler EnableGlobalChanged;
|
||||||
public event EventHandler ShareOverLANStatusChanged;
|
public event EventHandler ShareOverLANStatusChanged;
|
||||||
|
|
||||||
// when user clicked Edit PAC, and PAC file has already created
|
// when user clicked Edit PAC, and PAC file has already created
|
||||||
public event EventHandler<PathEventArgs> PACFileReadyToOpen;
|
public event EventHandler<PathEventArgs> PACFileReadyToOpen;
|
||||||
public event EventHandler<PathEventArgs> UserRuleFileReadyToOpen;
|
public event EventHandler<PathEventArgs> UserRuleFileReadyToOpen;
|
||||||
@@ -360,17 +360,15 @@ namespace Shadowsocks.Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdateSystemProxy();
|
UpdateSystemProxy();
|
||||||
Util.Utils.ReleaseMemory();
|
Util.Utils.ReleaseMemory(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void SaveConfig(Configuration newConfig)
|
protected void SaveConfig(Configuration newConfig)
|
||||||
{
|
{
|
||||||
Configuration.Save(newConfig);
|
Configuration.Save(newConfig);
|
||||||
Reload();
|
Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void UpdateSystemProxy()
|
private void UpdateSystemProxy()
|
||||||
{
|
{
|
||||||
if (_config.enabled)
|
if (_config.enabled)
|
||||||
@@ -417,7 +415,7 @@ namespace Shadowsocks.Controller
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Util.Utils.ReleaseMemory();
|
Util.Utils.ReleaseMemory(false);
|
||||||
Thread.Sleep(30 * 1000);
|
Thread.Sleep(30 * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ namespace Shadowsocks.Controller.Strategy
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* IStrategy
|
* IStrategy
|
||||||
*
|
*
|
||||||
* Subclasses must be thread-safe
|
* Subclasses must be thread-safe
|
||||||
*/
|
*/
|
||||||
public interface IStrategy
|
public interface IStrategy
|
||||||
{
|
{
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
string ID { get; }
|
string ID { get; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when servers need to be reloaded, i.e. new configuration saved
|
* Called when servers need to be reloaded, i.e. new configuration saved
|
||||||
*/
|
*/
|
||||||
void ReloadServers();
|
void ReloadServers();
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ namespace Shadowsocks.Controller.Strategy
|
|||||||
).Aggregate((result1, result2) => result1.score > result2.score ? result1 : result2);
|
).Aggregate((result1, result2) => result1.score > result2.score ? result1 : result2);
|
||||||
|
|
||||||
if (_controller.GetCurrentStrategy().ID == ID && _currentServer != bestResult.server) //output when enabled
|
if (_controller.GetCurrentStrategy().ID == ID && _currentServer != bestResult.server) //output when enabled
|
||||||
{
|
{
|
||||||
Console.WriteLine("Switch to server: {0} by package loss:{1}", bestResult.server.FriendlyName(), 1 - bestResult.score);
|
Console.WriteLine("Switch to server: {0} by package loss:{1}", bestResult.server.FriendlyName(), 1 - bestResult.score);
|
||||||
}
|
}
|
||||||
_currentServer = bestResult.server;
|
_currentServer = bestResult.server;
|
||||||
|
|||||||
@@ -56,18 +56,14 @@ namespace Shadowsocks.Controller
|
|||||||
pacUrl = "http://127.0.0.1:" + config.localPort.ToString() + "/pac?t=" + GetTimestamp(DateTime.Now);
|
pacUrl = "http://127.0.0.1:" + config.localPort.ToString() + "/pac?t=" + GetTimestamp(DateTime.Now);
|
||||||
registry.SetValue("ProxyEnable", 0);
|
registry.SetValue("ProxyEnable", 0);
|
||||||
var readProxyServer = registry.GetValue("ProxyServer");
|
var readProxyServer = registry.GetValue("ProxyServer");
|
||||||
if (readProxyServer != null && readProxyServer.Equals("127.0.0.1:" + config.localPort.ToString()))
|
registry.SetValue("ProxyServer", "");
|
||||||
registry.SetValue("ProxyServer", "");
|
|
||||||
registry.SetValue("AutoConfigURL", pacUrl);
|
registry.SetValue("AutoConfigURL", pacUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
registry.SetValue("ProxyEnable", 0);
|
registry.SetValue("ProxyEnable", 0);
|
||||||
if (global)
|
registry.SetValue("ProxyServer", "");
|
||||||
{
|
|
||||||
registry.SetValue("ProxyServer", "");
|
|
||||||
}
|
|
||||||
registry.SetValue("AutoConfigURL", "");
|
registry.SetValue("AutoConfigURL", "");
|
||||||
}
|
}
|
||||||
//Set AutoDetectProxy Off
|
//Set AutoDetectProxy Off
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ Update Local PAC from GFWList=从 GFWList 更新本地 PAC
|
|||||||
Edit User Rule for GFWList...=编辑 GFWList 的用户规则...
|
Edit User Rule for GFWList...=编辑 GFWList 的用户规则...
|
||||||
Show QRCode...=显示二维码...
|
Show QRCode...=显示二维码...
|
||||||
Scan QRCode from Screen...=扫描屏幕上的二维码...
|
Scan QRCode from Screen...=扫描屏幕上的二维码...
|
||||||
|
Availability Statistics=统计可用性
|
||||||
Show Logs...=显示日志...
|
Show Logs...=显示日志...
|
||||||
About...=关于...
|
About...=关于...
|
||||||
Quit=退出
|
Quit=退出
|
||||||
@@ -41,6 +42,19 @@ Remarks=备注
|
|||||||
OK=确定
|
OK=确定
|
||||||
Cancel=取消
|
Cancel=取消
|
||||||
New server=未配置的服务器
|
New server=未配置的服务器
|
||||||
|
Move &Up=上移(&U)
|
||||||
|
Move D&own=下移(&O)
|
||||||
|
|
||||||
|
# Log Form
|
||||||
|
|
||||||
|
&File=文件(&F)
|
||||||
|
&Open Location=在资源管理器中打开(&O)
|
||||||
|
E&xit=退出(&X)
|
||||||
|
&Clean logs=清空(&C)
|
||||||
|
&Font=字体(&F)
|
||||||
|
&Wrap text=自动换行(&W)
|
||||||
|
&Top most=置顶(&T)
|
||||||
|
Log Viewer=日志查看器
|
||||||
|
|
||||||
# QRCode Form
|
# QRCode Form
|
||||||
|
|
||||||
@@ -72,7 +86,10 @@ Failed to update PAC file =更新 PAC 文件失败
|
|||||||
PAC updated=更新 PAC 成功
|
PAC updated=更新 PAC 成功
|
||||||
No updates found. Please report to GFWList if you have problems with it.=未发现更新。如有问题请提交给 GFWList。
|
No updates found. Please report to GFWList if you have problems with it.=未发现更新。如有问题请提交给 GFWList。
|
||||||
No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置
|
No QRCode found. Try to zoom in or move it to the center of the screen.=未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置
|
||||||
|
Shadowsocks is already running.=Shadowsocks 已经在运行。
|
||||||
|
Find Shadowsocks icon in your notify tray.=请在任务栏里寻找 Shadowsocks 图标。
|
||||||
|
If you want to start multiple Shadowsocks, make a copy in another directory.=如果想同时启动多个,可以另外复制一份到别的目录。
|
||||||
Failed to decode QRCode=无法解析二维码
|
Failed to decode QRCode=无法解析二维码
|
||||||
Failed to update registry=无法修改注册表
|
Failed to update registry=无法修改注册表
|
||||||
System Proxy On: =系统代理已启用:
|
System Proxy On: =系统代理已启用:
|
||||||
Running: Port {0}=正在运行:端口 {0}
|
Running: Port {0}=正在运行:端口 {0}
|
||||||
|
|||||||
Binary file not shown.
@@ -26,7 +26,6 @@ namespace Shadowsocks.Encryption
|
|||||||
protected int keyLen;
|
protected int keyLen;
|
||||||
protected int ivLen;
|
protected int ivLen;
|
||||||
|
|
||||||
|
|
||||||
public IVEncryptor(string method, string password)
|
public IVEncryptor(string method, string password)
|
||||||
: base(method, password)
|
: base(method, password)
|
||||||
{
|
{
|
||||||
@@ -89,7 +88,8 @@ namespace Shadowsocks.Encryption
|
|||||||
protected static void randBytes(byte[] buf, int length)
|
protected static void randBytes(byte[] buf, int length)
|
||||||
{
|
{
|
||||||
byte[] temp = new byte[length];
|
byte[] temp = new byte[length];
|
||||||
new Random().NextBytes(temp);
|
RNGCryptoServiceProvider rngServiceProvider = new RNGCryptoServiceProvider();
|
||||||
|
rngServiceProvider.GetBytes(temp);
|
||||||
temp.CopyTo(buf, 0);
|
temp.CopyTo(buf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Shadowsocks.Controller;
|
using Shadowsocks.Controller;
|
||||||
using Shadowsocks.Properties;
|
using Shadowsocks.Properties;
|
||||||
|
using Shadowsocks.Util;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -18,7 +19,7 @@ namespace Shadowsocks.Encryption
|
|||||||
|
|
||||||
static PolarSSL()
|
static PolarSSL()
|
||||||
{
|
{
|
||||||
string tempPath = Path.GetTempPath();
|
string tempPath = Utils.GetTempPath();
|
||||||
string dllPath = tempPath + "/libsscrypto.dll";
|
string dllPath = tempPath + "/libsscrypto.dll";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -49,7 +50,6 @@ namespace Shadowsocks.Encryption
|
|||||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public extern static int aes_crypt_cfb128(IntPtr ctx, int mode, int length, ref int iv_off, byte[] iv, byte[] input, byte[] output);
|
public extern static int aes_crypt_cfb128(IntPtr ctx, int mode, int length, ref int iv_off, byte[] iv, byte[] input, byte[] output);
|
||||||
|
|
||||||
|
|
||||||
public const int ARC4_CTX_SIZE = 264;
|
public const int ARC4_CTX_SIZE = 264;
|
||||||
|
|
||||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Shadowsocks.Controller;
|
using Shadowsocks.Controller;
|
||||||
using Shadowsocks.Properties;
|
using Shadowsocks.Properties;
|
||||||
|
using Shadowsocks.Util;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -14,7 +15,7 @@ namespace Shadowsocks.Encryption
|
|||||||
|
|
||||||
static Sodium()
|
static Sodium()
|
||||||
{
|
{
|
||||||
string tempPath = Path.GetTempPath();
|
string tempPath = Utils.GetTempPath();
|
||||||
string dllPath = tempPath + "/libsscrypto.dll";
|
string dllPath = tempPath + "/libsscrypto.dll";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Shadowsocks.Encryption
|
namespace Shadowsocks.Encryption
|
||||||
{
|
{
|
||||||
@@ -12,19 +13,17 @@ namespace Shadowsocks.Encryption
|
|||||||
|
|
||||||
const int SODIUM_BLOCK_SIZE = 64;
|
const int SODIUM_BLOCK_SIZE = 64;
|
||||||
|
|
||||||
|
static byte[] sodiumBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
|
||||||
|
|
||||||
protected int _encryptBytesRemaining;
|
protected int _encryptBytesRemaining;
|
||||||
protected int _decryptBytesRemaining;
|
protected int _decryptBytesRemaining;
|
||||||
protected ulong _encryptIC;
|
protected ulong _encryptIC;
|
||||||
protected ulong _decryptIC;
|
protected ulong _decryptIC;
|
||||||
protected byte[] _encryptBuf;
|
|
||||||
protected byte[] _decryptBuf;
|
|
||||||
|
|
||||||
public SodiumEncryptor(string method, string password)
|
public SodiumEncryptor(string method, string password)
|
||||||
: base(method, password)
|
: base(method, password)
|
||||||
{
|
{
|
||||||
InitKey(method, password);
|
InitKey(method, password);
|
||||||
_encryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
|
|
||||||
_decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<string, int[]> _ciphers = new Dictionary<string, int[]> {
|
private static Dictionary<string, int[]> _ciphers = new Dictionary<string, int[]> {
|
||||||
@@ -47,48 +46,51 @@ namespace Shadowsocks.Encryption
|
|||||||
// TODO write a unidirection cipher so we don't have to if if if
|
// TODO write a unidirection cipher so we don't have to if if if
|
||||||
int bytesRemaining;
|
int bytesRemaining;
|
||||||
ulong ic;
|
ulong ic;
|
||||||
byte[] sodiumBuf;
|
|
||||||
byte[] iv;
|
byte[] iv;
|
||||||
if (isCipher)
|
|
||||||
{
|
|
||||||
bytesRemaining = _encryptBytesRemaining;
|
|
||||||
ic = _encryptIC;
|
|
||||||
sodiumBuf = _encryptBuf;
|
|
||||||
iv = _encryptIV;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bytesRemaining = _decryptBytesRemaining;
|
|
||||||
ic = _decryptIC;
|
|
||||||
sodiumBuf = _decryptBuf;
|
|
||||||
iv = _decryptIV;
|
|
||||||
}
|
|
||||||
int padding = bytesRemaining;
|
|
||||||
Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length);
|
|
||||||
|
|
||||||
switch (_cipher)
|
// I'm tired. just add a big lock
|
||||||
|
// let's optimize for RAM instead of CPU
|
||||||
|
lock(sodiumBuf)
|
||||||
{
|
{
|
||||||
case CIPHER_SALSA20:
|
if (isCipher)
|
||||||
Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
|
{
|
||||||
break;
|
bytesRemaining = _encryptBytesRemaining;
|
||||||
case CIPHER_CHACHA20:
|
ic = _encryptIC;
|
||||||
Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
|
iv = _encryptIV;
|
||||||
break;
|
}
|
||||||
}
|
else
|
||||||
Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length);
|
{
|
||||||
padding += length;
|
bytesRemaining = _decryptBytesRemaining;
|
||||||
ic += (ulong)padding / SODIUM_BLOCK_SIZE;
|
ic = _decryptIC;
|
||||||
bytesRemaining = padding % SODIUM_BLOCK_SIZE;
|
iv = _decryptIV;
|
||||||
|
}
|
||||||
|
int padding = bytesRemaining;
|
||||||
|
Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length);
|
||||||
|
|
||||||
if (isCipher)
|
switch (_cipher)
|
||||||
{
|
{
|
||||||
_encryptBytesRemaining = bytesRemaining;
|
case CIPHER_SALSA20:
|
||||||
_encryptIC = ic;
|
Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
|
||||||
}
|
break;
|
||||||
else
|
case CIPHER_CHACHA20:
|
||||||
{
|
Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
|
||||||
_decryptBytesRemaining = bytesRemaining;
|
break;
|
||||||
_decryptIC = ic;
|
}
|
||||||
|
Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length);
|
||||||
|
padding += length;
|
||||||
|
ic += (ulong)padding / SODIUM_BLOCK_SIZE;
|
||||||
|
bytesRemaining = padding % SODIUM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
if (isCipher)
|
||||||
|
{
|
||||||
|
_encryptBytesRemaining = bytesRemaining;
|
||||||
|
_encryptIC = ic;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_decryptBytesRemaining = bytesRemaining;
|
||||||
|
_decryptIC = ic;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ namespace Shadowsocks.Encryption
|
|||||||
outlength = length;
|
outlength = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
||||||
{
|
{
|
||||||
byte[] result = new byte[length];
|
byte[] result = new byte[length];
|
||||||
@@ -100,7 +99,6 @@ namespace Shadowsocks.Encryption
|
|||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ namespace Shadowsocks
|
|||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
Util.Utils.ReleaseMemory();
|
Util.Utils.ReleaseMemory(true);
|
||||||
using (Mutex mutex = new Mutex(false, "Global\\" + "71981632-A427-497F-AB91-241CD227EC1F"))
|
using (Mutex mutex = new Mutex(false, "Global\\Shadowsocks_" + Application.StartupPath.GetHashCode()))
|
||||||
{
|
{
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
@@ -31,7 +31,9 @@ namespace Shadowsocks
|
|||||||
{
|
{
|
||||||
Process oldProcess = oldProcesses[0];
|
Process oldProcess = oldProcesses[0];
|
||||||
}
|
}
|
||||||
MessageBox.Show("Shadowsocks is already running.\n\nFind Shadowsocks icon in your notify tray.");
|
MessageBox.Show(I18N.GetString("Find Shadowsocks icon in your notify tray.") + "\n" +
|
||||||
|
I18N.GetString("If you want to start multiple Shadowsocks, make a copy in another directory."),
|
||||||
|
I18N.GetString("Shadowsocks is already running."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Directory.SetCurrentDirectory(Application.StartupPath);
|
Directory.SetCurrentDirectory(Application.StartupPath);
|
||||||
|
|||||||
@@ -5,12 +5,31 @@ using System.IO;
|
|||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace Shadowsocks.Util
|
namespace Shadowsocks.Util
|
||||||
{
|
{
|
||||||
public class Utils
|
public class Utils
|
||||||
{
|
{
|
||||||
public static void ReleaseMemory()
|
// return path to store temporary files
|
||||||
|
public static string GetTempPath()
|
||||||
|
{
|
||||||
|
if (File.Exists(Application.StartupPath + "\\shadowsocks_portable_mode.txt"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Application.StartupPath + "\\temp");
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
// don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log
|
||||||
|
return Application.StartupPath + "\\temp";
|
||||||
|
}
|
||||||
|
return Path.GetTempPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ReleaseMemory(bool removePages)
|
||||||
{
|
{
|
||||||
// release any unused pages
|
// release any unused pages
|
||||||
// making the numbers look good in task manager
|
// making the numbers look good in task manager
|
||||||
@@ -20,8 +39,29 @@ namespace Shadowsocks.Util
|
|||||||
// which is part of user experience
|
// which is part of user experience
|
||||||
GC.Collect(GC.MaxGeneration);
|
GC.Collect(GC.MaxGeneration);
|
||||||
GC.WaitForPendingFinalizers();
|
GC.WaitForPendingFinalizers();
|
||||||
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
|
if (removePages)
|
||||||
(UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF);
|
{
|
||||||
|
// as some users have pointed out
|
||||||
|
// removing pages from working set will cause some IO
|
||||||
|
// which lowered user experience for another group of users
|
||||||
|
//
|
||||||
|
// so we do 2 more things here to satisfy them:
|
||||||
|
// 1. only remove pages once when configuration is changed
|
||||||
|
// 2. add more comments here to tell users that calling
|
||||||
|
// this function will not be more frequent than
|
||||||
|
// IM apps writing chat logs, or web browsers writing cache files
|
||||||
|
// if they're so concerned about their disk, they should
|
||||||
|
// uninstall all IM apps and web browsers
|
||||||
|
//
|
||||||
|
// please open an issue if you're worried about anything else in your computer
|
||||||
|
// no matter it's GPU performance, monitor contrast, audio fidelity
|
||||||
|
// or anything else in the task manager
|
||||||
|
// we'll do as much as we can to help you
|
||||||
|
//
|
||||||
|
// just kidding
|
||||||
|
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
|
||||||
|
(UIntPtr)0xFFFFFFFF, (UIntPtr)0xFFFFFFFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string UnGzip(byte[] buf)
|
public static string UnGzip(byte[] buf)
|
||||||
|
|||||||
+53
-1
@@ -47,6 +47,9 @@
|
|||||||
this.ServerGroupBox = new System.Windows.Forms.GroupBox();
|
this.ServerGroupBox = new System.Windows.Forms.GroupBox();
|
||||||
this.ServersListBox = new System.Windows.Forms.ListBox();
|
this.ServersListBox = new System.Windows.Forms.ListBox();
|
||||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||||
|
this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();
|
||||||
|
this.MoveDownButton = new System.Windows.Forms.Button();
|
||||||
|
this.MoveUpButton = new System.Windows.Forms.Button();
|
||||||
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
|
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
|
||||||
this.ProxyPortTextBox = new System.Windows.Forms.TextBox();
|
this.ProxyPortTextBox = new System.Windows.Forms.TextBox();
|
||||||
this.ProxyPortLabel = new System.Windows.Forms.Label();
|
this.ProxyPortLabel = new System.Windows.Forms.Label();
|
||||||
@@ -55,6 +58,7 @@
|
|||||||
this.tableLayoutPanel1.SuspendLayout();
|
this.tableLayoutPanel1.SuspendLayout();
|
||||||
this.ServerGroupBox.SuspendLayout();
|
this.ServerGroupBox.SuspendLayout();
|
||||||
this.tableLayoutPanel2.SuspendLayout();
|
this.tableLayoutPanel2.SuspendLayout();
|
||||||
|
this.tableLayoutPanel6.SuspendLayout();
|
||||||
this.tableLayoutPanel5.SuspendLayout();
|
this.tableLayoutPanel5.SuspendLayout();
|
||||||
this.tableLayoutPanel3.SuspendLayout();
|
this.tableLayoutPanel3.SuspendLayout();
|
||||||
this.tableLayoutPanel4.SuspendLayout();
|
this.tableLayoutPanel4.SuspendLayout();
|
||||||
@@ -184,7 +188,7 @@
|
|||||||
//
|
//
|
||||||
// EncryptionSelect
|
// EncryptionSelect
|
||||||
//
|
//
|
||||||
this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
this.EncryptionSelect.FormattingEnabled = true;
|
this.EncryptionSelect.FormattingEnabled = true;
|
||||||
@@ -281,6 +285,7 @@
|
|||||||
//
|
//
|
||||||
this.ServersListBox.FormattingEnabled = true;
|
this.ServersListBox.FormattingEnabled = true;
|
||||||
this.ServersListBox.IntegralHeight = false;
|
this.ServersListBox.IntegralHeight = false;
|
||||||
|
this.ServersListBox.ItemHeight = 12;
|
||||||
this.ServersListBox.Location = new System.Drawing.Point(0, 0);
|
this.ServersListBox.Location = new System.Drawing.Point(0, 0);
|
||||||
this.ServersListBox.Margin = new System.Windows.Forms.Padding(0);
|
this.ServersListBox.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.ServersListBox.Name = "ServersListBox";
|
this.ServersListBox.Name = "ServersListBox";
|
||||||
@@ -295,6 +300,7 @@
|
|||||||
this.tableLayoutPanel2.ColumnCount = 2;
|
this.tableLayoutPanel2.ColumnCount = 2;
|
||||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||||
|
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel6, 0, 2);
|
||||||
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel5, 1, 1);
|
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel5, 1, 1);
|
||||||
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 1, 2);
|
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 1, 2);
|
||||||
this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0);
|
this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0);
|
||||||
@@ -310,6 +316,48 @@
|
|||||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 238);
|
this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 238);
|
||||||
this.tableLayoutPanel2.TabIndex = 7;
|
this.tableLayoutPanel2.TabIndex = 7;
|
||||||
//
|
//
|
||||||
|
// tableLayoutPanel6
|
||||||
|
//
|
||||||
|
this.tableLayoutPanel6.AutoSize = true;
|
||||||
|
this.tableLayoutPanel6.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||||
|
this.tableLayoutPanel6.ColumnCount = 2;
|
||||||
|
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||||
|
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||||
|
this.tableLayoutPanel6.Controls.Add(this.MoveDownButton, 1, 0);
|
||||||
|
this.tableLayoutPanel6.Controls.Add(this.MoveUpButton, 0, 0);
|
||||||
|
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Top;
|
||||||
|
this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 211);
|
||||||
|
this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
|
||||||
|
this.tableLayoutPanel6.RowCount = 1;
|
||||||
|
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||||
|
this.tableLayoutPanel6.Size = new System.Drawing.Size(166, 32);
|
||||||
|
this.tableLayoutPanel6.TabIndex = 10;
|
||||||
|
//
|
||||||
|
// MoveDownButton
|
||||||
|
//
|
||||||
|
this.MoveDownButton.Dock = System.Windows.Forms.DockStyle.Right;
|
||||||
|
this.MoveDownButton.Location = new System.Drawing.Point(86, 6);
|
||||||
|
this.MoveDownButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3);
|
||||||
|
this.MoveDownButton.Name = "MoveDownButton";
|
||||||
|
this.MoveDownButton.Size = new System.Drawing.Size(80, 23);
|
||||||
|
this.MoveDownButton.TabIndex = 7;
|
||||||
|
this.MoveDownButton.Text = "Move D&own";
|
||||||
|
this.MoveDownButton.UseVisualStyleBackColor = true;
|
||||||
|
this.MoveDownButton.Click += new System.EventHandler(this.MoveDownButton_Click);
|
||||||
|
//
|
||||||
|
// MoveUpButton
|
||||||
|
//
|
||||||
|
this.MoveUpButton.Dock = System.Windows.Forms.DockStyle.Left;
|
||||||
|
this.MoveUpButton.Location = new System.Drawing.Point(0, 6);
|
||||||
|
this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3);
|
||||||
|
this.MoveUpButton.Name = "MoveUpButton";
|
||||||
|
this.MoveUpButton.Size = new System.Drawing.Size(80, 23);
|
||||||
|
this.MoveUpButton.TabIndex = 6;
|
||||||
|
this.MoveUpButton.Text = "Move &Up";
|
||||||
|
this.MoveUpButton.UseVisualStyleBackColor = true;
|
||||||
|
this.MoveUpButton.Click += new System.EventHandler(this.MoveUpButton_Click);
|
||||||
|
//
|
||||||
// tableLayoutPanel5
|
// tableLayoutPanel5
|
||||||
//
|
//
|
||||||
this.tableLayoutPanel5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.tableLayoutPanel5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
@@ -418,6 +466,7 @@
|
|||||||
this.ServerGroupBox.PerformLayout();
|
this.ServerGroupBox.PerformLayout();
|
||||||
this.tableLayoutPanel2.ResumeLayout(false);
|
this.tableLayoutPanel2.ResumeLayout(false);
|
||||||
this.tableLayoutPanel2.PerformLayout();
|
this.tableLayoutPanel2.PerformLayout();
|
||||||
|
this.tableLayoutPanel6.ResumeLayout(false);
|
||||||
this.tableLayoutPanel5.ResumeLayout(false);
|
this.tableLayoutPanel5.ResumeLayout(false);
|
||||||
this.tableLayoutPanel5.PerformLayout();
|
this.tableLayoutPanel5.PerformLayout();
|
||||||
this.tableLayoutPanel3.ResumeLayout(false);
|
this.tableLayoutPanel3.ResumeLayout(false);
|
||||||
@@ -453,6 +502,9 @@
|
|||||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5;
|
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5;
|
||||||
private System.Windows.Forms.TextBox ProxyPortTextBox;
|
private System.Windows.Forms.TextBox ProxyPortTextBox;
|
||||||
private System.Windows.Forms.Label ProxyPortLabel;
|
private System.Windows.Forms.Label ProxyPortLabel;
|
||||||
|
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6;
|
||||||
|
private System.Windows.Forms.Button MoveDownButton;
|
||||||
|
private System.Windows.Forms.Button MoveUpButton;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Shadowsocks.View
|
|||||||
|
|
||||||
// this is a copy of configuration that we are working on
|
// this is a copy of configuration that we are working on
|
||||||
private Configuration _modifiedConfiguration;
|
private Configuration _modifiedConfiguration;
|
||||||
private int _oldSelectedIndex = -1;
|
private int _lastSelectedIndex = -1;
|
||||||
|
|
||||||
public ConfigForm(ShadowsocksController controller)
|
public ConfigForm(ShadowsocksController controller)
|
||||||
{
|
{
|
||||||
@@ -51,6 +51,8 @@ namespace Shadowsocks.View
|
|||||||
ServerGroupBox.Text = I18N.GetString("Server");
|
ServerGroupBox.Text = I18N.GetString("Server");
|
||||||
OKButton.Text = I18N.GetString("OK");
|
OKButton.Text = I18N.GetString("OK");
|
||||||
MyCancelButton.Text = I18N.GetString("Cancel");
|
MyCancelButton.Text = I18N.GetString("Cancel");
|
||||||
|
MoveUpButton.Text = I18N.GetString("Move &Up");
|
||||||
|
MoveDownButton.Text = I18N.GetString("Move D&own");
|
||||||
this.Text = I18N.GetString("Edit Servers");
|
this.Text = I18N.GetString("Edit Servers");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +60,7 @@ namespace Shadowsocks.View
|
|||||||
{
|
{
|
||||||
LoadCurrentConfiguration();
|
LoadCurrentConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowWindow()
|
private void ShowWindow()
|
||||||
{
|
{
|
||||||
this.Opacity = 1;
|
this.Opacity = 1;
|
||||||
@@ -70,7 +72,7 @@ namespace Shadowsocks.View
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_oldSelectedIndex == -1 || _oldSelectedIndex >= _modifiedConfiguration.configs.Count)
|
if (_lastSelectedIndex == -1 || _lastSelectedIndex >= _modifiedConfiguration.configs.Count)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -85,9 +87,9 @@ namespace Shadowsocks.View
|
|||||||
int localPort = int.Parse(ProxyPortTextBox.Text);
|
int localPort = int.Parse(ProxyPortTextBox.Text);
|
||||||
Configuration.CheckServer(server);
|
Configuration.CheckServer(server);
|
||||||
Configuration.CheckLocalPort(localPort);
|
Configuration.CheckLocalPort(localPort);
|
||||||
_modifiedConfiguration.configs[_oldSelectedIndex] = server;
|
_modifiedConfiguration.configs[_lastSelectedIndex] = server;
|
||||||
_modifiedConfiguration.localPort = localPort;
|
_modifiedConfiguration.localPort = localPort;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (FormatException)
|
catch (FormatException)
|
||||||
@@ -113,12 +115,6 @@ namespace Shadowsocks.View
|
|||||||
ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString();
|
ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString();
|
||||||
EncryptionSelect.Text = server.method ?? "aes-256-cfb";
|
EncryptionSelect.Text = server.method ?? "aes-256-cfb";
|
||||||
RemarksTextBox.Text = server.remarks;
|
RemarksTextBox.Text = server.remarks;
|
||||||
ServerGroupBox.Visible = true;
|
|
||||||
//IPTextBox.Focus();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ServerGroupBox.Visible = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,12 +131,13 @@ namespace Shadowsocks.View
|
|||||||
{
|
{
|
||||||
_modifiedConfiguration = controller.GetConfigurationCopy();
|
_modifiedConfiguration = controller.GetConfigurationCopy();
|
||||||
LoadConfiguration(_modifiedConfiguration);
|
LoadConfiguration(_modifiedConfiguration);
|
||||||
_oldSelectedIndex = _modifiedConfiguration.index;
|
_lastSelectedIndex = _modifiedConfiguration.index;
|
||||||
if (_oldSelectedIndex < 0)
|
if (_lastSelectedIndex < 0)
|
||||||
{
|
{
|
||||||
_oldSelectedIndex = 0;
|
_lastSelectedIndex = 0;
|
||||||
}
|
}
|
||||||
ServersListBox.SelectedIndex = _oldSelectedIndex;
|
ServersListBox.SelectedIndex = _lastSelectedIndex;
|
||||||
|
UpdateMoveUpAndDownButton();
|
||||||
LoadSelectedServer();
|
LoadSelectedServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,9 +146,35 @@ namespace Shadowsocks.View
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ConfigForm_KeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
// Sometimes the users may hit enter key by mistake, and the form will close without saving entries.
|
||||||
|
|
||||||
|
if (e.KeyCode == Keys.Enter)
|
||||||
|
{
|
||||||
|
Server server = controller.GetCurrentServer();
|
||||||
|
if (!SaveOldSelectedServer())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_modifiedConfiguration.configs.Count == 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show(I18N.GetString("Please add at least one server"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort);
|
||||||
|
controller.SelectServerIndex(_modifiedConfiguration.configs.IndexOf(server));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e)
|
private void ServersListBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (_oldSelectedIndex == ServersListBox.SelectedIndex)
|
if (!ServersListBox.CanSelect)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_lastSelectedIndex == ServersListBox.SelectedIndex)
|
||||||
{
|
{
|
||||||
// we are moving back to oldSelectedIndex or doing a force move
|
// we are moving back to oldSelectedIndex or doing a force move
|
||||||
return;
|
return;
|
||||||
@@ -159,11 +182,13 @@ namespace Shadowsocks.View
|
|||||||
if (!SaveOldSelectedServer())
|
if (!SaveOldSelectedServer())
|
||||||
{
|
{
|
||||||
// why this won't cause stack overflow?
|
// why this won't cause stack overflow?
|
||||||
ServersListBox.SelectedIndex = _oldSelectedIndex;
|
ServersListBox.SelectedIndex = _lastSelectedIndex;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ServersListBox.Items[_lastSelectedIndex] = _modifiedConfiguration.configs[_lastSelectedIndex].FriendlyName();
|
||||||
|
UpdateMoveUpAndDownButton();
|
||||||
LoadSelectedServer();
|
LoadSelectedServer();
|
||||||
_oldSelectedIndex = ServersListBox.SelectedIndex;
|
_lastSelectedIndex = ServersListBox.SelectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddButton_Click(object sender, EventArgs e)
|
private void AddButton_Click(object sender, EventArgs e)
|
||||||
@@ -176,29 +201,30 @@ namespace Shadowsocks.View
|
|||||||
_modifiedConfiguration.configs.Add(server);
|
_modifiedConfiguration.configs.Add(server);
|
||||||
LoadConfiguration(_modifiedConfiguration);
|
LoadConfiguration(_modifiedConfiguration);
|
||||||
ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1;
|
ServersListBox.SelectedIndex = _modifiedConfiguration.configs.Count - 1;
|
||||||
_oldSelectedIndex = ServersListBox.SelectedIndex;
|
_lastSelectedIndex = ServersListBox.SelectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteButton_Click(object sender, EventArgs e)
|
private void DeleteButton_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
_oldSelectedIndex = ServersListBox.SelectedIndex;
|
_lastSelectedIndex = ServersListBox.SelectedIndex;
|
||||||
if (_oldSelectedIndex >= 0 && _oldSelectedIndex < _modifiedConfiguration.configs.Count)
|
if (_lastSelectedIndex >= 0 && _lastSelectedIndex < _modifiedConfiguration.configs.Count)
|
||||||
{
|
{
|
||||||
_modifiedConfiguration.configs.RemoveAt(_oldSelectedIndex);
|
_modifiedConfiguration.configs.RemoveAt(_lastSelectedIndex);
|
||||||
}
|
}
|
||||||
if (_oldSelectedIndex >= _modifiedConfiguration.configs.Count)
|
if (_lastSelectedIndex >= _modifiedConfiguration.configs.Count)
|
||||||
{
|
{
|
||||||
// can be -1
|
// can be -1
|
||||||
_oldSelectedIndex = _modifiedConfiguration.configs.Count - 1;
|
_lastSelectedIndex = _modifiedConfiguration.configs.Count - 1;
|
||||||
}
|
}
|
||||||
ServersListBox.SelectedIndex = _oldSelectedIndex;
|
ServersListBox.SelectedIndex = _lastSelectedIndex;
|
||||||
LoadConfiguration(_modifiedConfiguration);
|
LoadConfiguration(_modifiedConfiguration);
|
||||||
ServersListBox.SelectedIndex = _oldSelectedIndex;
|
ServersListBox.SelectedIndex = _lastSelectedIndex;
|
||||||
LoadSelectedServer();
|
LoadSelectedServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OKButton_Click(object sender, EventArgs e)
|
private void OKButton_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
Server server = controller.GetCurrentServer();
|
||||||
if (!SaveOldSelectedServer())
|
if (!SaveOldSelectedServer())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -209,6 +235,7 @@ namespace Shadowsocks.View
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort);
|
controller.SaveServers(_modifiedConfiguration.configs, _modifiedConfiguration.localPort);
|
||||||
|
controller.SelectServerIndex(_modifiedConfiguration.configs.IndexOf(server));
|
||||||
this.Close();
|
this.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,5 +254,70 @@ namespace Shadowsocks.View
|
|||||||
controller.ConfigChanged -= controller_ConfigChanged;
|
controller.ConfigChanged -= controller_ConfigChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MoveConfigItem(int step)
|
||||||
|
{
|
||||||
|
int index = ServersListBox.SelectedIndex;
|
||||||
|
Server server = _modifiedConfiguration.configs[index];
|
||||||
|
object item = ServersListBox.SelectedItem;
|
||||||
|
|
||||||
|
_modifiedConfiguration.configs.Remove(server);
|
||||||
|
_modifiedConfiguration.configs.Insert(index + step, server);
|
||||||
|
_modifiedConfiguration.index += step;
|
||||||
|
|
||||||
|
ServersListBox.BeginUpdate();
|
||||||
|
ServersListBox.Enabled = false;
|
||||||
|
_lastSelectedIndex = index + step;
|
||||||
|
ServersListBox.Items.Remove(item);
|
||||||
|
ServersListBox.Items.Insert(index + step, item);
|
||||||
|
ServersListBox.Enabled = true;
|
||||||
|
ServersListBox.SelectedIndex = index + step;
|
||||||
|
ServersListBox.EndUpdate();
|
||||||
|
|
||||||
|
UpdateMoveUpAndDownButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateMoveUpAndDownButton()
|
||||||
|
{
|
||||||
|
if (ServersListBox.SelectedIndex == 0)
|
||||||
|
{
|
||||||
|
MoveUpButton.Enabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MoveUpButton.Enabled = true;
|
||||||
|
}
|
||||||
|
if (ServersListBox.SelectedIndex == ServersListBox.Items.Count - 1)
|
||||||
|
{
|
||||||
|
MoveDownButton.Enabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MoveDownButton.Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MoveUpButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!SaveOldSelectedServer())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ServersListBox.SelectedIndex > 0)
|
||||||
|
{
|
||||||
|
MoveConfigItem(-1); // -1 means move backward
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MoveDownButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!SaveOldSelectedServer())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ServersListBox.SelectedIndex < ServersListBox.Items.Count - 1)
|
||||||
|
{
|
||||||
|
MoveConfigItem(+1); // +1 means move forward
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,9 +112,9 @@
|
|||||||
<value>2.0</value>
|
<value>2.0</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="reader">
|
<resheader name="reader">
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
</root>
|
</root>
|
||||||
+127
-41
@@ -29,29 +29,37 @@
|
|||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
this.LogMessageTextBox = new System.Windows.Forms.TextBox();
|
||||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||||
this.mainMenu1 = new System.Windows.Forms.MainMenu(this.components);
|
this.mainMenu1 = new System.Windows.Forms.MainMenu(this.components);
|
||||||
this.menuItem1 = new System.Windows.Forms.MenuItem();
|
this.FileMenuItem = new System.Windows.Forms.MenuItem();
|
||||||
this.menuItem2 = new System.Windows.Forms.MenuItem();
|
this.OpenLocationMenuItem = new System.Windows.Forms.MenuItem();
|
||||||
this.menuItem4 = new System.Windows.Forms.MenuItem();
|
this.ExitMenuItem = new System.Windows.Forms.MenuItem();
|
||||||
|
this.panel1 = new System.Windows.Forms.Panel();
|
||||||
|
this.ChangeFontButton = new System.Windows.Forms.Button();
|
||||||
|
this.CleanLogsButton = new System.Windows.Forms.Button();
|
||||||
|
this.WrapTextCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
|
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||||
|
this.TopMostCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
|
this.panel1.SuspendLayout();
|
||||||
|
this.tableLayoutPanel1.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// textBox1
|
// LogMessageTextBox
|
||||||
//
|
//
|
||||||
this.textBox1.BackColor = System.Drawing.Color.Black;
|
this.LogMessageTextBox.BackColor = System.Drawing.Color.Black;
|
||||||
this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill;
|
this.LogMessageTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.textBox1.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
this.LogMessageTextBox.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.textBox1.ForeColor = System.Drawing.Color.White;
|
this.LogMessageTextBox.ForeColor = System.Drawing.Color.White;
|
||||||
this.textBox1.Location = new System.Drawing.Point(0, 0);
|
this.LogMessageTextBox.Location = new System.Drawing.Point(3, 43);
|
||||||
this.textBox1.MaxLength = 2147483647;
|
this.LogMessageTextBox.MaxLength = 2147483647;
|
||||||
this.textBox1.Multiline = true;
|
this.LogMessageTextBox.Multiline = true;
|
||||||
this.textBox1.Name = "textBox1";
|
this.LogMessageTextBox.Name = "LogMessageTextBox";
|
||||||
this.textBox1.ReadOnly = true;
|
this.LogMessageTextBox.ReadOnly = true;
|
||||||
this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
this.LogMessageTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
this.textBox1.Size = new System.Drawing.Size(547, 382);
|
this.LogMessageTextBox.Size = new System.Drawing.Size(541, 307);
|
||||||
this.textBox1.TabIndex = 0;
|
this.LogMessageTextBox.TabIndex = 0;
|
||||||
this.textBox1.WordWrap = false;
|
this.LogMessageTextBox.WordWrap = false;
|
||||||
//
|
//
|
||||||
// contextMenuStrip1
|
// contextMenuStrip1
|
||||||
//
|
//
|
||||||
@@ -61,34 +69,103 @@
|
|||||||
// mainMenu1
|
// mainMenu1
|
||||||
//
|
//
|
||||||
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
|
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
|
||||||
this.menuItem1});
|
this.FileMenuItem});
|
||||||
//
|
//
|
||||||
// menuItem1
|
// FileMenuItem
|
||||||
//
|
//
|
||||||
this.menuItem1.Index = 0;
|
this.FileMenuItem.Index = 0;
|
||||||
this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
|
this.FileMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
|
||||||
this.menuItem2,
|
this.OpenLocationMenuItem,
|
||||||
this.menuItem4});
|
this.ExitMenuItem});
|
||||||
this.menuItem1.Text = "&File";
|
this.FileMenuItem.Text = "&File";
|
||||||
//
|
//
|
||||||
// menuItem2
|
// OpenLocationMenuItem
|
||||||
//
|
//
|
||||||
this.menuItem2.Index = 0;
|
this.OpenLocationMenuItem.Index = 0;
|
||||||
this.menuItem2.Text = "&Open Location";
|
this.OpenLocationMenuItem.Text = "&Open Location";
|
||||||
this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);
|
this.OpenLocationMenuItem.Click += new System.EventHandler(this.OpenLocationMenuItem_Click);
|
||||||
//
|
//
|
||||||
// menuItem4
|
// ExitMenuItem
|
||||||
//
|
//
|
||||||
this.menuItem4.Index = 1;
|
this.ExitMenuItem.Index = 1;
|
||||||
this.menuItem4.Text = "E&xit";
|
this.ExitMenuItem.Text = "E&xit";
|
||||||
this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);
|
this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click);
|
||||||
|
//
|
||||||
|
// panel1
|
||||||
|
//
|
||||||
|
this.panel1.Controls.Add(this.TopMostCheckBox);
|
||||||
|
this.panel1.Controls.Add(this.ChangeFontButton);
|
||||||
|
this.panel1.Controls.Add(this.CleanLogsButton);
|
||||||
|
this.panel1.Controls.Add(this.WrapTextCheckBox);
|
||||||
|
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.panel1.Location = new System.Drawing.Point(3, 3);
|
||||||
|
this.panel1.Name = "panel1";
|
||||||
|
this.panel1.Size = new System.Drawing.Size(541, 34);
|
||||||
|
this.panel1.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// ChangeFontButton
|
||||||
|
//
|
||||||
|
this.ChangeFontButton.Location = new System.Drawing.Point(107, 4);
|
||||||
|
this.ChangeFontButton.Name = "ChangeFontButton";
|
||||||
|
this.ChangeFontButton.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ChangeFontButton.TabIndex = 2;
|
||||||
|
this.ChangeFontButton.Text = "&Font";
|
||||||
|
this.ChangeFontButton.UseVisualStyleBackColor = true;
|
||||||
|
this.ChangeFontButton.Click += new System.EventHandler(this.ChangeFontButton_Click);
|
||||||
|
//
|
||||||
|
// CleanLogsButton
|
||||||
|
//
|
||||||
|
this.CleanLogsButton.Location = new System.Drawing.Point(9, 4);
|
||||||
|
this.CleanLogsButton.Name = "CleanLogsButton";
|
||||||
|
this.CleanLogsButton.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.CleanLogsButton.TabIndex = 1;
|
||||||
|
this.CleanLogsButton.Text = "&Clean logs";
|
||||||
|
this.CleanLogsButton.UseVisualStyleBackColor = true;
|
||||||
|
this.CleanLogsButton.Click += new System.EventHandler(this.CleanLogsButton_Click);
|
||||||
|
//
|
||||||
|
// WrapTextCheckBox
|
||||||
|
//
|
||||||
|
this.WrapTextCheckBox.AutoSize = true;
|
||||||
|
this.WrapTextCheckBox.Location = new System.Drawing.Point(209, 9);
|
||||||
|
this.WrapTextCheckBox.Name = "WrapTextCheckBox";
|
||||||
|
this.WrapTextCheckBox.Size = new System.Drawing.Size(78, 16);
|
||||||
|
this.WrapTextCheckBox.TabIndex = 0;
|
||||||
|
this.WrapTextCheckBox.Text = "&Wrap text";
|
||||||
|
this.WrapTextCheckBox.UseVisualStyleBackColor = true;
|
||||||
|
this.WrapTextCheckBox.CheckedChanged += new System.EventHandler(this.WrapTextCheckBox_CheckedChanged);
|
||||||
|
//
|
||||||
|
// tableLayoutPanel1
|
||||||
|
//
|
||||||
|
this.tableLayoutPanel1.ColumnCount = 1;
|
||||||
|
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
|
this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 0);
|
||||||
|
this.tableLayoutPanel1.Controls.Add(this.LogMessageTextBox, 0, 1);
|
||||||
|
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
|
this.tableLayoutPanel1.RowCount = 2;
|
||||||
|
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
|
||||||
|
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||||
|
this.tableLayoutPanel1.Size = new System.Drawing.Size(547, 353);
|
||||||
|
this.tableLayoutPanel1.TabIndex = 2;
|
||||||
|
//
|
||||||
|
// TopMostCheckBox
|
||||||
|
//
|
||||||
|
this.TopMostCheckBox.AutoSize = true;
|
||||||
|
this.TopMostCheckBox.Location = new System.Drawing.Point(311, 9);
|
||||||
|
this.TopMostCheckBox.Name = "TopMostCheckBox";
|
||||||
|
this.TopMostCheckBox.Size = new System.Drawing.Size(72, 16);
|
||||||
|
this.TopMostCheckBox.TabIndex = 3;
|
||||||
|
this.TopMostCheckBox.Text = "&Top most";
|
||||||
|
this.TopMostCheckBox.UseVisualStyleBackColor = true;
|
||||||
|
this.TopMostCheckBox.CheckedChanged += new System.EventHandler(this.TopMostCheckBox_CheckedChanged);
|
||||||
//
|
//
|
||||||
// LogForm
|
// LogForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(547, 382);
|
this.ClientSize = new System.Drawing.Size(547, 353);
|
||||||
this.Controls.Add(this.textBox1);
|
this.Controls.Add(this.tableLayoutPanel1);
|
||||||
this.Menu = this.mainMenu1;
|
this.Menu = this.mainMenu1;
|
||||||
this.Name = "LogForm";
|
this.Name = "LogForm";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
@@ -96,18 +173,27 @@
|
|||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LogForm_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LogForm_FormClosing);
|
||||||
this.Load += new System.EventHandler(this.LogForm_Load);
|
this.Load += new System.EventHandler(this.LogForm_Load);
|
||||||
this.Shown += new System.EventHandler(this.LogForm_Shown);
|
this.Shown += new System.EventHandler(this.LogForm_Shown);
|
||||||
|
this.panel1.ResumeLayout(false);
|
||||||
|
this.panel1.PerformLayout();
|
||||||
|
this.tableLayoutPanel1.ResumeLayout(false);
|
||||||
|
this.tableLayoutPanel1.PerformLayout();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.TextBox textBox1;
|
private System.Windows.Forms.TextBox LogMessageTextBox;
|
||||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
|
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
|
||||||
private System.Windows.Forms.MainMenu mainMenu1;
|
private System.Windows.Forms.MainMenu mainMenu1;
|
||||||
private System.Windows.Forms.MenuItem menuItem1;
|
private System.Windows.Forms.MenuItem FileMenuItem;
|
||||||
private System.Windows.Forms.MenuItem menuItem2;
|
private System.Windows.Forms.MenuItem OpenLocationMenuItem;
|
||||||
private System.Windows.Forms.MenuItem menuItem4;
|
private System.Windows.Forms.MenuItem ExitMenuItem;
|
||||||
|
private System.Windows.Forms.Panel panel1;
|
||||||
|
private System.Windows.Forms.CheckBox WrapTextCheckBox;
|
||||||
|
private System.Windows.Forms.Button CleanLogsButton;
|
||||||
|
private System.Windows.Forms.Button ChangeFontButton;
|
||||||
|
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||||
|
private System.Windows.Forms.CheckBox TopMostCheckBox;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Shadowsocks.Properties;
|
using Shadowsocks.Controller;
|
||||||
|
using Shadowsocks.Properties;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@@ -23,6 +24,20 @@ namespace Shadowsocks.View
|
|||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
|
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
|
||||||
|
|
||||||
|
UpdateTexts();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTexts()
|
||||||
|
{
|
||||||
|
FileMenuItem.Text = I18N.GetString("&File");
|
||||||
|
OpenLocationMenuItem.Text = I18N.GetString("&Open Location");
|
||||||
|
ExitMenuItem.Text = I18N.GetString("E&xit");
|
||||||
|
CleanLogsButton.Text = I18N.GetString("&Clean logs");
|
||||||
|
ChangeFontButton.Text = I18N.GetString("&Font");
|
||||||
|
WrapTextCheckBox.Text = I18N.GetString("&Wrap text");
|
||||||
|
TopMostCheckBox.Text = I18N.GetString("&Top most");
|
||||||
|
this.Text = I18N.GetString("Log Viewer");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Timer_Tick(object sender, EventArgs e)
|
private void Timer_Tick(object sender, EventArgs e)
|
||||||
@@ -43,9 +58,9 @@ namespace Shadowsocks.View
|
|||||||
|
|
||||||
string line = "";
|
string line = "";
|
||||||
while ((line = reader.ReadLine()) != null)
|
while ((line = reader.ReadLine()) != null)
|
||||||
textBox1.AppendText(line + "\r\n");
|
LogMessageTextBox.AppendText(line + "\r\n");
|
||||||
|
|
||||||
textBox1.ScrollToCaret();
|
LogMessageTextBox.ScrollToCaret();
|
||||||
|
|
||||||
lastOffset = reader.BaseStream.Position;
|
lastOffset = reader.BaseStream.Position;
|
||||||
}
|
}
|
||||||
@@ -63,12 +78,12 @@ namespace Shadowsocks.View
|
|||||||
while ((line = reader.ReadLine()) != null)
|
while ((line = reader.ReadLine()) != null)
|
||||||
{
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
textBox1.AppendText(line + "\r\n");
|
LogMessageTextBox.AppendText(line + "\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
textBox1.ScrollToCaret();
|
LogMessageTextBox.ScrollToCaret();
|
||||||
}
|
}
|
||||||
|
|
||||||
lastOffset = reader.BaseStream.Position;
|
lastOffset = reader.BaseStream.Position;
|
||||||
@@ -89,25 +104,47 @@ namespace Shadowsocks.View
|
|||||||
timer.Stop();
|
timer.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void menuItem2_Click(object sender, EventArgs e)
|
private void OpenLocationMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
string argument = @"/select, " + filename;
|
string argument = "/select, \"" + filename + "\"";
|
||||||
|
Console.WriteLine(argument);
|
||||||
System.Diagnostics.Process.Start("explorer.exe", argument);
|
System.Diagnostics.Process.Start("explorer.exe", argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void menuItem3_Click(object sender, EventArgs e)
|
private void ExitMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void menuItem4_Click(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
this.Close();
|
this.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogForm_Shown(object sender, EventArgs e)
|
private void LogForm_Shown(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
textBox1.ScrollToCaret();
|
LogMessageTextBox.ScrollToCaret();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WrapTextCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
LogMessageTextBox.WordWrap = WrapTextCheckBox.Checked;
|
||||||
|
LogMessageTextBox.ScrollToCaret();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CleanLogsButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
LogMessageTextBox.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangeFontButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
FontDialog fd = new FontDialog();
|
||||||
|
fd.Font = LogMessageTextBox.Font;
|
||||||
|
if (fd.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
LogMessageTextBox.Font = fd.Font;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TopMostCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.TopMost = TopMostCheckBox.Checked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Shadowsocks.View
|
|||||||
// yes this is just a menu view controller
|
// yes this is just a menu view controller
|
||||||
// when config form is closed, it moves away from RAM
|
// when config form is closed, it moves away from RAM
|
||||||
// and it should just do anything related to the config form
|
// and it should just do anything related to the config form
|
||||||
|
|
||||||
private ShadowsocksController controller;
|
private ShadowsocksController controller;
|
||||||
private UpdateChecker updateChecker;
|
private UpdateChecker updateChecker;
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ namespace Shadowsocks.View
|
|||||||
void configForm_FormClosed(object sender, FormClosedEventArgs e)
|
void configForm_FormClosed(object sender, FormClosedEventArgs e)
|
||||||
{
|
{
|
||||||
configForm = null;
|
configForm = null;
|
||||||
Util.Utils.ReleaseMemory();
|
Util.Utils.ReleaseMemory(true);
|
||||||
ShowFirstTimeBalloon();
|
ShowFirstTimeBalloon();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,17 +520,17 @@ namespace Shadowsocks.View
|
|||||||
Process.Start(_urlToOpen);
|
Process.Start(_urlToOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AutoStartupItem_Click(object sender, EventArgs e) {
|
private void AutoStartupItem_Click(object sender, EventArgs e) {
|
||||||
AutoStartupItem.Checked = !AutoStartupItem.Checked;
|
AutoStartupItem.Checked = !AutoStartupItem.Checked;
|
||||||
if (!AutoStartup.Set(AutoStartupItem.Checked)) {
|
if (!AutoStartup.Set(AutoStartupItem.Checked)) {
|
||||||
MessageBox.Show(I18N.GetString("Failed to update registry"));
|
MessageBox.Show(I18N.GetString("Failed to update registry"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AvailabilityStatisticsItem_Click(object sender, EventArgs e) {
|
private void AvailabilityStatisticsItem_Click(object sender, EventArgs e) {
|
||||||
AvailabilityStatistics.Checked = !AvailabilityStatistics.Checked;
|
AvailabilityStatistics.Checked = !AvailabilityStatistics.Checked;
|
||||||
controller.ToggleAvailabilityStatistics(AvailabilityStatistics.Checked);
|
controller.ToggleAvailabilityStatistics(AvailabilityStatistics.Checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LocalPACItem_Click(object sender, EventArgs e)
|
private void LocalPACItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -242,7 +242,6 @@ namespace Shadowsocks.View
|
|||||||
SetBitmap(bitmap, 255);
|
SetBitmap(bitmap, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <para>Changes the current bitmap with a custom opacity level. Here is where all happens!</para>
|
/// <para>Changes the current bitmap with a custom opacity level. Here is where all happens!</para>
|
||||||
public void SetBitmap(Bitmap bitmap, byte opacity)
|
public void SetBitmap(Bitmap bitmap, byte opacity)
|
||||||
{
|
{
|
||||||
@@ -288,7 +287,6 @@ namespace Shadowsocks.View
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override CreateParams CreateParams
|
protected override CreateParams CreateParams
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|||||||
Reference in New Issue
Block a user