1
2
3
4
5 package quic
6
7 import (
8 "context"
9 )
10
11
12
13
14
15
16
17
18
19 type localStreamLimits struct {
20 gate gate
21 max int64
22 opened int64
23 }
24
25 func (lim *localStreamLimits) init() {
26 lim.gate = newGate()
27 }
28
29
30 func (lim *localStreamLimits) open(ctx context.Context, c *Conn) (num int64, err error) {
31
32 if err := lim.gate.waitAndLock(ctx); err != nil {
33 return 0, err
34 }
35 defer lim.unlock()
36 if lim.opened < 0 {
37 return 0, errConnClosed
38 }
39 num = lim.opened
40 lim.opened++
41 return num, nil
42 }
43
44
45
46
47 func (lim *localStreamLimits) unlock() {
48 lim.gate.unlock(lim.opened < lim.max)
49 }
50
51
52 func (lim *localStreamLimits) wasOpened(num int64) bool {
53 lim.gate.lock()
54 defer lim.unlock()
55 return num < lim.opened
56 }
57
58
59 func (lim *localStreamLimits) connHasClosed() {
60 lim.gate.lock()
61 lim.opened = -1
62 lim.unlock()
63 }
64
65
66 func (lim *localStreamLimits) setMax(maxStreams int64) {
67 lim.gate.lock()
68 lim.max = max(lim.max, maxStreams)
69 lim.unlock()
70 }
71
72
73 type remoteStreamLimits struct {
74 max int64
75 opened int64
76 closed int64
77 maxOpen int64
78 sendMax sentVal
79 }
80
81 func (lim *remoteStreamLimits) init(maxOpen int64) {
82 lim.maxOpen = maxOpen
83 lim.max = min(maxOpen, implicitStreamLimit)
84 lim.opened = 0
85 }
86
87
88 func (lim *remoteStreamLimits) open(id streamID) error {
89 num := id.num()
90 if num >= lim.max {
91 return localTransportError{
92 code: errStreamLimit,
93 reason: "stream limit exceeded",
94 }
95 }
96 if num >= lim.opened {
97 lim.opened = num + 1
98 lim.maybeUpdateMax()
99 }
100 return nil
101 }
102
103
104 func (lim *remoteStreamLimits) close() {
105 lim.closed++
106 lim.maybeUpdateMax()
107 }
108
109
110 func (lim *remoteStreamLimits) maybeUpdateMax() {
111 newMax := min(
112
113 lim.closed+lim.maxOpen,
114
115 lim.opened+implicitStreamLimit,
116 )
117 avail := lim.max - lim.opened
118 if newMax > lim.max && (avail < 8 || newMax-lim.max >= 2*avail) {
119
120
121 lim.max = newMax
122 lim.sendMax.setUnsent()
123 }
124 }
125
126
127
128
129
130 func (lim *remoteStreamLimits) appendFrame(w *packetWriter, typ streamType, pnum packetNumber, pto bool) bool {
131 if lim.sendMax.shouldSendPTO(pto) {
132 if !w.appendMaxStreamsFrame(typ, lim.max) {
133 return false
134 }
135 lim.sendMax.setSent(pnum)
136 }
137 return true
138 }
139
View as plain text