diff --git a/tuic-client/src/config.rs b/tuic-client/src/config.rs index 60a27e9..8178b47 100644 --- a/tuic-client/src/config.rs +++ b/tuic-client/src/config.rs @@ -12,6 +12,7 @@ use std::{ net::{IpAddr, SocketAddr}, path::PathBuf, str::FromStr, + sync::Arc, time::Duration, }; use thiserror::Error; @@ -45,7 +46,8 @@ pub struct Relay { pub uuid: Uuid, - pub password: String, + #[serde(deserialize_with = "deserialize_password")] + pub password: Arc<[u8]>, pub ip: Option, @@ -64,8 +66,11 @@ pub struct Relay { )] pub congestion_control: CongestionControl, - #[serde(default = "default::relay::alpn")] - pub alpn: Vec, + #[serde( + default = "default::relay::alpn", + deserialize_with = "deserialize_alpn" + )] + pub alpn: Vec>, #[serde(default = "default::relay::zero_rtt_handshake")] pub zero_rtt_handshake: bool, @@ -112,9 +117,11 @@ pub struct Relay { pub struct Local { pub server: SocketAddr, - pub username: Option, + #[serde(deserialize_with = "deserialize_optional_bytes")] + pub username: Option>, - pub password: Option, + #[serde(deserialize_with = "deserialize_optional_bytes")] + pub password: Option>, pub dual_stack: Option, @@ -172,7 +179,7 @@ mod default { CongestionControl::Cubic } - pub fn alpn() -> Vec { + pub fn alpn() -> Vec> { Vec::new() } @@ -250,6 +257,30 @@ where } } +pub fn deserialize_password<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + Ok(Arc::from(s.into_bytes().into_boxed_slice())) +} + +pub fn deserialize_alpn<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let s = Vec::::deserialize(deserializer)?; + Ok(s.into_iter().map(|alpn| alpn.into_bytes()).collect()) +} + +pub fn deserialize_optional_bytes<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let s = Option::::deserialize(deserializer)?; + Ok(s.map(|s| s.into_bytes())) +} + pub fn deserialize_duration<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, diff --git a/tuic-client/src/connection/mod.rs b/tuic-client/src/connection/mod.rs index f13d84d..ffc2ef0 100644 --- a/tuic-client/src/connection/mod.rs +++ b/tuic-client/src/connection/mod.rs @@ -60,7 +60,7 @@ impl Connection { .with_root_certificates(certs) .with_no_client_auth(); - crypto.alpn_protocols = cfg.alpn.into_iter().map(|alpn| alpn.into_bytes()).collect(); + crypto.alpn_protocols = cfg.alpn; crypto.enable_early_data = true; crypto.enable_sni = !cfg.disable_sni; @@ -108,7 +108,7 @@ impl Connection { ep, server: ServerAddr::new(cfg.server.0, cfg.server.1, cfg.ip), uuid: cfg.uuid, - password: Arc::from(cfg.password.into_bytes().into_boxed_slice()), + password: cfg.password, udp_relay_mode: cfg.udp_relay_mode, zero_rtt_handshake: cfg.zero_rtt_handshake, heartbeat: cfg.heartbeat, diff --git a/tuic-client/src/socks5/mod.rs b/tuic-client/src/socks5/mod.rs index b62bdc5..f3d72eb 100644 --- a/tuic-client/src/socks5/mod.rs +++ b/tuic-client/src/socks5/mod.rs @@ -37,8 +37,8 @@ impl Server { cfg.server, cfg.dual_stack, cfg.max_packet_size, - cfg.username.map(|s| s.into_bytes()), - cfg.password.map(|s| s.into_bytes()), + cfg.username, + cfg.password, )?) .map_err(|_| "failed initializing socks5 server") .unwrap(); diff --git a/tuic-server/src/config.rs b/tuic-server/src/config.rs index f10f1a7..04ebc27 100644 --- a/tuic-server/src/config.rs +++ b/tuic-server/src/config.rs @@ -26,7 +26,7 @@ pub struct Config { pub server: SocketAddr, #[serde(deserialize_with = "deserialize_users")] - pub users: HashMap, + pub users: HashMap>, pub certificate: PathBuf, @@ -38,8 +38,8 @@ pub struct Config { )] pub congestion_control: CongestionControl, - #[serde(default = "default::alpn")] - pub alpn: Vec, + #[serde(default = "default::alpn", deserialize_with = "deserialize_alpn")] + pub alpn: Vec>, #[serde(default = "default::udp_relay_ipv6")] pub udp_relay_ipv6: bool, @@ -132,7 +132,7 @@ mod default { CongestionControl::Cubic } - pub fn alpn() -> Vec { + pub fn alpn() -> Vec> { Vec::new() } @@ -191,17 +191,28 @@ where T::from_str(&s).map_err(DeError::custom) } -pub fn deserialize_users<'de, D>(deserializer: D) -> Result, D::Error> +pub fn deserialize_users<'de, D>(deserializer: D) -> Result>, D::Error> where D: Deserializer<'de>, { - let map = HashMap::::deserialize(deserializer)?; + let users = HashMap::::deserialize(deserializer)?; - if map.is_empty() { + if users.is_empty() { return Err(DeError::custom("users cannot be empty")); } - Ok(map) + Ok(users + .into_iter() + .map(|(k, v)| (k, v.into_bytes().into_boxed_slice())) + .collect()) +} + +pub fn deserialize_alpn<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let s = Vec::::deserialize(deserializer)?; + Ok(s.into_iter().map(|alpn| alpn.into_bytes()).collect()) } pub fn deserialize_duration<'de, D>(deserializer: D) -> Result diff --git a/tuic-server/src/connection/mod.rs b/tuic-server/src/connection/mod.rs index 4f1b20e..f27d19b 100644 --- a/tuic-server/src/connection/mod.rs +++ b/tuic-server/src/connection/mod.rs @@ -25,7 +25,7 @@ pub const DEFAULT_CONCURRENT_STREAMS: u32 = 32; pub struct Connection { inner: QuinnConnection, model: Model, - users: Arc>>, + users: Arc>>, udp_relay_ipv6: bool, auth: Authenticated, task_negotiation_timeout: Duration, @@ -42,7 +42,7 @@ pub struct Connection { impl Connection { pub async fn handle( conn: Connecting, - users: Arc>>, + users: Arc>>, udp_relay_ipv6: bool, zero_rtt_handshake: bool, auth_timeout: Duration, @@ -135,7 +135,7 @@ impl Connection { fn new( conn: QuinnConnection, - users: Arc>>, + users: Arc>>, udp_relay_ipv6: bool, task_negotiation_timeout: Duration, max_external_pkt_size: usize, diff --git a/tuic-server/src/server.rs b/tuic-server/src/server.rs index 7bdd38d..efe5505 100644 --- a/tuic-server/src/server.rs +++ b/tuic-server/src/server.rs @@ -20,7 +20,7 @@ use uuid::Uuid; pub struct Server { ep: Endpoint, - users: Arc>>, + users: Arc>>, udp_relay_ipv6: bool, zero_rtt_handshake: bool, auth_timeout: Duration, @@ -43,7 +43,7 @@ impl Server { .with_no_client_auth() .with_single_cert(certs, priv_key)?; - crypto.alpn_protocols = cfg.alpn.into_iter().map(|alpn| alpn.into_bytes()).collect(); + crypto.alpn_protocols = cfg.alpn; crypto.max_early_data_size = u32::MAX; crypto.send_half_rtt_data = cfg.zero_rtt_handshake; @@ -102,15 +102,9 @@ impl Server { Arc::new(TokioRuntime), )?; - let users = cfg - .users - .into_iter() - .map(|(uuid, password)| (uuid, password.into_bytes())) - .collect(); - Ok(Self { ep, - users: Arc::new(users), + users: Arc::new(cfg.users), udp_relay_ipv6: cfg.udp_relay_ipv6, zero_rtt_handshake: cfg.zero_rtt_handshake, auth_timeout: cfg.auth_timeout,