github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/gquic-go/receive_stream.go (about)

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