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