github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/quic-go/retransmission_queue.go (about)

     1  package quic
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/protocol"
     7  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/wire"
     8  )
     9  
    10  type 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  
    22  func newRetransmissionQueue(ver protocol.VersionNumber) *retransmissionQueue {
    23  	return &retransmissionQueue{version: ver}
    24  }
    25  
    26  func (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  
    34  func (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  
    42  func (q *retransmissionQueue) HasInitialData() bool {
    43  	return len(q.initialCryptoData) > 0 || len(q.initial) > 0
    44  }
    45  
    46  func (q *retransmissionQueue) HasHandshakeData() bool {
    47  	return len(q.handshakeCryptoData) > 0 || len(q.handshake) > 0
    48  }
    49  
    50  func (q *retransmissionQueue) HasAppData() bool {
    51  	return len(q.appData) > 0
    52  }
    53  
    54  func (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  
    61  func (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  
    84  func (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  
   107  func (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  
   119  func (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  }