Commit 651d3923 authored by Chris Broadfoot's avatar Chris Broadfoot

net/http: update bundled http2

Updates bundled x/net/http2 to git rev 1195a05d for:

    http2: fix incorrect panic
    https://golang.org/cl/34498

    http2: fix race in writePushPromise
    https://golang.org/cl/34493

    http2: speed up TestTransportFlowControl in short mode
    https://golang.org/cl/33241

    http2: don't flush a stream's write queue in sc.resetStream
    https://golang.org/cl/34238

    http2: allow Transport to connect to https://[v6literal]/ without port
    https://golang.org/cl/34143

    http2: log Framer reads and writes when a server test fails
    https://golang.org/cl/34130

Updates #18326
Updates #18273
Updates #18111
Updates #18248
Updates #18235

Change-Id: I18c7a297fc94d6a843284efcfc43e0fdab9b5f41
Reviewed-on: https://go-review.googlesource.com/34495
Run-TryBot: Chris Broadfoot <cbro@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 94e0f06f
...@@ -855,10 +855,12 @@ type http2Framer struct { ...@@ -855,10 +855,12 @@ type http2Framer struct {
// If the limit is hit, MetaHeadersFrame.Truncated is set true. // If the limit is hit, MetaHeadersFrame.Truncated is set true.
MaxHeaderListSize uint32 MaxHeaderListSize uint32
logReads bool logReads, logWrites bool
debugFramer *http2Framer // only use for logging written writes debugFramer *http2Framer // only use for logging written writes
debugFramerBuf *bytes.Buffer debugFramerBuf *bytes.Buffer
debugReadLoggerf func(string, ...interface{})
debugWriteLoggerf func(string, ...interface{})
} }
func (fr *http2Framer) maxHeaderListSize() uint32 { func (fr *http2Framer) maxHeaderListSize() uint32 {
...@@ -892,7 +894,7 @@ func (f *http2Framer) endWrite() error { ...@@ -892,7 +894,7 @@ func (f *http2Framer) endWrite() error {
byte(length>>16), byte(length>>16),
byte(length>>8), byte(length>>8),
byte(length)) byte(length))
if http2logFrameWrites { if f.logWrites {
f.logWrite() f.logWrite()
} }
...@@ -914,10 +916,10 @@ func (f *http2Framer) logWrite() { ...@@ -914,10 +916,10 @@ func (f *http2Framer) logWrite() {
f.debugFramerBuf.Write(f.wbuf) f.debugFramerBuf.Write(f.wbuf)
fr, err := f.debugFramer.ReadFrame() fr, err := f.debugFramer.ReadFrame()
if err != nil { if err != nil {
log.Printf("http2: Framer %p: failed to decode just-written frame", f) f.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", f)
return return
} }
log.Printf("http2: Framer %p: wrote %v", f, http2summarizeFrame(fr)) f.debugWriteLoggerf("http2: Framer %p: wrote %v", f, http2summarizeFrame(fr))
} }
func (f *http2Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) } func (f *http2Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) }
...@@ -938,9 +940,12 @@ const ( ...@@ -938,9 +940,12 @@ const (
// NewFramer returns a Framer that writes frames to w and reads them from r. // NewFramer returns a Framer that writes frames to w and reads them from r.
func http2NewFramer(w io.Writer, r io.Reader) *http2Framer { func http2NewFramer(w io.Writer, r io.Reader) *http2Framer {
fr := &http2Framer{ fr := &http2Framer{
w: w, w: w,
r: r, r: r,
logReads: http2logFrameReads, logReads: http2logFrameReads,
logWrites: http2logFrameWrites,
debugReadLoggerf: log.Printf,
debugWriteLoggerf: log.Printf,
} }
fr.getReadBuf = func(size uint32) []byte { fr.getReadBuf = func(size uint32) []byte {
if cap(fr.readBuf) >= int(size) { if cap(fr.readBuf) >= int(size) {
...@@ -1022,7 +1027,7 @@ func (fr *http2Framer) ReadFrame() (http2Frame, error) { ...@@ -1022,7 +1027,7 @@ func (fr *http2Framer) ReadFrame() (http2Frame, error) {
return nil, err return nil, err
} }
if fr.logReads { if fr.logReads {
log.Printf("http2: Framer %p: read %v", fr, http2summarizeFrame(f)) fr.debugReadLoggerf("http2: Framer %p: read %v", fr, http2summarizeFrame(f))
} }
if fh.Type == http2FrameHeaders && fr.ReadMetaHeaders != nil { if fh.Type == http2FrameHeaders && fr.ReadMetaHeaders != nil {
return fr.readMetaFrame(f.(*http2HeadersFrame)) return fr.readMetaFrame(f.(*http2HeadersFrame))
...@@ -1922,8 +1927,8 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr ...@@ -1922,8 +1927,8 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr
hdec.SetEmitEnabled(true) hdec.SetEmitEnabled(true)
hdec.SetMaxStringLength(fr.maxHeaderStringLen()) hdec.SetMaxStringLength(fr.maxHeaderStringLen())
hdec.SetEmitFunc(func(hf hpack.HeaderField) { hdec.SetEmitFunc(func(hf hpack.HeaderField) {
if http2VerboseLogs && http2logFrameReads { if http2VerboseLogs && fr.logReads {
log.Printf("http2: decoded hpack field %+v", hf) fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
} }
if !httplex.ValidHeaderFieldValue(hf.Value) { if !httplex.ValidHeaderFieldValue(hf.Value) {
invalid = http2headerFieldValueError(hf.Value) invalid = http2headerFieldValueError(hf.Value)
...@@ -3285,8 +3290,7 @@ type http2stream struct { ...@@ -3285,8 +3290,7 @@ type http2stream struct {
numTrailerValues int64 numTrailerValues int64
weight uint8 weight uint8
state http2streamState state http2streamState
sentReset bool // only true once detached from streams map resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
gotReset bool // only true once detacted from streams map
gotTrailerHeader bool // HEADER frame for trailers was seen gotTrailerHeader bool // HEADER frame for trailers was seen
wroteHeaders bool // whether we wrote headers (not status 100) wroteHeaders bool // whether we wrote headers (not status 100)
reqBuf []byte // if non-nil, body pipe buffer to return later at EOF reqBuf []byte // if non-nil, body pipe buffer to return later at EOF
...@@ -3682,13 +3686,25 @@ func (sc *http2serverConn) writeFrameFromHandler(wr http2FrameWriteRequest) erro ...@@ -3682,13 +3686,25 @@ func (sc *http2serverConn) writeFrameFromHandler(wr http2FrameWriteRequest) erro
func (sc *http2serverConn) writeFrame(wr http2FrameWriteRequest) { func (sc *http2serverConn) writeFrame(wr http2FrameWriteRequest) {
sc.serveG.check() sc.serveG.check()
// If true, wr will not be written and wr.done will not be signaled.
var ignoreWrite bool var ignoreWrite bool
if wr.StreamID() != 0 {
_, isReset := wr.write.(http2StreamError)
if state, _ := sc.state(wr.StreamID()); state == http2stateClosed && !isReset {
ignoreWrite = true
}
}
switch wr.write.(type) { switch wr.write.(type) {
case *http2writeResHeaders: case *http2writeResHeaders:
wr.stream.wroteHeaders = true wr.stream.wroteHeaders = true
case http2write100ContinueHeadersFrame: case http2write100ContinueHeadersFrame:
if wr.stream.wroteHeaders { if wr.stream.wroteHeaders {
if wr.done != nil {
panic("wr.done != nil for write100ContinueHeadersFrame")
}
ignoreWrite = true ignoreWrite = true
} }
} }
...@@ -3712,14 +3728,14 @@ func (sc *http2serverConn) startFrameWrite(wr http2FrameWriteRequest) { ...@@ -3712,14 +3728,14 @@ func (sc *http2serverConn) startFrameWrite(wr http2FrameWriteRequest) {
if st != nil { if st != nil {
switch st.state { switch st.state {
case http2stateHalfClosedLocal: case http2stateHalfClosedLocal:
panic("internal error: attempt to send frame on half-closed-local stream") switch wr.write.(type) {
case http2stateClosed: case http2StreamError, http2handlerPanicRST, http2writeWindowUpdate:
if st.sentReset || st.gotReset {
sc.scheduleFrameWrite() default:
return panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", wr))
} }
panic(fmt.Sprintf("internal error: attempt to send a write %v on a closed stream", wr)) case http2stateClosed:
panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", wr))
} }
} }
if wpp, ok := wr.write.(*http2writePushPromise); ok { if wpp, ok := wr.write.(*http2writePushPromise); ok {
...@@ -3727,9 +3743,7 @@ func (sc *http2serverConn) startFrameWrite(wr http2FrameWriteRequest) { ...@@ -3727,9 +3743,7 @@ func (sc *http2serverConn) startFrameWrite(wr http2FrameWriteRequest) {
wpp.promisedID, err = wpp.allocatePromisedID() wpp.promisedID, err = wpp.allocatePromisedID()
if err != nil { if err != nil {
sc.writingFrameAsync = false sc.writingFrameAsync = false
if wr.done != nil { wr.replyToWriter(err)
wr.done <- err
}
return return
} }
} }
...@@ -3762,24 +3776,9 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) { ...@@ -3762,24 +3776,9 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) {
sc.writingFrameAsync = false sc.writingFrameAsync = false
wr := res.wr wr := res.wr
st := wr.stream
closeStream := http2endsStream(wr.write)
if _, ok := wr.write.(http2handlerPanicRST); ok {
sc.closeStream(st, http2errHandlerPanicked)
}
if ch := wr.done; ch != nil {
select {
case ch <- res.err:
default:
panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wr.write))
}
}
wr.write = nil
if closeStream { if http2writeEndsStream(wr.write) {
st := wr.stream
if st == nil { if st == nil {
panic("internal error: expecting non-nil stream") panic("internal error: expecting non-nil stream")
} }
...@@ -3787,13 +3786,24 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) { ...@@ -3787,13 +3786,24 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) {
case http2stateOpen: case http2stateOpen:
st.state = http2stateHalfClosedLocal st.state = http2stateHalfClosedLocal
errCancel := http2streamError(st.id, http2ErrCodeCancel) sc.resetStream(http2streamError(st.id, http2ErrCodeCancel))
sc.resetStream(errCancel)
case http2stateHalfClosedRemote: case http2stateHalfClosedRemote:
sc.closeStream(st, http2errHandlerComplete) sc.closeStream(st, http2errHandlerComplete)
} }
} else {
switch v := wr.write.(type) {
case http2StreamError:
if st, ok := sc.streams[v.StreamID]; ok {
sc.closeStream(st, v)
}
case http2handlerPanicRST:
sc.closeStream(wr.stream, http2errHandlerPanicked)
}
} }
wr.replyToWriter(res.err)
sc.scheduleFrameWrite() sc.scheduleFrameWrite()
} }
...@@ -3890,8 +3900,7 @@ func (sc *http2serverConn) resetStream(se http2StreamError) { ...@@ -3890,8 +3900,7 @@ func (sc *http2serverConn) resetStream(se http2StreamError) {
sc.serveG.check() sc.serveG.check()
sc.writeFrame(http2FrameWriteRequest{write: se}) sc.writeFrame(http2FrameWriteRequest{write: se})
if st, ok := sc.streams[se.StreamID]; ok { if st, ok := sc.streams[se.StreamID]; ok {
st.sentReset = true st.resetQueued = true
sc.closeStream(st, se)
} }
} }
...@@ -4030,7 +4039,6 @@ func (sc *http2serverConn) processResetStream(f *http2RSTStreamFrame) error { ...@@ -4030,7 +4039,6 @@ func (sc *http2serverConn) processResetStream(f *http2RSTStreamFrame) error {
return http2ConnectionError(http2ErrCodeProtocol) return http2ConnectionError(http2ErrCodeProtocol)
} }
if st != nil { if st != nil {
st.gotReset = true
st.cancelCtx() st.cancelCtx()
sc.closeStream(st, http2streamError(f.StreamID, f.ErrCode)) sc.closeStream(st, http2streamError(f.StreamID, f.ErrCode))
} }
...@@ -4145,7 +4153,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { ...@@ -4145,7 +4153,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
return http2ConnectionError(http2ErrCodeProtocol) return http2ConnectionError(http2ErrCodeProtocol)
} }
if st == nil || state != http2stateOpen || st.gotTrailerHeader { if st == nil || state != http2stateOpen || st.gotTrailerHeader || st.resetQueued {
if sc.inflow.available() < int32(f.Length) { if sc.inflow.available() < int32(f.Length) {
return http2streamError(id, http2ErrCodeFlowControl) return http2streamError(id, http2ErrCodeFlowControl)
...@@ -4154,6 +4162,10 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { ...@@ -4154,6 +4162,10 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
sc.inflow.take(int32(f.Length)) sc.inflow.take(int32(f.Length))
sc.sendWindowUpdate(nil, int(f.Length)) sc.sendWindowUpdate(nil, int(f.Length))
if st != nil && st.resetQueued {
return nil
}
return http2streamError(id, http2ErrCodeStreamClosed) return http2streamError(id, http2ErrCodeStreamClosed)
} }
if st.body == nil { if st.body == nil {
...@@ -4251,6 +4263,10 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { ...@@ -4251,6 +4263,10 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
} }
if st := sc.streams[f.StreamID]; st != nil { if st := sc.streams[f.StreamID]; st != nil {
if st.resetQueued {
return nil
}
return st.processTrailerHeaders(f) return st.processTrailerHeaders(f)
} }
...@@ -5216,7 +5232,7 @@ func (sc *http2serverConn) startPush(msg http2startPushRequest) { ...@@ -5216,7 +5232,7 @@ func (sc *http2serverConn) startPush(msg http2startPushRequest) {
scheme: msg.url.Scheme, scheme: msg.url.Scheme,
authority: msg.url.Host, authority: msg.url.Host,
path: msg.url.RequestURI(), path: msg.url.RequestURI(),
header: msg.header, header: http2cloneHeader(msg.header),
}) })
if err != nil { if err != nil {
...@@ -5647,6 +5663,10 @@ func http2authorityAddr(scheme string, authority string) (addr string) { ...@@ -5647,6 +5663,10 @@ func http2authorityAddr(scheme string, authority string) (addr string) {
if a, err := idna.ToASCII(host); err == nil { if a, err := idna.ToASCII(host); err == nil {
host = a host = a
} }
if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
return host + ":" + port
}
return net.JoinHostPort(host, port) return net.JoinHostPort(host, port)
} }
...@@ -7376,9 +7396,10 @@ type http2writeContext interface { ...@@ -7376,9 +7396,10 @@ type http2writeContext interface {
HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer)
} }
// endsStream reports whether the given frame writer w will locally // writeEndsStream reports whether w writes a frame that will transition
// close the stream. // the stream to a half-closed local state. This returns false for RST_STREAM,
func http2endsStream(w http2writeFramer) bool { // which closes the entire stream (not just the local half).
func http2writeEndsStream(w http2writeFramer) bool {
switch v := w.(type) { switch v := w.(type) {
case *http2writeData: case *http2writeData:
return v.endStream return v.endStream
...@@ -7386,7 +7407,7 @@ func http2endsStream(w http2writeFramer) bool { ...@@ -7386,7 +7407,7 @@ func http2endsStream(w http2writeFramer) bool {
return v.endStream return v.endStream
case nil: case nil:
panic("endsStream called on nil writeFramer") panic("writeEndsStream called on nil writeFramer")
} }
return false return false
} }
...@@ -7832,6 +7853,20 @@ func (wr http2FrameWriteRequest) String() string { ...@@ -7832,6 +7853,20 @@ func (wr http2FrameWriteRequest) String() string {
return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", wr.StreamID(), wr.done != nil, des) return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", wr.StreamID(), wr.done != nil, des)
} }
// replyToWriter sends err to wr.done and panics if the send must block
// This does nothing if wr.done is nil.
func (wr *http2FrameWriteRequest) replyToWriter(err error) {
if wr.done == nil {
return
}
select {
case wr.done <- err:
default:
panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wr.write))
}
wr.write = nil
}
// writeQueue is used by implementations of WriteScheduler. // writeQueue is used by implementations of WriteScheduler.
type http2writeQueue struct { type http2writeQueue struct {
s []http2FrameWriteRequest s []http2FrameWriteRequest
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment