#![doc = include_str!("../README.md")]
use std::{
fmt::Debug,
io::Error,
net::SocketAddr,
sync::Arc,
task::{Context, Poll},
};
use tokio::net::TcpListener;
pub mod auth;
pub mod connection;
pub use crate::{
auth::Auth,
connection::{
associate::{Associate, AssociatedUdpSocket},
bind::Bind,
connect::Connect,
Command, IncomingConnection,
},
};
pub use socks5_proto as proto;
pub(crate) type AuthAdaptor<A> = Arc<dyn Auth<Output = A> + Send + Sync>;
type ServerAcceptResult<A> = Result<
(
IncomingConnection<A, connection::state::NeedAuthenticate>,
SocketAddr,
),
Error,
>;
pub struct Server<A> {
listener: TcpListener,
auth: AuthAdaptor<A>,
}
impl<A> Server<A> {
#[inline]
pub fn new(listener: TcpListener, auth: AuthAdaptor<A>) -> Self {
Self { listener, auth }
}
#[inline]
pub async fn accept(&self) -> ServerAcceptResult<A> {
let (stream, addr) = self.listener.accept().await?;
Ok((IncomingConnection::new(stream, self.auth.clone()), addr))
}
#[inline]
pub fn poll_accept(&self, cx: &mut Context<'_>) -> Poll<ServerAcceptResult<A>> {
self.listener
.poll_accept(cx)
.map_ok(|(stream, addr)| (IncomingConnection::new(stream, self.auth.clone()), addr))
}
#[inline]
pub fn local_addr(&self) -> Result<SocketAddr, Error> {
self.listener.local_addr()
}
#[inline]
pub fn get_ref(&self) -> &TcpListener {
&self.listener
}
#[inline]
pub fn get_mut(&mut self) -> &mut TcpListener {
&mut self.listener
}
#[inline]
pub fn into_inner(self) -> (TcpListener, AuthAdaptor<A>) {
(self.listener, self.auth)
}
}
impl<A> Debug for Server<A> {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Server")
.field("listener", &self.listener)
.finish()
}
}