rebase: bump golang.org/x/net

Bumps the golang-dependencies group with 1 update in the / directory: [golang.org/x/net](https://github.com/golang/net).


Updates `golang.org/x/net` from 0.31.0 to 0.32.0
- [Commits](https://github.com/golang/net/compare/v0.31.0...v0.32.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2024-12-12 16:51:25 +00:00 committed by mergify[bot]
parent c7d54ab776
commit 8f4520ece5
7 changed files with 164 additions and 62 deletions

2
go.mod
View File

@ -26,7 +26,7 @@ require (
github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_golang v1.20.5
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.31.0 golang.org/x/crypto v0.31.0
golang.org/x/net v0.31.0 golang.org/x/net v0.32.0
golang.org/x/sys v0.28.0 golang.org/x/sys v0.28.0
google.golang.org/grpc v1.68.1 google.golang.org/grpc v1.68.1
google.golang.org/protobuf v1.35.2 google.golang.org/protobuf v1.35.2

4
go.sum
View File

@ -2614,8 +2614,8 @@ golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=

View File

@ -1490,7 +1490,7 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
pf := mh.PseudoFields() pf := mh.PseudoFields()
for i, hf := range pf { for i, hf := range pf {
switch hf.Name { switch hf.Name {
case ":method", ":path", ":scheme", ":authority": case ":method", ":path", ":scheme", ":authority", ":protocol":
isRequest = true isRequest = true
case ":status": case ":status":
isResponse = true isResponse = true
@ -1498,7 +1498,7 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
return pseudoHeaderError(hf.Name) return pseudoHeaderError(hf.Name)
} }
// Check for duplicates. // Check for duplicates.
// This would be a bad algorithm, but N is 4. // This would be a bad algorithm, but N is 5.
// And this doesn't allocate. // And this doesn't allocate.
for _, hf2 := range pf[:i] { for _, hf2 := range pf[:i] {
if hf.Name == hf2.Name { if hf.Name == hf2.Name {

View File

@ -34,10 +34,11 @@ import (
) )
var ( var (
VerboseLogs bool VerboseLogs bool
logFrameWrites bool logFrameWrites bool
logFrameReads bool logFrameReads bool
inTests bool inTests bool
disableExtendedConnectProtocol bool
) )
func init() { func init() {
@ -50,6 +51,9 @@ func init() {
logFrameWrites = true logFrameWrites = true
logFrameReads = true logFrameReads = true
} }
if strings.Contains(e, "http2xconnect=0") {
disableExtendedConnectProtocol = true
}
} }
const ( const (
@ -141,6 +145,10 @@ func (s Setting) Valid() error {
if s.Val < 16384 || s.Val > 1<<24-1 { if s.Val < 16384 || s.Val > 1<<24-1 {
return ConnectionError(ErrCodeProtocol) return ConnectionError(ErrCodeProtocol)
} }
case SettingEnableConnectProtocol:
if s.Val != 1 && s.Val != 0 {
return ConnectionError(ErrCodeProtocol)
}
} }
return nil return nil
} }
@ -150,21 +158,23 @@ func (s Setting) Valid() error {
type SettingID uint16 type SettingID uint16
const ( const (
SettingHeaderTableSize SettingID = 0x1 SettingHeaderTableSize SettingID = 0x1
SettingEnablePush SettingID = 0x2 SettingEnablePush SettingID = 0x2
SettingMaxConcurrentStreams SettingID = 0x3 SettingMaxConcurrentStreams SettingID = 0x3
SettingInitialWindowSize SettingID = 0x4 SettingInitialWindowSize SettingID = 0x4
SettingMaxFrameSize SettingID = 0x5 SettingMaxFrameSize SettingID = 0x5
SettingMaxHeaderListSize SettingID = 0x6 SettingMaxHeaderListSize SettingID = 0x6
SettingEnableConnectProtocol SettingID = 0x8
) )
var settingName = map[SettingID]string{ var settingName = map[SettingID]string{
SettingHeaderTableSize: "HEADER_TABLE_SIZE", SettingHeaderTableSize: "HEADER_TABLE_SIZE",
SettingEnablePush: "ENABLE_PUSH", SettingEnablePush: "ENABLE_PUSH",
SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS", SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
SettingInitialWindowSize: "INITIAL_WINDOW_SIZE", SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
SettingMaxFrameSize: "MAX_FRAME_SIZE", SettingMaxFrameSize: "MAX_FRAME_SIZE",
SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE", SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL",
} }
func (s SettingID) String() string { func (s SettingID) String() string {

View File

@ -932,14 +932,18 @@ func (sc *serverConn) serve(conf http2Config) {
sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs) sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
} }
settings := writeSettings{
{SettingMaxFrameSize, conf.MaxReadFrameSize},
{SettingMaxConcurrentStreams, sc.advMaxStreams},
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
{SettingHeaderTableSize, conf.MaxDecoderHeaderTableSize},
{SettingInitialWindowSize, uint32(sc.initialStreamRecvWindowSize)},
}
if !disableExtendedConnectProtocol {
settings = append(settings, Setting{SettingEnableConnectProtocol, 1})
}
sc.writeFrame(FrameWriteRequest{ sc.writeFrame(FrameWriteRequest{
write: writeSettings{ write: settings,
{SettingMaxFrameSize, conf.MaxReadFrameSize},
{SettingMaxConcurrentStreams, sc.advMaxStreams},
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
{SettingHeaderTableSize, conf.MaxDecoderHeaderTableSize},
{SettingInitialWindowSize, uint32(sc.initialStreamRecvWindowSize)},
},
}) })
sc.unackedSettings++ sc.unackedSettings++
@ -1801,6 +1805,9 @@ func (sc *serverConn) processSetting(s Setting) error {
sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31 sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31
case SettingMaxHeaderListSize: case SettingMaxHeaderListSize:
sc.peerMaxHeaderListSize = s.Val sc.peerMaxHeaderListSize = s.Val
case SettingEnableConnectProtocol:
// Receipt of this parameter by a server does not
// have any impact
default: default:
// Unknown setting: "An endpoint that receives a SETTINGS // Unknown setting: "An endpoint that receives a SETTINGS
// frame with any unknown or unsupported identifier MUST // frame with any unknown or unsupported identifier MUST
@ -2231,11 +2238,17 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
scheme: f.PseudoValue("scheme"), scheme: f.PseudoValue("scheme"),
authority: f.PseudoValue("authority"), authority: f.PseudoValue("authority"),
path: f.PseudoValue("path"), path: f.PseudoValue("path"),
protocol: f.PseudoValue("protocol"),
}
// extended connect is disabled, so we should not see :protocol
if disableExtendedConnectProtocol && rp.protocol != "" {
return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol))
} }
isConnect := rp.method == "CONNECT" isConnect := rp.method == "CONNECT"
if isConnect { if isConnect {
if rp.path != "" || rp.scheme != "" || rp.authority == "" { if rp.protocol == "" && (rp.path != "" || rp.scheme != "" || rp.authority == "") {
return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol)) return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol))
} }
} else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") { } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
@ -2259,6 +2272,9 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
if rp.authority == "" { if rp.authority == "" {
rp.authority = rp.header.Get("Host") rp.authority = rp.header.Get("Host")
} }
if rp.protocol != "" {
rp.header.Set(":protocol", rp.protocol)
}
rw, req, err := sc.newWriterAndRequestNoBody(st, rp) rw, req, err := sc.newWriterAndRequestNoBody(st, rp)
if err != nil { if err != nil {
@ -2285,6 +2301,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
type requestParam struct { type requestParam struct {
method string method string
scheme, authority, path string scheme, authority, path string
protocol string
header http.Header header http.Header
} }
@ -2326,7 +2343,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
var url_ *url.URL var url_ *url.URL
var requestURI string var requestURI string
if rp.method == "CONNECT" { if rp.method == "CONNECT" && rp.protocol == "" {
url_ = &url.URL{Host: rp.authority} url_ = &url.URL{Host: rp.authority}
requestURI = rp.authority // mimic HTTP/1 server behavior requestURI = rp.authority // mimic HTTP/1 server behavior
} else { } else {

View File

@ -368,25 +368,26 @@ type ClientConn struct {
idleTimeout time.Duration // or 0 for never idleTimeout time.Duration // or 0 for never
idleTimer timer idleTimer timer
mu sync.Mutex // guards following mu sync.Mutex // guards following
cond *sync.Cond // hold mu; broadcast on flow/closed changes cond *sync.Cond // hold mu; broadcast on flow/closed changes
flow outflow // our conn-level flow control quota (cs.outflow is per stream) flow outflow // our conn-level flow control quota (cs.outflow is per stream)
inflow inflow // peer's conn-level flow control inflow inflow // peer's conn-level flow control
doNotReuse bool // whether conn is marked to not be reused for any future requests doNotReuse bool // whether conn is marked to not be reused for any future requests
closing bool closing bool
closed bool closed bool
seenSettings bool // true if we've seen a settings frame, false otherwise seenSettings bool // true if we've seen a settings frame, false otherwise
wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back seenSettingsChan chan struct{} // closed when seenSettings is true or frame reading fails
goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back
goAwayDebug string // goAway frame's debug data, retained as a string goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received
streams map[uint32]*clientStream // client-initiated goAwayDebug string // goAway frame's debug data, retained as a string
streamsReserved int // incr by ReserveNewRequest; decr on RoundTrip streams map[uint32]*clientStream // client-initiated
nextStreamID uint32 streamsReserved int // incr by ReserveNewRequest; decr on RoundTrip
pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams nextStreamID uint32
pings map[[8]byte]chan struct{} // in flight ping data to notification channel pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
br *bufio.Reader pings map[[8]byte]chan struct{} // in flight ping data to notification channel
lastActive time.Time br *bufio.Reader
lastIdle time.Time // time last idle lastActive time.Time
lastIdle time.Time // time last idle
// Settings from peer: (also guarded by wmu) // Settings from peer: (also guarded by wmu)
maxFrameSize uint32 maxFrameSize uint32
maxConcurrentStreams uint32 maxConcurrentStreams uint32
@ -396,6 +397,17 @@ type ClientConn struct {
initialStreamRecvWindowSize int32 initialStreamRecvWindowSize int32
readIdleTimeout time.Duration readIdleTimeout time.Duration
pingTimeout time.Duration pingTimeout time.Duration
extendedConnectAllowed bool
// rstStreamPingsBlocked works around an unfortunate gRPC behavior.
// gRPC strictly limits the number of PING frames that it will receive.
// The default is two pings per two hours, but the limit resets every time
// the gRPC endpoint sends a HEADERS or DATA frame. See golang/go#70575.
//
// rstStreamPingsBlocked is set after receiving a response to a PING frame
// bundled with an RST_STREAM (see pendingResets below), and cleared after
// receiving a HEADERS or DATA frame.
rstStreamPingsBlocked bool
// pendingResets is the number of RST_STREAM frames we have sent to the peer, // pendingResets is the number of RST_STREAM frames we have sent to the peer,
// without confirming that the peer has received them. When we send a RST_STREAM, // without confirming that the peer has received them. When we send a RST_STREAM,
@ -819,6 +831,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead. peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
streams: make(map[uint32]*clientStream), streams: make(map[uint32]*clientStream),
singleUse: singleUse, singleUse: singleUse,
seenSettingsChan: make(chan struct{}),
wantSettingsAck: true, wantSettingsAck: true,
readIdleTimeout: conf.SendPingTimeout, readIdleTimeout: conf.SendPingTimeout,
pingTimeout: conf.PingTimeout, pingTimeout: conf.PingTimeout,
@ -1466,6 +1479,8 @@ func (cs *clientStream) doRequest(req *http.Request, streamf func(*clientStream)
cs.cleanupWriteRequest(err) cs.cleanupWriteRequest(err)
} }
var errExtendedConnectNotSupported = errors.New("net/http: extended connect not supported by peer")
// writeRequest sends a request. // writeRequest sends a request.
// //
// It returns nil after the request is written, the response read, // It returns nil after the request is written, the response read,
@ -1481,12 +1496,31 @@ func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStre
return err return err
} }
// wait for setting frames to be received, a server can change this value later,
// but we just wait for the first settings frame
var isExtendedConnect bool
if req.Method == "CONNECT" && req.Header.Get(":protocol") != "" {
isExtendedConnect = true
}
// Acquire the new-request lock by writing to reqHeaderMu. // Acquire the new-request lock by writing to reqHeaderMu.
// This lock guards the critical section covering allocating a new stream ID // This lock guards the critical section covering allocating a new stream ID
// (requires mu) and creating the stream (requires wmu). // (requires mu) and creating the stream (requires wmu).
if cc.reqHeaderMu == nil { if cc.reqHeaderMu == nil {
panic("RoundTrip on uninitialized ClientConn") // for tests panic("RoundTrip on uninitialized ClientConn") // for tests
} }
if isExtendedConnect {
select {
case <-cs.reqCancel:
return errRequestCanceled
case <-ctx.Done():
return ctx.Err()
case <-cc.seenSettingsChan:
if !cc.extendedConnectAllowed {
return errExtendedConnectNotSupported
}
}
}
select { select {
case cc.reqHeaderMu <- struct{}{}: case cc.reqHeaderMu <- struct{}{}:
case <-cs.reqCancel: case <-cs.reqCancel:
@ -1714,10 +1748,14 @@ func (cs *clientStream) cleanupWriteRequest(err error) {
ping := false ping := false
if !closeOnIdle { if !closeOnIdle {
cc.mu.Lock() cc.mu.Lock()
if cc.pendingResets == 0 { // rstStreamPingsBlocked works around a gRPC behavior:
ping = true // see comment on the field for details.
if !cc.rstStreamPingsBlocked {
if cc.pendingResets == 0 {
ping = true
}
cc.pendingResets++
} }
cc.pendingResets++
cc.mu.Unlock() cc.mu.Unlock()
} }
cc.writeStreamReset(cs.ID, ErrCodeCancel, ping, err) cc.writeStreamReset(cs.ID, ErrCodeCancel, ping, err)
@ -2030,7 +2068,7 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
func validateHeaders(hdrs http.Header) string { func validateHeaders(hdrs http.Header) string {
for k, vv := range hdrs { for k, vv := range hdrs {
if !httpguts.ValidHeaderFieldName(k) { if !httpguts.ValidHeaderFieldName(k) && k != ":protocol" {
return fmt.Sprintf("name %q", k) return fmt.Sprintf("name %q", k)
} }
for _, v := range vv { for _, v := range vv {
@ -2046,6 +2084,10 @@ func validateHeaders(hdrs http.Header) string {
var errNilRequestURL = errors.New("http2: Request.URI is nil") var errNilRequestURL = errors.New("http2: Request.URI is nil")
func isNormalConnect(req *http.Request) bool {
return req.Method == "CONNECT" && req.Header.Get(":protocol") == ""
}
// requires cc.wmu be held. // requires cc.wmu be held.
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) { func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
cc.hbuf.Reset() cc.hbuf.Reset()
@ -2066,7 +2108,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
} }
var path string var path string
if req.Method != "CONNECT" { if !isNormalConnect(req) {
path = req.URL.RequestURI() path = req.URL.RequestURI()
if !validPseudoPath(path) { if !validPseudoPath(path) {
orig := path orig := path
@ -2103,7 +2145,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
m = http.MethodGet m = http.MethodGet
} }
f(":method", m) f(":method", m)
if req.Method != "CONNECT" { if !isNormalConnect(req) {
f(":path", path) f(":path", path)
f(":scheme", req.URL.Scheme) f(":scheme", req.URL.Scheme)
} }
@ -2461,7 +2503,7 @@ func (rl *clientConnReadLoop) run() error {
cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err) cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
} }
if se, ok := err.(StreamError); ok { if se, ok := err.(StreamError); ok {
if cs := rl.streamByID(se.StreamID); cs != nil { if cs := rl.streamByID(se.StreamID, notHeaderOrDataFrame); cs != nil {
if se.Cause == nil { if se.Cause == nil {
se.Cause = cc.fr.errDetail se.Cause = cc.fr.errDetail
} }
@ -2507,13 +2549,16 @@ func (rl *clientConnReadLoop) run() error {
if VerboseLogs { if VerboseLogs {
cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, summarizeFrame(f), err) cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, summarizeFrame(f), err)
} }
if !cc.seenSettings {
close(cc.seenSettingsChan)
}
return err return err
} }
} }
} }
func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error { func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
cs := rl.streamByID(f.StreamID) cs := rl.streamByID(f.StreamID, headerOrDataFrame)
if cs == nil { if cs == nil {
// We'd get here if we canceled a request while the // We'd get here if we canceled a request while the
// server had its response still in flight. So if this // server had its response still in flight. So if this
@ -2842,7 +2887,7 @@ func (b transportResponseBody) Close() error {
func (rl *clientConnReadLoop) processData(f *DataFrame) error { func (rl *clientConnReadLoop) processData(f *DataFrame) error {
cc := rl.cc cc := rl.cc
cs := rl.streamByID(f.StreamID) cs := rl.streamByID(f.StreamID, headerOrDataFrame)
data := f.Data() data := f.Data()
if cs == nil { if cs == nil {
cc.mu.Lock() cc.mu.Lock()
@ -2977,9 +3022,22 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
cs.abortStream(err) cs.abortStream(err)
} }
func (rl *clientConnReadLoop) streamByID(id uint32) *clientStream { // Constants passed to streamByID for documentation purposes.
const (
headerOrDataFrame = true
notHeaderOrDataFrame = false
)
// streamByID returns the stream with the given id, or nil if no stream has that id.
// If headerOrData is true, it clears rst.StreamPingsBlocked.
func (rl *clientConnReadLoop) streamByID(id uint32, headerOrData bool) *clientStream {
rl.cc.mu.Lock() rl.cc.mu.Lock()
defer rl.cc.mu.Unlock() defer rl.cc.mu.Unlock()
if headerOrData {
// Work around an unfortunate gRPC behavior.
// See comment on ClientConn.rstStreamPingsBlocked for details.
rl.cc.rstStreamPingsBlocked = false
}
cs := rl.cc.streams[id] cs := rl.cc.streams[id]
if cs != nil && !cs.readAborted { if cs != nil && !cs.readAborted {
return cs return cs
@ -3073,6 +3131,21 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
case SettingHeaderTableSize: case SettingHeaderTableSize:
cc.henc.SetMaxDynamicTableSize(s.Val) cc.henc.SetMaxDynamicTableSize(s.Val)
cc.peerMaxHeaderTableSize = s.Val cc.peerMaxHeaderTableSize = s.Val
case SettingEnableConnectProtocol:
if err := s.Valid(); err != nil {
return err
}
// If the peer wants to send us SETTINGS_ENABLE_CONNECT_PROTOCOL,
// we require that it do so in the first SETTINGS frame.
//
// When we attempt to use extended CONNECT, we wait for the first
// SETTINGS frame to see if the server supports it. If we let the
// server enable the feature with a later SETTINGS frame, then
// users will see inconsistent results depending on whether we've
// seen that frame or not.
if !cc.seenSettings {
cc.extendedConnectAllowed = s.Val == 1
}
default: default:
cc.vlogf("Unhandled Setting: %v", s) cc.vlogf("Unhandled Setting: %v", s)
} }
@ -3090,6 +3163,7 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
// connection can establish to our default. // connection can establish to our default.
cc.maxConcurrentStreams = defaultMaxConcurrentStreams cc.maxConcurrentStreams = defaultMaxConcurrentStreams
} }
close(cc.seenSettingsChan)
cc.seenSettings = true cc.seenSettings = true
} }
@ -3098,7 +3172,7 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error { func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
cc := rl.cc cc := rl.cc
cs := rl.streamByID(f.StreamID) cs := rl.streamByID(f.StreamID, notHeaderOrDataFrame)
if f.StreamID != 0 && cs == nil { if f.StreamID != 0 && cs == nil {
return nil return nil
} }
@ -3127,7 +3201,7 @@ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
} }
func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error { func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
cs := rl.streamByID(f.StreamID) cs := rl.streamByID(f.StreamID, notHeaderOrDataFrame)
if cs == nil { if cs == nil {
// TODO: return error if server tries to RST_STREAM an idle stream // TODO: return error if server tries to RST_STREAM an idle stream
return nil return nil
@ -3205,6 +3279,7 @@ func (rl *clientConnReadLoop) processPing(f *PingFrame) error {
if cc.pendingResets > 0 { if cc.pendingResets > 0 {
// See clientStream.cleanupWriteRequest. // See clientStream.cleanupWriteRequest.
cc.pendingResets = 0 cc.pendingResets = 0
cc.rstStreamPingsBlocked = true
cc.cond.Broadcast() cc.cond.Broadcast()
} }
return nil return nil

2
vendor/modules.txt vendored
View File

@ -753,7 +753,7 @@ golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/exp/constraints golang.org/x/exp/constraints
golang.org/x/exp/maps golang.org/x/exp/maps
golang.org/x/exp/slices golang.org/x/exp/slices
# golang.org/x/net v0.31.0 # golang.org/x/net v0.32.0
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/net/context golang.org/x/net/context
golang.org/x/net/html golang.org/x/net/html