@@ -272,10 +272,11 @@ public async Task RequestProcessingAsync()
272
272
273
273
HttpContextFactory . Dispose ( httpContext ) ;
274
274
275
+ await ProduceEnd ( ) ;
276
+
275
277
var memoryBlock = Memory2 . Lease ( ) ;
276
278
try
277
279
{
278
- await ProduceEnd ( memoryBlock ) ;
279
280
280
281
var segment = memoryBlock . Data ;
281
282
while ( await RequestBody . ReadAsync ( segment . Array , segment . Offset , segment . Count ) != 0 )
@@ -393,43 +394,19 @@ private async Task FireOnCompleted()
393
394
394
395
public void Flush ( )
395
396
{
396
- var memoryBlock = Memory2 . Lease ( ) ;
397
- try
398
- {
399
- ProduceStartAndFireOnStarting ( memoryBlock , immediate : false ) . GetAwaiter ( ) . GetResult ( ) ;
400
- }
401
- finally
402
- {
403
- Memory2 . Return ( memoryBlock ) ;
404
- }
397
+ ProduceStartAndFireOnStarting ( immediate : false ) . GetAwaiter ( ) . GetResult ( ) ;
405
398
SocketOutput . Write ( _emptyData , immediate : true ) ;
406
399
}
407
400
408
401
public async Task FlushAsync ( CancellationToken cancellationToken )
409
402
{
410
- var memoryBlock = Memory2 . Lease ( ) ;
411
- try
412
- {
413
- await ProduceStartAndFireOnStarting ( memoryBlock , immediate : false ) ;
414
- }
415
- finally
416
- {
417
- Memory2 . Return ( memoryBlock ) ;
418
- }
403
+ await ProduceStartAndFireOnStarting ( immediate : false ) ;
419
404
await SocketOutput . WriteAsync ( _emptyData , immediate : true , cancellationToken : cancellationToken ) ;
420
405
}
421
406
422
407
public void Write ( ArraySegment < byte > data )
423
408
{
424
- var memoryBlock = Memory2 . Lease ( ) ;
425
- try
426
- {
427
- ProduceStartAndFireOnStarting ( memoryBlock , immediate : false ) . GetAwaiter ( ) . GetResult ( ) ;
428
- }
429
- finally
430
- {
431
- Memory2 . Return ( memoryBlock ) ;
432
- }
409
+ ProduceStartAndFireOnStarting ( immediate : false ) . GetAwaiter ( ) . GetResult ( ) ;
433
410
434
411
if ( _autoChunk )
435
412
{
@@ -447,15 +424,7 @@ public void Write(ArraySegment<byte> data)
447
424
448
425
public async Task WriteAsync ( ArraySegment < byte > data , CancellationToken cancellationToken )
449
426
{
450
- var memoryBlock = Memory2 . Lease ( ) ;
451
- try
452
- {
453
- await ProduceStartAndFireOnStarting ( memoryBlock , immediate : false ) ;
454
- }
455
- finally
456
- {
457
- Memory2 . Return ( memoryBlock ) ;
458
- }
427
+ await ProduceStartAndFireOnStarting ( immediate : false ) ;
459
428
460
429
if ( _autoChunk )
461
430
{
@@ -538,7 +507,7 @@ public void ProduceContinue()
538
507
}
539
508
}
540
509
541
- public async Task ProduceStartAndFireOnStarting ( MemoryPoolBlock2 memoryBlock , bool immediate = true )
510
+ public async Task ProduceStartAndFireOnStarting ( bool immediate = true )
542
511
{
543
512
if ( _responseStarted ) return ;
544
513
@@ -551,11 +520,10 @@ public async Task ProduceStartAndFireOnStarting(MemoryPoolBlock2 memoryBlock, bo
551
520
_applicationException ) ;
552
521
}
553
522
554
- await ProduceStart ( memoryBlock , immediate , appCompleted : false ) ;
523
+ await ProduceStart ( immediate , appCompleted : false ) ;
555
524
}
556
525
557
526
private Task ProduceStart (
558
- MemoryPoolBlock2 memoryBlock ,
559
527
bool immediate ,
560
528
bool appCompleted )
561
529
{
@@ -564,10 +532,10 @@ private Task ProduceStart(
564
532
565
533
var statusBytes = ReasonPhrases . ToStatusBytes ( StatusCode , ReasonPhrase ) ;
566
534
567
- return CreateResponseHeader ( statusBytes , memoryBlock , appCompleted , immediate ) ;
535
+ return CreateResponseHeader ( statusBytes , appCompleted , immediate ) ;
568
536
}
569
537
570
- private async Task ProduceEnd ( MemoryPoolBlock2 memoryBlock )
538
+ private async Task ProduceEnd ( )
571
539
{
572
540
if ( _applicationException != null )
573
541
{
@@ -587,7 +555,7 @@ private async Task ProduceEnd(MemoryPoolBlock2 memoryBlock)
587
555
}
588
556
}
589
557
590
- await ProduceStart ( memoryBlock , immediate : true , appCompleted : true ) ;
558
+ await ProduceStart ( immediate : true , appCompleted : true ) ;
591
559
592
560
// _autoChunk should be checked after we are sure ProduceStart() has been called
593
561
// since ProduceStart() may set _autoChunk to true.
@@ -602,12 +570,12 @@ private async Task ProduceEnd(MemoryPoolBlock2 memoryBlock)
602
570
}
603
571
}
604
572
605
- private static void OutputAsciiBlock ( string data , MemoryPoolBlock2 memoryBlock , ISocketOutput output )
573
+ private static void OutputAsciiBlock ( string data , ref MemoryPoolBlock2 currentMemoryBlock , MemoryPool2 memory , ISocketOutput output )
606
574
{
607
- var start = memoryBlock . Start ;
608
- var end = start + memoryBlock . Data . Count ;
609
- var array = memoryBlock . Array ;
610
- var current = memoryBlock . End ;
575
+ var start = currentMemoryBlock . Start ;
576
+ var end = start + currentMemoryBlock . Data . Count ;
577
+ var array = currentMemoryBlock . Array ;
578
+ var current = currentMemoryBlock . End ;
611
579
612
580
foreach ( var chr in data )
613
581
{
@@ -617,22 +585,31 @@ private static void OutputAsciiBlock(string data, MemoryPoolBlock2 memoryBlock,
617
585
618
586
if ( current == end )
619
587
{
620
- output . Write ( memoryBlock . Data , immediate : false ) ;
588
+ var socketOutput = output as SocketOutput ;
589
+ if ( socketOutput != null )
590
+ {
591
+ socketOutput . WriteAsync ( currentMemoryBlock , immediate : false ) ;
592
+ currentMemoryBlock = memory . Lease ( ) ;
593
+ }
594
+ else
595
+ {
596
+ output . Write ( currentMemoryBlock . Data , immediate : false ) ;
597
+ }
621
598
current = start ;
622
599
}
623
600
}
624
- memoryBlock . End = current ;
601
+ currentMemoryBlock . End = current ;
625
602
}
626
603
627
- private static void OutputAsciiBlock ( byte [ ] data , MemoryPoolBlock2 memoryBlock , ISocketOutput output )
604
+ private static void OutputAsciiBlock ( byte [ ] data , ref MemoryPoolBlock2 currentMemoryBlock , MemoryPool2 memory , ISocketOutput output )
628
605
{
629
606
var offset = 0 ;
630
607
var remaining = data . Length ;
631
608
632
- var start = memoryBlock . Start ;
633
- var end = start + memoryBlock . Data . Count ;
634
- var array = memoryBlock . Array ;
635
- var current = memoryBlock . End ;
609
+ var start = currentMemoryBlock . Start ;
610
+ var end = start + currentMemoryBlock . Data . Count ;
611
+ var array = currentMemoryBlock . Array ;
612
+ var current = currentMemoryBlock . End ;
636
613
637
614
while ( remaining > 0 )
638
615
{
@@ -646,97 +623,130 @@ private static void OutputAsciiBlock(byte[] data, MemoryPoolBlock2 memoryBlock,
646
623
647
624
if ( current == end )
648
625
{
649
- output . Write ( memoryBlock . Data , immediate : false ) ;
626
+ var socketOutput = output as SocketOutput ;
627
+ if ( socketOutput != null )
628
+ {
629
+ socketOutput . WriteAsync ( currentMemoryBlock , immediate : false ) ;
630
+ currentMemoryBlock = memory . Lease ( ) ;
631
+ }
632
+ else
633
+ {
634
+ output . Write ( currentMemoryBlock . Data , immediate : false ) ;
635
+ }
650
636
current = start ;
651
637
}
652
638
}
653
- memoryBlock . End = current ;
639
+ currentMemoryBlock . End = current ;
654
640
}
655
641
656
642
private Task CreateResponseHeader (
657
643
byte [ ] statusBytes ,
658
- MemoryPoolBlock2 memoryBlock ,
659
644
bool appCompleted ,
660
645
bool immediate )
661
646
{
662
- var blockRemaining = memoryBlock . Data . Count ;
663
647
664
- OutputAsciiBlock ( _httpVersion == HttpVersionType . Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0 , memoryBlock , SocketOutput ) ;
648
+ var memoryBlock = Memory2 . Lease ( ) ;
649
+ try
650
+ {
651
+ var blockRemaining = memoryBlock . Data . Count ;
665
652
666
- OutputAsciiBlock ( statusBytes , memoryBlock , SocketOutput ) ;
653
+ OutputAsciiBlock ( _httpVersion == HttpVersionType . Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0 , ref memoryBlock , Memory2 , SocketOutput ) ;
667
654
668
- if ( _responseHeaders . HasDefaultDate )
669
- {
670
- OutputAsciiBlock ( _bytesDate , memoryBlock , SocketOutput ) ;
671
- OutputAsciiBlock ( DateHeaderValueManager . GetDateHeaderValueBytes ( ) , memoryBlock , SocketOutput ) ;
672
- OutputAsciiBlock ( _bytesEndLine , memoryBlock , SocketOutput ) ;
673
- }
655
+ OutputAsciiBlock ( statusBytes , ref memoryBlock , Memory2 , SocketOutput ) ;
674
656
675
- foreach ( var header in _responseHeaders . AsOutputEnumerable ( ) )
676
- {
677
- foreach ( var value in header . Value )
657
+ if ( _responseHeaders . HasDefaultDate )
678
658
{
679
- OutputAsciiBlock ( header . Key , memoryBlock , SocketOutput ) ;
680
- OutputAsciiBlock ( value , memoryBlock , SocketOutput ) ;
681
- OutputAsciiBlock ( _bytesEndLine , memoryBlock , SocketOutput ) ;
659
+ OutputAsciiBlock ( _bytesDate , ref memoryBlock , Memory2 , SocketOutput ) ;
660
+ OutputAsciiBlock ( DateHeaderValueManager . GetDateHeaderValueBytes ( ) , ref memoryBlock , Memory2 , SocketOutput ) ;
661
+ OutputAsciiBlock ( _bytesEndLine , ref memoryBlock , Memory2 , SocketOutput ) ;
662
+ }
682
663
683
- if ( _responseHeaders . HasConnection && value . IndexOf ( "close" , StringComparison . OrdinalIgnoreCase ) != - 1 )
664
+ foreach ( var header in _responseHeaders . AsOutputEnumerable ( ) )
665
+ {
666
+ foreach ( var value in header . Value )
684
667
{
685
- _keepAlive = false ;
668
+ OutputAsciiBlock ( header . Key , ref memoryBlock , Memory2 , SocketOutput ) ;
669
+ OutputAsciiBlock ( value , ref memoryBlock , Memory2 , SocketOutput ) ;
670
+ OutputAsciiBlock ( _bytesEndLine , ref memoryBlock , Memory2 , SocketOutput ) ;
671
+
672
+ if ( _responseHeaders . HasConnection && value . IndexOf ( "close" , StringComparison . OrdinalIgnoreCase ) != - 1 )
673
+ {
674
+ _keepAlive = false ;
675
+ }
686
676
}
687
677
}
688
- }
689
-
690
- if ( _responseHeaders . HasDefaultServer )
691
- {
692
- OutputAsciiBlock ( _bytesServer , memoryBlock , SocketOutput ) ;
693
- }
694
678
695
- if ( _keepAlive && ! _responseHeaders . HasTransferEncoding && ! _responseHeaders . HasContentLength )
696
- {
697
- if ( appCompleted )
679
+ if ( _responseHeaders . HasDefaultServer )
698
680
{
699
- // Don't set the Content-Length or Transfer-Encoding headers
700
- // automatically for HEAD requests or 101, 204, 205, 304 responses.
701
- if ( Method != "HEAD" && StatusCanHaveBody ( StatusCode ) )
702
- {
703
- // Since the app has completed and we are only now generating
704
- // the headers we can safely set the Content-Length to 0.
705
- OutputAsciiBlock ( _bytesContentLengthZero , memoryBlock , SocketOutput ) ;
706
- }
681
+ OutputAsciiBlock ( _bytesServer , ref memoryBlock , Memory2 , SocketOutput ) ;
707
682
}
708
- else
683
+
684
+ if ( _keepAlive && ! _responseHeaders . HasTransferEncoding && ! _responseHeaders . HasContentLength )
709
685
{
710
- if ( _httpVersion == HttpVersionType . Http1_1 )
686
+ if ( appCompleted )
711
687
{
712
- _autoChunk = true ;
713
- OutputAsciiBlock ( _bytesTransferEncodingChunked , memoryBlock , SocketOutput ) ;
688
+ // Don't set the Content-Length or Transfer-Encoding headers
689
+ // automatically for HEAD requests or 101, 204, 205, 304 responses.
690
+ if ( Method != "HEAD" && StatusCanHaveBody ( StatusCode ) )
691
+ {
692
+ // Since the app has completed and we are only now generating
693
+ // the headers we can safely set the Content-Length to 0.
694
+ OutputAsciiBlock ( _bytesContentLengthZero , ref memoryBlock , Memory2 , SocketOutput ) ;
695
+ }
714
696
}
715
697
else
716
698
{
717
- _keepAlive = false ;
699
+ if ( _httpVersion == HttpVersionType . Http1_1 )
700
+ {
701
+ _autoChunk = true ;
702
+ OutputAsciiBlock ( _bytesTransferEncodingChunked , ref memoryBlock , Memory2 , SocketOutput ) ;
703
+ }
704
+ else
705
+ {
706
+ _keepAlive = false ;
707
+ }
718
708
}
719
709
}
720
- }
721
710
722
- if ( _keepAlive == false && _responseHeaders . HasConnection == false && _httpVersion == HttpVersionType . Http1_1 )
711
+ if ( _keepAlive == false && _responseHeaders . HasConnection == false && _httpVersion == HttpVersionType . Http1_1 )
712
+ {
713
+ OutputAsciiBlock ( _bytesConnectionClose , ref memoryBlock , Memory2 , SocketOutput ) ;
714
+ }
715
+ else if ( _keepAlive && _responseHeaders . HasConnection == false && _httpVersion == HttpVersionType . Http1_0 )
716
+ {
717
+ OutputAsciiBlock ( _bytesConnectionKeepAlive , ref memoryBlock , Memory2 , SocketOutput ) ;
718
+ }
719
+ else
720
+ {
721
+ OutputAsciiBlock ( _bytesEndLine , ref memoryBlock , Memory2 , SocketOutput ) ;
722
+ }
723
+ }
724
+ catch
723
725
{
724
- OutputAsciiBlock ( _bytesConnectionClose , memoryBlock , SocketOutput ) ;
726
+ Memory2 . Return ( memoryBlock ) ;
727
+ throw ;
725
728
}
726
- else if ( _keepAlive && _responseHeaders . HasConnection == false && _httpVersion == HttpVersionType . Http1_0 )
729
+ var socketOutput = SocketOutput as SocketOutput ;
730
+
731
+ if ( socketOutput != null )
727
732
{
728
- OutputAsciiBlock ( _bytesConnectionKeepAlive , memoryBlock , SocketOutput ) ;
733
+ return socketOutput . WriteAsync ( memoryBlock , immediate : immediate ) ;
729
734
}
730
735
else
731
736
{
732
- OutputAsciiBlock ( _bytesEndLine , memoryBlock , SocketOutput ) ;
737
+ try
738
+ {
739
+ return SocketOutput . WriteAsync (
740
+ ( memoryBlock . Start == memoryBlock . End ) ?
741
+ default ( ArraySegment < byte > ) :
742
+ new ArraySegment < byte > ( memoryBlock . Array , memoryBlock . Start , memoryBlock . End - memoryBlock . Start ) ,
743
+ immediate ) ;
744
+ }
745
+ finally
746
+ {
747
+ Memory2 . Return ( memoryBlock ) ;
748
+ }
733
749
}
734
-
735
- return SocketOutput . WriteAsync (
736
- ( memoryBlock . Start == memoryBlock . End ) ?
737
- default ( ArraySegment < byte > ) :
738
- new ArraySegment < byte > ( memoryBlock . Array , memoryBlock . Start , memoryBlock . End - memoryBlock . Start ) ,
739
- immediate ) ;
740
750
}
741
751
742
752
private bool TakeStartLine ( SocketInput input )
0 commit comments