github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/quic-go/receive_stream.go (about)

     1  package quic
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/flowcontrol"
    10  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/protocol"
    11  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/qerr"
    12  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/utils"
    13  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/wire"
    14  )
    15  
    16  type receiveStreamI interface {
    17  	ReceiveStream
    18  
    19  	handleStreamFrame(*wire.StreamFrame) error
    20  	handleResetStreamFrame(*wire.ResetStreamFrame) error
    21  	closeForShutdown(error)
    22  	getWindowUpdate() protocol.ByteCount
    23  }
    24  
    25  type receiveStream struct {
    26  	mutex sync.Mutex
    27  
    28  	streamID protocol.StreamID
    29  
    30  	sender streamSender
    31  
    32  	frameQueue  *frameSorter
    33  	finalOffset protocol.ByteCount
    34  
    35  	currentFrame       []byte
    36  	currentFrameDone   func()
    37  	currentFrameIsLast bool // is the currentFrame the last frame on this stream
    38  	readPosInFrame     int
    39  
    40  	closeForShutdownErr error
    41  	cancelReadErr       error
    42  	resetRemotelyErr    *StreamError
    43  
    44  	closedForShutdown bool // set when CloseForShutdown() is called
    45  	finRead           bool // set once we read a frame with a Fin
    46  	canceledRead      bool // set when CancelRead() is called
    47  	resetRemotely     bool // set when HandleResetStreamFrame() is called
    48  
    49  	readChan chan struct{}
    50  	deadline time.Time
    51  
    52  	flowController flowcontrol.StreamFlowController
    53  	version        protocol.VersionNumber
    54  }
    55  
    56  var (
    57  	_ ReceiveStream  = &receiveStream{}
    58  	_ receiveStreamI = &receiveStream{}
    59  )
    60  
    61  func newReceiveStream(
    62  	streamID protocol.StreamID,
    63  	sender streamSender,
    64  	flowController flowcontrol.StreamFlowController,
    65  	version protocol.VersionNumber,
    66  ) *receiveStream {
    67  	return &receiveStream{
    68  		streamID:       streamID,
    69  		sender:         sender,
    70  		flowController: flowController,
    71  		frameQueue:     newFrameSorter(),
    72  		readChan:       make(chan struct{}, 1),
    73  		finalOffset:    protocol.MaxByteCount,
    74  		version:        version,
    75  	}
    76  }
    77  
    78  func (s *receiveStream) StreamID() protocol.StreamID {
    79  	return s.streamID
    80  }
    81  
    82  // Read implements io.Reader. It is not thread safe!
    83  func (s *receiveStream) Read(p []byte) (int, error) {
    84  	s.mutex.Lock()
    85  	completed, n, err := s.readImpl(p)
    86  	s.mutex.Unlock()
    87  
    88  	if completed {
    89  		s.sender.onStreamCompleted(s.streamID)
    90  	}
    91  	return n, err
    92  }
    93  
    94  func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, error) {
    95  	if s.finRead {
    96  		return false, 0, io.EOF
    97  	}
    98  	if s.canceledRead {
    99  		return false, 0, s.cancelReadErr
   100  	}
   101  	if s.resetRemotely {
   102  		return false, 0, s.resetRemotelyErr
   103  	}
   104  	if s.closedForShutdown {
   105  		return false, 0, s.closeForShutdownErr
   106  	}
   107  
   108  	bytesRead := 0
   109  	var deadlineTimer *utils.Timer
   110  	for bytesRead < len(p) {
   111  		if s.currentFrame == nil || s.readPosInFrame >= len(s.currentFrame) {
   112  			s.dequeueNextFrame()
   113  		}
   114  		if s.currentFrame == nil && bytesRead > 0 {
   115  			return false, bytesRead, s.closeForShutdownErr
   116  		}
   117  
   118  		for {
   119  			// Stop waiting on errors
   120  			if s.closedForShutdown {
   121  				return false, bytesRead, s.closeForShutdownErr
   122  			}
   123  			if s.canceledRead {
   124  				return false, bytesRead, s.cancelReadErr
   125  			}
   126  			if s.resetRemotely {
   127  				return false, bytesRead, s.resetRemotelyErr
   128  			}
   129  
   130  			deadline := s.deadline
   131  			if !deadline.IsZero() {
   132  				if !time.Now().Before(deadline) {
   133  					return false, bytesRead, errDeadline
   134  				}
   135  				if deadlineTimer == nil {
   136  					deadlineTimer = utils.NewTimer()
   137  					defer deadlineTimer.Stop()
   138  				}
   139  				deadlineTimer.Reset(deadline)
   140  			}
   141  
   142  			if s.currentFrame != nil || s.currentFrameIsLast {
   143  				break
   144  			}
   145  
   146  			s.mutex.Unlock()
   147  			if deadline.IsZero() {
   148  				<-s.readChan
   149  			} else {
   150  				select {
   151  				case <-s.readChan:
   152  				case <-deadlineTimer.Chan():
   153  					deadlineTimer.SetRead()
   154  				}
   155  			}
   156  			s.mutex.Lock()
   157  			if s.currentFrame == nil {
   158  				s.dequeueNextFrame()
   159  			}
   160  		}
   161  
   162  		if bytesRead > len(p) {
   163  			return false, bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p))
   164  		}
   165  		if s.readPosInFrame > len(s.currentFrame) {
   166  			return false, bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, len(s.currentFrame))
   167  		}
   168  
   169  		m := copy(p[bytesRead:], s.currentFrame[s.readPosInFrame:])
   170  		s.readPosInFrame += m
   171  		bytesRead += m
   172  
   173  		// when a RESET_STREAM was received, the was already informed about the final byteOffset for this stream
   174  		if !s.resetRemotely {
   175  			s.flowController.AddBytesRead(protocol.ByteCount(m))
   176  		}
   177  
   178  		if s.readPosInFrame >= len(s.currentFrame) && s.currentFrameIsLast {
   179  			s.finRead = true
   180  			return true, bytesRead, io.EOF
   181  		}
   182  	}
   183  	return false, bytesRead, nil
   184  }
   185  
   186  func (s *receiveStream) dequeueNextFrame() {
   187  	var offset protocol.ByteCount
   188  	// We're done with the last frame. Release the buffer.
   189  	if s.currentFrameDone != nil {
   190  		s.currentFrameDone()
   191  	}
   192  	offset, s.currentFrame, s.currentFrameDone = s.frameQueue.Pop()
   193  	s.currentFrameIsLast = offset+protocol.ByteCount(len(s.currentFrame)) >= s.finalOffset
   194  	s.readPosInFrame = 0
   195  }
   196  
   197  func (s *receiveStream) CancelRead(errorCode StreamErrorCode) {
   198  	s.mutex.Lock()
   199  	completed := s.cancelReadImpl(errorCode)
   200  	s.mutex.Unlock()
   201  
   202  	if completed {
   203  		s.flowController.Abandon()
   204  		s.sender.onStreamCompleted(s.streamID)
   205  	}
   206  }
   207  
   208  func (s *receiveStream) cancelReadImpl(errorCode qerr.StreamErrorCode) bool /* completed */ {
   209  	if s.finRead || s.canceledRead || s.resetRemotely {
   210  		return false
   211  	}
   212  	s.canceledRead = true
   213  	s.cancelReadErr = fmt.Errorf("Read on stream %d canceled with error code %d", s.streamID, errorCode)
   214  	s.signalRead()
   215  	s.sender.queueControlFrame(&wire.StopSendingFrame{
   216  		StreamID:  s.streamID,
   217  		ErrorCode: errorCode,
   218  	})
   219  	// We're done with this stream if the final offset was already received.
   220  	return s.finalOffset != protocol.MaxByteCount
   221  }
   222  
   223  func (s *receiveStream) handleStreamFrame(frame *wire.StreamFrame) error {
   224  	s.mutex.Lock()
   225  	completed, err := s.handleStreamFrameImpl(frame)
   226  	s.mutex.Unlock()
   227  
   228  	if completed {
   229  		s.flowController.Abandon()
   230  		s.sender.onStreamCompleted(s.streamID)
   231  	}
   232  	return err
   233  }
   234  
   235  func (s *receiveStream) handleStreamFrameImpl(frame *wire.StreamFrame) (bool /* completed */, error) {
   236  	maxOffset := frame.Offset + frame.DataLen()
   237  	if err := s.flowController.UpdateHighestReceived(maxOffset, frame.Fin); err != nil {
   238  		return false, err
   239  	}
   240  	var newlyRcvdFinalOffset bool
   241  	if frame.Fin {
   242  		newlyRcvdFinalOffset = s.finalOffset == protocol.MaxByteCount
   243  		s.finalOffset = maxOffset
   244  	}
   245  	if s.canceledRead {
   246  		return newlyRcvdFinalOffset, nil
   247  	}
   248  	if err := s.frameQueue.Push(frame.Data, frame.Offset, frame.PutBack); err != nil {
   249  		return false, err
   250  	}
   251  	s.signalRead()
   252  	return false, nil
   253  }
   254  
   255  func (s *receiveStream) handleResetStreamFrame(frame *wire.ResetStreamFrame) error {
   256  	s.mutex.Lock()
   257  	completed, err := s.handleResetStreamFrameImpl(frame)
   258  	s.mutex.Unlock()
   259  
   260  	if completed {
   261  		s.flowController.Abandon()
   262  		s.sender.onStreamCompleted(s.streamID)
   263  	}
   264  	return err
   265  }
   266  
   267  func (s *receiveStream) handleResetStreamFrameImpl(frame *wire.ResetStreamFrame) (bool /*completed */, error) {
   268  	if s.closedForShutdown {
   269  		return false, nil
   270  	}
   271  	if err := s.flowController.UpdateHighestReceived(frame.FinalSize, true); err != nil {
   272  		return false, err
   273  	}
   274  	newlyRcvdFinalOffset := s.finalOffset == protocol.MaxByteCount
   275  	s.finalOffset = frame.FinalSize
   276  
   277  	// ignore duplicate RESET_STREAM frames for this stream (after checking their final offset)
   278  	if s.resetRemotely {
   279  		return false, nil
   280  	}
   281  	s.resetRemotely = true
   282  	s.resetRemotelyErr = &StreamError{
   283  		StreamID:  s.streamID,
   284  		ErrorCode: frame.ErrorCode,
   285  	}
   286  	s.signalRead()
   287  	return newlyRcvdFinalOffset, nil
   288  }
   289  
   290  func (s *receiveStream) CloseRemote(offset protocol.ByteCount) {
   291  	s.handleStreamFrame(&wire.StreamFrame{Fin: true, Offset: offset})
   292  }
   293  
   294  func (s *receiveStream) SetReadDeadline(t time.Time) error {
   295  	s.mutex.Lock()
   296  	s.deadline = t
   297  	s.mutex.Unlock()
   298  	s.signalRead()
   299  	return nil
   300  }
   301  
   302  // CloseForShutdown closes a stream abruptly.
   303  // It makes Read unblock (and return the error) immediately.
   304  // The peer will NOT be informed about this: the stream is closed without sending a FIN or RESET.
   305  func (s *receiveStream) closeForShutdown(err error) {
   306  	s.mutex.Lock()
   307  	s.closedForShutdown = true
   308  	s.closeForShutdownErr = err
   309  	s.mutex.Unlock()
   310  	s.signalRead()
   311  }
   312  
   313  func (s *receiveStream) getWindowUpdate() protocol.ByteCount {
   314  	return s.flowController.GetWindowUpdate()
   315  }
   316  
   317  // signalRead performs a non-blocking send on the readChan
   318  func (s *receiveStream) signalRead() {
   319  	select {
   320  	case s.readChan <- struct{}{}:
   321  	default:
   322  	}
   323  }