ant_quic/high_level/
incoming.rs1use std::{
9 future::{Future, IntoFuture},
10 net::{IpAddr, SocketAddr},
11 pin::Pin,
12 sync::Arc,
13 task::{Context, Poll},
14};
15
16use crate::{ConnectionError, ConnectionId, ServerConfig};
17use thiserror::Error;
18use tracing::error;
19
20use super::{
21 connection::{Connecting, Connection},
22 endpoint::EndpointRef,
23};
24
25#[derive(Debug)]
27pub struct Incoming(Option<State>);
28
29impl Incoming {
30 pub(crate) fn new(inner: crate::Incoming, endpoint: EndpointRef) -> Self {
31 Self(Some(State { inner, endpoint }))
32 }
33
34 pub fn accept(mut self) -> Result<Connecting, ConnectionError> {
36 let state = self.0.take().ok_or_else(|| {
37 error!("Incoming connection state already consumed");
38 ConnectionError::LocallyClosed
39 })?;
40 state.endpoint.accept(state.inner, None)
41 }
42
43 pub fn accept_with(
47 mut self,
48 server_config: Arc<ServerConfig>,
49 ) -> Result<Connecting, ConnectionError> {
50 let state = self.0.take().ok_or_else(|| {
51 error!("Incoming connection state already consumed");
52 ConnectionError::LocallyClosed
53 })?;
54 state.endpoint.accept(state.inner, Some(server_config))
55 }
56
57 pub fn refuse(mut self) {
59 if let Some(state) = self.0.take() {
60 state.endpoint.refuse(state.inner);
61 } else {
62 error!("Incoming connection state already consumed");
63 }
64 }
65
66 #[allow(clippy::panic)]
70 pub fn retry(mut self) -> Result<(), RetryError> {
71 let state = match self.0.take() {
72 Some(state) => state,
73 None => {
74 error!("Incoming connection state already consumed");
75 panic!("Incoming connection state already consumed - this is a programming error");
79 }
80 };
81 state.endpoint.retry(state.inner).map_err(|_| {
82 panic!("Retry failed due to internal error");
85 })
86 }
87
88 pub fn ignore(mut self) {
90 if let Some(state) = self.0.take() {
91 state.endpoint.ignore(state.inner);
92 } else {
93 error!("Incoming connection state already consumed");
94 }
95 }
96
97 pub fn local_ip(&self) -> Option<IpAddr> {
99 self.0.as_ref()?.inner.local_ip()
100 }
101
102 #[allow(clippy::panic)]
104 pub fn remote_address(&self) -> SocketAddr {
105 self.0
106 .as_ref()
107 .map(|state| state.inner.remote_address())
108 .unwrap_or_else(|| {
109 "0.0.0.0:0".parse().unwrap_or_else(|_| {
110 panic!("Failed to parse fallback address");
111 })
112 })
113 }
114
115 pub fn remote_address_validated(&self) -> bool {
123 self.0
124 .as_ref()
125 .map(|state| state.inner.remote_address_validated())
126 .unwrap_or(false)
127 }
128
129 pub fn may_retry(&self) -> bool {
134 self.0
135 .as_ref()
136 .map(|state| state.inner.may_retry())
137 .unwrap_or(false)
138 }
139
140 pub fn orig_dst_cid(&self) -> ConnectionId {
142 self.0
143 .as_ref()
144 .map(|state| *state.inner.orig_dst_cid())
145 .unwrap_or_else(|| ConnectionId::new(&[0]))
146 }
147}
148
149impl Drop for Incoming {
150 fn drop(&mut self) {
151 if let Some(state) = self.0.take() {
153 state.endpoint.refuse(state.inner);
154 }
155 }
156}
157
158#[derive(Debug)]
159struct State {
160 inner: crate::Incoming,
161 endpoint: EndpointRef,
162}
163
164#[derive(Debug, Error)]
166#[error("retry() with validated Incoming")]
167pub struct RetryError(Box<Incoming>);
168
169impl RetryError {
170 pub fn into_incoming(self) -> Incoming {
172 *self.0
173 }
174}
175
176#[derive(Debug)]
178pub struct IncomingFuture(Result<Connecting, ConnectionError>);
179
180impl Future for IncomingFuture {
181 type Output = Result<Connection, ConnectionError>;
182
183 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
184 match &mut self.0 {
185 Ok(connecting) => Pin::new(connecting).poll(cx),
186 Err(e) => Poll::Ready(Err(e.clone())),
187 }
188 }
189}
190
191impl IntoFuture for Incoming {
192 type Output = Result<Connection, ConnectionError>;
193 type IntoFuture = IncomingFuture;
194
195 fn into_future(self) -> Self::IntoFuture {
196 IncomingFuture(self.accept())
197 }
198}