Skip to content

Commit 212e13a

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat-multipath
2 parents 4ddc94f + 238925a commit 212e13a

27 files changed

+2008
-1110
lines changed

CHANGELOG.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,44 @@
22

33
All notable changes to iroh will be documented in this file.
44

5-
## [0.94.0](https://github.com/n0-computer/iroh/compare/v0.93.2..0.94.0) - 2025-10-21
5+
## [0.95.0](https://github.com/n0-computer/iroh/compare/v0.94.1..0.95.0) - 2025-11-04
6+
7+
### ⛰️ Features
8+
9+
- *(iroh-relay)* Allow for extension of `RelayMap`s ([#3575](https://github.com/n0-computer/iroh/issues/3575)) - ([45e1f48](https://github.com/n0-computer/iroh/commit/45e1f4895f2cc4bb74ebd442f153f5f6c03058bb))
10+
- Add new NA west default relay ([#3599](https://github.com/n0-computer/iroh/issues/3599)) - ([828789a](https://github.com/n0-computer/iroh/commit/828789af1f538781eebb8c40805043d1e70f75ea))
11+
- Make `Connection::remote_id` and `Connection::alpn` infallible ([#3556](https://github.com/n0-computer/iroh/issues/3556)) - ([e2dc591](https://github.com/n0-computer/iroh/commit/e2dc59107e350d07b86b77ae678d2a76edb6f6b7))
12+
13+
### 🐛 Bug Fixes
14+
15+
- Remove "https" from NA west url ([#3600](https://github.com/n0-computer/iroh/issues/3600)) - ([c2bdbe2](https://github.com/n0-computer/iroh/commit/c2bdbe25f85dfb1180bc842996c3934519deaa62))
16+
- Stop relay actor on endpoint close ([#3601](https://github.com/n0-computer/iroh/issues/3601)) - ([30c23e8](https://github.com/n0-computer/iroh/commit/30c23e8dbaa02d17ab57ba41f0aa5271b0a411dc))
17+
18+
### 🚜 Refactor
19+
20+
- [**breaking**] Convert from snafu to n0-error ([#3561](https://github.com/n0-computer/iroh/issues/3561)) - ([7b9c95b](https://github.com/n0-computer/iroh/commit/7b9c95b7a12415ded937a62858c72337d3e731a9))
21+
22+
### 📚 Documentation
23+
24+
- *(iroh)* Fix documentation on endpoint::Builder::empty ([#3592](https://github.com/n0-computer/iroh/issues/3592)) - ([71d5136](https://github.com/n0-computer/iroh/commit/71d5136962b6fb7b56c2ddb7789dfe9edaab7414))
25+
- *(iroh)* Clarify ProtocolHandler::accept ([#3567](https://github.com/n0-computer/iroh/issues/3567)) - ([406bfde](https://github.com/n0-computer/iroh/commit/406bfde94c00f45037a9a98c808629ecb35e8b11))
26+
27+
### ⚙️ Miscellaneous Tasks
28+
29+
- *(iroh)* Update wasm-bindgen version to fix CI ([#3589](https://github.com/n0-computer/iroh/issues/3589)) - ([0f4c15c](https://github.com/n0-computer/iroh/commit/0f4c15cbcad1fac13b3b60aba825d975a8843e46))
30+
- [**breaking**] Update redb to version 3 ([#3562](https://github.com/n0-computer/iroh/issues/3562)) - ([b057b91](https://github.com/n0-computer/iroh/commit/b057b91b26162b6e6aadac48eb82e6567acf7ef3))
31+
32+
## [0.94.1](https://github.com/n0-computer/iroh/compare/v0.94.0..v0.94.1) - 2025-10-22
33+
34+
### 🐛 Bug Fixes
35+
36+
- *(iroh-base)* Add serde support for Signature ([#3568](https://github.com/n0-computer/iroh/issues/3568)) - ([ad23e1a](https://github.com/n0-computer/iroh/commit/ad23e1aa6b0c5e92b5a6e66f3e26c3dd0946379e))
37+
38+
### ⚙️ Miscellaneous Tasks
39+
40+
- Release - ([edd4fc7](https://github.com/n0-computer/iroh/commit/edd4fc749921d979170c236f668fe93d9d844fd9))
41+
42+
## [0.94.0](https://github.com/n0-computer/iroh/compare/v0.93.2..v0.94.0) - 2025-10-21
643

744
### ⛰️ Features
845

@@ -39,6 +76,7 @@ All notable changes to iroh will be documented in this file.
3976
- *(dpes)* Bump iroh-relay deps ([#3547](https://github.com/n0-computer/iroh/issues/3547)) - ([4ed700e](https://github.com/n0-computer/iroh/commit/4ed700e8da8daf6bb3d897ceadea52a4dad6952c))
4077
- Update copyright dates ([#3543](https://github.com/n0-computer/iroh/issues/3543)) - ([5eaf52a](https://github.com/n0-computer/iroh/commit/5eaf52adc4097894dc3f6f08c23cfcdfef024fab))
4178
- Update deps & remove unused deps ([#3564](https://github.com/n0-computer/iroh/issues/3564)) - ([a63bcfd](https://github.com/n0-computer/iroh/commit/a63bcfdfe588fb9a9682a26a2f4c5e2ae2ce8a97))
79+
- Release - ([dd99737](https://github.com/n0-computer/iroh/commit/dd99737c12c553ece2607e5e74d605751a637397))
4280

4381
## [0.93.2](https://github.com/n0-computer/iroh/compare/v0.93.1..v0.93.2) - 2025-10-13
4482

Cargo.lock

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

iroh-base/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "iroh-base"
3-
version = "0.94.1"
3+
version = "0.95.0"
44
edition = "2024"
55
readme = "README.md"
66
description = "base type and utilities for Iroh"

iroh-dns-server/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "iroh-dns-server"
3-
version = "0.94.0"
3+
version = "0.95.0"
44
edition = "2024"
55
description = "A pkarr relay and DNS server"
66
license = "MIT OR Apache-2.0"

iroh-relay/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "iroh-relay"
3-
version = "0.94.0"
3+
version = "0.95.0"
44
edition = "2024"
55
readme = "README.md"
66
description = "Iroh's relay server and client"
@@ -31,7 +31,7 @@ http = "1"
3131
http-body-util = "0.1.0"
3232
hyper = { version = "1", features = ["server", "client", "http1"] }
3333
hyper-util = "0.1.1"
34-
iroh-base = { version = "0.94.1", path = "../iroh-base", default-features = false, features = ["key", "relay"] }
34+
iroh-base = { version = "0.95.0", path = "../iroh-base", default-features = false, features = ["key", "relay"] }
3535
iroh-metrics = { version = "0.37", default-features = false }
3636
n0-future = "0.3.0"
3737
num_enum = "0.7"

iroh/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "iroh"
3-
version = "0.94.0"
3+
version = "0.95.0"
44
edition = "2024"
55
readme = "README.md"
66
description = "p2p quic connections dialed by public key"
@@ -36,8 +36,8 @@ derive_more = { version = "2.0.1", features = [
3636
] }
3737
ed25519-dalek = { version = "3.0.0-pre.1", features = ["serde", "rand_core", "zeroize", "pkcs8", "pem"] }
3838
http = "1"
39-
iroh-base = { version = "0.94.1", default-features = false, features = ["key", "relay"], path = "../iroh-base" }
40-
iroh-relay = { version = "0.94", path = "../iroh-relay", default-features = false }
39+
iroh-base = { version = "0.95.0", default-features = false, features = ["key", "relay"], path = "../iroh-base" }
40+
iroh-relay = { version = "0.95", path = "../iroh-relay", default-features = false }
4141
n0-future = "0.3.0"
4242
n0-error = "0.1.0"
4343
n0-watcher = "0.5"
@@ -142,7 +142,7 @@ tracing-subscriber = { version = "0.3", features = [
142142
] }
143143
indicatif = { version = "0.18", features = ["tokio"] }
144144
parse-size = { version = "1.1.0", features = ['std'] }
145-
iroh-base = { version = "0.94.1", default-features = false, features = ["key", "relay"], path = "../iroh-base" }
145+
iroh-base = { version = "0.95.0", default-features = false, features = ["key", "relay"], path = "../iroh-base" }
146146

147147
# wasm-in-browser test/dev dependencies
148148
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dev-dependencies]

iroh/bench/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "iroh-bench"
3-
version = "0.94.0"
3+
version = "0.95.0"
44
edition = "2024"
55
license = "MIT OR Apache-2.0"
66
publish = false

iroh/bench/src/iroh.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,16 +249,16 @@ pub async fn server(endpoint: Endpoint, opt: Opt) -> Result<()> {
249249
// Handle only the expected amount of clients
250250
for _ in 0..opt.clients {
251251
let incoming = endpoint.accept().await.unwrap();
252-
let connecting = match incoming.accept() {
253-
Ok(connecting) => connecting,
252+
let accepting = match incoming.accept() {
253+
Ok(accepting) => accepting,
254254
Err(err) => {
255255
warn!("incoming connection failed: {err:#}");
256256
// we can carry on in these cases:
257257
// this can be caused by retransmitted datagrams
258258
continue;
259259
}
260260
};
261-
let connection = connecting.await.std_context("handshake failed")?;
261+
let connection = accepting.await.context("handshake failed")?;
262262

263263
server_tasks.push(tokio::spawn(async move {
264264
loop {

iroh/bench/src/quinn.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,16 @@ pub async fn server(endpoint: Endpoint, opt: Opt) -> Result<()> {
220220
// Handle only the expected amount of clients
221221
for _ in 0..opt.clients {
222222
let incoming = endpoint.accept().await.unwrap();
223-
let connecting = match incoming.accept() {
224-
Ok(connecting) => connecting,
223+
let accepting = match incoming.accept() {
224+
Ok(accepting) => accepting,
225225
Err(err) => {
226226
warn!("incoming connection failed: {err:#}");
227227
// we can carry on in these cases:
228228
// this can be caused by retransmitted datagrams
229229
continue;
230230
}
231231
};
232-
let connection = connecting.await.std_context("handshake failed")?;
232+
let connection = accepting.await.std_context("handshake failed")?;
233233

234234
server_tasks.push(tokio::spawn(async move {
235235
loop {

iroh/examples/0rtt.rs

Lines changed: 59 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
use std::{env, future::Future, str::FromStr, time::Instant};
1+
use std::{env, str::FromStr, time::Instant};
22

33
use clap::Parser;
44
use data_encoding::HEXLOWER;
5-
use iroh::{
6-
EndpointId, SecretKey,
7-
endpoint::{Connecting, Connection},
8-
};
9-
use n0_error::{Result, StackResultExt, StdResultExt, bail_any};
10-
use n0_future::{StreamExt, future};
11-
use n0_watcher::Watcher;
5+
use iroh::{EndpointId, SecretKey, discovery::Discovery, endpoint::ZeroRttStatus};
6+
use n0_error::{Result, StackResultExt, StdResultExt};
7+
use n0_future::StreamExt;
8+
use quinn::{RecvStream, SendStream};
129
use tracing::{info, trace};
1310

1411
const PINGPONG_ALPN: &[u8] = b"0rtt-pingpong";
@@ -44,59 +41,39 @@ pub fn get_or_generate_secret_key() -> Result<SecretKey> {
4441
}
4542

4643
/// Do a simple ping-pong with the given connection.
47-
///
48-
/// We send the data on the connection. If `proceed` resolves to true,
49-
/// read the response immediately. Otherwise, the stream pair is bad and we need
50-
/// to open a new stream pair.
51-
async fn pingpong(
52-
connection: &Connection,
53-
proceed: impl Future<Output = bool>,
54-
x: u64,
55-
) -> Result<()> {
56-
let (mut send, recv) = connection.open_bi().await.anyerr()?;
44+
async fn pingpong(send: SendStream, recv: RecvStream, x: u64) -> Result<()> {
45+
ping(send, x).await?;
46+
pong(recv, x).await
47+
}
48+
49+
async fn ping(mut send: SendStream, x: u64) -> Result<()> {
5750
let data = x.to_be_bytes();
5851
send.write_all(&data).await.anyerr()?;
59-
send.finish().anyerr()?;
60-
let mut recv = if proceed.await {
61-
// use recv directly if we can proceed
62-
recv
63-
} else {
64-
// proceed returned false, so we have learned that the 0-RTT send was rejected.
65-
// at this point we have a fully handshaked connection, so we try again.
66-
let (mut send, recv) = connection.open_bi().await.anyerr()?;
67-
send.write_all(&data).await.anyerr()?;
68-
send.finish().anyerr()?;
69-
recv
70-
};
52+
send.finish().anyerr()
53+
}
54+
55+
async fn pong(mut recv: RecvStream, x: u64) -> Result<()> {
56+
let data = x.to_be_bytes();
7157
let echo = recv.read_to_end(8).await.anyerr()?;
7258
assert!(echo == data);
7359
Ok(())
7460
}
7561

76-
async fn pingpong_0rtt(connecting: Connecting, i: u64) -> Result<Connection> {
77-
let connection = match connecting.into_0rtt() {
78-
Ok((connection, accepted)) => {
79-
trace!("0-RTT possible from our side");
80-
pingpong(&connection, accepted, i).await?;
81-
connection
82-
}
83-
Err(connecting) => {
84-
trace!("0-RTT not possible from our side");
85-
let connection = connecting.await.anyerr()?;
86-
pingpong(&connection, future::ready(true), i).await?;
87-
connection
88-
}
89-
};
90-
Ok(connection)
91-
}
92-
9362
async fn connect(args: Args) -> Result<()> {
94-
let remote_id = args.endpoint_id.context("Missing endpoint id")?;
63+
let remote_id = args.endpoint_id.unwrap();
9564
let endpoint = iroh::Endpoint::builder()
9665
.relay_mode(iroh::RelayMode::Disabled)
9766
.keylog(true)
9867
.bind()
9968
.await?;
69+
// ensure we have resolved the remote_id before connecting
70+
// so we get a more accurate connection timing
71+
let mut discovery_stream = endpoint
72+
.discovery()
73+
.resolve(remote_id)
74+
.expect("discovery to be enabled");
75+
let _ = discovery_stream.next().await;
76+
10077
let t0 = Instant::now();
10178
for i in 0..args.rounds {
10279
let t0 = Instant::now();
@@ -106,18 +83,40 @@ async fn connect(args: Args) -> Result<()> {
10683
let connection = if args.disable_0rtt {
10784
let connection = connecting.await.anyerr()?;
10885
trace!("connecting without 0-RTT");
109-
pingpong(&connection, future::ready(true), i).await?;
86+
let (send, recv) = connection.open_bi().await.anyerr()?;
87+
pingpong(send, recv, i).await?;
11088
connection
11189
} else {
112-
pingpong_0rtt(connecting, i).await?
90+
match connecting.into_0rtt() {
91+
Ok(zrtt_connection) => {
92+
trace!("0-RTT possible from our side");
93+
let (send, recv) = zrtt_connection.open_bi().await.anyerr()?;
94+
// before we get the full handshake, attempt to send 0-RTT data
95+
let zrtt_task = tokio::spawn(ping(send, i));
96+
match zrtt_connection.handshake_completed().await? {
97+
ZeroRttStatus::Accepted(conn) => {
98+
let _ = zrtt_task.await.anyerr()?;
99+
pong(recv, i).await?;
100+
conn
101+
}
102+
ZeroRttStatus::Rejected(conn) => {
103+
zrtt_task.abort();
104+
let (send, recv) = conn.open_bi().await.anyerr()?;
105+
pingpong(send, recv, i).await?;
106+
conn
107+
}
108+
}
109+
}
110+
Err(connecting) => {
111+
trace!("0-RTT not possible from our side");
112+
let conn = connecting.await.anyerr()?;
113+
let (send, recv) = conn.open_bi().await.anyerr()?;
114+
pingpong(send, recv, i).await?;
115+
conn
116+
}
117+
}
113118
};
114-
tokio::spawn(async move {
115-
// wait for some time for the handshake to complete and the server
116-
// to send a NewSessionTicket. This is less than ideal, but we
117-
// don't have a better way to wait for the handshake to complete.
118-
tokio::time::sleep(connection.rtt() * 2).await;
119-
connection.close(0u8.into(), b"");
120-
});
119+
connection.close(0u8.into(), b"");
121120
let elapsed = t0.elapsed();
122121
println!("round {i}: {} us", elapsed.as_micros());
123122
}
@@ -138,24 +137,13 @@ async fn accept(_args: Args) -> Result<()> {
138137
.relay_mode(iroh::RelayMode::Disabled)
139138
.bind()
140139
.await?;
141-
let mut addrs = endpoint.watch_addr().stream();
142-
let addr = loop {
143-
let Some(addr) = addrs.next().await else {
144-
bail_any!("Address stream closed");
145-
};
146-
if !addr.ip_addrs().count() == 0 {
147-
break addr;
148-
}
149-
};
150-
println!("Listening on: {addr:?}");
140+
println!("endpoint id: {}", endpoint.id());
151141

152142
let accept = async move {
153143
while let Some(incoming) = endpoint.accept().await {
154144
tokio::spawn(async move {
155-
let connecting = incoming.accept().anyerr()?;
156-
let (connection, _zero_rtt_accepted) = connecting
157-
.into_0rtt()
158-
.expect("accept into 0.5 RTT always succeeds");
145+
let accepting = incoming.accept().anyerr()?;
146+
let connection = accepting.into_0rtt();
159147
let (mut send, mut recv) = connection.accept_bi().await.anyerr()?;
160148
trace!("recv.is_0rtt: {}", recv.is_0rtt());
161149
let data = recv.read_to_end(8).await.anyerr()?;

0 commit comments

Comments
 (0)