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

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