#![doc = include_str!("../README.md")]
use std::{
net::{SocketAddrV4, SocketAddrV6},
pin::Pin,
time::{Duration, Instant},
};
use futures::Future; use tokio::io::{AsyncRead, AsyncWrite};
mod error;
pub use error::Error;
#[macro_use]
pub mod args;
mod helpers;
pub use helpers::*;
mod log;
pub mod orport;
pub trait PluggableTransport<InRW>
where
InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
{
type ClientBuilder: ClientBuilder<InRW>;
type ServerBuilder: ServerBuilder<InRW>;
fn name() -> String;
fn client_builder() -> <Self as PluggableTransport<InRW>>::ClientBuilder;
fn server_builder() -> <Self as PluggableTransport<InRW>>::ServerBuilder;
}
pub trait ClientBuilder<InRW>: Default + Clone
where
InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
{
type Error: std::error::Error + Send + Sync;
type ClientPT: ClientTransport<InRW, Self::Error>;
type Transport;
fn method_name() -> String;
fn build(&self) -> Self::ClientPT;
fn options(&mut self, opts: &args::Args) -> Result<&mut Self, Self::Error>;
fn statefile_location(&mut self, path: &str) -> Result<&mut Self, Self::Error>;
fn timeout(&mut self, timeout: Option<Duration>) -> Result<&mut Self, Self::Error>;
fn v4_bind_addr(&mut self, addr: SocketAddrV4) -> Result<&mut Self, Self::Error>;
fn v6_bind_addr(&mut self, addr: SocketAddrV6) -> Result<&mut Self, Self::Error>;
}
pub trait ClientTransport<InRW, InErr>
where
InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
{
type OutRW: AsyncRead + AsyncWrite + Send + Unpin;
type OutErr: std::error::Error + Send + Sync;
type Builder: ClientBuilder<InRW>;
fn establish(self, input: Pin<F<InRW, InErr>>) -> Pin<F<Self::OutRW, Self::OutErr>>;
fn wrap(self, io: InRW) -> Pin<F<Self::OutRW, Self::OutErr>>;
fn method_name() -> String;
}
pub trait ServerTransport<InRW>
where
InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
{
type OutRW: AsyncRead + AsyncWrite + Send + Unpin;
type OutErr: std::error::Error + Send + Sync;
type Builder: ServerBuilder<InRW>;
fn reveal(self, io: InRW) -> Pin<F<Self::OutRW, Self::OutErr>>;
fn method_name() -> String;
}
pub trait ServerBuilder<InRW>: Default
where
InRW: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
{
type ServerPT: ServerTransport<InRW>;
type Error: std::error::Error;
type Transport;
fn method_name() -> String;
fn build(&self) -> Self::ServerPT;
fn options(&mut self, opts: &args::Args) -> Result<&mut Self, Self::Error>;
fn get_client_params(&self) -> String;
fn statefile_location(&mut self, path: &str) -> Result<&mut Self, Self::Error>;
fn timeout(&mut self, timeout: Option<Duration>) -> Result<&mut Self, Self::Error>;
fn v4_bind_addr(&mut self, addr: SocketAddrV4) -> Result<&mut Self, Self::Error>;
fn v6_bind_addr(&mut self, addr: SocketAddrV6) -> Result<&mut Self, Self::Error>;
}
pub trait Conn {
type OutRW;
type OutErr;
type Future: Future<Output = Result<Self::OutRW, Self::OutErr>>;
fn new() -> Self::Future;
}
pub trait ConnectExt: Conn {
fn connect_with_deadline(
&mut self,
deadline: Instant,
) -> Result<Self::Future, tokio::time::error::Elapsed>;
fn connect_with_timeout(
&mut self,
timeout: Duration,
) -> Result<Self::Future, tokio::time::error::Elapsed>;
}
impl Conn for tokio::net::TcpStream {
type OutRW = Self;
type OutErr = std::io::Error;
type Future = Pin<F<Self::OutRW, Self::OutErr>>;
fn new() -> Self::Future {
let f = tokio::net::TcpStream::connect("127.0.0.1:9000");
Box::pin(f)
}
}
impl Conn for tokio::net::UdpSocket {
type OutErr = std::io::Error;
type OutRW = tokio::net::UdpSocket;
type Future = Pin<F<Self::OutRW, Self::OutErr>>;
fn new() -> Self::Future {
let f = tokio::net::UdpSocket::bind("127.0.0.1:9000");
Box::pin(f)
}
}
pub type FutureResult<T, E> = Box<dyn Future<Output = Result<T, E>> + Send>;
pub(crate) type F<T, E> = FutureResult<T, E>;
pub type TcpStreamFut = Pin<FutureResult<tokio::net::TcpStream, std::io::Error>>;
pub type UdpSocketFut = Pin<FutureResult<tokio::net::UdpSocket, std::io::Error>>;
#[cfg(test)]
mod passthrough;