Browse Source

Merge branch 'master' into check-updated

tags/4.1.9.3
Student Main 4 years ago
parent
commit
cdc620fc68
44 changed files with 1110 additions and 779 deletions
  1. +6
    -3
      shadowsocks-csharp/Controller/FileManager.cs
  2. +3
    -2
      shadowsocks-csharp/Controller/HotkeyReg.cs
  3. +7
    -5
      shadowsocks-csharp/Controller/I18N.cs
  4. +119
    -0
      shadowsocks-csharp/Controller/LoggerExtension.cs
  5. +0
    -198
      shadowsocks-csharp/Controller/Logging.cs
  6. +23
    -18
      shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
  7. +5
    -3
      shadowsocks-csharp/Controller/Service/GfwListUpdater.cs
  8. +9
    -10
      shadowsocks-csharp/Controller/Service/Listener.cs
  9. +6
    -3
      shadowsocks-csharp/Controller/Service/PACDaemon.cs
  10. +5
    -2
      shadowsocks-csharp/Controller/Service/PACServer.cs
  11. +13
    -10
      shadowsocks-csharp/Controller/Service/PortForwarder.cs
  12. +7
    -4
      shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs
  13. +41
    -46
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  14. +6
    -3
      shadowsocks-csharp/Controller/Service/UDPRelay.cs
  15. +11
    -9
      shadowsocks-csharp/Controller/Service/UpdateChecker.cs
  16. +16
    -5
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  17. +10
    -7
      shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs
  18. +7
    -5
      shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs
  19. +11
    -8
      shadowsocks-csharp/Controller/System/AutoStartup.cs
  20. +4
    -1
      shadowsocks-csharp/Controller/System/SystemProxy.cs
  21. +13
    -0
      shadowsocks-csharp/Data/NLog.config
  22. +2
    -1
      shadowsocks-csharp/Data/i18n.csv
  23. +20
    -18
      shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs
  24. +11
    -8
      shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs
  25. +4
    -1
      shadowsocks-csharp/Encryption/MbedTLS.cs
  26. +4
    -1
      shadowsocks-csharp/Encryption/OpenSSL.cs
  27. +5
    -2
      shadowsocks-csharp/Encryption/Sodium.cs
  28. +44
    -3
      shadowsocks-csharp/Model/Configuration.cs
  29. +126
    -0
      shadowsocks-csharp/Model/NlogConfig.cs
  30. +5
    -3
      shadowsocks-csharp/Model/StatisticsStrategyConfiguration.cs
  31. +12
    -13
      shadowsocks-csharp/Program.cs
  32. +252
    -231
      shadowsocks-csharp/Properties/Resources.Designer.cs
  33. +3
    -0
      shadowsocks-csharp/Properties/Resources.resx
  34. +4
    -1
      shadowsocks-csharp/Proxy/HttpProxy.cs
  35. +4
    -1
      shadowsocks-csharp/Util/ProcessManagement/Job.cs
  36. +5
    -2
      shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs
  37. +11
    -9
      shadowsocks-csharp/Util/Util.cs
  38. +123
    -116
      shadowsocks-csharp/View/ConfigForm.Designer.cs
  39. +80
    -2
      shadowsocks-csharp/View/ConfigForm.cs
  40. +35
    -10
      shadowsocks-csharp/View/LogForm.cs
  41. +14
    -12
      shadowsocks-csharp/View/MenuViewController.cs
  42. +1
    -0
      shadowsocks-csharp/packages.config
  43. +12
    -1
      shadowsocks-csharp/shadowsocks-csharp.csproj
  44. +11
    -2
      shadowsocks-windows.sln

+ 6
- 3
shadowsocks-csharp/Controller/FileManager.cs View File

@@ -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;
}
}


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

@@ -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;
}


+ 7
- 5
shadowsocks-csharp/Controller/I18N.cs View File

@@ -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<string, string> _strings = new Dictionary<string, string>();
@@ -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);
}


+ 119
- 0
shadowsocks-csharp/Controller/LoggerExtension.cs View File

@@ -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);
}
}
}
}

+ 0
- 198
shadowsocks-csharp/Controller/Logging.cs View File

@@ -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);
}
}
}

+ 23
- 18
shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs View File

@@ -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);
}
}


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

@@ -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<ResultEventArgs> 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)
{


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

@@ -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();
}
}


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

@@ -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
/// </summary>
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;


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

@@ -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();
}
}


+ 13
- 10
shadowsocks-csharp/Controller/Service/PortForwarder.cs View File

@@ -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);
}
}
}


+ 7
- 4
shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs View File

@@ -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;
}
}


+ 41
- 46
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -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();
}
}


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

@@ -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();


+ 11
- 9
shadowsocks-csharp/Controller/Service/UpdateChecker.cs View File

@@ -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);
}
}


+ 16
- 5
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -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<Server, Sip003Plugin>();
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);
}


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

@@ -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<Server, ServerStatus> _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))


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

@@ -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)


+ 11
- 8
shadowsocks-csharp/Controller/System/AutoStartup.cs View File

@@ -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");
}
}
}


+ 4
- 1
shadowsocks-csharp/Controller/System/SystemProxy.cs View File

@@ -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);


+ 13
- 0
shadowsocks-csharp/Data/NLog.config View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Warning: Configuration may reset after shadowsocks upgrade. -->
<!-- If you messed it up, delete this file and Shadowsocks will create a new one. -->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.-->
<target name="file" xsi:type="File" fileName="ss_win_temp\shadowsocks.log" writeBom="false" encoding="utf-8"/>
</targets>
<rules>
<!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing. -->
<logger name="*" minlevel="Info" writeTo="file"/>
</rules>
</nlog>

+ 2
- 1
shadowsocks-csharp/Data/i18n.csv View File

@@ -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,,,,
,,,,


+ 20
- 18
shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs View File

@@ -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();
}


+ 11
- 8
shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs View File

@@ -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;
}


+ 4
- 1
shadowsocks-csharp/Encryption/MbedTLS.cs View File

@@ -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);
}


+ 4
- 1
shadowsocks-csharp/Encryption/OpenSSL.cs View File

@@ -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);
}


+ 5
- 2
shadowsocks-csharp/Encryption/Sodium.cs View File

@@ -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}");
}
}
}


+ 44
- 3
shadowsocks-csharp/Model/Configuration.cs View File

@@ -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<Server> 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);
}
}


+ 126
- 0
shadowsocks-csharp/Model/NlogConfig.cs View File

@@ -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;
/// <summary>
/// Load the NLog config xml file content
/// </summary>
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;
}
/// <summary>
/// Save the content to NLog config xml file
/// </summary>
public static void SaveXML(NLogConfig nLogConfig)
{
nLogConfig.doc.Save(NLOG_CONFIG_FILE_NAME);
}
/// <summary>
/// Get the current minLogLevel from xml file
/// </summary>
/// <returns></returns>
public LogLevel GetLogLevel()
{
LogLevel level = LogLevel.Warn;
string levelStr = logLevelElement.GetAttribute(TARGET_MIN_LEVEL_ATTRIBUTE);
Enum.TryParse(levelStr, out level);
return level;
}
/// <summary>
/// Get the target fileName from xml file
/// </summary>
/// <returns></returns>
public string GetLogFileName()
{
return logFileNameElement.GetAttribute(LOGGER_FILE_NAME_ATTRIBUTE);
}
/// <summary>
/// Set the minLogLevel to xml file
/// </summary>
/// <param name="logLevel"></param>
public void SetLogLevel(LogLevel logLevel)
{
logLevelElement.SetAttribute(TARGET_MIN_LEVEL_ATTRIBUTE, logLevel.ToString("G"));
}
/// <summary>
/// Set the target fileName to xml file
/// </summary>
/// <param name="fileName"></param>
public void SetLogFileName(string fileName)
{
logFileNameElement.SetAttribute(LOGGER_FILE_NAME_ATTRIBUTE, fileName);
}
/// <summary>
/// Select a single XML node/elemant
/// </summary>
/// <param name="doc"></param>
/// <param name="xpath"></param>
/// <returns></returns>
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);
}
/// <summary>
/// Extract the pre-defined NLog configuration file is does not exist. Then reload the Nlog configuration.
/// </summary>
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);
}
}
/// <summary>
/// NLog reload the config file and apply to current LogManager
/// </summary>
public static void LoadConfiguration()
{
LogManager.LoadConfiguration(NLOG_CONFIG_FILE_NAME);
}
}
}

+ 5
- 3
shadowsocks-csharp/Model/StatisticsStrategyConfiguration.cs View File

@@ -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);
}
}



+ 12
- 13
shadowsocks-csharp/Program.cs View File

@@ -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;
}
}


+ 252
- 231
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -1,91 +1,91 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Shadowsocks.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 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() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[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;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性
/// 重写当前线程的 CurrentUICulture 属性。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找类似 /* eslint-disable */
///// Was generated by gfwlist2pac in precise mode
///// https://github.com/clowwindy/gfwlist2pac
///
///// 2019-10-06: More &apos;javascript&apos; 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 &lt;http://adblockplus.org/&gt;,
///* Copyright (C) 2006-2014 Eyeo GmbH
///*
///* Adblock Plus is free software: you can redistribute it and/or [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string abp_js {
get {
return ResourceManager.GetString("abp_js", resourceCulture);
}
}
/// <summary>
/// 查找类似 var __USERRULES__ = [];
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Shadowsocks.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 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 &apos;javascript&apos; 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 &lt;http://adblockplus.org/&gt;,
///* Copyright (C) 2006-2014 Eyeo GmbH
///*
///* Adblock Plus is free software: you can redistribute it and/or [rest of string was truncated]&quot;;.
/// </summary>
internal static string abp_js {
get {
return ResourceManager.GetString("abp_js", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to var __USERRULES__ = [];
///var __RULES__ = [
/// &quot;|http://85.17.73.31/&quot;,
/// &quot;||agnesb.fr&quot;,
@@ -106,154 +106,175 @@ namespace Shadowsocks.Properties {
/// &quot;||beeg.com&quot;,
/// &quot;||global.bing.com&quot;,
/// &quot;||bloombergview.com&quot;,
/// &quot; [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string default_abp_rule {
get {
return ResourceManager.GetString("default_abp_rule", resourceCulture);
}
}
/// <summary>
/// 查找类似 en,zh-CN,zh-TW,ja
/// &quot;||booktopia.com.au&quot;,
/// [rest of string was truncated]&quot;;.
/// </summary>
internal static string default_abp_rule {
get {
return ResourceManager.GetString("default_abp_rule", resourceCulture);
}
}
/// <summary>
/// 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,,,
///&quot;#You can find it by search &quot;&quot;Current language is:&quot;&quot;&quot;,,,
///#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,使 [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string i18n_csv {
get {
return ResourceManager.GetString("i18n_csv", resourceCulture);
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] libsscrypto_dll {
get {
object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找类似 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
/// 的本地化字符串。
/// </summary>
internal static string privoxy_conf {
get {
return ResourceManager.GetString("privoxy_conf", resourceCulture);
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] privoxy_exe {
get {
object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss32Fill {
get {
object obj = ResourceManager.GetObject("ss32Fill", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss32In {
get {
object obj = ResourceManager.GetObject("ss32In", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss32Out {
get {
object obj = ResourceManager.GetObject("ss32Out", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss32Outline {
get {
object obj = ResourceManager.GetObject("ss32Outline", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ssw128 {
get {
object obj = ResourceManager.GetObject("ssw128", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] sysproxy_exe {
get {
object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] sysproxy64_exe {
get {
object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找类似 ! Put user rules line by line in this file.
///! See https://adblockplus.org/en/filter-cheatsheet
/// 的本地化字符串。
/// </summary>
internal static string user_rule {
get {
return ResourceManager.GetString("user_rule", resourceCulture);
}
}
}
}
///Edit Servers...,编辑服务器...,編輯伺服器...,サーバーの編集.. [rest of string was truncated]&quot;;.
/// </summary>
internal static string i18n_csv {
get {
return ResourceManager.GetString("i18n_csv", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] libsscrypto_dll {
get {
object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
///&lt;nlog xmlns=&quot;http://www.nlog-project.org/schemas/NLog.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;
/// &lt;targets&gt;
/// &lt;target name=&quot;file&quot; xsi:type=&quot;File&quot; fileName=&quot;shadowsocks.log&quot;/&gt;
///
/// &lt;/targets&gt;
/// &lt;rules&gt;
/// &lt;logger name=&quot;Name.Space.Class1&quot; minlevel=&quot;Debug&quot; writeTo=&quot;f1&quot; /&gt;
/// &lt;/rules&gt;
///&lt;/nlog&gt;.
/// </summary>
internal static string NLog_config {
get {
return ResourceManager.GetString("NLog_config", resourceCulture);
}
}
/// <summary>
/// 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
///.
/// </summary>
internal static string privoxy_conf {
get {
return ResourceManager.GetString("privoxy_conf", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] privoxy_exe {
get {
object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ss32Fill {
get {
object obj = ResourceManager.GetObject("ss32Fill", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ss32In {
get {
object obj = ResourceManager.GetObject("ss32In", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ss32Out {
get {
object obj = ResourceManager.GetObject("ss32Out", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ss32Outline {
get {
object obj = ResourceManager.GetObject("ss32Outline", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ssw128 {
get {
object obj = ResourceManager.GetObject("ssw128", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] sysproxy_exe {
get {
object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] sysproxy64_exe {
get {
object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to ! Put user rules line by line in this file.
///! See https://adblockplus.org/en/filter-cheatsheet
///.
/// </summary>
internal static string user_rule {
get {
return ResourceManager.GetString("user_rule", resourceCulture);
}
}
}
}

+ 3
- 0
shadowsocks-csharp/Properties/Resources.resx View File

@@ -130,6 +130,9 @@
<data name="libsscrypto_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="NLog_config" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\nlog.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="privoxy_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\privoxy_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>


+ 4
- 1
shadowsocks-csharp/Proxy/HttpProxy.cs View File

@@ -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)
{


+ 4
- 1
shadowsocks-csharp/Util/ProcessManagement/Job.cs View File

@@ -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;


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

@@ -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);
}
}


+ 11
- 9
shadowsocks-csharp/Util/Util.cs View File

@@ -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;
}
}


+ 123
- 116
shadowsocks-csharp/View/ConfigForm.Designer.cs View File

@@ -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);


+ 80
- 2
shadowsocks-csharp/View/ConfigForm.cs View File

@@ -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<string, EncryptionMethod> methodByName = new Dictionary<string, EncryptionMethod>();
private static void Init()
{
var all = new List<EncryptionMethod>();
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;


+ 35
- 10
shadowsocks-csharp/View/LogForm.cs View File

@@ -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);
}
}


+ 14
- 12
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -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;


+ 1
- 0
shadowsocks-csharp/packages.config View File

@@ -5,6 +5,7 @@
<package id="Fody" version="4.2.1" targetFramework="net472" developmentDependency="true" />
<package id="GlobalHotKey" version="1.1.0" targetFramework="net472" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" />
<package id="NLog" version="4.6.8" targetFramework="net472" />
<package id="StringEx.CS" version="0.3.1" targetFramework="net472" developmentDependency="true" />
<package id="ZXing.Net" version="0.16.5" targetFramework="net472" />
</packages>

+ 12
- 1
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -82,12 +82,21 @@
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.6.8\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Management" />
<Reference Include="System.Net" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Windows.Forms.DataVisualization" />
@@ -102,6 +111,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Controller\HotkeyReg.cs" />
<Compile Include="Controller\LoggerExtension.cs" />
<Compile Include="Controller\Service\PACDaemon.cs" />
<Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" />
<Compile Include="Encryption\AEAD\AEADEncryptor.cs" />
@@ -122,6 +132,7 @@
<Compile Include="Encryption\Stream\StreamOpenSSLEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
<Compile Include="Model\HotKeyConfig.cs" />
<Compile Include="Model\NLogConfig.cs" />
<Compile Include="Model\ProxyConfig.cs" />
<Compile Include="Model\SysproxyConfig.cs" />
<Compile Include="Properties\Resources.Designer.cs">
@@ -145,7 +156,6 @@
<Compile Include="Controller\Service\GFWListUpdater.cs" />
<Compile Include="Controller\I18N.cs" />
<Compile Include="Controller\Service\Listener.cs" />
<Compile Include="Controller\Logging.cs" />
<Compile Include="Controller\Service\PortForwarder.cs" />
<Compile Include="Controller\Service\UDPRelay.cs" />
<Compile Include="Controller\Service\UpdateChecker.cs" />
@@ -257,6 +267,7 @@
</None>
<None Include="Data\i18n.csv" />
<None Include="Data\libsscrypto.dll.gz" />
<None Include="Data\NLog.config" />
<None Include="Data\privoxy.exe.gz" />
</ItemGroup>
<ItemGroup>


+ 11
- 2
shadowsocks-windows.sln View File

@@ -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

Loading…
Cancel
Save