@@ -14,8 +14,16 @@ import (
1414)
1515
1616type streamsState struct {
17- queue queue [* Stream ] // new, peer-created streams
18- streams map [streamID ]* Stream
17+ queue queue [* Stream ] // new, peer-created streams
18+
19+ // All peer-created streams.
20+ //
21+ // Implicitly created streams are included as an empty entry in the map.
22+ // (For example, if we receive a frame for stream 4, we implicitly create stream 0 and
23+ // insert an empty entry for it to the map.)
24+ //
25+ // The map value is maybeStream rather than *Stream as a reminder that values can be nil.
26+ streams map [streamID ]maybeStream
1927
2028 // Limits on the number of streams, indexed by streamType.
2129 localLimit [streamTypeCount ]localStreamLimits
@@ -37,8 +45,13 @@ type streamsState struct {
3745 queueData streamRing // streams with only flow-controlled frames
3846}
3947
48+ // maybeStream is a possibly nil *Stream. See streamsState.streams.
49+ type maybeStream struct {
50+ s * Stream
51+ }
52+
4053func (c * Conn ) streamsInit () {
41- c .streams .streams = make (map [streamID ]* Stream )
54+ c .streams .streams = make (map [streamID ]maybeStream )
4255 c .streams .queue = newQueue [* Stream ]()
4356 c .streams .localLimit [bidiStream ].init ()
4457 c .streams .localLimit [uniStream ].init ()
@@ -52,8 +65,8 @@ func (c *Conn) streamsCleanup() {
5265 c .streams .localLimit [bidiStream ].connHasClosed ()
5366 c .streams .localLimit [uniStream ].connHasClosed ()
5467 for _ , s := range c .streams .streams {
55- if s != nil {
56- s .connHasClosed ()
68+ if s . s != nil {
69+ s .s . connHasClosed ()
5770 }
5871 }
5972}
@@ -97,7 +110,7 @@ func (c *Conn) newLocalStream(ctx context.Context, styp streamType) (*Stream, er
97110
98111 // Modify c.streams on the conn's loop.
99112 if err := c .runOnLoop (ctx , func (now time.Time , c * Conn ) {
100- c .streams .streams [s .id ] = s
113+ c .streams .streams [s .id ] = maybeStream { s }
101114 }); err != nil {
102115 return nil , err
103116 }
@@ -119,7 +132,7 @@ const (
119132// streamForID returns the stream with the given id.
120133// If the stream does not exist, it returns nil.
121134func (c * Conn ) streamForID (id streamID ) * Stream {
122- return c .streams .streams [id ]
135+ return c .streams .streams [id ]. s
123136}
124137
125138// streamForFrame returns the stream with the given id.
@@ -144,9 +157,9 @@ func (c *Conn) streamForFrame(now time.Time, id streamID, ftype streamFrameType)
144157 }
145158 }
146159
147- s , isOpen := c .streams .streams [id ]
148- if s != nil {
149- return s
160+ ms , isOpen := c .streams .streams [id ]
161+ if ms . s != nil {
162+ return ms . s
150163 }
151164
152165 num := id .num ()
@@ -183,10 +196,10 @@ func (c *Conn) streamForFrame(now time.Time, id streamID, ftype streamFrameType)
183196 // with the same initiator and type and a lower number.
184197 // Add a nil entry to the streams map for each implicitly created stream.
185198 for n := newStreamID (id .initiator (), id .streamType (), prevOpened ); n < id ; n += 4 {
186- c .streams .streams [n ] = nil
199+ c .streams .streams [n ] = maybeStream {}
187200 }
188201
189- s = newStream (c , id )
202+ s : = newStream (c , id )
190203 s .inmaxbuf = c .config .maxStreamReadBufferSize ()
191204 s .inwin = c .config .maxStreamReadBufferSize ()
192205 if id .streamType () == bidiStream {
@@ -196,7 +209,7 @@ func (c *Conn) streamForFrame(now time.Time, id streamID, ftype streamFrameType)
196209 s .inUnlock ()
197210 s .outUnlock ()
198211
199- c .streams .streams [id ] = s
212+ c .streams .streams [id ] = maybeStream { s }
200213 c .streams .queue .put (s )
201214 return s
202215}
@@ -400,7 +413,11 @@ func (c *Conn) appendStreamFramesPTO(w *packetWriter, pnum packetNumber) bool {
400413 c .streams .sendMu .Lock ()
401414 defer c .streams .sendMu .Unlock ()
402415 const pto = true
403- for _ , s := range c .streams .streams {
416+ for _ , ms := range c .streams .streams {
417+ s := ms .s
418+ if s == nil {
419+ continue
420+ }
404421 const pto = true
405422 s .ingate .lock ()
406423 inOK := s .appendInFramesLocked (w , pnum , pto )
0 commit comments