1use std::{
2 collections::VecDeque,
3 fmt,
4 future::Future,
5 io,
6 io::IoSliceMut,
7 mem,
8 net::{SocketAddr, SocketAddrV6},
9 pin::Pin,
10 str,
11 sync::{
12 Arc, Mutex,
13 atomic::{AtomicUsize, Ordering},
14 },
15 task::{Context, Poll, Waker},
16};
17
18#[cfg(all(not(wasm_browser), any(feature = "aws-lc-rs", feature = "ring")))]
19use crate::runtime::default_runtime;
20use crate::{
21 Instant,
22 runtime::{AsyncUdpSocket, Runtime},
23 udp_transmit,
24};
25use bytes::{Bytes, BytesMut};
26use pin_project_lite::pin_project;
27use proto::{
28 self as proto, ClientConfig, ConnectError, ConnectionError, ConnectionHandle, DatagramEvent,
29 EndpointEvent, ServerConfig,
30};
31use rustc_hash::FxHashMap;
32#[cfg(all(not(wasm_browser), any(feature = "aws-lc-rs", feature = "ring"),))]
33use socket2::{Domain, Protocol, Socket, Type};
34use tokio::sync::{Notify, futures::Notified, mpsc};
35use tracing::{Instrument, Span};
36use udp::{BATCH_SIZE, RecvMeta};
37
38use crate::{
39 ConnectionEvent, EndpointConfig, IO_LOOP_BOUND, RECV_TIME_BOUND, VarInt,
40 connection::Connecting, incoming::Incoming, work_limiter::WorkLimiter,
41};
42
43#[derive(Debug, Clone)]
50pub struct Endpoint {
51 pub(crate) inner: EndpointRef,
52 pub(crate) default_client_config: Option<ClientConfig>,
53 runtime: Arc<dyn Runtime>,
54}
55
56impl Endpoint {
57 #[cfg(all(not(wasm_browser), any(feature = "aws-lc-rs", feature = "ring")))] pub fn client(addr: SocketAddr) -> io::Result<Self> {
76 let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?;
77 if addr.is_ipv6() {
78 if let Err(e) = socket.set_only_v6(false) {
79 tracing::debug!(%e, "unable to make socket dual-stack");
80 }
81 }
82 socket.bind(&addr.into())?;
83 let runtime =
84 default_runtime().ok_or_else(|| io::Error::other("no async runtime found"))?;
85 Self::new_with_abstract_socket(
86 EndpointConfig::default(),
87 None,
88 runtime.wrap_udp_socket(socket.into())?,
89 runtime,
90 )
91 }
92
93 pub fn stats(&self) -> EndpointStats {
95 self.inner.state.lock().unwrap().stats
96 }
97
98 #[cfg(all(not(wasm_browser), any(feature = "aws-lc-rs", feature = "ring")))] pub fn server(config: ServerConfig, addr: SocketAddr) -> io::Result<Self> {
106 let socket = std::net::UdpSocket::bind(addr)?;
107 let runtime =
108 default_runtime().ok_or_else(|| io::Error::other("no async runtime found"))?;
109 Self::new_with_abstract_socket(
110 EndpointConfig::default(),
111 Some(config),
112 runtime.wrap_udp_socket(socket)?,
113 runtime,
114 )
115 }
116
117 #[cfg(not(wasm_browser))]
119 pub fn new(
120 config: EndpointConfig,
121 server_config: Option<ServerConfig>,
122 socket: std::net::UdpSocket,
123 runtime: Arc<dyn Runtime>,
124 ) -> io::Result<Self> {
125 let socket = runtime.wrap_udp_socket(socket)?;
126 Self::new_with_abstract_socket(config, server_config, socket, runtime)
127 }
128
129 pub fn new_with_abstract_socket(
134 config: EndpointConfig,
135 server_config: Option<ServerConfig>,
136 socket: Arc<dyn AsyncUdpSocket>,
137 runtime: Arc<dyn Runtime>,
138 ) -> io::Result<Self> {
139 let addr = socket.local_addr()?;
140 let allow_mtud = !socket.may_fragment();
141 let rc = EndpointRef::new(
142 socket,
143 proto::Endpoint::new(
144 Arc::new(config),
145 server_config.map(Arc::new),
146 allow_mtud,
147 None,
148 ),
149 addr.is_ipv6(),
150 runtime.clone(),
151 );
152 let driver = EndpointDriver(rc.clone());
153 runtime.spawn(Box::pin(
154 async {
155 if let Err(e) = driver.await {
156 tracing::error!("I/O error: {}", e);
157 }
158 }
159 .instrument(Span::current()),
160 ));
161 Ok(Self {
162 inner: rc,
163 default_client_config: None,
164 runtime,
165 })
166 }
167
168 pub fn accept(&self) -> Accept<'_> {
175 Accept {
176 endpoint: self,
177 notify: self.inner.shared.incoming.notified(),
178 }
179 }
180
181 pub fn set_default_client_config(&mut self, config: ClientConfig) {
183 self.default_client_config = Some(config);
184 }
185
186 pub fn connect(&self, addr: SocketAddr, server_name: &str) -> Result<Connecting, ConnectError> {
195 let config = match &self.default_client_config {
196 Some(config) => config.clone(),
197 None => return Err(ConnectError::NoDefaultClientConfig),
198 };
199
200 self.connect_with(config, addr, server_name)
201 }
202
203 pub fn connect_with(
209 &self,
210 config: ClientConfig,
211 addr: SocketAddr,
212 server_name: &str,
213 ) -> Result<Connecting, ConnectError> {
214 let mut endpoint = self.inner.state.lock().unwrap();
215 if endpoint.driver_lost || endpoint.recv_state.connections.close.is_some() {
216 return Err(ConnectError::EndpointStopping);
217 }
218 if addr.is_ipv6() && !endpoint.ipv6 {
219 return Err(ConnectError::InvalidRemoteAddress(addr));
220 }
221 let addr = if endpoint.ipv6 {
222 SocketAddr::V6(ensure_ipv6(addr))
223 } else {
224 addr
225 };
226
227 let (ch, conn) = endpoint
228 .inner
229 .connect(self.runtime.now(), config, addr, server_name)?;
230
231 let socket = endpoint.socket.clone();
232 endpoint.stats.outgoing_handshakes += 1;
233 Ok(endpoint
234 .recv_state
235 .connections
236 .insert(ch, conn, socket, self.runtime.clone()))
237 }
238
239 #[cfg(not(wasm_browser))]
243 pub fn rebind(&self, socket: std::net::UdpSocket) -> io::Result<()> {
244 self.rebind_abstract(self.runtime.wrap_udp_socket(socket)?)
245 }
246
247 pub fn rebind_abstract(&self, socket: Arc<dyn AsyncUdpSocket>) -> io::Result<()> {
254 let addr = socket.local_addr()?;
255 let mut inner = self.inner.state.lock().unwrap();
256 inner.prev_socket = Some(mem::replace(&mut inner.socket, socket));
257 inner.ipv6 = addr.is_ipv6();
258
259 for sender in inner.recv_state.connections.senders.values() {
261 let _ = sender.send(ConnectionEvent::Rebind(inner.socket.clone()));
263 }
264 if let Some(driver) = inner.driver.take() {
265 driver.wake();
267 }
268
269 Ok(())
270 }
271
272 pub fn set_server_config(&self, server_config: Option<ServerConfig>) {
276 self.inner
277 .state
278 .lock()
279 .unwrap()
280 .inner
281 .set_server_config(server_config.map(Arc::new))
282 }
283
284 pub fn local_addr(&self) -> io::Result<SocketAddr> {
286 self.inner.state.lock().unwrap().socket.local_addr()
287 }
288
289 pub fn open_connections(&self) -> usize {
291 self.inner.state.lock().unwrap().inner.open_connections()
292 }
293
294 pub fn close(&self, error_code: VarInt, reason: &[u8]) {
300 let reason = Bytes::copy_from_slice(reason);
301 let mut endpoint = self.inner.state.lock().unwrap();
302 endpoint.recv_state.connections.close = Some((error_code, reason.clone()));
303 for sender in endpoint.recv_state.connections.senders.values() {
304 let _ = sender.send(ConnectionEvent::Close {
306 error_code,
307 reason: reason.clone(),
308 });
309 }
310 self.inner.shared.incoming.notify_waiters();
311 }
312
313 pub async fn wait_idle(&self) {
324 loop {
325 {
326 let endpoint = &mut *self.inner.state.lock().unwrap();
327 if endpoint.recv_state.connections.is_empty() {
328 break;
329 }
330 self.inner.shared.idle.notified()
332 }
333 .await;
334 }
335 }
336}
337
338#[non_exhaustive]
340#[derive(Debug, Default, Copy, Clone)]
341pub struct EndpointStats {
342 pub accepted_handshakes: u64,
344 pub outgoing_handshakes: u64,
346 pub refused_handshakes: u64,
348 pub ignored_handshakes: u64,
350}
351
352#[must_use = "endpoint drivers must be spawned for I/O to occur"]
363#[derive(Debug)]
364pub(crate) struct EndpointDriver(pub(crate) EndpointRef);
365
366impl Future for EndpointDriver {
367 type Output = Result<(), io::Error>;
368
369 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
370 let mut endpoint = self.0.state.lock().unwrap();
371 if endpoint.driver.is_none() {
372 endpoint.driver = Some(cx.waker().clone());
373 }
374
375 let now = endpoint.runtime.now();
376 let mut keep_going = false;
377 keep_going |= endpoint.drive_recv(cx, now)?;
378 keep_going |= endpoint.handle_events(cx, &self.0.shared);
379
380 if !endpoint.recv_state.incoming.is_empty() {
381 self.0.shared.incoming.notify_waiters();
382 }
383
384 if self.0.shared.ref_count.load(Ordering::Relaxed) == 0
385 && endpoint.recv_state.connections.is_empty()
386 {
387 Poll::Ready(Ok(()))
388 } else {
389 drop(endpoint);
390 if keep_going {
394 cx.waker().wake_by_ref();
395 }
396 Poll::Pending
397 }
398 }
399}
400
401impl Drop for EndpointDriver {
402 fn drop(&mut self) {
403 let mut endpoint = self.0.state.lock().unwrap();
404 endpoint.driver_lost = true;
405 self.0.shared.incoming.notify_waiters();
406 endpoint.recv_state.connections.senders.clear();
409 }
410}
411
412#[derive(Debug)]
413pub(crate) struct EndpointInner {
414 pub(crate) state: Mutex<State>,
415 pub(crate) shared: Shared,
416}
417
418impl EndpointInner {
419 pub(crate) fn accept(
420 &self,
421 incoming: proto::Incoming,
422 server_config: Option<Arc<ServerConfig>>,
423 ) -> Result<Connecting, ConnectionError> {
424 let mut state = self.state.lock().unwrap();
425 let mut response_buffer = Vec::new();
426 let now = state.runtime.now();
427 match state
428 .inner
429 .accept(incoming, now, &mut response_buffer, server_config)
430 {
431 Ok((handle, conn)) => {
432 state.stats.accepted_handshakes += 1;
433 let socket = state.socket.clone();
434 let runtime = state.runtime.clone();
435 Ok(state
436 .recv_state
437 .connections
438 .insert(handle, conn, socket, runtime))
439 }
440 Err(error) => {
441 if let Some(transmit) = error.response {
442 respond(transmit, &response_buffer, &*state.socket);
443 }
444 Err(error.cause)
445 }
446 }
447 }
448
449 pub(crate) fn refuse(&self, incoming: proto::Incoming) {
450 let mut state = self.state.lock().unwrap();
451 state.stats.refused_handshakes += 1;
452 let mut response_buffer = Vec::new();
453 let transmit = state.inner.refuse(incoming, &mut response_buffer);
454 respond(transmit, &response_buffer, &*state.socket);
455 }
456
457 pub(crate) fn retry(&self, incoming: proto::Incoming) -> Result<(), proto::RetryError> {
458 let mut state = self.state.lock().unwrap();
459 let mut response_buffer = Vec::new();
460 let transmit = state.inner.retry(incoming, &mut response_buffer)?;
461 respond(transmit, &response_buffer, &*state.socket);
462 Ok(())
463 }
464
465 pub(crate) fn ignore(&self, incoming: proto::Incoming) {
466 let mut state = self.state.lock().unwrap();
467 state.stats.ignored_handshakes += 1;
468 state.inner.ignore(incoming);
469 }
470}
471
472#[derive(Debug)]
473pub(crate) struct State {
474 socket: Arc<dyn AsyncUdpSocket>,
475 prev_socket: Option<Arc<dyn AsyncUdpSocket>>,
478 inner: proto::Endpoint,
479 recv_state: RecvState,
480 driver: Option<Waker>,
481 ipv6: bool,
482 events: mpsc::UnboundedReceiver<(ConnectionHandle, EndpointEvent)>,
483 driver_lost: bool,
484 runtime: Arc<dyn Runtime>,
485 stats: EndpointStats,
486}
487
488#[derive(Debug)]
489pub(crate) struct Shared {
490 incoming: Notify,
491 idle: Notify,
492 ref_count: AtomicUsize,
494}
495
496impl State {
497 fn drive_recv(&mut self, cx: &mut Context, now: Instant) -> Result<bool, io::Error> {
498 let get_time = || self.runtime.now();
499 self.recv_state.recv_limiter.start_cycle(get_time);
500 if let Some(socket) = &self.prev_socket {
501 let poll_res =
503 self.recv_state
504 .poll_socket(cx, &mut self.inner, &**socket, &*self.runtime, now);
505 if poll_res.is_err() {
506 self.prev_socket = None;
507 }
508 };
509 let poll_res =
510 self.recv_state
511 .poll_socket(cx, &mut self.inner, &*self.socket, &*self.runtime, now);
512 self.recv_state.recv_limiter.finish_cycle(get_time);
513 let poll_res = poll_res?;
514 if poll_res.received_connection_packet {
515 self.prev_socket = None;
518 }
519 Ok(poll_res.keep_going)
520 }
521
522 fn handle_events(&mut self, cx: &mut Context, shared: &Shared) -> bool {
523 for _ in 0..IO_LOOP_BOUND {
524 let (ch, event) = match self.events.poll_recv(cx) {
525 Poll::Ready(Some(x)) => x,
526 Poll::Ready(None) => unreachable!("EndpointInner owns one sender"),
527 Poll::Pending => {
528 return false;
529 }
530 };
531
532 if event.is_drained() {
533 self.recv_state.connections.senders.remove(&ch);
534 if self.recv_state.connections.is_empty() {
535 shared.idle.notify_waiters();
536 }
537 }
538 let Some(event) = self.inner.handle_event(ch, event) else {
539 continue;
540 };
541 let _ = self
543 .recv_state
544 .connections
545 .senders
546 .get_mut(&ch)
547 .unwrap()
548 .send(ConnectionEvent::Proto(event));
549 }
550
551 true
552 }
553}
554
555impl Drop for State {
556 fn drop(&mut self) {
557 for incoming in self.recv_state.incoming.drain(..) {
558 self.inner.ignore(incoming);
559 }
560 }
561}
562
563fn respond(transmit: proto::Transmit, response_buffer: &[u8], socket: &dyn AsyncUdpSocket) {
564 _ = socket.try_send(&udp_transmit(&transmit, &response_buffer[..transmit.size]));
585}
586
587#[inline]
588fn proto_ecn(ecn: udp::EcnCodepoint) -> proto::EcnCodepoint {
589 match ecn {
590 udp::EcnCodepoint::Ect0 => proto::EcnCodepoint::Ect0,
591 udp::EcnCodepoint::Ect1 => proto::EcnCodepoint::Ect1,
592 udp::EcnCodepoint::Ce => proto::EcnCodepoint::Ce,
593 }
594}
595
596#[derive(Debug)]
597struct ConnectionSet {
598 senders: FxHashMap<ConnectionHandle, mpsc::UnboundedSender<ConnectionEvent>>,
600 sender: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>,
602 close: Option<(VarInt, Bytes)>,
604}
605
606impl ConnectionSet {
607 fn insert(
608 &mut self,
609 handle: ConnectionHandle,
610 conn: proto::Connection,
611 socket: Arc<dyn AsyncUdpSocket>,
612 runtime: Arc<dyn Runtime>,
613 ) -> Connecting {
614 let (send, recv) = mpsc::unbounded_channel();
615 if let Some((error_code, ref reason)) = self.close {
616 send.send(ConnectionEvent::Close {
617 error_code,
618 reason: reason.clone(),
619 })
620 .unwrap();
621 }
622 self.senders.insert(handle, send);
623 Connecting::new(handle, conn, self.sender.clone(), recv, socket, runtime)
624 }
625
626 fn is_empty(&self) -> bool {
627 self.senders.is_empty()
628 }
629}
630
631fn ensure_ipv6(x: SocketAddr) -> SocketAddrV6 {
632 match x {
633 SocketAddr::V6(x) => x,
634 SocketAddr::V4(x) => SocketAddrV6::new(x.ip().to_ipv6_mapped(), x.port(), 0, 0),
635 }
636}
637
638pin_project! {
639 pub struct Accept<'a> {
641 endpoint: &'a Endpoint,
642 #[pin]
643 notify: Notified<'a>,
644 }
645}
646
647impl Future for Accept<'_> {
648 type Output = Option<Incoming>;
649 fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
650 let mut this = self.project();
651 let mut endpoint = this.endpoint.inner.state.lock().unwrap();
652 if endpoint.driver_lost {
653 return Poll::Ready(None);
654 }
655 if let Some(incoming) = endpoint.recv_state.incoming.pop_front() {
656 drop(endpoint);
658 let incoming = Incoming::new(incoming, this.endpoint.inner.clone());
659 return Poll::Ready(Some(incoming));
660 }
661 if endpoint.recv_state.connections.close.is_some() {
662 return Poll::Ready(None);
663 }
664 loop {
665 match this.notify.as_mut().poll(ctx) {
666 Poll::Pending => return Poll::Pending,
668 Poll::Ready(()) => this
670 .notify
671 .set(this.endpoint.inner.shared.incoming.notified()),
672 }
673 }
674 }
675}
676
677#[derive(Debug)]
678pub(crate) struct EndpointRef(Arc<EndpointInner>);
679
680impl EndpointRef {
681 pub(crate) fn new(
682 socket: Arc<dyn AsyncUdpSocket>,
683 inner: proto::Endpoint,
684 ipv6: bool,
685 runtime: Arc<dyn Runtime>,
686 ) -> Self {
687 let (sender, events) = mpsc::unbounded_channel();
688 let recv_state = RecvState::new(sender, socket.max_receive_segments(), &inner);
689 Self(Arc::new(EndpointInner {
690 shared: Shared {
691 incoming: Notify::new(),
692 idle: Notify::new(),
693 ref_count: AtomicUsize::new(0),
694 },
695 state: Mutex::new(State {
696 socket,
697 prev_socket: None,
698 inner,
699 ipv6,
700 events,
701 driver: None,
702 driver_lost: false,
703 recv_state,
704 runtime,
705 stats: EndpointStats::default(),
706 }),
707 }))
708 }
709}
710
711impl Clone for EndpointRef {
712 fn clone(&self) -> Self {
713 self.0.shared.ref_count.fetch_add(1, Ordering::Relaxed);
714 Self(self.0.clone())
715 }
716}
717
718impl Drop for EndpointRef {
719 fn drop(&mut self) {
720 if self.shared.ref_count.fetch_sub(1, Ordering::Relaxed) > 1 {
721 return;
722 }
723
724 let endpoint = &mut *self.0.state.lock().unwrap();
725 if let Some(task) = endpoint.driver.take() {
728 task.wake();
729 }
730 }
731}
732
733impl std::ops::Deref for EndpointRef {
734 type Target = EndpointInner;
735 fn deref(&self) -> &Self::Target {
736 &self.0
737 }
738}
739
740struct RecvState {
742 incoming: VecDeque<proto::Incoming>,
743 connections: ConnectionSet,
744 recv_buf: Box<[u8]>,
745 recv_limiter: WorkLimiter,
746}
747
748impl RecvState {
749 fn new(
750 sender: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>,
751 max_receive_segments: usize,
752 endpoint: &proto::Endpoint,
753 ) -> Self {
754 let recv_buf = vec![
755 0;
756 endpoint.config().get_max_udp_payload_size().min(64 * 1024) as usize
757 * max_receive_segments
758 * BATCH_SIZE
759 ];
760 Self {
761 connections: ConnectionSet {
762 senders: FxHashMap::default(),
763 sender,
764 close: None,
765 },
766 incoming: VecDeque::new(),
767 recv_buf: recv_buf.into(),
768 recv_limiter: WorkLimiter::new(RECV_TIME_BOUND),
769 }
770 }
771
772 fn poll_socket(
773 &mut self,
774 cx: &mut Context,
775 endpoint: &mut proto::Endpoint,
776 socket: &dyn AsyncUdpSocket,
777 runtime: &dyn Runtime,
778 now: Instant,
779 ) -> Result<PollProgress, io::Error> {
780 let mut received_connection_packet = false;
781 let mut metas = [RecvMeta::default(); BATCH_SIZE];
782 let mut iovs: [IoSliceMut; BATCH_SIZE] = {
783 let mut bufs = self
784 .recv_buf
785 .chunks_mut(self.recv_buf.len() / BATCH_SIZE)
786 .map(IoSliceMut::new);
787
788 std::array::from_fn(|_| bufs.next().expect("BATCH_SIZE elements"))
792 };
793 loop {
794 match socket.poll_recv(cx, &mut iovs, &mut metas) {
795 Poll::Ready(Ok(msgs)) => {
796 self.recv_limiter.record_work(msgs);
797 for (meta, buf) in metas.iter().zip(iovs.iter()).take(msgs) {
798 let mut data: BytesMut = buf[0..meta.len].into();
799 while !data.is_empty() {
800 let buf = data.split_to(meta.stride.min(data.len()));
801 let mut response_buffer = Vec::new();
802 match endpoint.handle(
803 now,
804 meta.addr,
805 meta.dst_ip,
806 meta.ecn.map(proto_ecn),
807 buf,
808 &mut response_buffer,
809 ) {
810 Some(DatagramEvent::NewConnection(incoming)) => {
811 if self.connections.close.is_none() {
812 self.incoming.push_back(incoming);
813 } else {
814 let transmit =
815 endpoint.refuse(incoming, &mut response_buffer);
816 respond(transmit, &response_buffer, socket);
817 }
818 }
819 Some(DatagramEvent::ConnectionEvent(handle, event)) => {
820 received_connection_packet = true;
822 let _ = self
823 .connections
824 .senders
825 .get_mut(&handle)
826 .unwrap()
827 .send(ConnectionEvent::Proto(event));
828 }
829 Some(DatagramEvent::Response(transmit)) => {
830 respond(transmit, &response_buffer, socket);
831 }
832 None => {}
833 }
834 }
835 }
836 }
837 Poll::Pending => {
838 return Ok(PollProgress {
839 received_connection_packet,
840 keep_going: false,
841 });
842 }
843 Poll::Ready(Err(ref e)) if e.kind() == io::ErrorKind::ConnectionReset => {
846 continue;
847 }
848 Poll::Ready(Err(e)) => {
849 return Err(e);
850 }
851 }
852 if !self.recv_limiter.allow_work(|| runtime.now()) {
853 return Ok(PollProgress {
854 received_connection_packet,
855 keep_going: true,
856 });
857 }
858 }
859 }
860}
861
862impl fmt::Debug for RecvState {
863 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
864 f.debug_struct("RecvState")
865 .field("incoming", &self.incoming)
866 .field("connections", &self.connections)
867 .field("recv_limiter", &self.recv_limiter)
869 .finish_non_exhaustive()
870 }
871}
872
873#[derive(Default)]
874struct PollProgress {
875 received_connection_packet: bool,
877 keep_going: bool,
879}