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 async ValueTask <int> SendAsync(ReadOnlyMemory <byte> buffer, CancellationToken cancellationToken = default) { byte[] encBuffer = ArrayPool <byte> .Shared.Rent(MaxUdpSize); try { using IShadowsocksCrypto encryptor = ShadowsocksCrypto.Create(_serverInfo.Method !, _serverInfo.Password !); int length = encryptor.EncryptUDP(buffer.Span, encBuffer); int sendLength = await _client.SendAsync(encBuffer.AsMemory(0, length), SocketFlags.None, cancellationToken); Report.IfNot(sendLength == length, @"Send Udp {0}/{1}", sendLength, length); return(sendLength == length ? buffer.Length : default);
public async ValueTask <int> ReceiveAsync(Memory <byte> buffer, CancellationToken cancellationToken = default) { byte[] encBuffer = ArrayPool <byte> .Shared.Rent(MaxUdpSize); try { int res = await _client.ReceiveAsync(encBuffer, SocketFlags.None, cancellationToken); using IShadowsocksCrypto decryptor = ShadowsocksCrypto.Create(_serverInfo.Method !, _serverInfo.Password !); return(decryptor.DecryptUDP(encBuffer.AsSpan(0, res), buffer.Span)); } finally { ArrayPool <byte> .Shared.Return(encBuffer); } }
public ShadowsocksPipeReader( PipeReader reader, ShadowsocksServerInfo serverInfo, PipeOptions?pipeOptions = null) { Requires.NotNull(reader, nameof(reader)); Requires.NotNull(serverInfo, nameof(serverInfo)); Requires.NotNullAllowStructs(serverInfo.Method, nameof(serverInfo)); Requires.NotNullAllowStructs(serverInfo.Password, nameof(serverInfo)); IShadowsocksCrypto decryptor = ShadowsocksCrypto.Create(serverInfo.Method, serverInfo.Password); InternalReader = reader; _pipe = new Pipe(pipeOptions ?? PipeOptions.Default); _cancellationTokenSource = new CancellationTokenSource(); WrapAsync(decryptor, _cancellationTokenSource.Token).Forget(); }
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"); }
private Task WrapAsync(IShadowsocksCrypto decryptor, CancellationToken cancellationToken) { return(Task.Run( async() => { try { while (true) { ReadResult result = await InternalReader.ReadAndCheckIsCanceledAsync(cancellationToken); ReadOnlySequence <byte> buffer = result.Buffer; try { while (!buffer.IsEmpty) { long oldLength = buffer.Length; Memory <byte> memory = Writer.GetMemory(BufferSize); int outLength = decryptor.DecryptTCP(ref buffer, memory.Span); Writer.Advance(outLength); if (outLength > 0) { FlushResult writerFlushResult = await Writer.FlushAsync(cancellationToken); if (writerFlushResult.IsCompleted) { goto NoData; } } if (oldLength == buffer.Length) { break; } } if (result.IsCompleted) { break; } } finally { InternalReader.AdvanceTo(buffer.Start, buffer.End); } } NoData: await Writer.CompleteAsync(); } catch (Exception ex) { await Writer.CompleteAsync(ex); } finally { decryptor.Dispose(); } }, default )); }