use std::{
future::{Future, IntoFuture},
net::{IpAddr, SocketAddr},
pin::Pin,
task::{Context, Poll},
};
use futures_util::FutureExt;
use noq_proto::{ConnectionId, ServerConfig};
use thiserror::Error;
use crate::{Connecting, Connection, ConnectionError, EndpointRef};
#[derive(Debug)]
pub(crate) struct IncomingInner {
pub(crate) incoming: noq_proto::Incoming,
pub(crate) endpoint: EndpointRef,
}
#[derive(Debug)]
pub struct Incoming(Option<IncomingInner>);
impl Incoming {
pub(crate) fn new(incoming: noq_proto::Incoming, endpoint: EndpointRef) -> Self {
Self(Some(IncomingInner { incoming, endpoint }))
}
pub fn accept(mut self) -> Result<Connecting, ConnectionError> {
let inner = self.0.take().unwrap();
Ok(inner.endpoint.accept(inner.incoming, None)?)
}
pub fn accept_with(
mut self,
server_config: ServerConfig,
) -> Result<Connecting, ConnectionError> {
let inner = self.0.take().unwrap();
Ok(inner.endpoint.accept(inner.incoming, Some(server_config))?)
}
pub fn refuse(mut self) {
let inner = self.0.take().unwrap();
inner.endpoint.refuse(inner.incoming);
}
#[allow(clippy::result_large_err)]
pub fn retry(mut self) -> Result<(), RetryError> {
let inner = self.0.take().unwrap();
inner
.endpoint
.retry(inner.incoming)
.map_err(|e| RetryError(Box::new(Self::new(e.into_incoming(), inner.endpoint))))
}
pub fn ignore(mut self) {
let inner = self.0.take().unwrap();
inner.endpoint.ignore(inner.incoming);
}
pub fn local_ip(&self) -> Option<IpAddr> {
self.0.as_ref().unwrap().incoming.local_ip()
}
pub fn remote_address(&self) -> SocketAddr {
self.0.as_ref().unwrap().incoming.remote_address()
}
pub fn remote_address_validated(&self) -> bool {
self.0.as_ref().unwrap().incoming.remote_address_validated()
}
pub fn may_retry(&self) -> bool {
self.0.as_ref().unwrap().incoming.may_retry()
}
pub fn orig_dst_cid(&self) -> ConnectionId {
self.0.as_ref().unwrap().incoming.orig_dst_cid()
}
}
impl Drop for Incoming {
fn drop(&mut self) {
if let Some(inner) = self.0.take() {
inner.endpoint.refuse(inner.incoming);
}
}
}
#[derive(Debug, Error)]
#[error("retry() with validated Incoming")]
pub struct RetryError(Box<Incoming>);
impl RetryError {
pub fn into_incoming(self) -> Incoming {
*self.0
}
}
#[derive(Debug)]
pub struct IncomingFuture(Result<Connecting, ConnectionError>);
impl Future for IncomingFuture {
type Output = Result<Connection, ConnectionError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
match &mut self.0 {
Ok(connecting) => connecting.poll_unpin(cx),
Err(e) => Poll::Ready(Err(e.clone())),
}
}
}
impl IntoFuture for Incoming {
type IntoFuture = IncomingFuture;
type Output = Result<Connection, ConnectionError>;
fn into_future(self) -> Self::IntoFuture {
IncomingFuture(self.accept())
}
}