github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/retransmission_queue.go (about)

     1  package quic
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/ackhandler"
     7  
     8  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol"
     9  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/wire"
    10  )
    11  
    12  type retransmissionQueue struct {
    13  	initial           []wire.Frame
    14  	initialCryptoData []*wire.CryptoFrame
    15  
    16  	handshake           []wire.Frame
    17  	handshakeCryptoData []*wire.CryptoFrame
    18  
    19  	appData []wire.Frame
    20  }
    21  
    22  func newRetransmissionQueue() *retransmissionQueue {
    23  	return &retransmissionQueue{}
    24  }
    25  
    26  // AddPing queues a ping.
    27  // It is used when a probe packet needs to be sent
    28  func (q *retransmissionQueue) AddPing(encLevel protocol.EncryptionLevel) {
    29  	//nolint:exhaustive // Cannot send probe packets for 0-RTT.
    30  	switch encLevel {
    31  	case protocol.EncryptionInitial:
    32  		q.addInitial(&wire.PingFrame{})
    33  	case protocol.EncryptionHandshake:
    34  		q.addHandshake(&wire.PingFrame{})
    35  	case protocol.Encryption1RTT:
    36  		q.addAppData(&wire.PingFrame{})
    37  	default:
    38  		panic("unexpected encryption level")
    39  	}
    40  }
    41  
    42  func (q *retransmissionQueue) addInitial(f wire.Frame) {
    43  	if cf, ok := f.(*wire.CryptoFrame); ok {
    44  		q.initialCryptoData = append(q.initialCryptoData, cf)
    45  		return
    46  	}
    47  	q.initial = append(q.initial, f)
    48  }
    49  
    50  func (q *retransmissionQueue) addHandshake(f wire.Frame) {
    51  	if cf, ok := f.(*wire.CryptoFrame); ok {
    52  		q.handshakeCryptoData = append(q.handshakeCryptoData, cf)
    53  		return
    54  	}
    55  	q.handshake = append(q.handshake, f)
    56  }
    57  
    58  func (q *retransmissionQueue) HasInitialData() bool {
    59  	return len(q.initialCryptoData) > 0 || len(q.initial) > 0
    60  }
    61  
    62  func (q *retransmissionQueue) HasHandshakeData() bool {
    63  	return len(q.handshakeCryptoData) > 0 || len(q.handshake) > 0
    64  }
    65  
    66  func (q *retransmissionQueue) HasAppData() bool {
    67  	return len(q.appData) > 0
    68  }
    69  
    70  func (q *retransmissionQueue) addAppData(f wire.Frame) {
    71  	if _, ok := f.(*wire.StreamFrame); ok {
    72  		panic("STREAM frames are handled with their respective streams.")
    73  	}
    74  	q.appData = append(q.appData, f)
    75  }
    76  
    77  func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
    78  	if len(q.initialCryptoData) > 0 {
    79  		f := q.initialCryptoData[0]
    80  		newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, v)
    81  		if newFrame == nil && !needsSplit { // the whole frame fits
    82  			q.initialCryptoData = q.initialCryptoData[1:]
    83  			return f
    84  		}
    85  		if newFrame != nil { // frame was split. Leave the original frame in the queue.
    86  			return newFrame
    87  		}
    88  	}
    89  	if len(q.initial) == 0 {
    90  		return nil
    91  	}
    92  	f := q.initial[0]
    93  	if f.Length(v) > maxLen {
    94  		return nil
    95  	}
    96  	q.initial = q.initial[1:]
    97  	return f
    98  }
    99  
   100  func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
   101  	if len(q.handshakeCryptoData) > 0 {
   102  		f := q.handshakeCryptoData[0]
   103  		newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, v)
   104  		if newFrame == nil && !needsSplit { // the whole frame fits
   105  			q.handshakeCryptoData = q.handshakeCryptoData[1:]
   106  			return f
   107  		}
   108  		if newFrame != nil { // frame was split. Leave the original frame in the queue.
   109  			return newFrame
   110  		}
   111  	}
   112  	if len(q.handshake) == 0 {
   113  		return nil
   114  	}
   115  	f := q.handshake[0]
   116  	if f.Length(v) > maxLen {
   117  		return nil
   118  	}
   119  	q.handshake = q.handshake[1:]
   120  	return f
   121  }
   122  
   123  func (q *retransmissionQueue) GetAppDataFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
   124  	if len(q.appData) == 0 {
   125  		return nil
   126  	}
   127  	f := q.appData[0]
   128  	if f.Length(v) > maxLen {
   129  		return nil
   130  	}
   131  	q.appData = q.appData[1:]
   132  	return f
   133  }
   134  
   135  func (q *retransmissionQueue) DropPackets(encLevel protocol.EncryptionLevel) {
   136  	//nolint:exhaustive // Can only drop Initial and Handshake packet number space.
   137  	switch encLevel {
   138  	case protocol.EncryptionInitial:
   139  		q.initial = nil
   140  		q.initialCryptoData = nil
   141  	case protocol.EncryptionHandshake:
   142  		q.handshake = nil
   143  		q.handshakeCryptoData = nil
   144  	default:
   145  		panic(fmt.Sprintf("unexpected encryption level: %s", encLevel))
   146  	}
   147  }
   148  
   149  func (q *retransmissionQueue) InitialAckHandler() ackhandler.FrameHandler {
   150  	return (*retransmissionQueueInitialAckHandler)(q)
   151  }
   152  
   153  func (q *retransmissionQueue) HandshakeAckHandler() ackhandler.FrameHandler {
   154  	return (*retransmissionQueueHandshakeAckHandler)(q)
   155  }
   156  
   157  func (q *retransmissionQueue) AppDataAckHandler() ackhandler.FrameHandler {
   158  	return (*retransmissionQueueAppDataAckHandler)(q)
   159  }
   160  
   161  type retransmissionQueueInitialAckHandler retransmissionQueue
   162  
   163  func (q *retransmissionQueueInitialAckHandler) OnAcked(wire.Frame) {}
   164  func (q *retransmissionQueueInitialAckHandler) OnLost(f wire.Frame) {
   165  	(*retransmissionQueue)(q).addInitial(f)
   166  }
   167  
   168  type retransmissionQueueHandshakeAckHandler retransmissionQueue
   169  
   170  func (q *retransmissionQueueHandshakeAckHandler) OnAcked(wire.Frame) {}
   171  func (q *retransmissionQueueHandshakeAckHandler) OnLost(f wire.Frame) {
   172  	(*retransmissionQueue)(q).addHandshake(f)
   173  }
   174  
   175  type retransmissionQueueAppDataAckHandler retransmissionQueue
   176  
   177  func (q *retransmissionQueueAppDataAckHandler) OnAcked(wire.Frame) {}
   178  func (q *retransmissionQueueAppDataAckHandler) OnLost(f wire.Frame) {
   179  	(*retransmissionQueue)(q).addAppData(f)
   180  }