github.com/daeuniverse/quic-go@v0.0.0-20240413031024-943f218e0810/retransmission_queue.go (about) 1 package quic 2 3 import ( 4 "fmt" 5 6 "github.com/daeuniverse/quic-go/internal/ackhandler" 7 8 "github.com/daeuniverse/quic-go/internal/protocol" 9 "github.com/daeuniverse/quic-go/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 }