@@ -22,6 +22,8 @@ public class ShellStream : Stream
22
22
private readonly Encoding _encoding ;
23
23
private readonly int _bufferSize ;
24
24
private readonly Queue < byte > _incoming ;
25
+ private readonly int _expectSize ;
26
+ private readonly Queue < byte > _expect ;
25
27
private readonly Queue < byte > _outgoing ;
26
28
private IChannelSession _channel ;
27
29
private AutoResetEvent _dataReceived = new AutoResetEvent ( initialState : false ) ;
@@ -76,15 +78,28 @@ internal int BufferSize
76
78
/// <param name="height">The terminal height in pixels.</param>
77
79
/// <param name="terminalModeValues">The terminal mode values.</param>
78
80
/// <param name="bufferSize">The size of the buffer.</param>
81
+ /// <param name="expectSize">The size of the expect buffer.</param>
79
82
/// <exception cref="SshException">The channel could not be opened.</exception>
80
83
/// <exception cref="SshException">The pseudo-terminal request was not accepted by the server.</exception>
81
84
/// <exception cref="SshException">The request to start a shell was not accepted by the server.</exception>
82
- internal ShellStream ( ISession session , string terminalName , uint columns , uint rows , uint width , uint height , IDictionary < TerminalModes , uint > terminalModeValues , int bufferSize )
85
+ internal ShellStream ( ISession session , string terminalName , uint columns , uint rows , uint width , uint height , IDictionary < TerminalModes , uint > terminalModeValues , int bufferSize , int expectSize )
83
86
{
87
+ if ( bufferSize <= 0 )
88
+ {
89
+ throw new ArgumentException ( $ "{ nameof ( bufferSize ) } must be between 1 and { int . MaxValue } .") ;
90
+ }
91
+
92
+ if ( expectSize <= 0 )
93
+ {
94
+ throw new ArgumentException ( $ "{ nameof ( expectSize ) } must be between 1 and { int . MaxValue } .") ;
95
+ }
96
+
84
97
_encoding = session . ConnectionInfo . Encoding ;
85
98
_session = session ;
86
99
_bufferSize = bufferSize ;
87
100
_incoming = new Queue < byte > ( ) ;
101
+ _expectSize = expectSize ;
102
+ _expect = new Queue < byte > ( _expectSize ) ;
88
103
_outgoing = new Queue < byte > ( ) ;
89
104
90
105
_channel = _session . CreateChannelSession ( ) ;
@@ -248,35 +263,40 @@ public void Expect(params ExpectAction[] expectActions)
248
263
public void Expect ( TimeSpan timeout , params ExpectAction [ ] expectActions )
249
264
{
250
265
var expectedFound = false ;
251
- var text = string . Empty ;
266
+ var matchText = string . Empty ;
252
267
253
268
do
254
269
{
255
270
lock ( _incoming )
256
271
{
257
- if ( _incoming . Count > 0 )
272
+ if ( _expect . Count > 0 )
258
273
{
259
- text = _encoding . GetString ( _incoming . ToArray ( ) , 0 , _incoming . Count ) ;
274
+ matchText = _encoding . GetString ( _expect . ToArray ( ) , 0 , _expect . Count ) ;
260
275
}
261
276
262
- if ( text . Length > 0 )
277
+ if ( matchText . Length > 0 )
263
278
{
264
279
foreach ( var expectAction in expectActions )
265
280
{
266
- var match = expectAction . Expect . Match ( text ) ;
281
+ var match = expectAction . Expect . Match ( matchText ) ;
267
282
268
283
if ( match . Success )
269
284
{
270
- var result = text . Substring ( 0 , match . Index + match . Length ) ;
271
- var charCount = _encoding . GetByteCount ( result ) ;
285
+ var returnText = matchText . Substring ( 0 , match . Index + match . Length ) ;
286
+ var returnLength = _encoding . GetByteCount ( returnText ) ;
272
287
273
- for ( var i = 0 ; i < charCount && _incoming . Count > 0 ; i ++ )
288
+ // Remove processed items from the queue
289
+ for ( var i = 0 ; i < returnLength && _incoming . Count > 0 ; i ++ )
274
290
{
275
- // Remove processed items from the queue
291
+ if ( _expect . Count == _incoming . Count )
292
+ {
293
+ _ = _expect . Dequeue ( ) ;
294
+ }
295
+
276
296
_ = _incoming . Dequeue ( ) ;
277
297
}
278
298
279
- expectAction . Action ( result ) ;
299
+ expectAction . Action ( returnText ) ;
280
300
expectedFound = true ;
281
301
}
282
302
}
@@ -349,27 +369,33 @@ public string Expect(Regex regex)
349
369
/// </returns>
350
370
public string Expect ( Regex regex , TimeSpan timeout )
351
371
{
352
- var result = string . Empty ;
372
+ var matchText = string . Empty ;
373
+ string returnText ;
353
374
354
375
while ( true )
355
376
{
356
377
lock ( _incoming )
357
378
{
358
- if ( _incoming . Count > 0 )
379
+ if ( _expect . Count > 0 )
359
380
{
360
- result = _encoding . GetString ( _incoming . ToArray ( ) , 0 , _incoming . Count ) ;
381
+ matchText = _encoding . GetString ( _expect . ToArray ( ) , 0 , _expect . Count ) ;
361
382
}
362
383
363
- var match = regex . Match ( result ) ;
384
+ var match = regex . Match ( matchText ) ;
364
385
365
386
if ( match . Success )
366
387
{
367
- result = result . Substring ( 0 , match . Index + match . Length ) ;
368
- var charCount = _encoding . GetByteCount ( result ) ;
388
+ returnText = matchText . Substring ( 0 , match . Index + match . Length ) ;
389
+ var returnLength = _encoding . GetByteCount ( returnText ) ;
369
390
370
391
// Remove processed items from the queue
371
- for ( var i = 0 ; i < charCount && _incoming . Count > 0 ; i ++ )
392
+ for ( var i = 0 ; i < returnLength && _incoming . Count > 0 ; i ++ )
372
393
{
394
+ if ( _expect . Count == _incoming . Count )
395
+ {
396
+ _ = _expect . Dequeue ( ) ;
397
+ }
398
+
373
399
_ = _incoming . Dequeue ( ) ;
374
400
}
375
401
@@ -390,7 +416,7 @@ public string Expect(Regex regex, TimeSpan timeout)
390
416
}
391
417
}
392
418
393
- return result ;
419
+ return returnText ;
394
420
}
395
421
396
422
/// <summary>
@@ -446,7 +472,8 @@ public IAsyncResult BeginExpect(AsyncCallback callback, object state, params Exp
446
472
public IAsyncResult BeginExpect ( TimeSpan timeout , AsyncCallback callback , object state , params ExpectAction [ ] expectActions )
447
473
#pragma warning restore CA1859 // Use concrete types when possible for improved performance
448
474
{
449
- var text = string . Empty ;
475
+ var matchText = string . Empty ;
476
+ string returnText ;
450
477
451
478
// Create new AsyncResult object
452
479
var asyncResult = new ExpectAsyncResult ( callback , state ) ;
@@ -461,31 +488,36 @@ public IAsyncResult BeginExpect(TimeSpan timeout, AsyncCallback callback, object
461
488
{
462
489
lock ( _incoming )
463
490
{
464
- if ( _incoming . Count > 0 )
491
+ if ( _expect . Count > 0 )
465
492
{
466
- text = _encoding . GetString ( _incoming . ToArray ( ) , 0 , _incoming . Count ) ;
493
+ matchText = _encoding . GetString ( _expect . ToArray ( ) , 0 , _expect . Count ) ;
467
494
}
468
495
469
- if ( text . Length > 0 )
496
+ if ( matchText . Length > 0 )
470
497
{
471
498
foreach ( var expectAction in expectActions )
472
499
{
473
- var match = expectAction . Expect . Match ( text ) ;
500
+ var match = expectAction . Expect . Match ( matchText ) ;
474
501
475
502
if ( match . Success )
476
503
{
477
- var result = text . Substring ( 0 , match . Index + match . Length ) ;
478
- var charCount = _encoding . GetByteCount ( result ) ;
504
+ returnText = matchText . Substring ( 0 , match . Index + match . Length ) ;
505
+ var returnLength = _encoding . GetByteCount ( returnText ) ;
479
506
480
- for ( var i = 0 ; i < match . Index + match . Length && _incoming . Count > 0 ; i ++ )
507
+ // Remove processed items from the queue
508
+ for ( var i = 0 ; i < returnLength && _incoming . Count > 0 ; i ++ )
481
509
{
482
- // Remove processed items from the queue
510
+ if ( _expect . Count == _incoming . Count )
511
+ {
512
+ _ = _expect . Dequeue ( ) ;
513
+ }
514
+
483
515
_ = _incoming . Dequeue ( ) ;
484
516
}
485
517
486
- expectAction . Action ( result ) ;
518
+ expectAction . Action ( returnText ) ;
487
519
callback ? . Invoke ( asyncResult ) ;
488
- expectActionResult = result ;
520
+ expectActionResult = returnText ;
489
521
}
490
522
}
491
523
}
@@ -584,6 +616,11 @@ public string ReadLine(TimeSpan timeout)
584
616
// remove processed bytes from the queue
585
617
for ( var i = 0 ; i < bytesProcessed ; i ++ )
586
618
{
619
+ if ( _expect . Count == _incoming . Count )
620
+ {
621
+ _ = _expect . Dequeue ( ) ;
622
+ }
623
+
587
624
_ = _incoming . Dequeue ( ) ;
588
625
}
589
626
@@ -620,6 +657,7 @@ public string Read()
620
657
lock ( _incoming )
621
658
{
622
659
text = _encoding . GetString ( _incoming . ToArray ( ) , 0 , _incoming . Count ) ;
660
+ _expect . Clear ( ) ;
623
661
_incoming . Clear ( ) ;
624
662
}
625
663
@@ -649,6 +687,11 @@ public override int Read(byte[] buffer, int offset, int count)
649
687
{
650
688
for ( ; i < count && _incoming . Count > 0 ; i ++ )
651
689
{
690
+ if ( _expect . Count == _incoming . Count )
691
+ {
692
+ _ = _expect . Dequeue ( ) ;
693
+ }
694
+
652
695
buffer [ offset + i ] = _incoming . Dequeue ( ) ;
653
696
}
654
697
}
@@ -800,6 +843,12 @@ private void Channel_DataReceived(object sender, ChannelDataEventArgs e)
800
843
foreach ( var b in e . Data )
801
844
{
802
845
_incoming . Enqueue ( b ) ;
846
+ if ( _expect . Count == _expectSize )
847
+ {
848
+ _ = _expect . Dequeue ( ) ;
849
+ }
850
+
851
+ _expect . Enqueue ( b ) ;
803
852
}
804
853
}
805
854
0 commit comments