Skip to content

Commit 1f4cadc

Browse files
committed
Fixed dequeueing of incoming queue.
1 parent dec5149 commit 1f4cadc

File tree

2 files changed

+51
-39
lines changed

2 files changed

+51
-39
lines changed

src/Renci.SshNet/ShellStream.cs

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -286,15 +286,7 @@ public void Expect(TimeSpan timeout, params ExpectAction[] expectActions)
286286
var returnLength = _encoding.GetByteCount(returnText);
287287

288288
// Remove processed items from the queue
289-
for (var i = 0; i < returnLength && _incoming.Count > 0; i++)
290-
{
291-
if (_expect.Count == _incoming.Count)
292-
{
293-
_ = _expect.Dequeue();
294-
}
295-
296-
_ = _incoming.Dequeue();
297-
}
289+
SyncQueuesAndDequeue(returnLength);
298290

299291
expectAction.Action(returnText);
300292
expectedFound = true;
@@ -389,15 +381,7 @@ public string Expect(Regex regex, TimeSpan timeout)
389381
var returnLength = _encoding.GetByteCount(returnText);
390382

391383
// Remove processed items from the queue
392-
for (var i = 0; i < returnLength && _incoming.Count > 0; i++)
393-
{
394-
if (_expect.Count == _incoming.Count)
395-
{
396-
_ = _expect.Dequeue();
397-
}
398-
399-
_ = _incoming.Dequeue();
400-
}
384+
SyncQueuesAndDequeue(returnLength);
401385

402386
break;
403387
}
@@ -505,15 +489,7 @@ public IAsyncResult BeginExpect(TimeSpan timeout, AsyncCallback callback, object
505489
var returnLength = _encoding.GetByteCount(returnText);
506490

507491
// Remove processed items from the queue
508-
for (var i = 0; i < returnLength && _incoming.Count > 0; i++)
509-
{
510-
if (_expect.Count == _incoming.Count)
511-
{
512-
_ = _expect.Dequeue();
513-
}
514-
515-
_ = _incoming.Dequeue();
516-
}
492+
SyncQueuesAndDequeue(returnLength);
517493

518494
expectAction.Action(returnText);
519495
callback?.Invoke(asyncResult);
@@ -614,15 +590,7 @@ public string ReadLine(TimeSpan timeout)
614590
var bytesProcessed = _encoding.GetByteCount(text + CrLf);
615591

616592
// remove processed bytes from the queue
617-
for (var i = 0; i < bytesProcessed; i++)
618-
{
619-
if (_expect.Count == _incoming.Count)
620-
{
621-
_ = _expect.Dequeue();
622-
}
623-
624-
_ = _incoming.Dequeue();
625-
}
593+
SyncQueuesAndDequeue(bytesProcessed);
626594

627595
break;
628596
}
@@ -687,7 +655,7 @@ public override int Read(byte[] buffer, int offset, int count)
687655
{
688656
for (; i < count && _incoming.Count > 0; i++)
689657
{
690-
if (_expect.Count == _incoming.Count)
658+
if (_incoming.Count == _expect.Count)
691659
{
692660
_ = _expect.Dequeue();
693661
}
@@ -869,5 +837,22 @@ private void OnDataReceived(byte[] data)
869837
{
870838
DataReceived?.Invoke(this, new ShellDataEventArgs(data));
871839
}
840+
841+
private void SyncQueuesAndDequeue(int bytesToDequeue)
842+
{
843+
lock (_incoming)
844+
{
845+
while (_incoming.Count > _expect.Count)
846+
{
847+
_ = _incoming.Dequeue();
848+
}
849+
850+
for (var count = 0; count < bytesToDequeue && _incoming.Count > 0; count++)
851+
{
852+
_ = _incoming.Dequeue();
853+
_ = _expect.Dequeue();
854+
}
855+
}
856+
}
872857
}
873858
}

test/Renci.SshNet.Tests/Classes/ShellStreamTest_ReadExpect.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ namespace Renci.SshNet.Tests.Classes
1717
[TestClass]
1818
public class ShellStreamTest_ReadExpect
1919
{
20+
private const int BufferSize = 1024;
21+
private const int ExpectSize = BufferSize * 2;
2022
private ShellStream _shellStream;
2123
private ChannelSessionStub _channelSessionStub;
2224

@@ -42,8 +44,8 @@ public void Initialize()
4244
width: 800,
4345
height: 600,
4446
terminalModeValues: null,
45-
bufferSize: 1024,
46-
expectSize: 2048);
47+
bufferSize: BufferSize,
48+
expectSize: ExpectSize);
4749
}
4850

4951
[TestMethod]
@@ -244,6 +246,31 @@ public void Expect_String_LargeExpect()
244246
Assert.AreEqual($"{new string('c', 100)}", _shellStream.Read());
245247
}
246248

249+
[TestMethod]
250+
public void Expect_String_DequeueChecks()
251+
{
252+
const string expected = "ccccc";
253+
254+
// Prime buffer
255+
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string(' ', BufferSize)));
256+
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string(' ', ExpectSize)));
257+
258+
// Test data
259+
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string('a', 100)));
260+
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string('b', 100)));
261+
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(expected));
262+
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string('d', 100)));
263+
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string('e', 100)));
264+
265+
// Expected result
266+
var expectedResult = $"{new string(' ', ExpectSize - 405)}{new string('a', 100)}{new string('b', 100)}{expected}";
267+
var expectedRead = $"{new string('d', 100)}{new string('e', 100)}";
268+
269+
Assert.AreEqual(expectedResult, _shellStream.Expect(expected));
270+
271+
Assert.AreEqual(expectedRead, _shellStream.Read());
272+
}
273+
247274
[TestMethod]
248275
public void Expect_Timeout()
249276
{

0 commit comments

Comments
 (0)