use std::fmt;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::os::fd::{AsFd, BorrowedFd};
use std::sync::Arc;
use std::time::Duration;
use core::fmt::Debug;
use async_trait::async_trait;
use crate::cfg_resolv_parser::ResolveConfEntry;
use crate::network_common::SocketTapCommon;
use crate::error::*;
#[async_trait]
#[allow(async_fn_in_trait)]
pub trait SocketTap<LOC>: SocketTapCommon + Send + Sync + fmt::Debug
{
async fn connect(&mut self, conn_timeout: Option<Duration>) -> CDnsResult<()>;
fn is_encrypted(&self) -> bool;
fn is_tcp(&self) -> bool;
fn should_append_len(&self) -> bool;
async fn poll_read(&self) -> CDnsResult<()>;
async fn send(&mut self, sndbuf: &[u8]) -> CDnsResult<usize> ;
async fn recv(&mut self, rcvbuf: &mut [u8]) -> CDnsResult<usize>;
}
pub type NetworkTapType<LOC> = (dyn SocketTap<LOC> + Send + Sync);
pub trait SocketTaps<LOC>: Clone + fmt::Debug + Send + Sync
{
type TcpSock: AsFd;
type UdpSock: AsFd;
#[cfg(feature = "use_async_tls")]
type TlsSock: AsFd;
fn new_tcp_socket(resolver: Arc<ResolveConfEntry>, timeout: Duration) -> CDnsResult<Box<NetworkTapType<LOC>>>;
fn new_udp_socket(resolver: Arc<ResolveConfEntry>, timeout: Duration) -> CDnsResult<Box<NetworkTapType<LOC>>>;
#[cfg(feature = "use_async_tls")]
fn new_tls_socket(resolver: Arc<ResolveConfEntry>, timeout: Duration) -> CDnsResult<Box<NetworkTapType<LOC>>>;
}
pub struct NetworkTap<T: AsFd, LOC>
{
pub sock: Option<T>,
pub timeout: Duration,
pub cfg: Arc<ResolveConfEntry>,
pub _loc: PhantomData<LOC>,
}
unsafe impl<T: AsFd, LOC> Send for NetworkTap<T, LOC> {}
unsafe impl<T: AsFd, LOC> Sync for NetworkTap<T, LOC> {}
impl<T: AsFd + Debug, LOC> fmt::Debug for NetworkTap<T, LOC>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
f.debug_struct("NetworkTap").field("sock", &self.sock).field("timeout", &self.timeout).field("cfg", &self.cfg).finish()
}
}
impl<T: AsFd, LOC> NetworkTap<T, LOC>
{
pub
fn new(resolver: Arc<ResolveConfEntry>, timeout: Duration) -> CDnsResult<Box<NetworkTapType<LOC>>> where NetworkTap<T, LOC>: SocketTap<LOC> + 'static
{
let ret =
NetworkTap::<T, LOC>
{
sock: None,
timeout: timeout,
cfg: resolver,
_loc: PhantomData
};
return Ok( Box::new(ret) );
}
}
impl<T: AsFd, LOC> SocketTapCommon for NetworkTap<T, LOC>
{
fn get_remote_addr(&self) -> &SocketAddr
{
return &self.cfg.get_resolver_sa();
}
}