golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/stream.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build go1.21
     6  
     7  package quic
     8  
     9  import (
    10  	"context"
    11  	"errors"
    12  	"fmt"
    13  	"io"
    14  	"math"
    15  )
    16  
    17  // A Stream is an ordered byte stream.
    18  //
    19  // Streams may be bidirectional, read-only, or write-only.
    20  // Methods inappropriate for a stream's direction
    21  // (for example, [Write] to a read-only stream)
    22  // return errors.
    23  //
    24  // It is not safe to perform concurrent reads from or writes to a stream.
    25  // It is safe, however, to read and write at the same time.
    26  //
    27  // Reads and writes are buffered.
    28  // It is generally not necessary to wrap a stream in a [bufio.ReadWriter]
    29  // or otherwise apply additional buffering.
    30  //
    31  // To cancel reads or writes, use the [SetReadContext] and [SetWriteContext] methods.
    32  type Stream struct {
    33  	id   streamID
    34  	conn *Conn
    35  
    36  	// Contexts used for read/write operations.
    37  	// Intentionally not mutex-guarded, to allow the race detector to catch concurrent access.
    38  	inctx  context.Context
    39  	outctx context.Context
    40  
    41  	// ingate's lock guards receive-related state.
    42  	//
    43  	// The gate condition is set if a read from the stream will not block,
    44  	// either because the stream has available data or because the read will fail.
    45  	ingate      gate
    46  	in          pipe            // received data
    47  	inwin       int64           // last MAX_STREAM_DATA sent to the peer
    48  	insendmax   sentVal         // set when we should send MAX_STREAM_DATA to the peer
    49  	inmaxbuf    int64           // maximum amount of data we will buffer
    50  	insize      int64           // stream final size; -1 before this is known
    51  	inset       rangeset[int64] // received ranges
    52  	inclosed    sentVal         // set by CloseRead
    53  	inresetcode int64           // RESET_STREAM code received from the peer; -1 if not reset
    54  
    55  	// outgate's lock guards send-related state.
    56  	//
    57  	// The gate condition is set if a write to the stream will not block,
    58  	// either because the stream has available flow control or because
    59  	// the write will fail.
    60  	outgate      gate
    61  	out          pipe            // buffered data to send
    62  	outflushed   int64           // offset of last flush call
    63  	outwin       int64           // maximum MAX_STREAM_DATA received from the peer
    64  	outmaxsent   int64           // maximum data offset we've sent to the peer
    65  	outmaxbuf    int64           // maximum amount of data we will buffer
    66  	outunsent    rangeset[int64] // ranges buffered but not yet sent (only flushed data)
    67  	outacked     rangeset[int64] // ranges sent and acknowledged
    68  	outopened    sentVal         // set if we should open the stream
    69  	outclosed    sentVal         // set by CloseWrite
    70  	outblocked   sentVal         // set when a write to the stream is blocked by flow control
    71  	outreset     sentVal         // set by Reset
    72  	outresetcode uint64          // reset code to send in RESET_STREAM
    73  	outdone      chan struct{}   // closed when all data sent
    74  
    75  	// Unsynchronized buffers, used for lock-free fast path.
    76  	inbuf     []byte // received data
    77  	inbufoff  int    // bytes of inbuf which have been consumed
    78  	outbuf    []byte // written data
    79  	outbufoff int    // bytes of outbuf which contain data to write
    80  
    81  	// Atomic stream state bits.
    82  	//
    83  	// These bits provide a fast way to coordinate between the
    84  	// send and receive sides of the stream, and the conn's loop.
    85  	//
    86  	// streamIn* bits must be set with ingate held.
    87  	// streamOut* bits must be set with outgate held.
    88  	// streamConn* bits are set by the conn's loop.
    89  	// streamQueue* bits must be set with streamsState.sendMu held.
    90  	state atomicBits[streamState]
    91  
    92  	prev, next *Stream // guarded by streamsState.sendMu
    93  }
    94  
    95  type streamState uint32
    96  
    97  const (
    98  	// streamInSendMeta is set when there are frames to send for the
    99  	// inbound side of the stream. For example, MAX_STREAM_DATA.
   100  	// Inbound frames are never flow-controlled.
   101  	streamInSendMeta = streamState(1 << iota)
   102  
   103  	// streamOutSendMeta is set when there are non-flow-controlled frames
   104  	// to send for the outbound side of the stream. For example, STREAM_DATA_BLOCKED.
   105  	// streamOutSendData is set when there are no non-flow-controlled outbound frames
   106  	// and the stream has data to send.
   107  	//
   108  	// At most one of streamOutSendMeta and streamOutSendData is set at any time.
   109  	streamOutSendMeta
   110  	streamOutSendData
   111  
   112  	// streamInDone and streamOutDone are set when the inbound or outbound
   113  	// sides of the stream are finished. When both are set, the stream
   114  	// can be removed from the Conn and forgotten.
   115  	streamInDone
   116  	streamOutDone
   117  
   118  	// streamConnRemoved is set when the stream has been removed from the conn.
   119  	streamConnRemoved
   120  
   121  	// streamQueueMeta and streamQueueData indicate which of the streamsState
   122  	// send queues the conn is currently on.
   123  	streamQueueMeta
   124  	streamQueueData
   125  )
   126  
   127  type streamQueue int
   128  
   129  const (
   130  	noQueue   = streamQueue(iota)
   131  	metaQueue // streamsState.queueMeta
   132  	dataQueue // streamsState.queueData
   133  )
   134  
   135  // streamResetByConnClose is assigned to Stream.inresetcode to indicate that a stream
   136  // was implicitly reset when the connection closed. It's out of the range of
   137  // possible reset codes the peer can send.
   138  const streamResetByConnClose = math.MaxInt64
   139  
   140  // wantQueue returns the send queue the stream should be on.
   141  func (s streamState) wantQueue() streamQueue {
   142  	switch {
   143  	case s&(streamInSendMeta|streamOutSendMeta) != 0:
   144  		return metaQueue
   145  	case s&(streamInDone|streamOutDone|streamConnRemoved) == streamInDone|streamOutDone:
   146  		return metaQueue
   147  	case s&streamOutSendData != 0:
   148  		// The stream has no non-flow-controlled frames to send,
   149  		// but does have data. Put it on the data queue, which is only
   150  		// processed when flow control is available.
   151  		return dataQueue
   152  	}
   153  	return noQueue
   154  }
   155  
   156  // inQueue returns the send queue the stream is currently on.
   157  func (s streamState) inQueue() streamQueue {
   158  	switch {
   159  	case s&streamQueueMeta != 0:
   160  		return metaQueue
   161  	case s&streamQueueData != 0:
   162  		return dataQueue
   163  	}
   164  	return noQueue
   165  }
   166  
   167  // newStream returns a new stream.
   168  //
   169  // The stream's ingate and outgate are locked.
   170  // (We create the stream with locked gates so after the caller
   171  // initializes the flow control window,
   172  // unlocking outgate will set the stream writability state.)
   173  func newStream(c *Conn, id streamID) *Stream {
   174  	s := &Stream{
   175  		conn:        c,
   176  		id:          id,
   177  		insize:      -1, // -1 indicates the stream size is unknown
   178  		inresetcode: -1, // -1 indicates no RESET_STREAM received
   179  		ingate:      newLockedGate(),
   180  		outgate:     newLockedGate(),
   181  		inctx:       context.Background(),
   182  		outctx:      context.Background(),
   183  	}
   184  	if !s.IsReadOnly() {
   185  		s.outdone = make(chan struct{})
   186  	}
   187  	return s
   188  }
   189  
   190  // SetReadContext sets the context used for reads from the stream.
   191  //
   192  // It is not safe to call SetReadContext concurrently.
   193  func (s *Stream) SetReadContext(ctx context.Context) {
   194  	s.inctx = ctx
   195  }
   196  
   197  // SetWriteContext sets the context used for writes to the stream.
   198  // The write context is also used by Close when waiting for writes to be
   199  // received by the peer.
   200  //
   201  // It is not safe to call SetWriteContext concurrently.
   202  func (s *Stream) SetWriteContext(ctx context.Context) {
   203  	s.outctx = ctx
   204  }
   205  
   206  // IsReadOnly reports whether the stream is read-only
   207  // (a unidirectional stream created by the peer).
   208  func (s *Stream) IsReadOnly() bool {
   209  	return s.id.streamType() == uniStream && s.id.initiator() != s.conn.side
   210  }
   211  
   212  // IsWriteOnly reports whether the stream is write-only
   213  // (a unidirectional stream created locally).
   214  func (s *Stream) IsWriteOnly() bool {
   215  	return s.id.streamType() == uniStream && s.id.initiator() == s.conn.side
   216  }
   217  
   218  // Read reads data from the stream.
   219  //
   220  // Read returns as soon as at least one byte of data is available.
   221  //
   222  // If the peer closes the stream cleanly, Read returns io.EOF after
   223  // returning all data sent by the peer.
   224  // If the peer aborts reads on the stream, Read returns
   225  // an error wrapping StreamResetCode.
   226  //
   227  // It is not safe to call Read concurrently.
   228  func (s *Stream) Read(b []byte) (n int, err error) {
   229  	if s.IsWriteOnly() {
   230  		return 0, errors.New("read from write-only stream")
   231  	}
   232  	if len(s.inbuf) > s.inbufoff {
   233  		// Fast path: If s.inbuf contains unread bytes, return them immediately
   234  		// without taking a lock.
   235  		n = copy(b, s.inbuf[s.inbufoff:])
   236  		s.inbufoff += n
   237  		return n, nil
   238  	}
   239  	if err := s.ingate.waitAndLock(s.inctx, s.conn.testHooks); err != nil {
   240  		return 0, err
   241  	}
   242  	if s.inbufoff > 0 {
   243  		// Discard bytes consumed by the fast path above.
   244  		s.in.discardBefore(s.in.start + int64(s.inbufoff))
   245  		s.inbufoff = 0
   246  		s.inbuf = nil
   247  	}
   248  	// bytesRead contains the number of bytes of connection-level flow control to return.
   249  	// We return flow control for bytes read by this Read call, as well as bytes moved
   250  	// to the fast-path read buffer (s.inbuf).
   251  	var bytesRead int64
   252  	defer func() {
   253  		s.inUnlock()
   254  		s.conn.handleStreamBytesReadOffLoop(bytesRead) // must be done with ingate unlocked
   255  	}()
   256  	if s.inresetcode != -1 {
   257  		return 0, fmt.Errorf("stream reset by peer: %w", StreamErrorCode(s.inresetcode))
   258  	}
   259  	if s.inclosed.isSet() {
   260  		return 0, errors.New("read from closed stream")
   261  	}
   262  	if s.insize == s.in.start {
   263  		return 0, io.EOF
   264  	}
   265  	// Getting here indicates the stream contains data to be read.
   266  	if len(s.inset) < 1 || s.inset[0].start != 0 || s.inset[0].end <= s.in.start {
   267  		panic("BUG: inconsistent input stream state")
   268  	}
   269  	if size := int(s.inset[0].end - s.in.start); size < len(b) {
   270  		b = b[:size]
   271  	}
   272  	bytesRead = int64(len(b))
   273  	start := s.in.start
   274  	end := start + int64(len(b))
   275  	s.in.copy(start, b)
   276  	s.in.discardBefore(end)
   277  	if end == s.insize {
   278  		// We have read up to the end of the stream.
   279  		// No need to update stream flow control.
   280  		return len(b), io.EOF
   281  	}
   282  	if len(s.inset) > 0 && s.inset[0].start <= s.in.start && s.inset[0].end > s.in.start {
   283  		// If we have more readable bytes available, put the next chunk of data
   284  		// in s.inbuf for lock-free reads.
   285  		s.inbuf = s.in.peek(s.inset[0].end - s.in.start)
   286  		bytesRead += int64(len(s.inbuf))
   287  	}
   288  	if s.insize == -1 || s.insize > s.inwin {
   289  		newWindow := s.in.start + int64(len(s.inbuf)) + s.inmaxbuf
   290  		addedWindow := newWindow - s.inwin
   291  		if shouldUpdateFlowControl(s.inmaxbuf, addedWindow) {
   292  			// Update stream flow control with a STREAM_MAX_DATA frame.
   293  			s.insendmax.setUnsent()
   294  		}
   295  	}
   296  	return len(b), nil
   297  }
   298  
   299  // ReadByte reads and returns a single byte from the stream.
   300  //
   301  // It is not safe to call ReadByte concurrently.
   302  func (s *Stream) ReadByte() (byte, error) {
   303  	if len(s.inbuf) > s.inbufoff {
   304  		b := s.inbuf[s.inbufoff]
   305  		s.inbufoff++
   306  		return b, nil
   307  	}
   308  	var b [1]byte
   309  	n, err := s.Read(b[:])
   310  	if n > 0 {
   311  		return b[0], err
   312  	}
   313  	return 0, err
   314  }
   315  
   316  // shouldUpdateFlowControl determines whether to send a flow control window update.
   317  //
   318  // We want to balance keeping the peer well-supplied with flow control with not sending
   319  // many small updates.
   320  func shouldUpdateFlowControl(maxWindow, addedWindow int64) bool {
   321  	return addedWindow >= maxWindow/8
   322  }
   323  
   324  // Write writes data to the stream.
   325  //
   326  // Write writes data to the stream write buffer.
   327  // Buffered data is only sent when the buffer is sufficiently full.
   328  // Call the Flush method to ensure buffered data is sent.
   329  func (s *Stream) Write(b []byte) (n int, err error) {
   330  	if s.IsReadOnly() {
   331  		return 0, errors.New("write to read-only stream")
   332  	}
   333  	if len(b) > 0 && len(s.outbuf)-s.outbufoff >= len(b) {
   334  		// Fast path: The data to write fits in s.outbuf.
   335  		copy(s.outbuf[s.outbufoff:], b)
   336  		s.outbufoff += len(b)
   337  		return len(b), nil
   338  	}
   339  	canWrite := s.outgate.lock()
   340  	s.flushFastOutputBuffer()
   341  	for {
   342  		// The first time through this loop, we may or may not be write blocked.
   343  		// We exit the loop after writing all data, so on subsequent passes through
   344  		// the loop we are always write blocked.
   345  		if len(b) > 0 && !canWrite {
   346  			// Our send buffer is full. Wait for the peer to ack some data.
   347  			s.outUnlock()
   348  			if err := s.outgate.waitAndLock(s.outctx, s.conn.testHooks); err != nil {
   349  				return n, err
   350  			}
   351  			// Successfully returning from waitAndLockGate means we are no longer
   352  			// write blocked. (Unlike traditional condition variables, gates do not
   353  			// have spurious wakeups.)
   354  		}
   355  		if s.outreset.isSet() {
   356  			s.outUnlock()
   357  			return n, errors.New("write to reset stream")
   358  		}
   359  		if s.outclosed.isSet() {
   360  			s.outUnlock()
   361  			return n, errors.New("write to closed stream")
   362  		}
   363  		if len(b) == 0 {
   364  			break
   365  		}
   366  		// Write limit is our send buffer limit.
   367  		// This is a stream offset.
   368  		lim := s.out.start + s.outmaxbuf
   369  		// Amount to write is min(the full buffer, data up to the write limit).
   370  		// This is a number of bytes.
   371  		nn := min(int64(len(b)), lim-s.out.end)
   372  		// Copy the data into the output buffer.
   373  		s.out.writeAt(b[:nn], s.out.end)
   374  		b = b[nn:]
   375  		n += int(nn)
   376  		// Possibly flush the output buffer.
   377  		// We automatically flush if:
   378  		//   - We have enough data to consume the send window.
   379  		//     Sending this data may cause the peer to extend the window.
   380  		//   - We have buffered as much data as we're willing do.
   381  		//     We need to send data to clear out buffer space.
   382  		//   - We have enough data to fill a 1-RTT packet using the smallest
   383  		//     possible maximum datagram size (1200 bytes, less header byte,
   384  		//     connection ID, packet number, and AEAD overhead).
   385  		const autoFlushSize = smallestMaxDatagramSize - 1 - connIDLen - 1 - aeadOverhead
   386  		shouldFlush := s.out.end >= s.outwin || // peer send window is full
   387  			s.out.end >= lim || // local send buffer is full
   388  			(s.out.end-s.outflushed) >= autoFlushSize // enough data buffered
   389  		if shouldFlush {
   390  			s.flushLocked()
   391  		}
   392  		if s.out.end > s.outwin {
   393  			// We're blocked by flow control.
   394  			// Send a STREAM_DATA_BLOCKED frame to let the peer know.
   395  			s.outblocked.set()
   396  		}
   397  		// If we have bytes left to send, we're blocked.
   398  		canWrite = false
   399  	}
   400  	if lim := s.out.start + s.outmaxbuf - s.out.end - 1; lim > 0 {
   401  		// If s.out has space allocated and available to be written into,
   402  		// then reference it in s.outbuf for fast-path writes.
   403  		//
   404  		// It's perhaps a bit pointless to limit s.outbuf to the send buffer limit.
   405  		// We've already allocated this buffer so we aren't saving any memory
   406  		// by not using it.
   407  		// For now, we limit it anyway to make it easier to reason about limits.
   408  		//
   409  		// We set the limit to one less than the send buffer limit (the -1 above)
   410  		// so that a write which completely fills the buffer will overflow
   411  		// s.outbuf and trigger a flush.
   412  		s.outbuf = s.out.availableBuffer()
   413  		if int64(len(s.outbuf)) > lim {
   414  			s.outbuf = s.outbuf[:lim]
   415  		}
   416  	}
   417  	s.outUnlock()
   418  	return n, nil
   419  }
   420  
   421  // WriteBytes writes a single byte to the stream.
   422  func (s *Stream) WriteByte(c byte) error {
   423  	if s.outbufoff < len(s.outbuf) {
   424  		s.outbuf[s.outbufoff] = c
   425  		s.outbufoff++
   426  		return nil
   427  	}
   428  	b := [1]byte{c}
   429  	_, err := s.Write(b[:])
   430  	return err
   431  }
   432  
   433  func (s *Stream) flushFastOutputBuffer() {
   434  	if s.outbuf == nil {
   435  		return
   436  	}
   437  	// Commit data previously written to s.outbuf.
   438  	// s.outbuf is a reference to a buffer in s.out, so we just need to record
   439  	// that the output buffer has been extended.
   440  	s.out.end += int64(s.outbufoff)
   441  	s.outbuf = nil
   442  	s.outbufoff = 0
   443  }
   444  
   445  // Flush flushes data written to the stream.
   446  // It does not wait for the peer to acknowledge receipt of the data.
   447  // Use Close to wait for the peer's acknowledgement.
   448  func (s *Stream) Flush() {
   449  	s.outgate.lock()
   450  	defer s.outUnlock()
   451  	s.flushLocked()
   452  }
   453  
   454  func (s *Stream) flushLocked() {
   455  	s.flushFastOutputBuffer()
   456  	s.outopened.set()
   457  	if s.outflushed < s.outwin {
   458  		s.outunsent.add(s.outflushed, min(s.outwin, s.out.end))
   459  	}
   460  	s.outflushed = s.out.end
   461  }
   462  
   463  // Close closes the stream.
   464  // Any blocked stream operations will be unblocked and return errors.
   465  //
   466  // Close flushes any data in the stream write buffer and waits for the peer to
   467  // acknowledge receipt of the data.
   468  // If the stream has been reset, it waits for the peer to acknowledge the reset.
   469  // If the context expires before the peer receives the stream's data,
   470  // Close discards the buffer and returns the context error.
   471  func (s *Stream) Close() error {
   472  	s.CloseRead()
   473  	if s.IsReadOnly() {
   474  		return nil
   475  	}
   476  	s.CloseWrite()
   477  	// TODO: Return code from peer's RESET_STREAM frame?
   478  	if err := s.conn.waitOnDone(s.outctx, s.outdone); err != nil {
   479  		return err
   480  	}
   481  	s.outgate.lock()
   482  	defer s.outUnlock()
   483  	if s.outclosed.isReceived() && s.outacked.isrange(0, s.out.end) {
   484  		return nil
   485  	}
   486  	return errors.New("stream reset")
   487  }
   488  
   489  // CloseRead aborts reads on the stream.
   490  // Any blocked reads will be unblocked and return errors.
   491  //
   492  // CloseRead notifies the peer that the stream has been closed for reading.
   493  // It does not wait for the peer to acknowledge the closure.
   494  // Use Close to wait for the peer's acknowledgement.
   495  func (s *Stream) CloseRead() {
   496  	if s.IsWriteOnly() {
   497  		return
   498  	}
   499  	s.ingate.lock()
   500  	if s.inset.isrange(0, s.insize) || s.inresetcode != -1 {
   501  		// We've already received all data from the peer,
   502  		// so there's no need to send STOP_SENDING.
   503  		// This is the same as saying we sent one and they got it.
   504  		s.inclosed.setReceived()
   505  	} else {
   506  		s.inclosed.set()
   507  	}
   508  	discarded := s.in.end - s.in.start
   509  	s.in.discardBefore(s.in.end)
   510  	s.inUnlock()
   511  	s.conn.handleStreamBytesReadOffLoop(discarded) // must be done with ingate unlocked
   512  }
   513  
   514  // CloseWrite aborts writes on the stream.
   515  // Any blocked writes will be unblocked and return errors.
   516  //
   517  // CloseWrite sends any data in the stream write buffer to the peer.
   518  // It does not wait for the peer to acknowledge receipt of the data.
   519  // Use Close to wait for the peer's acknowledgement.
   520  func (s *Stream) CloseWrite() {
   521  	if s.IsReadOnly() {
   522  		return
   523  	}
   524  	s.outgate.lock()
   525  	defer s.outUnlock()
   526  	s.outclosed.set()
   527  	s.flushLocked()
   528  }
   529  
   530  // Reset aborts writes on the stream and notifies the peer
   531  // that the stream was terminated abruptly.
   532  // Any blocked writes will be unblocked and return errors.
   533  //
   534  // Reset sends the application protocol error code, which must be
   535  // less than 2^62, to the peer.
   536  // It does not wait for the peer to acknowledge receipt of the error.
   537  // Use Close to wait for the peer's acknowledgement.
   538  //
   539  // Reset does not affect reads.
   540  // Use CloseRead to abort reads on the stream.
   541  func (s *Stream) Reset(code uint64) {
   542  	const userClosed = true
   543  	s.resetInternal(code, userClosed)
   544  }
   545  
   546  // resetInternal resets the send side of the stream.
   547  //
   548  // If userClosed is true, this is s.Reset.
   549  // If userClosed is false, this is a reaction to a STOP_SENDING frame.
   550  func (s *Stream) resetInternal(code uint64, userClosed bool) {
   551  	s.outgate.lock()
   552  	defer s.outUnlock()
   553  	if s.IsReadOnly() {
   554  		return
   555  	}
   556  	if userClosed {
   557  		// Mark that the user closed the stream.
   558  		s.outclosed.set()
   559  	}
   560  	if s.outreset.isSet() {
   561  		return
   562  	}
   563  	if code > maxVarint {
   564  		code = maxVarint
   565  	}
   566  	// We could check here to see if the stream is closed and the
   567  	// peer has acked all the data and the FIN, but sending an
   568  	// extra RESET_STREAM in this case is harmless.
   569  	s.outreset.set()
   570  	s.outresetcode = code
   571  	s.outbuf = nil
   572  	s.outbufoff = 0
   573  	s.out.discardBefore(s.out.end)
   574  	s.outunsent = rangeset[int64]{}
   575  	s.outblocked.clear()
   576  }
   577  
   578  // connHasClosed indicates the stream's conn has closed.
   579  func (s *Stream) connHasClosed() {
   580  	// If we're in the closing state, the user closed the conn.
   581  	// Otherwise, we the peer initiated the close.
   582  	// This only matters for the error we're going to return from stream operations.
   583  	localClose := s.conn.lifetime.state == connStateClosing
   584  
   585  	s.ingate.lock()
   586  	if !s.inset.isrange(0, s.insize) && s.inresetcode == -1 {
   587  		if localClose {
   588  			s.inclosed.set()
   589  		} else {
   590  			s.inresetcode = streamResetByConnClose
   591  		}
   592  	}
   593  	s.inUnlock()
   594  
   595  	s.outgate.lock()
   596  	if localClose {
   597  		s.outclosed.set()
   598  	}
   599  	s.outreset.set()
   600  	s.outUnlock()
   601  }
   602  
   603  // inUnlock unlocks s.ingate.
   604  // It sets the gate condition if reads from s will not block.
   605  // If s has receive-related frames to write or if both directions
   606  // are done and the stream should be removed, it notifies the Conn.
   607  func (s *Stream) inUnlock() {
   608  	state := s.inUnlockNoQueue()
   609  	s.conn.maybeQueueStreamForSend(s, state)
   610  }
   611  
   612  // inUnlockNoQueue is inUnlock,
   613  // but reports whether s has frames to write rather than notifying the Conn.
   614  func (s *Stream) inUnlockNoQueue() streamState {
   615  	nextByte := s.in.start + int64(len(s.inbuf))
   616  	canRead := s.inset.contains(nextByte) || // data available to read
   617  		s.insize == s.in.start+int64(len(s.inbuf)) || // at EOF
   618  		s.inresetcode != -1 || // reset by peer
   619  		s.inclosed.isSet() // closed locally
   620  	defer s.ingate.unlock(canRead)
   621  	var state streamState
   622  	switch {
   623  	case s.IsWriteOnly():
   624  		state = streamInDone
   625  	case s.inresetcode != -1: // reset by peer
   626  		fallthrough
   627  	case s.in.start == s.insize: // all data received and read
   628  		// We don't increase MAX_STREAMS until the user calls ReadClose or Close,
   629  		// so the receive side is not finished until inclosed is set.
   630  		if s.inclosed.isSet() {
   631  			state = streamInDone
   632  		}
   633  	case s.insendmax.shouldSend(): // STREAM_MAX_DATA
   634  		state = streamInSendMeta
   635  	case s.inclosed.shouldSend(): // STOP_SENDING
   636  		state = streamInSendMeta
   637  	}
   638  	const mask = streamInDone | streamInSendMeta
   639  	return s.state.set(state, mask)
   640  }
   641  
   642  // outUnlock unlocks s.outgate.
   643  // It sets the gate condition if writes to s will not block.
   644  // If s has send-related frames to write or if both directions
   645  // are done and the stream should be removed, it notifies the Conn.
   646  func (s *Stream) outUnlock() {
   647  	state := s.outUnlockNoQueue()
   648  	s.conn.maybeQueueStreamForSend(s, state)
   649  }
   650  
   651  // outUnlockNoQueue is outUnlock,
   652  // but reports whether s has frames to write rather than notifying the Conn.
   653  func (s *Stream) outUnlockNoQueue() streamState {
   654  	isDone := s.outclosed.isReceived() && s.outacked.isrange(0, s.out.end) || // all data acked
   655  		s.outreset.isSet() // reset locally
   656  	if isDone {
   657  		select {
   658  		case <-s.outdone:
   659  		default:
   660  			if !s.IsReadOnly() {
   661  				close(s.outdone)
   662  			}
   663  		}
   664  	}
   665  	lim := s.out.start + s.outmaxbuf
   666  	canWrite := lim > s.out.end || // available send buffer
   667  		s.outclosed.isSet() || // closed locally
   668  		s.outreset.isSet() // reset locally
   669  	defer s.outgate.unlock(canWrite)
   670  	var state streamState
   671  	switch {
   672  	case s.IsReadOnly():
   673  		state = streamOutDone
   674  	case s.outclosed.isReceived() && s.outacked.isrange(0, s.out.end): // all data sent and acked
   675  		fallthrough
   676  	case s.outreset.isReceived(): // RESET_STREAM sent and acked
   677  		// We don't increase MAX_STREAMS until the user calls WriteClose or Close,
   678  		// so the send side is not finished until outclosed is set.
   679  		if s.outclosed.isSet() {
   680  			state = streamOutDone
   681  		}
   682  	case s.outreset.shouldSend(): // RESET_STREAM
   683  		state = streamOutSendMeta
   684  	case s.outreset.isSet(): // RESET_STREAM sent but not acknowledged
   685  	case s.outblocked.shouldSend(): // STREAM_DATA_BLOCKED
   686  		state = streamOutSendMeta
   687  	case len(s.outunsent) > 0: // STREAM frame with data
   688  		if s.outunsent.min() < s.outmaxsent {
   689  			state = streamOutSendMeta // resent data, will not consume flow control
   690  		} else {
   691  			state = streamOutSendData // new data, requires flow control
   692  		}
   693  	case s.outclosed.shouldSend() && s.out.end == s.outmaxsent: // empty STREAM frame with FIN bit
   694  		state = streamOutSendMeta
   695  	case s.outopened.shouldSend(): // STREAM frame with no data
   696  		state = streamOutSendMeta
   697  	}
   698  	const mask = streamOutDone | streamOutSendMeta | streamOutSendData
   699  	return s.state.set(state, mask)
   700  }
   701  
   702  // handleData handles data received in a STREAM frame.
   703  func (s *Stream) handleData(off int64, b []byte, fin bool) error {
   704  	s.ingate.lock()
   705  	defer s.inUnlock()
   706  	end := off + int64(len(b))
   707  	if err := s.checkStreamBounds(end, fin); err != nil {
   708  		return err
   709  	}
   710  	if s.inclosed.isSet() || s.inresetcode != -1 {
   711  		// The user read-closed the stream, or the peer reset it.
   712  		// Either way, we can discard this frame.
   713  		return nil
   714  	}
   715  	if s.insize == -1 && end > s.in.end {
   716  		added := end - s.in.end
   717  		if err := s.conn.handleStreamBytesReceived(added); err != nil {
   718  			return err
   719  		}
   720  	}
   721  	s.in.writeAt(b, off)
   722  	s.inset.add(off, end)
   723  	if fin {
   724  		s.insize = end
   725  		// The peer has enough flow control window to send the entire stream.
   726  		s.insendmax.clear()
   727  	}
   728  	return nil
   729  }
   730  
   731  // handleReset handles a RESET_STREAM frame.
   732  func (s *Stream) handleReset(code uint64, finalSize int64) error {
   733  	s.ingate.lock()
   734  	defer s.inUnlock()
   735  	const fin = true
   736  	if err := s.checkStreamBounds(finalSize, fin); err != nil {
   737  		return err
   738  	}
   739  	if s.inresetcode != -1 {
   740  		// The stream was already reset.
   741  		return nil
   742  	}
   743  	if s.insize == -1 {
   744  		added := finalSize - s.in.end
   745  		if err := s.conn.handleStreamBytesReceived(added); err != nil {
   746  			return err
   747  		}
   748  	}
   749  	s.conn.handleStreamBytesReadOnLoop(finalSize - s.in.start)
   750  	s.in.discardBefore(s.in.end)
   751  	s.inresetcode = int64(code)
   752  	s.insize = finalSize
   753  	return nil
   754  }
   755  
   756  // checkStreamBounds validates the stream offset in a STREAM or RESET_STREAM frame.
   757  func (s *Stream) checkStreamBounds(end int64, fin bool) error {
   758  	if end > s.inwin {
   759  		// The peer sent us data past the maximum flow control window we gave them.
   760  		return localTransportError{
   761  			code:   errFlowControl,
   762  			reason: "stream flow control window exceeded",
   763  		}
   764  	}
   765  	if s.insize != -1 && end > s.insize {
   766  		// The peer sent us data past the final size of the stream they previously gave us.
   767  		return localTransportError{
   768  			code:   errFinalSize,
   769  			reason: "data received past end of stream",
   770  		}
   771  	}
   772  	if fin && s.insize != -1 && end != s.insize {
   773  		// The peer changed the final size of the stream.
   774  		return localTransportError{
   775  			code:   errFinalSize,
   776  			reason: "final size of stream changed",
   777  		}
   778  	}
   779  	if fin && end < s.in.end {
   780  		// The peer has previously sent us data past the final size.
   781  		return localTransportError{
   782  			code:   errFinalSize,
   783  			reason: "end of stream occurs before prior data",
   784  		}
   785  	}
   786  	return nil
   787  }
   788  
   789  // handleStopSending handles a STOP_SENDING frame.
   790  func (s *Stream) handleStopSending(code uint64) error {
   791  	// Peer requests that we reset this stream.
   792  	// https://www.rfc-editor.org/rfc/rfc9000#section-3.5-4
   793  	const userReset = false
   794  	s.resetInternal(code, userReset)
   795  	return nil
   796  }
   797  
   798  // handleMaxStreamData handles an update received in a MAX_STREAM_DATA frame.
   799  func (s *Stream) handleMaxStreamData(maxStreamData int64) error {
   800  	s.outgate.lock()
   801  	defer s.outUnlock()
   802  	if maxStreamData <= s.outwin {
   803  		return nil
   804  	}
   805  	if s.outflushed > s.outwin {
   806  		s.outunsent.add(s.outwin, min(maxStreamData, s.outflushed))
   807  	}
   808  	s.outwin = maxStreamData
   809  	if s.out.end > s.outwin {
   810  		// We've still got more data than flow control window.
   811  		s.outblocked.setUnsent()
   812  	} else {
   813  		s.outblocked.clear()
   814  	}
   815  	return nil
   816  }
   817  
   818  // ackOrLoss handles the fate of stream frames other than STREAM.
   819  func (s *Stream) ackOrLoss(pnum packetNumber, ftype byte, fate packetFate) {
   820  	// Frames which carry new information each time they are sent
   821  	// (MAX_STREAM_DATA, STREAM_DATA_BLOCKED) must only be marked
   822  	// as received if the most recent packet carrying this frame is acked.
   823  	//
   824  	// Frames which are always the same (STOP_SENDING, RESET_STREAM)
   825  	// can be marked as received if any packet carrying this frame is acked.
   826  	switch ftype {
   827  	case frameTypeResetStream:
   828  		s.outgate.lock()
   829  		s.outreset.ackOrLoss(pnum, fate)
   830  		s.outUnlock()
   831  	case frameTypeStopSending:
   832  		s.ingate.lock()
   833  		s.inclosed.ackOrLoss(pnum, fate)
   834  		s.inUnlock()
   835  	case frameTypeMaxStreamData:
   836  		s.ingate.lock()
   837  		s.insendmax.ackLatestOrLoss(pnum, fate)
   838  		s.inUnlock()
   839  	case frameTypeStreamDataBlocked:
   840  		s.outgate.lock()
   841  		s.outblocked.ackLatestOrLoss(pnum, fate)
   842  		s.outUnlock()
   843  	default:
   844  		panic("unhandled frame type")
   845  	}
   846  }
   847  
   848  // ackOrLossData handles the fate of a STREAM frame.
   849  func (s *Stream) ackOrLossData(pnum packetNumber, start, end int64, fin bool, fate packetFate) {
   850  	s.outgate.lock()
   851  	defer s.outUnlock()
   852  	s.outopened.ackOrLoss(pnum, fate)
   853  	if fin {
   854  		s.outclosed.ackOrLoss(pnum, fate)
   855  	}
   856  	if s.outreset.isSet() {
   857  		// If the stream has been reset, we don't care any more.
   858  		return
   859  	}
   860  	switch fate {
   861  	case packetAcked:
   862  		s.outacked.add(start, end)
   863  		s.outunsent.sub(start, end)
   864  		// If this ack is for data at the start of the send buffer, we can now discard it.
   865  		if s.outacked.contains(s.out.start) {
   866  			s.out.discardBefore(s.outacked[0].end)
   867  		}
   868  	case packetLost:
   869  		// Mark everything lost, but not previously acked, as needing retransmission.
   870  		// We do this by adding all the lost bytes to outunsent, and then
   871  		// removing everything already acked.
   872  		s.outunsent.add(start, end)
   873  		for _, a := range s.outacked {
   874  			s.outunsent.sub(a.start, a.end)
   875  		}
   876  	}
   877  }
   878  
   879  // appendInFramesLocked appends STOP_SENDING and MAX_STREAM_DATA frames
   880  // to the current packet.
   881  //
   882  // It returns true if no more frames need appending,
   883  // false if not everything fit in the current packet.
   884  func (s *Stream) appendInFramesLocked(w *packetWriter, pnum packetNumber, pto bool) bool {
   885  	if s.inclosed.shouldSendPTO(pto) {
   886  		// We don't currently have an API for setting the error code.
   887  		// Just send zero.
   888  		code := uint64(0)
   889  		if !w.appendStopSendingFrame(s.id, code) {
   890  			return false
   891  		}
   892  		s.inclosed.setSent(pnum)
   893  	}
   894  	// TODO: STOP_SENDING
   895  	if s.insendmax.shouldSendPTO(pto) {
   896  		// MAX_STREAM_DATA
   897  		maxStreamData := s.in.start + s.inmaxbuf
   898  		if !w.appendMaxStreamDataFrame(s.id, maxStreamData) {
   899  			return false
   900  		}
   901  		s.inwin = maxStreamData
   902  		s.insendmax.setSent(pnum)
   903  	}
   904  	return true
   905  }
   906  
   907  // appendOutFramesLocked appends RESET_STREAM, STREAM_DATA_BLOCKED, and STREAM frames
   908  // to the current packet.
   909  //
   910  // It returns true if no more frames need appending,
   911  // false if not everything fit in the current packet.
   912  func (s *Stream) appendOutFramesLocked(w *packetWriter, pnum packetNumber, pto bool) bool {
   913  	if s.outreset.isSet() {
   914  		// RESET_STREAM
   915  		if s.outreset.shouldSendPTO(pto) {
   916  			if !w.appendResetStreamFrame(s.id, s.outresetcode, min(s.outwin, s.out.end)) {
   917  				return false
   918  			}
   919  			s.outreset.setSent(pnum)
   920  			s.frameOpensStream(pnum)
   921  		}
   922  		return true
   923  	}
   924  	if s.outblocked.shouldSendPTO(pto) {
   925  		// STREAM_DATA_BLOCKED
   926  		if !w.appendStreamDataBlockedFrame(s.id, s.outwin) {
   927  			return false
   928  		}
   929  		s.outblocked.setSent(pnum)
   930  		s.frameOpensStream(pnum)
   931  	}
   932  	for {
   933  		// STREAM
   934  		off, size := dataToSend(min(s.out.start, s.outwin), min(s.outflushed, s.outwin), s.outunsent, s.outacked, pto)
   935  		if end := off + size; end > s.outmaxsent {
   936  			// This will require connection-level flow control to send.
   937  			end = min(end, s.outmaxsent+s.conn.streams.outflow.avail())
   938  			end = max(end, off)
   939  			size = end - off
   940  		}
   941  		fin := s.outclosed.isSet() && off+size == s.out.end
   942  		shouldSend := size > 0 || // have data to send
   943  			s.outopened.shouldSendPTO(pto) || // should open the stream
   944  			(fin && s.outclosed.shouldSendPTO(pto)) // should close the stream
   945  		if !shouldSend {
   946  			return true
   947  		}
   948  		b, added := w.appendStreamFrame(s.id, off, int(size), fin)
   949  		if !added {
   950  			return false
   951  		}
   952  		s.out.copy(off, b)
   953  		end := off + int64(len(b))
   954  		if end > s.outmaxsent {
   955  			s.conn.streams.outflow.consume(end - s.outmaxsent)
   956  			s.outmaxsent = end
   957  		}
   958  		s.outunsent.sub(off, end)
   959  		s.frameOpensStream(pnum)
   960  		if fin {
   961  			s.outclosed.setSent(pnum)
   962  		}
   963  		if pto {
   964  			return true
   965  		}
   966  		if int64(len(b)) < size {
   967  			return false
   968  		}
   969  	}
   970  }
   971  
   972  // frameOpensStream records that we're sending a frame that will open the stream.
   973  //
   974  // If we don't have an acknowledgement from the peer for a previous frame opening the stream,
   975  // record this packet as being the latest one to open it.
   976  func (s *Stream) frameOpensStream(pnum packetNumber) {
   977  	if !s.outopened.isReceived() {
   978  		s.outopened.setSent(pnum)
   979  	}
   980  }
   981  
   982  // dataToSend returns the next range of data to send in a STREAM or CRYPTO_STREAM.
   983  func dataToSend(start, end int64, outunsent, outacked rangeset[int64], pto bool) (sendStart, size int64) {
   984  	switch {
   985  	case pto:
   986  		// On PTO, resend unacked data that fits in the probe packet.
   987  		// For simplicity, we send the range starting at s.out.start
   988  		// (which is definitely unacked, or else we would have discarded it)
   989  		// up to the next acked byte (if any).
   990  		//
   991  		// This may miss unacked data starting after that acked byte,
   992  		// but avoids resending data the peer has acked.
   993  		for _, r := range outacked {
   994  			if r.start > start {
   995  				return start, r.start - start
   996  			}
   997  		}
   998  		return start, end - start
   999  	case outunsent.numRanges() > 0:
  1000  		return outunsent.min(), outunsent[0].size()
  1001  	default:
  1002  		return end, 0
  1003  	}
  1004  }