Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down Expand Up @@ -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" }
Comment on lines +52 to +54

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reqwest has indirect dependencies on hyper-util and relies on the types matching so it needs the patch on itself and every consumer. hyper-util PR is submitted.

11 changes: 10 additions & 1 deletion examples/api_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?;
Expand Down
11 changes: 10 additions & 1 deletion examples/block_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
25 changes: 23 additions & 2 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::net::IpAddr>,
#[cfg(target_os = "linux")] so_mark: Option<u32>,
resolver: Option<Arc<dyn Resolve>>,
) -> anyhow::Result<Self> {
let mut base_url = base_url.to_string();
Expand All @@ -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,
Expand All @@ -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<std::net::IpAddr>,
#[cfg(target_os = "linux")] so_mark: Option<u32>,
resolver: Option<Arc<dyn Resolve>>,
) -> anyhow::Result<reqwest::Client> {
let builder = ClientBuilder::new()
Expand All @@ -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")
}

Expand Down