package quic
import (
"fmt"
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/wire"
)
type framesToRetransmit struct {
crypto []*wire .CryptoFrame
other []wire .Frame
}
type retransmissionQueue struct {
initial *framesToRetransmit
handshake *framesToRetransmit
appData framesToRetransmit
}
func newRetransmissionQueue() *retransmissionQueue {
return &retransmissionQueue {
initial : &framesToRetransmit {},
handshake : &framesToRetransmit {},
}
}
func (q *retransmissionQueue ) addInitial (f wire .Frame ) {
if q .initial == nil {
return
}
if cf , ok := f .(*wire .CryptoFrame ); ok {
q .initial .crypto = append (q .initial .crypto , cf )
return
}
q .initial .other = append (q .initial .other , f )
}
func (q *retransmissionQueue ) addHandshake (f wire .Frame ) {
if q .handshake == nil {
return
}
if cf , ok := f .(*wire .CryptoFrame ); ok {
q .handshake .crypto = append (q .handshake .crypto , cf )
return
}
q .handshake .other = append (q .handshake .other , f )
}
func (q *retransmissionQueue ) addAppData (f wire .Frame ) {
switch f := f .(type ) {
case *wire .StreamFrame :
panic ("STREAM frames are handled with their respective streams." )
case *wire .CryptoFrame :
q .appData .crypto = append (q .appData .crypto , f )
default :
q .appData .other = append (q .appData .other , f )
}
}
func (q *retransmissionQueue ) HasData (encLevel protocol .EncryptionLevel ) bool {
switch encLevel {
case protocol .EncryptionInitial :
return q .initial != nil &&
(len (q .initial .crypto ) > 0 || len (q .initial .other ) > 0 )
case protocol .EncryptionHandshake :
return q .handshake != nil &&
(len (q .handshake .crypto ) > 0 || len (q .handshake .other ) > 0 )
case protocol .Encryption1RTT :
return len (q .appData .crypto ) > 0 || len (q .appData .other ) > 0
}
return false
}
func (q *retransmissionQueue ) GetFrame (encLevel protocol .EncryptionLevel , maxLen protocol .ByteCount , v protocol .Version ) wire .Frame {
var r *framesToRetransmit
switch encLevel {
case protocol .EncryptionInitial :
r = q .initial
case protocol .EncryptionHandshake :
r = q .handshake
case protocol .Encryption1RTT :
r = &q .appData
}
if r == nil {
return nil
}
if len (r .crypto ) > 0 {
f := r .crypto [0 ]
newFrame , needsSplit := f .MaybeSplitOffFrame (maxLen , v )
if newFrame == nil && !needsSplit {
r .crypto = r .crypto [1 :]
return f
}
if newFrame != nil {
return newFrame
}
}
if len (r .other ) == 0 {
return nil
}
f := r .other [0 ]
if f .Length (v ) > maxLen {
return nil
}
r .other = r .other [1 :]
return f
}
func (q *retransmissionQueue ) DropPackets (encLevel protocol .EncryptionLevel ) {
switch encLevel {
case protocol .EncryptionInitial :
q .initial = nil
case protocol .EncryptionHandshake :
q .handshake = nil
default :
panic (fmt .Sprintf ("unexpected encryption level: %s" , encLevel ))
}
}
func (q *retransmissionQueue ) AckHandler (encLevel protocol .EncryptionLevel ) ackhandler .FrameHandler {
switch encLevel {
case protocol .EncryptionInitial :
return (*retransmissionQueueInitialAckHandler )(q )
case protocol .EncryptionHandshake :
return (*retransmissionQueueHandshakeAckHandler )(q )
case protocol .Encryption0RTT , protocol .Encryption1RTT :
return (*retransmissionQueueAppDataAckHandler )(q )
}
return nil
}
type retransmissionQueueInitialAckHandler retransmissionQueue
func (q *retransmissionQueueInitialAckHandler ) OnAcked (wire .Frame ) {}
func (q *retransmissionQueueInitialAckHandler ) OnLost (f wire .Frame ) {
(*retransmissionQueue )(q ).addInitial (f )
}
type retransmissionQueueHandshakeAckHandler retransmissionQueue
func (q *retransmissionQueueHandshakeAckHandler ) OnAcked (wire .Frame ) {}
func (q *retransmissionQueueHandshakeAckHandler ) OnLost (f wire .Frame ) {
(*retransmissionQueue )(q ).addHandshake (f )
}
type retransmissionQueueAppDataAckHandler retransmissionQueue
func (q *retransmissionQueueAppDataAckHandler ) OnAcked (wire .Frame ) {}
func (q *retransmissionQueueAppDataAckHandler ) OnLost (f wire .Frame ) {
(*retransmissionQueue )(q ).addAppData (f )
}
The pages are generated with Golds v0.8.4 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .