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);
}
public static void Debug(object o)
{
#if DEBUG
Console.WriteLine("[D] " + o);
#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 ping = new Ping();
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
try
@@ -146,7 +145,7 @@ namespace Shadowsocks.Controller
}
catch (Exception e)
{
Console.WriteLine($"An exception occured when eveluating {server.FriendlyName()}");
Logging.Error($"An exception occured while eveluating {server.FriendlyName()}");
Logging.LogUsefulException(e);
}
}


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

@@ -38,6 +38,7 @@ namespace Shadowsocks.Controller
{
try
{
File.WriteAllText(Utils.GetTempPath() + "\\gfwlist.txt", e.Result, Encoding.UTF8);
List<string> lines = ParseResult(e.Result);
if (File.Exists(USER_RULE_FILE))
{
@@ -92,7 +93,7 @@ namespace Shadowsocks.Controller
http.DownloadStringAsync(new Uri(GFWLIST_URL));
}
public List<string> ParseResult(string response)
public static List<string> ParseResult(string response)
{
byte[] bytes = Convert.FromBase64String(response);
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);
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Shadowsocks started");
Logging.Info("Shadowsocks started");
_tcpSocket.BeginAccept(
new AsyncCallback(AcceptCallback),
_tcpSocket);
@@ -163,7 +163,7 @@ namespace Shadowsocks.Controller
}
catch (Exception e)
{
Console.WriteLine(e);
Logging.LogUsefulException(e);
}
finally
{
@@ -208,7 +208,7 @@ namespace Shadowsocks.Controller
}
catch (Exception e)
{
Console.WriteLine(e);
Logging.LogUsefulException(e);
conn.Close();
}
}


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

@@ -2,6 +2,7 @@
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -15,19 +16,20 @@ namespace Shadowsocks.Controller
class PACServer : Listener.Service
{
public static string PAC_FILE = "pac.txt";
public static string USER_RULE_FILE = "user-rule.txt";
public static string USER_ABP_FILE = "abp.txt";
FileSystemWatcher watcher;
FileSystemWatcher PACFileWatcher;
FileSystemWatcher UserRuleFileWatcher;
private Configuration _config;
public event EventHandler PACFileChanged;
public event EventHandler UserRuleFileChanged;
public PACServer()
{
this.WatchPacFile();
this.WatchUserRuleFile();
}
public void UpdateConfiguration(Configuration config)
@@ -151,7 +153,7 @@ Connection: Close
}
catch (Exception e)
{
Console.WriteLine(e);
Logging.LogUsefulException(e);
socket.Close();
}
}
@@ -169,28 +171,81 @@ Connection: Close
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)
{
//try
@@ -204,7 +259,7 @@ Connection: Close
//}
//catch (Exception e)
//{
// Console.WriteLine(e);
// Logging.LogUsefulException(e);
//}
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)
{
Console.WriteLine(e.ToString());
Logging.LogUsefulException(e);
}
}
string polipoConfig = Resources.privoxy_conf;
@@ -94,7 +94,7 @@ namespace Shadowsocks.Controller
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Logging.LogUsefulException(e);
}
_process = null;
}


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

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


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

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


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

@@ -7,6 +7,8 @@ using System.Threading;
using System.Net.Sockets;
using Shadowsocks.Controller.Strategy;
using System.Net;
using Shadowsocks.Util;
using Shadowsocks.Properties;
namespace Shadowsocks.Controller
{
@@ -314,6 +316,7 @@ namespace Shadowsocks.Controller
{
_pacServer = new PACServer();
_pacServer.PACFileChanged += pacServer_PACFileChanged;
_pacServer.UserRuleFileChanged += pacServer_UserRuleFileChanged;
}
_pacServer.UpdateConfiguration(_config);
if (gfwListUpdater == null)
@@ -424,6 +427,39 @@ namespace Shadowsocks.Controller
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()
{
_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)
{
_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)
{
Logging.Debug(String.Format("latency: {0} {1}", server.FriendlyName(), latency));
Logging.Debug($"latency: {server.FriendlyName()} {latency}");
ServerStatus status;
if (_serverStatus.TryGetValue(server, out status))
@@ -151,7 +151,7 @@ namespace Shadowsocks.Controller.Strategy
public void UpdateLastRead(Model.Server server)
{
Logging.Debug(String.Format("last read: {0}", server.FriendlyName()));
Logging.Debug($"last read: {server.FriendlyName()}");
ServerStatus status;
if (_serverStatus.TryGetValue(server, out status))
@@ -162,7 +162,7 @@ namespace Shadowsocks.Controller.Strategy
public void UpdateLastWrite(Model.Server server)
{
Logging.Debug(String.Format("last write: {0}", server.FriendlyName()));
Logging.Debug($"last write: {server.FriendlyName()}");
ServerStatus status;
if (_serverStatus.TryGetValue(server, out status))
@@ -173,7 +173,7 @@ namespace Shadowsocks.Controller.Strategy
public void SetFailure(Model.Server server)
{
Logging.Debug(String.Format("failure: {0}", server.FriendlyName()));
Logging.Debug($"failure: {server.FriendlyName()}");
ServerStatus 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)
{
Console.WriteLine(e.ToString());
Logging.LogUsefulException(e);
}
LoadLibrary(dllPath);
}


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

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


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

@@ -72,7 +72,7 @@ namespace Shadowsocks.Model
{
if (!(e is FileNotFoundException))
{
Console.WriteLine(e);
Logging.LogUsefulException(e);
}
return new Configuration
{
@@ -167,6 +167,7 @@ namespace Shadowsocks.Model
}
}
// internal class
private class JsonSerializerStrategy : SimpleJson.PocoJsonSerializerStrategy
{
// 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.Windows.Forms;
namespace Shadowsocks.Model
{
@@ -13,16 +15,37 @@ namespace Shadowsocks.Model
public bool topMost;
public bool wrapText;
public bool toolbarShown;
public int width;
public int height;
public int top;
public int left;
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()


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

@@ -7,6 +7,8 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Shadowsocks.Controller;
namespace Shadowsocks.Util
{
public class Utils
@@ -19,9 +21,10 @@ namespace Shadowsocks.Util
try
{
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
return Application.StartupPath + "\\temp";


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

@@ -63,7 +63,7 @@
this.LogMessageTextBox.Name = "LogMessageTextBox";
this.LogMessageTextBox.ReadOnly = true;
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;
//
// MainMenu
@@ -141,7 +141,7 @@
//
// 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)));
this.TopMostCheckBox.AutoSize = true;
this.TopMostCheckBox.Location = new System.Drawing.Point(249, 3);
@@ -176,7 +176,7 @@
//
// 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)));
this.WrapTextCheckBox.AutoSize = true;
this.WrapTextCheckBox.Location = new System.Drawing.Point(165, 3);
@@ -199,7 +199,7 @@
this.tableLayoutPanel1.RowCount = 2;
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;
//
// ToolbarFlowLayoutPanel
@@ -212,16 +212,17 @@
this.ToolbarFlowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ToolbarFlowLayoutPanel.Location = new System.Drawing.Point(3, 3);
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;
//
// LogForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
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.Menu = this.MainMenu;
this.MinimumSize = new System.Drawing.Size(400, 200);
this.Name = "LogForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Log Viewer";


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

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


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

@@ -44,6 +44,8 @@ namespace Shadowsocks.View
private MenuItem editOnlinePACItem;
private MenuItem autoCheckUpdatesToggleItem;
private ConfigForm configForm;
private List<LogForm> logForms = new List<LogForm>();
private bool logFormsVisible = false;
private string _urlToOpen;
public MenuViewController(ShadowsocksController controller)
@@ -289,7 +291,6 @@ namespace Shadowsocks.View
}
}
private void LoadCurrentConfiguration()
{
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)
{
configForm = null;
@@ -451,11 +478,13 @@ namespace Shadowsocks.View
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)
{
StatisticsStrategyConfigurationForm form = new StatisticsStrategyConfigurationForm(controller);
@@ -564,9 +593,11 @@ namespace Shadowsocks.View
Process.Start(_urlToOpen);
}
private void AutoStartupItem_Click(object sender, EventArgs e) {
private void AutoStartupItem_Click(object sender, EventArgs e)
{
AutoStartupItem.Checked = !AutoStartupItem.Checked;
if (!AutoStartup.Set(AutoStartupItem.Checked)) {
if (!AutoStartup.Set(AutoStartupItem.Checked))
{
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>

+ 30
- 0
test/test.csproj View File

@@ -17,6 +17,8 @@
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<OutputPath>bin\x86\Debug\</OutputPath>
@@ -30,8 +32,29 @@
<StartupObject />
</PropertyGroup>
<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.Net" />
<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" />
</ItemGroup>
<Choose>
@@ -79,6 +102,13 @@
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.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.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">


Loading…
Cancel
Save