1#![doc = include_str!("../README.md")]
2pub type Result<T> = std::result::Result<T, errors::Error>;
3
4
5#[cfg(feature = "tls")]
6pub mod tls_exports {
7 pub use rustls::{ClientConfig, RootCertStore};
8 pub use rustls_pki_types::ServerName;
9 pub use tokio::net::TcpStream;
10 pub use tokio_rustls::{TlsConnector, client::TlsStream};
11}
12
13#[cfg(feature = "tls")]
14pub use tls_exports::*;
15
16#[cfg(feature = "tls")]
17use std::sync::Arc;
18use std::{
19 borrow::Cow,
20 net::{SocketAddr, SocketAddrV4, SocketAddrV6},
21};
22fn is_ok_status(utf8_proxy_response: Cow<'_, str>) -> bool {
23 utf8_proxy_response
24 .lines()
25 .next()
26 .and_then(|line| line.split_whitespace().nth(1))
27 .and_then(|code| code.parse::<u16>().ok())
28 .map(|code| (200..399).contains(&code))
29 .unwrap_or(false)
30}
31
32pub mod auth;
33pub mod errors;
34
35pub use errors::Error;
36pub mod http;
37#[cfg(feature = "tls")]
38pub mod https;
39
40pub mod socks4;
41pub mod socks5;
42
43#[cfg(test)]
44mod tests;
45
46#[derive(Clone)]
48pub enum NetworkTarget {
49 IP(SocketAddr),
50 Domain(String, Port),
51}
52
53pub struct Context<T = SocketAddrV4, P = SocketAddrV4> {
55 pub destination: T,
56 pub proxy: P,
57}
58
59#[repr(transparent)]
74#[derive(Clone)]
75pub struct Port(pub u16);
76
77impl From<SocketAddrV4> for NetworkTarget {
78 fn from(value: SocketAddrV4) -> Self {
79 Self::IP(SocketAddr::V4(value))
80 }
81}
82
83impl From<SocketAddrV6> for NetworkTarget {
84 fn from(value: SocketAddrV6) -> Self {
85 Self::IP(SocketAddr::V6(value))
86 }
87}
88
89#[cfg(feature = "tls")]
95pub async fn socks_with_tls(
96 stream: TcpStream,
97 config: Arc<ClientConfig>,
98 sni: ServerName<'static>,
99) -> crate::Result<TlsStream<TcpStream>> {
100 let connector = TlsConnector::from(config);
101 let stream = connector.connect(sni, stream).await?;
102 Ok(stream)
103}