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

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