1package quic 2 3import ( 4 "fmt" 5 6 "github.com/lucas-clemente/quic-go/internal/protocol" 7 "github.com/lucas-clemente/quic-go/internal/wire" 8) 9 10type retransmissionQueue struct { 11 initial []wire.Frame 12 initialCryptoData []*wire.CryptoFrame 13 14 handshake []wire.Frame 15 handshakeCryptoData []*wire.CryptoFrame 16 17 appData []wire.Frame 18 19 version protocol.VersionNumber 20} 21 22func newRetransmissionQueue(ver protocol.VersionNumber) *retransmissionQueue { 23 return &retransmissionQueue{version: ver} 24} 25 26func (q *retransmissionQueue) AddInitial(f wire.Frame) { 27 if cf, ok := f.(*wire.CryptoFrame); ok { 28 q.initialCryptoData = append(q.initialCryptoData, cf) 29 return 30 } 31 q.initial = append(q.initial, f) 32} 33 34func (q *retransmissionQueue) AddHandshake(f wire.Frame) { 35 if cf, ok := f.(*wire.CryptoFrame); ok { 36 q.handshakeCryptoData = append(q.handshakeCryptoData, cf) 37 return 38 } 39 q.handshake = append(q.handshake, f) 40} 41 42func (q *retransmissionQueue) HasInitialData() bool { 43 return len(q.initialCryptoData) > 0 || len(q.initial) > 0 44} 45 46func (q *retransmissionQueue) HasHandshakeData() bool { 47 return len(q.handshakeCryptoData) > 0 || len(q.handshake) > 0 48} 49 50func (q *retransmissionQueue) HasAppData() bool { 51 return len(q.appData) > 0 52} 53 54func (q *retransmissionQueue) AddAppData(f wire.Frame) { 55 if _, ok := f.(*wire.StreamFrame); ok { 56 panic("STREAM frames are handled with their respective streams.") 57 } 58 q.appData = append(q.appData, f) 59} 60 61func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount) wire.Frame { 62 if len(q.initialCryptoData) > 0 { 63 f := q.initialCryptoData[0] 64 newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, q.version) 65 if newFrame == nil && !needsSplit { // the whole frame fits 66 q.initialCryptoData = q.initialCryptoData[1:] 67 return f 68 } 69 if newFrame != nil { // frame was split. Leave the original frame in the queue. 70 return newFrame 71 } 72 } 73 if len(q.initial) == 0 { 74 return nil 75 } 76 f := q.initial[0] 77 if f.Length(q.version) > maxLen { 78 return nil 79 } 80 q.initial = q.initial[1:] 81 return f 82} 83 84func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount) wire.Frame { 85 if len(q.handshakeCryptoData) > 0 { 86 f := q.handshakeCryptoData[0] 87 newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, q.version) 88 if newFrame == nil && !needsSplit { // the whole frame fits 89 q.handshakeCryptoData = q.handshakeCryptoData[1:] 90 return f 91 } 92 if newFrame != nil { // frame was split. Leave the original frame in the queue. 93 return newFrame 94 } 95 } 96 if len(q.handshake) == 0 { 97 return nil 98 } 99 f := q.handshake[0] 100 if f.Length(q.version) > maxLen { 101 return nil 102 } 103 q.handshake = q.handshake[1:] 104 return f 105} 106 107func (q *retransmissionQueue) GetAppDataFrame(maxLen protocol.ByteCount) wire.Frame { 108 if len(q.appData) == 0 { 109 return nil 110 } 111 f := q.appData[0] 112 if f.Length(q.version) > maxLen { 113 return nil 114 } 115 q.appData = q.appData[1:] 116 return f 117} 118 119func (q *retransmissionQueue) DropPackets(encLevel protocol.EncryptionLevel) { 120 //nolint:exhaustive // Can only drop Initial and Handshake packet number space. 121 switch encLevel { 122 case protocol.EncryptionInitial: 123 q.initial = nil 124 q.initialCryptoData = nil 125 case protocol.EncryptionHandshake: 126 q.handshake = nil 127 q.handshakeCryptoData = nil 128 default: 129 panic(fmt.Sprintf("unexpected encryption level: %s", encLevel)) 130 } 131} 132