@@ -146,10 +146,11 @@ type earlyAbortStream struct {
146
146
func (* earlyAbortStream ) isTransportResponseFrame () bool { return false }
147
147
148
148
type dataFrame struct {
149
- streamID uint32
150
- endStream bool
151
- h []byte
152
- reader mem.Reader
149
+ streamID uint32
150
+ endStream bool
151
+ h []byte
152
+ data mem.BufferSlice
153
+ processing bool
153
154
// onEachWrite is called every time
154
155
// a part of data is written out.
155
156
onEachWrite func ()
@@ -234,6 +235,7 @@ type outStream struct {
234
235
itl * itemList
235
236
bytesOutStanding int
236
237
wq * writeQuota
238
+ reader mem.Reader
237
239
238
240
next * outStream
239
241
prev * outStream
@@ -461,7 +463,9 @@ func (c *controlBuffer) finish() {
461
463
v .onOrphaned (ErrConnClosing )
462
464
}
463
465
case * dataFrame :
464
- _ = v .reader .Close ()
466
+ if ! v .processing {
467
+ v .data .Free ()
468
+ }
465
469
}
466
470
}
467
471
@@ -650,10 +654,11 @@ func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
650
654
651
655
func (l * loopyWriter ) registerStreamHandler (h * registerStream ) {
652
656
str := & outStream {
653
- id : h .streamID ,
654
- state : empty ,
655
- itl : & itemList {},
656
- wq : h .wq ,
657
+ id : h .streamID ,
658
+ state : empty ,
659
+ itl : & itemList {},
660
+ wq : h .wq ,
661
+ reader : mem.BufferSlice {}.Reader (),
657
662
}
658
663
l .estdStreams [h .streamID ] = str
659
664
}
@@ -685,10 +690,11 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
685
690
}
686
691
// Case 2: Client wants to originate stream.
687
692
str := & outStream {
688
- id : h .streamID ,
689
- state : empty ,
690
- itl : & itemList {},
691
- wq : h .wq ,
693
+ id : h .streamID ,
694
+ state : empty ,
695
+ itl : & itemList {},
696
+ wq : h .wq ,
697
+ reader : mem.BufferSlice {}.Reader (),
692
698
}
693
699
return l .originateStream (str , h )
694
700
}
@@ -790,10 +796,13 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
790
796
// a RST_STREAM before stream initialization thus the stream might
791
797
// not be established yet.
792
798
delete (l .estdStreams , c .streamID )
799
+ str .reader .Close ()
793
800
str .deleteSelf ()
794
801
for head := str .itl .dequeueAll (); head != nil ; head = head .next {
795
802
if df , ok := head .it .(* dataFrame ); ok {
796
- _ = df .reader .Close ()
803
+ if ! df .processing {
804
+ df .data .Free ()
805
+ }
797
806
}
798
807
}
799
808
}
@@ -928,21 +937,27 @@ func (l *loopyWriter) processData() (bool, error) {
928
937
if str == nil {
929
938
return true , nil
930
939
}
940
+ reader := str .reader
931
941
dataItem := str .itl .peek ().(* dataFrame ) // Peek at the first data item this stream.
942
+ if ! dataItem .processing {
943
+ dataItem .processing = true
944
+ str .reader .Reset (dataItem .data )
945
+ dataItem .data .Free ()
946
+ }
932
947
// A data item is represented by a dataFrame, since it later translates into
933
948
// multiple HTTP2 data frames.
934
949
// Every dataFrame has two buffers; h that keeps grpc-message header and data
935
950
// that is the actual message. As an optimization to keep wire traffic low, data
936
951
// from data is copied to h to make as big as the maximum possible HTTP2 frame
937
952
// size.
938
953
939
- if len (dataItem .h ) == 0 && dataItem . reader .Remaining () == 0 { // Empty data frame
954
+ if len (dataItem .h ) == 0 && reader .Remaining () == 0 { // Empty data frame
940
955
// Client sends out empty data frame with endStream = true
941
956
if err := l .framer .fr .WriteData (dataItem .streamID , dataItem .endStream , nil ); err != nil {
942
957
return false , err
943
958
}
944
959
str .itl .dequeue () // remove the empty data item from stream
945
- _ = dataItem . reader .Close ()
960
+ _ = reader .Close ()
946
961
if str .itl .isEmpty () {
947
962
str .state = empty
948
963
} else if trailer , ok := str .itl .peek ().(* headerFrame ); ok { // the next item is trailers.
@@ -971,8 +986,8 @@ func (l *loopyWriter) processData() (bool, error) {
971
986
}
972
987
// Compute how much of the header and data we can send within quota and max frame length
973
988
hSize := min (maxSize , len (dataItem .h ))
974
- dSize := min (maxSize - hSize , dataItem . reader .Remaining ())
975
- remainingBytes := len (dataItem .h ) + dataItem . reader .Remaining () - hSize - dSize
989
+ dSize := min (maxSize - hSize , reader .Remaining ())
990
+ remainingBytes := len (dataItem .h ) + reader .Remaining () - hSize - dSize
976
991
size := hSize + dSize
977
992
978
993
var buf * []byte
@@ -993,7 +1008,7 @@ func (l *loopyWriter) processData() (bool, error) {
993
1008
defer pool .Put (buf )
994
1009
995
1010
copy ((* buf )[:hSize ], dataItem .h )
996
- _ , _ = dataItem . reader .Read ((* buf )[hSize :])
1011
+ _ , _ = reader .Read ((* buf )[hSize :])
997
1012
}
998
1013
999
1014
// Now that outgoing flow controls are checked we can replenish str's write quota
@@ -1014,7 +1029,7 @@ func (l *loopyWriter) processData() (bool, error) {
1014
1029
dataItem .h = dataItem .h [hSize :]
1015
1030
1016
1031
if remainingBytes == 0 { // All the data from that message was written out.
1017
- _ = dataItem . reader .Close ()
1032
+ _ = reader .Close ()
1018
1033
str .itl .dequeue ()
1019
1034
}
1020
1035
if str .itl .isEmpty () {
0 commit comments