1use crate::coding::{put_varint_fixed, Reader};
8use crate::config::Config;
9use crate::crypto::{CryptoSession, HeaderKey, KeyChange, Keys, Level, NextSecrets, PacketKey};
10use crate::error::*;
11use crate::frame::{self, Frame};
12use crate::packet::{self, PacketType, MIN_INITIAL_SIZE};
13use crate::params::{Cid, TransportParams};
14use crate::ranges::RangeSet;
15use crate::recovery::{Recovery, SentFrame, SentPacket};
16use crate::stream::{Control, StreamConfig, StreamEvent, Streams};
17use std::collections::{BTreeMap, VecDeque};
18use std::net::SocketAddr;
19use std::sync::Arc;
20use std::time::{Duration, Instant};
21
22#[derive(Clone, Debug, PartialEq, Eq)]
24pub enum ConnectionError {
25 Transport(TransportError),
27 PeerTransport { code: u64, frame_type: u64, reason: Vec<u8> },
29 PeerApplication { code: u64, reason: Vec<u8> },
31 LocalApplication { code: u64 },
33 IdleTimeout,
34 StatelessReset,
35 VersionMismatch,
37}
38
39#[derive(Clone, Debug, PartialEq, Eq)]
41pub enum Event {
42 Connected,
44 StreamOpened(u64),
46 StreamReadable(u64),
47 StreamWritable(u64),
48 StreamStopped { id: u64, code: u64 },
50 StreamReset { id: u64, code: u64 },
52 StreamsAvailable(bool),
54 PathMigrated(SocketAddr),
56 Closed(ConnectionError),
58}
59
60#[derive(Clone, Debug, PartialEq, Eq)]
62pub enum EndpointEvent {
63 NewCid(Cid),
64 RetireCid(Cid),
65 ResetToken([u8; 16]),
67}
68
69#[derive(Clone, Copy, Debug, PartialEq, Eq)]
73pub struct Transmit {
74 pub destination: SocketAddr,
75 pub size: usize,
76 pub segment_size: Option<usize>,
77}
78
79#[derive(Clone, Copy, Debug, Default)]
80pub struct Stats {
81 pub sent_packets: u64,
82 pub recv_packets: u64,
83 pub lost_packets: u64,
84 pub sent_bytes: u64,
85 pub recv_bytes: u64,
86 pub dropped_packets: u64,
87 pub key_updates: u64,
88 pub cwnd: u64,
89 pub rtt: Duration,
90 pub mtu: usize,
91}
92
93#[derive(Clone, Copy, Debug, PartialEq, Eq)]
94enum State {
95 Handshake,
96 Established,
97 Closing(Instant),
98 Draining(Instant),
99 Drained,
100}
101
102const PN_SKIP_PERIOD: u64 = 256;
104
105const CRYPTO_CHUNK_OVERHEAD: usize = 64;
107
108#[derive(Default)]
110struct CryptoIn {
111 read: u64,
112 ooo: BTreeMap<u64, Vec<u8>>,
113 ooo_bytes: usize,
114}
115
116#[derive(Default)]
117struct Space {
118 keys: Option<Keys>,
119 crypto_out: Vec<u8>,
120 crypto_sent: u64,
121 crypto_retx: RangeSet,
122 crypto_in: CryptoIn,
123 recv: RangeSet,
124 ack_floor: u64,
125 largest_recv: Option<(u64, Instant)>,
126 unacked_eliciting: u32,
127 ack_now: bool,
128 ack_deadline: Option<Instant>,
129 probes: u8,
130 discarded: bool,
131}
132
133impl Space {
134 fn has_crypto(&self) -> bool {
135 !self.crypto_retx.is_empty() || self.crypto_sent < self.crypto_out.len() as u64
136 }
137}
138
139struct OneRtt {
140 local: Box<dyn PacketKey>,
141 remote: Box<dyn PacketKey>,
142 local_hp: Box<dyn HeaderKey>,
143 remote_hp: Box<dyn HeaderKey>,
144 secrets: Box<dyn NextSecrets>,
145 phase: bool,
146 next: Option<(Box<dyn PacketKey>, Box<dyn PacketKey>)>,
147 prev_remote: Option<(Box<dyn PacketKey>, Option<Instant>)>,
148 phase_first_sent: u64,
149 phase_first_recv: Option<u64>,
150 update_allowed: bool,
151 sealed: u64,
152}
153
154struct Path {
155 remote: SocketAddr,
156 validated: bool,
157 recv_bytes: u64,
158 sent_bytes: u64,
159 challenge: Option<([u8; 8], Instant)>,
160 challenge_pending: bool,
161}
162
163impl Path {
164 fn new(remote: SocketAddr, validated: bool) -> Self {
165 Path { remote, validated, recv_bytes: 0, sent_bytes: 0, challenge: None, challenge_pending: false }
166 }
167 fn budget(&self) -> usize {
169 if self.validated {
170 usize::MAX
171 } else {
172 (self.recv_bytes * 3).saturating_sub(self.sent_bytes) as usize
173 }
174 }
175}
176
177struct LocalCid {
178 seq: u64,
179 cid: Cid,
180 retired: bool,
181}
182
183struct RemoteCid {
184 seq: u64,
185 cid: Cid,
186 token: Option<[u8; 16]>,
187}
188
189struct Building {
191 space: usize,
192 start: usize,
193 len_at: Option<usize>,
194 pn_at: usize,
195 pn: u64,
196 pn_len: usize,
197 eliciting: bool,
198 frames: Vec<SentFrame>,
199 mtu_probe: bool,
200}
201
202pub struct Connection {
203 cfg: Arc<Config>,
204 is_server: bool,
205 version: u32,
206 state: State,
207 session: Box<dyn CryptoSession>,
208 write_level: Level,
209 spaces: [Space; 3],
210 one_rtt: Option<OneRtt>,
211 handshake_complete: bool,
212 handshake_confirmed: bool,
213 peer_params: Option<TransportParams>,
214 streams: Streams,
215 recovery: Recovery,
216 path: Path,
217 prev_path: Option<Path>,
218 path_responses: VecDeque<([u8; 8], SocketAddr)>,
219 local_cids: Vec<LocalCid>,
220 next_local_seq: u64,
221 remote_cids: Vec<RemoteCid>,
222 remote_cid_seq: u64,
223 retire_prior_to: u64,
224 pending_retire: VecDeque<u64>,
225 pending_new_cids: VecDeque<u64>,
226 orig_dcid: Cid,
228 dcid_switched: bool,
230 retry_scid: Option<Cid>,
231 peer_initial_scid: Option<Cid>,
232 token: Vec<u8>,
233 new_token: Option<Vec<u8>>,
234 new_token_pending: bool,
235 received_new_token: Option<Vec<u8>>,
236 handshake_done_pending: bool,
237 ping_pending: bool,
238 raw_frames: Vec<u8>,
240 close: Option<(u64, Option<u64>, Vec<u8>)>,
241 close_sent_count: u32,
242 close_recv_count: u32,
243 error: Option<ConnectionError>,
244 events: VecDeque<Event>,
245 endpoint_events: VecDeque<EndpointEvent>,
246 idle_timeout: Duration,
247 last_activity: Instant,
248 eliciting_since_recv: bool,
249 mds: usize,
250 mtu_probe: Option<(usize, u8)>,
251 mtu_probe_inflight: bool,
252 probe_allowed: bool,
253 pacing_until: Option<Instant>,
254 failed_decrypts: u64,
255 any_packet_processed: bool,
256 stats: Stats,
257 initial_dcid: Cid,
259 deferred: Option<(Cid, Option<Cid>)>,
262 hello: Vec<u8>,
264 orig_initial: Option<(u32, Keys)>,
268}
269
270fn space_of(ty: PacketType) -> usize {
271 match ty {
272 PacketType::Initial => 0,
273 PacketType::Handshake => 1,
274 _ => 2,
275 }
276}
277
278impl Connection {
279 fn new(
280 cfg: Arc<Config>,
281 is_server: bool,
282 version: u32,
283 now: Instant,
284 remote: SocketAddr,
285 session: Box<dyn CryptoSession>,
286 local_cid: Cid,
287 remote_cid: Cid,
288 orig_dcid: Cid,
289 ) -> Self {
290 let t = &cfg.transport;
291 let streams = Streams::new(
292 is_server,
293 StreamConfig {
294 max_streams_bidi: t.max_streams_bidi,
295 max_streams_uni: t.max_streams_uni,
296 stream_window_bidi_local: t.stream_window_bidi_local,
297 stream_window_bidi_remote: t.stream_window_bidi_remote,
298 stream_window_uni: t.stream_window_uni,
299 conn_window: t.max_data,
300 send_buffer: t.send_buffer,
301 },
302 );
303 let mut spaces: [Space; 3] = Default::default();
304 spaces[0].keys = Some(cfg.provider.initial_keys(version, &orig_dcid, is_server));
305 let idle = t.max_idle_timeout;
306 Connection {
307 is_server,
308 version,
309 state: State::Handshake,
310 session,
311 write_level: Level::Initial,
312 spaces,
313 one_rtt: None,
314 handshake_complete: false,
315 handshake_confirmed: false,
316 peer_params: None,
317 streams,
318 recovery: Recovery::new(MIN_INITIAL_SIZE as u64),
319 path: Path::new(remote, !is_server),
320 prev_path: None,
321 path_responses: VecDeque::new(),
322 local_cids: vec![LocalCid { seq: 0, cid: local_cid, retired: false }],
323 next_local_seq: 1,
324 remote_cids: vec![RemoteCid { seq: 0, cid: remote_cid, token: None }],
325 remote_cid_seq: 0,
326 retire_prior_to: 0,
327 pending_retire: VecDeque::new(),
328 pending_new_cids: VecDeque::new(),
329 orig_dcid,
330 dcid_switched: is_server,
331 retry_scid: None,
332 peer_initial_scid: None,
333 token: Vec::new(),
334 new_token: None,
335 new_token_pending: false,
336 received_new_token: None,
337 handshake_done_pending: false,
338 ping_pending: false,
339 raw_frames: Vec::new(),
340 close: None,
341 close_sent_count: 0,
342 close_recv_count: 0,
343 error: None,
344 events: VecDeque::new(),
345 endpoint_events: VecDeque::new(),
346 idle_timeout: idle,
347 last_activity: now,
348 eliciting_since_recv: false,
349 mds: MIN_INITIAL_SIZE,
350 mtu_probe: None,
351 mtu_probe_inflight: false,
352 probe_allowed: false,
353 pacing_until: None,
354 failed_decrypts: 0,
355 any_packet_processed: false,
356 stats: Stats::default(),
357 initial_dcid: orig_dcid,
358 deferred: None,
359 hello: Vec::new(),
360 orig_initial: None,
361 cfg,
362 }
363 }
364
365 fn local_params(&self, odcid: Option<Cid>, retry_scid: Option<Cid>) -> Vec<u8> {
366 let t = &self.cfg.transport;
367 let local = self.local_cids[0].cid;
368 let p = TransportParams {
369 original_destination_connection_id: odcid,
370 max_idle_timeout: t.max_idle_timeout.as_millis() as u64,
371 stateless_reset_token: if self.is_server { Some(self.cfg.reset_token(&local)) } else { None },
372 max_udp_payload_size: t.max_udp_payload_size,
373 initial_max_data: t.max_data,
374 initial_max_stream_data_bidi_local: t.stream_window_bidi_local,
375 initial_max_stream_data_bidi_remote: t.stream_window_bidi_remote,
376 initial_max_stream_data_uni: t.stream_window_uni,
377 initial_max_streams_bidi: t.max_streams_bidi,
378 initial_max_streams_uni: t.max_streams_uni,
379 ack_delay_exponent: t.ack_delay_exponent,
380 max_ack_delay: t.max_ack_delay.as_millis() as u64,
381 disable_active_migration: t.disable_active_migration,
382 preferred_address: None,
383 active_connection_id_limit: t.active_connection_id_limit,
384 initial_source_connection_id: Some(local),
385 retry_source_connection_id: retry_scid,
386 version_information: (self.cfg.versions.len() > 1).then(|| (self.version, self.cfg.versions.clone())),
389 };
390 let mut b = Vec::with_capacity(128);
391 p.encode(&mut b);
392 b
393 }
394
395 pub fn connect(
398 cfg: Arc<Config>,
399 now: Instant,
400 remote: SocketAddr,
401 server_name: &str,
402 token: &[u8],
403 ) -> Result<Self, TransportError> {
404 let mut scid = [0u8; 20];
405 let mut dcid = [0u8; 8];
406 cfg.provider.fill_random(&mut scid[..cfg.cid_len]);
407 cfg.provider.fill_random(&mut dcid);
408 let local = Cid::new(&scid[..cfg.cid_len]);
409 let dcid = Cid::new(&dcid);
410 let version = cfg.versions[0];
411 let placeholder: Box<dyn CryptoSession> = Box::new(Placeholder);
412 let mut c = Connection::new(cfg.clone(), false, version, now, remote, placeholder, local, dcid, dcid);
413 let tp = c.local_params(None, None);
414 c.session = cfg.provider.client_session(version, server_name, tp)?;
415 c.token = token.to_vec();
416 c.endpoint_events.push_back(EndpointEvent::NewCid(local));
417 c.drive_crypto()?;
418 Ok(c)
419 }
420
421 #[allow(clippy::too_many_arguments)]
423 pub(crate) fn accept(
424 cfg: Arc<Config>,
425 now: Instant,
426 remote: SocketAddr,
427 version: u32,
428 local_cid: Cid,
429 client_dcid: Cid,
430 client_scid: Cid,
431 odcid: Cid,
432 retry_scid: Option<Cid>,
433 validated: bool,
434 ) -> Result<Self, TransportError> {
435 let placeholder: Box<dyn CryptoSession> = Box::new(Placeholder);
436 let mut c = Connection::new(cfg.clone(), true, version, now, remote, placeholder, local_cid, client_scid, client_dcid);
437 if cfg.versions.len() > 1 {
438 c.deferred = Some((odcid, retry_scid));
440 } else {
441 let tp = c.local_params(Some(odcid), retry_scid);
442 c.session = cfg.provider.server_session(version, tp)?;
443 }
444 c.orig_dcid = odcid;
445 c.retry_scid = retry_scid;
446 c.peer_initial_scid = Some(client_scid);
447 c.path.validated = validated;
448 Ok(c)
449 }
450
451 pub fn is_server(&self) -> bool {
454 self.is_server
455 }
456 pub fn is_established(&self) -> bool {
457 self.state == State::Established
458 }
459 pub fn is_handshaking(&self) -> bool {
460 self.state == State::Handshake
461 }
462 pub fn is_closed(&self) -> bool {
464 matches!(self.state, State::Closing(_) | State::Draining(_) | State::Drained)
465 }
466 pub fn is_drained(&self) -> bool {
468 self.state == State::Drained
469 }
470 pub fn error(&self) -> Option<&ConnectionError> {
471 self.error.as_ref()
472 }
473 pub fn alpn(&self) -> Option<&[u8]> {
474 self.session.alpn_protocol()
475 }
476 pub fn tls(&self) -> &dyn CryptoSession {
478 &*self.session
479 }
480 pub fn remote_address(&self) -> SocketAddr {
481 self.path.remote
482 }
483 pub fn path_validated(&self) -> bool {
484 self.path.validated
485 }
486 pub fn peer_params(&self) -> Option<&TransportParams> {
487 self.peer_params.as_ref()
488 }
489 pub fn version(&self) -> u32 {
490 self.version
491 }
492 pub fn stats(&self) -> Stats {
493 let mut s = self.stats;
494 s.cwnd = self.recovery.cc.cwnd;
495 s.rtt = self.recovery.rtt.smoothed;
496 s.mtu = self.mds;
497 s
498 }
499 pub fn local_cids(&self) -> impl Iterator<Item = Cid> + '_ {
501 self.local_cids.iter().filter(|c| !c.retired).map(|c| c.cid)
502 }
503 pub fn remote_cid(&self) -> Cid {
505 self.remote_cids[0].cid
506 }
507 pub fn original_dcid(&self) -> Cid {
509 self.orig_dcid
510 }
511 pub fn new_token(&self) -> Option<&[u8]> {
513 self.received_new_token.as_deref()
514 }
515 pub fn poll_event(&mut self) -> Option<Event> {
516 self.pull_stream_events();
517 self.events.pop_front()
518 }
519 pub fn poll_endpoint_event(&mut self) -> Option<EndpointEvent> {
520 self.endpoint_events.pop_front()
521 }
522 pub fn stream_count(&self) -> usize {
524 self.streams.len()
525 }
526
527 fn pull_stream_events(&mut self) {
528 while let Some(e) = self.streams.events.pop_front() {
529 self.events.push_back(match e {
530 StreamEvent::Opened(id) => Event::StreamOpened(id),
531 StreamEvent::Readable(id) => Event::StreamReadable(id),
532 StreamEvent::Writable(id) => Event::StreamWritable(id),
533 StreamEvent::Stopped(id, code) => Event::StreamStopped { id, code },
534 StreamEvent::Reset(id, code) => Event::StreamReset { id, code },
535 StreamEvent::Available(b) => Event::StreamsAvailable(b),
536 });
537 }
538 }
539
540 fn usable(&self) -> Result<(), StreamError> {
543 if self.is_closed() {
544 Err(StreamError::ConnectionClosed)
545 } else {
546 Ok(())
547 }
548 }
549
550 pub fn open_bi(&mut self) -> Result<u64, StreamError> {
552 self.usable()?;
553 self.streams.open(true)
554 }
555 pub fn open_uni(&mut self) -> Result<u64, StreamError> {
557 self.usable()?;
558 self.streams.open(false)
559 }
560 pub fn stream_send(&mut self, id: u64, data: &[u8], fin: bool) -> Result<usize, StreamError> {
562 self.usable()?;
563 self.streams.write(id, data, fin)
564 }
565 pub fn stream_finish(&mut self, id: u64) -> Result<(), StreamError> {
567 self.usable()?;
568 self.streams.write(id, &[], true).map(|_| ())
569 }
570 pub fn stream_recv(&mut self, id: u64, out: &mut [u8]) -> Result<(usize, bool), StreamError> {
572 self.usable()?;
573 self.streams.read(id, out)
574 }
575 pub fn stream_reset(&mut self, id: u64, code: u64) -> Result<(), StreamError> {
576 self.usable()?;
577 self.streams.reset(id, code)
578 }
579 pub fn stream_stop(&mut self, id: u64, code: u64) -> Result<(), StreamError> {
580 self.usable()?;
581 self.streams.stop(id, code)
582 }
583 pub fn stream_writable(&self, id: u64) -> Option<u64> {
585 self.streams.writable(id)
586 }
587 pub fn stream_unacked(&self, id: u64) -> Option<u64> {
589 self.streams.unacked(id)
590 }
591 pub fn stream_exists(&self, id: u64) -> bool {
592 self.streams.contains(id)
593 }
594 pub fn ping(&mut self) {
596 self.ping_pending = true;
597 }
598
599 #[doc(hidden)]
602 pub fn largest_sent_packet_number(&self) -> Option<u64> {
603 let sp = &self.recovery.spaces[2];
604 let last = sp.next_pn.checked_sub(1)?;
605 if sp.skipped.back() == Some(&last) {
606 last.checked_sub(1)
607 } else {
608 Some(last)
609 }
610 }
611
612 #[doc(hidden)]
616 pub fn send_raw_frames(&mut self, frames: &[u8]) {
617 self.raw_frames.extend_from_slice(frames);
618 self.ping_pending = true;
619 }
620
621 pub fn close(&mut self, now: Instant, code: u64, reason: &[u8]) {
625 if self.is_closed() {
626 return;
627 }
628 self.close = Some((code, None, reason.to_vec()));
629 self.error = Some(ConnectionError::LocalApplication { code });
630 self.enter_closing(now);
631 }
632
633 fn close_transport(&mut self, now: Instant, e: TransportError) {
634 if self.is_closed() {
635 return;
636 }
637 self.close = Some((e.code, Some(e.frame_type), e.reason.as_bytes().to_vec()));
638 self.error = Some(ConnectionError::Transport(e.clone()));
639 self.events.push_back(Event::Closed(ConnectionError::Transport(e)));
640 self.enter_closing(now);
641 }
642
643 fn enter_closing(&mut self, now: Instant) {
644 let until = now + self.recovery.pto(2) * 3;
645 self.state = State::Closing(until);
646 self.close_sent_count = 0;
647 self.close_recv_count = 0;
648 self.ping_pending = false;
649 }
650
651 fn enter_draining(&mut self, now: Instant, err: ConnectionError) {
652 if matches!(self.state, State::Draining(_) | State::Drained) {
653 return;
654 }
655 let already_closing = matches!(self.state, State::Closing(_));
656 self.state = State::Draining(now + self.recovery.pto(2) * 3);
657 if !already_closing {
658 self.error = Some(err.clone());
659 self.events.push_back(Event::Closed(err));
660 }
661 }
662
663 fn drain_now(&mut self, err: ConnectionError) {
664 if self.state == State::Drained {
665 return;
666 }
667 if !self.is_closed() {
668 self.error = Some(err.clone());
669 self.events.push_back(Event::Closed(err));
670 }
671 self.state = State::Drained;
672 for c in &self.local_cids {
673 if !c.retired {
674 self.endpoint_events.push_back(EndpointEvent::RetireCid(c.cid));
675 }
676 }
677 }
678
679 pub fn recv(&mut self, now: Instant, remote: SocketAddr, data: &mut [u8]) {
684 if self.state == State::Drained {
685 return;
686 }
687 let len = data.len();
688 self.stats.recv_bytes += len as u64;
689 if remote == self.path.remote {
690 self.path.recv_bytes += len as u64;
691 } else if let Some(p) = self.prev_path.as_mut().filter(|p| p.remote == remote) {
692 p.recv_bytes += len as u64;
693 }
694 let mut start = 0;
695 let mut processed_any = false;
696 let mut first_dcid: Option<Cid> = None;
697 while start < len {
698 let cid_len = self.local_cids[0].cid.len();
699 let Some(h) = packet::parse_header(data, start, cid_len) else { break };
700 if let Some(f) = first_dcid {
701 if data[h.dcid.clone()] != f[..] {
703 break;
704 }
705 } else {
706 first_dcid = Some(Cid::new(&data[h.dcid.clone()]));
707 }
708 let end = h.end;
709 match h.ty {
710 PacketType::VersionNegotiation => {
711 self.on_version_negotiation(now, &data[h.token.clone()]);
712 return;
713 }
714 PacketType::Retry => {
715 self.on_retry(now, data, &h);
716 return;
717 }
718 PacketType::ZeroRtt => {
719 self.stats.dropped_packets += 1;
721 start = end;
722 continue;
723 }
724 _ => {}
725 }
726 let original = self.is_server && h.ty == PacketType::Initial && self.orig_initial.as_ref().is_some_and(|o| o.0 == h.version);
728 if h.ty != PacketType::OneRtt && h.version != self.version && !original && !self.follow_version(&h) {
729 break;
730 }
731 let result = if original { self.recv_original_initial(now, remote, data, start, &h) } else { self.recv_packet(now, remote, data, start, &h) };
732 match result {
733 Ok(true) => processed_any = true,
734 Ok(false) => self.stats.dropped_packets += 1,
735 Err(e) => {
736 self.close_transport(now, e);
737 return;
738 }
739 }
740 if self.state == State::Drained {
741 return;
742 }
743 start = end;
744 }
745 if !processed_any {
746 self.check_stateless_reset(now, data);
747 }
748 }
749
750 fn check_stateless_reset(&mut self, _now: Instant, data: &[u8]) {
751 if data.len() < packet::MIN_RESET_SIZE || data[0] & 0x80 != 0 {
752 return;
753 }
754 let tail = &data[data.len() - 16..];
755 let hit = self.remote_cids.iter().any(|c| c.token.is_some_and(|t| crate::crypto::ct_eq(&t, tail)));
756 if hit {
757 self.drain_now(ConnectionError::StatelessReset);
758 }
759 }
760
761 fn recv_original_initial(&mut self, now: Instant, remote: SocketAddr, data: &mut [u8], start: usize, h: &packet::Header) -> Result<bool, TransportError> {
764 let (v, keys) = self.orig_initial.take().expect("original keys");
765 let current = std::mem::replace(&mut self.spaces[0].keys, Some(keys));
766 let r = self.recv_packet(now, remote, data, start, h);
767 let used = std::mem::replace(&mut self.spaces[0].keys, current);
768 if self.spaces[0].discarded {
769 self.spaces[0].keys = None;
770 } else if let Some(k) = used {
771 self.orig_initial = Some((v, k));
772 }
773 r
774 }
775
776 fn follow_version(&mut self, h: &packet::Header) -> bool {
779 let ok = !self.is_server
780 && !self.any_packet_processed
781 && h.ty == PacketType::Initial
782 && self.cfg.versions.contains(&h.version)
783 && crate::vn::compatible(self.version, h.version);
784 if ok {
785 self.version = h.version;
786 self.spaces[0].keys = Some(self.cfg.provider.initial_keys(h.version, &self.initial_dcid, false));
787 self.session.set_version(h.version);
788 }
789 ok
790 }
791
792 fn on_version_negotiation(&mut self, now: Instant, list: &[u8]) {
793 if self.is_server || self.any_packet_processed {
794 return;
795 }
796 let mut r = Reader::new(list);
797 while let Some(v) = r.u32() {
798 if v == self.version {
799 return; }
801 }
802 let _ = now;
803 self.drain_now(ConnectionError::VersionMismatch);
804 }
805
806 fn on_retry(&mut self, _now: Instant, data: &[u8], h: &packet::Header) {
807 if self.is_server || self.any_packet_processed || self.retry_scid.is_some() {
808 return;
809 }
810 let scid = Cid::new(&data[h.scid.clone()]);
811 let token = &data[h.token.clone()];
812 if token.is_empty() || scid[..] == self.remote_cids[0].cid[..] {
813 return;
814 }
815 let tag_at = data.len() - 16;
816 let expect = packet::retry_tag(&*self.cfg.provider, self.version, &self.orig_dcid, &data[..tag_at]);
817 if !crate::crypto::ct_eq(&expect, &data[tag_at..]) {
818 return;
819 }
820 self.retry_scid = Some(scid);
821 self.remote_cids[0].cid = scid;
822 self.token = token.to_vec();
823 self.spaces[0].keys = Some(self.cfg.provider.initial_keys(self.version, &scid, false));
824 self.initial_dcid = scid;
825 let s = &mut self.spaces[0];
827 s.crypto_retx.clear();
828 s.crypto_sent = 0;
829 self.recovery.discard(0);
830 }
831
832 fn recv_packet(
834 &mut self,
835 now: Instant,
836 remote: SocketAddr,
837 data: &mut [u8],
838 start: usize,
839 h: &packet::Header,
840 ) -> Result<bool, TransportError> {
841 let space = space_of(h.ty);
842 if self.spaces[space].discarded {
843 return Ok(false);
844 }
845 if space < 2 && self.spaces[space].keys.is_none() {
846 return Ok(false);
847 }
848 if space == 2 && self.one_rtt.is_none() {
849 return Ok(false);
850 }
851 let hp: &dyn HeaderKey = if space == 2 {
853 &*self.one_rtt.as_ref().unwrap().remote_hp
854 } else {
855 &*self.spaces[space].keys.as_ref().unwrap().remote.header
856 };
857 let first_before = data[start];
858 let Some((tpn, pn_len)) = packet::unprotect(data, start, h.pn_offset, h.end, hp) else {
859 return Ok(false);
860 };
861 let largest = self.spaces[space].largest_recv.map(|x| x.0);
862 let pn = packet::decode_pn(largest, tpn, pn_len);
863 let hdr_end = h.pn_offset + pn_len;
864 let first = data[start];
865 let (head, rest) = data[start..h.end].split_at_mut(hdr_end - start);
866 let decrypted = if space == 2 {
867 let phase = first & 0x04 != 0;
868 self.open_one_rtt(now, pn, phase, head, rest)
869 } else {
870 self.spaces[space].keys.as_ref().unwrap().remote.packet.open(pn, head, rest).ok()
871 };
872 let Some(plen) = decrypted else {
873 data[start] = first_before;
874 self.failed_decrypts += 1;
875 let limit = self.one_rtt.as_ref().map(|k| k.remote.integrity_limit()).unwrap_or(u64::MAX);
876 if self.failed_decrypts >= limit {
877 return Err(TransportError::new(AEAD_LIMIT_REACHED, "integrity limit reached"));
878 }
879 return Ok(false);
880 };
881 let reserved = if first & 0x80 != 0 { first & 0x0c } else { first & 0x18 };
883 if reserved != 0 {
884 return Err(TransportError::proto("reserved header bits set"));
885 }
886 let sp = &self.spaces[space];
888 if pn < sp.ack_floor || sp.recv.contains(pn) {
889 return Ok(false);
890 }
891 self.any_packet_processed = true;
892 self.stats.recv_packets += 1;
893
894 if !self.is_server && !self.dcid_switched && space < 2 {
896 self.dcid_switched = true;
897 let scid = Cid::new(&data[h.scid.clone()]);
898 self.remote_cids[0].cid = scid;
899 self.peer_initial_scid = Some(scid);
900 }
901 let dcid = Cid::new(&data[h.dcid.clone()]);
902 let payload_start = hdr_end;
903 let payload_end = hdr_end + plen;
904 let payload: &[u8] = &data[payload_start..payload_end];
905 let ptype = h.ty;
906 let (eliciting, non_probing) = self.process_frames(now, remote, ptype, space, payload, &dcid)?;
907
908 let sp = &mut self.spaces[space];
910 let out_of_order = sp.largest_recv.is_some_and(|(l, _)| pn != l + 1);
911 sp.recv.insert(pn, pn + 1);
912 sp.recv.truncate_low(self.cfg.transport.max_ack_ranges);
913 if sp.largest_recv.is_none_or(|(l, _)| pn > l) {
914 sp.largest_recv = Some((pn, now));
915 }
916 if eliciting {
917 sp.unacked_eliciting += 1;
918 if space < 2 || out_of_order || sp.unacked_eliciting >= self.cfg.transport.ack_eliciting_threshold {
919 sp.ack_now = true;
920 } else if sp.ack_deadline.is_none() {
921 sp.ack_deadline = Some(now + self.cfg.transport.max_ack_delay);
922 }
923 }
924 if self.is_server && space == 1 {
926 self.path.validated = true;
927 self.discard_space(0);
928 }
929 if space == 2 && remote != self.path.remote && non_probing {
932 let highest = self.spaces[2].largest_recv.is_some_and(|(l, _)| l == pn);
933 if highest && self.is_server && self.handshake_confirmed {
934 self.migrate(now, remote);
935 }
936 }
937 if self.is_closed() {
938 if let State::Closing(_) = self.state {
939 self.close_recv_count += 1;
941 }
942 return Ok(true);
943 }
944 self.last_activity = now;
945 self.eliciting_since_recv = false;
946 Ok(true)
947 }
948
949 fn open_one_rtt(&mut self, now: Instant, pn: u64, phase: bool, head: &[u8], rest: &mut [u8]) -> Option<usize> {
950 let k = self.one_rtt.as_mut().unwrap();
951 if phase == k.phase {
952 let n = k.remote.open(pn, head, rest).ok()?;
953 if k.phase_first_recv.is_none_or(|f| pn < f) {
954 if k.phase_first_recv.is_none() {
955 let pto3 = self.recovery.pto(2) * 3;
957 if let Some(p) = k.prev_remote.as_mut() {
958 p.1.get_or_insert(now + pto3);
959 }
960 }
961 k.phase_first_recv = Some(pn);
962 }
963 return Some(n);
964 }
965 if let Some((prev, _)) = &k.prev_remote {
968 if k.phase_first_recv.is_none_or(|f| pn < f) {
969 return prev.open(pn, head, rest).ok();
970 }
971 }
972 if k.next.is_none() {
974 k.next = Some(k.secrets.next_packet_keys());
975 }
976 let n = k.next.as_ref().unwrap().1.open(pn, head, rest).ok()?;
977 if k.phase_first_recv.is_some_and(|f| pn < f) {
978 return None;
979 }
980 let pto3 = self.recovery.pto(2) * 3;
981 let k = self.one_rtt.as_mut().unwrap();
982 let (nl, nr) = k.next.take().unwrap();
983 let old_remote = std::mem::replace(&mut k.remote, nr);
984 k.local = nl;
985 k.prev_remote = Some((old_remote, Some(now + pto3)));
986 k.phase = !k.phase;
987 k.phase_first_recv = Some(pn);
988 k.phase_first_sent = self.recovery.spaces[2].next_pn;
989 k.update_allowed = false;
990 k.sealed = 0;
991 self.stats.key_updates += 1;
992 Some(n)
993 }
994
995 pub fn initiate_key_update(&mut self) -> bool {
997 if !self.handshake_confirmed {
998 return false;
999 }
1000 let next_pn = self.recovery.spaces[2].next_pn;
1001 let Some(k) = self.one_rtt.as_mut() else { return false };
1002 if !k.update_allowed {
1003 return false;
1004 }
1005 if k.next.is_none() {
1006 k.next = Some(k.secrets.next_packet_keys());
1007 }
1008 let (nl, nr) = k.next.take().unwrap();
1009 let old_remote = std::mem::replace(&mut k.remote, nr);
1010 k.local = nl;
1011 k.prev_remote = Some((old_remote, None));
1013 k.phase = !k.phase;
1014 k.phase_first_recv = None;
1015 k.phase_first_sent = next_pn;
1016 k.update_allowed = false;
1017 k.sealed = 0;
1018 self.stats.key_updates += 1;
1019 true
1020 }
1021
1022 fn process_frames(
1023 &mut self,
1024 now: Instant,
1025 remote: SocketAddr,
1026 ptype: PacketType,
1027 space: usize,
1028 payload: &[u8],
1029 dcid: &Cid,
1030 ) -> Result<(bool, bool), TransportError> {
1031 if payload.is_empty() {
1032 return Err(TransportError::proto("packet without frames"));
1033 }
1034 let mut r = Reader::new(payload);
1035 let mut eliciting = false;
1036 let mut non_probing = false;
1037 while !r.is_empty() {
1038 let (ty, f) = frame::parse(&mut r)?;
1039 let allowed = match ptype {
1040 PacketType::Initial | PacketType::Handshake => matches!(
1041 f,
1042 Frame::Padding | Frame::Ping | Frame::Ack { .. } | Frame::Crypto { .. }
1043 ) || matches!(f, Frame::ConnectionClose { frame_type: Some(_), .. }),
1044 _ => true,
1045 };
1046 if !allowed {
1047 return Err(TransportError::frame(PROTOCOL_VIOLATION, ty, "frame not allowed in this packet type"));
1048 }
1049 eliciting |= f.is_ack_eliciting();
1050 non_probing |= !f.is_probing();
1051 if self.is_closed() {
1052 if let Frame::ConnectionClose { code, frame_type, reason } = f {
1054 self.on_peer_close(now, code, frame_type, reason);
1055 }
1056 continue;
1057 }
1058 self.process_frame(now, remote, space, ty, f, dcid)?;
1059 if self.state == State::Drained {
1060 break;
1061 }
1062 }
1063 Ok((eliciting, non_probing))
1064 }
1065
1066 fn on_peer_close(&mut self, now: Instant, code: u64, frame_type: Option<u64>, reason: &[u8]) {
1067 let reason = reason[..reason.len().min(256)].to_vec();
1068 let err = match frame_type {
1069 Some(frame_type) => ConnectionError::PeerTransport { code, frame_type, reason },
1070 None => ConnectionError::PeerApplication { code, reason },
1071 };
1072 self.enter_draining(now, err);
1073 }
1074
1075 fn process_frame(
1076 &mut self,
1077 now: Instant,
1078 remote: SocketAddr,
1079 space: usize,
1080 ty: u64,
1081 f: Frame<'_>,
1082 dcid: &Cid,
1083 ) -> Result<(), TransportError> {
1084 let server_only = |is_server: bool| {
1085 if is_server {
1086 Err(TransportError::frame(PROTOCOL_VIOLATION, ty, "frame only a server may send"))
1087 } else {
1088 Ok(())
1089 }
1090 };
1091 match f {
1092 Frame::Padding | Frame::Ping => {}
1093 Frame::Ack { ranges, delay, .. } => {
1094 let exp = self.peer_params.as_ref().map_or(3, |p| p.ack_delay_exponent);
1095 let delay = Duration::from_micros(delay.checked_shl(exp as u32).unwrap_or(u64::MAX).min(1 << 40));
1096 let res = self.recovery.on_ack(space, &ranges, delay, now, self.handshake_confirmed)?;
1097 for p in res.acked {
1098 self.on_packet_acked(space, p);
1099 }
1100 self.on_packets_lost(space, res.lost);
1101 }
1102 Frame::Crypto { offset, data } => self.on_crypto(space, offset, data)?,
1103 Frame::Stream { id, offset, data, fin } => self.streams.on_stream(id, offset, data, fin)?,
1104 Frame::ResetStream { id, code, final_size } => self.streams.on_reset(id, code, final_size)?,
1105 Frame::StopSending { id, code } => self.streams.on_stop_sending(id, code)?,
1106 Frame::MaxData(m) => self.streams.on_max_data(m),
1107 Frame::MaxStreamData { id, max } => self.streams.on_max_stream_data(id, max)?,
1108 Frame::MaxStreams { bidi, max } => self.streams.on_max_streams(bidi, max),
1109 Frame::DataBlocked(_) => {}
1110 Frame::StreamDataBlocked { id, .. } => self.streams.on_stream_data_blocked(id)?,
1111 Frame::StreamsBlocked { bidi, limit } => self.streams.on_streams_blocked(bidi, limit),
1112 Frame::NewToken { token } => {
1113 server_only(self.is_server)?;
1114 self.received_new_token = Some(token.to_vec());
1115 }
1116 Frame::NewConnectionId { seq, retire_prior_to, cid, reset_token } => {
1117 self.on_new_cid(seq, retire_prior_to, cid, reset_token)?
1118 }
1119 Frame::RetireConnectionId { seq } => self.on_retire_cid(seq, dcid)?,
1120 Frame::PathChallenge(d) => {
1121 if self.path_responses.len() < 8 {
1122 self.path_responses.push_back((d, remote));
1123 }
1124 }
1125 Frame::PathResponse(d) => self.on_path_response(now, d),
1126 Frame::ConnectionClose { code, frame_type, reason } => self.on_peer_close(now, code, frame_type, reason),
1127 Frame::HandshakeDone => {
1128 server_only(self.is_server)?;
1129 if !self.handshake_confirmed {
1130 self.handshake_confirmed = true;
1131 self.discard_space(1);
1132 self.start_mtu_probe();
1133 }
1134 }
1135 }
1136 Ok(())
1137 }
1138
1139 fn on_crypto(&mut self, space: usize, offset: u64, data: &[u8]) -> Result<(), TransportError> {
1142 let cap = self.cfg.transport.crypto_buffer;
1143 let level = Level::ALL[space];
1144 let ci = &mut self.spaces[space].crypto_in;
1145 let end = offset + data.len() as u64;
1146 if end <= ci.read {
1147 if self.is_server && space == 0 && !data.is_empty() && !self.handshake_complete {
1152 self.resend_handshake_flight();
1153 }
1154 return Ok(());
1155 }
1156 if offset > ci.read {
1157 let charge = data.len() + CRYPTO_CHUNK_OVERHEAD;
1160 if end - ci.read > cap as u64 || ci.ooo_bytes + charge > cap {
1161 return Err(TransportError::frame(CRYPTO_BUFFER_EXCEEDED, frame::CRYPTO, "CRYPTO buffer exceeded"));
1162 }
1163 if !ci.ooo.contains_key(&offset) {
1164 ci.ooo_bytes += charge;
1165 ci.ooo.insert(offset, data.to_vec());
1166 }
1167 return Ok(());
1168 }
1169 let skip = (ci.read - offset) as usize;
1170 ci.read = end;
1171 self.feed_handshake(level, &data[skip..])?;
1172 loop {
1174 let ci = &mut self.spaces[space].crypto_in;
1175 let Some((&o, _)) = ci.ooo.first_key_value() else { break };
1176 if o > ci.read {
1177 break;
1178 }
1179 let chunk = ci.ooo.pop_first().unwrap().1;
1180 ci.ooo_bytes -= chunk.len() + CRYPTO_CHUNK_OVERHEAD;
1181 let e = o + chunk.len() as u64;
1182 if e <= ci.read {
1183 continue;
1184 }
1185 let skip = (ci.read - o) as usize;
1186 ci.read = e;
1187 self.feed_handshake(level, &chunk[skip..])?;
1188 }
1189 self.drive_crypto()
1190 }
1191
1192 fn feed_handshake(&mut self, level: Level, data: &[u8]) -> Result<(), TransportError> {
1196 let Some((odcid, retry_scid)) = self.deferred else {
1197 return Ok(self.session.read_handshake(level, data)?);
1198 };
1199 if level != Level::Initial {
1200 return Err(TransportError::new(PROTOCOL_VIOLATION, "handshake data before the ClientHello"));
1201 }
1202 self.hello.extend_from_slice(data);
1203 if self.hello.is_empty() {
1204 return Ok(());
1205 }
1206 let tls = self.hello[0] == 1;
1208 let need = if tls { crate::vn::hello_len(&self.hello) } else { Some(0) };
1209 let Some(need) = need else { return Ok(()) };
1210 if need > self.cfg.transport.crypto_buffer {
1211 return Err(TransportError::new(CRYPTO_BUFFER_EXCEEDED, "ClientHello too large"));
1212 }
1213 if self.hello.len() < need {
1214 return Ok(());
1215 }
1216 let client = if tls { crate::vn::client_versions(&self.hello[..need]) } else { None };
1217 let chosen = crate::vn::choose(self.version, &self.cfg.versions, client.as_ref());
1218 if chosen != self.version {
1219 let original = std::mem::replace(&mut self.version, chosen);
1222 let old = self.spaces[0].keys.replace(self.cfg.provider.initial_keys(chosen, &self.initial_dcid, true));
1223 self.orig_initial = old.map(|k| (original, k));
1224 }
1225 self.deferred = None;
1226 let tp = self.local_params(Some(odcid), retry_scid);
1227 self.session = self.cfg.provider.server_session(self.version, tp)?;
1228 let hello = std::mem::take(&mut self.hello);
1229 Ok(self.session.read_handshake(level, &hello)?)
1230 }
1231
1232 fn drive_crypto(&mut self) -> Result<(), TransportError> {
1234 let mut buf = Vec::new();
1235 loop {
1236 buf.clear();
1237 let change = self.session.write_handshake(&mut buf);
1238 let lvl = self.write_level as usize;
1239 self.spaces[lvl].crypto_out.extend_from_slice(&buf);
1240 match change {
1241 None => break,
1242 Some(KeyChange::Handshake { keys }) => {
1243 self.spaces[1].keys = Some(keys);
1244 self.write_level = Level::Handshake;
1245 }
1246 Some(KeyChange::OneRtt { keys, next }) => {
1247 let Keys { local, remote } = keys;
1248 self.one_rtt = Some(OneRtt {
1249 local: local.packet,
1250 remote: remote.packet,
1251 local_hp: local.header,
1252 remote_hp: remote.header,
1253 secrets: next,
1254 phase: false,
1255 next: None,
1256 prev_remote: None,
1257 phase_first_sent: 0,
1258 phase_first_recv: None,
1259 update_allowed: false,
1260 sealed: 0,
1261 });
1262 self.write_level = Level::OneRtt;
1263 }
1264 }
1265 }
1266 if self.peer_params.is_none() {
1267 if let Some(tp) = self.session.peer_transport_params() {
1268 let p = TransportParams::decode(tp, !self.is_server)?;
1269 self.apply_peer_params(p)?;
1270 }
1271 }
1272 if !self.handshake_complete && !self.session.is_handshaking() {
1273 if self.peer_params.is_none() {
1274 return Err(TransportError::new(TRANSPORT_PARAMETER_ERROR, "missing transport parameters"));
1275 }
1276 self.handshake_complete = true;
1277 self.state = State::Established;
1278 self.events.push_back(Event::Connected);
1279 if self.is_server {
1280 self.handshake_confirmed = true;
1281 self.handshake_done_pending = true;
1282 self.discard_space(1);
1283 if self.cfg.new_token_lifetime.is_some() {
1284 self.new_token_pending = true;
1285 }
1286 self.start_mtu_probe();
1287 }
1288 self.issue_cids();
1289 }
1290 Ok(())
1291 }
1292
1293 fn apply_peer_params(&mut self, p: TransportParams) -> Result<(), TransportError> {
1294 let err = |r| TransportError::new(TRANSPORT_PARAMETER_ERROR, r);
1295 if p.initial_source_connection_id != self.peer_initial_scid {
1296 return Err(err("initial_source_connection_id mismatch"));
1297 }
1298 if !self.is_server {
1299 if p.original_destination_connection_id != Some(self.orig_dcid) {
1300 return Err(err("original_destination_connection_id mismatch"));
1301 }
1302 if p.retry_source_connection_id != self.retry_scid {
1303 return Err(err("retry_source_connection_id mismatch"));
1304 }
1305 self.remote_cids[0].token = p.stateless_reset_token;
1306 if let Some(t) = p.stateless_reset_token {
1307 self.endpoint_events.push_back(EndpointEvent::ResetToken(t));
1308 }
1309 }
1310 self.streams.set_peer_params(&p);
1311 let peer_idle = Duration::from_millis(p.max_idle_timeout);
1312 let local_idle = self.cfg.transport.max_idle_timeout;
1313 self.idle_timeout = match (local_idle.is_zero(), peer_idle.is_zero()) {
1314 (true, true) => Duration::ZERO,
1315 (true, false) => peer_idle,
1316 (false, true) => local_idle,
1317 (false, false) => local_idle.min(peer_idle),
1318 };
1319 self.recovery.max_ack_delay = Duration::from_millis(p.max_ack_delay);
1320 self.peer_params = Some(p);
1321 Ok(())
1322 }
1323
1324 fn discard_space(&mut self, space: usize) {
1325 let s = &mut self.spaces[space];
1326 if s.discarded {
1327 return;
1328 }
1329 s.discarded = true;
1330 s.keys = None;
1331 if space == 0 {
1332 self.orig_initial = None;
1333 }
1334 let s = &mut self.spaces[space];
1335 s.crypto_out = Vec::new();
1336 s.crypto_retx.clear();
1337 s.ack_now = false;
1338 s.ack_deadline = None;
1339 s.probes = 0;
1340 self.recovery.discard(space);
1341 }
1342
1343 fn issue_cids(&mut self) {
1346 let peer_limit = self.peer_params.as_ref().map_or(2, |p| p.active_connection_id_limit);
1347 let want = peer_limit.min(self.cfg.transport.max_local_cids);
1348 while (self.local_cids.iter().filter(|c| !c.retired).count() as u64) < want {
1349 let mut b = [0u8; 20];
1350 self.cfg.provider.fill_random(&mut b[..self.cfg.cid_len]);
1351 let cid = Cid::new(&b[..self.cfg.cid_len]);
1352 let seq = self.next_local_seq;
1353 self.next_local_seq += 1;
1354 self.local_cids.push(LocalCid { seq, cid, retired: false });
1355 self.pending_new_cids.push_back(seq);
1356 self.endpoint_events.push_back(EndpointEvent::NewCid(cid));
1357 }
1358 }
1359
1360 fn on_retire_cid(&mut self, seq: u64, dcid: &Cid) -> Result<(), TransportError> {
1361 if seq >= self.next_local_seq {
1362 return Err(TransportError::frame(PROTOCOL_VIOLATION, frame::RETIRE_CONNECTION_ID, "retired an unissued CID"));
1363 }
1364 let Some(c) = self.local_cids.iter_mut().find(|c| c.seq == seq) else { return Ok(()) };
1365 if c.retired {
1366 return Ok(());
1367 }
1368 if c.cid == *dcid {
1369 return Err(TransportError::frame(
1370 PROTOCOL_VIOLATION,
1371 frame::RETIRE_CONNECTION_ID,
1372 "retired the CID the packet was sent to",
1373 ));
1374 }
1375 c.retired = true;
1376 let cid = c.cid;
1377 self.endpoint_events.push_back(EndpointEvent::RetireCid(cid));
1378 self.local_cids.retain(|c| !c.retired);
1379 self.issue_cids();
1380 Ok(())
1381 }
1382
1383 fn on_new_cid(&mut self, seq: u64, rpt: u64, cid: &[u8], token: [u8; 16]) -> Result<(), TransportError> {
1384 let ty = frame::NEW_CONNECTION_ID;
1385 if self.remote_cids[0].cid.is_empty() {
1386 return Err(TransportError::frame(PROTOCOL_VIOLATION, ty, "NEW_CONNECTION_ID with a zero-length CID"));
1387 }
1388 let cid = Cid::new(cid);
1389 if let Some(c) = self.remote_cids.iter().find(|c| c.seq == seq) {
1390 if c.cid != cid || (c.token.is_some() && c.token != Some(token)) {
1391 return Err(TransportError::frame(PROTOCOL_VIOLATION, ty, "NEW_CONNECTION_ID changed"));
1392 }
1393 return Ok(());
1394 }
1395 if seq < self.retire_prior_to {
1396 self.queue_retire(seq)?;
1398 return Ok(());
1399 }
1400 self.remote_cids.push(RemoteCid { seq, cid, token: Some(token) });
1401 self.endpoint_events.push_back(EndpointEvent::ResetToken(token));
1402 if rpt > self.retire_prior_to {
1403 self.retire_prior_to = rpt;
1404 let mut i = 0;
1405 while i < self.remote_cids.len() {
1406 if self.remote_cids[i].seq < rpt {
1407 let c = self.remote_cids.remove(i);
1408 self.queue_retire(c.seq)?;
1409 } else {
1410 i += 1;
1411 }
1412 }
1413 if self.remote_cids.is_empty() {
1414 return Err(TransportError::frame(PROTOCOL_VIOLATION, ty, "no connection ID left"));
1415 }
1416 self.remote_cids.sort_by_key(|c| c.seq);
1418 self.remote_cid_seq = self.remote_cids[0].seq;
1419 }
1420 if self.remote_cids.len() as u64 > self.cfg.transport.active_connection_id_limit {
1421 return Err(TransportError::frame(CONNECTION_ID_LIMIT_ERROR, ty, "too many connection IDs"));
1422 }
1423 Ok(())
1424 }
1425
1426 fn queue_retire(&mut self, seq: u64) -> Result<(), TransportError> {
1431 if self.pending_retire.contains(&seq) {
1432 return Ok(());
1433 }
1434 let cap = (self.cfg.transport.active_connection_id_limit.max(2) * 8) as usize;
1435 if self.pending_retire.len() >= cap {
1436 return Err(TransportError::frame(
1437 CONNECTION_ID_LIMIT_ERROR,
1438 frame::NEW_CONNECTION_ID,
1439 "too many connection IDs waiting to be retired",
1440 ));
1441 }
1442 self.pending_retire.push_back(seq);
1443 Ok(())
1444 }
1445
1446 pub fn rotate_remote_cid(&mut self) -> bool {
1449 if self.remote_cids.len() < 2 {
1450 return false;
1451 }
1452 let old = self.remote_cids.remove(0);
1453 self.pending_retire.push_back(old.seq);
1454 self.remote_cid_seq = self.remote_cids[0].seq;
1455 true
1456 }
1457
1458 fn migrate(&mut self, now: Instant, remote: SocketAddr) {
1461 let mut new = Path::new(remote, false);
1463 new.recv_bytes = self.stats.recv_bytes.min(MIN_INITIAL_SIZE as u64 * 3);
1465 let old = std::mem::replace(&mut self.path, new);
1466 self.prev_path = Some(old);
1467 self.recovery.cc.reset();
1468 self.rotate_remote_cid();
1469 self.start_challenge(now);
1470 }
1471
1472 fn start_challenge(&mut self, now: Instant) {
1473 let mut d = [0u8; 8];
1474 self.cfg.provider.fill_random(&mut d);
1475 let pto = self.recovery.pto(2);
1476 self.path.challenge = Some((d, now + (pto * 3).max(Duration::from_millis(100))));
1477 self.path.challenge_pending = true;
1478 }
1479
1480 fn on_path_response(&mut self, now: Instant, d: [u8; 8]) {
1481 if let Some((c, _)) = self.path.challenge {
1482 if c == d {
1483 self.path.challenge = None;
1484 self.path.challenge_pending = false;
1485 if !self.path.validated {
1486 self.path.validated = true;
1487 self.prev_path = None;
1488 self.events.push_back(Event::PathMigrated(self.path.remote));
1489 }
1490 }
1491 }
1492 let _ = now;
1493 }
1494
1495 fn on_packet_acked(&mut self, space: usize, p: SentPacket) {
1498 if p.mtu_probe_size() > 0 {
1499 self.mds = p.mtu_probe_size();
1500 self.recovery.cc.mds = self.mds as u64;
1501 self.mtu_probe_inflight = false;
1502 self.next_mtu_probe(true);
1503 }
1504 if space == 2 {
1505 if let Some(k) = self.one_rtt.as_mut() {
1506 if p.pn >= k.phase_first_sent {
1507 k.update_allowed = true;
1508 }
1509 }
1510 }
1511 for f in p.frames {
1512 match f {
1513 SentFrame::Stream { id, off, len, fin } => self.streams.on_stream_acked(id, off, len as u64, fin),
1514 SentFrame::Crypto { off, len } => {
1515 self.spaces[space].crypto_retx.remove(off, off + len as u64);
1516 }
1517 SentFrame::Control(Control::ResetStream(id)) => self.streams.on_reset_acked(id),
1518 SentFrame::Ack(largest) => {
1519 let s = &mut self.spaces[space];
1521 if largest >= s.ack_floor && s.recv.max().is_some_and(|m| m > largest) {
1522 s.recv.remove_below(largest + 1);
1523 s.ack_floor = largest + 1;
1524 }
1525 }
1526 _ => {}
1527 }
1528 }
1529 }
1530
1531 fn on_packets_lost(&mut self, space: usize, lost: Vec<SentPacket>) {
1532 for p in lost {
1533 self.stats.lost_packets += 1;
1534 if p.mtu_probe_size() > 0 {
1535 self.mtu_probe_inflight = false;
1536 self.next_mtu_probe(false);
1537 }
1538 self.requeue(space, &p.frames);
1539 }
1540 }
1541
1542 fn requeue(&mut self, space: usize, frames: &[SentFrame]) {
1543 for &f in frames {
1544 match f {
1545 SentFrame::Stream { id, off, len, fin } => self.streams.on_stream_lost(id, off, len as u64, fin),
1546 SentFrame::Crypto { off, len } => {
1547 if !self.spaces[space].discarded {
1548 self.spaces[space].crypto_retx.insert(off, off + len as u64);
1549 }
1550 }
1551 SentFrame::Control(c) => {
1552 if !self.streams.control.contains(&c) {
1553 self.streams.control.push_back(c);
1554 }
1555 }
1556 SentFrame::NewConnectionId(seq) => {
1557 if self.local_cids.iter().any(|c| c.seq == seq) && !self.pending_new_cids.contains(&seq) {
1558 self.pending_new_cids.push_back(seq);
1559 }
1560 }
1561 SentFrame::RetireConnectionId(seq) => {
1562 if !self.pending_retire.contains(&seq) {
1563 self.pending_retire.push_back(seq);
1564 }
1565 }
1566 SentFrame::HandshakeDone => self.handshake_done_pending = true,
1567 SentFrame::NewToken => self.new_token_pending = true,
1568 SentFrame::Ack(_) | SentFrame::Ping | SentFrame::MtuProbe(_) => {}
1569 }
1570 }
1571 }
1572
1573 fn start_mtu_probe(&mut self) {
1574 if self.cfg.transport.mtu_probing && self.cfg.transport.max_datagram_size > self.mds {
1575 self.next_mtu_probe(true);
1576 }
1577 }
1578
1579 fn next_mtu_probe(&mut self, success: bool) {
1581 let peer = self.peer_params.as_ref().map_or(1200, |p| p.max_udp_payload_size) as usize;
1582 let target = self.cfg.transport.max_datagram_size.min(peer);
1583 if target <= self.mds {
1584 self.mtu_probe = None;
1585 return;
1586 }
1587 self.mtu_probe = match self.mtu_probe {
1588 Some((size, tries)) if !success && tries < 2 => Some((size, tries + 1)),
1589 Some((size, _)) if !success => {
1590 let mid = (self.mds + size) / 2;
1591 if mid > self.mds + 20 {
1592 Some((mid, 0))
1593 } else {
1594 None
1595 }
1596 }
1597 _ => Some((target, 0)),
1598 };
1599 }
1600
1601 pub fn poll_timeout(&self) -> Option<Instant> {
1605 let mut t: Option<Instant> = None;
1606 let mut put = |x: Option<Instant>| {
1607 if let Some(x) = x {
1608 t = Some(t.map_or(x, |y| y.min(x)));
1609 }
1610 };
1611 match self.state {
1612 State::Drained => return None,
1613 State::Closing(u) | State::Draining(u) => return Some(u),
1614 _ => {}
1615 }
1616 if !self.idle_timeout.is_zero() {
1617 let idle = self.idle_timeout.max(self.recovery.pto(2) * 3);
1618 put(Some(self.last_activity + idle));
1619 }
1620 for s in &self.spaces {
1621 put(s.ack_deadline);
1622 }
1623 put(self.loss_timer());
1624 put(self.path.challenge.map(|c| c.1));
1625 if let Some(k) = &self.one_rtt {
1626 put(k.prev_remote.as_ref().and_then(|p| p.1));
1627 }
1628 put(self.pacing_until);
1629 t
1630 }
1631
1632 fn active_spaces(&self) -> [bool; 3] {
1633 [
1634 self.spaces[0].keys.is_some(),
1635 self.spaces[1].keys.is_some(),
1636 self.one_rtt.is_some(),
1637 ]
1638 }
1639
1640 fn loss_timer(&self) -> Option<Instant> {
1641 if let Some((t, _)) = self.recovery.earliest_loss_time() {
1642 return Some(t);
1643 }
1644 if self.is_server && self.path.budget() < MIN_INITIAL_SIZE / 2 {
1645 return None; }
1647 let anti_deadlock = !self.is_server && !self.handshake_complete;
1648 self.recovery
1649 .pto_deadline(self.last_activity, self.active_spaces(), self.handshake_confirmed, anti_deadlock)
1650 .map(|x| x.0)
1651 }
1652
1653 pub fn handle_timeout(&mut self, now: Instant) {
1654 match self.state {
1655 State::Drained => return,
1656 State::Closing(u) | State::Draining(u) => {
1657 if now >= u {
1658 let err = self.error.clone().unwrap_or(ConnectionError::IdleTimeout);
1659 self.drain_now(err);
1660 }
1661 return;
1662 }
1663 _ => {}
1664 }
1665 if self.pacing_until.is_some_and(|t| now >= t) {
1666 self.pacing_until = None;
1667 }
1668 if !self.idle_timeout.is_zero() {
1669 let idle = self.idle_timeout.max(self.recovery.pto(2) * 3);
1670 if now >= self.last_activity + idle {
1671 self.drain_now(ConnectionError::IdleTimeout);
1672 return;
1673 }
1674 }
1675 for s in &mut self.spaces {
1676 if s.ack_deadline.is_some_and(|d| now >= d) {
1677 s.ack_deadline = None;
1678 s.ack_now = true;
1679 }
1680 }
1681 if let Some((_, deadline)) = self.path.challenge {
1682 if now >= deadline {
1683 self.path.challenge = None;
1685 self.path.challenge_pending = false;
1686 if let Some(prev) = self.prev_path.take() {
1687 self.path = prev;
1688 }
1689 }
1690 }
1691 if let Some(k) = self.one_rtt.as_mut() {
1692 if k.prev_remote.as_ref().and_then(|p| p.1).is_some_and(|d| now >= d) {
1693 k.prev_remote = None;
1694 }
1695 }
1696 if let Some((t, space)) = self.recovery.earliest_loss_time() {
1698 if now >= t {
1699 let lost = self.recovery.detect_lost(space, now);
1700 self.on_packets_lost(space, lost);
1701 }
1702 return;
1703 }
1704 if let Some(t) = self.loss_timer() {
1705 if now >= t {
1706 self.on_pto(now);
1707 }
1708 }
1709 }
1710
1711 fn resend_handshake_flight(&mut self) {
1713 for space in 0..2 {
1714 if self.spaces[space].keys.is_none() || self.spaces[space].discarded {
1715 continue;
1716 }
1717 let frames: Vec<SentFrame> = self.recovery.spaces[space].sent.values().flat_map(|p| p.frames.iter().copied()).collect();
1718 self.requeue(space, &frames);
1719 }
1720 }
1721
1722 fn on_pto(&mut self, _now: Instant) {
1723 let active = self.active_spaces();
1724 let anti_deadlock = !self.is_server && !self.handshake_complete;
1725 let space = match self.recovery.pto_deadline(self.last_activity, active, self.handshake_confirmed, anti_deadlock) {
1726 Some((_, s)) => s,
1727 None => return,
1728 };
1729 self.recovery.pto_count += 1;
1730 let frames: Vec<SentFrame> = if space < 2 {
1732 self.recovery.spaces[space].sent.values().flat_map(|p| p.frames.iter().copied()).collect()
1733 } else {
1734 self.recovery.spaces[space].sent.values().filter(|p| p.ack_eliciting).take(2).flat_map(|p| p.frames.iter().copied()).collect()
1735 };
1736 self.requeue(space, &frames);
1737 self.spaces[space].probes = 2;
1738 if space == 1 && !self.is_server && self.spaces[0].keys.is_some() {
1740 self.spaces[0].probes = 1;
1741 }
1742 }
1743
1744 pub fn poll_transmit(&mut self, now: Instant, buf: &mut Vec<u8>, max_datagrams: usize) -> Option<Transmit> {
1748 buf.clear();
1749 if matches!(self.state, State::Draining(_) | State::Drained) {
1750 return None;
1751 }
1752 self.maybe_auto_key_update();
1753 if let Some(&(_, addr)) = self.path_responses.front() {
1755 if addr != self.path.remote {
1756 let (d, addr) = self.path_responses.pop_front().unwrap();
1757 if self.build_path_response(now, buf, d, addr) {
1758 return Some(Transmit { destination: addr, size: buf.len(), segment_size: None });
1759 }
1760 buf.clear();
1761 }
1762 }
1763 let seg = self.mds;
1764 let mut count = 0;
1765 while count < max_datagrams.max(1) {
1766 let before = buf.len();
1767 self.probe_allowed = count == 0;
1769 let built = self.build_datagram(now, buf);
1770 self.probe_allowed = false;
1771 if !built {
1772 break;
1773 }
1774 let n = buf.len() - before;
1775 count += 1;
1776 if n != seg {
1777 break;
1778 }
1779 if let State::Closing(_) = self.state {
1780 break;
1781 }
1782 }
1783 if count == 0 {
1784 return None;
1785 }
1786 let dest = self.path.remote;
1787 Some(Transmit { destination: dest, size: buf.len(), segment_size: if count > 1 { Some(seg) } else { None } })
1788 }
1789
1790 fn maybe_auto_key_update(&mut self) {
1791 let Some(k) = &self.one_rtt else { return };
1792 let limit = match self.cfg.transport.key_update_interval {
1793 Some(n) => n,
1794 None => k.local.confidentiality_limit().saturating_sub(1000),
1795 };
1796 if k.sealed >= limit && k.update_allowed {
1797 self.initiate_key_update();
1798 }
1799 }
1800
1801 fn build_path_response(&mut self, now: Instant, buf: &mut Vec<u8>, d: [u8; 8], addr: SocketAddr) -> bool {
1802 if self.one_rtt.is_none() {
1803 return false;
1804 }
1805 let Some(mut b) = self.begin_packet(buf, 2) else { return false };
1806 frame::put_path(buf, true, &d);
1807 b.eliciting = true;
1808 let budget = 3 * MIN_INITIAL_SIZE;
1810 let target = MIN_INITIAL_SIZE.min(budget) - self.one_rtt.as_ref().unwrap().local.tag_len();
1811 if buf.len() < target {
1812 buf.resize(target, 0);
1813 }
1814 self.finish_packet(now, buf, b);
1815 let _ = addr;
1816 true
1817 }
1818
1819 fn datagram_limit(&self) -> usize {
1821 let mut limit = self.mds;
1822 if !self.handshake_confirmed {
1823 limit = MIN_INITIAL_SIZE;
1824 }
1825 limit.min(self.path.budget())
1826 }
1827
1828 fn wants_ack(&self, space: usize) -> bool {
1829 let s = &self.spaces[space];
1830 s.ack_now && !s.recv.is_empty()
1831 }
1832
1833 fn space_has_data(&self, space: usize) -> bool {
1834 let s = &self.spaces[space];
1835 if s.has_crypto() || s.probes > 0 {
1836 return true;
1837 }
1838 if space == 2 {
1839 return self.handshake_done_pending
1840 || self.ping_pending
1841 || self.path.challenge_pending
1842 || self.path_responses.front().is_some_and(|x| x.1 == self.path.remote)
1843 || !self.pending_new_cids.is_empty()
1844 || !self.pending_retire.is_empty()
1845 || self.new_token_pending
1846 || !self.streams.control.is_empty()
1847 || self.streams.has_pending_data()
1848 || (self.probe_allowed && self.mtu_probe.is_some() && !self.mtu_probe_inflight && self.recovery.rtt.has_sample);
1849 }
1850 false
1851 }
1852
1853 fn build_datagram(&mut self, now: Instant, buf: &mut Vec<u8>) -> bool {
1855 let dstart = buf.len();
1856 let closing = matches!(self.state, State::Closing(_));
1857 if closing {
1858 let due = self.close_sent_count == 0 || self.close_recv_count >= (1 << self.close_sent_count.min(10));
1860 if !due {
1861 return false;
1862 }
1863 self.close_recv_count = 0;
1864 }
1865 let limit_total = self.datagram_limit();
1866 if limit_total < 64 {
1867 return false;
1868 }
1869 let cwnd_room = self.recovery.cc.available() as usize;
1870 let probing = self.spaces.iter().any(|s| s.probes > 0);
1871 if self.cfg.transport.pacing && !closing && !probing && self.recovery.rtt.has_sample {
1873 if let Some(t) = self.recovery.pacer.delay(
1874 now,
1875 self.mds as u64,
1876 self.recovery.rtt.smoothed,
1877 self.recovery.cc.cwnd,
1878 self.mds as u64,
1879 ) {
1880 if self.spaces.iter().all(|s| !s.ack_now) {
1881 self.pacing_until = Some(t);
1882 return false;
1883 }
1884 }
1885 }
1886 let mut pending: Option<Building> = None;
1887 let mut needs_padding = false;
1888 let mut sent_initial = false;
1889 for space in 0..3 {
1890 let has_keys = if space == 2 { self.one_rtt.is_some() } else { self.spaces[space].keys.is_some() };
1891 if !has_keys {
1892 continue;
1893 }
1894 if space == 2 && !self.handshake_complete && !closing {
1898 continue;
1899 }
1900 let ack = self.wants_ack(space);
1901 let data = self.space_has_data(space);
1902 if !(ack || data || (closing && self.close_space_ok(space))) {
1903 continue;
1904 }
1905 let used = buf.len() - dstart;
1907 let tag = self.tag_len(space);
1908 if used + 40 + tag >= limit_total {
1909 break;
1910 }
1911 let cc_limited = !closing && !probing && cwnd_room < self.mds;
1916 let challenge = space == 2 && self.path.challenge_pending;
1917 if cc_limited && !ack && !challenge {
1918 continue;
1919 }
1920 if let Some(p) = pending.take() {
1921 self.finish_packet(now, buf, p);
1922 }
1923 let Some(mut b) = self.begin_packet(buf, space) else { continue };
1924 let limit = dstart + limit_total - tag;
1925 let ack_due = ack || self.spaces[space].unacked_eliciting > 0;
1928 self.write_frames(now, buf, &mut b, limit, closing, cc_limited);
1929 let ack_only = b.frames.iter().all(|f| matches!(f, SentFrame::Ack(_)));
1930 if !closing && ((b.frames.is_empty() && buf.len() == b.pn_at + b.pn_len) || (ack_only && !ack_due)) {
1931 buf.truncate(b.start);
1933 continue;
1934 }
1935 if space == 0 {
1936 sent_initial = true;
1937 if !self.is_server || b.eliciting {
1938 needs_padding = true;
1939 }
1940 }
1941 if b.mtu_probe {
1942 needs_padding = false;
1943 }
1944 pending = Some(b);
1945 if space == 2 {
1946 break;
1947 }
1948 }
1949 let Some(mut last) = pending else {
1950 return false;
1951 };
1952 let tag = self.tag_len(last.space);
1953 if needs_padding {
1954 let target = dstart + MIN_INITIAL_SIZE.min(limit_total) - tag;
1955 if buf.len() < target {
1956 buf.resize(target, 0);
1957 }
1958 }
1959 if last.mtu_probe {
1960 let size = self.mtu_probe.map_or(self.mds, |m| m.0);
1961 let target = dstart + size - tag;
1962 if buf.len() < target {
1963 buf.resize(target, 0);
1964 }
1965 last.eliciting = true;
1966 }
1967 self.finish_packet(now, buf, last);
1968 if closing {
1969 self.close_sent_count += 1;
1970 }
1971 let n = buf.len() - dstart;
1972 self.path.sent_bytes += n as u64;
1973 self.stats.sent_bytes += n as u64;
1974 if !self.is_server && self.spaces[1].keys.is_some() && !sent_initial && self.spaces[0].keys.is_some() {
1976 let sent_handshake = self.recovery.spaces[1].next_pn > 0;
1977 if sent_handshake {
1978 self.discard_space(0);
1979 }
1980 }
1981 true
1982 }
1983
1984 fn close_space_ok(&self, space: usize) -> bool {
1985 space == 2 || !self.handshake_confirmed
1987 }
1988
1989 fn tag_len(&self, space: usize) -> usize {
1990 if space == 2 {
1991 self.one_rtt.as_ref().map_or(16, |k| k.local.tag_len())
1992 } else {
1993 self.spaces[space].keys.as_ref().map_or(16, |k| k.local.packet.tag_len())
1994 }
1995 }
1996
1997 fn begin_packet(&mut self, buf: &mut Vec<u8>, space: usize) -> Option<Building> {
1998 let start = buf.len();
1999 let pn = self.recovery.spaces[space].next_pn;
2000 let pn_len = packet::pn_len(pn, self.recovery.spaces[space].largest_acked);
2001 let dcid = self.remote_cids[0].cid;
2002 let (len_at, pn_at) = if space == 2 {
2003 let phase = self.one_rtt.as_ref()?.phase;
2004 (None, packet::put_short_header(buf, false, phase, &dcid, pn, pn_len))
2005 } else {
2006 let ty = if space == 0 { PacketType::Initial } else { PacketType::Handshake };
2007 let token = if space == 0 { Some(&self.token[..]).filter(|_| !self.is_server).or(Some(&[][..])) } else { None };
2008 let scid = self.local_cids[0].cid;
2009 let (l, p) = packet::put_long_header(buf, self.version, ty, &dcid, &scid, token, pn, pn_len);
2010 (Some(l), p)
2011 };
2012 Some(Building { space, start, len_at, pn_at, pn, pn_len, eliciting: false, frames: Vec::new(), mtu_probe: false })
2013 }
2014
2015 fn write_frames(&mut self, now: Instant, buf: &mut Vec<u8>, b: &mut Building, limit: usize, closing: bool, cc_limited: bool) {
2016 let space = b.space;
2017 if !self.spaces[space].recv.is_empty() && (self.spaces[space].ack_now || self.spaces[space].unacked_eliciting > 0 || closing || !cc_limited) {
2019 let s = &mut self.spaces[space];
2020 let delay = s.largest_recv.map_or(0, |(_, t)| now.saturating_duration_since(t).as_micros() as u64)
2021 >> self.cfg.transport.ack_delay_exponent;
2022 let before = buf.len();
2023 let delay = if space == 2 { delay } else { 0 };
2024 frame::put_ack(buf, &s.recv, delay, self.cfg.transport.max_ack_ranges);
2025 if buf.len() > limit {
2026 buf.truncate(before);
2027 } else {
2028 b.frames.push(SentFrame::Ack(s.recv.max().unwrap()));
2029 s.ack_now = false;
2030 s.ack_deadline = None;
2031 s.unacked_eliciting = 0;
2032 }
2033 }
2034 if closing {
2035 let (code, ft, reason) = self.close.clone().unwrap_or((0, Some(0), Vec::new()));
2036 let reason = &reason[..reason.len().min(limit.saturating_sub(buf.len() + 24))];
2037 if space == 2 {
2038 frame::put_close(buf, code, ft, reason);
2039 } else {
2040 match ft {
2042 Some(t) => frame::put_close(buf, code, Some(t), reason),
2043 None => frame::put_close(buf, APPLICATION_ERROR, Some(0), b""),
2044 }
2045 }
2046 b.frames.push(SentFrame::Ping);
2047 return;
2048 }
2049 if space == 2 && self.path.challenge_pending && buf.len() + 9 <= limit {
2052 if let Some((d, _)) = self.path.challenge {
2053 frame::put_path(buf, false, &d);
2054 self.path.challenge_pending = false;
2055 b.eliciting = true;
2056 b.frames.push(SentFrame::Ping);
2057 }
2058 }
2059 if cc_limited {
2060 return;
2061 }
2062 if space == 2 {
2063 if self.handshake_done_pending && buf.len() + 1 <= limit {
2064 frame::put_simple(buf, frame::HANDSHAKE_DONE, &[]);
2065 self.handshake_done_pending = false;
2066 b.frames.push(SentFrame::HandshakeDone);
2067 b.eliciting = true;
2068 }
2069 while let Some(&(d, addr)) = self.path_responses.front() {
2070 if addr != self.path.remote || buf.len() + 9 > limit {
2071 break;
2072 }
2073 frame::put_path(buf, true, &d);
2074 self.path_responses.pop_front();
2075 b.eliciting = true;
2076 }
2077 while let Some(&seq) = self.pending_new_cids.front() {
2078 if buf.len() + 1 + 8 + 8 + 21 + 16 > limit {
2079 break;
2080 }
2081 self.pending_new_cids.pop_front();
2082 if let Some(c) = self.local_cids.iter().find(|c| c.seq == seq && !c.retired) {
2083 let token = self.cfg.reset_token(&c.cid);
2084 frame::put_new_connection_id(buf, seq, 0, &c.cid, &token);
2085 b.frames.push(SentFrame::NewConnectionId(seq));
2086 b.eliciting = true;
2087 }
2088 }
2089 while let Some(&seq) = self.pending_retire.front() {
2090 if buf.len() + 9 > limit {
2091 break;
2092 }
2093 self.pending_retire.pop_front();
2094 frame::put_simple(buf, frame::RETIRE_CONNECTION_ID, &[seq]);
2095 b.frames.push(SentFrame::RetireConnectionId(seq));
2096 b.eliciting = true;
2097 }
2098 if self.new_token_pending && buf.len() + 80 <= limit {
2099 self.new_token_pending = false;
2100 let token = self.new_token.get_or_insert_with(|| {
2101 crate::token::new_token(&self.cfg, self.path.remote, now)
2102 });
2103 frame::put_new_token(buf, token);
2104 b.frames.push(SentFrame::NewToken);
2105 b.eliciting = true;
2106 }
2107 let mut n = self.streams.control.len();
2108 while n > 0 {
2109 n -= 1;
2110 let Some(c) = self.streams.control.pop_front() else { break };
2111 match self.streams.write_control(c, buf, limit) {
2112 None => {}
2113 Some(true) => {
2114 b.frames.push(SentFrame::Control(c));
2115 b.eliciting = true;
2116 }
2117 Some(false) => {
2118 self.streams.control.push_front(c);
2119 break;
2120 }
2121 }
2122 }
2123 }
2124 while buf.len() + 16 < limit {
2126 let s = &mut self.spaces[space];
2127 let room = (limit - buf.len()) as u64;
2128 let (off, len) = if let Some((a, e)) = s.crypto_retx.first() {
2129 let ov = frame::crypto_overhead(a, (e - a) as usize) as u64;
2130 if room <= ov {
2131 break;
2132 }
2133 let len = (e - a).min(room - ov);
2134 s.crypto_retx.remove(a, a + len);
2135 (a, len)
2136 } else if s.crypto_sent < s.crypto_out.len() as u64 {
2137 let a = s.crypto_sent;
2138 let avail = s.crypto_out.len() as u64 - a;
2139 let ov = frame::crypto_overhead(a, avail as usize) as u64;
2140 if room <= ov {
2141 break;
2142 }
2143 let len = avail.min(room - ov);
2144 s.crypto_sent += len;
2145 (a, len)
2146 } else {
2147 break;
2148 };
2149 frame::put_crypto(buf, off, &s.crypto_out[off as usize..(off + len) as usize]);
2150 b.frames.push(SentFrame::Crypto { off, len: len as u32 });
2151 b.eliciting = true;
2152 }
2153 if space == 2 {
2154 if self.probe_allowed && self.mtu_probe.is_some() && !self.mtu_probe_inflight && self.recovery.rtt.has_sample {
2155 let size = self.mtu_probe.unwrap().0;
2156 if b.frames.iter().all(|f| matches!(f, SentFrame::Ack(_))) {
2158 frame::put_simple(buf, frame::PING, &[]);
2159 b.frames.push(SentFrame::MtuProbe(size as u16));
2160 b.mtu_probe = true;
2161 b.eliciting = true;
2162 self.mtu_probe_inflight = true;
2163 return;
2164 }
2165 }
2166 let before = b.frames.len();
2167 self.streams.write_frames(buf, limit, &mut b.frames);
2168 if b.frames.len() > before {
2169 b.eliciting = true;
2170 } else if !self.streams.has_pending_data() && self.recovery.cc.available() > 0 {
2171 self.recovery.app_limited = true;
2172 }
2173 if self.streams.has_pending_data() {
2174 self.recovery.app_limited = false;
2175 }
2176 if !self.raw_frames.is_empty() && buf.len() + self.raw_frames.len() <= limit {
2177 buf.extend_from_slice(&self.raw_frames);
2178 self.raw_frames.clear();
2179 b.frames.push(SentFrame::Ping);
2180 b.eliciting = true;
2181 }
2182 if self.ping_pending && buf.len() < limit {
2183 frame::put_simple(buf, frame::PING, &[]);
2184 self.ping_pending = false;
2185 b.frames.push(SentFrame::Ping);
2186 b.eliciting = true;
2187 }
2188 }
2189 let s = &mut self.spaces[space];
2190 if s.probes > 0 {
2191 s.probes -= 1;
2192 if !b.eliciting && buf.len() < limit {
2193 frame::put_simple(buf, frame::PING, &[]);
2194 b.frames.push(SentFrame::Ping);
2195 b.eliciting = true;
2196 }
2197 }
2198 }
2199
2200 fn finish_packet(&mut self, now: Instant, buf: &mut Vec<u8>, b: Building) {
2202 let payload_start = b.pn_at + b.pn_len;
2203 if buf.len() < b.pn_at + 4 {
2205 buf.resize(b.pn_at + 4, 0);
2206 }
2207 let tag_len = self.tag_len(b.space);
2208 if let Some(len_at) = b.len_at {
2209 let len = buf.len() - b.pn_at + tag_len;
2210 put_varint_fixed(&mut buf[len_at..], len as u64, 2);
2211 }
2212 let end = buf.len();
2213 buf.resize(end + tag_len, 0);
2214 {
2215 let (head, rest) = buf[b.start..].split_at_mut(payload_start - b.start);
2216 let (payload, tag) = rest.split_at_mut(end - payload_start);
2217 if b.space == 2 {
2218 let k = self.one_rtt.as_mut().unwrap();
2219 k.local.seal(b.pn, head, payload, tag);
2220 k.sealed += 1;
2221 } else {
2222 self.spaces[b.space].keys.as_ref().unwrap().local.packet.seal(b.pn, head, payload, tag);
2223 }
2224 }
2225 let hp: &dyn HeaderKey = if b.space == 2 {
2226 &*self.one_rtt.as_ref().unwrap().local_hp
2227 } else {
2228 &*self.spaces[b.space].keys.as_ref().unwrap().local.header
2229 };
2230 packet::protect(buf, b.start, b.pn_at, b.pn_len, hp);
2231 let size = buf.len() - b.start;
2232 let sp = &mut self.recovery.spaces[b.space];
2233 sp.next_pn = b.pn + 1;
2234 if b.space == 2 {
2235 if sp.next_pn >= sp.skip_at {
2238 if sp.skip_at != 0 {
2239 sp.skipped.push_back(sp.next_pn);
2240 if sp.skipped.len() > 4 {
2241 sp.skipped.pop_front();
2242 }
2243 sp.next_pn += 1;
2244 }
2245 let mut r = [0u8; 2];
2246 self.cfg.provider.fill_random(&mut r);
2247 let jitter = u64::from(u16::from_le_bytes(r)) % PN_SKIP_PERIOD;
2248 sp.skip_at = sp.next_pn + PN_SKIP_PERIOD / 2 + jitter;
2249 }
2250 }
2251 if b.eliciting && !self.eliciting_since_recv {
2252 self.eliciting_since_recv = true;
2254 self.last_activity = now;
2255 }
2256 self.stats.sent_packets += 1;
2257 self.recovery.on_sent(
2258 b.space,
2259 SentPacket {
2260 pn: b.pn,
2261 time: now,
2262 size: size as u16,
2263 ack_eliciting: b.eliciting,
2264 in_flight: b.eliciting,
2265 frames: b.frames,
2266 },
2267 );
2268 }
2269}
2270
2271struct Placeholder;
2273
2274impl CryptoSession for Placeholder {
2275 fn read_handshake(&mut self, _: Level, _: &[u8]) -> Result<(), crate::crypto::CryptoError> {
2276 Ok(())
2277 }
2278 fn write_handshake(&mut self, _: &mut Vec<u8>) -> Option<KeyChange> {
2279 None
2280 }
2281 fn peer_transport_params(&self) -> Option<&[u8]> {
2282 None
2283 }
2284 fn alpn_protocol(&self) -> Option<&[u8]> {
2285 None
2286 }
2287 fn is_handshaking(&self) -> bool {
2288 true
2289 }
2290}
2291
2292impl SentPacket {
2293 fn mtu_probe_size(&self) -> usize {
2294 self.frames
2295 .iter()
2296 .find_map(|f| if let SentFrame::MtuProbe(s) = f { Some(*s as usize) } else { None })
2297 .unwrap_or(0)
2298 }
2299}
2300
2301#[cfg(test)]
2302mod tests {
2303 use crate::config::Config;
2304 use crate::crypto::null::NullProvider;
2305 use crate::sim::{Link, Pair};
2306 use std::sync::Arc;
2307 use std::time::Duration;
2308
2309 #[test]
2314 fn unbuildable_mtu_probe_does_not_spin_ack_only_packets() {
2315 let cfg = |seed| Arc::new(Config::new(Arc::new(NullProvider::new(seed))));
2316 let mut p = Pair::new(cfg(1), cfg(2), Link::default(), 1);
2317 let c = p.connect();
2318 let ok = p.run_until(Duration::from_secs(30), |p| {
2319 p.client.conn(c).is_some_and(|x| x.is_established()) && p.server_conn().and_then(|s| p.server.conn(s)).is_some_and(|x| x.is_established())
2320 });
2321 assert!(ok);
2322 p.run_for(Duration::from_millis(200));
2323 let s = p.server_conn().unwrap();
2324 let now = p.now;
2325 let conn = p.server.conn_mut(s).unwrap();
2326 conn.recovery.rtt.has_sample = false;
2327 conn.mtu_probe = Some((1400, 0));
2328 conn.mtu_probe_inflight = false;
2329 conn.spaces[2].unacked_eliciting = 1;
2331 let mut buf = Vec::new();
2332 let mut sent = 0;
2333 while conn.poll_transmit(now, &mut buf, 1).is_some() {
2334 sent += 1;
2335 assert!(sent < 20, "poll_transmit keeps producing packets at one instant");
2336 }
2337 }
2338
2339 #[test]
2343 fn duplicate_client_hello_resends_the_server_flight() {
2344 use std::cell::RefCell;
2345 use std::rc::Rc;
2346 let cfg = |seed| Arc::new(Config::new(Arc::new(NullProvider::new(seed))));
2347 let mut p = Pair::new(cfg(5), cfg(6), Link::default(), 5);
2348 let count: Rc<RefCell<(usize, usize)>> = Rc::default();
2351 let c2 = count.clone();
2352 p.tamper = Some(Box::new(move |to_server, d| {
2353 let mut c = c2.borrow_mut();
2354 if to_server {
2355 c.0 += 1;
2356 } else if d.len() >= 1200 {
2357 c.1 += 1;
2358 }
2359 to_server
2360 }));
2361 p.connect();
2362 p.run_until(Duration::from_millis(50), |p| p.server_conn().is_some());
2363 p.run_for(Duration::from_millis(20));
2364 let s = p.server_conn().expect("server connection");
2365 assert!(count.borrow().1 > 0, "the server sent its flight");
2366 p.server.conn_mut(s).unwrap().recovery.pto_count = 12;
2369 let (clients, flights) = *count.borrow();
2370 let c3 = count.clone();
2371 assert!(p.run_until(Duration::from_secs(5), |_| c3.borrow().0 > clients), "the client resent its Initial");
2372 p.run_for(Duration::from_millis(30));
2373 assert!(count.borrow().1 > flights, "a repeated ClientHello makes the server resend its flight at once");
2374 }
2375
2376 #[test]
2381 fn first_packet_on_a_new_path_carries_the_challenge_when_cwnd_is_full() {
2382 let cfg = |seed| Arc::new(Config::new(Arc::new(NullProvider::new(seed))));
2383 let mut p = Pair::new(cfg(3), cfg(4), Link::default(), 3);
2384 let c = p.connect();
2385 let ok = p.run_until(Duration::from_secs(30), |p| {
2386 p.client.conn(c).is_some_and(|x| x.is_established()) && p.server_conn().and_then(|s| p.server.conn(s)).is_some_and(|x| x.is_established())
2387 });
2388 assert!(ok);
2389 p.run_for(Duration::from_millis(200));
2390 let s = p.server_conn().unwrap();
2391 let now = p.now;
2392 let new: std::net::SocketAddr = "10.0.0.9:6000".parse().unwrap();
2393 let conn = p.server.conn_mut(s).unwrap();
2394 assert!(conn.handshake_confirmed);
2395 conn.migrate(now, new);
2396 conn.recovery.cc.in_flight = conn.recovery.cc.cwnd;
2398 conn.spaces[2].ack_now = true;
2399 let mut buf = Vec::new();
2400 let t = conn.poll_transmit(now, &mut buf, 1).expect("a packet on the new path");
2401 assert_eq!(t.destination, new);
2402 assert!(!conn.path.challenge_pending, "the first packet on the new path carries PATH_CHALLENGE");
2403 let last = conn.recovery.spaces[2].sent.values().last().unwrap();
2404 assert!(last.ack_eliciting, "the packet is not ACK-only");
2405 }
2406}