use std::{
collections::HashMap,
future::Future,
net::{SocketAddr, TcpListener as StdTcpListener, UdpSocket},
sync::Arc,
};
use faststr::FastStr;
use listenfd::ListenFd;
use parking_lot::RwLock;
use tokio::{
net::TcpListener,
task::{JoinHandle, JoinSet},
};
use crate::{CertLoad, CertLoader, Error, Result, Route};
pub mod h1;
pub mod h2;
pub mod h3;
pub mod s2n_quic;
struct Srv {
set: JoinSet<(FastStr, Result<()>)>,
stop_handle: JoinHandle<()>,
}
impl Srv {
fn new(stop_handle: JoinHandle<()>) -> Self {
Self {
set: JoinSet::new(),
stop_handle,
}
}
fn spawn<F>(&mut self, name: impl Into<FastStr>, fut: F)
where
F: Future<Output = Result<()>> + Send + 'static,
{
let name = name.into();
self.set.spawn(async move { (name, fut.await) });
}
async fn join(&mut self) {
while let Some(res) = self.set.join_next().await {
self.stop_handle.abort();
match res {
Ok((name, Ok(_))) => log::info!("{name} 服务正常结束"),
Ok((name, Err(e))) => log::warn!("{name} 服务因错误退出: {e}"),
Err(e) => log::warn!("服务 panic: {e}"),
}
}
}
}
pub async fn srv<D: CertLoad, F: Future<Output = ()> + Send + 'static>(
route: Arc<Route>,
cert_loader: Arc<CertLoader<D>>,
graceful_shutdown: F,
h1_addr: SocketAddr,
h2_addr: SocketAddr,
h3_addr: SocketAddr,
) -> Result<()> {
let shutdown_lock = Arc::new(tokio::sync::RwLock::new(()));
let stop_handle = tokio::spawn({
let shutdown_lock = shutdown_lock.clone();
async move {
let _guard = shutdown_lock.write().await;
graceful_shutdown.await
}
});
let conn_lock = Arc::new(RwLock::new(()));
let mut srv = Srv::new(stop_handle);
let mut listenfd = ListenFd::from_env();
let (mut tcp_listeners, mut udp_listeners) = if listenfd.len() > 0 {
socket_from_listenfd(&mut listenfd)?
} else {
Default::default()
};
let h1_listener = get_or_create_tcp_listener(&mut tcp_listeners, h1_addr).await?;
let h2_listener = get_or_create_tcp_listener(&mut tcp_listeners, h2_addr).await?;
let h3_socket = get_or_create_udp_socket(&mut udp_listeners, h3_addr).await?;
srv.spawn(
"h1",
h1::srv(
shutdown_lock.clone(),
conn_lock.clone(),
h1_listener,
route.clone(),
),
);
srv.spawn(
"h2",
h2::srv(
shutdown_lock.clone(),
conn_lock.clone(),
h2_listener,
route.clone(),
cert_loader.clone(),
),
);
srv.spawn(
"h3",
h3::srv(
shutdown_lock,
conn_lock.clone(),
h3_socket,
route,
cert_loader,
),
);
log::info!(
"
h1 {h1_addr}
h2 {h2_addr}
h3 {h3_addr}"
);
srv.join().await;
log::info!("等待所有连接关闭");
{
let _guard = conn_lock.write();
}
log::info!("所有连接都已关闭,退出进程");
Ok(())
}
fn socket_from_listenfd(
listenfd: &mut ListenFd,
) -> Result<(
HashMap<SocketAddr, StdTcpListener>,
HashMap<SocketAddr, UdpSocket>,
)> {
let mut tcp_listeners = HashMap::new();
let mut udp_sockets = HashMap::new();
for i in 0..listenfd.len() {
if let Ok(Some(l)) = listenfd.take_tcp_listener(i) {
l.set_nonblocking(true)?;
tcp_listeners.insert(l.local_addr()?, l);
} else if let Ok(Some(l)) = listenfd.take_udp_socket(i) {
l.set_nonblocking(true)?;
udp_sockets.insert(l.local_addr()?, l);
}
}
Ok((tcp_listeners, udp_sockets))
}
async fn get_or_create_tcp_listener(
listeners: &mut HashMap<SocketAddr, StdTcpListener>,
addr: SocketAddr,
) -> Result<TcpListener> {
if let Some(listener) = listeners.remove(&addr) {
log::info!("从环境变量获取TCP端口: {}", addr);
return TcpListener::from_std(listener).map_err(Error::Io);
}
log::info!("手动创建TCP端口: {}", addr);
TcpListener::bind(addr).await.map_err(Error::Io)
}
async fn get_or_create_udp_socket(
sockets: &mut HashMap<SocketAddr, UdpSocket>,
addr: SocketAddr,
) -> Result<UdpSocket> {
let socket = if let Some(socket) = sockets.remove(&addr) {
log::info!("从环境变量获取UDP端口: {}", addr);
socket
} else {
log::info!("手动创建UDP端口: {}", addr);
std::net::UdpSocket::bind(addr).map_err(Error::Io)?
};
Ok(socket)
}