@@ -42,6 +42,7 @@ type Stream struct {
4242 state streamState
4343 writeState , readState halfStreamState
4444 stateLock sync.Mutex
45+ resetErr * StreamError
4546
4647 recvBuf segmentedBuffer
4748
@@ -89,6 +90,7 @@ func (s *Stream) Read(b []byte) (n int, err error) {
8990START:
9091 s .stateLock .Lock ()
9192 state := s .readState
93+ resetErr := s .resetErr
9294 s .stateLock .Unlock ()
9395
9496 switch state {
@@ -101,7 +103,7 @@ START:
101103 }
102104 // Closed, but we have data pending -> read.
103105 case halfReset :
104- return 0 , ErrStreamReset
106+ return 0 , resetErr
105107 default :
106108 panic ("unknown state" )
107109 }
@@ -147,6 +149,7 @@ func (s *Stream) write(b []byte) (n int, err error) {
147149START:
148150 s .stateLock .Lock ()
149151 state := s .writeState
152+ resetErr := s .resetErr
150153 s .stateLock .Unlock ()
151154
152155 switch state {
@@ -155,7 +158,7 @@ START:
155158 case halfClosed :
156159 return 0 , ErrStreamClosed
157160 case halfReset :
158- return 0 , ErrStreamReset
161+ return 0 , resetErr
159162 default :
160163 panic ("unknown state" )
161164 }
@@ -250,13 +253,17 @@ func (s *Stream) sendClose() error {
250253}
251254
252255// sendReset is used to send a RST
253- func (s * Stream ) sendReset () error {
254- hdr := encode (typeWindowUpdate , flagRST , s .id , 0 )
256+ func (s * Stream ) sendReset (errCode uint32 ) error {
257+ hdr := encode (typeWindowUpdate , flagRST , s .id , errCode )
255258 return s .session .sendMsg (hdr , nil , nil )
256259}
257260
258261// Reset resets the stream (forcibly closes the stream)
259262func (s * Stream ) Reset () error {
263+ return s .ResetWithError (0 )
264+ }
265+
266+ func (s * Stream ) ResetWithError (errCode uint32 ) error {
260267 sendReset := false
261268 s .stateLock .Lock ()
262269 switch s .state {
@@ -281,10 +288,11 @@ func (s *Stream) Reset() error {
281288 s .readState = halfReset
282289 }
283290 s .state = streamFinished
291+ s .resetErr = & StreamError {Remote : false , ErrorCode : errCode }
284292 s .notifyWaiting ()
285293 s .stateLock .Unlock ()
286294 if sendReset {
287- _ = s .sendReset ()
295+ _ = s .sendReset (errCode )
288296 }
289297 s .cleanup ()
290298 return nil
@@ -382,7 +390,7 @@ func (s *Stream) cleanup() {
382390
383391// processFlags is used to update the state of the stream
384392// based on set flags, if any. Lock must be held
385- func (s * Stream ) processFlags (flags uint16 ) {
393+ func (s * Stream ) processFlags (flags uint16 , hdr header ) {
386394 // Close the stream without holding the state lock
387395 var closeStream bool
388396 defer func () {
@@ -425,6 +433,10 @@ func (s *Stream) processFlags(flags uint16) {
425433 s .writeState = halfReset
426434 }
427435 s .state = streamFinished
436+ // Length in a window update frame with RST flag encodes an error code.
437+ if hdr .MsgType () == typeWindowUpdate && s .resetErr == nil {
438+ s .resetErr = & StreamError {Remote : true , ErrorCode : hdr .Length ()}
439+ }
428440 s .stateLock .Unlock ()
429441 closeStream = true
430442 s .notifyWaiting ()
@@ -439,15 +451,15 @@ func (s *Stream) notifyWaiting() {
439451
440452// incrSendWindow updates the size of our send window
441453func (s * Stream ) incrSendWindow (hdr header , flags uint16 ) {
442- s .processFlags (flags )
454+ s .processFlags (flags , hdr )
443455 // Increase window, unblock a sender
444456 atomic .AddUint32 (& s .sendWindow , hdr .Length ())
445457 asyncNotify (s .sendNotifyCh )
446458}
447459
448460// readData is used to handle a data frame
449461func (s * Stream ) readData (hdr header , flags uint16 , conn io.Reader ) error {
450- s .processFlags (flags )
462+ s .processFlags (flags , hdr )
451463
452464 // Check that our recv window is not exceeded
453465 length := hdr .Length ()
0 commit comments