Skip to content

Commit

Permalink
[internal-branch.go1.17-vendor] http2: fix off-by-one error in client…
Browse files Browse the repository at this point in the history
… check for max concurrent streams

Updates golang/go#49077

Change-Id: Ib4eb93702b32ae7d03cad17ca0b997d5e6a58ad7
Reviewed-on: https://go-review.googlesource.com/c/net/+/349490
Trust: Damien Neil <dneil@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/net/+/357676
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
  • Loading branch information
neild authored and dmitshur committed Oct 29, 2021
1 parent fad72be commit 95197d6
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 2 deletions.
4 changes: 2 additions & 2 deletions transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
// writing it.
maxConcurrentOkay = true
} else {
maxConcurrentOkay = int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams)
maxConcurrentOkay = int64(len(cc.streams)+1) <= int64(cc.maxConcurrentStreams)
}

st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay &&
Expand Down Expand Up @@ -1207,7 +1207,7 @@ func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
return errClientConnUnusable
}
cc.lastIdle = time.Time{}
if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
if int64(len(cc.streams)) < int64(cc.maxConcurrentStreams) {
if waitingForConn != nil {
close(waitingForConn)
}
Expand Down
45 changes: 45 additions & 0 deletions transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3824,6 +3824,51 @@ func TestTransportResponseDataBeforeHeaders(t *testing.T) {
ct.run()
}

func TestTransportRequestsLowServerLimit(t *testing.T) {
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
}, optOnlyServer, func(s *Server) {
s.MaxConcurrentStreams = 1
})
defer st.Close()

var (
connCountMu sync.Mutex
connCount int
)
tr := &Transport{
TLSClientConfig: tlsConfigInsecure,
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
connCountMu.Lock()
defer connCountMu.Unlock()
connCount++
return tls.Dial(network, addr, cfg)
},
}
defer tr.CloseIdleConnections()

const reqCount = 3
for i := 0; i < reqCount; i++ {
req, err := http.NewRequest("GET", st.ts.URL, nil)
if err != nil {
t.Fatal(err)
}
res, err := tr.RoundTrip(req)
if err != nil {
t.Fatal(err)
}
if got, want := res.StatusCode, 200; got != want {
t.Errorf("StatusCode = %v; want %v", got, want)
}
if res != nil && res.Body != nil {
res.Body.Close()
}
}

if connCount != 1 {
t.Errorf("created %v connections for %v requests, want 1", connCount, reqCount)
}
}

// tests Transport.StrictMaxConcurrentStreams
func TestTransportRequestsStallAtServerLimit(t *testing.T) {
const maxConcurrent = 2
Expand Down

0 comments on commit 95197d6

Please sign in to comment.