github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/protocol/packet_number.go (about)

     1  package protocol
     2  
     3  // A PacketNumber in QUIC
     4  type PacketNumber int64
     5  
     6  // InvalidPacketNumber is a packet number that is never sent.
     7  // In QUIC, 0 is a valid packet number.
     8  const InvalidPacketNumber PacketNumber = -1
     9  
    10  // PacketNumberLen is the length of the packet number in bytes
    11  type PacketNumberLen uint8
    12  
    13  const (
    14  	// PacketNumberLen1 is a packet number length of 1 byte
    15  	PacketNumberLen1 PacketNumberLen = 1
    16  	// PacketNumberLen2 is a packet number length of 2 bytes
    17  	PacketNumberLen2 PacketNumberLen = 2
    18  	// PacketNumberLen3 is a packet number length of 3 bytes
    19  	PacketNumberLen3 PacketNumberLen = 3
    20  	// PacketNumberLen4 is a packet number length of 4 bytes
    21  	PacketNumberLen4 PacketNumberLen = 4
    22  )
    23  
    24  // DecodePacketNumber calculates the packet number based on the received packet number, its length and the last seen packet number
    25  func DecodePacketNumber(
    26  	packetNumberLength PacketNumberLen,
    27  	lastPacketNumber PacketNumber,
    28  	wirePacketNumber PacketNumber,
    29  ) PacketNumber {
    30  	var epochDelta PacketNumber
    31  	switch packetNumberLength {
    32  	case PacketNumberLen1:
    33  		epochDelta = PacketNumber(1) << 8
    34  	case PacketNumberLen2:
    35  		epochDelta = PacketNumber(1) << 16
    36  	case PacketNumberLen3:
    37  		epochDelta = PacketNumber(1) << 24
    38  	case PacketNumberLen4:
    39  		epochDelta = PacketNumber(1) << 32
    40  	}
    41  	epoch := lastPacketNumber & ^(epochDelta - 1)
    42  	var prevEpochBegin PacketNumber
    43  	if epoch > epochDelta {
    44  		prevEpochBegin = epoch - epochDelta
    45  	}
    46  	nextEpochBegin := epoch + epochDelta
    47  	return closestTo(
    48  		lastPacketNumber+1,
    49  		epoch+wirePacketNumber,
    50  		closestTo(lastPacketNumber+1, prevEpochBegin+wirePacketNumber, nextEpochBegin+wirePacketNumber),
    51  	)
    52  }
    53  
    54  func closestTo(target, a, b PacketNumber) PacketNumber {
    55  	if delta(target, a) < delta(target, b) {
    56  		return a
    57  	}
    58  	return b
    59  }
    60  
    61  func delta(a, b PacketNumber) PacketNumber {
    62  	if a < b {
    63  		return b - a
    64  	}
    65  	return a - b
    66  }
    67  
    68  // GetPacketNumberLengthForHeader gets the length of the packet number for the public header
    69  // it never chooses a PacketNumberLen of 1 byte, since this is too short under certain circumstances
    70  func GetPacketNumberLengthForHeader(packetNumber, leastUnacked PacketNumber) PacketNumberLen {
    71  	diff := uint64(packetNumber - leastUnacked)
    72  	if diff < (1 << (16 - 1)) {
    73  		return PacketNumberLen2
    74  	}
    75  	if diff < (1 << (24 - 1)) {
    76  		return PacketNumberLen3
    77  	}
    78  	return PacketNumberLen4
    79  }