github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/receive_stream.go (about)

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