package quic import ( "fmt" "github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/internal/wire" ) type retransmissionQueue struct { initial []wire.Frame initialCryptoData []*wire.CryptoFrame handshake []wire.Frame handshakeCryptoData []*wire.CryptoFrame appData []wire.Frame streamData []*wire.StreamFrame version protocol.VersionNumber } func newRetransmissionQueue(ver protocol.VersionNumber) *retransmissionQueue { return &retransmissionQueue{version: ver} } func (q *retransmissionQueue) AddInitial(f wire.Frame) { if cf, ok := f.(*wire.CryptoFrame); ok { q.initialCryptoData = append(q.initialCryptoData, cf) return } q.initial = append(q.initial, f) } func (q *retransmissionQueue) AddHandshake(f wire.Frame) { if cf, ok := f.(*wire.CryptoFrame); ok { q.handshakeCryptoData = append(q.handshakeCryptoData, cf) return } q.handshake = append(q.handshake, f) } func (q *retransmissionQueue) HasInitialData() bool { return len(q.initialCryptoData) > 0 || len(q.initial) > 0 } func (q *retransmissionQueue) HasHandshakeData() bool { return len(q.handshakeCryptoData) > 0 || len(q.handshake) > 0 } func (q *retransmissionQueue) AddAppData(f wire.Frame) { if sf, ok := f.(*wire.StreamFrame); ok { sf.DataLenPresent = true q.streamData = append(q.streamData, sf) return } q.appData = append(q.appData, f) } func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount) wire.Frame { if len(q.initialCryptoData) > 0 { if f := q.initialCryptoData[0]; f.Length(q.version) <= maxLen { q.initialCryptoData = q.initialCryptoData[1:] return f } } if len(q.initial) == 0 { return nil } f := q.initial[0] if f.Length(q.version) > maxLen { return nil } q.initial = q.initial[1:] return f } func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount) wire.Frame { if len(q.handshakeCryptoData) > 0 { if f := q.handshakeCryptoData[0]; f.Length(q.version) <= maxLen { q.handshakeCryptoData = q.handshakeCryptoData[1:] return f } } if len(q.handshake) == 0 { return nil } f := q.handshake[0] if f.Length(q.version) > maxLen { return nil } q.handshake = q.handshake[1:] return f } func (q *retransmissionQueue) GetAppDataFrame(maxLen protocol.ByteCount) wire.Frame { if len(q.streamData) > 0 { f := q.streamData[0] if f.Length(q.version) <= maxLen { q.streamData = q.streamData[1:] return f } if maxLen >= protocol.MinStreamFrameSize { newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, q.version) if needsSplit && newFrame != nil { return newFrame } } } if len(q.appData) == 0 { return nil } f := q.appData[0] if f.Length(q.version) > maxLen { return nil } q.appData = q.appData[1:] return f } func (q *retransmissionQueue) DropPackets(encLevel protocol.EncryptionLevel) { switch encLevel { case protocol.EncryptionInitial: q.initial = nil q.initialCryptoData = nil case protocol.EncryptionHandshake: q.handshake = nil q.handshakeCryptoData = nil default: panic(fmt.Sprintf("unexpected encryption level: %s", encLevel)) } }