Skip to content

Commit 8a24a95

Browse files
authored
feat(iroh,iroh-relay): Enable proxying and test-utils support for websockets, allow configuring websockets in endpoint::Builder (#3217)
## Description - Make connecting to relays via websockets the default code path - Enable using HTTPS proxies when dialing a relay with websockets - Abstract away the proxied TLS stream establishment in `MaybeTlsStreamBuilder` (rename `connect_relay.rs` to `tls.rs`) - Enable reusing `MaybeTlsStream` by making it generic over the plain stream (can be either `TcpStream` or `ProxyStream` now) - Switch from `tokio-tungstenite` to `tokio-websockets` (has `bytes::Bytes` support, great maintenance & performance) - Switch from `tokio-tungstenite-wasm` to `ws_stream_wasm` (no need to pay for tungstenite dependency) - Added `iroh::endpoint::Builder::relay_conn_protocol` that allows setting the relay protocol to websockets - Re-exporting `iroh_relay::http::Protocol` as `iroh::RelayProtocol` ## Breaking Changes - iroh-relay: Minor change in the `From` impls for `ConnSendError` due to changing the underlying library ## Notes & open questions We're not switching the default to websockets yet, the reason being we want to use the opportunity of that switch to update to a new relay protocol. ## Change checklist - [x] Self-review. - [x] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [x] All breaking changes documented. - [x] List all breaking changes in the above "Breaking Changes" section.
1 parent b43e013 commit 8a24a95

File tree

16 files changed

+589
-237
lines changed

16 files changed

+589
-237
lines changed

Cargo.lock

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

deny.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ allow = [
1414
"Zlib",
1515
"MPL-2.0", # https://fossa.com/blog/open-source-software-licenses-101-mozilla-public-license-2-0/
1616
"Unicode-3.0",
17+
"Unlicense", # https://unlicense.org/
1718
]
1819

1920

iroh-relay/Cargo.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ tokio-rustls = { version = "0.26", default-features = false, features = [
6464
"logging",
6565
"ring",
6666
] }
67-
tokio-tungstenite-wasm = "0.4"
67+
sha1 = "0.10.6"
6868
tokio-util = { version = "0.7", features = ["io-util", "io", "codec", "rt"] }
6969
tracing = "0.1"
7070
url = { version = "2.5", features = ["serde"] }
@@ -87,7 +87,7 @@ rustls-cert-file-reader = { version = "0.4.1", optional = true }
8787
rustls-pemfile = { version = "2.1", optional = true }
8888
time = { version = "0.3.37", optional = true }
8989
tokio-rustls-acme = { version = "0.6", optional = true }
90-
tokio-tungstenite = { version = "0.24", default-features = false, optional = true } # keep version in sync with what tokio-tungstenite-wasm depends on
90+
tokio-websockets = { version = "0.11.3", features = ["rustls-bring-your-own-connector", "ring", "getrandom", "rand", "server"], optional = true } # server-side websocket implementation
9191
toml = { version = "0.8", optional = true }
9292
tracing-subscriber = { version = "0.3", features = [
9393
"env-filter",
@@ -107,6 +107,11 @@ tokio = { version = "1", features = [
107107
"signal",
108108
"process",
109109
] }
110+
tokio-websockets = { version = "0.11.3", features = ["rustls-bring-your-own-connector", "ring", "getrandom", "rand", "client"] }
111+
112+
# wasm-in-browser dependencies
113+
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
114+
ws_stream_wasm = { version = "0.7.4", default-features = false }
110115

111116
[dev-dependencies]
112117
clap = { version = "4", features = ["derive"] }
@@ -146,7 +151,7 @@ server = [
146151
"dep:rustls-pemfile",
147152
"dep:time",
148153
"dep:tokio-rustls-acme",
149-
"dep:tokio-tungstenite",
154+
"dep:tokio-websockets",
150155
"dep:toml",
151156
"dep:tracing-subscriber",
152157
"quinn/log",

iroh-relay/src/client.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ use crate::{
3131

3232
pub(crate) mod conn;
3333
#[cfg(not(wasm_browser))]
34-
mod connect_relay;
35-
#[cfg(not(wasm_browser))]
3634
pub(crate) mod streams;
3735
#[cfg(not(wasm_browser))]
36+
mod tls;
37+
#[cfg(not(wasm_browser))]
3838
mod util;
3939

4040
/// Build a Client.
@@ -140,12 +140,18 @@ impl ClientBuilder {
140140
/// Establishes a new connection to the relay server.
141141
pub async fn connect(&self) -> Result<Client> {
142142
let (conn, local_addr) = match self.protocol {
143+
#[cfg(wasm_browser)]
143144
Protocol::Websocket => {
144145
let conn = self.connect_ws().await?;
145146
let local_addr = None;
146147
(conn, local_addr)
147148
}
148149
#[cfg(not(wasm_browser))]
150+
Protocol::Websocket => {
151+
let (conn, local_addr) = self.connect_ws().await?;
152+
(conn, Some(local_addr))
153+
}
154+
#[cfg(not(wasm_browser))]
149155
Protocol::Relay => {
150156
let (conn, local_addr) = self.connect_relay().await?;
151157
(conn, Some(local_addr))
@@ -167,31 +173,27 @@ impl ClientBuilder {
167173
Ok(Client { conn, local_addr })
168174
}
169175

176+
#[cfg(wasm_browser)]
170177
async fn connect_ws(&self) -> Result<Conn> {
171178
let mut dial_url = (*self.url).clone();
172179
dial_url.set_path(RELAY_PATH);
173180
// The relay URL is exchanged with the http(s) scheme in tickets and similar.
174181
// We need to use the ws:// or wss:// schemes when connecting with websockets, though.
175182
dial_url
176-
.set_scheme(if self.use_tls() { "wss" } else { "ws" })
183+
.set_scheme(match self.url.scheme() {
184+
"http" => "ws",
185+
"ws" => "ws",
186+
_ => "wss",
187+
})
177188
.map_err(|()| anyhow!("Invalid URL"))?;
178189

179190
debug!(%dial_url, "Dialing relay by websocket");
180191

181-
let conn = tokio_tungstenite_wasm::connect(dial_url).await?;
182-
let conn = Conn::new_ws(conn, self.key_cache.clone(), &self.secret_key).await?;
192+
let (_, ws_stream) = ws_stream_wasm::WsMeta::connect(dial_url.as_str(), None).await?;
193+
let conn =
194+
Conn::new_ws_browser(ws_stream, self.key_cache.clone(), &self.secret_key).await?;
183195
Ok(conn)
184196
}
185-
186-
fn use_tls(&self) -> bool {
187-
// only disable tls if we are explicitly dialing a http url
188-
#[allow(clippy::match_like_matches_macro)]
189-
match self.url.scheme() {
190-
"http" => false,
191-
"ws" => false,
192-
_ => true,
193-
}
194-
}
195197
}
196198

197199
/// A relay client.

0 commit comments

Comments
 (0)