github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/stream.go (about) 1 package quic 2 3 import ( 4 "context" 5 "net" 6 "os" 7 "sync" 8 "time" 9 10 "github.com/apernet/quic-go/internal/ackhandler" 11 "github.com/apernet/quic-go/internal/flowcontrol" 12 "github.com/apernet/quic-go/internal/protocol" 13 "github.com/apernet/quic-go/internal/wire" 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 } 85 86 var _ Stream = &stream{} 87 88 // newStream creates a new Stream 89 func newStream( 90 ctx context.Context, 91 streamID protocol.StreamID, 92 sender streamSender, 93 flowController flowcontrol.StreamFlowController, 94 ) *stream { 95 s := &stream{sender: sender} 96 senderForSendStream := &uniStreamSender{ 97 streamSender: sender, 98 onStreamCompletedImpl: func() { 99 s.completedMutex.Lock() 100 s.sendStreamCompleted = true 101 s.checkIfCompleted() 102 s.completedMutex.Unlock() 103 }, 104 } 105 s.sendStream = *newSendStream(ctx, streamID, senderForSendStream, flowController) 106 senderForReceiveStream := &uniStreamSender{ 107 streamSender: sender, 108 onStreamCompletedImpl: func() { 109 s.completedMutex.Lock() 110 s.receiveStreamCompleted = true 111 s.checkIfCompleted() 112 s.completedMutex.Unlock() 113 }, 114 } 115 s.receiveStream = *newReceiveStream(streamID, senderForReceiveStream, flowController) 116 return s 117 } 118 119 // need to define StreamID() here, since both receiveStream and readStream have a StreamID() 120 func (s *stream) StreamID() protocol.StreamID { 121 // the result is same for receiveStream and sendStream 122 return s.sendStream.StreamID() 123 } 124 125 func (s *stream) Close() error { 126 return s.sendStream.Close() 127 } 128 129 func (s *stream) SetDeadline(t time.Time) error { 130 _ = s.SetReadDeadline(t) // SetReadDeadline never errors 131 _ = s.SetWriteDeadline(t) // SetWriteDeadline never errors 132 return nil 133 } 134 135 // CloseForShutdown closes a stream abruptly. 136 // It makes Read and Write unblock (and return the error) immediately. 137 // The peer will NOT be informed about this: the stream is closed without sending a FIN or RST. 138 func (s *stream) closeForShutdown(err error) { 139 s.sendStream.closeForShutdown(err) 140 s.receiveStream.closeForShutdown(err) 141 } 142 143 // checkIfCompleted is called from the uniStreamSender, when one of the stream halves is completed. 144 // It makes sure that the onStreamCompleted callback is only called if both receive and send side have completed. 145 func (s *stream) checkIfCompleted() { 146 if s.sendStreamCompleted && s.receiveStreamCompleted { 147 s.sender.onStreamCompleted(s.StreamID()) 148 } 149 }