1use std::{
2 future::{Future, IntoFuture},
3 net::{IpAddr, SocketAddr},
4 pin::Pin,
5 task::{Context, Poll},
6};
7
8use futures_util::FutureExt;
9use quinn_proto::{ConnectionId, ServerConfig};
10use thiserror::Error;
11
12use crate::{Connecting, Connection, ConnectionError, EndpointRef};
13
14#[derive(Debug)]
15pub(crate) struct IncomingInner {
16 pub(crate) incoming: quinn_proto::Incoming,
17 pub(crate) endpoint: EndpointRef,
18}
19
20#[derive(Debug)]
23pub struct Incoming(Option<IncomingInner>);
24
25impl Incoming {
26 pub(crate) fn new(incoming: quinn_proto::Incoming, endpoint: EndpointRef) -> Self {
27 Self(Some(IncomingInner { incoming, endpoint }))
28 }
29
30 pub fn accept(mut self) -> Result<Connecting, ConnectionError> {
33 let inner = self.0.take().unwrap();
34 Ok(inner.endpoint.accept(inner.incoming, None)?)
35 }
36
37 pub fn accept_with(
43 mut self,
44 server_config: ServerConfig,
45 ) -> Result<Connecting, ConnectionError> {
46 let inner = self.0.take().unwrap();
47 Ok(inner.endpoint.accept(inner.incoming, Some(server_config))?)
48 }
49
50 pub fn refuse(mut self) {
52 let inner = self.0.take().unwrap();
53 inner.endpoint.refuse(inner.incoming);
54 }
55
56 #[allow(clippy::result_large_err)]
61 pub fn retry(mut self) -> Result<(), RetryError> {
62 let inner = self.0.take().unwrap();
63 inner
64 .endpoint
65 .retry(inner.incoming)
66 .map_err(|e| RetryError(Box::new(Self::new(e.into_incoming(), inner.endpoint))))
67 }
68
69 pub fn ignore(mut self) {
72 let inner = self.0.take().unwrap();
73 inner.endpoint.ignore(inner.incoming);
74 }
75
76 pub fn local_ip(&self) -> Option<IpAddr> {
79 self.0.as_ref().unwrap().incoming.local_ip()
80 }
81
82 pub fn remote_address(&self) -> SocketAddr {
84 self.0.as_ref().unwrap().incoming.remote_address()
85 }
86
87 pub fn remote_address_validated(&self) -> bool {
93 self.0.as_ref().unwrap().incoming.remote_address_validated()
94 }
95
96 pub fn may_retry(&self) -> bool {
101 self.0.as_ref().unwrap().incoming.may_retry()
102 }
103
104 pub fn orig_dst_cid(&self) -> ConnectionId {
106 *self.0.as_ref().unwrap().incoming.orig_dst_cid()
107 }
108}
109
110impl Drop for Incoming {
111 fn drop(&mut self) {
112 if let Some(inner) = self.0.take() {
114 inner.endpoint.refuse(inner.incoming);
115 }
116 }
117}
118
119#[derive(Debug, Error)]
122#[error("retry() with validated Incoming")]
123pub struct RetryError(Box<Incoming>);
124
125impl RetryError {
126 pub fn into_incoming(self) -> Incoming {
128 *self.0
129 }
130}
131
132#[derive(Debug)]
134pub struct IncomingFuture(Result<Connecting, ConnectionError>);
135
136impl Future for IncomingFuture {
137 type Output = Result<Connection, ConnectionError>;
138
139 fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
140 match &mut self.0 {
141 Ok(connecting) => connecting.poll_unpin(cx),
142 Err(e) => Poll::Ready(Err(e.clone())),
143 }
144 }
145}
146
147impl IntoFuture for Incoming {
148 type IntoFuture = IncomingFuture;
149 type Output = Result<Connection, ConnectionError>;
150
151 fn into_future(self) -> Self::IntoFuture {
152 IncomingFuture(self.accept())
153 }
154}