github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/gquic-go/receive_stream.go (about) 1 package gquic 2 3 import ( 4 "fmt" 5 "io" 6 "sync" 7 "time" 8 9 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/flowcontrol" 10 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/protocol" 11 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/utils" 12 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/wire" 13 ) 14 15 type receiveStreamI interface { 16 ReceiveStream 17 18 handleStreamFrame(*wire.StreamFrame) error 19 handleRstStreamFrame(*wire.RstStreamFrame) error 20 closeForShutdown(error) 21 getWindowUpdate() protocol.ByteCount 22 } 23 24 type receiveStream struct { 25 mutex sync.Mutex 26 27 streamID protocol.StreamID 28 29 sender streamSender 30 31 frameQueue *frameSorter 32 readOffset protocol.ByteCount 33 34 currentFrame []byte 35 currentFrameIsLast bool // is the currentFrame the last frame on this stream 36 readPosInFrame int 37 38 closeForShutdownErr error 39 cancelReadErr error 40 resetRemotelyErr StreamError 41 42 closedForShutdown bool // set when CloseForShutdown() is called 43 finRead bool // set once we read a frame with a FinBit 44 canceledRead bool // set when CancelRead() is called 45 resetRemotely bool // set when HandleRstStreamFrame() is called 46 47 readChan chan struct{} 48 deadline time.Time 49 50 flowController flowcontrol.StreamFlowController 51 version protocol.VersionNumber 52 } 53 54 var _ ReceiveStream = &receiveStream{} 55 var _ receiveStreamI = &receiveStream{} 56 57 func newReceiveStream( 58 streamID protocol.StreamID, 59 sender streamSender, 60 flowController flowcontrol.StreamFlowController, 61 version protocol.VersionNumber, 62 ) *receiveStream { 63 return &receiveStream{ 64 streamID: streamID, 65 sender: sender, 66 flowController: flowController, 67 frameQueue: newFrameSorter(), 68 readChan: make(chan struct{}, 1), 69 version: version, 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 completed, n, err := s.readImpl(p) 80 if completed { 81 s.sender.onStreamCompleted(s.streamID) 82 } 83 return n, err 84 } 85 86 func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, error) { 87 s.mutex.Lock() 88 defer s.mutex.Unlock() 89 90 if s.finRead { 91 return false, 0, io.EOF 92 } 93 if s.canceledRead { 94 return false, 0, s.cancelReadErr 95 } 96 if s.resetRemotely { 97 return false, 0, s.resetRemotelyErr 98 } 99 if s.closedForShutdown { 100 return false, 0, s.closeForShutdownErr 101 } 102 103 bytesRead := 0 104 for bytesRead < len(p) { 105 if s.currentFrame == nil || s.readPosInFrame >= len(s.currentFrame) { 106 s.dequeueNextFrame() 107 } 108 if s.currentFrame == nil && bytesRead > 0 { 109 return false, bytesRead, s.closeForShutdownErr 110 } 111 112 var deadlineTimer *utils.Timer 113 for { 114 // Stop waiting on errors 115 if s.closedForShutdown { 116 return false, bytesRead, s.closeForShutdownErr 117 } 118 if s.canceledRead { 119 return false, bytesRead, s.cancelReadErr 120 } 121 if s.resetRemotely { 122 return false, bytesRead, s.resetRemotelyErr 123 } 124 125 deadline := s.deadline 126 if !deadline.IsZero() { 127 if !time.Now().Before(deadline) { 128 return false, bytesRead, errDeadline 129 } 130 if deadlineTimer == nil { 131 deadlineTimer = utils.NewTimer() 132 } 133 deadlineTimer.Reset(deadline) 134 } 135 136 if s.currentFrame != nil || s.currentFrameIsLast { 137 break 138 } 139 140 s.mutex.Unlock() 141 if deadline.IsZero() { 142 <-s.readChan 143 } else { 144 select { 145 case <-s.readChan: 146 case <-deadlineTimer.Chan(): 147 deadlineTimer.SetRead() 148 } 149 } 150 s.mutex.Lock() 151 if s.currentFrame == nil { 152 s.dequeueNextFrame() 153 } 154 } 155 156 // [Psiphon] 157 // Stop timer to immediately release resources 158 if deadlineTimer != nil { 159 deadlineTimer.Reset(time.Time{}) 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 s.mutex.Unlock() 170 171 m := copy(p[bytesRead:], s.currentFrame[s.readPosInFrame:]) 172 s.readPosInFrame += m 173 bytesRead += m 174 s.readOffset += protocol.ByteCount(m) 175 176 s.mutex.Lock() 177 // when a RST_STREAM was received, the was already informed about the final byteOffset for this stream 178 if !s.resetRemotely { 179 s.flowController.AddBytesRead(protocol.ByteCount(m)) 180 } 181 // increase the flow control window, if necessary 182 if s.streamID != s.version.CryptoStreamID() { 183 s.flowController.MaybeQueueWindowUpdate() 184 } 185 186 if s.readPosInFrame >= len(s.currentFrame) && s.currentFrameIsLast { 187 s.finRead = true 188 return true, bytesRead, io.EOF 189 } 190 } 191 return false, bytesRead, nil 192 } 193 194 func (s *receiveStream) dequeueNextFrame() { 195 s.currentFrame, s.currentFrameIsLast = s.frameQueue.Pop() 196 s.readPosInFrame = 0 197 } 198 199 func (s *receiveStream) CancelRead(errorCode protocol.ApplicationErrorCode) error { 200 s.mutex.Lock() 201 defer s.mutex.Unlock() 202 203 if s.finRead { 204 return nil 205 } 206 if s.canceledRead { 207 return nil 208 } 209 s.canceledRead = true 210 s.cancelReadErr = fmt.Errorf("Read on stream %d canceled with error code %d", s.streamID, errorCode) 211 s.signalRead() 212 if s.version.UsesIETFFrameFormat() { 213 s.sender.queueControlFrame(&wire.StopSendingFrame{ 214 StreamID: s.streamID, 215 ErrorCode: errorCode, 216 }) 217 } 218 return nil 219 } 220 221 func (s *receiveStream) handleStreamFrame(frame *wire.StreamFrame) error { 222 maxOffset := frame.Offset + frame.DataLen() 223 if err := s.flowController.UpdateHighestReceived(maxOffset, frame.FinBit); err != nil { 224 return err 225 } 226 227 s.mutex.Lock() 228 defer s.mutex.Unlock() 229 if err := s.frameQueue.Push(frame.Data, frame.Offset, frame.FinBit); err != nil { 230 return err 231 } 232 s.signalRead() 233 return nil 234 } 235 236 func (s *receiveStream) handleRstStreamFrame(frame *wire.RstStreamFrame) error { 237 completed, err := s.handleRstStreamFrameImpl(frame) 238 if completed { 239 s.sender.onStreamCompleted(s.streamID) 240 } 241 return err 242 } 243 244 func (s *receiveStream) handleRstStreamFrameImpl(frame *wire.RstStreamFrame) (bool /*completed */, error) { 245 s.mutex.Lock() 246 defer s.mutex.Unlock() 247 248 if s.closedForShutdown { 249 return false, nil 250 } 251 if err := s.flowController.UpdateHighestReceived(frame.ByteOffset, true); err != nil { 252 return false, err 253 } 254 // In gQUIC, error code 0 has a special meaning. 255 // The peer will reliably continue transmitting, but is not interested in reading from the stream. 256 // We should therefore just continue reading from the stream, until we encounter the FIN bit. 257 if !s.version.UsesIETFFrameFormat() && frame.ErrorCode == 0 { 258 return false, nil 259 } 260 261 // ignore duplicate RST_STREAM frames for this stream (after checking their final offset) 262 if s.resetRemotely { 263 return false, nil 264 } 265 s.resetRemotely = true 266 s.resetRemotelyErr = streamCanceledError{ 267 errorCode: frame.ErrorCode, 268 error: fmt.Errorf("Stream %d was reset with error code %d", s.streamID, frame.ErrorCode), 269 } 270 s.signalRead() 271 return true, nil 272 } 273 274 func (s *receiveStream) CloseRemote(offset protocol.ByteCount) { 275 s.handleStreamFrame(&wire.StreamFrame{FinBit: true, Offset: offset}) 276 } 277 278 func (s *receiveStream) onClose(offset protocol.ByteCount) { 279 280 // [Psiphon] 281 // Fix race condition. 282 s.mutex.Lock() 283 canceledRead := s.canceledRead 284 s.mutex.Unlock() 285 // [Psiphon] 286 287 if canceledRead && !s.version.UsesIETFFrameFormat() { 288 s.sender.queueControlFrame(&wire.RstStreamFrame{ 289 StreamID: s.streamID, 290 ByteOffset: offset, 291 ErrorCode: 0, 292 }) 293 } 294 } 295 296 func (s *receiveStream) SetReadDeadline(t time.Time) error { 297 s.mutex.Lock() 298 s.deadline = t 299 s.mutex.Unlock() 300 s.signalRead() 301 return nil 302 } 303 304 // CloseForShutdown closes a stream abruptly. 305 // It makes Read unblock (and return the error) immediately. 306 // The peer will NOT be informed about this: the stream is closed without sending a FIN or RST. 307 func (s *receiveStream) closeForShutdown(err error) { 308 s.mutex.Lock() 309 s.closedForShutdown = true 310 s.closeForShutdownErr = err 311 s.mutex.Unlock() 312 s.signalRead() 313 } 314 315 func (s *receiveStream) getWindowUpdate() protocol.ByteCount { 316 return s.flowController.GetWindowUpdate() 317 } 318 319 // signalRead performs a non-blocking send on the readChan 320 func (s *receiveStream) signalRead() { 321 select { 322 case s.readChan <- struct{}{}: 323 default: 324 } 325 }