]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: regenerate h2_bundle.go
authorDmitri Shuralyov <dmitshur@golang.org>
Fri, 18 Nov 2022 23:34:15 +0000 (18:34 -0500)
committerGopher Robot <gobot@golang.org>
Fri, 18 Nov 2022 23:57:13 +0000 (23:57 +0000)
Done with:

go generate -run=bundle std

After CL 452096 updated the x/net version.

Change-Id: I1c1cd76d4ec9e14f45dc66c945c74e41ff689a30
Reviewed-on: https://go-review.googlesource.com/c/go/+/452195
Reviewed-by: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
src/net/http/h2_bundle.go

index 32b628ad1241a0ca460cb8ee660555a722592831..26543c2b32263c284853be4a282a2df486602a5b 100644 (file)
@@ -30,6 +30,7 @@ import (
        "errors"
        "fmt"
        "io"
+       "io/fs"
        "log"
        "math"
        mathrand "math/rand"
@@ -3185,7 +3186,14 @@ func http2buildCommonHeaderMaps() {
                "accept-language",
                "accept-ranges",
                "age",
+               "access-control-allow-credentials",
+               "access-control-allow-headers",
+               "access-control-allow-methods",
                "access-control-allow-origin",
+               "access-control-expose-headers",
+               "access-control-max-age",
+               "access-control-request-headers",
+               "access-control-request-method",
                "allow",
                "authorization",
                "cache-control",
@@ -3211,6 +3219,7 @@ func http2buildCommonHeaderMaps() {
                "link",
                "location",
                "max-forwards",
+               "origin",
                "proxy-authenticate",
                "proxy-authorization",
                "range",
@@ -3226,6 +3235,8 @@ func http2buildCommonHeaderMaps() {
                "vary",
                "via",
                "www-authenticate",
+               "x-forwarded-for",
+               "x-forwarded-proto",
        }
        http2commonLowerHeader = make(map[string]string, len(common))
        http2commonCanonHeader = make(map[string]string, len(common))
@@ -3244,6 +3255,14 @@ func http2lowerHeader(v string) (lower string, ascii bool) {
        return http2asciiToLower(v)
 }
 
+func http2canonicalHeader(v string) string {
+       http2buildCommonHeaderMapsOnce()
+       if s, ok := http2commonCanonHeader[v]; ok {
+               return s
+       }
+       return CanonicalHeaderKey(v)
+}
+
 var (
        http2VerboseLogs    bool
        http2logFrameWrites bool
@@ -4342,7 +4361,9 @@ type http2stream struct {
        resetQueued      bool        // RST_STREAM queued for write; set by sc.resetStream
        gotTrailerHeader bool        // HEADER frame for trailers was seen
        wroteHeaders     bool        // whether we wrote headers (not status 100)
+       readDeadline     *time.Timer // nil if unused
        writeDeadline    *time.Timer // nil if unused
+       closeErr         error       // set before cw is closed
 
        trailer    Header // accumulated trailers
        reqTrailer Header // handler's Request.Trailer
@@ -4592,7 +4613,9 @@ func (sc *http2serverConn) serve() {
 
        // Each connection starts with initialWindowSize inflow tokens.
        // If a higher value is configured, we add more tokens.
-       sc.sendWindowUpdate(nil)
+       if diff := sc.srv.initialConnRecvWindowSize() - http2initialWindowSize; diff > 0 {
+               sc.sendWindowUpdate(nil, int(diff))
+       }
 
        if err := sc.readPreface(); err != nil {
                sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
@@ -4669,6 +4692,8 @@ func (sc *http2serverConn) serve() {
                                }
                        case *http2startPushRequest:
                                sc.startPush(v)
+                       case func(*http2serverConn):
+                               v(sc)
                        default:
                                panic(fmt.Sprintf("unexpected type %T", v))
                        }
@@ -5184,6 +5209,21 @@ func (sc *http2serverConn) processFrame(f http2Frame) error {
                sc.sawFirstSettings = true
        }
 
+       // Discard frames for streams initiated after the identified last
+       // stream sent in a GOAWAY, or all frames after sending an error.
+       // We still need to return connection-level flow control for DATA frames.
+       // RFC 9113 Section 6.8.
+       if sc.inGoAway && (sc.goAwayCode != http2ErrCodeNo || f.Header().StreamID > sc.maxClientStreamID) {
+
+               if f, ok := f.(*http2DataFrame); ok {
+                       if sc.inflow.available() < int32(f.Length) {
+                               return sc.countError("data_flow", http2streamError(f.Header().StreamID, http2ErrCodeFlowControl))
+                       }
+                       sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
+               }
+               return nil
+       }
+
        switch f := f.(type) {
        case *http2SettingsFrame:
                return sc.processSettings(f)
@@ -5226,9 +5266,6 @@ func (sc *http2serverConn) processPing(f *http2PingFrame) error {
                // PROTOCOL_ERROR."
                return sc.countError("ping_on_stream", http2ConnectionError(http2ErrCodeProtocol))
        }
-       if sc.inGoAway && sc.goAwayCode != http2ErrCodeNo {
-               return nil
-       }
        sc.writeFrame(http2FrameWriteRequest{write: http2writePingAck{f}})
        return nil
 }
@@ -5290,6 +5327,9 @@ func (sc *http2serverConn) closeStream(st *http2stream, err error) {
                panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
        }
        st.state = http2stateClosed
+       if st.readDeadline != nil {
+               st.readDeadline.Stop()
+       }
        if st.writeDeadline != nil {
                st.writeDeadline.Stop()
        }
@@ -5311,10 +5351,18 @@ func (sc *http2serverConn) closeStream(st *http2stream, err error) {
        if p := st.body; p != nil {
                // Return any buffered unread bytes worth of conn-level flow control.
                // See golang.org/issue/16481
-               sc.sendWindowUpdate(nil)
+               sc.sendWindowUpdate(nil, p.Len())
 
                p.CloseWithError(err)
        }
+       if e, ok := err.(http2StreamError); ok {
+               if e.Cause != nil {
+                       err = e.Cause
+               } else {
+                       err = http2errStreamClosed
+               }
+       }
+       st.closeErr = err
        st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
        sc.writeSched.CloseStream(st.id)
 }
@@ -5411,16 +5459,6 @@ func (sc *http2serverConn) processSettingInitialWindowSize(val uint32) error {
 func (sc *http2serverConn) processData(f *http2DataFrame) error {
        sc.serveG.check()
        id := f.Header().StreamID
-       if sc.inGoAway && (sc.goAwayCode != http2ErrCodeNo || id > sc.maxClientStreamID) {
-               // Discard all DATA frames if the GOAWAY is due to an
-               // error, or:
-               //
-               // Section 6.8: After sending a GOAWAY frame, the sender
-               // can discard frames for streams initiated by the
-               // receiver with identifiers higher than the identified
-               // last stream.
-               return nil
-       }
 
        data := f.Data()
        state, st := sc.state(id)
@@ -5459,7 +5497,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
                // sendWindowUpdate, which also schedules sending the
                // frames.
                sc.inflow.take(int32(f.Length))
-               sc.sendWindowUpdate(nil) // conn-level
+               sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
 
                if st != nil && st.resetQueued {
                        // Already have a stream error in flight. Don't send another.
@@ -5477,7 +5515,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
                        return sc.countError("data_flow", http2streamError(id, http2ErrCodeFlowControl))
                }
                sc.inflow.take(int32(f.Length))
-               sc.sendWindowUpdate(nil) // conn-level
+               sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
 
                st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
                // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
@@ -5495,7 +5533,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
                if len(data) > 0 {
                        wrote, err := st.body.Write(data)
                        if err != nil {
-                               sc.sendWindowUpdate32(nil, int32(f.Length)-int32(wrote))
+                               sc.sendWindowUpdate(nil, int(f.Length)-wrote)
                                return sc.countError("body_write_err", http2streamError(id, http2ErrCodeStreamClosed))
                        }
                        if wrote != len(data) {
@@ -5563,19 +5601,27 @@ func (st *http2stream) copyTrailersToHandlerRequest() {
        }
 }
 
+// onReadTimeout is run on its own goroutine (from time.AfterFunc)
+// when the stream's ReadTimeout has fired.
+func (st *http2stream) onReadTimeout() {
+       // Wrap the ErrDeadlineExceeded to avoid callers depending on us
+       // returning the bare error.
+       st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))
+}
+
 // onWriteTimeout is run on its own goroutine (from time.AfterFunc)
 // when the stream's WriteTimeout has fired.
 func (st *http2stream) onWriteTimeout() {
-       st.sc.writeFrameFromHandler(http2FrameWriteRequest{write: http2streamError(st.id, http2ErrCodeInternal)})
+       st.sc.writeFrameFromHandler(http2FrameWriteRequest{write: http2StreamError{
+               StreamID: st.id,
+               Code:     http2ErrCodeInternal,
+               Cause:    os.ErrDeadlineExceeded,
+       }})
 }
 
 func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
        sc.serveG.check()
        id := f.StreamID
-       if sc.inGoAway {
-               // Ignore.
-               return nil
-       }
        // http://tools.ietf.org/html/rfc7540#section-5.1.1
        // Streams initiated by a client MUST use odd-numbered stream
        // identifiers. [...] An endpoint that receives an unexpected
@@ -5678,6 +5724,9 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
        // (in Go 1.8), though. That's a more sane option anyway.
        if sc.hs.ReadTimeout != 0 {
                sc.conn.SetReadDeadline(time.Time{})
+               if st.body != nil {
+                       st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
+               }
        }
 
        go sc.runHandler(rw, req, handler)
@@ -5746,9 +5795,6 @@ func (sc *http2serverConn) checkPriority(streamID uint32, p http2PriorityParam)
 }
 
 func (sc *http2serverConn) processPriority(f *http2PriorityFrame) error {
-       if sc.inGoAway {
-               return nil
-       }
        if err := sc.checkPriority(f.StreamID, f.http2PriorityParam); err != nil {
                return err
        }
@@ -6047,39 +6093,24 @@ func (sc *http2serverConn) noteBodyReadFromHandler(st *http2stream, n int, err e
 
 func (sc *http2serverConn) noteBodyRead(st *http2stream, n int) {
        sc.serveG.check()
-       sc.sendWindowUpdate(nil) // conn-level
+       sc.sendWindowUpdate(nil, n) // conn-level
        if st.state != http2stateHalfClosedRemote && st.state != http2stateClosed {
                // Don't send this WINDOW_UPDATE if the stream is closed
                // remotely.
-               sc.sendWindowUpdate(st)
+               sc.sendWindowUpdate(st, n)
        }
 }
 
 // st may be nil for conn-level
-func (sc *http2serverConn) sendWindowUpdate(st *http2stream) {
+func (sc *http2serverConn) sendWindowUpdate(st *http2stream, n int) {
        sc.serveG.check()
-
-       var n int32
-       if st == nil {
-               if avail, windowSize := sc.inflow.available(), sc.srv.initialConnRecvWindowSize(); avail > windowSize/2 {
-                       return
-               } else {
-                       n = windowSize - avail
-               }
-       } else {
-               if avail, windowSize := st.inflow.available(), sc.srv.initialStreamRecvWindowSize(); avail > windowSize/2 {
-                       return
-               } else {
-                       n = windowSize - avail
-               }
-       }
        // "The legal range for the increment to the flow control
        // window is 1 to 2^31-1 (2,147,483,647) octets."
        // A Go Read call on 64-bit machines could in theory read
        // a larger Read than this. Very unlikely, but we handle it here
        // rather than elsewhere for now.
        const maxUint31 = 1<<31 - 1
-       for n >= maxUint31 {
+       for n > maxUint31 {
                sc.sendWindowUpdate32(st, maxUint31)
                n -= maxUint31
        }
@@ -6199,7 +6230,15 @@ type http2responseWriterState struct {
 
 type http2chunkWriter struct{ rws *http2responseWriterState }
 
-func (cw http2chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) }
+func (cw http2chunkWriter) Write(p []byte) (n int, err error) {
+       n, err = cw.rws.writeChunk(p)
+       if err == http2errStreamClosed {
+               // If writing failed because the stream has been closed,
+               // return the reason it was closed.
+               err = cw.rws.stream.closeErr
+       }
+       return n, err
+}
 
 func (rws *http2responseWriterState) hasTrailers() bool { return len(rws.trailers) > 0 }
 
@@ -6393,23 +6432,85 @@ func (rws *http2responseWriterState) promoteUndeclaredTrailers() {
        }
 }
 
+func (w *http2responseWriter) SetReadDeadline(deadline time.Time) error {
+       st := w.rws.stream
+       if !deadline.IsZero() && deadline.Before(time.Now()) {
+               // If we're setting a deadline in the past, reset the stream immediately
+               // so writes after SetWriteDeadline returns will fail.
+               st.onReadTimeout()
+               return nil
+       }
+       w.rws.conn.sendServeMsg(func(sc *http2serverConn) {
+               if st.readDeadline != nil {
+                       if !st.readDeadline.Stop() {
+                               // Deadline already exceeded, or stream has been closed.
+                               return
+                       }
+               }
+               if deadline.IsZero() {
+                       st.readDeadline = nil
+               } else if st.readDeadline == nil {
+                       st.readDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onReadTimeout)
+               } else {
+                       st.readDeadline.Reset(deadline.Sub(time.Now()))
+               }
+       })
+       return nil
+}
+
+func (w *http2responseWriter) SetWriteDeadline(deadline time.Time) error {
+       st := w.rws.stream
+       if !deadline.IsZero() && deadline.Before(time.Now()) {
+               // If we're setting a deadline in the past, reset the stream immediately
+               // so writes after SetWriteDeadline returns will fail.
+               st.onWriteTimeout()
+               return nil
+       }
+       w.rws.conn.sendServeMsg(func(sc *http2serverConn) {
+               if st.writeDeadline != nil {
+                       if !st.writeDeadline.Stop() {
+                               // Deadline already exceeded, or stream has been closed.
+                               return
+                       }
+               }
+               if deadline.IsZero() {
+                       st.writeDeadline = nil
+               } else if st.writeDeadline == nil {
+                       st.writeDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onWriteTimeout)
+               } else {
+                       st.writeDeadline.Reset(deadline.Sub(time.Now()))
+               }
+       })
+       return nil
+}
+
 func (w *http2responseWriter) Flush() {
+       w.FlushError()
+}
+
+func (w *http2responseWriter) FlushError() error {
        rws := w.rws
        if rws == nil {
                panic("Header called after Handler finished")
        }
+       var err error
        if rws.bw.Buffered() > 0 {
-               if err := rws.bw.Flush(); err != nil {
-                       // Ignore the error. The frame writer already knows.
-                       return
-               }
+               err = rws.bw.Flush()
        } else {
                // The bufio.Writer won't call chunkWriter.Write
                // (writeChunk with zero bytes, so we have to do it
                // ourselves to force the HTTP response header and/or
                // final DATA frame (with END_STREAM) to be sent.
-               rws.writeChunk(nil)
+               _, err = http2chunkWriter{rws}.Write(nil)
+               if err == nil {
+                       select {
+                       case <-rws.stream.cw:
+                               err = rws.stream.closeErr
+                       default:
+                       }
+               }
        }
+       return err
 }
 
 func (w *http2responseWriter) CloseNotify() <-chan bool {
@@ -7329,6 +7430,15 @@ func http2authorityAddr(scheme string, authority string) (addr string) {
        return net.JoinHostPort(host, port)
 }
 
+var http2retryBackoffHook func(time.Duration) *time.Timer
+
+func http2backoffNewTimer(d time.Duration) *time.Timer {
+       if http2retryBackoffHook != nil {
+               return http2retryBackoffHook(d)
+       }
+       return time.NewTimer(d)
+}
+
 // RoundTripOpt is like RoundTrip, but takes options.
 func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Response, error) {
        if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
@@ -7354,11 +7464,14 @@ func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Res
                                }
                                backoff := float64(uint(1) << (uint(retry) - 1))
                                backoff += backoff * (0.1 * mathrand.Float64())
+                               d := time.Second * time.Duration(backoff)
+                               timer := http2backoffNewTimer(d)
                                select {
-                               case <-time.After(time.Second * time.Duration(backoff)):
+                               case <-timer.C:
                                        t.vlogf("RoundTrip retrying after failure: %v", err)
                                        continue
                                case <-req.Context().Done():
+                                       timer.Stop()
                                        err = req.Context().Err()
                                }
                        }
@@ -7903,7 +8016,7 @@ var http2errRequestCanceled = errors.New("net/http: request canceled")
 func http2commaSeparatedTrailers(req *Request) (string, error) {
        keys := make([]string, 0, len(req.Trailer))
        for k := range req.Trailer {
-               k = CanonicalHeaderKey(k)
+               k = http2canonicalHeader(k)
                switch k {
                case "Transfer-Encoding", "Trailer", "Content-Length":
                        return "", fmt.Errorf("invalid Trailer key %q", k)
@@ -8440,7 +8553,7 @@ func (cs *http2clientStream) writeRequestBody(req *Request) (err error) {
 
        var sawEOF bool
        for !sawEOF {
-               n, err := body.Read(buf[:len(buf)])
+               n, err := body.Read(buf)
                if hasContentLen {
                        remainLen -= int64(n)
                        if remainLen == 0 && err == nil {
@@ -8743,7 +8856,7 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail
 
        // Header list size is ok. Write the headers.
        enumerateHeaders(func(name, value string) {
-               name, ascii := http2asciiToLower(name)
+               name, ascii := http2lowerHeader(name)
                if !ascii {
                        // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
                        // field names have to be ASCII characters (just as in HTTP/1.x).
@@ -8796,7 +8909,7 @@ func (cc *http2ClientConn) encodeTrailers(trailer Header) ([]byte, error) {
        }
 
        for k, vv := range trailer {
-               lowKey, ascii := http2asciiToLower(k)
+               lowKey, ascii := http2lowerHeader(k)
                if !ascii {
                        // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
                        // field names have to be ASCII characters (just as in HTTP/1.x).
@@ -9129,7 +9242,7 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http
                Status:     status + " " + StatusText(statusCode),
        }
        for _, hf := range regularFields {
-               key := CanonicalHeaderKey(hf.Name)
+               key := http2canonicalHeader(hf.Name)
                if key == "Trailer" {
                        t := res.Trailer
                        if t == nil {
@@ -9137,7 +9250,7 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http
                                res.Trailer = t
                        }
                        http2foreachHeaderElement(hf.Value, func(v string) {
-                               t[CanonicalHeaderKey(v)] = nil
+                               t[http2canonicalHeader(v)] = nil
                        })
                } else {
                        vv := header[key]
@@ -9242,7 +9355,7 @@ func (rl *http2clientConnReadLoop) processTrailers(cs *http2clientStream, f *htt
 
        trailer := make(Header)
        for _, hf := range f.RegularFields() {
-               key := CanonicalHeaderKey(hf.Name)
+               key := http2canonicalHeader(hf.Name)
                trailer[key] = append(trailer[key], hf.Value)
        }
        cs.trailer = trailer
@@ -9816,7 +9929,11 @@ func (gz *http2gzipReader) Read(p []byte) (n int, err error) {
 }
 
 func (gz *http2gzipReader) Close() error {
-       return gz.body.Close()
+       if err := gz.body.Close(); err != nil {
+               return err
+       }
+       gz.zerr = fs.ErrClosed
+       return nil
 }
 
 type http2errorReader struct{ err error }