github.com/TugasAkhir-QUIC/quic-go@v0.0.2-0.20240215011318-d20e25a9054c/send_stream.go (about) 1 package quic 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 "time" 8 9 "github.com/TugasAkhir-QUIC/quic-go/internal/ackhandler" 10 "github.com/TugasAkhir-QUIC/quic-go/internal/flowcontrol" 11 "github.com/TugasAkhir-QUIC/quic-go/internal/protocol" 12 "github.com/TugasAkhir-QUIC/quic-go/internal/qerr" 13 "github.com/TugasAkhir-QUIC/quic-go/internal/utils" 14 "github.com/TugasAkhir-QUIC/quic-go/internal/wire" 15 ) 16 17 type sendStreamI interface { 18 SendStream 19 handleStopSendingFrame(*wire.StopSendingFrame) 20 hasData() bool 21 popStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (frame ackhandler.StreamFrame, ok, hasMore bool) 22 closeForShutdown(error) 23 updateSendWindow(protocol.ByteCount) 24 getPriority() int 25 } 26 27 type sendStream struct { 28 mutex sync.Mutex 29 30 numOutstandingFrames int64 31 retransmissionQueue []*wire.StreamFrame 32 33 ctx context.Context 34 ctxCancel context.CancelCauseFunc 35 36 streamID protocol.StreamID 37 sender streamSender 38 39 writeOffset protocol.ByteCount 40 41 cancelWriteErr error 42 closeForShutdownErr error 43 44 finishedWriting bool // set once Close() is called 45 finSent bool // set when a STREAM_FRAME with FIN bit has been sent 46 completed bool // set when this stream has been reported to the streamSender as completed 47 48 dataForWriting []byte // during a Write() call, this slice is the part of p that still needs to be sent out 49 nextFrame *wire.StreamFrame 50 51 writeChan chan struct{} 52 writeOnce chan struct{} 53 deadline time.Time 54 55 flowController flowcontrol.StreamFlowController 56 57 priority int 58 } 59 60 var ( 61 _ SendStream = &sendStream{} 62 _ sendStreamI = &sendStream{} 63 ) 64 65 func newSendStream( 66 streamID protocol.StreamID, 67 sender streamSender, 68 flowController flowcontrol.StreamFlowController, 69 ) *sendStream { 70 s := &sendStream{ 71 streamID: streamID, 72 sender: sender, 73 flowController: flowController, 74 writeChan: make(chan struct{}, 1), 75 writeOnce: make(chan struct{}, 1), // cap: 1, to protect against concurrent use of Write 76 } 77 s.ctx, s.ctxCancel = context.WithCancelCause(context.Background()) 78 return s 79 } 80 81 func (s *sendStream) StreamID() protocol.StreamID { 82 return s.streamID // same for receiveStream and sendStream 83 } 84 85 func (s *sendStream) Write(p []byte) (int, error) { 86 // Concurrent use of Write is not permitted (and doesn't make any sense), 87 // but sometimes people do it anyway. 88 // Make sure that we only execute one call at any given time to avoid hard to debug failures. 89 s.writeOnce <- struct{}{} 90 defer func() { <-s.writeOnce }() 91 92 s.mutex.Lock() 93 defer s.mutex.Unlock() 94 95 if s.finishedWriting { 96 return 0, fmt.Errorf("write on closed stream %d", s.streamID) 97 } 98 if s.cancelWriteErr != nil { 99 return 0, s.cancelWriteErr 100 } 101 if s.closeForShutdownErr != nil { 102 return 0, s.closeForShutdownErr 103 } 104 if !s.deadline.IsZero() && !time.Now().Before(s.deadline) { 105 return 0, errDeadline 106 } 107 if len(p) == 0 { 108 return 0, nil 109 } 110 111 s.dataForWriting = p 112 113 var ( 114 deadlineTimer *utils.Timer 115 bytesWritten int 116 notifiedSender bool 117 ) 118 for { 119 var copied bool 120 var deadline time.Time 121 // As soon as dataForWriting becomes smaller than a certain size x, we copy all the data to a STREAM frame (s.nextFrame), 122 // which can then be popped the next time we assemble a packet. 123 // This allows us to return Write() when all data but x bytes have been sent out. 124 // When the user now calls Close(), this is much more likely to happen before we popped that last STREAM frame, 125 // allowing us to set the FIN bit on that frame (instead of sending an empty STREAM frame with FIN). 126 if s.canBufferStreamFrame() && len(s.dataForWriting) > 0 { 127 if s.nextFrame == nil { 128 f := wire.GetStreamFrame() 129 f.Offset = s.writeOffset 130 f.StreamID = s.streamID 131 f.DataLenPresent = true 132 f.Data = f.Data[:len(s.dataForWriting)] 133 copy(f.Data, s.dataForWriting) 134 s.nextFrame = f 135 } else { 136 l := len(s.nextFrame.Data) 137 s.nextFrame.Data = s.nextFrame.Data[:l+len(s.dataForWriting)] 138 copy(s.nextFrame.Data[l:], s.dataForWriting) 139 } 140 s.dataForWriting = nil 141 bytesWritten = len(p) 142 copied = true 143 } else { 144 bytesWritten = len(p) - len(s.dataForWriting) 145 deadline = s.deadline 146 if !deadline.IsZero() { 147 if !time.Now().Before(deadline) { 148 s.dataForWriting = nil 149 return bytesWritten, errDeadline 150 } 151 if deadlineTimer == nil { 152 deadlineTimer = utils.NewTimer() 153 defer deadlineTimer.Stop() 154 } 155 deadlineTimer.Reset(deadline) 156 } 157 if s.dataForWriting == nil || s.cancelWriteErr != nil || s.closeForShutdownErr != nil { 158 break 159 } 160 } 161 162 s.mutex.Unlock() 163 if !notifiedSender { 164 s.sender.onHasStreamData(s.streamID) // must be called without holding the mutex 165 notifiedSender = true 166 } 167 if copied { 168 s.mutex.Lock() 169 break 170 } 171 if deadline.IsZero() { 172 <-s.writeChan 173 } else { 174 select { 175 case <-s.writeChan: 176 case <-deadlineTimer.Chan(): 177 deadlineTimer.SetRead() 178 } 179 } 180 s.mutex.Lock() 181 } 182 183 if bytesWritten == len(p) { 184 return bytesWritten, nil 185 } 186 if s.closeForShutdownErr != nil { 187 return bytesWritten, s.closeForShutdownErr 188 } else if s.cancelWriteErr != nil { 189 return bytesWritten, s.cancelWriteErr 190 } 191 return bytesWritten, nil 192 } 193 194 func (s *sendStream) canBufferStreamFrame() bool { 195 var l protocol.ByteCount 196 if s.nextFrame != nil { 197 l = s.nextFrame.DataLen() 198 } 199 return l+protocol.ByteCount(len(s.dataForWriting)) <= protocol.MaxPacketBufferSize 200 } 201 202 // popStreamFrame returns the next STREAM frame that is supposed to be sent on this stream 203 // maxBytes is the maximum length this frame (including frame header) will have. 204 func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (af ackhandler.StreamFrame, ok, hasMore bool) { 205 s.mutex.Lock() 206 f, hasMoreData := s.popNewOrRetransmittedStreamFrame(maxBytes, v) 207 if f != nil { 208 s.numOutstandingFrames++ 209 } 210 s.mutex.Unlock() 211 212 if f == nil { 213 return ackhandler.StreamFrame{}, false, hasMoreData 214 } 215 return ackhandler.StreamFrame{ 216 Frame: f, 217 Handler: (*sendStreamAckHandler)(s), 218 }, true, hasMoreData 219 } 220 221 func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (*wire.StreamFrame, bool /* has more data to send */) { 222 if s.cancelWriteErr != nil || s.closeForShutdownErr != nil { 223 return nil, false 224 } 225 226 if len(s.retransmissionQueue) > 0 { 227 f, hasMoreRetransmissions := s.maybeGetRetransmission(maxBytes, v) 228 if f != nil || hasMoreRetransmissions { 229 if f == nil { 230 return nil, true 231 } 232 // We always claim that we have more data to send. 233 // This might be incorrect, in which case there'll be a spurious call to popStreamFrame in the future. 234 return f, true 235 } 236 } 237 238 if len(s.dataForWriting) == 0 && s.nextFrame == nil { 239 if s.finishedWriting && !s.finSent { 240 s.finSent = true 241 return &wire.StreamFrame{ 242 StreamID: s.streamID, 243 Offset: s.writeOffset, 244 DataLenPresent: true, 245 Fin: true, 246 }, false 247 } 248 return nil, false 249 } 250 251 sendWindow := s.flowController.SendWindowSize() 252 if sendWindow == 0 { 253 if isBlocked, offset := s.flowController.IsNewlyBlocked(); isBlocked { 254 s.sender.queueControlFrame(&wire.StreamDataBlockedFrame{ 255 StreamID: s.streamID, 256 MaximumStreamData: offset, 257 }) 258 return nil, false 259 } 260 return nil, true 261 } 262 263 f, hasMoreData := s.popNewStreamFrame(maxBytes, sendWindow, v) 264 if dataLen := f.DataLen(); dataLen > 0 { 265 s.writeOffset += f.DataLen() 266 s.flowController.AddBytesSent(f.DataLen()) 267 } 268 f.Fin = s.finishedWriting && s.dataForWriting == nil && s.nextFrame == nil && !s.finSent 269 if f.Fin { 270 s.finSent = true 271 } 272 return f, hasMoreData 273 } 274 275 func (s *sendStream) popNewStreamFrame(maxBytes, sendWindow protocol.ByteCount, v protocol.Version) (*wire.StreamFrame, bool) { 276 if s.nextFrame != nil { 277 nextFrame := s.nextFrame 278 s.nextFrame = nil 279 280 maxDataLen := min(sendWindow, nextFrame.MaxDataLen(maxBytes, v)) 281 if nextFrame.DataLen() > maxDataLen { 282 s.nextFrame = wire.GetStreamFrame() 283 s.nextFrame.StreamID = s.streamID 284 s.nextFrame.Offset = s.writeOffset + maxDataLen 285 s.nextFrame.Data = s.nextFrame.Data[:nextFrame.DataLen()-maxDataLen] 286 s.nextFrame.DataLenPresent = true 287 copy(s.nextFrame.Data, nextFrame.Data[maxDataLen:]) 288 nextFrame.Data = nextFrame.Data[:maxDataLen] 289 } else { 290 s.signalWrite() 291 } 292 return nextFrame, s.nextFrame != nil || s.dataForWriting != nil 293 } 294 295 f := wire.GetStreamFrame() 296 f.Fin = false 297 f.StreamID = s.streamID 298 f.Offset = s.writeOffset 299 f.DataLenPresent = true 300 f.Data = f.Data[:0] 301 302 hasMoreData := s.popNewStreamFrameWithoutBuffer(f, maxBytes, sendWindow, v) 303 if len(f.Data) == 0 && !f.Fin { 304 f.PutBack() 305 return nil, hasMoreData 306 } 307 return f, hasMoreData 308 } 309 310 func (s *sendStream) popNewStreamFrameWithoutBuffer(f *wire.StreamFrame, maxBytes, sendWindow protocol.ByteCount, v protocol.Version) bool { 311 maxDataLen := f.MaxDataLen(maxBytes, v) 312 if maxDataLen == 0 { // a STREAM frame must have at least one byte of data 313 return s.dataForWriting != nil || s.nextFrame != nil || s.finishedWriting 314 } 315 s.getDataForWriting(f, min(maxDataLen, sendWindow)) 316 317 return s.dataForWriting != nil || s.nextFrame != nil || s.finishedWriting 318 } 319 320 func (s *sendStream) maybeGetRetransmission(maxBytes protocol.ByteCount, v protocol.Version) (*wire.StreamFrame, bool /* has more retransmissions */) { 321 f := s.retransmissionQueue[0] 322 newFrame, needsSplit := f.MaybeSplitOffFrame(maxBytes, v) 323 if needsSplit { 324 return newFrame, true 325 } 326 s.retransmissionQueue = s.retransmissionQueue[1:] 327 return f, len(s.retransmissionQueue) > 0 328 } 329 330 func (s *sendStream) hasData() bool { 331 s.mutex.Lock() 332 hasData := len(s.dataForWriting) > 0 333 s.mutex.Unlock() 334 return hasData 335 } 336 337 func (s *sendStream) getDataForWriting(f *wire.StreamFrame, maxBytes protocol.ByteCount) { 338 if protocol.ByteCount(len(s.dataForWriting)) <= maxBytes { 339 f.Data = f.Data[:len(s.dataForWriting)] 340 copy(f.Data, s.dataForWriting) 341 s.dataForWriting = nil 342 s.signalWrite() 343 return 344 } 345 f.Data = f.Data[:maxBytes] 346 copy(f.Data, s.dataForWriting) 347 s.dataForWriting = s.dataForWriting[maxBytes:] 348 if s.canBufferStreamFrame() { 349 s.signalWrite() 350 } 351 } 352 353 func (s *sendStream) isNewlyCompleted() bool { 354 completed := (s.finSent || s.cancelWriteErr != nil) && s.numOutstandingFrames == 0 && len(s.retransmissionQueue) == 0 355 if completed && !s.completed { 356 s.completed = true 357 return true 358 } 359 return false 360 } 361 362 func (s *sendStream) Close() error { 363 s.mutex.Lock() 364 if s.closeForShutdownErr != nil { 365 s.mutex.Unlock() 366 return nil 367 } 368 if s.cancelWriteErr != nil { 369 s.mutex.Unlock() 370 return fmt.Errorf("close called for canceled stream %d", s.streamID) 371 } 372 s.ctxCancel(nil) 373 s.finishedWriting = true 374 s.mutex.Unlock() 375 376 s.sender.onHasStreamData(s.streamID) // need to send the FIN, must be called without holding the mutex 377 return nil 378 } 379 380 func (s *sendStream) CancelWrite(errorCode StreamErrorCode) { 381 s.cancelWriteImpl(errorCode, false) 382 } 383 384 // must be called after locking the mutex 385 func (s *sendStream) cancelWriteImpl(errorCode qerr.StreamErrorCode, remote bool) { 386 s.mutex.Lock() 387 if s.cancelWriteErr != nil { 388 s.mutex.Unlock() 389 return 390 } 391 s.cancelWriteErr = &StreamError{StreamID: s.streamID, ErrorCode: errorCode, Remote: remote} 392 s.ctxCancel(s.cancelWriteErr) 393 s.numOutstandingFrames = 0 394 s.retransmissionQueue = nil 395 newlyCompleted := s.isNewlyCompleted() 396 s.mutex.Unlock() 397 398 s.signalWrite() 399 s.sender.queueControlFrame(&wire.ResetStreamFrame{ 400 StreamID: s.streamID, 401 FinalSize: s.writeOffset, 402 ErrorCode: errorCode, 403 }) 404 if newlyCompleted { 405 s.sender.onStreamCompleted(s.streamID) 406 } 407 } 408 409 func (s *sendStream) updateSendWindow(limit protocol.ByteCount) { 410 updated := s.flowController.UpdateSendWindow(limit) 411 if !updated { // duplicate or reordered MAX_STREAM_DATA frame 412 return 413 } 414 s.mutex.Lock() 415 hasStreamData := s.dataForWriting != nil || s.nextFrame != nil 416 s.mutex.Unlock() 417 if hasStreamData { 418 s.sender.onHasStreamData(s.streamID) 419 } 420 } 421 422 func (s *sendStream) handleStopSendingFrame(frame *wire.StopSendingFrame) { 423 s.cancelWriteImpl(frame.ErrorCode, true) 424 } 425 426 func (s *sendStream) Context() context.Context { 427 return s.ctx 428 } 429 430 func (s *sendStream) SetWriteDeadline(t time.Time) error { 431 s.mutex.Lock() 432 s.deadline = t 433 s.mutex.Unlock() 434 s.signalWrite() 435 return nil 436 } 437 438 // CloseForShutdown closes a stream abruptly. 439 // It makes Write unblock (and return the error) immediately. 440 // The peer will NOT be informed about this: the stream is closed without sending a FIN or RST. 441 func (s *sendStream) closeForShutdown(err error) { 442 s.mutex.Lock() 443 s.ctxCancel(err) 444 s.closeForShutdownErr = err 445 s.mutex.Unlock() 446 s.signalWrite() 447 } 448 449 // signalWrite performs a non-blocking send on the writeChan 450 func (s *sendStream) signalWrite() { 451 select { 452 case s.writeChan <- struct{}{}: 453 default: 454 } 455 } 456 457 type sendStreamAckHandler sendStream 458 459 var _ ackhandler.FrameHandler = &sendStreamAckHandler{} 460 461 func (s *sendStreamAckHandler) OnAcked(f wire.Frame) { 462 sf := f.(*wire.StreamFrame) 463 sf.PutBack() 464 s.mutex.Lock() 465 if s.cancelWriteErr != nil { 466 s.mutex.Unlock() 467 return 468 } 469 s.numOutstandingFrames-- 470 if s.numOutstandingFrames < 0 { 471 panic("numOutStandingFrames negative") 472 } 473 newlyCompleted := (*sendStream)(s).isNewlyCompleted() 474 s.mutex.Unlock() 475 476 if newlyCompleted { 477 s.sender.onStreamCompleted(s.streamID) 478 } 479 } 480 481 func (s *sendStreamAckHandler) OnLost(f wire.Frame) { 482 sf := f.(*wire.StreamFrame) 483 s.mutex.Lock() 484 if s.cancelWriteErr != nil { 485 s.mutex.Unlock() 486 return 487 } 488 sf.DataLenPresent = true 489 s.retransmissionQueue = append(s.retransmissionQueue, sf) 490 s.numOutstandingFrames-- 491 if s.numOutstandingFrames < 0 { 492 panic("numOutStandingFrames negative") 493 } 494 s.mutex.Unlock() 495 496 s.sender.onHasStreamData(s.streamID) 497 } 498 499 func (s *sendStream) getPriority() int { 500 return s.priority 501 } 502 503 func (s *sendStream) SetPriority(priority int) { 504 s.priority = priority 505 }