Skip to content

Commit 0062b7f

Browse files
Add SO_MARK support on Linux
1 parent c293c2c commit 0062b7f

5 files changed

Lines changed: 68 additions & 19 deletions

File tree

Cargo.lock

Lines changed: 20 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ http = { version = "1.3.1" }
1919
ipnetwork = { version = "0.21.1", features = ["serde"] }
2020
itertools = "0.14.0"
2121
rand = { version = "0.8.5"}
22-
reqwest = { version = "0.13.2", default-features = false, features = ["json", "rustls", "stream"], optional = true }
22+
reqwest = { git = "https://github.com/Sovereign-Engineering/reqwest", rev = "7ba2e76a02454b0fa414e0ddbf8aa609ed05b944", default-features = false, features = ["json", "rustls", "stream"], optional = true }
2323
rustls = { version = "0.23.27", optional = true }
2424
semver = "1.0.26"
2525
serde = { version = "1.0.219", features = ["derive"] }
@@ -48,3 +48,7 @@ tracing-subscriber = "0.3.19"
4848
tokio = { version = "1.45.1", features = ["full"] }
4949
verhoeff = "1.0.0"
5050
x25519-dalek = { version = "2.0.1", features = ["static_secrets"] }
51+
52+
# Temporary SO_MARK fork. Patches do not propagate, consumers need this entry too.
53+
[patch.crates-io]
54+
hyper-util = { git = "https://github.com/Sovereign-Engineering/hyper-util", rev = "f2659bd55b85bf524abac9ab0ce4951bb67077b9" }

examples/api_cli.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,16 @@ async fn main() -> anyhow::Result<()> {
8080
let url = args.base_url;
8181
let account_id = AccountId::from_string_unchecked(args.account_no);
8282

83-
let client = Client::new(url, vec![], account_id, "example cli client", None, None)?;
83+
let client = Client::new(
84+
url,
85+
vec![],
86+
account_id,
87+
"example cli client",
88+
None,
89+
#[cfg(target_os = "linux")]
90+
None,
91+
None,
92+
)?;
8493

8594
eprintln!("Get account info");
8695
let account_info = client.run(GetAccountInfo()).await?;

examples/block_test.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,16 @@ async fn main() -> anyhow::Result<()> {
2222
let account_id = AccountId::from_string_unchecked(args.account_no);
2323
let alternative_hosts = vec![ALTERNATIVE_HOST.to_string()];
2424

25-
let client = Client::new(API_URL, alternative_hosts, account_id, "block test cli client", None, None)?;
25+
let client = Client::new(
26+
API_URL,
27+
alternative_hosts,
28+
account_id,
29+
"block test cli client",
30+
None,
31+
#[cfg(target_os = "linux")]
32+
None,
33+
None,
34+
)?;
2635
match client.acquire_auth_token().await {
2736
Ok(_) => println!("not blocked"),
2837
Err(error) => match error {

src/client.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ impl Client {
6060
user_agent: &str,
6161
#[cfg(not(any(target_os = "android", target_os = "windows")))] network_interface: Option<&str>,
6262
#[cfg(any(target_os = "android", target_os = "windows"))] network_interface: Option<std::net::IpAddr>,
63+
#[cfg(target_os = "linux")] so_mark: Option<u32>,
6364
resolver: Option<Arc<dyn Resolve>>,
6465
) -> anyhow::Result<Self> {
6566
let mut base_url = base_url.to_string();
@@ -74,9 +75,23 @@ impl Client {
7475
let server_names = once(primary_host).chain(alternative_hosts.iter().cloned());
7576

7677
let mut rustls_config = Self::rustls_config(server_names)?;
77-
let http = Self::http_client_builder(user_agent, rustls_config.clone(), network_interface, resolver.clone())?;
78+
let http = Self::http_client_builder(
79+
user_agent,
80+
rustls_config.clone(),
81+
network_interface,
82+
#[cfg(target_os = "linux")]
83+
so_mark,
84+
resolver.clone(),
85+
)?;
7886
rustls_config.enable_sni = false;
79-
let http_no_sni = Self::http_client_builder(user_agent, rustls_config, network_interface, resolver)?;
87+
let http_no_sni = Self::http_client_builder(
88+
user_agent,
89+
rustls_config,
90+
network_interface,
91+
#[cfg(target_os = "linux")]
92+
so_mark,
93+
resolver,
94+
)?;
8095

8196
Ok(Self {
8297
account_id,
@@ -94,6 +109,7 @@ impl Client {
94109
rustls_config: rustls::ClientConfig,
95110
#[cfg(not(any(target_os = "android", target_os = "windows")))] network_interface: Option<&str>,
96111
#[cfg(any(target_os = "android", target_os = "windows"))] network_interface: Option<std::net::IpAddr>,
112+
#[cfg(target_os = "linux")] so_mark: Option<u32>,
97113
resolver: Option<Arc<dyn Resolve>>,
98114
) -> anyhow::Result<reqwest::Client> {
99115
let builder = ClientBuilder::new()
@@ -112,6 +128,11 @@ impl Client {
112128
#[cfg(any(target_os = "android", target_os = "windows"))]
113129
Some(network_interface) => builder.local_address(network_interface),
114130
};
131+
#[cfg(target_os = "linux")]
132+
let builder = match so_mark {
133+
None => builder,
134+
Some(so_mark) => builder.so_mark(so_mark),
135+
};
115136
builder.build().context("failed to initialize HTTP client")
116137
}
117138

0 commit comments

Comments
 (0)