Skip to content

Commit 0c1aede

Browse files
ZekeLugopherbot
authored andcommitted
http2: calculate a correct window increment size for a stream
CL 432038 reduces sending WindowUpdates by introducing a threshold. Once the remaining bytes are below the threshold, a single WindowUpdate is sent to reset the amount back to the maximum amount configured. The window increment size for a stream is calculated from: sc.srv.initialStreamRecvWindowSize() - st.inflow.available() Where (*flow).available is defined as: func (f *flow) available() int32 { n := f.n if f.conn != nil && f.conn.n < n { n = f.conn.n } return n } When f.conn.c < f.n, it gets a bigger increment size. It should be calculated from: sc.srv.initialStreamRecvWindowSize() - st.inflow.n While we're here, remove an unnecessary type conversion too. Updates golang/go#56315. Change-Id: I4b26b27e4c5c5cd66e6a32b152d68f304adc65d8 GitHub-Last-Rev: 02fc09c GitHub-Pull-Request: #155 Reviewed-on: https://go-review.googlesource.com/c/net/+/444816 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Damien Neil <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Run-TryBot: Damien Neil <[email protected]>
1 parent 84c13af commit 0c1aede

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

http2/server.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,13 +2336,13 @@ func (sc *serverConn) sendWindowUpdate(st *stream) {
23362336

23372337
var n int32
23382338
if st == nil {
2339-
if avail, windowSize := sc.inflow.available(), sc.srv.initialConnRecvWindowSize(); avail > windowSize/2 {
2339+
if avail, windowSize := sc.inflow.n, sc.srv.initialConnRecvWindowSize(); avail > windowSize/2 {
23402340
return
23412341
} else {
23422342
n = windowSize - avail
23432343
}
23442344
} else {
2345-
if avail, windowSize := st.inflow.available(), sc.srv.initialStreamRecvWindowSize(); avail > windowSize/2 {
2345+
if avail, windowSize := st.inflow.n, sc.srv.initialStreamRecvWindowSize(); avail > windowSize/2 {
23462346
return
23472347
} else {
23482348
n = windowSize - avail
@@ -2358,7 +2358,7 @@ func (sc *serverConn) sendWindowUpdate(st *stream) {
23582358
sc.sendWindowUpdate32(st, maxUint31)
23592359
n -= maxUint31
23602360
}
2361-
sc.sendWindowUpdate32(st, int32(n))
2361+
sc.sendWindowUpdate32(st, n)
23622362
}
23632363

23642364
// st may be nil for conn-level

http2/server_test.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ func (st *serverTester) greetAndCheckSettings(checkSetting func(s Setting) error
315315
if f.FrameHeader.StreamID != 0 {
316316
st.t.Fatalf("WindowUpdate StreamID = %d; want 0", f.FrameHeader.StreamID)
317317
}
318-
incr := uint32((&Server{}).initialConnRecvWindowSize() - initialWindowSize)
318+
incr := uint32(st.sc.srv.initialConnRecvWindowSize() - initialWindowSize)
319319
if f.Increment != incr {
320320
st.t.Fatalf("WindowUpdate increment = %d; want %d", f.Increment, incr)
321321
}
@@ -1326,6 +1326,44 @@ func TestServer_Handler_Sends_WindowUpdate_Padding(t *testing.T) {
13261326
puppet.do(readBodyHandler(t, "def"))
13271327
}
13281328

1329+
// This is a regression test to make sure the correct window increment size is
1330+
// calculated for a stream.
1331+
// See https://go.dev/issue/56315#issuecomment-1287642591.
1332+
func TestServer_Handler_Sends_WindowUpdate_IncrementSize(t *testing.T) {
1333+
maxSizePerConn := initialWindowSize * 2
1334+
maxSizePerStream := maxSizePerConn*2 + 100
1335+
1336+
puppet := newHandlerPuppet()
1337+
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
1338+
puppet.act(w, r)
1339+
}, func(s *Server) {
1340+
s.MaxUploadBufferPerConnection = int32(maxSizePerConn)
1341+
s.MaxUploadBufferPerStream = int32(maxSizePerStream)
1342+
})
1343+
defer st.Close()
1344+
defer puppet.done()
1345+
1346+
st.greet()
1347+
1348+
st.writeHeaders(HeadersFrameParam{
1349+
StreamID: 1,
1350+
BlockFragment: st.encodeHeader(":method", "POST"),
1351+
EndStream: false,
1352+
EndHeaders: true,
1353+
})
1354+
1355+
st.writeData(1, false, bytes.Repeat([]byte("a"), maxSizePerConn/2))
1356+
puppet.do(readBodyHandler(t, strings.Repeat("a", maxSizePerConn/2)))
1357+
st.wantWindowUpdate(0, uint32(maxSizePerConn/2))
1358+
1359+
st.writeData(1, false, bytes.Repeat([]byte("b"), maxSizePerConn/2+100))
1360+
puppet.do(readBodyHandler(t, strings.Repeat("b", maxSizePerConn/2+100)))
1361+
st.wantWindowUpdate(0, uint32(maxSizePerConn/2+100))
1362+
st.wantWindowUpdate(1, uint32(maxSizePerConn+100))
1363+
1364+
st.writeData(1, true, nil) // END_STREAM here
1365+
}
1366+
13291367
func TestServer_Send_GoAway_After_Bogus_WindowUpdate(t *testing.T) {
13301368
st := newServerTester(t, nil)
13311369
defer st.Close()

0 commit comments

Comments
 (0)