use std::{
future::Future,
io,
net::SocketAddr,
pin::Pin,
task::{Context, Poll},
};
use shadowsocks::net::AcceptOpts;
use tokio::net::TcpListener;
use crate::config::RedirType;
pub trait TcpListenerRedirExt {
async fn bind_redir(ty: RedirType, addr: SocketAddr, accept_opts: AcceptOpts) -> io::Result<TcpListener>;
}
pub trait TcpStreamRedirExt {
fn destination_addr(&self, ty: RedirType) -> io::Result<SocketAddr>;
}
pub trait UdpSocketRedir {
fn poll_recv_dest_from(
&self,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<(usize, SocketAddr, SocketAddr)>>;
}
pub trait UdpSocketRedirExt {
fn recv_dest_from<'a>(&'a self, buf: &'a mut [u8]) -> RecvDestFrom<'a, Self>
where
Self: Sized,
{
RecvDestFrom { socket: self, buf }
}
}
impl<S> UdpSocketRedirExt for S where S: UdpSocketRedir {}
pub struct RecvDestFrom<'a, S: 'a> {
socket: &'a S,
buf: &'a mut [u8],
}
impl<'a, S: 'a> Future for RecvDestFrom<'a, S>
where
S: UdpSocketRedir,
{
type Output = io::Result<(usize, SocketAddr, SocketAddr)>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.socket.poll_recv_dest_from(cx, self.buf)
}
}
#[derive(Debug, Clone, Default)]
pub struct RedirSocketOpts {
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fwmark: Option<u32>,
}