use crate::{config, tcp, websocket, ResultType}; use sodiumoxide::crypto::secretbox::Key; use std::net::SocketAddr; use tokio::net::TcpStream; // support Websocket and tcp. pub enum Stream { WebSocket(websocket::WsFramedStream), Tcp(tcp::FramedStream), } impl Stream { #[inline] pub fn set_send_timeout(&mut self, ms: u64) { match self { Stream::WebSocket(s) => s.set_send_timeout(ms), Stream::Tcp(s) => s.set_send_timeout(ms), } } #[inline] pub fn set_raw(&mut self) { match self { Stream::WebSocket(s) => s.set_raw(), Stream::Tcp(s) => s.set_raw(), } } #[inline] pub async fn send_bytes(&mut self, bytes: bytes::Bytes) -> ResultType<()> { match self { Stream::WebSocket(s) => s.send_bytes(bytes).await, Stream::Tcp(s) => s.send_bytes(bytes).await, } } #[inline] pub async fn send_raw(&mut self, bytes: Vec) -> ResultType<()> { match self { Stream::WebSocket(s) => s.send_raw(bytes).await, Stream::Tcp(s) => s.send_raw(bytes).await, } } #[inline] pub fn set_key(&mut self, key: Key) { match self { Stream::WebSocket(s) => s.set_key(key), Stream::Tcp(s) => s.set_key(key), } } #[inline] pub fn is_secured(&self) -> bool { match self { Stream::WebSocket(s) => s.is_secured(), Stream::Tcp(s) => s.is_secured(), } } #[inline] pub async fn next_timeout( &mut self, timeout: u64, ) -> Option> { match self { Stream::WebSocket(s) => s.next_timeout(timeout).await, Stream::Tcp(s) => s.next_timeout(timeout).await, } } /// establish connect from websocket #[inline] pub async fn connect_websocket( url: impl AsRef, local_addr: Option, proxy_conf: Option<&config::Socks5Server>, timeout_ms: u64, ) -> ResultType { let ws_stream = websocket::WsFramedStream::new(url, local_addr, proxy_conf, timeout_ms).await?; log::debug!("WebSocket connection established"); Ok(Self::WebSocket(ws_stream)) } /// send message #[inline] pub async fn send(&mut self, msg: &impl protobuf::Message) -> ResultType<()> { match self { Self::WebSocket(ws) => ws.send(msg).await, Self::Tcp(tcp) => tcp.send(msg).await, } } /// receive message #[inline] pub async fn next(&mut self) -> Option> { match self { Self::WebSocket(ws) => ws.next().await, Self::Tcp(tcp) => tcp.next().await, } } #[inline] pub fn local_addr(&self) -> SocketAddr { match self { Self::WebSocket(ws) => ws.local_addr(), Self::Tcp(tcp) => tcp.local_addr(), } } #[inline] pub fn from(stream: TcpStream, stream_addr: SocketAddr) -> Self { Self::Tcp(tcp::FramedStream::from(stream, stream_addr)) } }