1use std::cell::RefCell;
4use std::net::SocketAddr;
5use std::rc::{Rc, Weak};
6use std::task::{Context, Poll};
7use std::time::Instant;
8
9use bytes::Bytes;
10use moq_noq_proto::{ConnectionHandle, Dir, StreamId, VarInt};
11use rustc_hash::FxHashMap;
12
13use super::super::{Error, SEGMENT};
14use super::endpoint;
15use crate::udp;
16use crate::worker::Owner;
17
18pub(crate) type Shared = Rc<Inner>;
21
22const TRAIN_SEGMENTS: usize = 63;
24
25pub(crate) struct Inner {
31 pub(crate) conn: RefCell<moq_noq_proto::Connection>,
32 pub(crate) state: RefCell<State>,
33 pub(crate) owner: Owner,
36}
37
38pub(crate) struct State {
39 driver: kio::WaiterList,
42
43 established: bool,
44 establish_waiters: kio::WaiterList,
45
46 accept_bi_waiters: kio::WaiterList,
49 accept_uni_waiters: kio::WaiterList,
50
51 open_waiters: kio::WaiterList,
53
54 readable: FxHashMap<StreamId, kio::WaiterList>,
59 writable: FxHashMap<StreamId, kio::WaiterList>,
60 finishing: FxHashMap<StreamId, kio::WaiterList>,
63 sends: FxHashMap<StreamId, Option<End>>,
72
73 datagram_recv_waiters: kio::WaiterList,
74 datagram_send_waiters: kio::WaiterList,
75
76 closed: Option<Error>,
78 closed_waiters: kio::WaiterList,
79
80 dead: bool,
83
84 local_close: Option<(u64, String)>,
88}
89
90impl State {
91 fn new() -> Self {
92 Self {
93 driver: kio::WaiterList::new(),
94 established: false,
95 establish_waiters: kio::WaiterList::new(),
96 accept_bi_waiters: kio::WaiterList::new(),
97 accept_uni_waiters: kio::WaiterList::new(),
98 open_waiters: kio::WaiterList::new(),
99 readable: FxHashMap::default(),
100 writable: FxHashMap::default(),
101 finishing: FxHashMap::default(),
102 sends: FxHashMap::default(),
103 datagram_recv_waiters: kio::WaiterList::new(),
104 datagram_send_waiters: kio::WaiterList::new(),
105 closed: None,
106 closed_waiters: kio::WaiterList::new(),
107 dead: false,
108 local_close: None,
109 }
110 }
111
112 fn forget_send(&mut self, id: StreamId) {
114 self.sends.remove(&id);
115 self.finishing.remove(&id);
116 self.writable.remove(&id);
117 }
118
119 fn forget_recv(&mut self, id: StreamId) {
123 self.readable.remove(&id);
124 }
125
126 fn fail(&mut self, err: Error) {
129 if self.closed.is_none() {
130 self.closed = Some(err);
131 }
132 self.driver.wake();
133 self.closed_waiters.wake();
134 self.establish_waiters.wake();
135 self.accept_bi_waiters.wake();
136 self.accept_uni_waiters.wake();
137 self.open_waiters.wake();
138 self.datagram_recv_waiters.wake();
139 self.datagram_send_waiters.wake();
140 for waiters in self.readable.values_mut() {
141 waiters.wake();
142 }
143 for waiters in self.writable.values_mut() {
144 waiters.wake();
145 }
146 for waiters in self.finishing.values_mut() {
147 waiters.wake();
148 }
149 }
150}
151
152impl Inner {
153 pub(crate) fn closed(&self) -> Option<Error> {
155 self.state.borrow().closed.clone()
156 }
157
158 pub(crate) fn kick(&self) {
160 self.state.borrow_mut().driver.wake();
161 }
162
163 pub(crate) fn fail(&self, err: Error) {
166 let mut state = self.state.borrow_mut();
167 state.dead = true;
168 state.fail(err);
169 }
170
171 pub(crate) fn park_writable(&self, id: StreamId, waiter: &kio::Waiter) {
173 let mut state = self.state.borrow_mut();
174 waiter.register(state.writable.entry(id).or_default());
175 }
176
177 pub(crate) fn park_readable(&self, id: StreamId, waiter: &kio::Waiter) {
179 let mut state = self.state.borrow_mut();
180 waiter.register(state.readable.entry(id).or_default());
181 }
182
183 pub(crate) fn park_finishing(&self, id: StreamId, waiter: &kio::Waiter) {
185 let mut state = self.state.borrow_mut();
186 waiter.register(state.finishing.entry(id).or_default());
187 }
188
189 pub(crate) fn track(&self, id: StreamId) {
197 let stopped = self.conn.borrow_mut().send_stream(id).stopped().ok().flatten();
200 self.state
201 .borrow_mut()
202 .sends
203 .insert(id, stopped.map(|code| End::Stopped(code.into_inner())));
204 }
205
206 pub(crate) fn ended(&self, id: StreamId) -> Option<End> {
209 self.state.borrow().sends.get(&id).copied().flatten()
210 }
211
212 pub(crate) fn forget_send(&self, id: StreamId) {
219 self.state.borrow_mut().forget_send(id);
220 }
221
222 pub(crate) fn forget_recv(&self, id: StreamId) {
224 self.state.borrow_mut().forget_recv(id);
225 }
226
227 pub(crate) fn wake_readable(&self, id: StreamId) {
229 let mut state = self.state.borrow_mut();
230 if let Some(mut waiters) = state.readable.remove(&id) {
231 waiters.wake();
232 }
233 }
234
235 pub(crate) fn close_code(&self, code: u64, reason: &str) {
241 self.conn.borrow_mut().close(
242 Instant::now(),
243 VarInt::from_u64(code).unwrap_or(VarInt::MAX),
244 Bytes::copy_from_slice(reason.as_bytes()),
245 );
246 let mut state = self.state.borrow_mut();
252 state.local_close.get_or_insert((code, reason.to_string()));
253 state.driver.wake();
254 }
255}
256
257pub struct Connection {
275 shared: Shared,
276 park: kio::Park,
278 alpn: Option<String>,
281 server_name: Option<String>,
283 remote: SocketAddr,
285}
286
287impl Connection {
288 pub(crate) fn close_code(&self, code: u64, reason: &str) {
294 self.shared.close_code(code, reason);
295 }
296
297 pub(crate) fn owner(&self) -> &Owner {
299 &self.shared.owner
300 }
301
302 pub fn peer_chain(&self) -> Option<Vec<Vec<u8>>> {
311 let conn = self.shared.conn.borrow();
312 let identity = conn.crypto_session().peer_identity()?;
313 let chain = identity
314 .downcast::<Vec<rustls::pki_types::CertificateDer<'static>>>()
315 .ok()?;
316 Some(chain.iter().map(|cert| cert.to_vec()).collect())
317 }
318
319 pub fn remote_addr(&self) -> SocketAddr {
322 self.remote
323 }
324
325 pub fn server_name(&self) -> Option<&str> {
328 self.server_name.as_deref()
329 }
330}
331
332impl Clone for Connection {
333 fn clone(&self) -> Self {
334 Self {
335 shared: self.shared.clone(),
336 park: kio::Park::default(),
337 alpn: self.alpn.clone(),
338 server_name: self.server_name.clone(),
339 remote: self.remote,
340 }
341 }
342}
343
344pub(crate) fn launch(
351 owner: &Owner,
352 socket: Rc<udp::Socket>,
353 endpoint: Weak<endpoint::Inner>,
354 key: ConnectionHandle,
355 conn: moq_noq_proto::Connection,
356) -> (Shared, impl Future<Output = ()> + use<>) {
357 let shared = Rc::new(Inner {
358 conn: RefCell::new(conn),
359 state: RefCell::new(State::new()),
360 owner: owner.clone(),
361 });
362
363 let mut driver = Driver {
364 shared: shared.clone(),
365 socket,
366 endpoint,
367 key,
368 deadline: owner.timer(),
369 scratch: Vec::with_capacity(TRAIN_SEGMENTS * SEGMENT),
370 blocked: false,
371 };
372 let future = async move { kio::wait(|waiter| driver.poll(waiter)).await };
373 (shared, future)
374}
375
376struct EstablishGuard {
381 shared: Option<Shared>,
382}
383
384impl Drop for EstablishGuard {
385 fn drop(&mut self) {
386 if let Some(shared) = self.shared.take() {
387 shared.close_code(0, "QUIC handshake abandoned");
388 }
389 }
390}
391
392pub(crate) async fn establish(shared: Shared) -> Result<Connection, Error> {
394 let mut guard = EstablishGuard {
395 shared: Some(shared.clone()),
396 };
397 let result = kio::wait(|waiter| {
398 let mut state = shared.state.borrow_mut();
399 if state.established {
400 return Poll::Ready(Ok(()));
401 }
402 if let Some(err) = &state.closed {
403 return Poll::Ready(Err(err.clone()));
404 }
405 waiter.register(&mut state.establish_waiters);
406 Poll::Pending
407 })
408 .await;
409 if result.is_err() {
410 guard.shared = None;
412 }
413 result?;
414
415 let (alpn, server_name, remote) = {
416 let conn = shared.conn.borrow();
417 let handshake = conn
418 .crypto_session()
419 .handshake_data()
420 .and_then(|data| data.downcast::<moq_noq_proto::crypto::rustls::HandshakeData>().ok());
421 let (alpn, server_name) = match handshake {
422 Some(data) => (
423 data.protocol.map(|proto| String::from_utf8_lossy(&proto).into_owned()),
424 data.server_name,
425 ),
426 None => (None, None),
427 };
428 let remote = conn
430 .network_path(moq_noq_proto::PathId::ZERO)
431 .expect("an established connection has its first path")
432 .remote();
433 (alpn, server_name, remote)
434 };
435
436 let conn = Connection {
437 shared,
438 park: kio::Park::default(),
439 alpn,
440 server_name,
441 remote,
442 };
443 guard.shared = None;
444 Ok(conn)
445}
446
447impl web_transport_trait::poll::Session for Connection {
448 type SendStream = super::SendStream;
449 type RecvStream = super::RecvStream;
450 type Error = Error;
451
452 fn poll_accept_uni(&mut self, cx: &mut Context<'_>) -> Poll<Result<Self::RecvStream, Self::Error>> {
453 let waiter = self.park.hold(cx);
454 if let Some(id) = self.shared.conn.borrow_mut().streams().accept(Dir::Uni) {
455 return Poll::Ready(Ok(super::RecvStream::new(self.shared.clone(), id)));
456 }
457 let mut state = self.shared.state.borrow_mut();
458 if let Some(err) = &state.closed {
459 return Poll::Ready(Err(err.clone()));
460 }
461 waiter.register(&mut state.accept_uni_waiters);
462 Poll::Pending
463 }
464
465 fn poll_accept_bi(
466 &mut self,
467 cx: &mut Context<'_>,
468 ) -> Poll<Result<(Self::SendStream, Self::RecvStream), Self::Error>> {
469 let waiter = self.park.hold(cx);
470 let accepted = self.shared.conn.borrow_mut().streams().accept(Dir::Bi);
473 if let Some(id) = accepted {
474 return Poll::Ready(Ok((
475 super::SendStream::new(self.shared.clone(), id),
476 super::RecvStream::new(self.shared.clone(), id),
477 )));
478 }
479 let mut state = self.shared.state.borrow_mut();
480 if let Some(err) = &state.closed {
481 return Poll::Ready(Err(err.clone()));
482 }
483 waiter.register(&mut state.accept_bi_waiters);
484 Poll::Pending
485 }
486
487 fn poll_open_uni(&mut self, cx: &mut Context<'_>) -> Poll<Result<Self::SendStream, Self::Error>> {
488 let waiter = self.park.hold(cx);
489 if let Some(err) = self.shared.closed() {
490 return Poll::Ready(Err(err));
491 }
492 let opened = self.shared.conn.borrow_mut().streams().open(Dir::Uni);
495 match opened {
496 Some(id) => Poll::Ready(Ok(super::SendStream::new(self.shared.clone(), id))),
497 None => {
498 let mut state = self.shared.state.borrow_mut();
499 waiter.register(&mut state.open_waiters);
500 Poll::Pending
501 }
502 }
503 }
504
505 fn poll_open_bi(
506 &mut self,
507 cx: &mut Context<'_>,
508 ) -> Poll<Result<(Self::SendStream, Self::RecvStream), Self::Error>> {
509 let waiter = self.park.hold(cx);
510 if let Some(err) = self.shared.closed() {
511 return Poll::Ready(Err(err));
512 }
513 let opened = self.shared.conn.borrow_mut().streams().open(Dir::Bi);
514 match opened {
515 Some(id) => Poll::Ready(Ok((
516 super::SendStream::new(self.shared.clone(), id),
517 super::RecvStream::new(self.shared.clone(), id),
518 ))),
519 None => {
520 let mut state = self.shared.state.borrow_mut();
521 waiter.register(&mut state.open_waiters);
522 Poll::Pending
523 }
524 }
525 }
526
527 fn poll_send_datagram(&mut self, cx: &mut Context<'_>, payload: &[u8]) -> Poll<Result<(), Self::Error>> {
528 let waiter = self.park.hold(cx);
529 if let Some(err) = self.shared.closed() {
530 return Poll::Ready(Err(err));
531 }
532 let payload = Bytes::copy_from_slice(payload);
533 match self.shared.conn.borrow_mut().datagrams().send(payload, false) {
534 Ok(()) => {
535 self.shared.kick();
536 Poll::Ready(Ok(()))
537 }
538 Err(moq_noq_proto::SendDatagramError::Blocked(_)) => {
540 let mut state = self.shared.state.borrow_mut();
541 waiter.register(&mut state.datagram_send_waiters);
542 Poll::Pending
543 }
544 Err(err) => Poll::Ready(Err(Error::Quic(err.to_string()))),
545 }
546 }
547
548 fn poll_recv_datagram(&mut self, cx: &mut Context<'_>) -> Poll<Result<Bytes, Self::Error>> {
549 let waiter = self.park.hold(cx);
550 if let Some(datagram) = self.shared.conn.borrow_mut().datagrams().recv() {
551 return Poll::Ready(Ok(datagram));
552 }
553 let mut state = self.shared.state.borrow_mut();
554 if let Some(err) = &state.closed {
555 return Poll::Ready(Err(err.clone()));
556 }
557 waiter.register(&mut state.datagram_recv_waiters);
558 Poll::Pending
559 }
560
561 fn max_datagram_size(&self) -> usize {
562 self.shared.conn.borrow_mut().datagrams().max_size().unwrap_or(0)
563 }
564
565 fn protocol(&self) -> Option<&str> {
566 self.alpn.as_deref()
567 }
568
569 fn close(&mut self, code: u32, reason: &str) {
570 self.shared.close_code(u64::from(code), reason);
571 }
572
573 fn poll_closed(&mut self, cx: &mut Context<'_>) -> Poll<Self::Error> {
574 let waiter = self.park.hold(cx);
575 let mut state = self.shared.state.borrow_mut();
576 if let Some(err) = &state.closed {
577 return Poll::Ready(err.clone());
578 }
579 waiter.register(&mut state.closed_waiters);
580 Poll::Pending
581 }
582
583 fn stats(&self) -> impl web_transport_trait::Stats {
584 let (stats, path) = {
585 let mut conn = self.shared.conn.borrow_mut();
586 let stats = conn.stats();
587 let path = conn.path_stats(moq_noq_proto::PathId::ZERO).unwrap_or_default();
588 (stats, path)
589 };
590 Stats {
591 bytes_sent: stats.udp_tx.bytes,
592 bytes_received: stats.udp_rx.bytes,
593 bytes_lost: stats.lost_bytes,
594 packets_sent: stats.udp_tx.datagrams,
595 packets_received: stats.udp_rx.datagrams,
596 packets_lost: stats.lost_packets,
597 rtt: path.rtt,
598 }
599 }
600}
601
602impl std::fmt::Debug for Connection {
603 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
604 f.debug_struct("Connection").field("alpn", &self.alpn).finish()
605 }
606}
607
608struct Stats {
611 bytes_sent: u64,
612 bytes_received: u64,
613 bytes_lost: u64,
614 packets_sent: u64,
615 packets_received: u64,
616 packets_lost: u64,
617 rtt: std::time::Duration,
618}
619
620impl web_transport_trait::Stats for Stats {
621 fn bytes_sent(&self) -> Option<u64> {
622 Some(self.bytes_sent)
623 }
624
625 fn bytes_received(&self) -> Option<u64> {
626 Some(self.bytes_received)
627 }
628
629 fn bytes_lost(&self) -> Option<u64> {
630 Some(self.bytes_lost)
631 }
632
633 fn packets_sent(&self) -> Option<u64> {
634 Some(self.packets_sent)
635 }
636
637 fn packets_received(&self) -> Option<u64> {
638 Some(self.packets_received)
639 }
640
641 fn packets_lost(&self) -> Option<u64> {
642 Some(self.packets_lost)
643 }
644
645 fn rtt(&self) -> Option<std::time::Duration> {
646 Some(self.rtt)
647 }
648
649 fn estimated_send_rate(&self) -> Option<u64> {
660 None
661 }
662}
663
664struct Driver {
668 shared: Shared,
669 socket: Rc<udp::Socket>,
670 endpoint: Weak<endpoint::Inner>,
674 key: ConnectionHandle,
675 deadline: crate::Timer,
676 scratch: Vec<u8>,
679 blocked: bool,
682}
683
684impl Driver {
685 fn poll(&mut self, waiter: &kio::Waiter) -> Poll<()> {
686 {
687 let mut state = self.shared.state.borrow_mut();
688 if state.dead {
691 return Poll::Ready(());
692 }
693 waiter.register(&mut state.driver);
696 }
697
698 loop {
699 self.endpoint_events();
700 self.sweep();
701
702 if self.shared.state.borrow().dead {
703 return Poll::Ready(());
704 }
705 if self.shared.conn.borrow().is_drained() {
709 return Poll::Ready(());
710 }
711
712 if let Poll::Ready(err) = self.flush(waiter) {
713 self.shared.state.borrow_mut().fail(err);
714 return Poll::Ready(());
715 }
716 self.publish_close();
717
718 self.deadline.set(self.shared.conn.borrow_mut().poll_timeout());
723 if self.deadline.poll(waiter).is_pending() {
724 return Poll::Pending;
725 }
726 self.shared.conn.borrow_mut().handle_timeout(Instant::now());
727 }
728 }
729
730 fn endpoint_events(&mut self) {
736 let Some(endpoint) = self.endpoint.upgrade() else {
737 return;
738 };
739 loop {
740 let event = self.shared.conn.borrow_mut().poll_endpoint_events();
741 let Some(event) = event else {
742 return;
743 };
744 if let Some(event) = endpoint.on_connection_event(self.key, event) {
745 self.shared.conn.borrow_mut().handle_event(event);
746 }
747 }
748 }
749
750 fn sweep(&mut self) {
753 loop {
754 let event = self.shared.conn.borrow_mut().poll();
755 let Some(event) = event else {
756 return;
757 };
758
759 let mut state = self.shared.state.borrow_mut();
760 match event {
761 moq_noq_proto::Event::Connected => {
762 state.established = true;
763 state.establish_waiters.wake();
764 }
765 moq_noq_proto::Event::ConnectionLost { reason } => state.fail(reason.into()),
766 moq_noq_proto::Event::DatagramReceived => state.datagram_recv_waiters.wake(),
767 moq_noq_proto::Event::DatagramsUnblocked => state.datagram_send_waiters.wake(),
768 moq_noq_proto::Event::HandshakeDataReady => {}
769 moq_noq_proto::Event::Stream(event) => sweep_stream(&mut state, event),
770 moq_noq_proto::Event::HandshakeConfirmed
771 | moq_noq_proto::Event::Path(_)
772 | moq_noq_proto::Event::NatTraversal(_) => {}
773 }
774 }
775 }
776
777 fn publish_close(&mut self) {
786 if self.blocked || !self.shared.conn.borrow().is_closed() {
787 return;
788 }
789 let mut state = self.shared.state.borrow_mut();
790 let Some((code, reason)) = state.local_close.take() else {
791 return;
792 };
793 state.fail(Error::App { code, reason });
794 }
795
796 fn flush(&mut self, waiter: &kio::Waiter) -> Poll<Error> {
799 match self.flush_one(waiter) {
800 Poll::Ready(Ok(())) => {}
801 Poll::Ready(Err(err)) => return Poll::Ready(err),
802 Poll::Pending => return Poll::Pending,
804 }
805 waiter.waker().wake_by_ref();
808 Poll::Pending
809 }
810
811 fn flush_one(&mut self, waiter: &kio::Waiter) -> Poll<Result<(), Error>> {
814 let mut tx = match self.socket.poll_acquire(waiter) {
815 Poll::Ready(Ok(tx)) => tx,
816 Poll::Ready(Err(err)) => return Poll::Ready(Err(Error::Io(err.to_string()))),
817 Poll::Pending => {
819 self.blocked = true;
820 return Poll::Pending;
821 }
822 };
823 self.blocked = false;
824
825 let segments = (tx.len() / SEGMENT).min(TRAIN_SEGMENTS);
826 if segments == 0 {
827 return Poll::Ready(Err(Error::Io(format!(
828 "transmit buffer of {} bytes holds no {SEGMENT} byte segment",
829 tx.len()
830 ))));
831 }
832 let segments = std::num::NonZeroUsize::new(segments).expect("segments was checked above");
833
834 self.scratch.clear();
835 let transmit = match self
836 .shared
837 .conn
838 .borrow_mut()
839 .poll_transmit(Instant::now(), segments, &mut self.scratch)
840 {
841 Some(transmit) => transmit,
842 None => return Poll::Pending,
844 };
845
846 tx[..transmit.size].copy_from_slice(&self.scratch[..transmit.size]);
847 let transmit = udp::Transmit {
850 to: transmit.destination,
851 len: transmit.size,
852 segment: transmit.segment_size.unwrap_or(transmit.size),
853 ecn: transmit.ecn.map(super::ecn_from_noq),
854 };
855 if let Err(err) = tx.send(transmit) {
856 return Poll::Ready(Err(Error::Io(err.to_string())));
857 }
858 self.shared.state.borrow_mut().datagram_send_waiters.wake();
860 Poll::Ready(Ok(()))
861 }
862}
863
864#[derive(Clone, Copy, Debug)]
866pub(crate) enum End {
867 Delivered,
869 Stopped(u64),
871}
872
873fn end(state: &mut State, id: StreamId, end: End) {
878 if let Some(slot) = state.sends.get_mut(&id) {
879 *slot = Some(end);
880 }
881 if let Some(mut waiters) = state.finishing.remove(&id) {
882 waiters.wake();
883 }
884}
885
886fn sweep_stream(state: &mut State, event: moq_noq_proto::StreamEvent) {
888 match event {
891 moq_noq_proto::StreamEvent::Opened { dir: Dir::Bi } => state.accept_bi_waiters.wake(),
892 moq_noq_proto::StreamEvent::Opened { dir: Dir::Uni } => state.accept_uni_waiters.wake(),
893 moq_noq_proto::StreamEvent::Available { .. } => state.open_waiters.wake(),
894 moq_noq_proto::StreamEvent::Readable { id } => {
895 if let Some(mut waiters) = state.readable.remove(&id) {
896 waiters.wake();
897 }
898 }
899 moq_noq_proto::StreamEvent::Writable { id } => {
900 if let Some(mut waiters) = state.writable.remove(&id) {
901 waiters.wake();
902 }
903 }
904 moq_noq_proto::StreamEvent::Finished { id } => end(state, id, End::Delivered),
905 moq_noq_proto::StreamEvent::Stopped { id, error_code } => {
906 end(state, id, End::Stopped(error_code.into_inner()));
907 if let Some(mut waiters) = state.writable.remove(&id) {
909 waiters.wake();
910 }
911 }
912 }
913}
914
915#[cfg(test)]
916mod tests {
917 use moq_noq_proto::Side;
918
919 use super::*;
920
921 #[test]
927 fn forgetting_a_handle_clears_its_parking() {
928 let mut state = State::new();
929 let id = StreamId::new(Side::Client, Dir::Bi, 0);
930 state.writable.entry(id).or_default();
931 state.readable.entry(id).or_default();
932 state.finishing.entry(id).or_default();
933 state.sends.insert(id, None);
934
935 state.forget_send(id);
936 assert!(state.writable.is_empty(), "the write half's parking");
937 assert!(state.finishing.is_empty(), "the finish watch");
938 assert!(state.sends.is_empty(), "the end bookkeeping");
939 assert!(!state.readable.is_empty(), "the read half's parking survives");
941
942 state.forget_recv(id);
943 assert!(state.readable.is_empty(), "the read half's parking");
944 }
945}