github.com/tumi8/quic-go@v0.37.4-tum/receive_stream.go (about)

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