package quic import ( "crypto/rand" "math" "github.com/lucas-clemente/quic-go/protocol" ) type packetNumberGenerator struct { last protocol.PacketNumber nextToSkip protocol.PacketNumber averagePeriod protocol.PacketNumber } func newPacketNumberGenerator(averagePeriod protocol.PacketNumber) *packetNumberGenerator { return &packetNumberGenerator{ averagePeriod: averagePeriod, } } func (p *packetNumberGenerator) GetNextPacketNumber() protocol.PacketNumber { p.last++ if p.last == p.nextToSkip { return p.GetNextPacketNumber() } if p.last > p.nextToSkip { p.generateNewSkip() } return p.last } func (p *packetNumberGenerator) generateNewSkip() error { num, err := p.getRandomNumber() if err != nil { return err } skip := protocol.PacketNumber(num) * (p.averagePeriod - 1) / (math.MaxUint16 / 2) // make sure that there are never two consecutive packet numbers that are skipped p.nextToSkip = p.last + 2 + skip return nil } // getRandomNumber() generates a cryptographically secure random number between 0 and MaxUint16 (= 65535) // The expectation value is 65535/2 func (p *packetNumberGenerator) getRandomNumber() (uint16, error) { b := make([]byte, 2) _, err := rand.Read(b) if err != nil { return 0, err } num := uint16(b[0])<<8 + uint16(b[1]) return num, nil }