compio_quic/
incoming.rs

1use std::{
2    future::{Future, IntoFuture},
3    net::{IpAddr, SocketAddr},
4    pin::Pin,
5    sync::Arc,
6    task::{Context, Poll},
7};
8
9use futures_util::FutureExt;
10use quinn_proto::ServerConfig;
11use thiserror::Error;
12
13use crate::{Connecting, Connection, ConnectionError, EndpointInner};
14
15#[derive(Debug)]
16pub(crate) struct IncomingInner {
17    pub(crate) incoming: quinn_proto::Incoming,
18    pub(crate) endpoint: Arc<EndpointInner>,
19}
20
21/// An incoming connection for which the server has not yet begun its part
22/// of the handshake.
23#[derive(Debug)]
24pub struct Incoming(Option<IncomingInner>);
25
26impl Incoming {
27    pub(crate) fn new(incoming: quinn_proto::Incoming, endpoint: Arc<EndpointInner>) -> Self {
28        Self(Some(IncomingInner { incoming, endpoint }))
29    }
30
31    /// Attempt to accept this incoming connection (an error may still
32    /// occur).
33    pub fn accept(mut self) -> Result<Connecting, ConnectionError> {
34        let inner = self.0.take().unwrap();
35        Ok(inner.endpoint.accept(inner.incoming, None)?)
36    }
37
38    /// Accept this incoming connection using a custom configuration.
39    ///
40    /// See [`accept()`] for more details.
41    ///
42    /// [`accept()`]: Incoming::accept
43    pub fn accept_with(
44        mut self,
45        server_config: ServerConfig,
46    ) -> Result<Connecting, ConnectionError> {
47        let inner = self.0.take().unwrap();
48        Ok(inner.endpoint.accept(inner.incoming, Some(server_config))?)
49    }
50
51    /// Reject this incoming connection attempt.
52    pub fn refuse(mut self) {
53        let inner = self.0.take().unwrap();
54        inner.endpoint.refuse(inner.incoming);
55    }
56
57    /// Respond with a retry packet, requiring the client to retry with
58    /// address validation.
59    ///
60    /// Errors if `remote_address_validated()` is true.
61    #[allow(clippy::result_large_err)]
62    pub fn retry(mut self) -> Result<(), RetryError> {
63        let inner = self.0.take().unwrap();
64        inner
65            .endpoint
66            .retry(inner.incoming)
67            .map_err(|e| RetryError(Self::new(e.into_incoming(), inner.endpoint)))
68    }
69
70    /// Ignore this incoming connection attempt, not sending any packet in
71    /// response.
72    pub fn ignore(mut self) {
73        let inner = self.0.take().unwrap();
74        inner.endpoint.ignore(inner.incoming);
75    }
76
77    /// The local IP address which was used when the peer established
78    /// the connection.
79    pub fn local_ip(&self) -> Option<IpAddr> {
80        self.0.as_ref().unwrap().incoming.local_ip()
81    }
82
83    /// The peer's UDP address.
84    pub fn remote_address(&self) -> SocketAddr {
85        self.0.as_ref().unwrap().incoming.remote_address()
86    }
87
88    /// Whether the socket address that is initiating this connection has
89    /// been validated.
90    ///
91    /// This means that the sender of the initial packet has proved that
92    /// they can receive traffic sent to `self.remote_address()`.
93    pub fn remote_address_validated(&self) -> bool {
94        self.0.as_ref().unwrap().incoming.remote_address_validated()
95    }
96}
97
98impl Drop for Incoming {
99    fn drop(&mut self) {
100        // Implicit reject, similar to Connection's implicit close
101        if let Some(inner) = self.0.take() {
102            inner.endpoint.refuse(inner.incoming);
103        }
104    }
105}
106
107/// Error for attempting to retry an [`Incoming`] which already bears an
108/// address validation token from a previous retry.
109#[derive(Debug, Error)]
110#[error("retry() with validated Incoming")]
111pub struct RetryError(Incoming);
112
113impl RetryError {
114    /// Get the [`Incoming`]
115    pub fn into_incoming(self) -> Incoming {
116        self.0
117    }
118}
119
120/// Basic adapter to let [`Incoming`] be `await`-ed like a [`Connecting`].
121#[derive(Debug)]
122pub struct IncomingFuture(Result<Connecting, ConnectionError>);
123
124impl Future for IncomingFuture {
125    type Output = Result<Connection, ConnectionError>;
126
127    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
128        match &mut self.0 {
129            Ok(connecting) => connecting.poll_unpin(cx),
130            Err(e) => Poll::Ready(Err(e.clone())),
131        }
132    }
133}
134
135impl IntoFuture for Incoming {
136    type IntoFuture = IncomingFuture;
137    type Output = Result<Connection, ConnectionError>;
138
139    fn into_future(self) -> Self::IntoFuture {
140        IncomingFuture(self.accept())
141    }
142}