diff --git a/Cargo.lock b/Cargo.lock index bc11399..363586e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -827,9 +827,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.8.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" dependencies = [ "atomic-waker", "bytes", @@ -840,7 +840,6 @@ dependencies = [ "httparse", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -864,14 +863,12 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +version = "0.1.20" +source = "git+https://github.com/Sovereign-Engineering/hyper-util?rev=f2659bd55b85bf524abac9ab0ce4951bb67077b9#f2659bd55b85bf524abac9ab0ce4951bb67077b9" dependencies = [ "base64", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -880,7 +877,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.5", "tokio", "tower-service", "tracing", @@ -1497,7 +1494,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls", - "socket2", + "socket2 0.5.10", "thiserror 2.0.12", "tokio", "tracing", @@ -1535,7 +1532,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.5.10", "tracing", "windows-sys 0.59.0", ] @@ -1654,9 +1651,8 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +version = "0.13.4" +source = "git+https://github.com/Sovereign-Engineering/reqwest?rev=7ba2e76a02454b0fa414e0ddbf8aa609ed05b944#7ba2e76a02454b0fa414e0ddbf8aa609ed05b944" dependencies = [ "base64", "bytes", @@ -2007,6 +2003,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -2202,7 +2208,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.10", "tokio-macros", "windows-sys 0.52.0", ] diff --git a/Cargo.toml b/Cargo.toml index 2de176b..2aff01d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ http = { version = "1.3.1" } ipnetwork = { version = "0.21.1", features = ["serde"] } itertools = "0.14.0" rand = { version = "0.8.5"} -reqwest = { version = "0.13.2", default-features = false, features = ["json", "rustls", "stream"], optional = true } +reqwest = { git = "https://github.com/Sovereign-Engineering/reqwest", rev = "7ba2e76a02454b0fa414e0ddbf8aa609ed05b944", default-features = false, features = ["json", "rustls", "stream"], optional = true } rustls = { version = "0.23.27", optional = true } semver = "1.0.26" serde = { version = "1.0.219", features = ["derive"] } @@ -48,3 +48,7 @@ tracing-subscriber = "0.3.19" tokio = { version = "1.45.1", features = ["full"] } verhoeff = "1.0.0" x25519-dalek = { version = "2.0.1", features = ["static_secrets"] } + +# Temporary SO_MARK fork. Patches do not propagate, consumers need this entry too. +[patch.crates-io] +hyper-util = { git = "https://github.com/Sovereign-Engineering/hyper-util", rev = "f2659bd55b85bf524abac9ab0ce4951bb67077b9" } diff --git a/examples/api_cli.rs b/examples/api_cli.rs index 925b99c..58405ff 100644 --- a/examples/api_cli.rs +++ b/examples/api_cli.rs @@ -80,7 +80,16 @@ async fn main() -> anyhow::Result<()> { let url = args.base_url; let account_id = AccountId::from_string_unchecked(args.account_no); - let client = Client::new(url, vec![], account_id, "example cli client", None, None)?; + let client = Client::new( + url, + vec![], + account_id, + "example cli client", + None, + #[cfg(target_os = "linux")] + None, + None, + )?; eprintln!("Get account info"); let account_info = client.run(GetAccountInfo()).await?; diff --git a/examples/block_test.rs b/examples/block_test.rs index 8cd8b10..329b6da 100644 --- a/examples/block_test.rs +++ b/examples/block_test.rs @@ -22,7 +22,16 @@ async fn main() -> anyhow::Result<()> { let account_id = AccountId::from_string_unchecked(args.account_no); let alternative_hosts = vec![ALTERNATIVE_HOST.to_string()]; - let client = Client::new(API_URL, alternative_hosts, account_id, "block test cli client", None, None)?; + let client = Client::new( + API_URL, + alternative_hosts, + account_id, + "block test cli client", + None, + #[cfg(target_os = "linux")] + None, + None, + )?; match client.acquire_auth_token().await { Ok(_) => println!("not blocked"), Err(error) => match error { diff --git a/src/client.rs b/src/client.rs index 257c55c..7f339b7 100644 --- a/src/client.rs +++ b/src/client.rs @@ -60,6 +60,7 @@ impl Client { user_agent: &str, #[cfg(not(any(target_os = "android", target_os = "windows")))] network_interface: Option<&str>, #[cfg(any(target_os = "android", target_os = "windows"))] network_interface: Option, + #[cfg(target_os = "linux")] so_mark: Option, resolver: Option>, ) -> anyhow::Result { let mut base_url = base_url.to_string(); @@ -74,9 +75,23 @@ impl Client { let server_names = once(primary_host).chain(alternative_hosts.iter().cloned()); let mut rustls_config = Self::rustls_config(server_names)?; - let http = Self::http_client_builder(user_agent, rustls_config.clone(), network_interface, resolver.clone())?; + let http = Self::http_client_builder( + user_agent, + rustls_config.clone(), + network_interface, + #[cfg(target_os = "linux")] + so_mark, + resolver.clone(), + )?; rustls_config.enable_sni = false; - let http_no_sni = Self::http_client_builder(user_agent, rustls_config, network_interface, resolver)?; + let http_no_sni = Self::http_client_builder( + user_agent, + rustls_config, + network_interface, + #[cfg(target_os = "linux")] + so_mark, + resolver, + )?; Ok(Self { account_id, @@ -94,6 +109,7 @@ impl Client { rustls_config: rustls::ClientConfig, #[cfg(not(any(target_os = "android", target_os = "windows")))] network_interface: Option<&str>, #[cfg(any(target_os = "android", target_os = "windows"))] network_interface: Option, + #[cfg(target_os = "linux")] so_mark: Option, resolver: Option>, ) -> anyhow::Result { let builder = ClientBuilder::new() @@ -112,6 +128,11 @@ impl Client { #[cfg(any(target_os = "android", target_os = "windows"))] Some(network_interface) => builder.local_address(network_interface), }; + #[cfg(target_os = "linux")] + let builder = match so_mark { + None => builder, + Some(so_mark) => builder.so_mark(so_mark), + }; builder.build().context("failed to initialize HTTP client") }