fn write_frame()

in neqo-transport/src/tracking.rs [418:505]


    fn write_frame(
        &mut self,
        now: Instant,
        rtt: Duration,
        builder: &mut PacketBuilder,
        tokens: &mut Vec<RecoveryToken>,
        stats: &mut FrameStats,
    ) {
        // Check that we aren't delaying ACKs.
        if !self.ack_now(now, rtt) {
            return;
        }

        // Drop extra ACK ranges to fit the available space.  Do this based on
        // a worst-case estimate of frame size for simplicity.
        //
        // When congestion limited, ACK-only packets are 255 bytes at most
        // (`recovery::ACK_ONLY_SIZE_LIMIT - 1`).  This results in limiting the
        // ranges to 13 here.
        let max_ranges = if let Some(avail) = builder.remaining().checked_sub(Self::USEFUL_ACK_LEN)
        {
            // Apply a hard maximum to keep plenty of space for other stuff.
            min(1 + (avail / 16), MAX_ACKS_PER_FRAME)
        } else {
            return;
        };

        let ranges = self
            .ranges
            .iter()
            .filter(|r| r.ack_needed())
            .take(max_ranges)
            .cloned()
            .collect::<Vec<_>>();
        if ranges.is_empty() {
            return;
        }

        builder.encode_varint(if self.ecn_count.is_some() {
            FrameType::AckEcn
        } else {
            FrameType::Ack
        });
        let mut iter = ranges.iter();
        let Some(first) = iter.next() else { return };
        builder.encode_varint(first.largest);
        stats.largest_acknowledged = first.largest;
        stats.ack += 1;

        let Some(largest_pn_time) = self.largest_pn_time else {
            return;
        };
        let elapsed = now.duration_since(largest_pn_time);
        // We use the default exponent, so delay is in multiples of 8 microseconds.
        let ack_delay = u64::try_from(elapsed.as_micros() / 8).unwrap_or(u64::MAX);
        let ack_delay = min((1 << 62) - 1, ack_delay);
        builder.encode_varint(ack_delay);
        let Ok(extra_ranges) = u64::try_from(ranges.len() - 1) else {
            return;
        };
        builder.encode_varint(extra_ranges); // extra ranges
        builder.encode_varint(first.len() - 1); // first range

        let mut last = first.smallest;
        for r in iter {
            // the difference must be at least 2 because 0-length gaps,
            // (difference 1) are illegal.
            builder.encode_varint(last - r.largest - 2); // Gap
            builder.encode_varint(r.len() - 1); // Range
            last = r.smallest;
        }

        if self.ecn_count.is_some() {
            builder.encode_varint(self.ecn_count[IpTosEcn::Ect0]);
            builder.encode_varint(self.ecn_count[IpTosEcn::Ect1]);
            builder.encode_varint(self.ecn_count[IpTosEcn::Ce]);
        }

        // We've sent an ACK, reset the timer.
        self.ack_time = None;
        self.last_ack_time = Some(now);
        self.unacknowledged_count = 0;

        tokens.push(RecoveryToken::Ack(AckToken {
            space: self.space,
            ranges,
        }));
    }