@@ -448,7 +448,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
448
448
// configured value for inflow, that will be updated when we send a
449
449
// WINDOW_UPDATE shortly after sending SETTINGS.
450
450
sc .flow .add (initialWindowSize )
451
- sc .inflow .add (initialWindowSize )
451
+ sc .inflow .init (initialWindowSize )
452
452
sc .hpackEncoder = hpack .NewEncoder (& sc .headerWriteBuf )
453
453
sc .hpackEncoder .SetMaxDynamicTableSizeLimit (s .maxEncoderHeaderTableSize ())
454
454
@@ -563,8 +563,8 @@ type serverConn struct {
563
563
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
564
564
bodyReadCh chan bodyReadMsg // from handlers -> serve
565
565
serveMsgCh chan interface {} // misc messages & code to send to / run on the serve loop
566
- flow flow // conn-wide (not stream-specific) outbound flow control
567
- inflow flow // conn-wide inbound flow control
566
+ flow outflow // conn-wide (not stream-specific) outbound flow control
567
+ inflow inflow // conn-wide inbound flow control
568
568
tlsState * tls.ConnectionState // shared by all handlers, like net/http
569
569
remoteAddrStr string
570
570
writeSched WriteScheduler
@@ -641,10 +641,10 @@ type stream struct {
641
641
cancelCtx func ()
642
642
643
643
// owned by serverConn's serve loop:
644
- bodyBytes int64 // body bytes seen so far
645
- declBodyBytes int64 // or -1 if undeclared
646
- flow flow // limits writing from Handler to client
647
- inflow flow // what the client is allowed to POST/etc to us
644
+ bodyBytes int64 // body bytes seen so far
645
+ declBodyBytes int64 // or -1 if undeclared
646
+ flow outflow // limits writing from Handler to client
647
+ inflow inflow // what the client is allowed to POST/etc to us
648
648
state streamState
649
649
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
650
650
gotTrailerHeader bool // HEADER frame for trailers was seen
@@ -1503,7 +1503,7 @@ func (sc *serverConn) processFrame(f Frame) error {
1503
1503
if sc .inGoAway && (sc .goAwayCode != ErrCodeNo || f .Header ().StreamID > sc .maxClientStreamID ) {
1504
1504
1505
1505
if f , ok := f .(* DataFrame ); ok {
1506
- if sc .inflow .available () < int32 (f .Length ) {
1506
+ if ! sc .inflow .take (f .Length ) {
1507
1507
return sc .countError ("data_flow" , streamError (f .Header ().StreamID , ErrCodeFlowControl ))
1508
1508
}
1509
1509
sc .sendWindowUpdate (nil , int (f .Length )) // conn-level
@@ -1775,14 +1775,9 @@ func (sc *serverConn) processData(f *DataFrame) error {
1775
1775
// But still enforce their connection-level flow control,
1776
1776
// and return any flow control bytes since we're not going
1777
1777
// to consume them.
1778
- if sc .inflow .available () < int32 (f .Length ) {
1778
+ if ! sc .inflow .take (f .Length ) {
1779
1779
return sc .countError ("data_flow" , streamError (id , ErrCodeFlowControl ))
1780
1780
}
1781
- // Deduct the flow control from inflow, since we're
1782
- // going to immediately add it back in
1783
- // sendWindowUpdate, which also schedules sending the
1784
- // frames.
1785
- sc .inflow .take (int32 (f .Length ))
1786
1781
sc .sendWindowUpdate (nil , int (f .Length )) // conn-level
1787
1782
1788
1783
if st != nil && st .resetQueued {
@@ -1797,10 +1792,9 @@ func (sc *serverConn) processData(f *DataFrame) error {
1797
1792
1798
1793
// Sender sending more than they'd declared?
1799
1794
if st .declBodyBytes != - 1 && st .bodyBytes + int64 (len (data )) > st .declBodyBytes {
1800
- if sc .inflow .available () < int32 (f .Length ) {
1795
+ if ! sc .inflow .take (f .Length ) {
1801
1796
return sc .countError ("data_flow" , streamError (id , ErrCodeFlowControl ))
1802
1797
}
1803
- sc .inflow .take (int32 (f .Length ))
1804
1798
sc .sendWindowUpdate (nil , int (f .Length )) // conn-level
1805
1799
1806
1800
st .body .CloseWithError (fmt .Errorf ("sender tried to send more than declared Content-Length of %d bytes" , st .declBodyBytes ))
@@ -1811,10 +1805,9 @@ func (sc *serverConn) processData(f *DataFrame) error {
1811
1805
}
1812
1806
if f .Length > 0 {
1813
1807
// Check whether the client has flow control quota.
1814
- if st .inflow . available () < int32 ( f .Length ) {
1808
+ if ! takeInflows ( & sc .inflow , & st . inflow , f .Length ) {
1815
1809
return sc .countError ("flow_on_data_length" , streamError (id , ErrCodeFlowControl ))
1816
1810
}
1817
- st .inflow .take (int32 (f .Length ))
1818
1811
1819
1812
if len (data ) > 0 {
1820
1813
wrote , err := st .body .Write (data )
@@ -1830,10 +1823,12 @@ func (sc *serverConn) processData(f *DataFrame) error {
1830
1823
1831
1824
// Return any padded flow control now, since we won't
1832
1825
// refund it later on body reads.
1833
- if pad := int32 (f .Length ) - int32 (len (data )); pad > 0 {
1834
- sc .sendWindowUpdate32 (nil , pad )
1835
- sc .sendWindowUpdate32 (st , pad )
1836
- }
1826
+ // Call sendWindowUpdate even if there is no padding,
1827
+ // to return buffered flow control credit if the sent
1828
+ // window has shrunk.
1829
+ pad := int32 (f .Length ) - int32 (len (data ))
1830
+ sc .sendWindowUpdate32 (nil , pad )
1831
+ sc .sendWindowUpdate32 (st , pad )
1837
1832
}
1838
1833
if f .StreamEnded () {
1839
1834
st .endStream ()
@@ -2105,8 +2100,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
2105
2100
st .cw .Init ()
2106
2101
st .flow .conn = & sc .flow // link to conn-level counter
2107
2102
st .flow .add (sc .initialStreamSendWindowSize )
2108
- st .inflow .conn = & sc .inflow // link to conn-level counter
2109
- st .inflow .add (sc .srv .initialStreamRecvWindowSize ())
2103
+ st .inflow .init (sc .srv .initialStreamRecvWindowSize ())
2110
2104
if sc .hs .WriteTimeout != 0 {
2111
2105
st .writeDeadline = time .AfterFunc (sc .hs .WriteTimeout , st .onWriteTimeout )
2112
2106
}
@@ -2388,47 +2382,28 @@ func (sc *serverConn) noteBodyRead(st *stream, n int) {
2388
2382
}
2389
2383
2390
2384
// st may be nil for conn-level
2391
- func (sc * serverConn ) sendWindowUpdate (st * stream , n int ) {
2392
- sc .serveG .check ()
2393
- // "The legal range for the increment to the flow control
2394
- // window is 1 to 2^31-1 (2,147,483,647) octets."
2395
- // A Go Read call on 64-bit machines could in theory read
2396
- // a larger Read than this. Very unlikely, but we handle it here
2397
- // rather than elsewhere for now.
2398
- const maxUint31 = 1 << 31 - 1
2399
- for n > maxUint31 {
2400
- sc .sendWindowUpdate32 (st , maxUint31 )
2401
- n -= maxUint31
2402
- }
2403
- sc .sendWindowUpdate32 (st , int32 (n ))
2385
+ func (sc * serverConn ) sendWindowUpdate32 (st * stream , n int32 ) {
2386
+ sc .sendWindowUpdate (st , int (n ))
2404
2387
}
2405
2388
2406
2389
// st may be nil for conn-level
2407
- func (sc * serverConn ) sendWindowUpdate32 (st * stream , n int32 ) {
2390
+ func (sc * serverConn ) sendWindowUpdate (st * stream , n int ) {
2408
2391
sc .serveG .check ()
2409
- if n == 0 {
2410
- return
2411
- }
2412
- if n < 0 {
2413
- panic ("negative update" )
2414
- }
2415
2392
var streamID uint32
2416
- if st != nil {
2393
+ var send int32
2394
+ if st == nil {
2395
+ send = sc .inflow .add (n )
2396
+ } else {
2417
2397
streamID = st .id
2398
+ send = st .inflow .add (n )
2399
+ }
2400
+ if send == 0 {
2401
+ return
2418
2402
}
2419
2403
sc .writeFrame (FrameWriteRequest {
2420
- write : writeWindowUpdate {streamID : streamID , n : uint32 (n )},
2404
+ write : writeWindowUpdate {streamID : streamID , n : uint32 (send )},
2421
2405
stream : st ,
2422
2406
})
2423
- var ok bool
2424
- if st == nil {
2425
- ok = sc .inflow .add (n )
2426
- } else {
2427
- ok = st .inflow .add (n )
2428
- }
2429
- if ! ok {
2430
- panic ("internal error; sent too many window updates without decrements?" )
2431
- }
2432
2407
}
2433
2408
2434
2409
// requestBody is the Handler's Request.Body type.
0 commit comments