fn write_appdata_frames()

in neqo-transport/src/connection/mod.rs [2155:2248]


    fn write_appdata_frames(
        &mut self,
        builder: &mut PacketBuilder,
        tokens: &mut Vec<RecoveryToken>,
        now: Instant,
    ) {
        let rtt = self.paths.primary().map_or_else(
            || RttEstimate::default().estimate(),
            |p| p.borrow().rtt().estimate(),
        );

        let stats = &mut self.stats.borrow_mut();
        let frame_stats = &mut stats.frame_tx;
        if self.role == Role::Server {
            if let Some(t) = self.state_signaling.write_done(builder) {
                tokens.push(t);
                frame_stats.handshake_done += 1;
            }
        }

        self.streams
            .write_frames(TransmissionPriority::Critical, builder, tokens, frame_stats);
        if builder.is_full() {
            return;
        }

        self.streams
            .write_maintenance_frames(builder, tokens, frame_stats, now, rtt);
        if builder.is_full() {
            return;
        }

        self.streams.write_frames(
            TransmissionPriority::Important,
            builder,
            tokens,
            frame_stats,
        );
        if builder.is_full() {
            return;
        }

        // NEW_CONNECTION_ID, RETIRE_CONNECTION_ID, and ACK_FREQUENCY.
        self.cid_manager.write_frames(builder, tokens, frame_stats);
        if builder.is_full() {
            return;
        }

        self.paths.write_frames(builder, tokens, frame_stats);
        if builder.is_full() {
            return;
        }

        for prio in [TransmissionPriority::High, TransmissionPriority::Normal] {
            self.streams
                .write_frames(prio, builder, tokens, &mut stats.frame_tx);
            if builder.is_full() {
                return;
            }
        }

        // Datagrams are best-effort and unreliable.  Let streams starve them for now.
        self.quic_datagrams.write_frames(builder, tokens, stats);
        if builder.is_full() {
            return;
        }

        // CRYPTO here only includes NewSessionTicket, plus NEW_TOKEN.
        // Both of these are only used for resumption and so can be relatively low priority.
        let frame_stats = &mut stats.frame_tx;
        self.crypto.write_frame(
            PacketNumberSpace::ApplicationData,
            self.conn_params.sni_slicing_enabled(),
            builder,
            tokens,
            frame_stats,
        );
        if builder.is_full() {
            return;
        }

        self.new_token.write_frames(builder, tokens, frame_stats);
        if builder.is_full() {
            return;
        }

        self.streams
            .write_frames(TransmissionPriority::Low, builder, tokens, frame_stats);

        #[cfg(test)]
        if let Some(w) = &mut self.test_frame_writer {
            w.write_frames(builder);
        }
    }