github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/internal/protocol/packet_number.go (about)

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