Browse Source

per encryptor optimization

pull/2865/head
Student Main 5 years ago
parent
commit
69dff0cce5
12 changed files with 27 additions and 117 deletions
  1. +1
    -0
      shadowsocks-csharp/Controller/Service/Listener.cs
  2. +0
    -1
      shadowsocks-csharp/Controller/Service/PACServer.cs
  3. +1
    -0
      shadowsocks-csharp/Controller/Service/UDPRelay.cs
  4. +0
    -24
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  5. +7
    -2
      shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs
  6. +2
    -2
      shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs
  7. +1
    -1
      shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs
  8. +6
    -0
      shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs
  9. +8
    -12
      shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs
  10. +1
    -16
      shadowsocks-csharp/Program.cs
  11. +0
    -55
      shadowsocks-csharp/Util/Util.cs
  12. +0
    -4
      shadowsocks-csharp/View/MenuViewController.cs

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

@@ -9,6 +9,7 @@ using Shadowsocks.Model;
namespace Shadowsocks.Controller
{
// TODO: Stream/Dgram Listener, so we needn't put TCP/UDP service together
public class Listener
{
private static Logger logger = LogManager.GetCurrentClassLogger();


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

@@ -181,7 +181,6 @@ Connection: Close
";
byte[] response = Encoding.UTF8.GetBytes(responseHead + pacContent);
socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket);
Utils.ReleaseMemory(true);
}
catch (Exception e)
{


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

@@ -25,6 +25,7 @@ namespace Shadowsocks.Controller
this._controller = controller;
}
// TODO: UDP is datagram protocol not stream protocol
public override bool Handle(CachedNetworkStream stream, object state)
{
byte[] fp = new byte[256];


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

@@ -95,7 +95,6 @@ namespace Shadowsocks.Controller
StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
_strategyManager = new StrategyManager(this);
_pluginsByServer = new ConcurrentDictionary<Server, Sip003Plugin>();
StartReleasingMemory();
StartTrafficStatistics(61);
ProgramUpdated += (o, e) =>
@@ -568,7 +567,6 @@ namespace Shadowsocks.Controller
ConfigChanged?.Invoke(this, new EventArgs());
UpdateSystemProxy();
Utils.ReleaseMemory(true);
}
private void StartPlugin()
@@ -622,28 +620,6 @@ namespace Shadowsocks.Controller
Clipboard.SetDataObject(_pacServer.PacUrl);
}
#region Memory Management
private void StartReleasingMemory()
{
_ramThread = new Thread(new ThreadStart(ReleaseMemory))
{
IsBackground = true
};
_ramThread.Start();
}
private void ReleaseMemory()
{
while (true)
{
Utils.ReleaseMemory(false);
Thread.Sleep(30 * 1000);
}
}
#endregion
#region Traffic Statistics
private void StartTrafficStatistics(int queueMaxSize)


+ 7
- 2
shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs View File

@@ -29,9 +29,15 @@ namespace Shadowsocks.Encryption.AEAD
}
#endregion

AesGcm aes;
public override void InitCipher(byte[] salt, bool isEncrypt)
{
base.InitCipher(salt, isEncrypt);
aes = new AesGcm(sessionKey);
}

public override int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
using AesGcm aes = new AesGcm(sessionKey);
aes.Encrypt(nonce, plain, cipher.Slice(0, plain.Length), cipher.Slice(plain.Length, tagLen));
return plain.Length + tagLen;
}
@@ -39,7 +45,6 @@ namespace Shadowsocks.Encryption.AEAD
public override int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
int clen = cipher.Length - tagLen;
using AesGcm aes = new AesGcm(sessionKey);
ReadOnlySpan<byte> ciphertxt = cipher.Slice(0, clen);
ReadOnlySpan<byte> tag = cipher.Slice(clen);
aes.Decrypt(nonce, ciphertxt, tag, plain.Slice(0, clen));


+ 2
- 2
shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs View File

@@ -43,14 +43,14 @@ namespace Shadowsocks.Encryption.AEAD

public override int CipherEncrypt(ReadOnlySpan<byte> plain, Span<byte> cipher)
{
byte[] ct = enc!.Encrypt(plain, null, nonce);
byte[] ct = enc.Encrypt(plain, null, nonce);
ct.CopyTo(cipher);
return ct.Length;
}

public override int CipherDecrypt(Span<byte> plain, ReadOnlySpan<byte> cipher)
{
byte[] pt = enc!.Decrypt(cipher, null, nonce);
byte[] pt = enc.Decrypt(cipher, null, nonce);
pt.CopyTo(plain);
return pt.Length;
}


+ 1
- 1
shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs View File

@@ -41,7 +41,7 @@ namespace Shadowsocks.Encryption.Stream
{
Span<byte> ob = new byte[o.Length + 128];
i.CopyTo(cfbBuf.AsSpan(ptr));
// TODO: standard CFB
// TODO: standard CFB, maybe with native aes
int total = i.Length + ptr;

int blkSize = b.GetBlockSize();


+ 6
- 0
shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs View File

@@ -39,6 +39,12 @@ namespace Shadowsocks.Encryption.Stream
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
private int CipherUpdate(ReadOnlySpan<byte> i, Span<byte> o, bool enc)
{
// about performance problem:
// as a part of hacking for streaming, we need manually increase IC
// so we need new Chacha20
// and to get correct position, copy paste array everytime is required
// NaCl.Core has no int Encrypt(ReadOnlySpan<byte>,Span<byte>)...

int len = i.Length;
int pad = remain;
i.CopyTo(chachaBuf.AsSpan(pad));


+ 8
- 12
shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs View File

@@ -46,7 +46,7 @@ namespace Shadowsocks.Encryption.Stream
// don't know why we need third array, but it works...
Span<byte> t = new byte[i.Length];
i.CopyTo(t);
RC4(ctx, sbox, t, t.Length);
RC4(sbox, t, t.Length);
t.CopyTo(o);
return t.Length;
}
@@ -71,13 +71,9 @@ namespace Shadowsocks.Encryption.Stream
#endregion

#region RC4
class Context
{
public int index1 = 0;
public int index2 = 0;
}

private readonly Context ctx = new Context();
int index1 = 0;
int index2 = 0;

private byte[] SBox(byte[] key)
{
@@ -99,17 +95,17 @@ namespace Shadowsocks.Encryption.Stream
}

[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private void RC4(Context ctx, Span<byte> s, Span<byte> data, int length)
private void RC4(Span<byte> s, Span<byte> data, int length)
{
for (int n = 0; n < length; n++)
{
byte b = data[n];

ctx.index1 = (ctx.index1 + 1) & 255;
ctx.index2 = (ctx.index2 + s[ctx.index1]) & 255;
index1 = (index1 + 1) & 255;
index2 = (index2 + s[index1]) & 255;

Swap(s, ctx.index1, ctx.index2);
data[n] = (byte)(b ^ s[(s[ctx.index1] + s[ctx.index2]) & 255]);
Swap(s, index1, index2);
data[n] = (byte)(b ^ s[(s[index1] + s[index2]) & 255]);
}
}



+ 1
- 16
shadowsocks-csharp/Program.cs View File

@@ -46,23 +46,8 @@ namespace Shadowsocks
"Shadowsocks Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
#if NET472
// Check .NET Framework version
if (!Utils.IsSupportedRuntimeVersion())
{
if (DialogResult.OK == MessageBox.Show(I18N.GetString("Unsupported .NET Framework, please update to {0} or later.", "4.7.2"),
"Shadowsocks Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error))
{
//Process.Start("https://www.microsoft.com/download/details.aspx?id=53344"); // 4.6.2
Process.Start("https://dotnet.microsoft.com/download/dotnet-framework/net472");
}
return;
}
if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware();
#else
Application.SetHighDpiMode(HighDpiMode.SystemAware);
#endif
Utils.ReleaseMemory(true);
using (Mutex mutex = new Mutex(false, $"Global\\Shadowsocks_{Application.StartupPath.GetHashCode()}"))
{
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);


+ 0
- 55
shadowsocks-csharp/Util/Util.cs View File

@@ -95,61 +95,6 @@ namespace Shadowsocks.Util
return Path.Combine(GetTempPath(), filename);
}
public static void ReleaseMemory(bool removePages)
{
// release any unused pages
// making the numbers look good in task manager
// this is totally nonsense in programming
// but good for those users who care
// making them happier with their everyday life
// which is part of user experience
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
if (removePages)
{
// as some users have pointed out
// removing pages from working set will cause some IO
// which lowered user experience for another group of users
//
// so we do 2 more things here to satisfy them:
// 1. only remove pages once when configuration is changed
// 2. add more comments here to tell users that calling
// this function will not be more frequent than
// IM apps writing chat logs, or web browsers writing cache files
// if they're so concerned about their disk, they should
// uninstall all IM apps and web browsers
//
// please open an issue if you're worried about anything else in your computer
// no matter it's GPU performance, monitor contrast, audio fidelity
// or anything else in the task manager
// we'll do as much as we can to help you
//
// just kidding
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
(UIntPtr)0xFFFFFFFF,
(UIntPtr)0xFFFFFFFF);
}
}
public static string UnGzip(byte[] buf)
{
byte[] buffer = new byte[1024];
int n;
using (MemoryStream sb = new MemoryStream())
{
using (GZipStream input = new GZipStream(new MemoryStream(buf),
CompressionMode.Decompress,
false))
{
while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
{
sb.Write(buffer, 0, n);
}
}
return System.Text.Encoding.UTF8.GetString(sb.ToArray());
}
}
public static string FormatBandwidth(long n)
{
var result = GetBandwidthScale(n);


+ 0
- 4
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -575,14 +575,12 @@ namespace Shadowsocks.View
{
logForm.Dispose();
logForm = null;
Utils.ReleaseMemory(true);
}
void configForm_FormClosed(object sender, FormClosedEventArgs e)
{
configForm.Dispose();
configForm = null;
Utils.ReleaseMemory(true);
if (_isFirstRun)
{
CheckUpdateForFirstRun();
@@ -600,14 +598,12 @@ namespace Shadowsocks.View
{
proxyForm.Dispose();
proxyForm = null;
Utils.ReleaseMemory(true);
}
void hotkeySettingsForm_FormClosed(object sender, FormClosedEventArgs e)
{
hotkeySettingsForm.Dispose();
hotkeySettingsForm = null;
Utils.ReleaseMemory(true);
}
private void Config_Click(object sender, EventArgs e)


Loading…
Cancel
Save