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