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  }