github.com/TugasAkhir-QUIC/quic-go@v0.0.2-0.20240215011318-d20e25a9054c/framer.go (about)

     1  package quic
     2  
     3  import (
     4  	"errors"
     5  	"sort"
     6  	"sync"
     7  
     8  	"github.com/TugasAkhir-QUIC/quic-go/internal/ackhandler"
     9  	"github.com/TugasAkhir-QUIC/quic-go/internal/protocol"
    10  	"github.com/TugasAkhir-QUIC/quic-go/internal/wire"
    11  	"github.com/TugasAkhir-QUIC/quic-go/quicvarint"
    12  )
    13  
    14  type framer interface {
    15  	HasData() bool
    16  
    17  	QueueControlFrame(wire.Frame)
    18  	AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.Version) ([]ackhandler.Frame, protocol.ByteCount)
    19  
    20  	AddActiveStream(protocol.StreamID)
    21  	AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount)
    22  
    23  	Handle0RTTRejection() error
    24  }
    25  
    26  const maxPathResponses = 256
    27  
    28  type framerI struct {
    29  	mutex sync.Mutex
    30  
    31  	streamGetter streamGetter
    32  
    33  	activeStreams map[protocol.StreamID]struct{}
    34  	//streamQueue   ringbuffer.RingBuffer[protocol.StreamID]
    35  	streamQueue []protocol.StreamID
    36  
    37  	controlFrameMutex sync.Mutex
    38  	controlFrames     []wire.Frame
    39  	pathResponses     []*wire.PathResponseFrame
    40  }
    41  
    42  var _ framer = &framerI{}
    43  
    44  func newFramer(streamGetter streamGetter) framer {
    45  	return &framerI{
    46  		streamGetter:  streamGetter,
    47  		activeStreams: make(map[protocol.StreamID]struct{}),
    48  	}
    49  }
    50  
    51  func (f *framerI) HasData() bool {
    52  	f.mutex.Lock()
    53  	hasData := len(f.streamQueue) > 0
    54  	f.mutex.Unlock()
    55  	if hasData {
    56  		return true
    57  	}
    58  	f.controlFrameMutex.Lock()
    59  	defer f.controlFrameMutex.Unlock()
    60  	return len(f.controlFrames) > 0 || len(f.pathResponses) > 0
    61  }
    62  
    63  func (f *framerI) QueueControlFrame(frame wire.Frame) {
    64  	f.controlFrameMutex.Lock()
    65  	defer f.controlFrameMutex.Unlock()
    66  
    67  	if pr, ok := frame.(*wire.PathResponseFrame); ok {
    68  		// Only queue up to maxPathResponses PATH_RESPONSE frames.
    69  		// This limit should be high enough to never be hit in practice,
    70  		// unless the peer is doing something malicious.
    71  		if len(f.pathResponses) >= maxPathResponses {
    72  			return
    73  		}
    74  		f.pathResponses = append(f.pathResponses, pr)
    75  		return
    76  	}
    77  	f.controlFrames = append(f.controlFrames, frame)
    78  }
    79  
    80  func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) {
    81  	f.controlFrameMutex.Lock()
    82  	defer f.controlFrameMutex.Unlock()
    83  
    84  	var length protocol.ByteCount
    85  	// add a PATH_RESPONSE first, but only pack a single PATH_RESPONSE per packet
    86  	if len(f.pathResponses) > 0 {
    87  		frame := f.pathResponses[0]
    88  		frameLen := frame.Length(v)
    89  		if frameLen <= maxLen {
    90  			frames = append(frames, ackhandler.Frame{Frame: frame})
    91  			length += frameLen
    92  			f.pathResponses = f.pathResponses[1:]
    93  		}
    94  	}
    95  
    96  	for len(f.controlFrames) > 0 {
    97  		frame := f.controlFrames[len(f.controlFrames)-1]
    98  		frameLen := frame.Length(v)
    99  		if length+frameLen > maxLen {
   100  			break
   101  		}
   102  		frames = append(frames, ackhandler.Frame{Frame: frame})
   103  		length += frameLen
   104  		f.controlFrames = f.controlFrames[:len(f.controlFrames)-1]
   105  	}
   106  	return frames, length
   107  }
   108  
   109  func (f *framerI) AddActiveStream(id protocol.StreamID) {
   110  	f.mutex.Lock()
   111  	if _, ok := f.activeStreams[id]; !ok {
   112  		f.streamQueue = append(f.streamQueue, id)
   113  		f.activeStreams[id] = struct{}{}
   114  		f.sortQueue()
   115  	}
   116  	f.mutex.Unlock()
   117  }
   118  
   119  func (f *framerI) sortQueue() {
   120  	// Sort the queue by descending priority order
   121  	sort.SliceStable(f.streamQueue, func(i int, j int) bool {
   122  		str1, err := f.streamGetter.GetOrOpenSendStream(f.streamQueue[i])
   123  		if str1 == nil || err != nil {
   124  			return false // Push to the front so we can pop it
   125  		}
   126  
   127  		str2, err := f.streamGetter.GetOrOpenSendStream(f.streamQueue[j])
   128  		if str2 == nil || err != nil {
   129  			return true // Push to the front so we can pop it
   130  		}
   131  
   132  		return str1.getPriority() > str2.getPriority()
   133  	})
   134  }
   135  
   136  func (f *framerI) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen protocol.ByteCount, v protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) {
   137  	startLen := len(frames)
   138  	var length protocol.ByteCount
   139  	f.mutex.Lock()
   140  
   141  	// TODO perform this sort when SetPriority() is called
   142  	f.sortQueue()
   143  
   144  	// Record information about streams with the same priority
   145  	priorityCurrent := 0 // The current priority value
   146  	prioritySent := 0    // The number of sent streams with this priority
   147  	priorityUnsent := 0  // The number of unsent streams with this priority
   148  
   149  	i := 0
   150  
   151  	// pop STREAM frames, until less than MinStreamFrameSize bytes are left in the packet
   152  	for i < len(f.streamQueue) {
   153  		id := f.streamQueue[i]
   154  		// This should never return an error. Better check it anyway.
   155  		// The stream will only be in the streamQueue, if it enqueued itself there.
   156  		str, err := f.streamGetter.GetOrOpenSendStream(id)
   157  		// The stream can be nil if it completed after it said it had data.
   158  		if str == nil || err != nil {
   159  			delete(f.activeStreams, id)
   160  
   161  			// Shift the remaining elements in the queue forward
   162  			copy(f.streamQueue[i:], f.streamQueue[i+1:])
   163  			f.streamQueue = f.streamQueue[:len(f.streamQueue)-1]
   164  
   165  			// Don't increment i since we just removed an element
   166  			continue
   167  		}
   168  
   169  		// Get the priority for the current stream
   170  		priority := str.getPriority()
   171  		full := protocol.MinStreamFrameSize+length > maxLen
   172  		if full {
   173  			// If we're full, see if the previous streams had the same priority
   174  			if priority != priorityCurrent {
   175  				// We can stop interating since we've found all streams with the same priority
   176  				break
   177  			}
   178  
   179  			// Keep looping until this is no longer the case.
   180  			priorityUnsent += 1
   181  			i += 1
   182  
   183  			continue
   184  		}
   185  
   186  		// See if the previous streams had the same priority
   187  		if i == 0 || priority != priorityCurrent {
   188  			// We just sent a new priority level; reset our counters
   189  			priorityCurrent = priority
   190  			priorityUnsent = 0
   191  			prioritySent = 0
   192  		}
   193  
   194  		remainingLen := maxLen - length
   195  		// For the last STREAM frame, we'll remove the DataLen field later.
   196  		// Therefore, we can pretend to have more bytes available when popping
   197  		// the STREAM frame (which will always have the DataLen set).
   198  		remainingLen += quicvarint.Len(uint64(remainingLen))
   199  
   200  		frame, ok, hasMoreData := str.popStreamFrame(remainingLen, v)
   201  		// The frame can be "nil"
   202  		// * if the receiveStream was canceled after it said it had data
   203  		// * the remaining size doesn't allow us to add another STREAM frame
   204  		if ok {
   205  			frames = append(frames, frame)
   206  			length += frame.Frame.Length(v)
   207  		}
   208  		if !hasMoreData {
   209  			// no more data to send. Stream is not active any more
   210  			delete(f.activeStreams, id)
   211  
   212  			// Shift the remaining elements in the queue forward
   213  			copy(f.streamQueue[i:], f.streamQueue[i+1:])
   214  			f.streamQueue = f.streamQueue[:len(f.streamQueue)-1]
   215  
   216  			// Don't increment i since we just removed an element
   217  			continue
   218  		}
   219  
   220  		i += 1
   221  		prioritySent += 1
   222  	}
   223  
   224  	if priorityUnsent > 0 && prioritySent > 0 {
   225  		// There were some streams sent and some streams unsent within the same priority.
   226  		// We want to swap the last `priorityUnsent` values with the prior `prioritySent` values.
   227  		// This way we will round-robin streams with the same priority.
   228  		swap := make([]protocol.StreamID, prioritySent)
   229  
   230  		end := i
   231  		middle := end - priorityUnsent
   232  		start := middle - prioritySent
   233  
   234  		copy(swap, f.streamQueue[start:middle+1])
   235  		copy(f.streamQueue[start:], f.streamQueue[middle:end])
   236  		copy(f.streamQueue[end-len(swap):], swap)
   237  
   238  		// Example:
   239  		// i = 7
   240  		// streamQueue (priority): [ 7, 7, 5, 5, 5, 5, 5, 2, 2 ]
   241  		// priorityUnset = 3
   242  		// prioritySent = 2
   243  
   244  		// We want to move index 2,3 to index 5,6 and index 4,5,6 to index 2,3,4
   245  		// end = 7
   246  		// middle = 4
   247  		// start = 2
   248  
   249  		// copy(swap, queue[2:5])
   250  		// copy(queue[2:], queue[4:7])
   251  		// copy(queue[5:], swap)
   252  	}
   253  
   254  	f.mutex.Unlock()
   255  	if len(frames) > startLen {
   256  		l := frames[len(frames)-1].Frame.Length(v)
   257  		// account for the smaller size of the last STREAM frame
   258  		frames[len(frames)-1].Frame.DataLenPresent = false
   259  		length += frames[len(frames)-1].Frame.Length(v) - l
   260  	}
   261  
   262  	return frames, length
   263  }
   264  
   265  func (f *framerI) Handle0RTTRejection() error {
   266  	f.mutex.Lock()
   267  	defer f.mutex.Unlock()
   268  
   269  	f.controlFrameMutex.Lock()
   270  	f.streamQueue = f.streamQueue[:0]
   271  	for id := range f.activeStreams {
   272  		delete(f.activeStreams, id)
   273  	}
   274  	var j int
   275  	for i, frame := range f.controlFrames {
   276  		switch frame.(type) {
   277  		case *wire.MaxDataFrame, *wire.MaxStreamDataFrame, *wire.MaxStreamsFrame:
   278  			return errors.New("didn't expect MAX_DATA / MAX_STREAM_DATA / MAX_STREAMS frame to be sent in 0-RTT")
   279  		case *wire.DataBlockedFrame, *wire.StreamDataBlockedFrame, *wire.StreamsBlockedFrame:
   280  			continue
   281  		default:
   282  			f.controlFrames[j] = f.controlFrames[i]
   283  			j++
   284  		}
   285  	}
   286  	f.controlFrames = f.controlFrames[:j]
   287  	f.controlFrameMutex.Unlock()
   288  	return nil
   289  }