From b20c055230a20663c75e3099f672c15c39d46b9e Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 10 Nov 2016 22:53:16 +0000 Subject: net/http: update bundled http2 Updates http2 to x/net/http2 git rev 9ef22118 for: http2: fix CloseNotify data race https://golang.org/cl/33013 http2: don't overflow stream IDs in server push https://golang.org/cl/32488 http2: disable server push on receiving a GOAWAY https://golang.org/cl/32887 http2: fix state tracking for pushed streams https://golang.org/cl/32755 Change-Id: Ie7d675857423c102c9ec164d3c943093c749c7cf Reviewed-on: https://go-review.googlesource.com/33100 Reviewed-by: Tom Bergan Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/net/http/h2_bundle.go | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 6367d20aac..f606098796 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -3206,8 +3206,8 @@ type http2serverConn struct { advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client curClientStreams uint32 // number of open streams initiated by the client curPushedStreams uint32 // number of open streams initiated by server push - maxStreamID uint32 // max ever seen from client - maxPushPromiseID uint32 // ID of the last push promise, or 0 if there have been no pushes + maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests + maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes streams map[uint32]*http2stream initialWindowSize int32 maxFrameSize int32 @@ -3295,8 +3295,14 @@ func (sc *http2serverConn) state(streamID uint32) (http2streamState, *http2strea return st.state, st } - if streamID <= sc.maxStreamID { - return http2stateClosed, nil + if streamID%2 == 1 { + if streamID <= sc.maxClientStreamID { + return http2stateClosed, nil + } + } else { + if streamID <= sc.maxPushPromiseID { + return http2stateClosed, nil + } } return http2stateIdle, nil } @@ -3797,7 +3803,7 @@ func (sc *http2serverConn) scheduleFrameWrite() { sc.needToSendGoAway = false sc.startFrameWrite(http2FrameWriteRequest{ write: &http2writeGoAway{ - maxStreamID: sc.maxStreamID, + maxStreamID: sc.maxClientStreamID, code: sc.goAwayCode, }, }) @@ -3938,6 +3944,8 @@ func (sc *http2serverConn) processFrame(f http2Frame) error { return sc.processResetStream(f) case *http2PriorityFrame: return sc.processPriority(f) + case *http2GoAwayFrame: + return sc.processGoAway(f) case *http2PushPromiseFrame: return http2ConnectionError(http2ErrCodeProtocol) @@ -4158,6 +4166,19 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { return nil } +func (sc *http2serverConn) processGoAway(f *http2GoAwayFrame) error { + sc.serveG.check() + if f.ErrCode != http2ErrCodeNo { + sc.logf("http2: received GOAWAY %+v, starting graceful shutdown", f) + } else { + sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f) + } + sc.goAwayIn(http2ErrCodeNo, 0) + + sc.pushEnabled = false + return nil +} + // isPushed reports whether the stream is server-initiated. func (st *http2stream) isPushed() bool { return st.id%2 == 0 @@ -4206,10 +4227,10 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { return st.processTrailerHeaders(f) } - if id <= sc.maxStreamID { + if id <= sc.maxClientStreamID { return http2ConnectionError(http2ErrCodeProtocol) } - sc.maxStreamID = id + sc.maxClientStreamID = id if sc.idleTimer != nil { sc.idleTimer.Stop() @@ -4926,8 +4947,9 @@ func (w *http2responseWriter) CloseNotify() <-chan bool { if ch == nil { ch = make(chan bool, 1) rws.closeNotifierCh = ch + cw := rws.stream.cw go func() { - rws.stream.cw.Wait() + cw.Wait() ch <- true }() } @@ -5152,6 +5174,10 @@ func (sc *http2serverConn) startPush(msg http2startPushRequest) { return 0, http2ErrPushLimitReached } + if sc.maxPushPromiseID+2 >= 1<<31 { + sc.goAwayIn(http2ErrCodeNo, 0) + return 0, http2ErrPushLimitReached + } sc.maxPushPromiseID += 2 promisedID := sc.maxPushPromiseID -- cgit v1.2.3-54-g00ecf