@ttsc/darwin-x64 0.32.1 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/go/VERSION +2 -2
- package/bin/go/bin/go +0 -0
- package/bin/go/bin/gofmt +0 -0
- package/bin/go/pkg/tool/darwin_amd64/asm +0 -0
- package/bin/go/pkg/tool/darwin_amd64/cgo +0 -0
- package/bin/go/pkg/tool/darwin_amd64/compile +0 -0
- package/bin/go/pkg/tool/darwin_amd64/cover +0 -0
- package/bin/go/pkg/tool/darwin_amd64/fix +0 -0
- package/bin/go/pkg/tool/darwin_amd64/link +0 -0
- package/bin/go/pkg/tool/darwin_amd64/preprofile +0 -0
- package/bin/go/pkg/tool/darwin_amd64/vet +0 -0
- package/bin/go/src/crypto/internal/fips140/mlkem/cast.go +66 -36
- package/bin/go/src/crypto/internal/fips140/mlkem/mlkem768.go +6 -0
- package/bin/go/src/crypto/tls/ech.go +18 -4
- package/bin/go/src/go.mod +1 -1
- package/bin/go/src/go.sum +2 -2
- package/bin/go/src/html/template/js.go +8 -3
- package/bin/go/src/html/template/transition.go +8 -1
- package/bin/go/src/internal/buildcfg/zbootstrap.go +1 -1
- package/bin/go/src/internal/godebugs/table.go +1 -0
- package/bin/go/src/internal/poll/fd_windows.go +21 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_arm.go +3 -3
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_arm64.go +3 -3
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_loong64.go +2 -2
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_mips64x.go +2 -2
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_mipsx.go +1 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_ppc64x.go +2 -2
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_riscv64.go +2 -2
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_s390x.go +2 -2
- package/bin/go/src/internal/syscall/windows/at_windows.go +91 -15
- package/bin/go/src/internal/syscall/windows/types_windows.go +8 -1
- package/bin/go/src/mime/multipart/formdata.go +4 -5
- package/bin/go/src/net/http/fs.go +28 -0
- package/bin/go/src/net/http/h2_bundle.go +278 -133
- package/bin/go/src/net/http/httputil/reverseproxy.go +15 -0
- package/bin/go/src/net/http/server.go +23 -3
- package/bin/go/src/net/http/transport.go +6 -1
- package/bin/go/src/net/textproto/reader.go +9 -7
- package/bin/go/src/os/file_windows.go +7 -3
- package/bin/go/src/os/root_openat.go +5 -5
- package/bin/go/src/os/root_unix.go +4 -0
- package/bin/go/src/os/root_windows.go +8 -2
- package/bin/go/src/runtime/metrics/doc.go +5 -0
- package/bin/go/src/runtime/netpoll_epoll.go +20 -7
- package/bin/go/src/runtime/os_windows.go +23 -0
- package/bin/go/src/vendor/modules.txt +1 -1
- package/bin/ttsc +0 -0
- package/bin/ttsc-cache +0 -0
- package/bin/ttscserver +0 -0
- package/package.json +2 -1
|
@@ -41,6 +41,7 @@ import (
|
|
|
41
41
|
"os"
|
|
42
42
|
"reflect"
|
|
43
43
|
"runtime"
|
|
44
|
+
"slices"
|
|
44
45
|
"sort"
|
|
45
46
|
"strconv"
|
|
46
47
|
"strings"
|
|
@@ -1472,6 +1473,9 @@ var (
|
|
|
1472
1473
|
// flow control window update.
|
|
1473
1474
|
const http2inflowMinRefresh = 4 << 10
|
|
1474
1475
|
|
|
1476
|
+
// maxFlowWindow is the maximum size of a flow control window.
|
|
1477
|
+
const http2maxFlowWindow = (1 << 31) - 1
|
|
1478
|
+
|
|
1475
1479
|
// inflow accounts for an inbound flow control window.
|
|
1476
1480
|
// It tracks both the latest window sent to the peer (used for enforcement)
|
|
1477
1481
|
// and the accumulated unsent window.
|
|
@@ -1536,49 +1540,101 @@ func http2takeInflows(f1, f2 *http2inflow, n uint32) bool {
|
|
|
1536
1540
|
return true
|
|
1537
1541
|
}
|
|
1538
1542
|
|
|
1539
|
-
//
|
|
1543
|
+
// connOutflow is connection-level outbound flow control.
|
|
1544
|
+
type http2connOutflow struct {
|
|
1545
|
+
initial int32 // SETTINGS_INITIAL_WINDOW_SIZE, changes with settings updates
|
|
1546
|
+
n int32 // connection-level flow control window
|
|
1547
|
+
flowErr bool // set when a flow control error is encountered
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
func (f *http2connOutflow) init() {
|
|
1551
|
+
f.initial = http2initialWindowSize // initial stream window size
|
|
1552
|
+
f.n = http2initialWindowSize // current connection window size
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
func (f *http2connOutflow) changeInitialWindowSize(size int64) bool {
|
|
1556
|
+
if size > http2maxFlowWindow {
|
|
1557
|
+
f.flowErr = true
|
|
1558
|
+
return false
|
|
1559
|
+
}
|
|
1560
|
+
f.initial = int32(size)
|
|
1561
|
+
return true
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
func (f *http2connOutflow) add(n int32) bool {
|
|
1565
|
+
sum := int64(f.n) + int64(n)
|
|
1566
|
+
if sum > http2maxFlowWindow {
|
|
1567
|
+
f.flowErr = true
|
|
1568
|
+
return false
|
|
1569
|
+
}
|
|
1570
|
+
f.n += n
|
|
1571
|
+
return true
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
// outflow is the stream-level outbound flow control window's size.
|
|
1540
1575
|
type http2outflow struct {
|
|
1541
1576
|
_ http2incomparable
|
|
1542
1577
|
|
|
1543
|
-
//
|
|
1544
|
-
//
|
|
1545
|
-
|
|
1578
|
+
// delta is the difference between the stream's flow control window and
|
|
1579
|
+
// the connection's initial window size (conn.initial).
|
|
1580
|
+
//
|
|
1581
|
+
// Another view is that delta is the number of flow control bytes provided to this
|
|
1582
|
+
// stream in WINDOW_UPDATE frames, less the number of bytes sent on the stream.
|
|
1583
|
+
delta int32
|
|
1546
1584
|
|
|
1547
1585
|
// conn points to the shared connection-level outflow that is
|
|
1548
|
-
// shared by all streams on that conn.
|
|
1549
|
-
|
|
1550
|
-
conn *http2outflow
|
|
1586
|
+
// shared by all streams on that conn.
|
|
1587
|
+
conn *http2connOutflow
|
|
1551
1588
|
}
|
|
1552
1589
|
|
|
1553
|
-
func (f *http2outflow)
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
n := f.n
|
|
1557
|
-
if f.conn != nil && f.conn.n < n {
|
|
1558
|
-
n = f.conn.n
|
|
1590
|
+
func (f *http2outflow) available() (int32, bool) {
|
|
1591
|
+
if f.conn == nil {
|
|
1592
|
+
return http2maxFlowWindow, true // only happens in tests
|
|
1559
1593
|
}
|
|
1560
|
-
|
|
1594
|
+
if f.conn.flowErr {
|
|
1595
|
+
// Block all sending once any stream observes a flow control error.
|
|
1596
|
+
return 0, false
|
|
1597
|
+
}
|
|
1598
|
+
n := int64(f.conn.initial) + int64(f.delta)
|
|
1599
|
+
if n > http2maxFlowWindow {
|
|
1600
|
+
f.conn.flowErr = true
|
|
1601
|
+
return 0, false
|
|
1602
|
+
}
|
|
1603
|
+
return min(int32(n), f.conn.n), true
|
|
1561
1604
|
}
|
|
1562
1605
|
|
|
1563
1606
|
func (f *http2outflow) take(n int32) {
|
|
1564
|
-
if
|
|
1565
|
-
|
|
1607
|
+
if f.conn == nil {
|
|
1608
|
+
return // only happens in tests
|
|
1566
1609
|
}
|
|
1567
|
-
f.
|
|
1568
|
-
if
|
|
1569
|
-
|
|
1610
|
+
avail, _ := f.available()
|
|
1611
|
+
if n > avail {
|
|
1612
|
+
panic("internal error: took too much")
|
|
1570
1613
|
}
|
|
1614
|
+
f.delta -= n
|
|
1615
|
+
f.conn.n -= n
|
|
1571
1616
|
}
|
|
1572
1617
|
|
|
1573
1618
|
// add adds n bytes (positive or negative) to the flow control window.
|
|
1574
1619
|
// It returns false if the sum would exceed 2^31-1.
|
|
1575
1620
|
func (f *http2outflow) add(n int32) bool {
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1621
|
+
if f.conn == nil {
|
|
1622
|
+
return true // only happens in tests
|
|
1623
|
+
}
|
|
1624
|
+
avail := int64(f.conn.initial) + int64(f.delta)
|
|
1625
|
+
if avail > http2maxFlowWindow {
|
|
1626
|
+
// An earlier change to the initial window pushed this stream over the limit.
|
|
1627
|
+
// This is a connection-level flow control error.
|
|
1628
|
+
f.conn.flowErr = true
|
|
1629
|
+
return false
|
|
1580
1630
|
}
|
|
1581
|
-
|
|
1631
|
+
if avail+int64(n) > http2maxFlowWindow {
|
|
1632
|
+
// This update would push the stream over the limit.
|
|
1633
|
+
// This is a stream-level flow control error.
|
|
1634
|
+
return false
|
|
1635
|
+
}
|
|
1636
|
+
f.delta += n
|
|
1637
|
+
return true
|
|
1582
1638
|
}
|
|
1583
1639
|
|
|
1584
1640
|
const http2frameHeaderLen = 9
|
|
@@ -3159,7 +3215,8 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (http2Frame, error)
|
|
|
3159
3215
|
mh := &http2MetaHeadersFrame{
|
|
3160
3216
|
http2HeadersFrame: hf,
|
|
3161
3217
|
}
|
|
3162
|
-
var
|
|
3218
|
+
var headersRemainSize = fr.maxHeaderListSize()
|
|
3219
|
+
var trailersRemainSize = fr.maxHeaderListSize()
|
|
3163
3220
|
var sawRegular bool
|
|
3164
3221
|
|
|
3165
3222
|
var invalid error // pseudo header field errors
|
|
@@ -3191,14 +3248,29 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (http2Frame, error)
|
|
|
3191
3248
|
return
|
|
3192
3249
|
}
|
|
3193
3250
|
|
|
3194
|
-
|
|
3195
|
-
|
|
3251
|
+
var remainSize *uint32
|
|
3252
|
+
var size uint32
|
|
3253
|
+
if hf.Name == "trailer" {
|
|
3254
|
+
remainSize = &trailersRemainSize
|
|
3255
|
+
fieldCount := strings.Count(hf.Value, ",") + 1
|
|
3256
|
+
// Rather than actually constructing hpack.HeaderField for each
|
|
3257
|
+
// trailer field and cumulatively adding its Size, just do the math
|
|
3258
|
+
// manually to avoid unnecessary work. This does make it so
|
|
3259
|
+
// whitespaces after comma are counted against the budget, but that
|
|
3260
|
+
// should be innocuous.
|
|
3261
|
+
size = uint32(len(hf.Value)-fieldCount+1) + uint32(fieldCount)*hpack.HeaderField{}.Size()
|
|
3262
|
+
} else {
|
|
3263
|
+
remainSize = &headersRemainSize
|
|
3264
|
+
size = hf.Size()
|
|
3265
|
+
}
|
|
3266
|
+
if size > *remainSize {
|
|
3196
3267
|
hdec.SetEmitEnabled(false)
|
|
3197
3268
|
mh.Truncated = true
|
|
3198
|
-
|
|
3269
|
+
headersRemainSize = 0
|
|
3270
|
+
trailersRemainSize = 0
|
|
3199
3271
|
return
|
|
3200
3272
|
}
|
|
3201
|
-
remainSize -= size
|
|
3273
|
+
*remainSize -= size
|
|
3202
3274
|
|
|
3203
3275
|
mh.Fields = append(mh.Fields, hf)
|
|
3204
3276
|
})
|
|
@@ -3214,10 +3286,10 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (http2Frame, error)
|
|
|
3214
3286
|
// skip parsing the fragment and close the connection.
|
|
3215
3287
|
//
|
|
3216
3288
|
// "Too much" is either any CONTINUATION frame after we've already
|
|
3217
|
-
// exceeded the max header list size (
|
|
3218
|
-
//
|
|
3219
|
-
//
|
|
3220
|
-
if int64(len(frag)) > int64(
|
|
3289
|
+
// exceeded the max header list size (if so, both budgets are 0), or a
|
|
3290
|
+
// frame whose encoded size is more than twice the remaining header
|
|
3291
|
+
// list bytes we're willing to accept.
|
|
3292
|
+
if int64(len(frag)) > 2*int64(headersRemainSize+trailersRemainSize) {
|
|
3221
3293
|
if http2VerboseLogs {
|
|
3222
3294
|
log.Printf("http2: header list too large")
|
|
3223
3295
|
}
|
|
@@ -4429,7 +4501,6 @@ func (s *http2Server) serveConn(c net.Conn, opts *http2ServeConnOpts, newf func(
|
|
|
4429
4501
|
doneServing: make(chan struct{}),
|
|
4430
4502
|
clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
|
|
4431
4503
|
advMaxStreams: conf.MaxConcurrentStreams,
|
|
4432
|
-
initialStreamSendWindowSize: http2initialWindowSize,
|
|
4433
4504
|
initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream,
|
|
4434
4505
|
maxFrameSize: http2initialMaxFrameSize,
|
|
4435
4506
|
pingTimeout: conf.PingTimeout,
|
|
@@ -4463,7 +4534,7 @@ func (s *http2Server) serveConn(c net.Conn, opts *http2ServeConnOpts, newf func(
|
|
|
4463
4534
|
// These start at the RFC-specified defaults. If there is a higher
|
|
4464
4535
|
// configured value for inflow, that will be updated when we send a
|
|
4465
4536
|
// WINDOW_UPDATE shortly after sending SETTINGS.
|
|
4466
|
-
sc.flow.
|
|
4537
|
+
sc.flow.init()
|
|
4467
4538
|
sc.inflow.init(http2initialWindowSize)
|
|
4468
4539
|
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
|
4469
4540
|
sc.hpackEncoder.SetMaxDynamicTableSizeLimit(conf.MaxEncoderHeaderTableSize)
|
|
@@ -4579,7 +4650,7 @@ type http2serverConn struct {
|
|
|
4579
4650
|
wroteFrameCh chan http2frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
|
4580
4651
|
bodyReadCh chan http2bodyReadMsg // from handlers -> serve
|
|
4581
4652
|
serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
|
|
4582
|
-
flow
|
|
4653
|
+
flow http2connOutflow // conn-wide (not stream-specific) outbound flow control
|
|
4583
4654
|
inflow http2inflow // conn-wide inbound flow control
|
|
4584
4655
|
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
|
4585
4656
|
remoteAddrStr string
|
|
@@ -4593,6 +4664,9 @@ type http2serverConn struct {
|
|
|
4593
4664
|
sawFirstSettings bool // got the initial SETTINGS frame after the preface
|
|
4594
4665
|
needToSendSettingsAck bool
|
|
4595
4666
|
unackedSettings int // how many SETTINGS have we sent without ACKs?
|
|
4667
|
+
pendingEncoderTableSize bool // peer changed SETTINGS_HEADER_TABLE_SIZE; apply to hpackEncoder before the next frame write
|
|
4668
|
+
encoderTableSizeMin uint32 // smallest SETTINGS_HEADER_TABLE_SIZE since the last apply
|
|
4669
|
+
encoderTableSize uint32 // latest SETTINGS_HEADER_TABLE_SIZE
|
|
4596
4670
|
queuedControlFrames int // control frames in the writeSched queue
|
|
4597
4671
|
clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
|
|
4598
4672
|
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
|
|
@@ -4603,7 +4677,6 @@ type http2serverConn struct {
|
|
|
4603
4677
|
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
|
|
4604
4678
|
streams map[uint32]*http2stream
|
|
4605
4679
|
unstartedHandlers []http2unstartedHandler
|
|
4606
|
-
initialStreamSendWindowSize int32
|
|
4607
4680
|
initialStreamRecvWindowSize int32
|
|
4608
4681
|
maxFrameSize int32
|
|
4609
4682
|
peerMaxHeaderListSize uint32 // zero means unknown (default)
|
|
@@ -4656,7 +4729,8 @@ type http2stream struct {
|
|
|
4656
4729
|
// immutable:
|
|
4657
4730
|
sc *http2serverConn
|
|
4658
4731
|
id uint32
|
|
4659
|
-
body *http2pipe
|
|
4732
|
+
body *http2pipe // non-nil if expecting DATA frames
|
|
4733
|
+
reqBody *http2requestBody
|
|
4660
4734
|
cw http2closeWaiter // closed wait stream transitions to closed state
|
|
4661
4735
|
ctx context.Context
|
|
4662
4736
|
cancelCtx func()
|
|
@@ -5310,6 +5384,16 @@ func (sc *http2serverConn) startFrameWrite(wr http2FrameWriteRequest) {
|
|
|
5310
5384
|
|
|
5311
5385
|
sc.writingFrame = true
|
|
5312
5386
|
sc.needsFrameFlush = true
|
|
5387
|
+
if sc.pendingEncoderTableSize {
|
|
5388
|
+
// hpackEncoder may be in use by writeFrameAsync, so SETTINGS
|
|
5389
|
+
// changes to it are deferred until no frame is being written.
|
|
5390
|
+
// Replaying the smallest size before the latest one keeps the
|
|
5391
|
+
// encoder's view identical to having applied every change
|
|
5392
|
+
// (RFC 7541, Section 4.2).
|
|
5393
|
+
sc.pendingEncoderTableSize = false
|
|
5394
|
+
sc.hpackEncoder.SetMaxDynamicTableSize(sc.encoderTableSizeMin)
|
|
5395
|
+
sc.hpackEncoder.SetMaxDynamicTableSize(sc.encoderTableSize)
|
|
5396
|
+
}
|
|
5313
5397
|
if wr.write.staysWithinBuffer(sc.bw.Available()) {
|
|
5314
5398
|
sc.writingFrameAsync = false
|
|
5315
5399
|
err := wr.write.writeFrame(sc)
|
|
@@ -5409,6 +5493,11 @@ func (sc *http2serverConn) scheduleFrameWrite() {
|
|
|
5409
5493
|
}
|
|
5410
5494
|
sc.inFrameScheduleLoop = true
|
|
5411
5495
|
for !sc.writingFrameAsync {
|
|
5496
|
+
if sc.flow.flowErr && (!sc.inGoAway || sc.goAwayCode == http2ErrCodeNo) {
|
|
5497
|
+
sc.inGoAway = true
|
|
5498
|
+
sc.needToSendGoAway = true
|
|
5499
|
+
sc.goAwayCode = http2ErrCodeFlowControl
|
|
5500
|
+
}
|
|
5412
5501
|
if sc.needToSendGoAway {
|
|
5413
5502
|
sc.needToSendGoAway = false
|
|
5414
5503
|
sc.startFrameWrite(http2FrameWriteRequest{
|
|
@@ -5432,6 +5521,9 @@ func (sc *http2serverConn) scheduleFrameWrite() {
|
|
|
5432
5521
|
sc.startFrameWrite(wr)
|
|
5433
5522
|
continue
|
|
5434
5523
|
}
|
|
5524
|
+
if sc.flow.flowErr {
|
|
5525
|
+
continue
|
|
5526
|
+
}
|
|
5435
5527
|
}
|
|
5436
5528
|
if sc.needsFrameFlush {
|
|
5437
5529
|
sc.startFrameWrite(http2FrameWriteRequest{write: http2flushFrameWriter{}})
|
|
@@ -5662,6 +5754,10 @@ func (sc *http2serverConn) processWindowUpdate(f *http2WindowUpdateFrame) error
|
|
|
5662
5754
|
return nil
|
|
5663
5755
|
}
|
|
5664
5756
|
if !st.flow.add(int32(f.Increment)) {
|
|
5757
|
+
if st.flow.conn.flowErr {
|
|
5758
|
+
// This is a lazily-detected connection-level flow control error.
|
|
5759
|
+
return sc.countError("bad_flow", http2ConnectionError(http2ErrCodeFlowControl))
|
|
5760
|
+
}
|
|
5665
5761
|
return sc.countError("bad_flow", http2streamError(f.StreamID, http2ErrCodeFlowControl))
|
|
5666
5762
|
}
|
|
5667
5763
|
default: // connection-level flow control
|
|
@@ -5720,10 +5816,6 @@ func (sc *http2serverConn) closeStream(st *http2stream, err error) {
|
|
|
5720
5816
|
}
|
|
5721
5817
|
}
|
|
5722
5818
|
if p := st.body; p != nil {
|
|
5723
|
-
// Return any buffered unread bytes worth of conn-level flow control.
|
|
5724
|
-
// See golang.org/issue/16481
|
|
5725
|
-
sc.sendWindowUpdate(nil, p.Len())
|
|
5726
|
-
|
|
5727
5819
|
p.CloseWithError(err)
|
|
5728
5820
|
}
|
|
5729
5821
|
if e, ok := err.(http2StreamError); ok {
|
|
@@ -5777,7 +5869,12 @@ func (sc *http2serverConn) processSetting(s http2Setting) error {
|
|
|
5777
5869
|
}
|
|
5778
5870
|
switch s.ID {
|
|
5779
5871
|
case http2SettingHeaderTableSize:
|
|
5780
|
-
|
|
5872
|
+
// Applied by startFrameWrite; see comment there.
|
|
5873
|
+
if !sc.pendingEncoderTableSize || s.Val < sc.encoderTableSizeMin {
|
|
5874
|
+
sc.encoderTableSizeMin = s.Val
|
|
5875
|
+
}
|
|
5876
|
+
sc.encoderTableSize = s.Val
|
|
5877
|
+
sc.pendingEncoderTableSize = true
|
|
5781
5878
|
case http2SettingEnablePush:
|
|
5782
5879
|
sc.pushEnabled = s.Val != 0
|
|
5783
5880
|
case http2SettingMaxConcurrentStreams:
|
|
@@ -5804,28 +5901,14 @@ func (sc *http2serverConn) processSetting(s http2Setting) error {
|
|
|
5804
5901
|
|
|
5805
5902
|
func (sc *http2serverConn) processSettingInitialWindowSize(val uint32) error {
|
|
5806
5903
|
sc.serveG.check()
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
// old value."
|
|
5816
|
-
old := sc.initialStreamSendWindowSize
|
|
5817
|
-
sc.initialStreamSendWindowSize = int32(val)
|
|
5818
|
-
growth := int32(val) - old // may be negative
|
|
5819
|
-
for _, st := range sc.streams {
|
|
5820
|
-
if !st.flow.add(growth) {
|
|
5821
|
-
// 6.9.2 Initial Flow Control Window Size
|
|
5822
|
-
// "An endpoint MUST treat a change to
|
|
5823
|
-
// SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
|
|
5824
|
-
// control window to exceed the maximum size as a
|
|
5825
|
-
// connection error (Section 5.4.1) of type
|
|
5826
|
-
// FLOW_CONTROL_ERROR."
|
|
5827
|
-
return sc.countError("setting_win_size", http2ConnectionError(http2ErrCodeFlowControl))
|
|
5828
|
-
}
|
|
5904
|
+
if !sc.flow.changeInitialWindowSize(int64(val)) {
|
|
5905
|
+
// 6.9.2 Initial Flow Control Window Size
|
|
5906
|
+
// "An endpoint MUST treat a change to
|
|
5907
|
+
// SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
|
|
5908
|
+
// control window to exceed the maximum size as a
|
|
5909
|
+
// connection error (Section 5.4.1) of type
|
|
5910
|
+
// FLOW_CONTROL_ERROR."
|
|
5911
|
+
return sc.countError("setting_win_size", http2ConnectionError(http2ErrCodeFlowControl))
|
|
5829
5912
|
}
|
|
5830
5913
|
return nil
|
|
5831
5914
|
}
|
|
@@ -6078,7 +6161,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
|
|
|
6078
6161
|
if st.reqTrailer != nil {
|
|
6079
6162
|
st.trailer = make(Header)
|
|
6080
6163
|
}
|
|
6081
|
-
st.body =
|
|
6164
|
+
st.body = st.reqBody.pipe // may be nil
|
|
6082
6165
|
st.declBodyBytes = req.ContentLength
|
|
6083
6166
|
|
|
6084
6167
|
handler := sc.handler.ServeHTTP
|
|
@@ -6101,7 +6184,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
|
|
|
6101
6184
|
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
|
|
6102
6185
|
}
|
|
6103
6186
|
|
|
6104
|
-
return sc.scheduleHandler(
|
|
6187
|
+
return sc.scheduleHandler(st, rw, req, handler)
|
|
6105
6188
|
}
|
|
6106
6189
|
|
|
6107
6190
|
func (sc *http2serverConn) upgradeRequest(req *Request) {
|
|
@@ -6193,7 +6276,6 @@ func (sc *http2serverConn) newStream(id, pusherID uint32, state http2streamState
|
|
|
6193
6276
|
}
|
|
6194
6277
|
st.cw.Init()
|
|
6195
6278
|
st.flow.conn = &sc.flow // link to conn-level counter
|
|
6196
|
-
st.flow.add(sc.initialStreamSendWindowSize)
|
|
6197
6279
|
st.inflow.init(sc.initialStreamRecvWindowSize)
|
|
6198
6280
|
if sc.hs.WriteTimeout > 0 {
|
|
6199
6281
|
st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
|
|
@@ -6275,7 +6357,7 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead
|
|
|
6275
6357
|
} else {
|
|
6276
6358
|
req.ContentLength = -1
|
|
6277
6359
|
}
|
|
6278
|
-
|
|
6360
|
+
st.reqBody.pipe = &http2pipe{
|
|
6279
6361
|
b: &http2dataBuffer{expected: req.ContentLength},
|
|
6280
6362
|
}
|
|
6281
6363
|
}
|
|
@@ -6295,7 +6377,7 @@ func (sc *http2serverConn) newWriterAndRequestNoBody(st *http2stream, rp httpcom
|
|
|
6295
6377
|
return nil, nil, sc.countError(res.InvalidReason, http2streamError(st.id, http2ErrCodeProtocol))
|
|
6296
6378
|
}
|
|
6297
6379
|
|
|
6298
|
-
|
|
6380
|
+
st.reqBody = &http2requestBody{
|
|
6299
6381
|
conn: sc,
|
|
6300
6382
|
stream: st,
|
|
6301
6383
|
needsContinue: res.NeedsContinue,
|
|
@@ -6311,7 +6393,7 @@ func (sc *http2serverConn) newWriterAndRequestNoBody(st *http2stream, rp httpcom
|
|
|
6311
6393
|
ProtoMinor: 0,
|
|
6312
6394
|
TLS: tlsState,
|
|
6313
6395
|
Host: rp.Authority,
|
|
6314
|
-
Body:
|
|
6396
|
+
Body: st.reqBody,
|
|
6315
6397
|
Trailer: res.Trailer,
|
|
6316
6398
|
}).WithContext(st.ctx)
|
|
6317
6399
|
rw := sc.newResponseWriter(st, req)
|
|
@@ -6335,11 +6417,12 @@ type http2unstartedHandler struct {
|
|
|
6335
6417
|
rw *http2responseWriter
|
|
6336
6418
|
req *Request
|
|
6337
6419
|
handler func(ResponseWriter, *Request)
|
|
6420
|
+
body *http2pipe
|
|
6338
6421
|
}
|
|
6339
6422
|
|
|
6340
6423
|
// scheduleHandler starts a handler goroutine,
|
|
6341
6424
|
// or schedules one to start as soon as an existing handler finishes.
|
|
6342
|
-
func (sc *http2serverConn) scheduleHandler(
|
|
6425
|
+
func (sc *http2serverConn) scheduleHandler(st *http2stream, rw *http2responseWriter, req *Request, handler func(ResponseWriter, *Request)) error {
|
|
6343
6426
|
sc.serveG.check()
|
|
6344
6427
|
maxHandlers := sc.advMaxStreams
|
|
6345
6428
|
if sc.curHandlers < maxHandlers {
|
|
@@ -6351,10 +6434,11 @@ func (sc *http2serverConn) scheduleHandler(streamID uint32, rw *http2responseWri
|
|
|
6351
6434
|
return sc.countError("too_many_early_resets", http2ConnectionError(http2ErrCodeEnhanceYourCalm))
|
|
6352
6435
|
}
|
|
6353
6436
|
sc.unstartedHandlers = append(sc.unstartedHandlers, http2unstartedHandler{
|
|
6354
|
-
streamID:
|
|
6437
|
+
streamID: st.id,
|
|
6355
6438
|
rw: rw,
|
|
6356
6439
|
req: req,
|
|
6357
6440
|
handler: handler,
|
|
6441
|
+
body: st.body,
|
|
6358
6442
|
})
|
|
6359
6443
|
return nil
|
|
6360
6444
|
}
|
|
@@ -6368,6 +6452,10 @@ func (sc *http2serverConn) handlerDone() {
|
|
|
6368
6452
|
u := sc.unstartedHandlers[i]
|
|
6369
6453
|
if sc.streams[u.streamID] == nil {
|
|
6370
6454
|
// This stream was reset before its goroutine had a chance to start.
|
|
6455
|
+
if u.body != nil {
|
|
6456
|
+
u.body.BreakWithError(http2errClosedBody)
|
|
6457
|
+
sc.sendWindowUpdate(nil, u.body.Len())
|
|
6458
|
+
}
|
|
6371
6459
|
continue
|
|
6372
6460
|
}
|
|
6373
6461
|
if sc.curHandlers >= maxHandlers {
|
|
@@ -6389,6 +6477,12 @@ func (sc *http2serverConn) runHandler(rw *http2responseWriter, req *Request, han
|
|
|
6389
6477
|
didPanic := true
|
|
6390
6478
|
defer func() {
|
|
6391
6479
|
rw.rws.stream.cancelCtx()
|
|
6480
|
+
if b := rw.rws.stream.reqBody; b != nil {
|
|
6481
|
+
// Closing the body refunds flow control credit for any unconsumed data.
|
|
6482
|
+
// (reqBody is nil for Upgrade: h2c requests, but those do not use flow
|
|
6483
|
+
// control for the request body.)
|
|
6484
|
+
b.Close()
|
|
6485
|
+
}
|
|
6392
6486
|
if req.MultipartForm != nil {
|
|
6393
6487
|
req.MultipartForm.RemoveAll()
|
|
6394
6488
|
}
|
|
@@ -6487,7 +6581,7 @@ func (sc *http2serverConn) noteBodyReadFromHandler(st *http2stream, n int, err e
|
|
|
6487
6581
|
func (sc *http2serverConn) noteBodyRead(st *http2stream, n int) {
|
|
6488
6582
|
sc.serveG.check()
|
|
6489
6583
|
sc.sendWindowUpdate(nil, n) // conn-level
|
|
6490
|
-
if st.state != http2stateHalfClosedRemote && st.state != http2stateClosed {
|
|
6584
|
+
if st != nil && st.state != http2stateHalfClosedRemote && st.state != http2stateClosed {
|
|
6491
6585
|
// Don't send this WINDOW_UPDATE if the stream is closed
|
|
6492
6586
|
// remotely.
|
|
6493
6587
|
sc.sendWindowUpdate(st, n)
|
|
@@ -6535,6 +6629,9 @@ func (b *http2requestBody) Close() error {
|
|
|
6535
6629
|
b.closeOnce.Do(func() {
|
|
6536
6630
|
if b.pipe != nil {
|
|
6537
6631
|
b.pipe.BreakWithError(http2errClosedBody)
|
|
6632
|
+
if unread := b.pipe.Len(); unread > 0 {
|
|
6633
|
+
b.conn.noteBodyReadFromHandler(nil, unread, http2errClosedBody)
|
|
6634
|
+
}
|
|
6538
6635
|
}
|
|
6539
6636
|
})
|
|
6540
6637
|
return nil
|
|
@@ -6552,9 +6649,6 @@ func (b *http2requestBody) Read(p []byte) (n int, err error) {
|
|
|
6552
6649
|
if err == io.EOF {
|
|
6553
6650
|
b.sawEOF = true
|
|
6554
6651
|
}
|
|
6555
|
-
if b.conn == nil {
|
|
6556
|
-
return
|
|
6557
|
-
}
|
|
6558
6652
|
b.conn.noteBodyReadFromHandler(b.stream, n, err)
|
|
6559
6653
|
return
|
|
6560
6654
|
}
|
|
@@ -7615,11 +7709,11 @@ type http2ClientConn struct {
|
|
|
7615
7709
|
idleTimeout time.Duration // or 0 for never
|
|
7616
7710
|
idleTimer *time.Timer
|
|
7617
7711
|
|
|
7618
|
-
mu sync.Mutex
|
|
7619
|
-
cond *sync.Cond
|
|
7620
|
-
flow
|
|
7621
|
-
inflow http2inflow
|
|
7622
|
-
doNotReuse bool
|
|
7712
|
+
mu sync.Mutex // guards following
|
|
7713
|
+
cond *sync.Cond // hold mu; broadcast on flow/closed changes
|
|
7714
|
+
flow http2connOutflow // our conn-level flow control quota (cs.outflow is per stream)
|
|
7715
|
+
inflow http2inflow // peer's conn-level flow control
|
|
7716
|
+
doNotReuse bool // whether conn is marked to not be reused for any future requests
|
|
7623
7717
|
closing bool
|
|
7624
7718
|
closed bool
|
|
7625
7719
|
closedOnIdle bool // true if conn was closed for idleness
|
|
@@ -7641,7 +7735,6 @@ type http2ClientConn struct {
|
|
|
7641
7735
|
maxConcurrentStreams uint32
|
|
7642
7736
|
peerMaxHeaderListSize uint64
|
|
7643
7737
|
peerMaxHeaderTableSize uint32
|
|
7644
|
-
initialWindowSize uint32
|
|
7645
7738
|
initialStreamRecvWindowSize int32
|
|
7646
7739
|
readIdleTimeout time.Duration
|
|
7647
7740
|
pingTimeout time.Duration
|
|
@@ -8087,7 +8180,6 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool, internalState
|
|
|
8087
8180
|
readerDone: make(chan struct{}),
|
|
8088
8181
|
nextStreamID: 1,
|
|
8089
8182
|
maxFrameSize: 16 << 10, // spec default
|
|
8090
|
-
initialWindowSize: 65535, // spec default
|
|
8091
8183
|
initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream,
|
|
8092
8184
|
maxConcurrentStreams: http2initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings.
|
|
8093
8185
|
strictMaxConcurrentStreams: conf.StrictMaxConcurrentRequests,
|
|
@@ -8112,7 +8204,7 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool, internalState
|
|
|
8112
8204
|
}
|
|
8113
8205
|
|
|
8114
8206
|
cc.cond = sync.NewCond(&cc.mu)
|
|
8115
|
-
cc.flow.
|
|
8207
|
+
cc.flow.init()
|
|
8116
8208
|
|
|
8117
8209
|
// TODO: adjust this writer size to account for frame size +
|
|
8118
8210
|
// MTU + crypto/tls record padding.
|
|
@@ -8529,6 +8621,33 @@ func (cc *http2ClientConn) sendGoAway() error {
|
|
|
8529
8621
|
return nil
|
|
8530
8622
|
}
|
|
8531
8623
|
|
|
8624
|
+
func (cc *http2ClientConn) goAwayAndClose(code http2ErrCode) {
|
|
8625
|
+
cc.mu.Lock()
|
|
8626
|
+
closed := cc.closed
|
|
8627
|
+
cc.closing = true
|
|
8628
|
+
cc.closed = true
|
|
8629
|
+
cc.mu.Unlock()
|
|
8630
|
+
if closed {
|
|
8631
|
+
return
|
|
8632
|
+
}
|
|
8633
|
+
if f := cc.fr.countError; f != nil {
|
|
8634
|
+
f(fmt.Sprintf("conn_close_error_%s", code.stringToken()))
|
|
8635
|
+
}
|
|
8636
|
+
done := make(chan struct{})
|
|
8637
|
+
go func() {
|
|
8638
|
+
defer close(done)
|
|
8639
|
+
cc.wmu.Lock()
|
|
8640
|
+
cc.fr.WriteGoAway(0, code, nil)
|
|
8641
|
+
cc.bw.Flush()
|
|
8642
|
+
cc.wmu.Unlock()
|
|
8643
|
+
}()
|
|
8644
|
+
select {
|
|
8645
|
+
case <-done:
|
|
8646
|
+
case <-time.After(250 * time.Millisecond):
|
|
8647
|
+
}
|
|
8648
|
+
cc.closeForError(fmt.Errorf("http2: closing connection with %v", code))
|
|
8649
|
+
}
|
|
8650
|
+
|
|
8532
8651
|
// closes the client connection immediately. In-flight requests are interrupted.
|
|
8533
8652
|
// err is sent to streams.
|
|
8534
8653
|
func (cc *http2ClientConn) closeForError(err error) {
|
|
@@ -8975,7 +9094,9 @@ func (cs *http2clientStream) cleanupWriteRequest(err error) {
|
|
|
8975
9094
|
}
|
|
8976
9095
|
if err != nil {
|
|
8977
9096
|
cs.abortStream(err) // possibly redundant, but harmless
|
|
8978
|
-
if
|
|
9097
|
+
if ce, ok := err.(http2ConnectionError); ok {
|
|
9098
|
+
cc.goAwayAndClose(http2ErrCode(ce))
|
|
9099
|
+
} else if cs.sentHeaders {
|
|
8979
9100
|
if se, ok := err.(http2StreamError); ok {
|
|
8980
9101
|
if se.Cause != http2errFromPeer {
|
|
8981
9102
|
cc.writeStreamReset(cs.ID, se.Code, false, err)
|
|
@@ -9305,8 +9426,12 @@ func (cs *http2clientStream) awaitFlowControl(maxBytes int) (taken int32, err er
|
|
|
9305
9426
|
return 0, http2errRequestCanceled
|
|
9306
9427
|
default:
|
|
9307
9428
|
}
|
|
9308
|
-
|
|
9309
|
-
|
|
9429
|
+
avail, ok := cs.flow.available()
|
|
9430
|
+
if !ok {
|
|
9431
|
+
return 0, http2ConnectionError(http2ErrCodeFlowControl)
|
|
9432
|
+
}
|
|
9433
|
+
if avail > 0 {
|
|
9434
|
+
take := avail
|
|
9310
9435
|
if int(take) > maxBytes {
|
|
9311
9436
|
|
|
9312
9437
|
take = int32(maxBytes) // can't truncate int; take is int32
|
|
@@ -9367,8 +9492,7 @@ type http2resAndError struct {
|
|
|
9367
9492
|
|
|
9368
9493
|
// requires cc.mu be held.
|
|
9369
9494
|
func (cc *http2ClientConn) addStreamLocked(cs *http2clientStream) {
|
|
9370
|
-
cs.flow.
|
|
9371
|
-
cs.flow.setConnFlow(&cc.flow)
|
|
9495
|
+
cs.flow.conn = &cc.flow
|
|
9372
9496
|
cs.inflow.init(cc.initialStreamRecvWindowSize)
|
|
9373
9497
|
cs.ID = cc.nextStreamID
|
|
9374
9498
|
cc.nextStreamID += 2
|
|
@@ -9765,18 +9889,42 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http
|
|
|
9765
9889
|
return nil, nil
|
|
9766
9890
|
}
|
|
9767
9891
|
|
|
9892
|
+
// Delete various headers that might mess up framing for HTTP/1. This is
|
|
9893
|
+
// not a problem for HTTP/2, but someone might use HTTP/2 transport as a
|
|
9894
|
+
// reverse proxy which forwards the response to an HTTP/1 client. Our
|
|
9895
|
+
// HTTP/1 client transport will properly reject improper headers such as
|
|
9896
|
+
// multiple conflicting Content-Length headers, but other implementations
|
|
9897
|
+
// might not.
|
|
9898
|
+
// TODO: just reject such responses? We deleted them for compatibility
|
|
9899
|
+
// since this was done in a security fix (go.dev/issue/81115). However,
|
|
9900
|
+
// rejecting them seems entirely reasonable and relatively safe.
|
|
9901
|
+
|
|
9902
|
+
// Connection-specific header fields must not appear in an HTTP/2 message,
|
|
9903
|
+
// and any message containing them is malformed. RFC 9113, Section 8.2.2.
|
|
9904
|
+
for _, k := range http2connHeaders {
|
|
9905
|
+
delete(res.Header, k)
|
|
9906
|
+
}
|
|
9768
9907
|
res.ContentLength = -1
|
|
9769
|
-
if clens := res.Header["Content-Length"];
|
|
9770
|
-
|
|
9771
|
-
|
|
9908
|
+
if clens, ok := res.Header["Content-Length"]; ok {
|
|
9909
|
+
// Repeated Content-Length values may be collapsed into one only if
|
|
9910
|
+
// they are identical per RFC 9110 Section 8.6.
|
|
9911
|
+
// No need to trim whitespace, HTTP/2 header values must not have
|
|
9912
|
+
// extraneous whitespace per RFC 9113 Section 8.2.1.
|
|
9913
|
+
// Non-canonical headers are already rejected by our framer at this
|
|
9914
|
+
// point.
|
|
9915
|
+
conflicting := slices.ContainsFunc(clens[1:], func(clen string) bool {
|
|
9916
|
+
return clen != clens[0]
|
|
9917
|
+
})
|
|
9918
|
+
cl, err := strconv.ParseUint(clens[0], 10, 63)
|
|
9919
|
+
if conflicting || err != nil {
|
|
9920
|
+
delete(res.Header, "Content-Length")
|
|
9772
9921
|
} else {
|
|
9773
|
-
|
|
9774
|
-
|
|
9922
|
+
res.Header["Content-Length"] = clens[:1]
|
|
9923
|
+
res.ContentLength = int64(cl)
|
|
9775
9924
|
}
|
|
9776
|
-
}
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
} else if f.StreamEnded() && !cs.isHead {
|
|
9925
|
+
}
|
|
9926
|
+
|
|
9927
|
+
if res.ContentLength < 0 && f.StreamEnded() && !cs.isHead {
|
|
9780
9928
|
res.ContentLength = 0
|
|
9781
9929
|
}
|
|
9782
9930
|
|
|
@@ -10071,6 +10219,11 @@ func (rl *http2clientConnReadLoop) endStreamError(cs *http2clientStream, err err
|
|
|
10071
10219
|
cs.abortStream(err)
|
|
10072
10220
|
}
|
|
10073
10221
|
|
|
10222
|
+
func (rl *http2clientConnReadLoop) endStreamErrorLocked(cs *http2clientStream, err error) {
|
|
10223
|
+
cs.readAborted = true
|
|
10224
|
+
cs.abortStreamLocked(err)
|
|
10225
|
+
}
|
|
10226
|
+
|
|
10074
10227
|
// Constants passed to streamByID for documentation purposes.
|
|
10075
10228
|
const (
|
|
10076
10229
|
http2headerOrDataFrame = true
|
|
@@ -10082,6 +10235,10 @@ const (
|
|
|
10082
10235
|
func (rl *http2clientConnReadLoop) streamByID(id uint32, headerOrData bool) *http2clientStream {
|
|
10083
10236
|
rl.cc.mu.Lock()
|
|
10084
10237
|
defer rl.cc.mu.Unlock()
|
|
10238
|
+
return rl.streamByIDLocked(id, headerOrData)
|
|
10239
|
+
}
|
|
10240
|
+
|
|
10241
|
+
func (rl *http2clientConnReadLoop) streamByIDLocked(id uint32, headerOrData bool) *http2clientStream {
|
|
10085
10242
|
if headerOrData {
|
|
10086
10243
|
// Work around an unfortunate gRPC behavior.
|
|
10087
10244
|
// See comment on ClientConn.rstStreamPingsBlocked for details.
|
|
@@ -10164,24 +10321,10 @@ func (rl *http2clientConnReadLoop) processSettingsNoWrite(f *http2SettingsFrame)
|
|
|
10164
10321
|
case http2SettingMaxHeaderListSize:
|
|
10165
10322
|
cc.peerMaxHeaderListSize = uint64(s.Val)
|
|
10166
10323
|
case http2SettingInitialWindowSize:
|
|
10167
|
-
|
|
10168
|
-
// window size of 2^31-1 MUST be treated as a
|
|
10169
|
-
// connection error (Section 5.4.1) of type
|
|
10170
|
-
// FLOW_CONTROL_ERROR.
|
|
10171
|
-
if s.Val > math.MaxInt32 {
|
|
10324
|
+
if !cc.flow.changeInitialWindowSize(int64(s.Val)) {
|
|
10172
10325
|
return http2ConnectionError(http2ErrCodeFlowControl)
|
|
10173
10326
|
}
|
|
10174
|
-
|
|
10175
|
-
// Adjust flow control of currently-open
|
|
10176
|
-
// frames by the difference of the old initial
|
|
10177
|
-
// window size and this one.
|
|
10178
|
-
delta := int32(s.Val) - int32(cc.initialWindowSize)
|
|
10179
|
-
for _, cs := range cc.streams {
|
|
10180
|
-
cs.flow.add(delta)
|
|
10181
|
-
}
|
|
10182
10327
|
cc.cond.Broadcast()
|
|
10183
|
-
|
|
10184
|
-
cc.initialWindowSize = s.Val
|
|
10185
10328
|
case http2SettingHeaderTableSize:
|
|
10186
10329
|
cc.henc.SetMaxDynamicTableSize(s.Val)
|
|
10187
10330
|
cc.peerMaxHeaderTableSize = s.Val
|
|
@@ -10223,29 +10366,30 @@ func (rl *http2clientConnReadLoop) processSettingsNoWrite(f *http2SettingsFrame)
|
|
|
10223
10366
|
|
|
10224
10367
|
func (rl *http2clientConnReadLoop) processWindowUpdate(f *http2WindowUpdateFrame) error {
|
|
10225
10368
|
cc := rl.cc
|
|
10226
|
-
cs := rl.streamByID(f.StreamID, http2notHeaderOrDataFrame)
|
|
10227
|
-
if f.StreamID != 0 && cs == nil {
|
|
10228
|
-
return nil
|
|
10229
|
-
}
|
|
10230
|
-
|
|
10231
10369
|
cc.mu.Lock()
|
|
10232
10370
|
defer cc.mu.Unlock()
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
}
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10371
|
+
if f.StreamID == 0 {
|
|
10372
|
+
if !cc.flow.add(int32(f.Increment)) {
|
|
10373
|
+
return http2ConnectionError(http2ErrCodeFlowControl)
|
|
10374
|
+
}
|
|
10375
|
+
} else {
|
|
10376
|
+
cs := rl.streamByIDLocked(f.StreamID, http2notHeaderOrDataFrame)
|
|
10377
|
+
if cs == nil {
|
|
10378
|
+
return nil
|
|
10379
|
+
}
|
|
10380
|
+
if !cs.flow.add(int32(f.Increment)) {
|
|
10381
|
+
if cs.flow.conn.flowErr {
|
|
10382
|
+
// This is a lazily-detected connection-level flow control error.
|
|
10383
|
+
return http2ConnectionError(http2ErrCodeFlowControl)
|
|
10384
|
+
}
|
|
10385
|
+
// For stream, the sender sends RST_STREAM with
|
|
10386
|
+
// an error code of FLOW_CONTROL_ERROR.
|
|
10387
|
+
rl.endStreamErrorLocked(cs, http2StreamError{
|
|
10242
10388
|
StreamID: f.StreamID,
|
|
10243
10389
|
Code: http2ErrCodeFlowControl,
|
|
10244
10390
|
})
|
|
10245
10391
|
return nil
|
|
10246
10392
|
}
|
|
10247
|
-
|
|
10248
|
-
return http2ConnectionError(http2ErrCodeFlowControl)
|
|
10249
10393
|
}
|
|
10250
10394
|
cc.cond.Broadcast()
|
|
10251
10395
|
return nil
|
|
@@ -11232,10 +11376,11 @@ func (wr http2FrameWriteRequest) Consume(n int32) (http2FrameWriteRequest, http2
|
|
|
11232
11376
|
}
|
|
11233
11377
|
|
|
11234
11378
|
// Might need to split after applying limits.
|
|
11235
|
-
|
|
11236
|
-
if
|
|
11237
|
-
|
|
11379
|
+
avail, ok := wr.stream.flow.available()
|
|
11380
|
+
if !ok {
|
|
11381
|
+
return empty, empty, 0
|
|
11238
11382
|
}
|
|
11383
|
+
allowed := min(n, avail)
|
|
11239
11384
|
if wr.stream.sc.maxFrameSize < allowed {
|
|
11240
11385
|
allowed = wr.stream.sc.maxFrameSize
|
|
11241
11386
|
}
|