http2: schedule RSTStream writes onto its stream's queue
Fixes golang/go#17243
Change-Id: I76f972f908757b103e2ab8d9b1701312308d66e5
Reviewed-on: https://go-review.googlesource.com/33238
Reviewed-by: Tom Bergan <tombergan@google.com>
diff --git a/http2/writesched.go b/http2/writesched.go
index 9f3e1b3..fb5da35 100644
--- a/http2/writesched.go
+++ b/http2/writesched.go
@@ -62,6 +62,13 @@
// 0 is used for non-stream frames such as PING and SETTINGS.
func (wr FrameWriteRequest) StreamID() uint32 {
if wr.stream == nil {
+ if se, ok := wr.write.(StreamError); ok {
+ // (*serverConn).resetStream doesn't set
+ // stream because it doesn't necessarily have
+ // one. So special case this type of write
+ // message.
+ return se.StreamID
+ }
return 0
}
return wr.stream.id
@@ -142,17 +149,13 @@
// String is for debugging only.
func (wr FrameWriteRequest) String() string {
- var streamID uint32
- if wr.stream != nil {
- streamID = wr.stream.id
- }
var des string
if s, ok := wr.write.(fmt.Stringer); ok {
des = s.String()
} else {
des = fmt.Sprintf("%T", wr.write)
}
- return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", streamID, wr.done != nil, des)
+ return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", wr.StreamID(), wr.done != nil, des)
}
// writeQueue is used by implementations of WriteScheduler.
diff --git a/http2/writesched_test.go b/http2/writesched_test.go
index 10d2362..0807056 100644
--- a/http2/writesched_test.go
+++ b/http2/writesched_test.go
@@ -115,3 +115,11 @@
t.Errorf("Consume(remainder):\n%v", err)
}
}
+
+func TestFrameWriteRequest_StreamID(t *testing.T) {
+ const streamID = 123
+ wr := FrameWriteRequest{write: streamError(streamID, ErrCodeNo)}
+ if got := wr.StreamID(); got != streamID {
+ t.Errorf("FrameWriteRequest(StreamError) = %v; want %v", got, streamID)
+ }
+}