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  }