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