diff --git a/shadowsocks-csharp/Controller/FileManager.cs b/shadowsocks-csharp/Controller/FileManager.cs index d7db51c1..ef30470d 100755 --- a/shadowsocks-csharp/Controller/FileManager.cs +++ b/shadowsocks-csharp/Controller/FileManager.cs @@ -1,4 +1,5 @@ -using System; +using NLog; +using System; using System.IO; using System.IO.Compression; using System.Text; @@ -7,6 +8,8 @@ namespace Shadowsocks.Controller { public static class FileManager { + private static Logger logger = LogManager.GetCurrentClassLogger(); + public static bool ByteArrayToFile(string fileName, byte[] content) { try @@ -17,7 +20,7 @@ namespace Shadowsocks.Controller } catch (Exception ex) { - Logging.Error(ex); + logger.Error(ex); } return false; } @@ -57,7 +60,7 @@ namespace Shadowsocks.Controller } catch (Exception ex) { - Logging.Error(ex); + logger.Error(ex); throw ex; } } diff --git a/shadowsocks-csharp/Controller/HotkeyReg.cs b/shadowsocks-csharp/Controller/HotkeyReg.cs index 5482ec6d..90a3dee9 100644 --- a/shadowsocks-csharp/Controller/HotkeyReg.cs +++ b/shadowsocks-csharp/Controller/HotkeyReg.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Windows.Forms; - +using NLog; using Shadowsocks.Controller.Hotkeys; using Shadowsocks.Model; @@ -9,6 +9,7 @@ namespace Shadowsocks.Controller { static class HotkeyReg { + private static Logger logger = LogManager.GetCurrentClassLogger(); public static void RegAllHotkeys() { var hotkeyConfig = Configuration.Load().hotkey; @@ -60,7 +61,7 @@ namespace Shadowsocks.Controller var hotkey = HotKeys.Str2HotKey(hotkeyStr); if (hotkey == null) { - Logging.Error($"Cannot parse hotkey: {hotkeyStr}"); + logger.Error($"Cannot parse hotkey: {hotkeyStr}"); onComplete?.Invoke(RegResult.ParseError); return false; } diff --git a/shadowsocks-csharp/Controller/I18N.cs b/shadowsocks-csharp/Controller/I18N.cs index 7102b79a..eb948c39 100755 --- a/shadowsocks-csharp/Controller/I18N.cs +++ b/shadowsocks-csharp/Controller/I18N.cs @@ -1,4 +1,5 @@ using Microsoft.VisualBasic.FileIO; +using NLog; using Shadowsocks.Properties; using Shadowsocks.Util; using System.Collections.Generic; @@ -9,9 +10,10 @@ using System.Windows.Forms; namespace Shadowsocks.Controller { - public static class I18N { + private static Logger logger = LogManager.GetCurrentClassLogger(); + public const string I18N_FILE = "i18n.csv"; private static Dictionary _strings = new Dictionary(); @@ -47,12 +49,12 @@ namespace Shadowsocks.Controller } if (targetIndex != -1 && enIndex != targetIndex) { - Logging.Info($"Using {localeNames[targetIndex]} translation for {locale}"); + logger.Info($"Using {localeNames[targetIndex]} translation for {locale}"); } else { // Still not found, exit - Logging.Info($"Translation for {locale} not found"); + logger.Info($"Translation for {locale} not found"); return; } } @@ -85,10 +87,10 @@ namespace Shadowsocks.Controller } else { - Logging.Info("Using external translation"); + logger.Info("Using external translation"); i18n = File.ReadAllText(I18N_FILE, Encoding.UTF8); } - Logging.Info("Current language is: " + locale); + logger.Info("Current language is: " + locale); Init(i18n, locale); } diff --git a/shadowsocks-csharp/Controller/LoggerExtension.cs b/shadowsocks-csharp/Controller/LoggerExtension.cs new file mode 100644 index 00000000..bd9b5925 --- /dev/null +++ b/shadowsocks-csharp/Controller/LoggerExtension.cs @@ -0,0 +1,119 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Net.Sockets; +using System.Net; +using System.Diagnostics; +using System.Text; +using Shadowsocks.Util.SystemProxy; + +namespace NLog +{ + public static class LoggerExtension + { + public static void Dump(this Logger logger, string tag, byte[] arr, int length) + { + if (logger.IsTraceEnabled) + { + var sb = new StringBuilder($"{Environment.NewLine}{tag}: "); + for (int i = 0; i < length - 1; i++) + { + sb.Append($"0x{arr[i]:X2}, "); + } + sb.Append($"0x{arr[length - 1]:X2}"); + sb.Append(Environment.NewLine); + logger.Trace(sb.ToString()); + } + } + + public static void Debug(this Logger logger, EndPoint local, EndPoint remote, int len, string header = null, string tailer = null) + { + if (logger.IsDebugEnabled) + { + if (header == null && tailer == null) + logger.Debug($"{local} => {remote} (size={len})"); + else if (header == null && tailer != null) + logger.Debug($"{local} => {remote} (size={len}), {tailer}"); + else if (header != null && tailer == null) + logger.Debug($"{header}: {local} => {remote} (size={len})"); + else + logger.Debug($"{header}: {local} => {remote} (size={len}), {tailer}"); + } + } + + public static void Debug(this Logger logger, Socket sock, int len, string header = null, string tailer = null) + { + if (logger.IsDebugEnabled) + { + logger.Debug(sock.LocalEndPoint, sock.RemoteEndPoint, len, header, tailer); + } + } + + public static void LogUsefulException(this Logger logger, Exception e) + { + // just log useful exceptions, not all of them + if (e is SocketException) + { + SocketException se = (SocketException)e; + if (se.SocketErrorCode == SocketError.ConnectionAborted) + { + // closed by browser when sending + // normally happens when download is canceled or a tab is closed before page is loaded + } + else if (se.SocketErrorCode == SocketError.ConnectionReset) + { + // received rst + } + else if (se.SocketErrorCode == SocketError.NotConnected) + { + // The application tried to send or receive data, and the System.Net.Sockets.Socket is not connected. + } + else if (se.SocketErrorCode == SocketError.HostUnreachable) + { + // There is no network route to the specified host. + } + else if (se.SocketErrorCode == SocketError.TimedOut) + { + // The connection attempt timed out, or the connected host has failed to respond. + } + else + { + logger.Warn(e); + } + } + else if (e is ObjectDisposedException) + { + } + else if (e is Win32Exception) + { + var ex = (Win32Exception)e; + + // Win32Exception (0x80004005): A 32 bit processes cannot access modules of a 64 bit process. + if ((uint)ex.ErrorCode != 0x80004005) + { + logger.Warn(e); + } + } + else if (e is ProxyException) + { + var ex = (ProxyException)e; + switch (ex.Type) + { + case ProxyExceptionType.FailToRun: + case ProxyExceptionType.QueryReturnMalformed: + case ProxyExceptionType.SysproxyExitError: + logger.Error($"sysproxy - {ex.Type.ToString()}:{ex.Message}"); + break; + case ProxyExceptionType.QueryReturnEmpty: + case ProxyExceptionType.Unspecific: + logger.Error($"sysproxy - {ex.Type.ToString()}"); + break; + } + } + else + { + logger.Warn(e); + } + } + } +} diff --git a/shadowsocks-csharp/Controller/Logging.cs b/shadowsocks-csharp/Controller/Logging.cs deleted file mode 100755 index 1ea6f276..00000000 --- a/shadowsocks-csharp/Controller/Logging.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System; -using System.ComponentModel; -using System.IO; -using System.Net.Sockets; -using System.Net; -using System.Diagnostics; -using System.Text; -using Shadowsocks.Util; -using Shadowsocks.Util.SystemProxy; - -namespace Shadowsocks.Controller -{ - public class Logging - { - public static string LogFilePath; - - private static FileStream _fs; - private static StreamWriterWithTimestamp _sw; - - public static bool OpenLogFile() - { - try - { - LogFilePath = Utils.GetTempPath("shadowsocks.log"); - - _fs = new FileStream(LogFilePath, FileMode.Append); - _sw = new StreamWriterWithTimestamp(_fs); - _sw.AutoFlush = true; - Console.SetOut(_sw); - Console.SetError(_sw); - - return true; - } - catch (IOException e) - { - Console.WriteLine(e.ToString()); - return false; - } - } - - private static void WriteToLogFile(object o) - { - try { - Console.WriteLine(o); - } catch(ObjectDisposedException) { - } - } - - public static void Error(object o) - { - WriteToLogFile("[E] " + o); - } - - public static void Info(object o) - { - WriteToLogFile(o); - } - - public static void Clear() { - _sw.Close(); - _sw.Dispose(); - _fs.Close(); - _fs.Dispose(); - File.Delete(LogFilePath); - OpenLogFile(); - } - - [Conditional("DEBUG")] - public static void Debug(object o) - { - WriteToLogFile("[D] " + o); - } - - [Conditional("DEBUG")] - public static void Dump(string tag, byte[] arr, int length) - { - var sb = new StringBuilder($"{Environment.NewLine}{tag}: "); - for (int i = 0; i < length - 1; i++) { - sb.Append($"0x{arr[i]:X2}, "); - } - sb.Append($"0x{arr[length - 1]:X2}"); - sb.Append(Environment.NewLine); - Debug(sb.ToString()); - } - - [Conditional("DEBUG")] - public static void Debug(EndPoint local, EndPoint remote, int len, string header = null, string tailer = null) - { - if (header == null && tailer == null) - Debug($"{local} => {remote} (size={len})"); - else if (header == null && tailer != null) - Debug($"{local} => {remote} (size={len}), {tailer}"); - else if (header != null && tailer == null) - Debug($"{header}: {local} => {remote} (size={len})"); - else - Debug($"{header}: {local} => {remote} (size={len}), {tailer}"); - } - - [Conditional("DEBUG")] - public static void Debug(Socket sock, int len, string header = null, string tailer = null) - { - Debug(sock.LocalEndPoint, sock.RemoteEndPoint, len, header, tailer); - } - - public static void LogUsefulException(Exception e) - { - // just log useful exceptions, not all of them - if (e is SocketException) - { - SocketException se = (SocketException)e; - if (se.SocketErrorCode == SocketError.ConnectionAborted) - { - // closed by browser when sending - // normally happens when download is canceled or a tab is closed before page is loaded - } - else if (se.SocketErrorCode == SocketError.ConnectionReset) - { - // received rst - } - else if (se.SocketErrorCode == SocketError.NotConnected) - { - // The application tried to send or receive data, and the System.Net.Sockets.Socket is not connected. - } - else if (se.SocketErrorCode == SocketError.HostUnreachable) - { - // There is no network route to the specified host. - } - else if (se.SocketErrorCode == SocketError.TimedOut) - { - // The connection attempt timed out, or the connected host has failed to respond. - } - else - { - Info(e); - } - } - else if (e is ObjectDisposedException) - { - } - else if (e is Win32Exception) - { - var ex = (Win32Exception) e; - - // Win32Exception (0x80004005): A 32 bit processes cannot access modules of a 64 bit process. - if ((uint) ex.ErrorCode != 0x80004005) - { - Info(e); - } - } - else if (e is ProxyException) - { - var ex = (ProxyException)e; - switch (ex.Type) - { - case ProxyExceptionType.FailToRun: - case ProxyExceptionType.QueryReturnMalformed: - case ProxyExceptionType.SysproxyExitError: - Error($"sysproxy - {ex.Type.ToString()}:{ex.Message}"); - break; - case ProxyExceptionType.QueryReturnEmpty: - case ProxyExceptionType.Unspecific: - Error($"sysproxy - {ex.Type.ToString()}"); - break; - } - - - } - else - { - Info(e); - } - } - } - - // Simply extended System.IO.StreamWriter for adding timestamp workaround - public class StreamWriterWithTimestamp : StreamWriter - { - public StreamWriterWithTimestamp(Stream stream) : base(stream) - { - } - - private string GetTimestamp() - { - return "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] "; - } - - public override void WriteLine(string value) - { - base.WriteLine(GetTimestamp() + value); - } - - public override void Write(string value) - { - base.Write(GetTimestamp() + value); - } - } - -} diff --git a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs index 7cbeb743..5d11e1d8 100644 --- a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs +++ b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs @@ -9,6 +9,7 @@ using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; +using NLog; using Shadowsocks.Model; using Shadowsocks.Util; @@ -18,6 +19,8 @@ namespace Shadowsocks.Controller public sealed class AvailabilityStatistics : IDisposable { + private static Logger logger = LogManager.GetCurrentClassLogger(); + public const string DateTimePattern = "yyyy-MM-dd HH:mm:ss"; private const string StatisticsFilesName = "shadowsocks.availability.json"; public static string AvailabilityStatisticsFile; @@ -111,7 +114,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } @@ -155,7 +158,7 @@ namespace Shadowsocks.Controller inR.Add(inboundSpeed); outR.Add(outboundSpeed); - Logging.Debug( + logger.Debug( $"{id}: current/max inbound {inboundSpeed}/{inR.Max()} KiB/s, current/max outbound {outboundSpeed}/{outR.Max()} KiB/s"); } } @@ -213,7 +216,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.Debug("config changed asynchrously, just ignore this server"); + logger.Debug("config changed asynchrously, just ignore this server"); } } @@ -235,7 +238,7 @@ namespace Shadowsocks.Controller { AppendRecord(server.Identifier(), record); } - Logging.Debug($"Ping {server.FriendlyName()} {e.RoundtripTime.Count} times, {(100 - record.PackageLoss * 100)}% packages loss, min {record.MinResponse} ms, max {record.MaxResponse} ms, avg {record.AverageResponse} ms"); + logger.Debug($"Ping {server.FriendlyName()} {e.RoundtripTime.Count} times, {(100 - record.PackageLoss * 100)}% packages loss, min {record.MinResponse} ms, max {record.MaxResponse} ms, avg {record.AverageResponse} ms"); if (Interlocked.Decrement(ref state.counter) == 0) { Save(); @@ -260,13 +263,13 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } private void Save() { - Logging.Debug($"save statistics to {AvailabilityStatisticsFile}"); + logger.Debug($"save statistics to {AvailabilityStatisticsFile}"); if (RawStatistics.Count == 0) { return; @@ -283,7 +286,7 @@ namespace Shadowsocks.Controller } catch (IOException e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } @@ -300,7 +303,7 @@ namespace Shadowsocks.Controller { try { - Logging.Debug("filter raw statistics"); + logger.Debug("filter raw statistics"); if (RawStatistics == null) return; var filteredStatistics = new Statistics(); @@ -315,7 +318,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } @@ -324,7 +327,7 @@ namespace Shadowsocks.Controller try { var path = AvailabilityStatisticsFile; - Logging.Debug($"loading statistics from {path}"); + logger.Debug($"loading statistics from {path}"); if (!File.Exists(path)) { using (File.Create(path)) @@ -337,7 +340,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Console.WriteLine($"failed to load statistics; use runtime statistics, some data may be lost"); } } @@ -411,6 +414,8 @@ namespace Shadowsocks.Controller class MyPing { + private static Logger logger = LogManager.GetCurrentClassLogger(); + //arguments for ICMP tests public const int TimeoutMilliseconds = 500; @@ -445,7 +450,7 @@ namespace Shadowsocks.Controller { try { - Logging.Debug($"Ping {server.FriendlyName()}"); + logger.Debug($"Ping {server.FriendlyName()}"); if (ip == null) { ip = Dns.GetHostAddresses(server.server) @@ -461,8 +466,8 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.Error($"An exception occured while eveluating {server.FriendlyName()}"); - Logging.LogUsefulException(e); + logger.Error($"An exception occured while eveluating {server.FriendlyName()}"); + logger.LogUsefulException(e); FireCompleted(e, userstate); } } @@ -473,20 +478,20 @@ namespace Shadowsocks.Controller { if (e.Reply.Status == IPStatus.Success) { - Logging.Debug($"Ping {server.FriendlyName()} {e.Reply.RoundtripTime} ms"); + logger.Debug($"Ping {server.FriendlyName()} {e.Reply.RoundtripTime} ms"); RoundtripTime.Add((int?)e.Reply.RoundtripTime); } else { - Logging.Debug($"Ping {server.FriendlyName()} timeout"); + logger.Debug($"Ping {server.FriendlyName()} timeout"); RoundtripTime.Add(null); } TestNext(e.UserState); } catch (Exception ex) { - Logging.Error($"An exception occured while eveluating {server.FriendlyName()}"); - Logging.LogUsefulException(ex); + logger.Error($"An exception occured while eveluating {server.FriendlyName()}"); + logger.LogUsefulException(ex); FireCompleted(ex, e.UserState); } } diff --git a/shadowsocks-csharp/Controller/Service/GfwListUpdater.cs b/shadowsocks-csharp/Controller/Service/GfwListUpdater.cs index 38044315..7f380cb4 100644 --- a/shadowsocks-csharp/Controller/Service/GfwListUpdater.cs +++ b/shadowsocks-csharp/Controller/Service/GfwListUpdater.cs @@ -5,7 +5,7 @@ using System.Net; using System.Text; using Newtonsoft.Json; - +using NLog; using Shadowsocks.Model; using Shadowsocks.Properties; using Shadowsocks.Util; @@ -14,6 +14,8 @@ namespace Shadowsocks.Controller { public class GFWListUpdater { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private const string GFWLIST_URL = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt"; public event EventHandler UpdateCompleted; @@ -93,10 +95,10 @@ var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; string gfwListUrl = GFWLIST_URL; if (!string.IsNullOrWhiteSpace(config.gfwListUrl)) { - Logging.Info("Found custom GFWListURL in config file"); + logger.Info("Found custom GFWListURL in config file"); gfwListUrl = config.gfwListUrl; } - Logging.Info($"Checking GFWList from {gfwListUrl}"); + logger.Info($"Checking GFWList from {gfwListUrl}"); WebClient http = new WebClient(); if (config.enabled) { diff --git a/shadowsocks-csharp/Controller/Service/Listener.cs b/shadowsocks-csharp/Controller/Service/Listener.cs index 70819163..2627587c 100644 --- a/shadowsocks-csharp/Controller/Service/Listener.cs +++ b/shadowsocks-csharp/Controller/Service/Listener.cs @@ -4,13 +4,15 @@ using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; - +using NLog; using Shadowsocks.Model; namespace Shadowsocks.Controller { public class Listener { + private static Logger logger = LogManager.GetCurrentClassLogger(); + public interface IService { bool Handle(byte[] firstPacket, int length, Socket socket, object state); @@ -80,11 +82,8 @@ namespace Shadowsocks.Controller _tcpSocket.Listen(1024); // Start an asynchronous socket to listen for connections. - Logging.Info($"Shadowsocks started ({UpdateChecker.Version})"); - if (_config.isVerboseLogging) - { - Logging.Info(Encryption.EncryptorFactory.DumpRegisteredEncryptor()); - } + logger.Info($"Shadowsocks started ({UpdateChecker.Version})"); + logger.Debug(Encryption.EncryptorFactory.DumpRegisteredEncryptor()); _tcpSocket.BeginAccept(new AsyncCallback(AcceptCallback), _tcpSocket); UDPState udpState = new UDPState(_udpSocket); _udpSocket.BeginReceiveFrom(udpState.buffer, 0, udpState.buffer.Length, 0, ref udpState.remoteEndPoint, new AsyncCallback(RecvFromCallback), udpState); @@ -132,7 +131,7 @@ namespace Shadowsocks.Controller } catch (Exception ex) { - Logging.Debug(ex); + logger.Debug(ex); } finally { @@ -171,7 +170,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } finally { @@ -187,7 +186,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } } @@ -218,7 +217,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); conn.Close(); } } diff --git a/shadowsocks-csharp/Controller/Service/PACDaemon.cs b/shadowsocks-csharp/Controller/Service/PACDaemon.cs index 11dc18b4..3aee925a 100644 --- a/shadowsocks-csharp/Controller/Service/PACDaemon.cs +++ b/shadowsocks-csharp/Controller/Service/PACDaemon.cs @@ -1,4 +1,5 @@ -using Shadowsocks.Properties; +using NLog; +using Shadowsocks.Properties; using Shadowsocks.Util; using System; using System.Collections.Generic; @@ -15,6 +16,8 @@ namespace Shadowsocks.Controller /// public class PACDaemon { + private static Logger logger = LogManager.GetCurrentClassLogger(); + public const string PAC_FILE = "pac.txt"; public const string USER_RULE_FILE = "user-rule.txt"; public const string USER_ABP_FILE = "abp.txt"; @@ -100,7 +103,7 @@ namespace Shadowsocks.Controller { if (PACFileChanged != null) { - Logging.Info($"Detected: PAC file '{e.Name}' was {e.ChangeType.ToString().ToLower()}."); + logger.Info($"Detected: PAC file '{e.Name}' was {e.ChangeType.ToString().ToLower()}."); Task.Factory.StartNew(() => { ((FileSystemWatcher)sender).EnableRaisingEvents = false; @@ -115,7 +118,7 @@ namespace Shadowsocks.Controller { if (UserRuleFileChanged != null) { - Logging.Info($"Detected: User Rule file '{e.Name}' was {e.ChangeType.ToString().ToLower()}."); + logger.Info($"Detected: User Rule file '{e.Name}' was {e.ChangeType.ToString().ToLower()}."); Task.Factory.StartNew(() => { ((FileSystemWatcher)sender).EnableRaisingEvents = false; diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs index 57e64ca2..7fd9250e 100644 --- a/shadowsocks-csharp/Controller/Service/PACServer.cs +++ b/shadowsocks-csharp/Controller/Service/PACServer.cs @@ -6,11 +6,14 @@ using System.Net; using System.Net.Sockets; using System.Text; using System.Web; +using NLog; namespace Shadowsocks.Controller { public class PACServer : Listener.Service { + private static Logger logger = LogManager.GetCurrentClassLogger(); + public const string RESOURCE_NAME = "pac"; private string PacSecret @@ -43,7 +46,7 @@ namespace Shadowsocks.Controller string usedSecret = _config.secureLocalPac ? $"&secret={PacSecret}" : ""; string contentHash = GetHash(_pacDaemon.GetPACContent()); PacUrl = $"http://{config.localHost}:{config.localPort}/{RESOURCE_NAME}?hash={contentHash}{usedSecret}"; - Logging.Debug("Set PAC URL:" + PacUrl); + logger.Debug("Set PAC URL:" + PacUrl); } private static string GetHash(string content) @@ -177,7 +180,7 @@ Connection: Close } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); socket.Close(); } } diff --git a/shadowsocks-csharp/Controller/Service/PortForwarder.cs b/shadowsocks-csharp/Controller/Service/PortForwarder.cs index 1acfa5bd..8284fd11 100644 --- a/shadowsocks-csharp/Controller/Service/PortForwarder.cs +++ b/shadowsocks-csharp/Controller/Service/PortForwarder.cs @@ -1,6 +1,7 @@ using System; using System.Net; using System.Net.Sockets; +using NLog; using Shadowsocks.Util.Sockets; namespace Shadowsocks.Controller @@ -26,6 +27,8 @@ namespace Shadowsocks.Controller private class Handler { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private byte[] _firstPacket; private int _firstPacketLength; private Socket _local; @@ -58,7 +61,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Close(); } } @@ -77,7 +80,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Close(); } } @@ -94,7 +97,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Close(); } } @@ -115,7 +118,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Close(); } } @@ -142,7 +145,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Close(); } } @@ -169,7 +172,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Close(); } } @@ -188,7 +191,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Close(); } } @@ -207,7 +210,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); Close(); } } @@ -239,7 +242,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } if (_remote != null) @@ -251,7 +254,7 @@ namespace Shadowsocks.Controller } catch (SocketException e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } } diff --git a/shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs b/shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs index 187e7a09..0a6135d1 100644 --- a/shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs +++ b/shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs @@ -6,6 +6,7 @@ using System.Net; using System.Net.Sockets; using System.Text; using System.Windows.Forms; +using NLog; using Shadowsocks.Model; using Shadowsocks.Properties; using Shadowsocks.Util; @@ -15,6 +16,8 @@ namespace Shadowsocks.Controller { class PrivoxyRunner { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private static int _uid; private static string _uniqueConfigFile; private static Job _privoxyJob; @@ -33,7 +36,7 @@ namespace Shadowsocks.Controller } catch (IOException e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } @@ -106,7 +109,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } @@ -139,7 +142,7 @@ namespace Shadowsocks.Controller * are already dead, and that will cause exceptions here. * We could simply ignore those exceptions. */ - Logging.LogUsefulException(ex); + logger.LogUsefulException(ex); return false; } } @@ -159,7 +162,7 @@ namespace Shadowsocks.Controller catch (Exception e) { // in case access denied - Logging.LogUsefulException(e); + logger.LogUsefulException(e); return defaultPort; } } diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index 7c89cac3..8327bda9 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -1,4 +1,5 @@ -using System; +using NLog; +using System; using System.Collections.Generic; using System.Linq; using System.Net; @@ -17,6 +18,7 @@ namespace Shadowsocks.Controller { class TCPRelay : Listener.Service { + private static Logger logger = LogManager.GetCurrentClassLogger(); private ShadowsocksController _controller; private DateTime _lastSweepTime; private Configuration _config; @@ -54,7 +56,7 @@ namespace Shadowsocks.Controller } foreach (TCPHandler handler1 in handlersToClose) { - Logging.Debug("Closing timed out TCP connection."); + logger.Debug("Closing timed out TCP connection."); handler1.Close(); } @@ -122,6 +124,8 @@ namespace Shadowsocks.Controller } } + private static Logger Logger = LogManager.GetCurrentClassLogger(); + private readonly int _serverTimeout; private readonly int _proxyTimeout; @@ -217,7 +221,7 @@ namespace Shadowsocks.Controller this._server = server; /* prepare address buffer length for AEAD */ - Logging.Debug($"_addrBufLength={_addrBufLength}"); + Logger.Debug($"_addrBufLength={_addrBufLength}"); _encryptor.AddrBufLength = _addrBufLength; } @@ -252,7 +256,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); } if (_currentRemoteSession != null) @@ -265,7 +269,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); } } @@ -291,7 +295,7 @@ namespace Shadowsocks.Controller { // reject socks 4 response = new byte[] { 0, 91 }; - Logging.Error("socks 5 protocol error"); + Logger.Error("socks 5 protocol error"); } _connection.BeginSend(response, 0, response.Length, SocketFlags.None, HandshakeSendCallback, null); @@ -301,7 +305,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -326,7 +330,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -358,21 +362,21 @@ namespace Shadowsocks.Controller break; case CMD_BIND: // not implemented default: - Logging.Debug("Unsupported CMD=" + _command); + Logger.Debug("Unsupported CMD=" + _command); Close(); break; } } else { - Logging.Debug( + Logger.Debug( "failed to recv data in Shadowsocks.Controller.TCPHandler.handshakeReceive2Callback()"); Close(); } } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -387,7 +391,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -409,7 +413,7 @@ namespace Shadowsocks.Controller ReadAddress(16 + ADDR_PORT_LEN - 1, onSuccess); break; default: - Logging.Debug("Unsupported ATYP=" + atyp); + Logger.Debug("Unsupported ATYP=" + atyp); Close(); break; } @@ -468,10 +472,7 @@ namespace Shadowsocks.Controller break; } - if (_config.isVerboseLogging) - { - Logging.Info($"connect to {dstAddr}:{dstPort}"); - } + Logger.Debug($"connect to {dstAddr}:{dstPort}"); _destEndPoint = SocketUtil.GetEndPoint(dstAddr, dstPort); @@ -479,13 +480,13 @@ namespace Shadowsocks.Controller } else { - Logging.Debug("failed to recv data in Shadowsocks.Controller.TCPHandler.OnAddressFullyRead()"); + Logger.Debug("failed to recv data in Shadowsocks.Controller.TCPHandler.OnAddressFullyRead()"); Close(); } } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -537,7 +538,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -631,7 +632,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -650,7 +651,7 @@ namespace Shadowsocks.Controller } var proxy = timer.Session.Remote; - Logging.Info($"Proxy {proxy.ProxyEndPoint} timed out"); + Logger.Info($"Proxy {proxy.ProxyEndPoint} timed out"); proxy.Close(); Close(); } @@ -678,12 +679,9 @@ namespace Shadowsocks.Controller _proxyConnected = true; - if (_config.isVerboseLogging) + if (!(remote is DirectConnect)) { - if (!(remote is DirectConnect)) - { - Logging.Info($"Socket connected to proxy {remote.ProxyEndPoint}"); - } + Logger.Debug($"Socket connected to proxy {remote.ProxyEndPoint}"); } _startConnectTime = DateTime.Now; @@ -710,7 +708,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -731,7 +729,7 @@ namespace Shadowsocks.Controller Server server = timer.Server; IStrategy strategy = _controller.GetCurrentStrategy(); strategy?.SetFailure(server); - Logging.Info($"{server.FriendlyName()} timed out"); + Logger.Info($"{server.FriendlyName()} timed out"); session.Remote.Close(); Close(); } @@ -754,10 +752,7 @@ namespace Shadowsocks.Controller _destConnected = true; - if (_config.isVerboseLogging) - { - Logging.Info($"Socket connected to ss server: {_server.FriendlyName()}"); - } + Logger.Debug($"Socket connected to ss server: {_server.FriendlyName()}"); var latency = DateTime.Now - _startConnectTime; IStrategy strategy = _controller.GetCurrentStrategy(); @@ -776,7 +771,7 @@ namespace Shadowsocks.Controller IStrategy strategy = _controller.GetCurrentStrategy(); strategy?.SetFailure(_server); } - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -803,12 +798,12 @@ namespace Shadowsocks.Controller PipeRemoteReceiveCallback, session); TryReadAvailableData(); - Logging.Debug($"_firstPacketLength = {_firstPacketLength}"); + Logger.Debug($"_firstPacketLength = {_firstPacketLength}"); SendToServer(_firstPacketLength, session); } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -834,7 +829,7 @@ namespace Shadowsocks.Controller } catch (CryptoErrorException) { - Logging.Error("decryption error"); + Logger.Error("decryption error"); Close(); return; } @@ -842,12 +837,12 @@ namespace Shadowsocks.Controller if (bytesToSend == 0) { // need more to decrypt - Logging.Debug("Need more to decrypt"); + Logger.Debug("Need more to decrypt"); session.Remote.BeginReceive(_remoteRecvBuffer, 0, RecvSize, SocketFlags.None, PipeRemoteReceiveCallback, session); return; } - Logging.Debug($"start sending {bytesToSend}"); + Logger.Debug($"start sending {bytesToSend}"); _connection.BeginSend(_remoteSendBuffer, 0, bytesToSend, SocketFlags.None, PipeConnectionSendCallback, new object[] { session, bytesToSend }); IStrategy strategy = _controller.GetCurrentStrategy(); @@ -862,7 +857,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -890,7 +885,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -907,7 +902,7 @@ namespace Shadowsocks.Controller } catch (CryptoErrorException) { - Logging.Debug("encryption error"); + Logger.Debug("encryption error"); Close(); return; } @@ -932,7 +927,7 @@ namespace Shadowsocks.Controller int bytesRemaining = bytesShouldSend - bytesSent; if (bytesRemaining > 0) { - Logging.Info("reconstruct _connetionSendBuffer to re-send"); + Logger.Info("reconstruct _connetionSendBuffer to re-send"); Buffer.BlockCopy(_connetionSendBuffer, bytesSent, _connetionSendBuffer, 0, bytesRemaining); session.Remote.BeginSend(_connetionSendBuffer, 0, bytesRemaining, SocketFlags.None, PipeRemoteSendCallback, new object[] { session, bytesRemaining }); @@ -943,7 +938,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } @@ -960,7 +955,7 @@ namespace Shadowsocks.Controller var bytesRemaining = bytesShouldSend - bytesSent; if (bytesRemaining > 0) { - Logging.Info("reconstruct _remoteSendBuffer to re-send"); + Logger.Info("reconstruct _remoteSendBuffer to re-send"); Buffer.BlockCopy(_remoteSendBuffer, bytesSent, _remoteSendBuffer, 0, bytesRemaining); _connection.BeginSend(_remoteSendBuffer, 0, bytesRemaining, SocketFlags.None, PipeConnectionSendCallback, new object[] { session, bytesRemaining }); @@ -971,7 +966,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + Logger.LogUsefulException(e); Close(); } } diff --git a/shadowsocks-csharp/Controller/Service/UDPRelay.cs b/shadowsocks-csharp/Controller/Service/UDPRelay.cs index 5ac03839..568e1f75 100644 --- a/shadowsocks-csharp/Controller/Service/UDPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/UDPRelay.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Runtime.CompilerServices; +using NLog; using Shadowsocks.Controller.Strategy; using Shadowsocks.Encryption; using Shadowsocks.Model; @@ -49,6 +50,8 @@ namespace Shadowsocks.Controller public class UDPHandler { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private Socket _local; private Socket _remote; @@ -98,14 +101,14 @@ namespace Shadowsocks.Controller byte[] dataOut = new byte[65536]; // enough space for AEAD ciphers int outlen; encryptor.EncryptUDP(dataIn, length - 3, dataOut, out outlen); - Logging.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay"); + logger.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay"); _remote?.SendTo(dataOut, outlen, SocketFlags.None, _remoteEndPoint); } public void Receive() { EndPoint remoteEndPoint = new IPEndPoint(GetIPAddress(), 0); - Logging.Debug($"++++++Receive Server Port, size:" + _buffer.Length); + logger.Debug($"++++++Receive Server Port, size:" + _buffer.Length); _remote?.BeginReceiveFrom(_buffer, 0, _buffer.Length, 0, ref remoteEndPoint, new AsyncCallback(RecvFromCallback), null); } @@ -126,7 +129,7 @@ namespace Shadowsocks.Controller byte[] sendBuf = new byte[outlen + 3]; Array.Copy(dataOut, 0, sendBuf, 3, outlen); - Logging.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay"); + logger.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay"); _local?.SendTo(sendBuf, outlen + 3, 0, _localEndPoint); Receive(); diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs index cce193f1..fb1aa331 100644 --- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs @@ -4,7 +4,7 @@ using System.Net; using System.Text.RegularExpressions; using Newtonsoft.Json.Linq; - +using NLog; using Shadowsocks.Model; using Shadowsocks.Util; @@ -12,6 +12,8 @@ namespace Shadowsocks.Controller { public class UpdateChecker { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private const string UpdateURL = "https://api.github.com/repos/shadowsocks/shadowsocks-windows/releases"; private const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"; @@ -60,14 +62,14 @@ namespace Shadowsocks.Controller try { - Logging.Debug("Checking updates..."); + logger.Debug("Checking updates..."); WebClient http = CreateWebClient(); http.DownloadStringCompleted += http_DownloadStringCompleted; http.DownloadStringAsync(new Uri(UpdateURL)); } catch (Exception ex) { - Logging.LogUsefulException(ex); + logger.LogUsefulException(ex); } } @@ -117,7 +119,7 @@ namespace Shadowsocks.Controller } else { - Logging.Debug("No update is available"); + logger.Debug("No update is available"); if (CheckUpdateCompleted != null) { CheckUpdateCompleted(this, new EventArgs()); @@ -126,7 +128,7 @@ namespace Shadowsocks.Controller } catch (Exception ex) { - Logging.LogUsefulException(ex); + logger.LogUsefulException(ex); } } @@ -141,7 +143,7 @@ namespace Shadowsocks.Controller } catch (Exception ex) { - Logging.LogUsefulException(ex); + logger.LogUsefulException(ex); } } @@ -151,10 +153,10 @@ namespace Shadowsocks.Controller { if (e.Error != null) { - Logging.LogUsefulException(e.Error); + logger.LogUsefulException(e.Error); return; } - Logging.Debug($"New version {LatestVersionNumber}{LatestVersionSuffix} found: {LatestVersionLocalName}"); + logger.Debug($"New version {LatestVersionNumber}{LatestVersionSuffix} found: {LatestVersionLocalName}"); if (CheckUpdateCompleted != null) { CheckUpdateCompleted(this, new EventArgs()); @@ -162,7 +164,7 @@ namespace Shadowsocks.Controller } catch (Exception ex) { - Logging.LogUsefulException(ex); + logger.LogUsefulException(ex); } } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 66a42f6f..f4ea1294 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -9,7 +9,7 @@ using System.Text; using System.Threading; using System.Web; using System.Windows.Forms; - +using NLog; using Shadowsocks.Controller.Service; using Shadowsocks.Controller.Strategy; using Shadowsocks.Model; @@ -19,6 +19,8 @@ namespace Shadowsocks.Controller { public class ShadowsocksController { + private static Logger logger = LogManager.GetCurrentClassLogger(); + // controller: // handle user actions // manipulates UI @@ -95,6 +97,11 @@ namespace Shadowsocks.Controller _pluginsByServer = new ConcurrentDictionary(); StartReleasingMemory(); StartTrafficStatistics(61); + + ProgramUpdated += (o, e) => + { + logger.Info($"Updated from {e.OldVersion} to {e.NewVersion}"); + }; } public void Start(bool regHotkeys = true) @@ -184,13 +191,13 @@ namespace Shadowsocks.Controller { if (plugin.StartIfNeeded()) { - Logging.Info( + logger.Info( $"Started SIP003 plugin for {server.Identifier()} on {plugin.LocalEndPoint} - PID: {plugin.ProcessId}"); } } catch (Exception ex) { - Logging.Error("Failed to start SIP003 plugin: " + ex.Message); + logger.Error("Failed to start SIP003 plugin: " + ex.Message); throw; } @@ -232,7 +239,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); return false; } } @@ -271,6 +278,7 @@ namespace Shadowsocks.Controller { _config.isVerboseLogging = enabled; SaveConfig(_config); + NLogConfig.LoadConfiguration(); // reload nlog VerboseLoggingStatusChanged?.Invoke(this, new EventArgs()); } @@ -494,6 +502,9 @@ namespace Shadowsocks.Controller Encryption.RNG.Reload(); // some logic in configuration updated the config when saving, we need to read it again _config = Configuration.Load(); + + NLogConfig.LoadConfiguration(); + StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); privoxyRunner = privoxyRunner ?? new PrivoxyRunner(); @@ -552,7 +563,7 @@ namespace Shadowsocks.Controller e = new Exception(I18N.GetString("Port {0} is reserved by system", _config.localPort), e); } } - Logging.LogUsefulException(e); + logger.LogUsefulException(e); ReportError(e); } diff --git a/shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs b/shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs index 9804fad2..61356543 100644 --- a/shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs +++ b/shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs @@ -1,4 +1,5 @@ -using Shadowsocks.Model; +using NLog; +using Shadowsocks.Model; using System; using System.Collections.Generic; using System.Net; @@ -8,6 +9,8 @@ namespace Shadowsocks.Controller.Strategy { class HighAvailabilityStrategy : IStrategy { + private static Logger logger = LogManager.GetCurrentClassLogger(); + protected ServerStatus _currentServer; protected Dictionary _serverStatus; ShadowsocksController _controller; @@ -111,7 +114,7 @@ namespace Shadowsocks.Controller.Strategy 100 * 1000 * Math.Min(5 * 60, (now - status.lastFailure).TotalSeconds) -2 * 5 * (Math.Min(2000, status.latency.TotalMilliseconds) / (1 + (now - status.lastTimeDetectLatency).TotalSeconds / 30 / 10) + -0.5 * 200 * Math.Min(5, (status.lastRead - status.lastWrite).TotalSeconds)); - Logging.Debug(String.Format("server: {0} latency:{1} score: {2}", status.server.FriendlyName(), status.latency, status.score)); + logger.Debug(String.Format("server: {0} latency:{1} score: {2}", status.server.FriendlyName(), status.latency, status.score)); } ServerStatus max = null; foreach (var status in servers) @@ -133,14 +136,14 @@ namespace Shadowsocks.Controller.Strategy if (_currentServer == null || max.score - _currentServer.score > 200) { _currentServer = max; - Logging.Info($"HA switching to server: {_currentServer.server.FriendlyName()}"); + logger.Info($"HA switching to server: {_currentServer.server.FriendlyName()}"); } } } public void UpdateLatency(Model.Server server, TimeSpan latency) { - Logging.Debug($"latency: {server.FriendlyName()} {latency}"); + logger.Debug($"latency: {server.FriendlyName()} {latency}"); ServerStatus status; if (_serverStatus.TryGetValue(server, out status)) @@ -152,7 +155,7 @@ namespace Shadowsocks.Controller.Strategy public void UpdateLastRead(Model.Server server) { - Logging.Debug($"last read: {server.FriendlyName()}"); + logger.Debug($"last read: {server.FriendlyName()}"); ServerStatus status; if (_serverStatus.TryGetValue(server, out status)) @@ -163,7 +166,7 @@ namespace Shadowsocks.Controller.Strategy public void UpdateLastWrite(Model.Server server) { - Logging.Debug($"last write: {server.FriendlyName()}"); + logger.Debug($"last write: {server.FriendlyName()}"); ServerStatus status; if (_serverStatus.TryGetValue(server, out status)) @@ -174,7 +177,7 @@ namespace Shadowsocks.Controller.Strategy public void SetFailure(Model.Server server) { - Logging.Debug($"failure: {server.FriendlyName()}"); + logger.Debug($"failure: {server.FriendlyName()}"); ServerStatus status; if (_serverStatus.TryGetValue(server, out status)) diff --git a/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs b/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs index d965a083..57f37989 100644 --- a/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs +++ b/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs @@ -5,7 +5,7 @@ using System.Net; using System.Threading; using Newtonsoft.Json; - +using NLog; using Shadowsocks.Model; namespace Shadowsocks.Controller.Strategy @@ -14,6 +14,8 @@ namespace Shadowsocks.Controller.Strategy internal class StatisticsStrategy : IStrategy, IDisposable { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private readonly ShadowsocksController _controller; private Server _currentServer; private readonly Timer _timer; @@ -34,7 +36,7 @@ namespace Shadowsocks.Controller.Strategy private void ReloadStatisticsAndChooseAServer(object obj) { - Logging.Debug("Reloading statistics and choose a new server...."); + logger.Debug("Reloading statistics and choose a new server...."); var servers = _controller.GetCurrentConfiguration().configs; LoadStatistics(); ChooseNewServer(servers); @@ -74,7 +76,7 @@ namespace Shadowsocks.Controller.Strategy if (score != null) { - Logging.Debug($"Highest score: {score} {JsonConvert.SerializeObject(averageRecord, Formatting.Indented)}"); + logger.Debug($"Highest score: {score} {JsonConvert.SerializeObject(averageRecord, Formatting.Indented)}"); } return score; } @@ -112,7 +114,7 @@ namespace Shadowsocks.Controller.Strategy } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } @@ -145,7 +147,7 @@ namespace Shadowsocks.Controller.Strategy public void SetFailure(Server server) { - Logging.Debug($"failure: {server.FriendlyName()}"); + logger.Debug($"failure: {server.FriendlyName()}"); } public void UpdateLastRead(Server server) diff --git a/shadowsocks-csharp/Controller/System/AutoStartup.cs b/shadowsocks-csharp/Controller/System/AutoStartup.cs index 310a3c71..c1d207e0 100644 --- a/shadowsocks-csharp/Controller/System/AutoStartup.cs +++ b/shadowsocks-csharp/Controller/System/AutoStartup.cs @@ -5,12 +5,15 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; using Microsoft.Win32; +using NLog; using Shadowsocks.Util; namespace Shadowsocks.Controller { static class AutoStartup { + private static Logger logger = LogManager.GetCurrentClassLogger(); + // Don't use Application.ExecutablePath // see https://stackoverflow.com/questions/12945805/odd-c-sharp-path-issue private static readonly string ExecutablePath = Assembly.GetEntryAssembly().Location; @@ -25,7 +28,7 @@ namespace Shadowsocks.Controller runKey = Utils.OpenRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true); if (runKey == null) { - Logging.Error(@"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run"); + logger.Error(@"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run"); return false; } if (enabled) @@ -42,7 +45,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); return false; } finally @@ -55,7 +58,7 @@ namespace Shadowsocks.Controller runKey.Dispose(); } catch (Exception e) - { Logging.LogUsefulException(e); } + { logger.LogUsefulException(e); } } } } @@ -68,7 +71,7 @@ namespace Shadowsocks.Controller runKey = Utils.OpenRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true); if (runKey == null) { - Logging.Error(@"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run"); + logger.Error(@"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run"); return false; } string[] runList = runKey.GetValueNames(); @@ -91,7 +94,7 @@ namespace Shadowsocks.Controller } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); return false; } finally @@ -104,7 +107,7 @@ namespace Shadowsocks.Controller runKey.Dispose(); } catch (Exception e) - { Logging.LogUsefulException(e); } + { logger.LogUsefulException(e); } } } } @@ -140,13 +143,13 @@ namespace Shadowsocks.Controller // first parameter is process command line parameter // needn't include the name of the executable in the command line RegisterApplicationRestart(cmdline, (int)(ApplicationRestartFlags.RESTART_NO_CRASH | ApplicationRestartFlags.RESTART_NO_HANG)); - Logging.Debug("Register restart after system reboot, command line:" + cmdline); + logger.Debug("Register restart after system reboot, command line:" + cmdline); } // requested unregister, which has no side effect else if (!register) { UnregisterApplicationRestart(); - Logging.Debug("Unregister restart after system reboot"); + logger.Debug("Unregister restart after system reboot"); } } } diff --git a/shadowsocks-csharp/Controller/System/SystemProxy.cs b/shadowsocks-csharp/Controller/System/SystemProxy.cs index fa7d6853..1d61dd86 100644 --- a/shadowsocks-csharp/Controller/System/SystemProxy.cs +++ b/shadowsocks-csharp/Controller/System/SystemProxy.cs @@ -1,5 +1,6 @@ using System; using System.Windows.Forms; +using NLog; using Shadowsocks.Model; using Shadowsocks.Util.SystemProxy; @@ -7,6 +8,8 @@ namespace Shadowsocks.Controller { public static class SystemProxy { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private static string GetTimestamp(DateTime value) { return value.ToString("yyyyMMddHHmmssfff"); @@ -52,7 +55,7 @@ namespace Shadowsocks.Controller } catch (ProxyException ex) { - Logging.LogUsefulException(ex); + logger.LogUsefulException(ex); if (ex.Type != ProxyExceptionType.Unspecific && !noRetry) { var ret = MessageBox.Show(I18N.GetString("Error occured when process proxy setting, do you want reset current setting and retry?"), I18N.GetString("Shadowsocks"), MessageBoxButtons.YesNo, MessageBoxIcon.Warning); diff --git a/shadowsocks-csharp/Data/NLog.config b/shadowsocks-csharp/Data/NLog.config new file mode 100644 index 00000000..05509cff --- /dev/null +++ b/shadowsocks-csharp/Data/NLog.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/shadowsocks-csharp/Data/i18n.csv b/shadowsocks-csharp/Data/i18n.csv index 3db1ef8f..f2bf8a29 100644 --- a/shadowsocks-csharp/Data/i18n.csv +++ b/shadowsocks-csharp/Data/i18n.csv @@ -1,4 +1,4 @@ -en,ru-RU,zh-CN,zh-TW,ja +en,ru-RU,zh-CN,zh-TW,ja #Restart program to apply translation,,,, #This is comment line,,,, #Always keep language name at head of file,,,, @@ -75,6 +75,7 @@ Apply,Применить,应用,應用,適用 New server,Новый сервер,未配置的服务器,新伺服器,新規サーバー Move &Up,Выше,上移(&U),上移 (&U),上に移動 (&U) Move D&own,Ниже,下移(&O),下移 (&O),下に移動 (&O) +deprecated,Устаревшее,不推荐,不推薦,非推奨 ,,,, #Statistics Config,,,, ,,,, diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs index a4e42eae..2acd54bd 100644 --- a/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs +++ b/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs @@ -1,4 +1,5 @@ -using System; +using NLog; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Net; @@ -13,6 +14,7 @@ namespace Shadowsocks.Encryption.AEAD public abstract class AEADEncryptor : EncryptorBase { + private static Logger logger = LogManager.GetCurrentClassLogger(); // We are using the same saltLen and keyLen private const string Info = "ss-subkey"; private static readonly byte[] InfoBytes = Encoding.ASCII.GetBytes(Info); @@ -122,7 +124,7 @@ namespace Shadowsocks.Encryption.AEAD _decryptSalt = new byte[saltLen]; Array.Copy(salt, _decryptSalt, saltLen); } - Logging.Dump("Salt", salt, saltLen); + logger.Dump("Salt", salt, saltLen); } public static void randBytes(byte[] buf, int length) { RNG.GetBytes(buf, length); } @@ -139,7 +141,7 @@ namespace Shadowsocks.Encryption.AEAD _encCircularBuffer.Put(buf, 0, length); outlength = 0; - Logging.Debug("---Start Encryption"); + logger.Debug("---Start Encryption"); if (! _encryptSaltSent) { _encryptSaltSent = true; // Generate salt @@ -148,7 +150,7 @@ namespace Shadowsocks.Encryption.AEAD InitCipher(saltBytes, true, false); Array.Copy(saltBytes, 0, outbuf, 0, saltLen); outlength = saltLen; - Logging.Debug($"_encryptSaltSent outlength {outlength}"); + logger.Debug($"_encryptSaltSent outlength {outlength}"); } if (! _tcpRequestSent) { @@ -161,7 +163,7 @@ namespace Shadowsocks.Encryption.AEAD Debug.Assert(encAddrBufLength == AddrBufLength + tagLen * 2 + CHUNK_LEN_BYTES); Array.Copy(encAddrBufBytes, 0, outbuf, outlength, encAddrBufLength); outlength += encAddrBufLength; - Logging.Debug($"_tcpRequestSent outlength {outlength}"); + logger.Debug($"_tcpRequestSent outlength {outlength}"); } // handle other chunks @@ -176,15 +178,15 @@ namespace Shadowsocks.Encryption.AEAD Debug.Assert(encChunkLength == chunklength + tagLen * 2 + CHUNK_LEN_BYTES); Buffer.BlockCopy(encChunkBytes, 0, outbuf, outlength, encChunkLength); outlength += encChunkLength; - Logging.Debug("chunks enc outlength " + outlength); + logger.Debug("chunks enc outlength " + outlength); // check if we have enough space for outbuf if (outlength + TCPHandler.ChunkOverheadSize > TCPHandler.BufferSize) { - Logging.Debug("enc outbuf almost full, giving up"); + logger.Debug("enc outbuf almost full, giving up"); return; } bufSize = (uint)_encCircularBuffer.Size; if (bufSize <= 0) { - Logging.Debug("No more data to encrypt, leaving"); + logger.Debug("No more data to encrypt, leaving"); return; } } @@ -199,7 +201,7 @@ namespace Shadowsocks.Encryption.AEAD // drop all into buffer _decCircularBuffer.Put(buf, 0, length); - Logging.Debug("---Start Decryption"); + logger.Debug("---Start Decryption"); if (! _decryptSaltReceived) { bufSize = _decCircularBuffer.Size; // check if we get the leading salt @@ -210,7 +212,7 @@ namespace Shadowsocks.Encryption.AEAD _decryptSaltReceived = true; byte[] salt = _decCircularBuffer.Get(saltLen); InitCipher(salt, false, false); - Logging.Debug("get salt len " + saltLen); + logger.Debug("get salt len " + saltLen); } // handle chunks @@ -218,7 +220,7 @@ namespace Shadowsocks.Encryption.AEAD bufSize = _decCircularBuffer.Size; // check if we have any data if (bufSize <= 0) { - Logging.Debug("No data in _decCircularBuffer"); + logger.Debug("No data in _decCircularBuffer"); return; } @@ -241,13 +243,13 @@ namespace Shadowsocks.Encryption.AEAD if (chunkLen > CHUNK_LEN_MASK) { // we get invalid chunk - Logging.Error($"Invalid chunk length: {chunkLen}"); + logger.Error($"Invalid chunk length: {chunkLen}"); throw new CryptoErrorException(); } - Logging.Debug("Get the real chunk len:" + chunkLen); + logger.Debug("Get the real chunk len:" + chunkLen); bufSize = _decCircularBuffer.Size; if (bufSize < CHUNK_LEN_BYTES + tagLen /* we haven't remove them */+ chunkLen + tagLen) { - Logging.Debug("No more data to decrypt one chunk"); + logger.Debug("No more data to decrypt one chunk"); return; } IncrementNonce(false); @@ -267,16 +269,16 @@ namespace Shadowsocks.Encryption.AEAD // output to outbuf Buffer.BlockCopy(decChunkBytes, 0, outbuf, outlength, (int) decChunkLen); outlength += (int)decChunkLen; - Logging.Debug("aead dec outlength " + outlength); + logger.Debug("aead dec outlength " + outlength); if (outlength + 100 > TCPHandler.BufferSize) { - Logging.Debug("dec outbuf almost full, giving up"); + logger.Debug("dec outbuf almost full, giving up"); return; } bufSize = _decCircularBuffer.Size; // check if we already done all of them if (bufSize <= 0) { - Logging.Debug("No data in _decCircularBuffer, already all done"); + logger.Debug("No data in _decCircularBuffer, already all done"); return; } } @@ -319,7 +321,7 @@ namespace Shadowsocks.Encryption.AEAD private void ChunkEncrypt(byte[] plaintext, int plainLen, byte[] ciphertext, out int cipherLen) { if (plainLen > CHUNK_LEN_MASK) { - Logging.Error("enc chunk too big"); + logger.Error("enc chunk too big"); throw new CryptoErrorException(); } diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs index 2aa2856f..06aef5d7 100644 --- a/shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs +++ b/shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using NLog; using Shadowsocks.Controller; using Shadowsocks.Encryption.Exception; @@ -9,6 +10,8 @@ namespace Shadowsocks.Encryption.AEAD public class AEADSodiumEncryptor : AEADEncryptor, IDisposable { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private const int CIPHER_CHACHA20IETFPOLY1305 = 1; private const int CIPHER_XCHACHA20IETFPOLY1305 = 2; private const int CIPHER_AES256GCM = 3; @@ -55,9 +58,9 @@ namespace Shadowsocks.Encryption.AEAD // outbuf: ciphertext + tag int ret; ulong encClen = 0; - Logging.Dump("_encNonce before enc", _encNonce, nonceLen); - Logging.Dump("_sodiumEncSubkey", _sodiumEncSubkey, keyLen); - Logging.Dump("before cipherEncrypt: plain", plaintext, (int) plen); + logger.Dump("_encNonce before enc", _encNonce, nonceLen); + logger.Dump("_sodiumEncSubkey", _sodiumEncSubkey, keyLen); + logger.Dump("before cipherEncrypt: plain", plaintext, (int) plen); switch (_cipher) { case CIPHER_CHACHA20IETFPOLY1305: @@ -85,7 +88,7 @@ namespace Shadowsocks.Encryption.AEAD throw new System.Exception("not implemented"); } if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret)); - Logging.Dump("after cipherEncrypt: cipher", ciphertext, (int) encClen); + logger.Dump("after cipherEncrypt: cipher", ciphertext, (int) encClen); clen = (uint) encClen; } @@ -96,9 +99,9 @@ namespace Shadowsocks.Encryption.AEAD // outbuf: plaintext int ret; ulong decPlen = 0; - Logging.Dump("_decNonce before dec", _decNonce, nonceLen); - Logging.Dump("_sodiumDecSubkey", _sodiumDecSubkey, keyLen); - Logging.Dump("before cipherDecrypt: cipher", ciphertext, (int) clen); + logger.Dump("_decNonce before dec", _decNonce, nonceLen); + logger.Dump("_sodiumDecSubkey", _sodiumDecSubkey, keyLen); + logger.Dump("before cipherDecrypt: cipher", ciphertext, (int) clen); switch (_cipher) { case CIPHER_CHACHA20IETFPOLY1305: @@ -127,7 +130,7 @@ namespace Shadowsocks.Encryption.AEAD } if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret)); - Logging.Dump("after cipherDecrypt: plain", plaintext, (int) decPlen); + logger.Dump("after cipherDecrypt: plain", plaintext, (int) decPlen); plen = (uint) decPlen; } diff --git a/shadowsocks-csharp/Encryption/MbedTLS.cs b/shadowsocks-csharp/Encryption/MbedTLS.cs index 4e0b76d8..be681670 100644 --- a/shadowsocks-csharp/Encryption/MbedTLS.cs +++ b/shadowsocks-csharp/Encryption/MbedTLS.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Runtime.InteropServices; +using NLog; using Shadowsocks.Controller; using Shadowsocks.Properties; using Shadowsocks.Util; @@ -9,6 +10,8 @@ namespace Shadowsocks.Encryption { public static class MbedTLS { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private const string DLLNAME = "libsscrypto.dll"; public const int MBEDTLS_ENCRYPT = 1; @@ -26,7 +29,7 @@ namespace Shadowsocks.Encryption } catch (System.Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } LoadLibrary(dllPath); } diff --git a/shadowsocks-csharp/Encryption/OpenSSL.cs b/shadowsocks-csharp/Encryption/OpenSSL.cs index c88404ed..00056a04 100644 --- a/shadowsocks-csharp/Encryption/OpenSSL.cs +++ b/shadowsocks-csharp/Encryption/OpenSSL.cs @@ -3,6 +3,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Text; +using NLog; using Shadowsocks.Controller; using Shadowsocks.Encryption.Exception; using Shadowsocks.Properties; @@ -13,6 +14,8 @@ namespace Shadowsocks.Encryption // XXX: only for OpenSSL 1.1.0 and higher public static class OpenSSL { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private const string DLLNAME = "libsscrypto.dll"; public const int OPENSSL_ENCRYPT = 1; @@ -34,7 +37,7 @@ namespace Shadowsocks.Encryption } catch (System.Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } LoadLibrary(dllPath); } diff --git a/shadowsocks-csharp/Encryption/Sodium.cs b/shadowsocks-csharp/Encryption/Sodium.cs index 66b1abbe..6b9441dd 100755 --- a/shadowsocks-csharp/Encryption/Sodium.cs +++ b/shadowsocks-csharp/Encryption/Sodium.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Runtime.InteropServices; +using NLog; using Shadowsocks.Controller; using Shadowsocks.Properties; using Shadowsocks.Util; @@ -9,6 +10,8 @@ namespace Shadowsocks.Encryption { public static class Sodium { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private const string DLLNAME = "libsscrypto.dll"; private static bool _initialized = false; @@ -28,7 +31,7 @@ namespace Shadowsocks.Encryption } catch (System.Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } LoadLibrary(dllPath); @@ -46,7 +49,7 @@ namespace Shadowsocks.Encryption } AES256GCMAvailable = crypto_aead_aes256gcm_is_available() == 1; - Logging.Debug($"sodium: AES256GCMAvailable is {AES256GCMAvailable}"); + logger.Debug($"sodium: AES256GCMAvailable is {AES256GCMAvailable}"); } } } diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index 23523416..9eb50a09 100644 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using Newtonsoft.Json; +using NLog; using Shadowsocks.Controller; namespace Shadowsocks.Model @@ -9,6 +10,9 @@ namespace Shadowsocks.Model [Serializable] public class Configuration { + [JsonIgnore] + private static Logger logger = LogManager.GetCurrentClassLogger(); + public string version; public List configs; @@ -32,10 +36,14 @@ namespace Shadowsocks.Model public bool autoCheckUpdate; public bool checkPreRelease; public bool isVerboseLogging; + //public NLogConfig.LogLevel logLevel; public LogViewerConfig logViewer; public ProxyConfig proxy; public HotkeyConfig hotkey; + [JsonIgnore] + NLogConfig nLogConfig; + private static readonly string CONFIG_FILE = "gui-config.json"; [JsonIgnore] @@ -110,12 +118,35 @@ namespace Shadowsocks.Model config.proxy.CheckConfig(); + try + { + config.nLogConfig = NLogConfig.LoadXML(); + switch (config.nLogConfig.GetLogLevel()) + { + case NLogConfig.LogLevel.Fatal: + case NLogConfig.LogLevel.Error: + case NLogConfig.LogLevel.Warn: + case NLogConfig.LogLevel.Info: + config.isVerboseLogging = false; + break; + case NLogConfig.LogLevel.Debug: + case NLogConfig.LogLevel.Trace: + config.isVerboseLogging = true; + break; + } + } + catch (Exception e) + { + // todo: route the error to UI since there is no log file in this scenario + logger.Error(e, "Cannot get the log level from NLog config file. Please check if the nlog config file exists with corresponding XML nodes."); + } + return config; } catch (Exception e) { if (!(e is FileNotFoundException)) - Logging.LogUsefulException(e); + logger.LogUsefulException(e); return new Configuration { index = 0, @@ -128,7 +159,7 @@ namespace Shadowsocks.Model }, logViewer = new LogViewerConfig(), proxy = new ProxyConfig(), - hotkey = new HotkeyConfig() + hotkey = new HotkeyConfig(), }; } } @@ -151,10 +182,20 @@ namespace Shadowsocks.Model sw.Write(jsonString); sw.Flush(); } + try + { + // apply changs to NLog.config + config.nLogConfig.SetLogLevel(config.isVerboseLogging? NLogConfig.LogLevel.Trace: NLogConfig.LogLevel.Info); + NLogConfig.SaveXML(config.nLogConfig); + } + catch(Exception e) + { + logger.Error(e, "Cannot set the log level to NLog config file. Please check if the nlog config file exists with corresponding XML nodes."); + } } catch (IOException e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } diff --git a/shadowsocks-csharp/Model/NlogConfig.cs b/shadowsocks-csharp/Model/NlogConfig.cs new file mode 100644 index 00000000..11d6d858 --- /dev/null +++ b/shadowsocks-csharp/Model/NlogConfig.cs @@ -0,0 +1,126 @@ +using NLog; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace Shadowsocks.Model +{ + public class NLogConfig + { + public enum LogLevel + { + Fatal, + Error, + Warn, + Info, + Debug, + Trace, + } + + const string NLOG_CONFIG_FILE_NAME = "NLog.config"; + const string TARGET_MIN_LEVEL_ATTRIBUTE = "minlevel"; + const string LOGGER_FILE_NAME_ATTRIBUTE = "fileName"; + + XmlDocument doc = new XmlDocument(); + XmlElement logFileNameElement; + XmlElement logLevelElement; + + /// + /// Load the NLog config xml file content + /// + public static NLogConfig LoadXML() + { + NLogConfig config = new NLogConfig(); + config.doc.Load(NLOG_CONFIG_FILE_NAME); + config.logLevelElement = (XmlElement)SelectSingleNode(config.doc, "//nlog:logger[@name='*']"); + config.logFileNameElement = (XmlElement)SelectSingleNode(config.doc, "//nlog:target[@name='file']"); + return config; + } + + /// + /// Save the content to NLog config xml file + /// + public static void SaveXML(NLogConfig nLogConfig) + { + nLogConfig.doc.Save(NLOG_CONFIG_FILE_NAME); + } + + + /// + /// Get the current minLogLevel from xml file + /// + /// + public LogLevel GetLogLevel() + { + LogLevel level = LogLevel.Warn; + string levelStr = logLevelElement.GetAttribute(TARGET_MIN_LEVEL_ATTRIBUTE); + Enum.TryParse(levelStr, out level); + return level; + } + + /// + /// Get the target fileName from xml file + /// + /// + public string GetLogFileName() + { + return logFileNameElement.GetAttribute(LOGGER_FILE_NAME_ATTRIBUTE); + } + + /// + /// Set the minLogLevel to xml file + /// + /// + public void SetLogLevel(LogLevel logLevel) + { + logLevelElement.SetAttribute(TARGET_MIN_LEVEL_ATTRIBUTE, logLevel.ToString("G")); + } + + /// + /// Set the target fileName to xml file + /// + /// + public void SetLogFileName(string fileName) + { + logFileNameElement.SetAttribute(LOGGER_FILE_NAME_ATTRIBUTE, fileName); + } + + /// + /// Select a single XML node/elemant + /// + /// + /// + /// + private static XmlNode SelectSingleNode(XmlDocument doc, string xpath) + { + XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable); + manager.AddNamespace("nlog", "http://www.nlog-project.org/schemas/NLog.xsd"); + //return doc.SelectSingleNode("//nlog:logger[(@shadowsocks='managed') and (@name='*')]", manager); + return doc.SelectSingleNode(xpath, manager); + } + + /// + /// Extract the pre-defined NLog configuration file is does not exist. Then reload the Nlog configuration. + /// + public static void TouchAndApplyNLogConfig() + { + if (!File.Exists(NLOG_CONFIG_FILE_NAME)) + { + File.WriteAllText(NLOG_CONFIG_FILE_NAME, Properties.Resources.NLog_config); + LogManager.LoadConfiguration(NLOG_CONFIG_FILE_NAME); + } + } + + /// + /// NLog reload the config file and apply to current LogManager + /// + public static void LoadConfiguration() + { + LogManager.LoadConfiguration(NLOG_CONFIG_FILE_NAME); + } + } +} diff --git a/shadowsocks-csharp/Model/StatisticsStrategyConfiguration.cs b/shadowsocks-csharp/Model/StatisticsStrategyConfiguration.cs index c648027d..e0f3bf2d 100644 --- a/shadowsocks-csharp/Model/StatisticsStrategyConfiguration.cs +++ b/shadowsocks-csharp/Model/StatisticsStrategyConfiguration.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Reflection; using Newtonsoft.Json; - +using NLog; using Shadowsocks.Controller; namespace Shadowsocks.Model @@ -13,6 +13,8 @@ namespace Shadowsocks.Model [Serializable] public class StatisticsStrategyConfiguration { + private static Logger logger = LogManager.GetCurrentClassLogger(); + public static readonly string ID = "com.shadowsocks.strategy.statistics"; public bool StatisticsEnabled { get; set; } = false; public bool ByHourOfDay { get; set; } = true; @@ -39,7 +41,7 @@ namespace Shadowsocks.Model } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); return new StatisticsStrategyConfiguration(); } } @@ -53,7 +55,7 @@ namespace Shadowsocks.Model } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 63485522..e24ab322 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; using System.Threading; using System.Windows.Forms; +using NLog; using Microsoft.Win32; using Shadowsocks.Controller; @@ -14,6 +15,7 @@ namespace Shadowsocks { static class Program { + private static Logger logger = LogManager.GetCurrentClassLogger(); public static ShadowsocksController MainController { get; private set; } public static MenuViewController MenuController { get; private set; } public static string[] Args { get; private set; } @@ -24,6 +26,9 @@ namespace Shadowsocks [STAThread] static void Main(string[] args) { + // todo: initialize the NLog configuartion + Model.NLogConfig.TouchAndApplyNLogConfig(); + // .NET Framework 4.7.2 on Win7 compatibility System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12; @@ -79,7 +84,6 @@ namespace Shadowsocks } Directory.SetCurrentDirectory(Application.StartupPath); - Logging.OpenLogFile(); #if DEBUG // truncate privoxy log file while debugging string privoxyLogFilename = Utils.GetTempPath("privoxy.log"); @@ -89,11 +93,6 @@ namespace Shadowsocks MainController = new ShadowsocksController(); MenuController = new MenuViewController(MainController); - MainController.ProgramUpdated += (o, e) => - { - Logging.Info($"Updated from {e.OldVersion} to {e.NewVersion}"); - }; - HotKeys.Init(MainController); MainController.Start(); Application.Run(); @@ -106,7 +105,7 @@ namespace Shadowsocks if (Interlocked.Increment(ref exited) == 1) { string errMsg = e.ExceptionObject.ToString(); - Logging.Error(errMsg); + logger.Error(errMsg); MessageBox.Show( $"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{errMsg}", "Shadowsocks non-UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error); @@ -119,7 +118,7 @@ namespace Shadowsocks if (Interlocked.Increment(ref exited) == 1) { string errorMsg = $"Exception Detail: {Environment.NewLine}{e.Exception}"; - Logging.Error(errorMsg); + logger.Error(errorMsg); MessageBox.Show( $"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{errorMsg}", "Shadowsocks UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error); @@ -132,7 +131,7 @@ namespace Shadowsocks switch (e.Mode) { case PowerModes.Resume: - Logging.Info("os wake up"); + logger.Info("os wake up"); if (MainController != null) { System.Threading.Tasks.Task.Factory.StartNew(() => @@ -141,11 +140,11 @@ namespace Shadowsocks try { MainController.Start(false); - Logging.Info("controller started"); + logger.Info("controller started"); } catch (Exception ex) { - Logging.LogUsefulException(ex); + logger.LogUsefulException(ex); } }); } @@ -154,9 +153,9 @@ namespace Shadowsocks if (MainController != null) { MainController.Stop(); - Logging.Info("controller stopped"); + logger.Info("controller stopped"); } - Logging.Info("os suspend"); + logger.Info("os suspend"); break; } } diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index dea95e63..bc5b8c24 100644 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -1,91 +1,91 @@ -//------------------------------------------------------------------------------ -// -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 -// -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 -// -//------------------------------------------------------------------------------ - -namespace Shadowsocks.Properties { - using System; - - - /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 - /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// 返回此类使用的缓存的 ResourceManager 实例。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// 重写当前线程的 CurrentUICulture 属性 - /// 重写当前线程的 CurrentUICulture 属性。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// 查找类似 /* eslint-disable */ - ///// Was generated by gfwlist2pac in precise mode - ///// https://github.com/clowwindy/gfwlist2pac - /// - ///// 2019-10-06: More 'javascript' way to interaction with main program - ///// 2019-02-08: Updated to support shadowsocks-windows user rules. - /// - ///var proxy = __PROXY__; - ///var userrules = __USERRULES__; - ///var rules = __RULES__; - /// - ////* - ///* This file is part of Adblock Plus <http://adblockplus.org/>, - ///* Copyright (C) 2006-2014 Eyeo GmbH - ///* - ///* Adblock Plus is free software: you can redistribute it and/or [字符串的其余部分被截断]"; 的本地化字符串。 - /// - internal static string abp_js { - get { - return ResourceManager.GetString("abp_js", resourceCulture); - } - } - - /// - /// 查找类似 var __USERRULES__ = []; +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Shadowsocks.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Shadowsocks.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to /* eslint-disable */ + ///// Was generated by gfwlist2pac in precise mode + ///// https://github.com/clowwindy/gfwlist2pac + /// + ///// 2019-10-06: More 'javascript' way to interaction with main program + ///// 2019-02-08: Updated to support shadowsocks-windows user rules. + /// + ///var proxy = __PROXY__; + ///var userrules = __USERRULES__; + ///var rules = __RULES__; + /// + ////* + ///* This file is part of Adblock Plus <http://adblockplus.org/>, + ///* Copyright (C) 2006-2014 Eyeo GmbH + ///* + ///* Adblock Plus is free software: you can redistribute it and/or [rest of string was truncated]";. + /// + internal static string abp_js { + get { + return ResourceManager.GetString("abp_js", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to var __USERRULES__ = []; ///var __RULES__ = [ /// "|http://85.17.73.31/", /// "||agnesb.fr", @@ -106,154 +106,175 @@ namespace Shadowsocks.Properties { /// "||beeg.com", /// "||global.bing.com", /// "||bloombergview.com", - /// " [字符串的其余部分被截断]"; 的本地化字符串。 - /// - internal static string default_abp_rule { - get { - return ResourceManager.GetString("default_abp_rule", resourceCulture); - } - } - - /// - /// 查找类似 en,zh-CN,zh-TW,ja + /// "||booktopia.com.au", + /// [rest of string was truncated]";. + /// + internal static string default_abp_rule { + get { + return ResourceManager.GetString("default_abp_rule", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to en,zh-CN,zh-TW,ja + ///#Restart program to apply translation,,, + ///#This is comment line,,, + ///#Always keep language name at head of file,,, + ///#Language name is output in log,,, + ///"#You can find it by search ""Current language is:""",,, + ///#Please use UTF-8 with BOM encoding so we can edit it in Excel,,, ///,,, ///Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks ///,,, + ///#Menu,,, + ///,,, ///System Proxy,系统代理,系統代理,システムプロキシ ///Disable,禁用,禁用,無効 ///PAC,PAC 模式,PAC 模式,PAC ///Global,全局模式,全局模式,全般 ///Servers,服务器,伺服器,サーバー - ///Edit Servers...,编辑服务器...,編輯伺服器...,サーバーの編集... - ///Statistics Config...,统计配置...,統計設定檔...,統計情報の設定... - ///Start on Boot,开机启动,開機啟動,システムと同時に起動 - ///Forward Proxy...,正向代理设置...,正向 Proxy 設定...,フォワードプロキシの設定... - ///Allow other Devices to connect,允许其他设备连入,允許其他裝置連入,他のデバイスからの接続を許可する - ///Local PAC,使用本地 PAC,使用本機 PAC,ローカル PAC - ///Online PAC,使用在线 PAC,使 [字符串的其余部分被截断]"; 的本地化字符串。 - /// - internal static string i18n_csv { - get { - return ResourceManager.GetString("i18n_csv", resourceCulture); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] libsscrypto_dll { - get { - object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找类似 listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ - ///toggle 0 - ///logfile ss_privoxy.log - ///show-on-task-bar 0 - ///activity-animation 0 - ///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . - ///max-client-connections 2048 - ///hide-console - /// 的本地化字符串。 - /// - internal static string privoxy_conf { - get { - return ResourceManager.GetString("privoxy_conf", resourceCulture); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] privoxy_exe { - get { - object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap ss32Fill { - get { - object obj = ResourceManager.GetObject("ss32Fill", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap ss32In { - get { - object obj = ResourceManager.GetObject("ss32In", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap ss32Out { - get { - object obj = ResourceManager.GetObject("ss32Out", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap ss32Outline { - get { - object obj = ResourceManager.GetObject("ss32Outline", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap ssw128 { - get { - object obj = ResourceManager.GetObject("ssw128", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] sysproxy_exe { - get { - object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] sysproxy64_exe { - get { - object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找类似 ! Put user rules line by line in this file. - ///! See https://adblockplus.org/en/filter-cheatsheet - /// 的本地化字符串。 - /// - internal static string user_rule { - get { - return ResourceManager.GetString("user_rule", resourceCulture); - } - } - } -} + ///Edit Servers...,编辑服务器...,編輯伺服器...,サーバーの編集.. [rest of string was truncated]";. + /// + internal static string i18n_csv { + get { + return ResourceManager.GetString("i18n_csv", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] libsscrypto_dll { + get { + object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> + ///<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + /// <targets> + /// <target name="file" xsi:type="File" fileName="shadowsocks.log"/> + /// + /// </targets> + /// <rules> + /// <logger name="Name.Space.Class1" minlevel="Debug" writeTo="f1" /> + /// </rules> + ///</nlog>. + /// + internal static string NLog_config { + get { + return ResourceManager.GetString("NLog_config", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ + ///toggle 0 + ///logfile ss_privoxy.log + ///show-on-task-bar 0 + ///activity-animation 0 + ///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . + ///max-client-connections 2048 + ///hide-console + ///. + /// + internal static string privoxy_conf { + get { + return ResourceManager.GetString("privoxy_conf", resourceCulture); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] privoxy_exe { + get { + object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ss32Fill { + get { + object obj = ResourceManager.GetObject("ss32Fill", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ss32In { + get { + object obj = ResourceManager.GetObject("ss32In", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ss32Out { + get { + object obj = ResourceManager.GetObject("ss32Out", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ss32Outline { + get { + object obj = ResourceManager.GetObject("ss32Outline", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ssw128 { + get { + object obj = ResourceManager.GetObject("ssw128", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] sysproxy_exe { + get { + object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] sysproxy64_exe { + get { + object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized string similar to ! Put user rules line by line in this file. + ///! See https://adblockplus.org/en/filter-cheatsheet + ///. + /// + internal static string user_rule { + get { + return ResourceManager.GetString("user_rule", resourceCulture); + } + } + } +} diff --git a/shadowsocks-csharp/Properties/Resources.resx b/shadowsocks-csharp/Properties/Resources.resx index 9661ee9a..99f2c596 100755 --- a/shadowsocks-csharp/Properties/Resources.resx +++ b/shadowsocks-csharp/Properties/Resources.resx @@ -130,6 +130,9 @@ ..\Data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\data\nlog.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + ..\data\privoxy_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 diff --git a/shadowsocks-csharp/Proxy/HttpProxy.cs b/shadowsocks-csharp/Proxy/HttpProxy.cs index b7d671a6..ecf7dc89 100644 --- a/shadowsocks-csharp/Proxy/HttpProxy.cs +++ b/shadowsocks-csharp/Proxy/HttpProxy.cs @@ -4,6 +4,7 @@ using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; using System.Threading; +using NLog; using Shadowsocks.Controller; using Shadowsocks.Util.Sockets; @@ -11,6 +12,8 @@ namespace Shadowsocks.Proxy { public class HttpProxy : IProxy { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private class FakeAsyncResult : IAsyncResult { public readonly HttpState innerState; @@ -179,7 +182,7 @@ namespace Shadowsocks.Proxy private bool OnLineRead(string line, object state) { - Logging.Debug(line); + logger.Debug(line); if (_respondLineCount == 0) { diff --git a/shadowsocks-csharp/Util/ProcessManagement/Job.cs b/shadowsocks-csharp/Util/ProcessManagement/Job.cs index dd82134d..bb05dccb 100644 --- a/shadowsocks-csharp/Util/ProcessManagement/Job.cs +++ b/shadowsocks-csharp/Util/ProcessManagement/Job.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; +using NLog; using Shadowsocks.Controller; namespace Shadowsocks.Util.ProcessManagement @@ -11,6 +12,8 @@ namespace Shadowsocks.Util.ProcessManagement */ public class Job : IDisposable { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private IntPtr handle = IntPtr.Zero; public Job() @@ -54,7 +57,7 @@ namespace Shadowsocks.Util.ProcessManagement if (!succ) { - Logging.Error("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); + logger.Error("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); } return succ; diff --git a/shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs b/shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs index 863be1df..b1ffcac4 100644 --- a/shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs +++ b/shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using NLog; using Shadowsocks.Controller; using Shadowsocks.Model; using Shadowsocks.Properties; @@ -14,6 +15,8 @@ namespace Shadowsocks.Util.SystemProxy { public static class Sysproxy { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private const string _userWininetConfigFile = "user-wininet.json"; private readonly static string[] _lanIP = { @@ -70,7 +73,7 @@ namespace Shadowsocks.Util.SystemProxy } catch (IOException e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } @@ -233,7 +236,7 @@ namespace Shadowsocks.Util.SystemProxy } catch (IOException e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); } } diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index 56f1e0b1..8912eb68 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -1,4 +1,5 @@ -using System; +using NLog; +using System; using System.Diagnostics; using System.IO; using System.IO.Compression; @@ -26,6 +27,8 @@ namespace Shadowsocks.Util public static class Utils { + private static Logger logger = LogManager.GetCurrentClassLogger(); + private static string _tempPath = null; // return path to store temporary files @@ -48,7 +51,7 @@ namespace Shadowsocks.Util } catch (Exception e) { - Logging.Error(e); + logger.Error(e); throw; } } @@ -58,7 +61,7 @@ namespace Shadowsocks.Util public enum WindowsThemeMode { Dark, Light } // Support on Windows 10 1903+ - public static WindowsThemeMode GetWindows10SystemThemeSetting(bool isVerbose) + public static WindowsThemeMode GetWindows10SystemThemeSetting() { WindowsThemeMode themeMode = WindowsThemeMode.Dark; try @@ -78,11 +81,10 @@ namespace Shadowsocks.Util } catch { - if (isVerbose) - { - Logging.Info( - $"Cannot get Windows 10 system theme mode, return default value 0 (dark mode)."); - } + + logger.Debug( + $"Cannot get Windows 10 system theme mode, return default value 0 (dark mode)."); + } return themeMode; } @@ -251,7 +253,7 @@ namespace Shadowsocks.Util } catch (Exception e) { - Logging.LogUsefulException(e); + logger.LogUsefulException(e); return null; } } diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index fafbca48..bc21915a 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -106,10 +106,10 @@ this.tableLayoutPanel1.Controls.Add(this.PluginArgumentsLabel, 0, 8); this.tableLayoutPanel1.Controls.Add(this.RemarksLabel, 0, 10); this.tableLayoutPanel1.Controls.Add(this.NeedPluginArgCheckBox, 1, 7); - this.tableLayoutPanel1.Location = new System.Drawing.Point(8, 21); + this.tableLayoutPanel1.Location = new System.Drawing.Point(10, 26); this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3); + this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(4); this.tableLayoutPanel1.RowCount = 12; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -123,16 +123,17 @@ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(279, 292); + this.tableLayoutPanel1.Size = new System.Drawing.Size(394, 357); this.tableLayoutPanel1.TabIndex = 0; // // PluginOptionsLabel // this.PluginOptionsLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PluginOptionsLabel.AutoSize = true; - this.PluginOptionsLabel.Location = new System.Drawing.Point(18, 166); + this.PluginOptionsLabel.Location = new System.Drawing.Point(24, 203); + this.PluginOptionsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PluginOptionsLabel.Name = "PluginOptionsLabel"; - this.PluginOptionsLabel.Size = new System.Drawing.Size(89, 12); + this.PluginOptionsLabel.Size = new System.Drawing.Size(119, 15); this.PluginOptionsLabel.TabIndex = 6; this.PluginOptionsLabel.Text = "Plugin Options"; this.toolTip1.SetToolTip(this.PluginOptionsLabel, "Environment variables for plugin program"); @@ -140,20 +141,22 @@ // PluginTextBox // this.PluginTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.PluginTextBox.Location = new System.Drawing.Point(113, 135); + this.PluginTextBox.Location = new System.Drawing.Point(151, 165); + this.PluginTextBox.Margin = new System.Windows.Forms.Padding(4); this.PluginTextBox.MaxLength = 256; this.PluginTextBox.Name = "PluginTextBox"; - this.PluginTextBox.Size = new System.Drawing.Size(160, 21); + this.PluginTextBox.Size = new System.Drawing.Size(235, 25); this.PluginTextBox.TabIndex = 5; this.PluginTextBox.WordWrap = false; // // RemarksTextBox // this.RemarksTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.RemarksTextBox.Location = new System.Drawing.Point(113, 238); + this.RemarksTextBox.Location = new System.Drawing.Point(151, 291); + this.RemarksTextBox.Margin = new System.Windows.Forms.Padding(4); this.RemarksTextBox.MaxLength = 32; this.RemarksTextBox.Name = "RemarksTextBox"; - this.RemarksTextBox.Size = new System.Drawing.Size(160, 21); + this.RemarksTextBox.Size = new System.Drawing.Size(235, 25); this.RemarksTextBox.TabIndex = 8; this.RemarksTextBox.WordWrap = false; // @@ -161,9 +164,10 @@ // this.IPLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.IPLabel.AutoSize = true; - this.IPLabel.Location = new System.Drawing.Point(48, 10); + this.IPLabel.Location = new System.Drawing.Point(64, 13); + this.IPLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.IPLabel.Name = "IPLabel"; - this.IPLabel.Size = new System.Drawing.Size(59, 12); + this.IPLabel.Size = new System.Drawing.Size(79, 15); this.IPLabel.TabIndex = 0; this.IPLabel.Text = "Server IP"; // @@ -171,9 +175,10 @@ // this.ServerPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.ServerPortLabel.AutoSize = true; - this.ServerPortLabel.Location = new System.Drawing.Point(36, 37); + this.ServerPortLabel.Location = new System.Drawing.Point(48, 46); + this.ServerPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.ServerPortLabel.Name = "ServerPortLabel"; - this.ServerPortLabel.Size = new System.Drawing.Size(71, 12); + this.ServerPortLabel.Size = new System.Drawing.Size(95, 15); this.ServerPortLabel.TabIndex = 1; this.ServerPortLabel.Text = "Server Port"; // @@ -181,9 +186,10 @@ // this.PasswordLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PasswordLabel.AutoSize = true; - this.PasswordLabel.Location = new System.Drawing.Point(54, 64); + this.PasswordLabel.Location = new System.Drawing.Point(72, 79); + this.PasswordLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PasswordLabel.Name = "PasswordLabel"; - this.PasswordLabel.Size = new System.Drawing.Size(53, 12); + this.PasswordLabel.Size = new System.Drawing.Size(71, 15); this.PasswordLabel.TabIndex = 2; this.PasswordLabel.Text = "Password"; this.PasswordLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -191,30 +197,34 @@ // IPTextBox // this.IPTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.IPTextBox.Location = new System.Drawing.Point(113, 6); + this.IPTextBox.Location = new System.Drawing.Point(151, 8); + this.IPTextBox.Margin = new System.Windows.Forms.Padding(4); this.IPTextBox.MaxLength = 512; this.IPTextBox.Name = "IPTextBox"; - this.IPTextBox.Size = new System.Drawing.Size(160, 21); + this.IPTextBox.Size = new System.Drawing.Size(235, 25); this.IPTextBox.TabIndex = 0; this.IPTextBox.WordWrap = false; // // ServerPortTextBox // this.ServerPortTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.ServerPortTextBox.Location = new System.Drawing.Point(113, 33); + this.ServerPortTextBox.Location = new System.Drawing.Point(151, 41); + this.ServerPortTextBox.Margin = new System.Windows.Forms.Padding(4); this.ServerPortTextBox.MaxLength = 10; this.ServerPortTextBox.Name = "ServerPortTextBox"; - this.ServerPortTextBox.Size = new System.Drawing.Size(160, 21); + this.ServerPortTextBox.Size = new System.Drawing.Size(235, 25); this.ServerPortTextBox.TabIndex = 1; this.ServerPortTextBox.WordWrap = false; // // PasswordTextBox // this.PasswordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.PasswordTextBox.Location = new System.Drawing.Point(113, 60); + this.PasswordTextBox.Font = new System.Drawing.Font("Consolas", 9F); + this.PasswordTextBox.Location = new System.Drawing.Point(151, 74); + this.PasswordTextBox.Margin = new System.Windows.Forms.Padding(4); this.PasswordTextBox.MaxLength = 256; this.PasswordTextBox.Name = "PasswordTextBox"; - this.PasswordTextBox.Size = new System.Drawing.Size(160, 21); + this.PasswordTextBox.Size = new System.Drawing.Size(235, 25); this.PasswordTextBox.TabIndex = 2; this.PasswordTextBox.UseSystemPasswordChar = true; this.PasswordTextBox.WordWrap = false; @@ -223,9 +233,10 @@ // this.EncryptionLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.EncryptionLabel.AutoSize = true; - this.EncryptionLabel.Location = new System.Drawing.Point(42, 113); + this.EncryptionLabel.Location = new System.Drawing.Point(56, 138); + this.EncryptionLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.EncryptionLabel.Name = "EncryptionLabel"; - this.EncryptionLabel.Size = new System.Drawing.Size(65, 12); + this.EncryptionLabel.Size = new System.Drawing.Size(87, 15); this.EncryptionLabel.TabIndex = 4; this.EncryptionLabel.Text = "Encryption"; // @@ -236,69 +247,54 @@ this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.EncryptionSelect.FormattingEnabled = true; this.EncryptionSelect.ImeMode = System.Windows.Forms.ImeMode.NoControl; - this.EncryptionSelect.ItemHeight = 12; - this.EncryptionSelect.Items.AddRange(new object[] { - "rc4-md5", - "salsa20", - "chacha20", - "chacha20-ietf", - "aes-256-cfb", - "aes-192-cfb", - "aes-128-cfb", - "aes-256-ctr", - "aes-192-ctr", - "aes-128-ctr", - "bf-cfb", - "camellia-128-cfb", - "camellia-192-cfb", - "camellia-256-cfb", - "aes-128-gcm", - "aes-192-gcm", - "aes-256-gcm", - "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305"}); - this.EncryptionSelect.Location = new System.Drawing.Point(113, 109); + this.EncryptionSelect.ItemHeight = 15; + this.EncryptionSelect.Location = new System.Drawing.Point(151, 134); + this.EncryptionSelect.Margin = new System.Windows.Forms.Padding(4); this.EncryptionSelect.Name = "EncryptionSelect"; - this.EncryptionSelect.Size = new System.Drawing.Size(160, 20); + this.EncryptionSelect.Size = new System.Drawing.Size(235, 23); this.EncryptionSelect.TabIndex = 4; // // TimeoutLabel // this.TimeoutLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.TimeoutLabel.AutoSize = true; - this.TimeoutLabel.Location = new System.Drawing.Point(30, 269); + this.TimeoutLabel.Location = new System.Drawing.Point(40, 329); + this.TimeoutLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.TimeoutLabel.Name = "TimeoutLabel"; this.TimeoutLabel.RightToLeft = System.Windows.Forms.RightToLeft.No; - this.TimeoutLabel.Size = new System.Drawing.Size(77, 12); + this.TimeoutLabel.Size = new System.Drawing.Size(103, 15); this.TimeoutLabel.TabIndex = 9; this.TimeoutLabel.Text = "Timeout(Sec)"; // // TimeoutTextBox // this.TimeoutTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.TimeoutTextBox.Location = new System.Drawing.Point(113, 265); + this.TimeoutTextBox.Location = new System.Drawing.Point(151, 324); + this.TimeoutTextBox.Margin = new System.Windows.Forms.Padding(4); this.TimeoutTextBox.MaxLength = 5; this.TimeoutTextBox.Name = "TimeoutTextBox"; - this.TimeoutTextBox.Size = new System.Drawing.Size(160, 21); + this.TimeoutTextBox.Size = new System.Drawing.Size(235, 25); this.TimeoutTextBox.TabIndex = 9; // // PluginLabel // this.PluginLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PluginLabel.AutoSize = true; - this.PluginLabel.Location = new System.Drawing.Point(18, 139); + this.PluginLabel.Location = new System.Drawing.Point(24, 170); + this.PluginLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PluginLabel.Name = "PluginLabel"; - this.PluginLabel.Size = new System.Drawing.Size(89, 12); + this.PluginLabel.Size = new System.Drawing.Size(119, 15); this.PluginLabel.TabIndex = 5; this.PluginLabel.Text = "Plugin Program"; // // PluginOptionsTextBox // this.PluginOptionsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.PluginOptionsTextBox.Location = new System.Drawing.Point(113, 162); + this.PluginOptionsTextBox.Location = new System.Drawing.Point(151, 198); + this.PluginOptionsTextBox.Margin = new System.Windows.Forms.Padding(4); this.PluginOptionsTextBox.MaxLength = 256; this.PluginOptionsTextBox.Name = "PluginOptionsTextBox"; - this.PluginOptionsTextBox.Size = new System.Drawing.Size(160, 21); + this.PluginOptionsTextBox.Size = new System.Drawing.Size(235, 25); this.PluginOptionsTextBox.TabIndex = 6; this.PluginOptionsTextBox.WordWrap = false; // @@ -307,9 +303,10 @@ this.ShowPasswdCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left))); this.ShowPasswdCheckBox.AutoSize = true; - this.ShowPasswdCheckBox.Location = new System.Drawing.Point(113, 87); + this.ShowPasswdCheckBox.Location = new System.Drawing.Point(151, 107); + this.ShowPasswdCheckBox.Margin = new System.Windows.Forms.Padding(4); this.ShowPasswdCheckBox.Name = "ShowPasswdCheckBox"; - this.ShowPasswdCheckBox.Size = new System.Drawing.Size(102, 16); + this.ShowPasswdCheckBox.Size = new System.Drawing.Size(133, 19); this.ShowPasswdCheckBox.TabIndex = 3; this.ShowPasswdCheckBox.Text = "Show Password"; this.ShowPasswdCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -319,10 +316,11 @@ // PluginArgumentsTextBox // this.PluginArgumentsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.PluginArgumentsTextBox.Location = new System.Drawing.Point(113, 211); + this.PluginArgumentsTextBox.Location = new System.Drawing.Point(151, 258); + this.PluginArgumentsTextBox.Margin = new System.Windows.Forms.Padding(4); this.PluginArgumentsTextBox.MaxLength = 512; this.PluginArgumentsTextBox.Name = "PluginArgumentsTextBox"; - this.PluginArgumentsTextBox.Size = new System.Drawing.Size(160, 21); + this.PluginArgumentsTextBox.Size = new System.Drawing.Size(235, 25); this.PluginArgumentsTextBox.TabIndex = 7; this.PluginArgumentsTextBox.WordWrap = false; // @@ -330,9 +328,10 @@ // this.PluginArgumentsLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PluginArgumentsLabel.AutoSize = true; - this.PluginArgumentsLabel.Location = new System.Drawing.Point(6, 215); + this.PluginArgumentsLabel.Location = new System.Drawing.Point(8, 263); + this.PluginArgumentsLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PluginArgumentsLabel.Name = "PluginArgumentsLabel"; - this.PluginArgumentsLabel.Size = new System.Drawing.Size(101, 12); + this.PluginArgumentsLabel.Size = new System.Drawing.Size(135, 15); this.PluginArgumentsLabel.TabIndex = 7; this.PluginArgumentsLabel.Text = "Plugin Arguments"; this.toolTip1.SetToolTip(this.PluginArgumentsLabel, "Not a SIP003 standard. Used as CLI arguments.\r\nMandatory:\r\n%SS_LOCAL_HOST%, %SS_L" + @@ -342,18 +341,20 @@ // this.RemarksLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.RemarksLabel.AutoSize = true; - this.RemarksLabel.Location = new System.Drawing.Point(60, 242); + this.RemarksLabel.Location = new System.Drawing.Point(80, 296); + this.RemarksLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.RemarksLabel.Name = "RemarksLabel"; - this.RemarksLabel.Size = new System.Drawing.Size(47, 12); + this.RemarksLabel.Size = new System.Drawing.Size(63, 15); this.RemarksLabel.TabIndex = 8; this.RemarksLabel.Text = "Remarks"; // // NeedPluginArgCheckBox // this.NeedPluginArgCheckBox.AutoSize = true; - this.NeedPluginArgCheckBox.Location = new System.Drawing.Point(113, 189); + this.NeedPluginArgCheckBox.Location = new System.Drawing.Point(151, 231); + this.NeedPluginArgCheckBox.Margin = new System.Windows.Forms.Padding(4); this.NeedPluginArgCheckBox.Name = "NeedPluginArgCheckBox"; - this.NeedPluginArgCheckBox.Size = new System.Drawing.Size(144, 16); + this.NeedPluginArgCheckBox.Size = new System.Drawing.Size(189, 19); this.NeedPluginArgCheckBox.TabIndex = 10; this.NeedPluginArgCheckBox.Text = "Need Plugin Argument"; this.NeedPluginArgCheckBox.UseVisualStyleBackColor = true; @@ -364,7 +365,8 @@ this.panel2.Anchor = System.Windows.Forms.AnchorStyles.Top; this.panel2.AutoSize = true; this.panel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.panel2.Location = new System.Drawing.Point(165, 187); + this.panel2.Location = new System.Drawing.Point(206, 234); + this.panel2.Margin = new System.Windows.Forms.Padding(4); this.panel2.Name = "panel2"; this.panel2.Size = new System.Drawing.Size(0, 0); this.panel2.TabIndex = 1; @@ -373,10 +375,10 @@ // this.OKButton.DialogResult = System.Windows.Forms.DialogResult.OK; this.OKButton.Dock = System.Windows.Forms.DockStyle.Right; - this.OKButton.Location = new System.Drawing.Point(3, 3); - this.OKButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0); + this.OKButton.Location = new System.Drawing.Point(4, 4); + this.OKButton.Margin = new System.Windows.Forms.Padding(4, 4, 4, 0); this.OKButton.Name = "OKButton"; - this.OKButton.Size = new System.Drawing.Size(75, 23); + this.OKButton.Size = new System.Drawing.Size(94, 29); this.OKButton.TabIndex = 17; this.OKButton.Text = "OK"; this.OKButton.UseVisualStyleBackColor = true; @@ -386,10 +388,10 @@ // this.MyCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.MyCancelButton.Dock = System.Windows.Forms.DockStyle.Right; - this.MyCancelButton.Location = new System.Drawing.Point(84, 3); - this.MyCancelButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0); + this.MyCancelButton.Location = new System.Drawing.Point(106, 4); + this.MyCancelButton.Margin = new System.Windows.Forms.Padding(4, 4, 4, 0); this.MyCancelButton.Name = "MyCancelButton"; - this.MyCancelButton.Size = new System.Drawing.Size(75, 23); + this.MyCancelButton.Size = new System.Drawing.Size(94, 29); this.MyCancelButton.TabIndex = 18; this.MyCancelButton.Text = "Cancel"; this.MyCancelButton.UseVisualStyleBackColor = true; @@ -399,10 +401,10 @@ // this.ApplyButton.Dock = System.Windows.Forms.DockStyle.Right; this.ApplyButton.Enabled = false; - this.ApplyButton.Location = new System.Drawing.Point(165, 3); - this.ApplyButton.Margin = new System.Windows.Forms.Padding(3, 3, 0, 0); + this.ApplyButton.Location = new System.Drawing.Point(208, 4); + this.ApplyButton.Margin = new System.Windows.Forms.Padding(4, 4, 0, 0); this.ApplyButton.Name = "ApplyButton"; - this.ApplyButton.Size = new System.Drawing.Size(75, 23); + this.ApplyButton.Size = new System.Drawing.Size(94, 29); this.ApplyButton.TabIndex = 19; this.ApplyButton.Text = "Apply"; this.ApplyButton.UseVisualStyleBackColor = true; @@ -411,10 +413,10 @@ // DeleteButton // this.DeleteButton.Dock = System.Windows.Forms.DockStyle.Right; - this.DeleteButton.Location = new System.Drawing.Point(86, 6); - this.DeleteButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3); + this.DeleteButton.Location = new System.Drawing.Point(108, 8); + this.DeleteButton.Margin = new System.Windows.Forms.Padding(4, 8, 0, 4); this.DeleteButton.Name = "DeleteButton"; - this.DeleteButton.Size = new System.Drawing.Size(80, 23); + this.DeleteButton.Size = new System.Drawing.Size(100, 29); this.DeleteButton.TabIndex = 13; this.DeleteButton.Text = "&Delete"; this.DeleteButton.UseVisualStyleBackColor = true; @@ -423,10 +425,10 @@ // AddButton // this.AddButton.Dock = System.Windows.Forms.DockStyle.Left; - this.AddButton.Location = new System.Drawing.Point(0, 6); - this.AddButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3); + this.AddButton.Location = new System.Drawing.Point(0, 8); + this.AddButton.Margin = new System.Windows.Forms.Padding(0, 8, 4, 4); this.AddButton.Name = "AddButton"; - this.AddButton.Size = new System.Drawing.Size(80, 23); + this.AddButton.Size = new System.Drawing.Size(100, 29); this.AddButton.TabIndex = 12; this.AddButton.Text = "&Add"; this.AddButton.UseVisualStyleBackColor = true; @@ -437,10 +439,11 @@ this.ServerGroupBox.AutoSize = true; this.ServerGroupBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.ServerGroupBox.Controls.Add(this.tableLayoutPanel1); - this.ServerGroupBox.Location = new System.Drawing.Point(178, 0); - this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(12, 0, 0, 0); + this.ServerGroupBox.Location = new System.Drawing.Point(223, 0); + this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(15, 0, 0, 0); this.ServerGroupBox.Name = "ServerGroupBox"; - this.ServerGroupBox.Size = new System.Drawing.Size(290, 330); + this.ServerGroupBox.Padding = new System.Windows.Forms.Padding(4); + this.ServerGroupBox.Size = new System.Drawing.Size(408, 405); this.ServerGroupBox.TabIndex = 0; this.ServerGroupBox.TabStop = false; this.ServerGroupBox.Text = "Server"; @@ -449,11 +452,11 @@ // this.ServersListBox.FormattingEnabled = true; this.ServersListBox.IntegralHeight = false; - this.ServersListBox.ItemHeight = 12; + this.ServersListBox.ItemHeight = 15; this.ServersListBox.Location = new System.Drawing.Point(0, 0); this.ServersListBox.Margin = new System.Windows.Forms.Padding(0); this.ServersListBox.Name = "ServersListBox"; - this.ServersListBox.Size = new System.Drawing.Size(166, 148); + this.ServersListBox.Size = new System.Drawing.Size(206, 184); this.ServersListBox.TabIndex = 11; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // @@ -470,14 +473,14 @@ this.tableLayoutPanel2.Controls.Add(this.ServersListBox, 0, 0); this.tableLayoutPanel2.Controls.Add(this.ServerGroupBox, 1, 0); this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel4, 0, 1); - this.tableLayoutPanel2.Location = new System.Drawing.Point(12, 12); + this.tableLayoutPanel2.Location = new System.Drawing.Point(15, 15); this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 3; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel2.Size = new System.Drawing.Size(468, 426); + this.tableLayoutPanel2.Size = new System.Drawing.Size(631, 528); this.tableLayoutPanel2.TabIndex = 7; // // tableLayoutPanel6 @@ -490,21 +493,21 @@ this.tableLayoutPanel6.Controls.Add(this.MoveDownButton, 1, 0); this.tableLayoutPanel6.Controls.Add(this.MoveUpButton, 0, 0); this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 394); + this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 487); this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel6.Name = "tableLayoutPanel6"; this.tableLayoutPanel6.RowCount = 1; this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel6.Size = new System.Drawing.Size(166, 32); + this.tableLayoutPanel6.Size = new System.Drawing.Size(208, 41); this.tableLayoutPanel6.TabIndex = 10; // // MoveDownButton // this.MoveDownButton.Dock = System.Windows.Forms.DockStyle.Right; - this.MoveDownButton.Location = new System.Drawing.Point(86, 6); - this.MoveDownButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3); + this.MoveDownButton.Location = new System.Drawing.Point(108, 8); + this.MoveDownButton.Margin = new System.Windows.Forms.Padding(4, 8, 0, 4); this.MoveDownButton.Name = "MoveDownButton"; - this.MoveDownButton.Size = new System.Drawing.Size(80, 23); + this.MoveDownButton.Size = new System.Drawing.Size(100, 29); this.MoveDownButton.TabIndex = 16; this.MoveDownButton.Text = "Move D&own"; this.MoveDownButton.UseVisualStyleBackColor = true; @@ -513,10 +516,10 @@ // MoveUpButton // this.MoveUpButton.Dock = System.Windows.Forms.DockStyle.Left; - this.MoveUpButton.Location = new System.Drawing.Point(0, 6); - this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3); + this.MoveUpButton.Location = new System.Drawing.Point(0, 8); + this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 8, 4, 4); this.MoveUpButton.Name = "MoveUpButton"; - this.MoveUpButton.Size = new System.Drawing.Size(80, 23); + this.MoveUpButton.Size = new System.Drawing.Size(100, 29); this.MoveUpButton.TabIndex = 15; this.MoveUpButton.Text = "Move &Up"; this.MoveUpButton.UseVisualStyleBackColor = true; @@ -534,23 +537,24 @@ this.tableLayoutPanel5.Controls.Add(this.ProxyPortTextBox, 1, 0); this.tableLayoutPanel5.Controls.Add(this.ProxyPortLabel, 0, 0); this.tableLayoutPanel5.Controls.Add(this.PortableModeCheckBox, 0, 1); - this.tableLayoutPanel5.Location = new System.Drawing.Point(166, 330); + this.tableLayoutPanel5.Location = new System.Drawing.Point(208, 405); this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel5.Name = "tableLayoutPanel5"; - this.tableLayoutPanel5.Padding = new System.Windows.Forms.Padding(3); + this.tableLayoutPanel5.Padding = new System.Windows.Forms.Padding(4); this.tableLayoutPanel5.RowCount = 2; this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel5.Size = new System.Drawing.Size(196, 64); + this.tableLayoutPanel5.Size = new System.Drawing.Size(251, 82); this.tableLayoutPanel5.TabIndex = 9; // // ProxyPortTextBox // this.ProxyPortTextBox.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.ProxyPortTextBox.Location = new System.Drawing.Point(77, 6); + this.ProxyPortTextBox.Location = new System.Drawing.Point(103, 8); + this.ProxyPortTextBox.Margin = new System.Windows.Forms.Padding(4); this.ProxyPortTextBox.MaxLength = 10; this.ProxyPortTextBox.Name = "ProxyPortTextBox"; - this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 21); + this.ProxyPortTextBox.Size = new System.Drawing.Size(140, 25); this.ProxyPortTextBox.TabIndex = 10; this.ProxyPortTextBox.WordWrap = false; // @@ -558,9 +562,10 @@ // this.ProxyPortLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; this.ProxyPortLabel.AutoSize = true; - this.ProxyPortLabel.Location = new System.Drawing.Point(6, 10); + this.ProxyPortLabel.Location = new System.Drawing.Point(8, 13); + this.ProxyPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.ProxyPortLabel.Name = "ProxyPortLabel"; - this.ProxyPortLabel.Size = new System.Drawing.Size(65, 12); + this.ProxyPortLabel.Size = new System.Drawing.Size(87, 15); this.ProxyPortLabel.TabIndex = 10; this.ProxyPortLabel.Text = "Proxy Port"; // @@ -569,9 +574,10 @@ this.PortableModeCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; this.PortableModeCheckBox.AutoSize = true; this.tableLayoutPanel5.SetColumnSpan(this.PortableModeCheckBox, 2); - this.PortableModeCheckBox.Location = new System.Drawing.Point(6, 37); + this.PortableModeCheckBox.Location = new System.Drawing.Point(8, 48); + this.PortableModeCheckBox.Margin = new System.Windows.Forms.Padding(4); this.PortableModeCheckBox.Name = "PortableModeCheckBox"; - this.PortableModeCheckBox.Size = new System.Drawing.Size(102, 16); + this.PortableModeCheckBox.Size = new System.Drawing.Size(133, 19); this.PortableModeCheckBox.TabIndex = 11; this.PortableModeCheckBox.Text = "Portable Mode"; this.toolTip1.SetToolTip(this.PortableModeCheckBox, "restart required"); @@ -585,17 +591,17 @@ this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0); this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0); this.tableLayoutPanel3.Controls.Add(this.ApplyButton, 2, 0); this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right; - this.tableLayoutPanel3.Location = new System.Drawing.Point(228, 397); - this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3); + this.tableLayoutPanel3.Location = new System.Drawing.Point(329, 491); + this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(4, 4, 0, 4); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 1; this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel3.Size = new System.Drawing.Size(240, 26); + this.tableLayoutPanel3.Size = new System.Drawing.Size(302, 33); this.tableLayoutPanel3.TabIndex = 8; // // tableLayoutPanel4 @@ -609,22 +615,22 @@ this.tableLayoutPanel4.Controls.Add(this.DeleteButton, 1, 0); this.tableLayoutPanel4.Controls.Add(this.AddButton, 0, 0); this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 330); + this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 405); this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel4.Name = "tableLayoutPanel4"; this.tableLayoutPanel4.RowCount = 2; this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel4.Size = new System.Drawing.Size(166, 64); + this.tableLayoutPanel4.Size = new System.Drawing.Size(208, 82); this.tableLayoutPanel4.TabIndex = 8; // // DuplicateButton // this.DuplicateButton.Dock = System.Windows.Forms.DockStyle.Left; - this.DuplicateButton.Location = new System.Drawing.Point(0, 38); - this.DuplicateButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3); + this.DuplicateButton.Location = new System.Drawing.Point(0, 49); + this.DuplicateButton.Margin = new System.Windows.Forms.Padding(0, 8, 4, 4); this.DuplicateButton.Name = "DuplicateButton"; - this.DuplicateButton.Size = new System.Drawing.Size(80, 23); + this.DuplicateButton.Size = new System.Drawing.Size(100, 29); this.DuplicateButton.TabIndex = 14; this.DuplicateButton.Text = "Dupli&cate"; this.DuplicateButton.UseVisualStyleBackColor = true; @@ -633,19 +639,20 @@ // ConfigForm // this.AcceptButton = this.OKButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.CancelButton = this.MyCancelButton; - this.ClientSize = new System.Drawing.Size(491, 438); + this.ClientSize = new System.Drawing.Size(614, 548); this.Controls.Add(this.tableLayoutPanel2); this.Controls.Add(this.panel2); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Margin = new System.Windows.Forms.Padding(4); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "ConfigForm"; - this.Padding = new System.Windows.Forms.Padding(12, 12, 12, 9); + this.Padding = new System.Windows.Forms.Padding(15, 15, 15, 11); this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Edit Servers"; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ConfigForm_FormClosed); diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 379edc29..caab2f6d 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -2,7 +2,9 @@ using Shadowsocks.Controller; using Shadowsocks.Model; using Shadowsocks.Properties; using System; +using System.Collections.Generic; using System.Drawing; +using System.Linq; using System.Windows.Forms; namespace Shadowsocks.View @@ -17,10 +19,86 @@ namespace Shadowsocks.View private bool isChange = false; + private class EncryptionMethod + { + public readonly string name; + public readonly bool deprecated; + + // Edit here to add/delete encryption method displayed in UI + private static string[] deprecatedMethod = new string[] + { + "rc4-md5", + "salsa20", + "chacha20", + "bf-cfb", + "chacha20-ietf", + "aes-256-cfb", + "aes-192-cfb", + "aes-128-cfb", + "aes-256-ctr", + "aes-192-ctr", + "aes-128-ctr", + "camellia-256-cfb", + "camellia-192-cfb", + "camellia-128-cfb", + }; + private static string[] inuseMethod = new string[] + { + "aes-256-gcm", + "aes-192-gcm", + "aes-128-gcm", + "chacha20-ietf-poly1305", + "xchacha20-ietf-poly1305", + }; + public static EncryptionMethod[] AllMethods + { + get + { + if (!init) Init(); + return allMethods; + } + } + private static bool init = false; + private static EncryptionMethod[] allMethods; + private static Dictionary methodByName = new Dictionary(); + private static void Init() + { + var all = new List(); + + all.AddRange(inuseMethod.Select(i => new EncryptionMethod(i, false))); + all.AddRange(deprecatedMethod.Select(d => new EncryptionMethod(d, true))); + + allMethods = all.ToArray(); + foreach (var item in all) + { + methodByName[item.name] = item; + } + init = true; + } + + public static EncryptionMethod GetMethod(string name) + { + if (!init) Init(); + return methodByName[name]; + } + + private EncryptionMethod(string name, bool deprecated) + { + this.name = name; + this.deprecated = deprecated; + } + + public override string ToString() + { + return deprecated ? $"{name} ({I18N.GetString("deprecated")})" : name; + } + } + public ConfigForm(ShadowsocksController controller) { Font = SystemFonts.MessageBoxFont; InitializeComponent(); + EncryptionSelect.Items.AddRange(EncryptionMethod.AllMethods); // a dirty hack ServersListBox.Dock = DockStyle.Fill; @@ -115,7 +193,7 @@ namespace Shadowsocks.View server = address, server_port = addressPort.Value, password = serverPassword, - method = EncryptionSelect.Text, + method = ((EncryptionMethod)EncryptionSelect.SelectedItem).name, plugin = PluginTextBox.Text, plugin_opts = PluginOptionsTextBox.Text, plugin_args = PluginArgumentsTextBox.Text, @@ -316,7 +394,7 @@ namespace Shadowsocks.View IPTextBox.Text = server.server; ServerPortTextBox.Text = server.server_port.ToString(); PasswordTextBox.Text = server.password; - EncryptionSelect.Text = server.method ?? Server.DefaultMethod; + EncryptionSelect.SelectedItem = EncryptionMethod.GetMethod(server.method ?? Server.DefaultMethod); PluginTextBox.Text = server.plugin; PluginOptionsTextBox.Text = server.plugin_opts; PluginArgumentsTextBox.Text = server.plugin_args; diff --git a/shadowsocks-csharp/View/LogForm.cs b/shadowsocks-csharp/View/LogForm.cs index ba4e76cf..06b0f678 100644 --- a/shadowsocks-csharp/View/LogForm.cs +++ b/shadowsocks-csharp/View/LogForm.cs @@ -11,11 +11,14 @@ using Shadowsocks.Properties; using Shadowsocks.Model; using Shadowsocks.Util; using System.Text; +using NLog; namespace Shadowsocks.View { public partial class LogForm : Form { + private static Logger logger = LogManager.GetCurrentClassLogger(); + long lastOffset; string filename; Timer timer; @@ -38,13 +41,27 @@ namespace Shadowsocks.View TextAnnotation outboundAnnotation = new TextAnnotation(); #endregion - public LogForm(ShadowsocksController controller, string filename) + public LogForm(ShadowsocksController controller) { this.controller = controller; - this.filename = filename; + InitializeComponent(); Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); + var nLogConfig = NLogConfig.LoadXML(); + try + { + this.filename = nLogConfig.GetLogFileName(); + } + catch(Exception) + { + // failed to get the file name + } + if (string.IsNullOrEmpty(this.filename)) + { + LogMessageTextBox.AppendText("Cannot get the log file name from NLog config file. Please check if the nlog config file exists with corresponding XML nodes."); + } + LogViewerConfig config = controller.GetConfigurationCopy().logViewer; topMostTrigger = config.topMost; @@ -158,6 +175,8 @@ namespace Shadowsocks.View private void InitContent() { + if (string.IsNullOrEmpty(filename) || !File.Exists(filename)) + return; using (StreamReader reader = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) { @@ -170,7 +189,7 @@ namespace Shadowsocks.View string line = ""; StringBuilder appendText = new StringBuilder(1024); while ((line = reader.ReadLine()) != null) - appendText.Append(line + Environment.NewLine); + appendText.AppendLine(line); LogMessageTextBox.AppendText(appendText.ToString()); LogMessageTextBox.ScrollToCaret(); @@ -181,6 +200,11 @@ namespace Shadowsocks.View private void UpdateContent() { + this.Text = I18N.GetString("Log Viewer") + + $" [in: {Utils.FormatBytes(controller.InboundCounter)}, out: {Utils.FormatBytes(controller.OutboundCounter)}]"; + + if (string.IsNullOrEmpty(filename) || !File.Exists(filename)) + return; try { using (StreamReader reader = new StreamReader(new FileStream(filename, @@ -194,7 +218,7 @@ namespace Shadowsocks.View while ((line = reader.ReadLine()) != null) { changed = true; - appendText.Append(line + Environment.NewLine); + appendText.AppendLine(line); } if (changed) @@ -209,9 +233,6 @@ namespace Shadowsocks.View catch (FileNotFoundException) { } - - this.Text = I18N.GetString("Log Viewer") + - $" [in: {Utils.FormatBytes(controller.InboundCounter)}, out: {Utils.FormatBytes(controller.OutboundCounter)}]"; } private void LogForm_Load(object sender, EventArgs e) @@ -270,7 +291,7 @@ namespace Shadowsocks.View private void OpenLocationMenuItem_Click(object sender, EventArgs e) { string argument = "/select, \"" + filename + "\""; - Logging.Debug(argument); + logger.Debug(argument); System.Diagnostics.Process.Start("explorer.exe", argument); } @@ -287,7 +308,11 @@ namespace Shadowsocks.View #region Clean up the content in LogMessageTextBox. private void DoClearLogs() { - Logging.Clear(); + try + { + File.Delete(filename); + } + catch { } lastOffset = 0; LogMessageTextBox.Clear(); } @@ -317,7 +342,7 @@ namespace Shadowsocks.View } catch (Exception ex) { - Logging.LogUsefulException(ex); + logger.LogUsefulException(ex); MessageBox.Show(ex.Message); } } diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 59abf18b..ddcf21f4 100644 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -1,4 +1,5 @@ -using Shadowsocks.Controller; +using NLog; +using Shadowsocks.Controller; using Shadowsocks.Model; using Shadowsocks.Properties; using Shadowsocks.Util; @@ -17,6 +18,7 @@ namespace Shadowsocks.View { public class MenuViewController { + private static Logger logger = LogManager.GetCurrentClassLogger(); // yes this is just a menu view controller // when config form is closed, it moves away from RAM // and it should just do anything related to the config form @@ -220,7 +222,7 @@ namespace Shadowsocks.View { Color colorMask = Color.White; - Utils.WindowsThemeMode currentWindowsThemeMode = Utils.GetWindows10SystemThemeSetting(controller.GetCurrentConfiguration().isVerboseLogging); + Utils.WindowsThemeMode currentWindowsThemeMode = Utils.GetWindows10SystemThemeSetting(); if (isProxyEnabled) { @@ -386,7 +388,7 @@ namespace Shadowsocks.View void controller_UpdatePACFromGFWListError(object sender, System.IO.ErrorEventArgs e) { ShowBalloonTip(I18N.GetString("Failed to update PAC file"), e.GetException().Message, ToolTipIcon.Error, 5000); - Logging.LogUsefulException(e.GetException()); + logger.LogUsefulException(e.GetException()); } void controller_UpdatePACFromGFWListCompleted(object sender, GFWListUpdater.ResultEventArgs e) @@ -454,30 +456,30 @@ namespace Shadowsocks.View { items.RemoveAt(0); } - int i = 0; + int strategyCount = 0; foreach (var strategy in controller.GetStrategies()) { MenuItem item = new MenuItem(strategy.Name); item.Tag = strategy.ID; item.Click += AStrategyItem_Click; - items.Add(i, item); - i++; + items.Add(strategyCount, item); + strategyCount++; } // user wants a seperator item between strategy and servers menugroup - items.Add(i++, new MenuItem("-")); + items.Add(strategyCount++, new MenuItem("-")); - int strategyCount = i; + int serverCount = 0; Configuration configuration = controller.GetConfigurationCopy(); foreach (var server in configuration.configs) { if (Configuration.ChecksServer(server)) { MenuItem item = new MenuItem(server.FriendlyName()); - item.Tag = i - strategyCount; + item.Tag = configuration.configs.FindIndex(s => s == server); item.Click += AServerItem_Click; - items.Add(i, item); - i++; + items.Add(strategyCount + serverCount, item); + serverCount++; } } @@ -543,7 +545,7 @@ namespace Shadowsocks.View } else { - logForm = new LogForm(controller, Logging.LogFilePath); + logForm = new LogForm(controller); logForm.Show(); logForm.Activate(); logForm.FormClosed += logForm_FormClosed; diff --git a/shadowsocks-csharp/packages.config b/shadowsocks-csharp/packages.config index f7fcb451..911e1d9a 100644 --- a/shadowsocks-csharp/packages.config +++ b/shadowsocks-csharp/packages.config @@ -5,6 +5,7 @@ + \ No newline at end of file diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index dd59f561..bf562337 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -82,12 +82,21 @@ ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + ..\packages\NLog.4.6.8\lib\net45\NLog.dll + + + + + + + @@ -102,6 +111,7 @@ + @@ -122,6 +132,7 @@ + @@ -145,7 +156,6 @@ - @@ -257,6 +267,7 @@ + diff --git a/shadowsocks-windows.sln b/shadowsocks-windows.sln index 1c24be82..d0048437 100644 --- a/shadowsocks-windows.sln +++ b/shadowsocks-windows.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26228.10 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shadowsocks-csharp", "shadowsocks-csharp\shadowsocks-csharp.csproj", "{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}" EndProject @@ -12,21 +12,30 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShadowsocksTest", "test\Sha EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|Any CPU.ActiveCfg = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.ActiveCfg = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Build.0 = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Deploy.0 = Debug|x86 + {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|Any CPU.ActiveCfg = Release|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.ActiveCfg = Release|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.Build.0 = Release|x86 + {45913187-0685-4903-B250-DCEF0479CD86}.Debug|Any CPU.ActiveCfg = Debug|x86 {45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.ActiveCfg = Debug|x86 {45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.Build.0 = Debug|x86 + {45913187-0685-4903-B250-DCEF0479CD86}.Release|Any CPU.ActiveCfg = Release|x86 {45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.ActiveCfg = Release|x86 {45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F7E7D35B-4FDA-4385-95CF-09DADED042EA} + EndGlobalSection EndGlobal