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

     1  package gquic
     2  
     3  import (
     4  	"net"
     5  	"sync"
     6  	"time"
     7  
     8  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/flowcontrol"
     9  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/protocol"
    10  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/wire"
    11  )
    12  
    13  const (
    14  	errorCodeStopping      protocol.ApplicationErrorCode = 0
    15  	errorCodeStoppingGQUIC protocol.ApplicationErrorCode = 7
    16  )
    17  
    18  // The streamSender is notified by the stream about various events.
    19  type streamSender interface {
    20  	queueControlFrame(wire.Frame)
    21  	onHasStreamData(protocol.StreamID)
    22  	// must be called without holding the mutex that is acquired by closeForShutdown
    23  	onStreamCompleted(protocol.StreamID)
    24  }
    25  
    26  // Each of the both stream halves gets its own uniStreamSender.
    27  // This is necessary in order to keep track when both halves have been completed.
    28  type uniStreamSender struct {
    29  	streamSender
    30  	onStreamCompletedImpl func()
    31  }
    32  
    33  func (s *uniStreamSender) queueControlFrame(f wire.Frame) {
    34  	s.streamSender.queueControlFrame(f)
    35  }
    36  
    37  func (s *uniStreamSender) onHasStreamData(id protocol.StreamID) {
    38  	s.streamSender.onHasStreamData(id)
    39  }
    40  
    41  func (s *uniStreamSender) onStreamCompleted(protocol.StreamID) {
    42  	s.onStreamCompletedImpl()
    43  }
    44  
    45  var _ streamSender = &uniStreamSender{}
    46  
    47  type streamI interface {
    48  	Stream
    49  	closeForShutdown(error)
    50  	// for receiving
    51  	handleStreamFrame(*wire.StreamFrame) error
    52  	handleRstStreamFrame(*wire.RstStreamFrame) error
    53  	getWindowUpdate() protocol.ByteCount
    54  	// for sending
    55  	hasData() bool
    56  	handleStopSendingFrame(*wire.StopSendingFrame)
    57  	popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFrame, bool)
    58  	handleMaxStreamDataFrame(*wire.MaxStreamDataFrame)
    59  }
    60  
    61  var _ receiveStreamI = (streamI)(nil)
    62  var _ sendStreamI = (streamI)(nil)
    63  
    64  // A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface
    65  //
    66  // Read() and Write() may be called concurrently, but multiple calls to Read() or Write() individually must be synchronized manually.
    67  type stream struct {
    68  	receiveStream
    69  	sendStream
    70  
    71  	completedMutex         sync.Mutex
    72  	sender                 streamSender
    73  	receiveStreamCompleted bool
    74  	sendStreamCompleted    bool
    75  
    76  	version protocol.VersionNumber
    77  }
    78  
    79  var _ Stream = &stream{}
    80  
    81  type deadlineError struct{}
    82  
    83  func (deadlineError) Error() string   { return "deadline exceeded" }
    84  func (deadlineError) Temporary() bool { return true }
    85  func (deadlineError) Timeout() bool   { return true }
    86  
    87  var errDeadline net.Error = &deadlineError{}
    88  
    89  type streamCanceledError struct {
    90  	error
    91  	errorCode protocol.ApplicationErrorCode
    92  }
    93  
    94  func (streamCanceledError) Canceled() bool                             { return true }
    95  func (e streamCanceledError) ErrorCode() protocol.ApplicationErrorCode { return e.errorCode }
    96  
    97  var _ StreamError = &streamCanceledError{}
    98  
    99  // newStream creates a new Stream
   100  func newStream(streamID protocol.StreamID,
   101  	sender streamSender,
   102  	flowController flowcontrol.StreamFlowController,
   103  	version protocol.VersionNumber,
   104  ) *stream {
   105  	s := &stream{sender: sender, version: version}
   106  	senderForSendStream := &uniStreamSender{
   107  		streamSender: sender,
   108  		onStreamCompletedImpl: func() {
   109  			s.completedMutex.Lock()
   110  			s.sendStreamCompleted = true
   111  			s.checkIfCompleted()
   112  			s.completedMutex.Unlock()
   113  		},
   114  	}
   115  	s.sendStream = *newSendStream(streamID, senderForSendStream, flowController, version)
   116  	senderForReceiveStream := &uniStreamSender{
   117  		streamSender: sender,
   118  		onStreamCompletedImpl: func() {
   119  			s.completedMutex.Lock()
   120  			s.receiveStreamCompleted = true
   121  			s.checkIfCompleted()
   122  			s.completedMutex.Unlock()
   123  		},
   124  	}
   125  	s.receiveStream = *newReceiveStream(streamID, senderForReceiveStream, flowController, version)
   126  	return s
   127  }
   128  
   129  // need to define StreamID() here, since both receiveStream and readStream have a StreamID()
   130  func (s *stream) StreamID() protocol.StreamID {
   131  	// the result is same for receiveStream and sendStream
   132  	return s.sendStream.StreamID()
   133  }
   134  
   135  func (s *stream) Close() error {
   136  	if err := s.sendStream.Close(); err != nil {
   137  		return err
   138  	}
   139  	// in gQUIC, we need to send a RST_STREAM with the final offset if CancelRead() was called
   140  	s.receiveStream.onClose(s.sendStream.getWriteOffset())
   141  	return nil
   142  }
   143  
   144  func (s *stream) SetDeadline(t time.Time) error {
   145  	_ = s.SetReadDeadline(t)  // SetReadDeadline never errors
   146  	_ = s.SetWriteDeadline(t) // SetWriteDeadline never errors
   147  	return nil
   148  }
   149  
   150  // CloseForShutdown closes a stream abruptly.
   151  // It makes Read and Write unblock (and return the error) immediately.
   152  // The peer will NOT be informed about this: the stream is closed without sending a FIN or RST.
   153  func (s *stream) closeForShutdown(err error) {
   154  	s.sendStream.closeForShutdown(err)
   155  	s.receiveStream.closeForShutdown(err)
   156  }
   157  
   158  func (s *stream) handleRstStreamFrame(frame *wire.RstStreamFrame) error {
   159  	if err := s.receiveStream.handleRstStreamFrame(frame); err != nil {
   160  		return err
   161  	}
   162  	if !s.version.UsesIETFFrameFormat() {
   163  		s.handleStopSendingFrame(&wire.StopSendingFrame{
   164  			StreamID:  s.StreamID(),
   165  			ErrorCode: frame.ErrorCode,
   166  		})
   167  	}
   168  	return nil
   169  }
   170  
   171  // checkIfCompleted is called from the uniStreamSender, when one of the stream halves is completed.
   172  // It makes sure that the onStreamCompleted callback is only called if both receive and send side have completed.
   173  func (s *stream) checkIfCompleted() {
   174  	if s.sendStreamCompleted && s.receiveStreamCompleted {
   175  		s.sender.onStreamCompleted(s.StreamID())
   176  	}
   177  }