mirror of
https://github.com/golang/net.git
synced 2026-03-31 10:27:08 +09:00
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: 02fc09c1e7
GitHub-Pull-Request: golang/net#155
Reviewed-on: https://go-review.googlesource.com/c/net/+/444816
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
This commit is contained in:
@@ -2336,13 +2336,13 @@ func (sc *serverConn) sendWindowUpdate(st *stream) {
|
||||
|
||||
var n int32
|
||||
if st == nil {
|
||||
if avail, windowSize := sc.inflow.available(), sc.srv.initialConnRecvWindowSize(); avail > windowSize/2 {
|
||||
if avail, windowSize := sc.inflow.n, sc.srv.initialConnRecvWindowSize(); avail > windowSize/2 {
|
||||
return
|
||||
} else {
|
||||
n = windowSize - avail
|
||||
}
|
||||
} else {
|
||||
if avail, windowSize := st.inflow.available(), sc.srv.initialStreamRecvWindowSize(); avail > windowSize/2 {
|
||||
if avail, windowSize := st.inflow.n, sc.srv.initialStreamRecvWindowSize(); avail > windowSize/2 {
|
||||
return
|
||||
} else {
|
||||
n = windowSize - avail
|
||||
@@ -2358,7 +2358,7 @@ func (sc *serverConn) sendWindowUpdate(st *stream) {
|
||||
sc.sendWindowUpdate32(st, maxUint31)
|
||||
n -= maxUint31
|
||||
}
|
||||
sc.sendWindowUpdate32(st, int32(n))
|
||||
sc.sendWindowUpdate32(st, n)
|
||||
}
|
||||
|
||||
// st may be nil for conn-level
|
||||
|
||||
@@ -315,7 +315,7 @@ func (st *serverTester) greetAndCheckSettings(checkSetting func(s Setting) error
|
||||
if f.FrameHeader.StreamID != 0 {
|
||||
st.t.Fatalf("WindowUpdate StreamID = %d; want 0", f.FrameHeader.StreamID)
|
||||
}
|
||||
incr := uint32((&Server{}).initialConnRecvWindowSize() - initialWindowSize)
|
||||
incr := uint32(st.sc.srv.initialConnRecvWindowSize() - initialWindowSize)
|
||||
if f.Increment != incr {
|
||||
st.t.Fatalf("WindowUpdate increment = %d; want %d", f.Increment, incr)
|
||||
}
|
||||
@@ -1326,6 +1326,44 @@ func TestServer_Handler_Sends_WindowUpdate_Padding(t *testing.T) {
|
||||
puppet.do(readBodyHandler(t, "def"))
|
||||
}
|
||||
|
||||
// This is a regression test to make sure the correct window increment size is
|
||||
// calculated for a stream.
|
||||
// See https://go.dev/issue/56315#issuecomment-1287642591.
|
||||
func TestServer_Handler_Sends_WindowUpdate_IncrementSize(t *testing.T) {
|
||||
maxSizePerConn := initialWindowSize * 2
|
||||
maxSizePerStream := maxSizePerConn*2 + 100
|
||||
|
||||
puppet := newHandlerPuppet()
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
puppet.act(w, r)
|
||||
}, func(s *Server) {
|
||||
s.MaxUploadBufferPerConnection = int32(maxSizePerConn)
|
||||
s.MaxUploadBufferPerStream = int32(maxSizePerStream)
|
||||
})
|
||||
defer st.Close()
|
||||
defer puppet.done()
|
||||
|
||||
st.greet()
|
||||
|
||||
st.writeHeaders(HeadersFrameParam{
|
||||
StreamID: 1,
|
||||
BlockFragment: st.encodeHeader(":method", "POST"),
|
||||
EndStream: false,
|
||||
EndHeaders: true,
|
||||
})
|
||||
|
||||
st.writeData(1, false, bytes.Repeat([]byte("a"), maxSizePerConn/2))
|
||||
puppet.do(readBodyHandler(t, strings.Repeat("a", maxSizePerConn/2)))
|
||||
st.wantWindowUpdate(0, uint32(maxSizePerConn/2))
|
||||
|
||||
st.writeData(1, false, bytes.Repeat([]byte("b"), maxSizePerConn/2+100))
|
||||
puppet.do(readBodyHandler(t, strings.Repeat("b", maxSizePerConn/2+100)))
|
||||
st.wantWindowUpdate(0, uint32(maxSizePerConn/2+100))
|
||||
st.wantWindowUpdate(1, uint32(maxSizePerConn+100))
|
||||
|
||||
st.writeData(1, true, nil) // END_STREAM here
|
||||
}
|
||||
|
||||
func TestServer_Send_GoAway_After_Bogus_WindowUpdate(t *testing.T) {
|
||||
st := newServerTester(t, nil)
|
||||
defer st.Close()
|
||||
|
||||
Reference in New Issue
Block a user