github.com/daeuniverse/quic-go@v0.0.0-20240413031024-943f218e0810/receive_stream.go (about) 1 package quic 2 3 import ( 4 "fmt" 5 "io" 6 "sync" 7 "time" 8 9 "github.com/daeuniverse/quic-go/internal/flowcontrol" 10 "github.com/daeuniverse/quic-go/internal/protocol" 11 "github.com/daeuniverse/quic-go/internal/qerr" 12 "github.com/daeuniverse/quic-go/internal/utils" 13 "github.com/daeuniverse/quic-go/internal/wire" 14 ) 15 16 type receiveStreamI interface { 17 ReceiveStream 18 19 handleStreamFrame(*wire.StreamFrame) error 20 handleResetStreamFrame(*wire.ResetStreamFrame) error 21 closeForShutdown(error) 22 getWindowUpdate() protocol.ByteCount 23 } 24 25 type receiveStream struct { 26 mutex sync.Mutex 27 28 streamID protocol.StreamID 29 30 sender streamSender 31 32 frameQueue *frameSorter 33 finalOffset protocol.ByteCount 34 35 currentFrame []byte 36 currentFrameDone func() 37 readPosInFrame int 38 currentFrameIsLast bool // is the currentFrame the last frame on this stream 39 40 finRead bool // set once we read a frame with a Fin 41 closeForShutdownErr error 42 cancelReadErr error 43 resetRemotelyErr *StreamError 44 45 readChan chan struct{} 46 readOnce chan struct{} // cap: 1, to protect against concurrent use of Read 47 deadline time.Time 48 49 flowController flowcontrol.StreamFlowController 50 } 51 52 var ( 53 _ ReceiveStream = &receiveStream{} 54 _ receiveStreamI = &receiveStream{} 55 ) 56 57 func newReceiveStream( 58 streamID protocol.StreamID, 59 sender streamSender, 60 flowController flowcontrol.StreamFlowController, 61 ) *receiveStream { 62 return &receiveStream{ 63 streamID: streamID, 64 sender: sender, 65 flowController: flowController, 66 frameQueue: newFrameSorter(), 67 readChan: make(chan struct{}, 1), 68 readOnce: make(chan struct{}, 1), 69 finalOffset: protocol.MaxByteCount, 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 // Concurrent use of Read is not permitted (and doesn't make any sense), 80 // but sometimes people do it anyway. 81 // Make sure that we only execute one call at any given time to avoid hard to debug failures. 82 s.readOnce <- struct{}{} 83 defer func() { <-s.readOnce }() 84 85 s.mutex.Lock() 86 completed, n, err := s.readImpl(p) 87 s.mutex.Unlock() 88 89 if completed { 90 s.sender.onStreamCompleted(s.streamID) 91 } 92 return n, err 93 } 94 95 func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, error) { 96 if s.finRead { 97 return false, 0, io.EOF 98 } 99 if s.cancelReadErr != nil { 100 return false, 0, s.cancelReadErr 101 } 102 if s.resetRemotelyErr != nil { 103 return false, 0, s.resetRemotelyErr 104 } 105 if s.closeForShutdownErr != nil { 106 return false, 0, s.closeForShutdownErr 107 } 108 109 var bytesRead int 110 var deadlineTimer *utils.Timer 111 for bytesRead < len(p) { 112 if s.currentFrame == nil || s.readPosInFrame >= len(s.currentFrame) { 113 s.dequeueNextFrame() 114 } 115 if s.currentFrame == nil && bytesRead > 0 { 116 return false, bytesRead, s.closeForShutdownErr 117 } 118 119 for { 120 // Stop waiting on errors 121 if s.closeForShutdownErr != nil { 122 return false, bytesRead, s.closeForShutdownErr 123 } 124 if s.cancelReadErr != nil { 125 return false, bytesRead, s.cancelReadErr 126 } 127 if s.resetRemotelyErr != nil { 128 return false, bytesRead, s.resetRemotelyErr 129 } 130 131 deadline := s.deadline 132 if !deadline.IsZero() { 133 if !time.Now().Before(deadline) { 134 return false, bytesRead, errDeadline 135 } 136 if deadlineTimer == nil { 137 deadlineTimer = utils.NewTimer() 138 defer deadlineTimer.Stop() 139 } 140 deadlineTimer.Reset(deadline) 141 } 142 143 if s.currentFrame != nil || s.currentFrameIsLast { 144 break 145 } 146 147 s.mutex.Unlock() 148 if deadline.IsZero() { 149 <-s.readChan 150 } else { 151 select { 152 case <-s.readChan: 153 case <-deadlineTimer.Chan(): 154 deadlineTimer.SetRead() 155 } 156 } 157 s.mutex.Lock() 158 if s.currentFrame == nil { 159 s.dequeueNextFrame() 160 } 161 } 162 163 if bytesRead > len(p) { 164 return false, bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p)) 165 } 166 if s.readPosInFrame > len(s.currentFrame) { 167 return false, bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, len(s.currentFrame)) 168 } 169 170 m := copy(p[bytesRead:], s.currentFrame[s.readPosInFrame:]) 171 s.readPosInFrame += m 172 bytesRead += m 173 174 // when a RESET_STREAM was received, the flow controller was already 175 // informed about the final byteOffset for this stream 176 if s.resetRemotelyErr == nil { 177 s.flowController.AddBytesRead(protocol.ByteCount(m)) 178 } 179 180 if s.readPosInFrame >= len(s.currentFrame) && s.currentFrameIsLast { 181 s.finRead = true 182 s.currentFrame = nil 183 if s.currentFrameDone != nil { 184 s.currentFrameDone() 185 } 186 return true, bytesRead, io.EOF 187 } 188 } 189 return false, bytesRead, nil 190 } 191 192 func (s *receiveStream) dequeueNextFrame() { 193 var offset protocol.ByteCount 194 // We're done with the last frame. Release the buffer. 195 if s.currentFrameDone != nil { 196 s.currentFrameDone() 197 } 198 offset, s.currentFrame, s.currentFrameDone = s.frameQueue.Pop() 199 s.currentFrameIsLast = offset+protocol.ByteCount(len(s.currentFrame)) >= s.finalOffset 200 s.readPosInFrame = 0 201 } 202 203 func (s *receiveStream) CancelRead(errorCode StreamErrorCode) { 204 s.mutex.Lock() 205 completed := s.cancelReadImpl(errorCode) 206 s.mutex.Unlock() 207 208 if completed { 209 s.flowController.Abandon() 210 s.sender.onStreamCompleted(s.streamID) 211 } 212 } 213 214 func (s *receiveStream) cancelReadImpl(errorCode qerr.StreamErrorCode) bool /* completed */ { 215 if s.finRead || s.cancelReadErr != nil || s.resetRemotelyErr != nil { 216 return false 217 } 218 s.cancelReadErr = &StreamError{StreamID: s.streamID, ErrorCode: errorCode, Remote: false} 219 s.signalRead() 220 s.sender.queueControlFrame(&wire.StopSendingFrame{ 221 StreamID: s.streamID, 222 ErrorCode: errorCode, 223 }) 224 // We're done with this stream if the final offset was already received. 225 return s.finalOffset != protocol.MaxByteCount 226 } 227 228 func (s *receiveStream) handleStreamFrame(frame *wire.StreamFrame) error { 229 s.mutex.Lock() 230 completed, err := s.handleStreamFrameImpl(frame) 231 s.mutex.Unlock() 232 233 if completed { 234 s.flowController.Abandon() 235 s.sender.onStreamCompleted(s.streamID) 236 } 237 return err 238 } 239 240 func (s *receiveStream) handleStreamFrameImpl(frame *wire.StreamFrame) (bool /* completed */, error) { 241 maxOffset := frame.Offset + frame.DataLen() 242 if err := s.flowController.UpdateHighestReceived(maxOffset, frame.Fin); err != nil { 243 return false, err 244 } 245 var newlyRcvdFinalOffset bool 246 if frame.Fin { 247 newlyRcvdFinalOffset = s.finalOffset == protocol.MaxByteCount 248 s.finalOffset = maxOffset 249 } 250 if s.cancelReadErr != nil { 251 return newlyRcvdFinalOffset, nil 252 } 253 if err := s.frameQueue.Push(frame.Data, frame.Offset, frame.PutBack); err != nil { 254 return false, err 255 } 256 s.signalRead() 257 return false, nil 258 } 259 260 func (s *receiveStream) handleResetStreamFrame(frame *wire.ResetStreamFrame) error { 261 s.mutex.Lock() 262 completed, err := s.handleResetStreamFrameImpl(frame) 263 s.mutex.Unlock() 264 265 if completed { 266 s.flowController.Abandon() 267 s.sender.onStreamCompleted(s.streamID) 268 } 269 return err 270 } 271 272 func (s *receiveStream) handleResetStreamFrameImpl(frame *wire.ResetStreamFrame) (bool /*completed */, error) { 273 if s.closeForShutdownErr != nil { 274 return false, nil 275 } 276 if err := s.flowController.UpdateHighestReceived(frame.FinalSize, true); err != nil { 277 return false, err 278 } 279 newlyRcvdFinalOffset := s.finalOffset == protocol.MaxByteCount 280 s.finalOffset = frame.FinalSize 281 282 // ignore duplicate RESET_STREAM frames for this stream (after checking their final offset) 283 if s.resetRemotelyErr != nil { 284 return false, nil 285 } 286 s.resetRemotelyErr = &StreamError{ 287 StreamID: s.streamID, 288 ErrorCode: frame.ErrorCode, 289 Remote: true, 290 } 291 s.signalRead() 292 return newlyRcvdFinalOffset, nil 293 } 294 295 func (s *receiveStream) SetReadDeadline(t time.Time) error { 296 s.mutex.Lock() 297 s.deadline = t 298 s.mutex.Unlock() 299 s.signalRead() 300 return nil 301 } 302 303 // CloseForShutdown closes a stream abruptly. 304 // It makes Read unblock (and return the error) immediately. 305 // The peer will NOT be informed about this: the stream is closed without sending a FIN or RESET. 306 func (s *receiveStream) closeForShutdown(err error) { 307 s.mutex.Lock() 308 s.closeForShutdownErr = err 309 s.mutex.Unlock() 310 s.signalRead() 311 } 312 313 func (s *receiveStream) getWindowUpdate() protocol.ByteCount { 314 return s.flowController.GetWindowUpdate() 315 } 316 317 // signalRead performs a non-blocking send on the readChan 318 func (s *receiveStream) signalRead() { 319 select { 320 case s.readChan <- struct{}{}: 321 default: 322 } 323 }