@@ -157,10 +157,11 @@ type earlyAbortStream struct {
157157func (* earlyAbortStream ) isTransportResponseFrame () bool { return false }
158158
159159type dataFrame struct {
160- streamID uint32
161- endStream bool
162- h []byte
163- reader mem.Reader
160+ streamID uint32
161+ endStream bool
162+ h []byte
163+ data mem.BufferSlice
164+ processing bool
164165 // onEachWrite is called every time
165166 // a part of data is written out.
166167 onEachWrite func ()
@@ -245,6 +246,7 @@ type outStream struct {
245246 itl * itemList
246247 bytesOutStanding int
247248 wq * writeQuota
249+ reader mem.Reader
248250
249251 next * outStream
250252 prev * outStream
@@ -472,7 +474,9 @@ func (c *controlBuffer) finish() {
472474 v .onOrphaned (ErrConnClosing )
473475 }
474476 case * dataFrame :
475- _ = v .reader .Close ()
477+ if ! v .processing {
478+ v .data .Free ()
479+ }
476480 }
477481 }
478482
@@ -661,10 +665,11 @@ func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
661665
662666func (l * loopyWriter ) registerStreamHandler (h * registerStream ) {
663667 str := & outStream {
664- id : h .streamID ,
665- state : empty ,
666- itl : & itemList {},
667- wq : h .wq ,
668+ id : h .streamID ,
669+ state : empty ,
670+ itl : & itemList {},
671+ wq : h .wq ,
672+ reader : mem.BufferSlice {}.Reader (),
668673 }
669674 l .estdStreams [h .streamID ] = str
670675}
@@ -696,10 +701,11 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error {
696701 }
697702 // Case 2: Client wants to originate stream.
698703 str := & outStream {
699- id : h .streamID ,
700- state : empty ,
701- itl : & itemList {},
702- wq : h .wq ,
704+ id : h .streamID ,
705+ state : empty ,
706+ itl : & itemList {},
707+ wq : h .wq ,
708+ reader : mem.BufferSlice {}.Reader (),
703709 }
704710 return l .originateStream (str , h )
705711}
@@ -801,10 +807,13 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
801807 // a RST_STREAM before stream initialization thus the stream might
802808 // not be established yet.
803809 delete (l .estdStreams , c .streamID )
810+ str .reader .Close ()
804811 str .deleteSelf ()
805812 for head := str .itl .dequeueAll (); head != nil ; head = head .next {
806813 if df , ok := head .it .(* dataFrame ); ok {
807- _ = df .reader .Close ()
814+ if ! df .processing {
815+ df .data .Free ()
816+ }
808817 }
809818 }
810819 }
@@ -939,21 +948,27 @@ func (l *loopyWriter) processData() (bool, error) {
939948 if str == nil {
940949 return true , nil
941950 }
951+ reader := str .reader
942952 dataItem := str .itl .peek ().(* dataFrame ) // Peek at the first data item this stream.
953+ if ! dataItem .processing {
954+ dataItem .processing = true
955+ str .reader .Reset (dataItem .data )
956+ dataItem .data .Free ()
957+ }
943958 // A data item is represented by a dataFrame, since it later translates into
944959 // multiple HTTP2 data frames.
945960 // Every dataFrame has two buffers; h that keeps grpc-message header and data
946961 // that is the actual message. As an optimization to keep wire traffic low, data
947962 // from data is copied to h to make as big as the maximum possible HTTP2 frame
948963 // size.
949964
950- if len (dataItem .h ) == 0 && dataItem . reader .Remaining () == 0 { // Empty data frame
965+ if len (dataItem .h ) == 0 && reader .Remaining () == 0 { // Empty data frame
951966 // Client sends out empty data frame with endStream = true
952967 if err := l .framer .fr .WriteData (dataItem .streamID , dataItem .endStream , nil ); err != nil {
953968 return false , err
954969 }
955970 str .itl .dequeue () // remove the empty data item from stream
956- _ = dataItem . reader .Close ()
971+ _ = reader .Close ()
957972 if str .itl .isEmpty () {
958973 str .state = empty
959974 } else if trailer , ok := str .itl .peek ().(* headerFrame ); ok { // the next item is trailers.
@@ -982,8 +997,8 @@ func (l *loopyWriter) processData() (bool, error) {
982997 }
983998 // Compute how much of the header and data we can send within quota and max frame length
984999 hSize := min (maxSize , len (dataItem .h ))
985- dSize := min (maxSize - hSize , dataItem . reader .Remaining ())
986- remainingBytes := len (dataItem .h ) + dataItem . reader .Remaining () - hSize - dSize
1000+ dSize := min (maxSize - hSize , reader .Remaining ())
1001+ remainingBytes := len (dataItem .h ) + reader .Remaining () - hSize - dSize
9871002 size := hSize + dSize
9881003
9891004 var buf * []byte
@@ -1004,7 +1019,7 @@ func (l *loopyWriter) processData() (bool, error) {
10041019 defer pool .Put (buf )
10051020
10061021 copy ((* buf )[:hSize ], dataItem .h )
1007- _ , _ = dataItem . reader .Read ((* buf )[hSize :])
1022+ _ , _ = reader .Read ((* buf )[hSize :])
10081023 }
10091024
10101025 // Now that outgoing flow controls are checked we can replenish str's write quota
@@ -1025,7 +1040,7 @@ func (l *loopyWriter) processData() (bool, error) {
10251040 dataItem .h = dataItem .h [hSize :]
10261041
10271042 if remainingBytes == 0 { // All the data from that message was written out.
1028- _ = dataItem . reader .Close ()
1043+ _ = reader .Close ()
10291044 str .itl .dequeue ()
10301045 }
10311046 if str .itl .isEmpty () {
0 commit comments