mod socket;
mod middle;
mod plain;
#[cfg(feature = "hook")]
mod hook;
#[cfg(feature = "proxy")]
mod proxy;
#[cfg(feature = "transport")]
mod transport;
use std::io::{ErrorKind, Result};
use crate::trick::Ref;
use crate::endpoint::Endpoint;
use middle::connect_and_relay;
pub async fn run_tcp(endpoint: Endpoint) -> Result<()> {
let Endpoint {
laddr,
raddr,
bind_opts,
conn_opts,
extra_raddrs,
} = endpoint;
let raddr = Ref::new(&raddr);
let conn_opts = Ref::new(&conn_opts);
let extra_raddrs = Ref::new(&extra_raddrs);
let lis = socket::bind(&laddr, bind_opts).unwrap_or_else(|e| panic!("[tcp]failed to bind {}: {}", &laddr, e));
let keepalive = socket::keepalive::build(&conn_opts);
loop {
let (local, addr) = match lis.accept().await {
Ok(x) => x,
Err(e) if e.kind() == ErrorKind::ConnectionAborted => {
log::warn!("[tcp]failed to accept: {}", e);
continue;
}
Err(e) => {
log::error!("[tcp]failed to accept: {}", e);
break;
}
};
let _ = local.set_nodelay(true);
if let Some(kpa) = &keepalive {
use socket::keepalive::SockRef;
SockRef::from(&local).set_tcp_keepalive(kpa)?;
}
tokio::spawn(async move {
match connect_and_relay(local, raddr, conn_opts, extra_raddrs).await {
Ok(..) => log::debug!("[tcp]{} => {}, finish", addr, raddr.as_ref()),
Err(e) => log::error!("[tcp]{} => {}, error: {}", addr, raddr.as_ref(), e),
}
});
}
Ok(())
}