Browse Source

Merge upstream

# Conflicts:
#	README.md
#	shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
#	shadowsocks-csharp/Controller/Service/PACServer.cs
#	shadowsocks-csharp/Controller/Strategy/SimplyChooseByStatisticsStrategy.cs
#	shadowsocks-csharp/Data/cn.txt
#	shadowsocks-csharp/Model/Configuration.cs
#	shadowsocks-csharp/Model/LogViewerConfig.cs
#	shadowsocks-csharp/View/LogForm.Designer.cs
#	shadowsocks-csharp/View/LogForm.cs
#	shadowsocks-csharp/View/MenuViewController.cs
tags/3.0
kimw 9 years ago
parent
commit
0b16ef7445
20 changed files with 295 additions and 90 deletions
  1. +11
    -2
      shadowsocks-csharp/Controller/Logging.cs
  2. +2
    -3
      shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
  3. +2
    -1
      shadowsocks-csharp/Controller/Service/GfwListUpdater.cs
  4. +3
    -3
      shadowsocks-csharp/Controller/Service/Listener.cs
  5. +75
    -20
      shadowsocks-csharp/Controller/Service/PACServer.cs
  6. +2
    -2
      shadowsocks-csharp/Controller/Service/PolipoRunner.cs
  7. +0
    -1
      shadowsocks-csharp/Controller/Service/PortForwarder.cs
  8. +8
    -10
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  9. +36
    -0
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  10. +5
    -5
      shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs
  11. +1
    -1
      shadowsocks-csharp/Encryption/PolarSSL.cs
  12. +1
    -1
      shadowsocks-csharp/Encryption/Sodium.cs
  13. +2
    -1
      shadowsocks-csharp/Model/Configuration.cs
  14. +31
    -8
      shadowsocks-csharp/Model/LogViewerConfig.cs
  15. +5
    -2
      shadowsocks-csharp/Util/Util.cs
  16. +7
    -6
      shadowsocks-csharp/View/LogForm.Designer.cs
  17. +30
    -14
      shadowsocks-csharp/View/LogForm.cs
  18. +37
    -6
      shadowsocks-csharp/View/MenuViewController.cs
  19. +7
    -4
      test/packages.config
  20. +30
    -0
      test/test.csproj

+ 11
- 2
shadowsocks-csharp/Controller/Logging.cs View File

@@ -32,11 +32,20 @@ namespace Shadowsocks.Controller
} }
} }
public static void Debug(object o)
public static void Error(object o)
{ {
Console.WriteLine("[E] "+ o);
}
#if DEBUG
public static void Info(object o)
{
Console.WriteLine(o); Console.WriteLine(o);
}
public static void Debug(object o)
{
#if DEBUG
Console.WriteLine("[D] " + o);
#endif #endif
} }


+ 2
- 3
shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs View File

@@ -126,8 +126,7 @@ namespace Shadowsocks.Controller
var IP = Dns.GetHostAddresses(server.server).First(ip => (ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6)); var IP = Dns.GetHostAddresses(server.server).First(ip => (ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6));
var ping = new Ping(); var ping = new Ping();
var ret = new List<DataList>(); var ret = new List<DataList>();
foreach (
var timestamp in Enumerable.Range(0, Repeat).Select(_ => DateTime.Now.ToString(DateTimePattern)))
foreach (var timestamp in Enumerable.Range(0, Repeat).Select(_ => DateTime.Now.ToString(DateTimePattern)))
{ {
//ICMP echo. we can also set options and special bytes //ICMP echo. we can also set options and special bytes
try try
@@ -146,7 +145,7 @@ namespace Shadowsocks.Controller
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine($"An exception occured when eveluating {server.FriendlyName()}");
Logging.Error($"An exception occured while eveluating {server.FriendlyName()}");
Logging.LogUsefulException(e); Logging.LogUsefulException(e);
} }
} }


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

@@ -38,6 +38,7 @@ namespace Shadowsocks.Controller
{ {
try try
{ {
File.WriteAllText(Utils.GetTempPath() + "\\gfwlist.txt", e.Result, Encoding.UTF8);
List<string> lines = ParseResult(e.Result); List<string> lines = ParseResult(e.Result);
if (File.Exists(USER_RULE_FILE)) if (File.Exists(USER_RULE_FILE))
{ {
@@ -92,7 +93,7 @@ namespace Shadowsocks.Controller
http.DownloadStringAsync(new Uri(GFWLIST_URL)); http.DownloadStringAsync(new Uri(GFWLIST_URL));
} }
public List<string> ParseResult(string response)
public static List<string> ParseResult(string response)
{ {
byte[] bytes = Convert.FromBase64String(response); byte[] bytes = Convert.FromBase64String(response);
string content = Encoding.ASCII.GetString(bytes); string content = Encoding.ASCII.GetString(bytes);


+ 3
- 3
shadowsocks-csharp/Controller/Service/Listener.cs View File

@@ -78,7 +78,7 @@ namespace Shadowsocks.Controller
_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");
Logging.Info("Shadowsocks started");
_tcpSocket.BeginAccept( _tcpSocket.BeginAccept(
new AsyncCallback(AcceptCallback), new AsyncCallback(AcceptCallback),
_tcpSocket); _tcpSocket);
@@ -163,7 +163,7 @@ namespace Shadowsocks.Controller
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e);
Logging.LogUsefulException(e);
} }
finally finally
{ {
@@ -208,7 +208,7 @@ namespace Shadowsocks.Controller
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e);
Logging.LogUsefulException(e);
conn.Close(); conn.Close();
} }
} }


+ 75
- 20
shadowsocks-csharp/Controller/Service/PACServer.cs View File

@@ -2,6 +2,7 @@
using Shadowsocks.Properties; using Shadowsocks.Properties;
using Shadowsocks.Util; using Shadowsocks.Util;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@@ -15,19 +16,20 @@ namespace Shadowsocks.Controller
class PACServer : Listener.Service class PACServer : Listener.Service
{ {
public static string PAC_FILE = "pac.txt"; public static string PAC_FILE = "pac.txt";
public static string USER_RULE_FILE = "user-rule.txt"; public static string USER_RULE_FILE = "user-rule.txt";
public static string USER_ABP_FILE = "abp.txt"; public static string USER_ABP_FILE = "abp.txt";
FileSystemWatcher watcher;
FileSystemWatcher PACFileWatcher;
FileSystemWatcher UserRuleFileWatcher;
private Configuration _config; private Configuration _config;
public event EventHandler PACFileChanged; public event EventHandler PACFileChanged;
public event EventHandler UserRuleFileChanged;
public PACServer() public PACServer()
{ {
this.WatchPacFile(); this.WatchPacFile();
this.WatchUserRuleFile();
} }
public void UpdateConfiguration(Configuration config) public void UpdateConfiguration(Configuration config)
@@ -151,7 +153,7 @@ Connection: Close
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e);
Logging.LogUsefulException(e);
socket.Close(); socket.Close();
} }
} }
@@ -169,28 +171,81 @@ Connection: Close
private void WatchPacFile() private void WatchPacFile()
{ {
if (watcher != null)
{
watcher.Dispose();
}
watcher = new FileSystemWatcher(Directory.GetCurrentDirectory());
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = PAC_FILE;
watcher.Changed += Watcher_Changed;
watcher.Created += Watcher_Changed;
watcher.Deleted += Watcher_Changed;
watcher.Renamed += Watcher_Changed;
watcher.EnableRaisingEvents = true;
if (PACFileWatcher != null)
{
PACFileWatcher.Dispose();
}
PACFileWatcher = new FileSystemWatcher(Directory.GetCurrentDirectory());
PACFileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
PACFileWatcher.Filter = PAC_FILE;
PACFileWatcher.Changed += PACFileWatcher_Changed;
PACFileWatcher.Created += PACFileWatcher_Changed;
PACFileWatcher.Deleted += PACFileWatcher_Changed;
PACFileWatcher.Renamed += PACFileWatcher_Changed;
PACFileWatcher.EnableRaisingEvents = true;
}
private void WatchUserRuleFile()
{
if (UserRuleFileWatcher != null)
{
UserRuleFileWatcher.Dispose();
}
UserRuleFileWatcher = new FileSystemWatcher(Directory.GetCurrentDirectory());
UserRuleFileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
UserRuleFileWatcher.Filter = USER_RULE_FILE;
UserRuleFileWatcher.Changed += UserRuleFileWatcher_Changed;
UserRuleFileWatcher.Created += UserRuleFileWatcher_Changed;
UserRuleFileWatcher.Deleted += UserRuleFileWatcher_Changed;
UserRuleFileWatcher.Renamed += UserRuleFileWatcher_Changed;
UserRuleFileWatcher.EnableRaisingEvents = true;
}
#region FileSystemWatcher.OnChanged()
// FileSystemWatcher Changed event is raised twice
// http://stackoverflow.com/questions/1764809/filesystemwatcher-changed-event-is-raised-twice
private static Hashtable fileChangedTime = new Hashtable();
private void PACFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
string path = e.FullPath.ToString();
string currentLastWriteTime = File.GetLastWriteTime(e.FullPath).ToString();
// if there is no path info stored yet or stored path has different time of write then the one now is inspected
if (!fileChangedTime.ContainsKey(path) || fileChangedTime[path].ToString() != currentLastWriteTime)
{
if (PACFileChanged != null)
{
Logging.Info($"Detected: PAC file '{e.Name}' was {e.ChangeType.ToString().ToLower()}.");
PACFileChanged(this, new EventArgs());
}
//lastly we update the last write time in the hashtable
fileChangedTime[path] = currentLastWriteTime;
}
} }
private void Watcher_Changed(object sender, FileSystemEventArgs e)
private void UserRuleFileWatcher_Changed(object sender, FileSystemEventArgs e)
{ {
if (PACFileChanged != null)
string path = e.FullPath.ToString();
string currentLastWriteTime = File.GetLastWriteTime(e.FullPath).ToString();
// if there is no path info stored yet or stored path has different time of write then the one now is inspected
if (!fileChangedTime.ContainsKey(path) || fileChangedTime[path].ToString() != currentLastWriteTime)
{ {
PACFileChanged(this, new EventArgs());
if (UserRuleFileChanged != null)
{
Logging.Info($"Detected: User Rule file '{e.Name}' was {e.ChangeType.ToString().ToLower()}.");
UserRuleFileChanged(this, new EventArgs());
}
//lastly we update the last write time in the hashtable
fileChangedTime[path] = currentLastWriteTime;
} }
} }
#endregion
private string GetPACAddress(byte[] requestBuf, int length, IPEndPoint localEndPoint, bool useSocks) private string GetPACAddress(byte[] requestBuf, int length, IPEndPoint localEndPoint, bool useSocks)
{ {
//try //try
@@ -204,7 +259,7 @@ Connection: Close
//} //}
//catch (Exception e) //catch (Exception e)
//{ //{
// Console.WriteLine(e);
// Logging.LogUsefulException(e);
//} //}
return (useSocks ? "SOCKS5 " : "PROXY ") + localEndPoint.Address + ":" + this._config.localPort + ";"; return (useSocks ? "SOCKS5 " : "PROXY ") + localEndPoint.Address + ":" + this._config.localPort + ";";
} }


+ 2
- 2
shadowsocks-csharp/Controller/Service/PolipoRunner.cs View File

@@ -56,7 +56,7 @@ namespace Shadowsocks.Controller
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e.ToString());
Logging.LogUsefulException(e);
} }
} }
string polipoConfig = Resources.privoxy_conf; string polipoConfig = Resources.privoxy_conf;
@@ -94,7 +94,7 @@ namespace Shadowsocks.Controller
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e.ToString());
Logging.LogUsefulException(e);
} }
_process = null; _process = null;
} }


+ 0
- 1
shadowsocks-csharp/Controller/Service/PortForwarder.cs View File

@@ -140,7 +140,6 @@ namespace Shadowsocks.Controller
} }
else else
{ {
//Console.WriteLine("bytesRead: " + bytesRead.ToString());
_local.Shutdown(SocketShutdown.Send); _local.Shutdown(SocketShutdown.Send);
_localShutdown = true; _localShutdown = true;
CheckClose(); CheckClose();


+ 8
- 10
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -49,7 +49,7 @@ namespace Shadowsocks.Controller
lock (this.Handlers) lock (this.Handlers)
{ {
this.Handlers.Add(handler); this.Handlers.Add(handler);
Logging.Debug($"connections: {Handlers.Count}");
Logging.Debug($"TCP connections: {Handlers.Count}");
DateTime now = DateTime.Now; DateTime now = DateTime.Now;
if (now - _lastSweepTime > TimeSpan.FromSeconds(1)) if (now - _lastSweepTime > TimeSpan.FromSeconds(1))
{ {
@@ -65,10 +65,10 @@ namespace Shadowsocks.Controller
} }
foreach (Handler handler1 in handlersToClose) foreach (Handler handler1 in handlersToClose)
{ {
Logging.Debug("Closing timed out connection");
Logging.Debug("Closing timed out TCP connection.");
handler1.Close(); handler1.Close();
} }
return true;
return true;
} }
} }
@@ -149,7 +149,7 @@ namespace Shadowsocks.Controller
{ {
lock (relay.Handlers) lock (relay.Handlers)
{ {
Logging.Debug($"connections: {relay.Handlers.Count}");
Logging.Debug($"TCP connections: {relay.Handlers.Count}");
relay.Handlers.Remove(this); relay.Handlers.Remove(this);
} }
lock (this) lock (this)
@@ -213,7 +213,7 @@ namespace Shadowsocks.Controller
{ {
// reject socks 4 // reject socks 4
response = new byte[] { 0, 91 }; response = new byte[] { 0, 91 };
Console.WriteLine("socks 5 protocol error");
Logging.Error("socks 5 protocol error");
} }
Logging.Debug($"======Send Local Port, size:" + response.Length); Logging.Debug($"======Send Local Port, size:" + response.Length);
connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null); connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null);
@@ -284,7 +284,7 @@ namespace Shadowsocks.Controller
} }
else else
{ {
Console.WriteLine("failed to recv data in handshakeReceive2Callback");
Logging.Error("failed to recv data in handshakeReceive2Callback");
this.Close(); this.Close();
} }
} }
@@ -431,7 +431,7 @@ namespace Shadowsocks.Controller
{ {
strategy.SetFailure(server); strategy.SetFailure(server);
} }
Console.WriteLine(String.Format("{0} timed out", server.FriendlyName()));
Logging.Info($"{server.FriendlyName()} timed out");
remote.Close(); remote.Close();
RetryConnect(); RetryConnect();
} }
@@ -470,8 +470,7 @@ namespace Shadowsocks.Controller
connected = true; connected = true;
//Console.WriteLine("Socket connected to {0}",
// remote.RemoteEndPoint.ToString());
Logging.Debug($"Socket connected to {remote.RemoteEndPoint}");
var latency = DateTime.Now - _startConnectTime; var latency = DateTime.Now - _startConnectTime;
IStrategy strategy = controller.GetCurrentStrategy(); IStrategy strategy = controller.GetCurrentStrategy();
@@ -556,7 +555,6 @@ namespace Shadowsocks.Controller
} }
else else
{ {
//Console.WriteLine("bytesRead: " + bytesRead.ToString());
connection.Shutdown(SocketShutdown.Send); connection.Shutdown(SocketShutdown.Send);
connectionShutdown = true; connectionShutdown = true;
CheckClose(); CheckClose();


+ 36
- 0
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -7,6 +7,8 @@ using System.Threading;
using System.Net.Sockets; using System.Net.Sockets;
using Shadowsocks.Controller.Strategy; using Shadowsocks.Controller.Strategy;
using System.Net; using System.Net;
using Shadowsocks.Util;
using Shadowsocks.Properties;
namespace Shadowsocks.Controller namespace Shadowsocks.Controller
{ {
@@ -314,6 +316,7 @@ namespace Shadowsocks.Controller
{ {
_pacServer = new PACServer(); _pacServer = new PACServer();
_pacServer.PACFileChanged += pacServer_PACFileChanged; _pacServer.PACFileChanged += pacServer_PACFileChanged;
_pacServer.UserRuleFileChanged += pacServer_UserRuleFileChanged;
} }
_pacServer.UpdateConfiguration(_config); _pacServer.UpdateConfiguration(_config);
if (gfwListUpdater == null) if (gfwListUpdater == null)
@@ -424,6 +427,39 @@ namespace Shadowsocks.Controller
UpdatePACFromGFWListError(this, e); UpdatePACFromGFWListError(this, e);
} }
private void pacServer_UserRuleFileChanged(object sender, EventArgs e)
{
// TODO: this is a dirty hack. (from code GListUpdater.http_DownloadStringCompleted())
if (!File.Exists(Utils.GetTempPath() + "\\gfwlist.txt"))
{
UpdatePACFromGFWList();
return;
}
List<string> lines = GFWListUpdater.ParseResult(File.ReadAllText(Utils.GetTempPath() + "\\gfwlist.txt"));
if (File.Exists(PACServer.USER_RULE_FILE))
{
string local = File.ReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8);
string[] rules = local.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string rule in rules)
{
if (rule.StartsWith("!") || rule.StartsWith("["))
continue;
lines.Add(rule);
}
}
string abpContent = Utils.UnGzip(Resources.abp_js);
abpContent = abpContent.Replace("__RULES__", SimpleJson.SimpleJson.SerializeObject(lines));
if (File.Exists(PACServer.PAC_FILE))
{
string original = File.ReadAllText(PACServer.PAC_FILE, Encoding.UTF8);
if (original == abpContent)
{
return;
}
}
File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8);
}
private void StartReleasingMemory() private void StartReleasingMemory()
{ {
_ramThread = new Thread(new ThreadStart(ReleaseMemory)); _ramThread = new Thread(new ThreadStart(ReleaseMemory));


+ 5
- 5
shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs View File

@@ -132,14 +132,14 @@ namespace Shadowsocks.Controller.Strategy
if (_currentServer == null || max.score - _currentServer.score > 200) if (_currentServer == null || max.score - _currentServer.score > 200)
{ {
_currentServer = max; _currentServer = max;
Console.WriteLine("HA switching to server: {0}", _currentServer.server.FriendlyName());
Logging.Info($"HA switching to server: {_currentServer.server.FriendlyName()}");
} }
} }
} }
public void UpdateLatency(Model.Server server, TimeSpan latency) public void UpdateLatency(Model.Server server, TimeSpan latency)
{ {
Logging.Debug(String.Format("latency: {0} {1}", server.FriendlyName(), latency));
Logging.Debug($"latency: {server.FriendlyName()} {latency}");
ServerStatus status; ServerStatus status;
if (_serverStatus.TryGetValue(server, out status)) if (_serverStatus.TryGetValue(server, out status))
@@ -151,7 +151,7 @@ namespace Shadowsocks.Controller.Strategy
public void UpdateLastRead(Model.Server server) public void UpdateLastRead(Model.Server server)
{ {
Logging.Debug(String.Format("last read: {0}", server.FriendlyName()));
Logging.Debug($"last read: {server.FriendlyName()}");
ServerStatus status; ServerStatus status;
if (_serverStatus.TryGetValue(server, out status)) if (_serverStatus.TryGetValue(server, out status))
@@ -162,7 +162,7 @@ namespace Shadowsocks.Controller.Strategy
public void UpdateLastWrite(Model.Server server) public void UpdateLastWrite(Model.Server server)
{ {
Logging.Debug(String.Format("last write: {0}", server.FriendlyName()));
Logging.Debug($"last write: {server.FriendlyName()}");
ServerStatus status; ServerStatus status;
if (_serverStatus.TryGetValue(server, out status)) if (_serverStatus.TryGetValue(server, out status))
@@ -173,7 +173,7 @@ namespace Shadowsocks.Controller.Strategy
public void SetFailure(Model.Server server) public void SetFailure(Model.Server server)
{ {
Logging.Debug(String.Format("failure: {0}", server.FriendlyName()));
Logging.Debug($"failure: {server.FriendlyName()}");
ServerStatus status; ServerStatus status;
if (_serverStatus.TryGetValue(server, out status)) if (_serverStatus.TryGetValue(server, out status))


+ 1
- 1
shadowsocks-csharp/Encryption/PolarSSL.cs View File

@@ -30,7 +30,7 @@ namespace Shadowsocks.Encryption
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e.ToString());
Logging.LogUsefulException(e);
} }
LoadLibrary(dllPath); LoadLibrary(dllPath);
} }


+ 1
- 1
shadowsocks-csharp/Encryption/Sodium.cs View File

@@ -26,7 +26,7 @@ namespace Shadowsocks.Encryption
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e.ToString());
Logging.LogUsefulException(e);
} }
LoadLibrary(dllPath); LoadLibrary(dllPath);
} }


+ 2
- 1
shadowsocks-csharp/Model/Configuration.cs View File

@@ -72,7 +72,7 @@ namespace Shadowsocks.Model
{ {
if (!(e is FileNotFoundException)) if (!(e is FileNotFoundException))
{ {
Console.WriteLine(e);
Logging.LogUsefulException(e);
} }
return new Configuration return new Configuration
{ {
@@ -167,6 +167,7 @@ namespace Shadowsocks.Model
} }
} }
// internal class
private class JsonSerializerStrategy : SimpleJson.PocoJsonSerializerStrategy private class JsonSerializerStrategy : SimpleJson.PocoJsonSerializerStrategy
{ {
// convert string to int // convert string to int


+ 31
- 8
shadowsocks-csharp/Model/LogViewerConfig.cs View File

@@ -1,5 +1,7 @@
using System;
using Shadowsocks.View;
using System;
using System.Drawing; using System.Drawing;
using System.Windows.Forms;
namespace Shadowsocks.Model namespace Shadowsocks.Model
{ {
@@ -13,16 +15,37 @@ namespace Shadowsocks.Model
public bool topMost; public bool topMost;
public bool wrapText; public bool wrapText;
public bool toolbarShown; public bool toolbarShown;
public int width;
public int height;
public int top;
public int left;
public LogViewerConfig() public LogViewerConfig()
{ {
this.fontName = "Consolas";
this.fontSize = 8;
this.bgColor = "black";
this.textColor = "white";
this.topMost = false;
this.wrapText = false;
this.toolbarShown = false;
fontName = "Consolas";
fontSize = 8;
bgColor = "black";
textColor = "white";
topMost = false;
wrapText = false;
toolbarShown = false;
width = 600;
height = 400;
left = GetBestLeft();
top = GetBestTop();
}
// Use GetBestTop() and GetBestLeft() to ensure the log viwer form can be always display IN screen.
public int GetBestLeft()
{
width = (width >= 400) ? width : 400; // set up the minimum size
return Screen.PrimaryScreen.WorkingArea.Width - width;
}
public int GetBestTop()
{
height = (height >= 200) ? height : 200; // set up the minimum size
return Screen.PrimaryScreen.WorkingArea.Height - height;
} }
public Font GetFont() public Font GetFont()


+ 5
- 2
shadowsocks-csharp/Util/Util.cs View File

@@ -7,6 +7,8 @@ using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using Shadowsocks.Controller;
namespace Shadowsocks.Util namespace Shadowsocks.Util
{ {
public class Utils public class Utils
@@ -19,9 +21,10 @@ namespace Shadowsocks.Util
try try
{ {
Directory.CreateDirectory(Application.StartupPath + "\\temp"); Directory.CreateDirectory(Application.StartupPath + "\\temp");
} catch (Exception e)
}
catch (Exception e)
{ {
Console.WriteLine(e);
Logging.LogUsefulException(e);
} }
// don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log // don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log
return Application.StartupPath + "\\temp"; return Application.StartupPath + "\\temp";


+ 7
- 6
shadowsocks-csharp/View/LogForm.Designer.cs View File

@@ -63,7 +63,7 @@
this.LogMessageTextBox.Name = "LogMessageTextBox"; this.LogMessageTextBox.Name = "LogMessageTextBox";
this.LogMessageTextBox.ReadOnly = true; this.LogMessageTextBox.ReadOnly = true;
this.LogMessageTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.LogMessageTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.LogMessageTextBox.Size = new System.Drawing.Size(584, 377);
this.LogMessageTextBox.Size = new System.Drawing.Size(378, 99);
this.LogMessageTextBox.TabIndex = 0; this.LogMessageTextBox.TabIndex = 0;
// //
// MainMenu // MainMenu
@@ -141,7 +141,7 @@
// //
// TopMostCheckBox // TopMostCheckBox
// //
this.TopMostCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
this.TopMostCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left))); | System.Windows.Forms.AnchorStyles.Left)));
this.TopMostCheckBox.AutoSize = true; this.TopMostCheckBox.AutoSize = true;
this.TopMostCheckBox.Location = new System.Drawing.Point(249, 3); this.TopMostCheckBox.Location = new System.Drawing.Point(249, 3);
@@ -176,7 +176,7 @@
// //
// WrapTextCheckBox // WrapTextCheckBox
// //
this.WrapTextCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
this.WrapTextCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left))); | System.Windows.Forms.AnchorStyles.Left)));
this.WrapTextCheckBox.AutoSize = true; this.WrapTextCheckBox.AutoSize = true;
this.WrapTextCheckBox.Location = new System.Drawing.Point(165, 3); this.WrapTextCheckBox.Location = new System.Drawing.Point(165, 3);
@@ -199,7 +199,7 @@
this.tableLayoutPanel1.RowCount = 2; this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(590, 418);
this.tableLayoutPanel1.Size = new System.Drawing.Size(384, 140);
this.tableLayoutPanel1.TabIndex = 2; this.tableLayoutPanel1.TabIndex = 2;
// //
// ToolbarFlowLayoutPanel // ToolbarFlowLayoutPanel
@@ -212,16 +212,17 @@
this.ToolbarFlowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.ToolbarFlowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ToolbarFlowLayoutPanel.Location = new System.Drawing.Point(3, 3); this.ToolbarFlowLayoutPanel.Location = new System.Drawing.Point(3, 3);
this.ToolbarFlowLayoutPanel.Name = "ToolbarFlowLayoutPanel"; this.ToolbarFlowLayoutPanel.Name = "ToolbarFlowLayoutPanel";
this.ToolbarFlowLayoutPanel.Size = new System.Drawing.Size(584, 29);
this.ToolbarFlowLayoutPanel.Size = new System.Drawing.Size(378, 29);
this.ToolbarFlowLayoutPanel.TabIndex = 2; this.ToolbarFlowLayoutPanel.TabIndex = 2;
// //
// LogForm // LogForm
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 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(590, 418);
this.ClientSize = new System.Drawing.Size(384, 140);
this.Controls.Add(this.tableLayoutPanel1); this.Controls.Add(this.tableLayoutPanel1);
this.Menu = this.MainMenu; this.Menu = this.MainMenu;
this.MinimumSize = new System.Drawing.Size(400, 200);
this.Name = "LogForm"; this.Name = "LogForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Log Viewer"; this.Text = "Log Viewer";


+ 30
- 14
shadowsocks-csharp/View/LogForm.cs View File

@@ -27,17 +27,21 @@ namespace Shadowsocks.View
this.controller = controller; this.controller = controller;
this.filename = filename; this.filename = filename;
InitializeComponent(); InitializeComponent();
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
LogViewerConfig config = controller.GetConfigurationCopy().logViewer; LogViewerConfig config = controller.GetConfigurationCopy().logViewer;
if (config == null) if (config == null)
{
config = new LogViewerConfig(); config = new LogViewerConfig();
topMostTrigger = config.topMost;
wrapTextTrigger = config.wrapText;
toolbarTrigger = config.toolbarShown;
LogMessageTextBox.BackColor = config.GetBackgroundColor();
LogMessageTextBox.ForeColor = config.GetTextColor();
LogMessageTextBox.Font = config.GetFont();
}
else {
topMostTrigger = config.topMost;
wrapTextTrigger = config.wrapText;
toolbarTrigger = config.toolbarShown;
LogMessageTextBox.BackColor = config.GetBackgroundColor();
LogMessageTextBox.ForeColor = config.GetTextColor();
LogMessageTextBox.Font = config.GetFont();
}
UpdateTexts(); UpdateTexts();
} }
@@ -57,7 +61,7 @@ namespace Shadowsocks.View
WrapTextMenuItem.Text = I18N.GetString("&Wrap Text"); WrapTextMenuItem.Text = I18N.GetString("&Wrap Text");
TopMostMenuItem.Text = I18N.GetString("&Top Most"); TopMostMenuItem.Text = I18N.GetString("&Top Most");
ShowToolbarMenuItem.Text = I18N.GetString("&Show Toolbar"); ShowToolbarMenuItem.Text = I18N.GetString("&Show Toolbar");
this.Text = I18N.GetString("Log Viewer");
Text = I18N.GetString("Log Viewer");
} }
private void Timer_Tick(object sender, EventArgs e) private void Timer_Tick(object sender, EventArgs e)
@@ -118,8 +122,16 @@ namespace Shadowsocks.View
timer.Tick += Timer_Tick; timer.Tick += Timer_Tick;
timer.Start(); timer.Start();
LogViewerConfig config = controller.GetConfigurationCopy().logViewer;
if (config == null)
config = new LogViewerConfig();
Height = config.height;
Width = config.width;
Top = config.GetBestTop();
Left = config.GetBestLeft();
topMostTriggerLock = true; topMostTriggerLock = true;
this.TopMost = TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger;
TopMost = TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger;
topMostTriggerLock = false; topMostTriggerLock = false;
wrapTextTriggerLock = true; wrapTextTriggerLock = true;
@@ -141,19 +153,23 @@ namespace Shadowsocks.View
config.SetFont(LogMessageTextBox.Font); config.SetFont(LogMessageTextBox.Font);
config.SetBackgroundColor(LogMessageTextBox.BackColor); config.SetBackgroundColor(LogMessageTextBox.BackColor);
config.SetTextColor(LogMessageTextBox.ForeColor); config.SetTextColor(LogMessageTextBox.ForeColor);
config.top = Top;
config.left = Left;
config.height = Height;
config.width = Width;
controller.SaveLogViewerConfig(config); controller.SaveLogViewerConfig(config);
} }
private void OpenLocationMenuItem_Click(object sender, EventArgs e) private void OpenLocationMenuItem_Click(object sender, EventArgs e)
{ {
string argument = "/select, \"" + filename + "\""; string argument = "/select, \"" + filename + "\"";
Console.WriteLine(argument);
Logging.Debug(argument);
System.Diagnostics.Process.Start("explorer.exe", argument); System.Diagnostics.Process.Start("explorer.exe", argument);
} }
private void ExitMenuItem_Click(object sender, EventArgs e) private void ExitMenuItem_Click(object sender, EventArgs e)
{ {
this.Close();
Close();
} }
private void LogForm_Shown(object sender, EventArgs e) private void LogForm_Shown(object sender, EventArgs e)
@@ -208,7 +224,7 @@ namespace Shadowsocks.View
} }
#endregion #endregion
#region Trigger the log messages wrapable, or not.
#region Trigger the log messages to wrapable, or not.
bool wrapTextTrigger = false; bool wrapTextTrigger = false;
bool wrapTextTriggerLock = false; bool wrapTextTriggerLock = false;
@@ -241,7 +257,7 @@ namespace Shadowsocks.View
} }
#endregion #endregion
#region Trigger this window top most, or not.
#region Trigger the window to top most, or not.
bool topMostTrigger = false; bool topMostTrigger = false;
bool topMostTriggerLock = false; bool topMostTriggerLock = false;
@@ -250,7 +266,7 @@ namespace Shadowsocks.View
topMostTriggerLock = true; topMostTriggerLock = true;
topMostTrigger = !topMostTrigger; topMostTrigger = !topMostTrigger;
this.TopMost = topMostTrigger;
TopMost = topMostTrigger;
TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger; TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger;
topMostTriggerLock = false; topMostTriggerLock = false;


+ 37
- 6
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -44,6 +44,8 @@ namespace Shadowsocks.View
private MenuItem editOnlinePACItem; private MenuItem editOnlinePACItem;
private MenuItem autoCheckUpdatesToggleItem; private MenuItem autoCheckUpdatesToggleItem;
private ConfigForm configForm; private ConfigForm configForm;
private List<LogForm> logForms = new List<LogForm>();
private bool logFormsVisible = false;
private string _urlToOpen; private string _urlToOpen;
public MenuViewController(ShadowsocksController controller) public MenuViewController(ShadowsocksController controller)
@@ -289,7 +291,6 @@ namespace Shadowsocks.View
} }
} }
private void LoadCurrentConfiguration() private void LoadCurrentConfiguration()
{ {
Configuration config = controller.GetConfigurationCopy(); Configuration config = controller.GetConfigurationCopy();
@@ -357,6 +358,32 @@ namespace Shadowsocks.View
} }
} }
private void ShowLogForms()
{
if (logForms.Count == 0)
{
LogForm f = new LogForm(controller, Logging.LogFile);
f.Show();
f.FormClosed += logForm_FormClosed;
logForms.Add(f);
logFormsVisible = true;
}
else
{
logFormsVisible = !logFormsVisible;
foreach (LogForm f in logForms)
{
f.Visible = logFormsVisible;
}
}
}
void logForm_FormClosed(object sender, FormClosedEventArgs e)
{
logForms.Remove((LogForm)sender);
}
void configForm_FormClosed(object sender, FormClosedEventArgs e) void configForm_FormClosed(object sender, FormClosedEventArgs e)
{ {
configForm = null; configForm = null;
@@ -451,11 +478,13 @@ namespace Shadowsocks.View
private void ShowLogItem_Click(object sender, EventArgs e) private void ShowLogItem_Click(object sender, EventArgs e)
{ {
string argument = Logging.LogFile;
LogForm f = new LogForm(controller, Logging.LogFile);
f.Show();
f.FormClosed += logForm_FormClosed;
new LogForm(controller, argument).Show();
logForms.Add(f);
} }
private void StatisticsConfigItem_Click(object sender, EventArgs e) private void StatisticsConfigItem_Click(object sender, EventArgs e)
{ {
StatisticsStrategyConfigurationForm form = new StatisticsStrategyConfigurationForm(controller); StatisticsStrategyConfigurationForm form = new StatisticsStrategyConfigurationForm(controller);
@@ -564,9 +593,11 @@ 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"));
} }
} }


+ 7
- 4
test/packages.config View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" />
<package id="System.Net.Http" version="2.0.20710.0" targetFramework="net45" />
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
<package id="System.Net.Http" version="4.0.0" targetFramework="net45" />
</packages> </packages>

+ 30
- 0
test/test.csproj View File

@@ -17,6 +17,8 @@
<IsCodedUITest>False</IsCodedUITest> <IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType> <TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<OutputPath>bin\x86\Debug\</OutputPath> <OutputPath>bin\x86\Debug\</OutputPath>
@@ -30,8 +32,29 @@
<StartupObject /> <StartupObject />
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http.WebRequest" /> <Reference Include="System.Net.Http.WebRequest" />
</ItemGroup> </ItemGroup>
<Choose> <Choose>
@@ -79,6 +102,13 @@
</Choose> </Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\shadowsocks-csharp\3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\shadowsocks-csharp\3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\shadowsocks-csharp\3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\shadowsocks-csharp\3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">


Loading…
Cancel
Save