1 pub mod conn_bridge; 2 pub mod conn_disconnected_packet; 3 pub mod conn_pipe; 4 pub mod conn_udp; 5 pub mod conn_udp_listener; 6 7 #[cfg(test)] 8 mod conn_bridge_test; 9 #[cfg(test)] 10 mod conn_pipe_test; 11 #[cfg(test)] 12 mod conn_test; 13 14 //TODO: remove this conditional test 15 #[cfg(not(target_os = "windows"))] 16 #[cfg(test)] 17 mod conn_udp_listener_test; 18 19 use async_trait::async_trait; 20 use std::net::SocketAddr; 21 use std::sync::Arc; 22 use tokio::net::ToSocketAddrs; 23 24 use crate::error::Result; 25 26 #[async_trait] 27 pub trait Conn { 28 async fn connect(&self, addr: SocketAddr) -> Result<()>; 29 async fn recv(&self, buf: &mut [u8]) -> Result<usize>; 30 async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)>; 31 async fn send(&self, buf: &[u8]) -> Result<usize>; 32 async fn send_to(&self, buf: &[u8], target: SocketAddr) -> Result<usize>; 33 async fn local_addr(&self) -> Result<SocketAddr>; 34 async fn remote_addr(&self) -> Option<SocketAddr>; 35 async fn close(&self) -> Result<()>; 36 } 37 38 /// A Listener is a generic network listener for connection-oriented protocols. 39 /// Multiple connections may invoke methods on a Listener simultaneously. 40 #[async_trait] 41 pub trait Listener { 42 /// accept waits for and returns the next connection to the listener. 43 async fn accept(&self) -> Result<(Arc<dyn Conn + Send + Sync>, SocketAddr)>; 44 45 /// close closes the listener. 46 /// Any blocked accept operations will be unblocked and return errors. 47 async fn close(&self) -> Result<()>; 48 49 /// addr returns the listener's network address. 50 async fn addr(&self) -> Result<SocketAddr>; 51 } 52 53 pub async fn lookup_host<T>(use_ipv4: bool, host: T) -> Result<SocketAddr> 54 where 55 T: ToSocketAddrs, 56 { 57 for remote_addr in tokio::net::lookup_host(host).await? { 58 if (use_ipv4 && remote_addr.is_ipv4()) || (!use_ipv4 && remote_addr.is_ipv6()) { 59 return Ok(remote_addr); 60 } 61 } 62 63 Err(std::io::Error::new( 64 std::io::ErrorKind::Other, 65 format!( 66 "No available {} IP address found!", 67 if use_ipv4 { "ipv4" } else { "ipv6" }, 68 ), 69 ) 70 .into()) 71 } 72