use crate::dual::{DualAddr, DualListener, DualStream, ToDualAddr};
pub struct MultiListener {
pub listeners: Vec<DualListener>,
}
#[derive(Debug, Clone)]
pub struct MultiAddr {
pub addrs: Vec<DualAddr>,
}
pub struct MultiStream {
pub streams: Vec<DualStream>,
}
impl MultiListener {
pub async fn bind<I: IntoIterator<Item = A>, A: ToDualAddr>(
addresses: I,
) -> Result<Self, std::io::Error> {
let listeners = futures::future::join_all(addresses.into_iter().map(DualListener::bind))
.await
.into_iter()
.map(|f| dbg!(f))
.collect::<Result<Vec<_>, _>>()?;
Ok(MultiListener { listeners })
}
pub async fn accept(&self) -> Result<(DualStream, DualAddr), std::io::Error> {
let (out, idx, _rest) = futures::future::select_all(
self.listeners
.iter()
.map(|listener| listener._accept_unpin()),
)
.await;
tracing::trace!("Accepted connection on multi-listener from index {}", idx);
out
}
}
impl axum::serve::Listener for MultiListener {
type Io = DualStream;
type Addr = MultiAddr;
async fn accept(&mut self) -> (Self::Io, Self::Addr) {
let (out, _index, _rest) = futures::future::select_all(
self.listeners
.iter_mut()
.map(|listener| listener._accept_axum_unpin()),
)
.await;
tracing::trace!("Accepted connection on multi-listener from {}", _index);
(out.0, MultiAddr { addrs: vec![out.1] })
}
fn local_addr(&self) -> std::io::Result<Self::Addr> {
self.listeners
.iter()
.map(|listener| listener.local_addr())
.collect::<Result<Vec<_>, _>>()
.map(|addrs| MultiAddr { addrs })
}
}
const _: () = {
use super::MultiAddr;
use axum::extract::connect_info::Connected;
impl Connected<MultiAddr> for MultiAddr {
fn connect_info(remote_addr: MultiAddr) -> Self {
remote_addr
}
}
use axum::serve;
impl Connected<serve::IncomingStream<'_, MultiListener>> for MultiAddr {
fn connect_info(stream: serve::IncomingStream<'_, MultiListener>) -> Self {
stream.remote_addr().clone()
}
}
};