Skip to content

Commit 4aac677

Browse files
committed
update
1 parent bccd6b9 commit 4aac677

File tree

3 files changed

+42
-25
lines changed

3 files changed

+42
-25
lines changed

Diff for: http2/frame.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
14981498
return pseudoHeaderError(hf.Name)
14991499
}
15001500
// Check for duplicates.
1501-
// This would be a bad algorithm, but N is 4.
1501+
// This would be a bad algorithm, but N is 5.
15021502
// And this doesn't allocate.
15031503
for _, hf2 := range pf[:i] {
15041504
if hf.Name == hf2.Name {

Diff for: http2/transport.go

+38-24
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ type ClientConn struct {
364364
initialStreamRecvWindowSize int32
365365
readIdleTimeout time.Duration
366366
pingTimeout time.Duration
367-
extendedConnecAllowed bool
367+
extendedConnectAllowed bool
368368

369369
// reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests.
370370
// Write to reqHeaderMu to lock it, read from it to unlock.
@@ -1396,34 +1396,42 @@ func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStre
13961396
return err
13971397
}
13981398

1399+
// wait for setting frames to be received, a server can change this value later,
1400+
// but we just wait for the first settings frame
1401+
var isExtendedConnect bool
1402+
if req.Method == "CONNECT" && req.Header.Get(":protocol") != "" {
1403+
isExtendedConnect = true
1404+
}
1405+
13991406
// Acquire the new-request lock by writing to reqHeaderMu.
14001407
// This lock guards the critical section covering allocating a new stream ID
14011408
// (requires mu) and creating the stream (requires wmu).
14021409
if cc.reqHeaderMu == nil {
14031410
panic("RoundTrip on uninitialized ClientConn") // for tests
14041411
}
1405-
select {
1406-
case cc.reqHeaderMu <- struct{}{}:
1407-
case <-cs.reqCancel:
1408-
return errRequestCanceled
1409-
case <-ctx.Done():
1410-
return ctx.Err()
1411-
}
1412-
1413-
// wait for setting frames to be received, a server can change this value later,
1414-
// but we just wait for the first settings frame
1415-
var isExtendedConnect bool
1416-
if req.Method == "CONNECT" && req.Header.Get(":protocol") != "" {
1417-
isExtendedConnect = true
1418-
<-cc.seenSettingsChan
1412+
if isExtendedConnect {
1413+
select {
1414+
case cc.reqHeaderMu <- struct{}{}:
1415+
case <-cs.reqCancel:
1416+
return errRequestCanceled
1417+
case <-ctx.Done():
1418+
return ctx.Err()
1419+
case <-cc.seenSettingsChan:
1420+
if !cc.extendedConnectAllowed {
1421+
return errExtendedConnectNotSupported
1422+
}
1423+
}
1424+
} else {
1425+
select {
1426+
case cc.reqHeaderMu <- struct{}{}:
1427+
case <-cs.reqCancel:
1428+
return errRequestCanceled
1429+
case <-ctx.Done():
1430+
return ctx.Err()
1431+
}
14191432
}
14201433

14211434
cc.mu.Lock()
1422-
if isExtendedConnect && !cc.extendedConnecAllowed {
1423-
cc.mu.Unlock()
1424-
<-cc.reqHeaderMu
1425-
return errExtendedConnectNotSupported
1426-
}
14271435
if cc.idleTimer != nil {
14281436
cc.idleTimer.Stop()
14291437
}
@@ -2946,11 +2954,17 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
29462954
if err := s.Valid(); err != nil {
29472955
return err
29482956
}
2949-
// RFC 8441 section, https://datatracker.ietf.org/doc/html/rfc8441#section-3
2950-
if s.Val == 0 && cc.extendedConnecAllowed {
2951-
return ConnectionError(ErrCodeProtocol)
2957+
// If the peer wants to send us SETTINGS_ENABLE_CONNECT_PROTOCOL,
2958+
// we require that it do so in the first SETTINGS frame.
2959+
//
2960+
// When we attempt to use extended CONNECT, we wait for the first
2961+
// SETTINGS frame to see if the server supports it. If we let the
2962+
// server enable the feature with a later SETTINGS frame, then
2963+
// users will see inconsistent results depending on whether we've
2964+
// seen that frame or not.
2965+
if !cc.seenSettings {
2966+
cc.extendedConnectAllowed = s.Val == 1
29522967
}
2953-
cc.extendedConnecAllowed = s.Val == 1
29542968
default:
29552969
cc.vlogf("Unhandled Setting: %v", s)
29562970
}

Diff for: http2/transport_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -5425,6 +5425,9 @@ func TestIssue67671(t *testing.T) {
54255425
func TestExtendedConnectClientWithServerSupport(t *testing.T) {
54265426
disableExtendedConnectProtocol = false
54275427
ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
5428+
if r.Header.Get(":protocol") != "extended-connect" {
5429+
t.Fatalf("unexpected :protocol header received")
5430+
}
54285431
t.Log(io.Copy(w, r.Body))
54295432
})
54305433
tr := &Transport{

0 commit comments

Comments
 (0)