github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/quic-go/receive_stream.go (about) 1 package quic 2 3 import ( 4 "fmt" 5 "io" 6 "sync" 7 "time" 8 9 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/flowcontrol" 10 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/protocol" 11 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/qerr" 12 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/utils" 13 "github.com/ooni/psiphon/tunnel-core/oovendor/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 currentFrameIsLast bool // is the currentFrame the last frame on this stream 38 readPosInFrame int 39 40 closeForShutdownErr error 41 cancelReadErr error 42 resetRemotelyErr *StreamError 43 44 closedForShutdown bool // set when CloseForShutdown() is called 45 finRead bool // set once we read a frame with a Fin 46 canceledRead bool // set when CancelRead() is called 47 resetRemotely bool // set when HandleResetStreamFrame() is called 48 49 readChan chan struct{} 50 deadline time.Time 51 52 flowController flowcontrol.StreamFlowController 53 version protocol.VersionNumber 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 version protocol.VersionNumber, 66 ) *receiveStream { 67 return &receiveStream{ 68 streamID: streamID, 69 sender: sender, 70 flowController: flowController, 71 frameQueue: newFrameSorter(), 72 readChan: make(chan struct{}, 1), 73 finalOffset: protocol.MaxByteCount, 74 version: version, 75 } 76 } 77 78 func (s *receiveStream) StreamID() protocol.StreamID { 79 return s.streamID 80 } 81 82 // Read implements io.Reader. It is not thread safe! 83 func (s *receiveStream) Read(p []byte) (int, error) { 84 s.mutex.Lock() 85 completed, n, err := s.readImpl(p) 86 s.mutex.Unlock() 87 88 if completed { 89 s.sender.onStreamCompleted(s.streamID) 90 } 91 return n, err 92 } 93 94 func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, error) { 95 if s.finRead { 96 return false, 0, io.EOF 97 } 98 if s.canceledRead { 99 return false, 0, s.cancelReadErr 100 } 101 if s.resetRemotely { 102 return false, 0, s.resetRemotelyErr 103 } 104 if s.closedForShutdown { 105 return false, 0, s.closeForShutdownErr 106 } 107 108 bytesRead := 0 109 var deadlineTimer *utils.Timer 110 for bytesRead < len(p) { 111 if s.currentFrame == nil || s.readPosInFrame >= len(s.currentFrame) { 112 s.dequeueNextFrame() 113 } 114 if s.currentFrame == nil && bytesRead > 0 { 115 return false, bytesRead, s.closeForShutdownErr 116 } 117 118 for { 119 // Stop waiting on errors 120 if s.closedForShutdown { 121 return false, bytesRead, s.closeForShutdownErr 122 } 123 if s.canceledRead { 124 return false, bytesRead, s.cancelReadErr 125 } 126 if s.resetRemotely { 127 return false, bytesRead, s.resetRemotelyErr 128 } 129 130 deadline := s.deadline 131 if !deadline.IsZero() { 132 if !time.Now().Before(deadline) { 133 return false, bytesRead, errDeadline 134 } 135 if deadlineTimer == nil { 136 deadlineTimer = utils.NewTimer() 137 defer deadlineTimer.Stop() 138 } 139 deadlineTimer.Reset(deadline) 140 } 141 142 if s.currentFrame != nil || s.currentFrameIsLast { 143 break 144 } 145 146 s.mutex.Unlock() 147 if deadline.IsZero() { 148 <-s.readChan 149 } else { 150 select { 151 case <-s.readChan: 152 case <-deadlineTimer.Chan(): 153 deadlineTimer.SetRead() 154 } 155 } 156 s.mutex.Lock() 157 if s.currentFrame == nil { 158 s.dequeueNextFrame() 159 } 160 } 161 162 if bytesRead > len(p) { 163 return false, bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p)) 164 } 165 if s.readPosInFrame > len(s.currentFrame) { 166 return false, bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, len(s.currentFrame)) 167 } 168 169 m := copy(p[bytesRead:], s.currentFrame[s.readPosInFrame:]) 170 s.readPosInFrame += m 171 bytesRead += m 172 173 // when a RESET_STREAM was received, the was already informed about the final byteOffset for this stream 174 if !s.resetRemotely { 175 s.flowController.AddBytesRead(protocol.ByteCount(m)) 176 } 177 178 if s.readPosInFrame >= len(s.currentFrame) && s.currentFrameIsLast { 179 s.finRead = true 180 return true, bytesRead, io.EOF 181 } 182 } 183 return false, bytesRead, nil 184 } 185 186 func (s *receiveStream) dequeueNextFrame() { 187 var offset protocol.ByteCount 188 // We're done with the last frame. Release the buffer. 189 if s.currentFrameDone != nil { 190 s.currentFrameDone() 191 } 192 offset, s.currentFrame, s.currentFrameDone = s.frameQueue.Pop() 193 s.currentFrameIsLast = offset+protocol.ByteCount(len(s.currentFrame)) >= s.finalOffset 194 s.readPosInFrame = 0 195 } 196 197 func (s *receiveStream) CancelRead(errorCode StreamErrorCode) { 198 s.mutex.Lock() 199 completed := s.cancelReadImpl(errorCode) 200 s.mutex.Unlock() 201 202 if completed { 203 s.flowController.Abandon() 204 s.sender.onStreamCompleted(s.streamID) 205 } 206 } 207 208 func (s *receiveStream) cancelReadImpl(errorCode qerr.StreamErrorCode) bool /* completed */ { 209 if s.finRead || s.canceledRead || s.resetRemotely { 210 return false 211 } 212 s.canceledRead = true 213 s.cancelReadErr = fmt.Errorf("Read on stream %d canceled with error code %d", s.streamID, errorCode) 214 s.signalRead() 215 s.sender.queueControlFrame(&wire.StopSendingFrame{ 216 StreamID: s.streamID, 217 ErrorCode: errorCode, 218 }) 219 // We're done with this stream if the final offset was already received. 220 return s.finalOffset != protocol.MaxByteCount 221 } 222 223 func (s *receiveStream) handleStreamFrame(frame *wire.StreamFrame) error { 224 s.mutex.Lock() 225 completed, err := s.handleStreamFrameImpl(frame) 226 s.mutex.Unlock() 227 228 if completed { 229 s.flowController.Abandon() 230 s.sender.onStreamCompleted(s.streamID) 231 } 232 return err 233 } 234 235 func (s *receiveStream) handleStreamFrameImpl(frame *wire.StreamFrame) (bool /* completed */, error) { 236 maxOffset := frame.Offset + frame.DataLen() 237 if err := s.flowController.UpdateHighestReceived(maxOffset, frame.Fin); err != nil { 238 return false, err 239 } 240 var newlyRcvdFinalOffset bool 241 if frame.Fin { 242 newlyRcvdFinalOffset = s.finalOffset == protocol.MaxByteCount 243 s.finalOffset = maxOffset 244 } 245 if s.canceledRead { 246 return newlyRcvdFinalOffset, nil 247 } 248 if err := s.frameQueue.Push(frame.Data, frame.Offset, frame.PutBack); err != nil { 249 return false, err 250 } 251 s.signalRead() 252 return false, nil 253 } 254 255 func (s *receiveStream) handleResetStreamFrame(frame *wire.ResetStreamFrame) error { 256 s.mutex.Lock() 257 completed, err := s.handleResetStreamFrameImpl(frame) 258 s.mutex.Unlock() 259 260 if completed { 261 s.flowController.Abandon() 262 s.sender.onStreamCompleted(s.streamID) 263 } 264 return err 265 } 266 267 func (s *receiveStream) handleResetStreamFrameImpl(frame *wire.ResetStreamFrame) (bool /*completed */, error) { 268 if s.closedForShutdown { 269 return false, nil 270 } 271 if err := s.flowController.UpdateHighestReceived(frame.FinalSize, true); err != nil { 272 return false, err 273 } 274 newlyRcvdFinalOffset := s.finalOffset == protocol.MaxByteCount 275 s.finalOffset = frame.FinalSize 276 277 // ignore duplicate RESET_STREAM frames for this stream (after checking their final offset) 278 if s.resetRemotely { 279 return false, nil 280 } 281 s.resetRemotely = true 282 s.resetRemotelyErr = &StreamError{ 283 StreamID: s.streamID, 284 ErrorCode: frame.ErrorCode, 285 } 286 s.signalRead() 287 return newlyRcvdFinalOffset, nil 288 } 289 290 func (s *receiveStream) CloseRemote(offset protocol.ByteCount) { 291 s.handleStreamFrame(&wire.StreamFrame{Fin: true, Offset: offset}) 292 } 293 294 func (s *receiveStream) SetReadDeadline(t time.Time) error { 295 s.mutex.Lock() 296 s.deadline = t 297 s.mutex.Unlock() 298 s.signalRead() 299 return nil 300 } 301 302 // CloseForShutdown closes a stream abruptly. 303 // It makes Read unblock (and return the error) immediately. 304 // The peer will NOT be informed about this: the stream is closed without sending a FIN or RESET. 305 func (s *receiveStream) closeForShutdown(err error) { 306 s.mutex.Lock() 307 s.closedForShutdown = true 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 }