private Task WrapAsync(IShadowsocksCrypto encryptor, CancellationToken cancellationToken) { return(Task.Run( async() => { try { while (true) { ReadResult result = await Reader.ReadAsync(cancellationToken); ReadOnlySequence <byte> buffer = result.Buffer; foreach (ReadOnlyMemory <byte> segment in buffer) { SendToRemote(segment.Span); FlushResult flushResult = await InternalWriter.FlushAsync(cancellationToken); if (flushResult.IsCompleted) { goto NoData; } } Reader.AdvanceTo(buffer.End); if (result.IsCompleted) { break; } } NoData: await Reader.CompleteAsync(); } catch (Exception ex) { await Reader.CompleteAsync(ex); } finally { encryptor.Dispose(); } }, default )); void SendToRemote(ReadOnlySpan <byte> buffer) { while (!buffer.IsEmpty) { Span <byte> span = InternalWriter.GetSpan(BufferSize); encryptor.EncryptTCP(buffer, span, out int p, out int outLength); InternalWriter.Advance(outLength); if (p == buffer.Length) { break; } buffer = buffer[p..];
public static void Test(string method) { Console.Write($@"Testing {method}: "); ReadOnlySpan <byte> i = new byte[Step]; Span <byte> o = new byte[AEADShadowsocksCrypto.GetBufferSize(i.Length)]; using IShadowsocksCrypto crypto = ShadowsocksCrypto.Create(method, Password); ulong length = 0ul; Stopwatch sw = Stopwatch.StartNew(); do { crypto.EncryptTCP(i, o, out int pLength, out _); length += (uint)pLength; } while (sw.ElapsedMilliseconds < 2000); sw.Stop(); double result = length / sw.Elapsed.TotalSeconds / 1024.0 / 1024.0; Console.WriteLine($@"{result:F2} MB/s"); }