# 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.cstags/3.0
@@ -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 | |||
} | |||
@@ -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) | |||
{ | |||
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 + ";"; | |||
} | |||
@@ -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"; | |||
@@ -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"> | |||