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
This commit is contained in:
@@ -32,11 +32,20 @@ namespace Shadowsocks.Controller
|
||||
}
|
||||
}
|
||||
|
||||
public static void Error(object o)
|
||||
{
|
||||
Console.WriteLine("[E] "+ o);
|
||||
}
|
||||
|
||||
public static void Info(object o)
|
||||
{
|
||||
Console.WriteLine(o);
|
||||
}
|
||||
|
||||
public static void Debug(object o)
|
||||
{
|
||||
|
||||
#if DEBUG
|
||||
Console.WriteLine(o);
|
||||
Console.WriteLine("[D] " + o);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
if (PACFileWatcher != null)
|
||||
{
|
||||
watcher.Dispose();
|
||||
PACFileWatcher.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;
|
||||
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 Watcher_Changed(object sender, FileSystemEventArgs e)
|
||||
private void WatchUserRuleFile()
|
||||
{
|
||||
if (PACFileChanged != null)
|
||||
if (UserRuleFileWatcher != null)
|
||||
{
|
||||
PACFileChanged(this, new EventArgs());
|
||||
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 UserRuleFileWatcher_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 (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 + ";";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,6 @@ namespace Shadowsocks.Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
//Console.WriteLine("bytesRead: " + bytesRead.ToString());
|
||||
_local.Shutdown(SocketShutdown.Send);
|
||||
_localShutdown = true;
|
||||
CheckClose();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Shadowsocks.Encryption
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
Logging.LogUsefulException(e);
|
||||
}
|
||||
LoadLibrary(dllPath);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Shadowsocks.Encryption
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
Logging.LogUsefulException(e);
|
||||
}
|
||||
LoadLibrary(dllPath);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user