Skip to content

Commit 52124f0

Browse files
committed
fix: Large buffer will cause FlushAsync block
1 parent 4b05448 commit 52124f0

File tree

2 files changed

+23
-39
lines changed

2 files changed

+23
-39
lines changed

Shadowsocks.Protocol/TcpClients/ShadowsocksPipeReader.cs

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using Shadowsocks.Crypto;
55
using Shadowsocks.Protocol.Models;
66
using System;
7-
using System.Buffers;
87
using System.IO.Pipelines;
98
using System.Threading;
109
using System.Threading.Tasks;
@@ -56,10 +55,25 @@ private Task WrapAsync(IShadowsocksCrypto decryptor, CancellationToken cancellat
5655

5756
try
5857
{
59-
if (ReceiveFromRemote(ref buffer))
58+
while (!buffer.IsEmpty)
6059
{
61-
var writerFlushResult = await Writer.FlushAsync(cancellationToken);
62-
if (writerFlushResult.IsCompleted)
60+
var oldLength = buffer.Length;
61+
62+
var memory = Writer.GetMemory(BufferSize);
63+
64+
var outLength = decryptor.DecryptTCP(ref buffer, memory.Span);
65+
66+
Writer.Advance(outLength);
67+
if (outLength > 0)
68+
{
69+
var writerFlushResult = await Writer.FlushAsync(cancellationToken);
70+
if (writerFlushResult.IsCompleted)
71+
{
72+
goto NoData;
73+
}
74+
}
75+
76+
if (oldLength == buffer.Length)
6377
{
6478
break;
6579
}
@@ -75,7 +89,7 @@ private Task WrapAsync(IShadowsocksCrypto decryptor, CancellationToken cancellat
7589
InternalReader.AdvanceTo(buffer.Start, buffer.End);
7690
}
7791
}
78-
92+
NoData:
7993
await Writer.CompleteAsync();
8094
}
8195
catch (Exception ex)
@@ -89,32 +103,6 @@ private Task WrapAsync(IShadowsocksCrypto decryptor, CancellationToken cancellat
89103
},
90104
default
91105
);
92-
93-
bool ReceiveFromRemote(ref ReadOnlySequence<byte> sequence)
94-
{
95-
var result = false;
96-
while (!sequence.IsEmpty)
97-
{
98-
var oldLength = sequence.Length;
99-
100-
var span = Writer.GetSpan(BufferSize);
101-
102-
var outLength = decryptor.DecryptTCP(ref sequence, span);
103-
104-
Writer.Advance(outLength);
105-
if (outLength > 0)
106-
{
107-
result = true;
108-
}
109-
110-
if (oldLength == sequence.Length)
111-
{
112-
break;
113-
}
114-
}
115-
116-
return result;
117-
}
118106
}
119107

120108
public override void AdvanceTo(SequencePosition consumed)

Shadowsocks.Protocol/TcpClients/ShadowsocksPipeWriter.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,13 @@ private Task WrapAsync(IShadowsocksCrypto encryptor, CancellationToken cancellat
5252
var result = await Reader.ReadAsync(cancellationToken);
5353
var buffer = result.Buffer;
5454

55-
if (!buffer.IsEmpty)
55+
foreach (var segment in buffer)
5656
{
57-
foreach (var segment in buffer)
58-
{
59-
SendToRemote(segment.Span);
60-
}
61-
57+
SendToRemote(segment.Span);
6258
var flushResult = await InternalWriter.FlushAsync(cancellationToken);
6359
if (flushResult.IsCompleted)
6460
{
65-
break;
61+
goto NoData;
6662
}
6763
}
6864

@@ -73,7 +69,7 @@ private Task WrapAsync(IShadowsocksCrypto encryptor, CancellationToken cancellat
7369
break;
7470
}
7571
}
76-
72+
NoData:
7773
await Reader.CompleteAsync();
7874
}
7975
catch (Exception ex)

0 commit comments

Comments
 (0)