35
35
using System . IO . Pipelines ;
36
36
using System . Net ;
37
37
using System . Net . Sockets ;
38
- using System . Text ;
39
38
using System . Threading ;
40
39
using System . Threading . Channels ;
41
40
using System . Threading . Tasks ;
@@ -226,37 +225,32 @@ public void Close()
226
225
{
227
226
if ( ! _closed )
228
227
{
229
- try
230
- {
231
- _channelWriter . Complete ( ) ;
232
- _writerTask . GetAwaiter ( ) . GetResult ( ) ;
233
- _pipeReader . Complete ( ) ;
234
- _pipeWriter . Complete ( ) ;
235
- }
236
- catch ( Exception )
237
- {
238
- }
228
+ _channelWriter . TryComplete ( ) ;
229
+ _frameWriter . TryComplete ( ) ;
230
+ try { _writerTask . GetAwaiter ( ) . GetResult ( ) ; } catch { }
239
231
240
- try
241
- {
242
- _socket . Close ( ) ;
243
- }
244
- catch ( Exception )
245
- {
246
- // ignore, we are closing anyway
247
- }
248
- finally
232
+ if ( _pipe != null )
249
233
{
250
- _closed = true ;
234
+ try { _pipe . Input ? . CancelPendingRead ( ) ; } catch { }
235
+ try { _pipe . Input ? . Complete ( ) ; } catch { }
236
+ try { _pipe . Output ? . CancelPendingFlush ( ) ; } catch { }
237
+ try { _pipe . Output ? . Complete ( ) ; } catch { }
238
+ try { using ( _pipe as IDisposable ) { } } catch { }
251
239
}
240
+
241
+ try { _socket . Close ( ) ; } catch { }
242
+ _closed = true ;
252
243
}
253
244
}
254
245
}
255
246
256
247
public void SendHeader ( )
257
248
{
258
- byte [ ] headerBytes = ArrayPool < byte > . Shared . Rent ( 8 ) ;
259
- Encoding . ASCII . GetBytes ( "AMQP" , 0 , 4 , headerBytes , 0 ) ;
249
+ Span < byte > headerBytes = stackalloc byte [ 8 ] ;
250
+ headerBytes [ 0 ] = ( byte ) 'A' ;
251
+ headerBytes [ 1 ] = ( byte ) 'M' ;
252
+ headerBytes [ 2 ] = ( byte ) 'Q' ;
253
+ headerBytes [ 3 ] = ( byte ) 'P' ;
260
254
if ( Endpoint . Protocol . Revision != 0 )
261
255
{
262
256
headerBytes [ 4 ] = 0 ;
@@ -272,8 +266,10 @@ public void SendHeader()
272
266
headerBytes [ 7 ] = ( byte ) Endpoint . Protocol . MinorVersion ;
273
267
}
274
268
275
- _pipeWriter . WriteAsync ( headerBytes . AsMemory ( 0 , 8 ) ) . AsTask ( ) . GetAwaiter ( ) . GetResult ( ) ;
276
- ArrayPool < byte > . Shared . Return ( headerBytes ) ;
269
+ Memory < byte > pipeMemory = _pipeWriter . GetMemory ( 8 ) ;
270
+ headerBytes . CopyTo ( pipeMemory . Span ) ;
271
+ _pipeWriter . Advance ( headerBytes . Length ) ;
272
+ _pipeWriter . FlushAsync ( ) . AsTask ( ) . GetAwaiter ( ) . GetResult ( ) ;
277
273
}
278
274
279
275
public void Write ( OutgoingFrame frame )
@@ -283,28 +279,51 @@ public void Write(OutgoingFrame frame)
283
279
284
280
private async Task ReadLoop ( )
285
281
{
286
- while ( ! FrameReader . Completion . IsCompleted )
282
+ bool allowSync = true ;
283
+ try
287
284
{
288
- // Let's read some bytes
289
- if ( ! _pipeReader . TryRead ( out ReadResult readResult ) )
285
+ while ( true )
290
286
{
291
- readResult = await _pipeReader . ReadAsync ( ) . ConfigureAwait ( false ) ;
292
- }
287
+ // Let's read some bytes
288
+ if ( ! ( allowSync && _pipeReader . TryRead ( out ReadResult readResult ) ) )
289
+ {
290
+ readResult = await _pipeReader . ReadAsync ( ) . ConfigureAwait ( false ) ;
291
+ }
293
292
294
- ReadOnlySequence < byte > buffer = readResult . Buffer ;
295
- if ( buffer . IsEmpty )
296
- {
297
- _frameWriter . Complete ( new EndOfStreamException ( ) ) ;
298
- return ;
299
- }
293
+ int handled = 0 ;
294
+ ReadOnlySequence < byte > buffer = readResult . Buffer ;
295
+ if ( ! buffer . IsEmpty )
296
+ {
297
+ handled = ProcessBuffer ( ref buffer ) ;
298
+ }
300
299
301
- while ( InboundFrame . TryReadFrame ( ref buffer , out InboundFrame frame ) )
302
- {
303
- _frameWriter . TryWrite ( frame ) ;
300
+ allowSync = handled != 0 ;
301
+ _pipeReader . AdvanceTo ( buffer . Start , buffer . End ) ;
302
+
303
+ if ( handled == 0 && readResult . IsCompleted )
304
+ {
305
+ break ;
306
+ }
304
307
}
308
+ }
309
+ catch ( Exception e )
310
+ {
311
+ _frameWriter . TryComplete ( e ) ;
312
+ }
313
+
314
+ _frameWriter . TryComplete ( new EndOfStreamException ( ) ) ;
315
+ }
305
316
306
- _pipeReader . AdvanceTo ( buffer . Start , buffer . End ) ;
317
+ private int ProcessBuffer ( ref ReadOnlySequence < byte > buffer )
318
+ {
319
+ int handled = 0 ;
320
+ while ( InboundFrame . TryReadFrame ( ref buffer , out InboundFrame frame ) )
321
+ {
322
+ _frameWriter . TryWrite ( frame ) ;
323
+ handled ++ ;
307
324
}
325
+
326
+ return handled ;
308
327
}
309
328
310
329
private async Task WriteLoop ( )
0 commit comments