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..];
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 )); }