use anyhow::Result;
use tokio_tfo::TfoListener;
use crate::relay::core;
use crate::relay::inbound::{Inbound, InboundContext, InboundFuture};
use crate::relay::runtime::RelayRuntime;
const ACCEPT_ERROR_BACKOFF: std::time::Duration = std::time::Duration::from_secs(1);
pub struct TcpInbound;
impl Inbound for TcpInbound {
fn run(self: Box<Self>, ctx: InboundContext) -> InboundFuture {
Box::pin(async move { run(ctx.addr, ctx.runtime).await })
}
}
pub async fn run(addr: std::net::SocketAddr, runtime: RelayRuntime) -> Result<()> {
let listener = TfoListener::bind(addr).await?;
tracing::info!("relay listening on {}", addr);
loop {
let (stream, peer_addr) = match listener.accept().await {
Ok(v) => v,
Err(e) => {
tracing::warn!("accept error: {}", e);
tokio::time::sleep(ACCEPT_ERROR_BACKOFF).await;
continue;
}
};
tracing::debug!("accepted connection from {}", peer_addr);
let runtime = runtime.clone();
tokio::spawn(async move {
if let Err(e) = handle_conn(stream, peer_addr, runtime).await {
tracing::debug!("connection error ({}): {}", peer_addr, e);
}
});
}
}
async fn handle_conn(
stream: tokio_tfo::TfoStream,
peer_addr: std::net::SocketAddr,
runtime: RelayRuntime,
) -> Result<()> {
core::handle_stream(stream, peer_addr, runtime).await
}