2 Commits
Author SHA1 Message Date
Bendik Aagaard LynghaugandClaude Fable 5.1 520580e0e6 release v0.1.10
ci / quality (push) Failing after 10s
release / build (aarch64-unknown-linux-gnu) (push) Successful in 2m29s
release / build (x86_64-unknown-linux-gnu) (push) Successful in 2m11s
release / publish (push) Successful in 47s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 14:10:16 +02:00
Bendik Aagaard LynghaugandClaude Fable 5.1 7322812524 status shows each home relay: connected, down with the error, or denied
iroh 1.3's home_relay_status, on GlobalStatus as relays (absent when
empty, so older clients parse it). The thing we lacked when fetches
timed out: whether this daemon can be reached through a relay at all.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 14:08:41 +02:00
6 changed files with 61 additions and 5 deletions
Generated
+3 -3
View File
@@ -4305,7 +4305,7 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]] [[package]]
name = "varde-ctl" name = "varde-ctl"
version = "0.1.9" version = "0.1.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@@ -4318,7 +4318,7 @@ dependencies = [
[[package]] [[package]]
name = "varde-daemon" name = "varde-daemon"
version = "0.1.9" version = "0.1.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64", "base64",
@@ -4344,7 +4344,7 @@ dependencies = [
[[package]] [[package]]
name = "varde-proto" name = "varde-proto"
version = "0.1.9" version = "0.1.10"
dependencies = [ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
+1 -1
View File
@@ -3,7 +3,7 @@ resolver = "2"
members = ["varde-proto", "varde-daemon", "varde-ctl"] members = ["varde-proto", "varde-daemon", "varde-ctl"]
[workspace.package] [workspace.package]
version = "0.1.9" version = "0.1.10"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
repository = "https://project.uhhm.no/uhhm/varde" repository = "https://project.uhhm.no/uhhm/varde"
+9
View File
@@ -272,6 +272,15 @@ fn print_human(data: Option<&ResponseData>) {
println!("store: {}", s.store_path); println!("store: {}", s.store_path);
println!("pins: {}", s.pins); println!("pins: {}", s.pins);
println!("peers: {} connected", s.connected_peers); println!("peers: {} connected", s.connected_peers);
for r in &s.relays {
let how = match (&r.auth_denied, &r.last_error, r.connected) {
(Some(reason), _, _) => format!("denied: {reason}"),
(None, Some(err), false) => format!("down: {err}"),
(None, None, false) => "connecting".to_string(),
(None, _, true) => "connected".to_string(),
};
println!("relay: {} {how}", r.url);
}
} }
ResponseData::HashStatus(h) => { ResponseData::HashStatus(h) => {
println!("hash: {}", h.hash); println!("hash: {}", h.hash);
+1
View File
@@ -486,6 +486,7 @@ impl Daemon {
store_path: self.config.store_dir.display().to_string(), store_path: self.config.store_dir.display().to_string(),
pins: self.meta.pins().len() as u64, pins: self.meta.pins().len() as u64,
connected_peers: connected, connected_peers: connected,
relays: self.transfer.relay_status(),
})) }))
} }
Request::Status { hash: Some(hash) } => { Request::Status { hash: Some(hash) } => {
+17 -1
View File
@@ -12,7 +12,7 @@ use std::time::Duration;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use iroh::address_lookup::memory::MemoryLookup; use iroh::address_lookup::memory::MemoryLookup;
use iroh::protocol::Router; use iroh::protocol::Router;
use iroh::{Endpoint, EndpointAddr, EndpointId, RelayMode, SecretKey}; use iroh::{Endpoint, EndpointAddr, EndpointId, RelayMode, SecretKey, Watcher as _};
use iroh_blobs::api::downloader::{DownloadOptions, Downloader, Shuffled, SplitStrategy}; use iroh_blobs::api::downloader::{DownloadOptions, Downloader, Shuffled, SplitStrategy};
use iroh_blobs::protocol::GetRequest; use iroh_blobs::protocol::GetRequest;
use iroh_blobs::{BlobFormat, BlobsProtocol, Hash, HashAndFormat}; use iroh_blobs::{BlobFormat, BlobsProtocol, Hash, HashAndFormat};
@@ -156,6 +156,22 @@ impl Transfer {
self.endpoint.id().to_string() self.endpoint.id().to_string()
} }
/// How each home relay is doing right now: connected, or why not.
/// Empty with relays disabled.
pub fn relay_status(&self) -> Vec<varde_proto::RelayInfo> {
self.endpoint
.home_relay_status()
.get()
.iter()
.map(|r| varde_proto::RelayInfo {
url: r.url().to_string(),
connected: r.is_connected(),
last_error: r.last_error().map(|e| format!("{e:#}")),
auth_denied: r.auth_denied_reason().map(str::to_string),
})
.collect()
}
/// The endpoint's identity key (also signs our announcements). /// The endpoint's identity key (also signs our announcements).
pub fn secret_key(&self) -> SecretKey { pub fn secret_key(&self) -> SecretKey {
self.endpoint.secret_key().clone() self.endpoint.secret_key().clone()
+30
View File
@@ -324,6 +324,27 @@ pub struct GlobalStatus {
pub pins: u64, pub pins: u64,
/// Number of connected trusted peers. /// Number of connected trusted peers.
pub connected_peers: u64, pub connected_peers: u64,
/// The home relays this endpoint uses and how each is doing. Empty
/// when relays are off (LAN-only) or on a daemon before 0.1.10.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub relays: Vec<RelayInfo>,
}
/// One home relay's connection state (iroh's `home_relay_status`).
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RelayInfo {
/// The relay URL.
pub url: String,
/// Whether the endpoint holds a connection to it right now.
pub connected: bool,
/// The most recent connection error, when not connected and an
/// attempt has failed; for a person to read, not to match on.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_error: Option<String>,
/// The relay's reason when it denied this endpoint's authentication:
/// the one failure retrying will not cure.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub auth_denied: Option<String>,
} }
/// Status of one hash. /// Status of one hash.
@@ -478,4 +499,13 @@ mod tests {
_ => panic!("wrong variant"), _ => panic!("wrong variant"),
} }
} }
#[test]
fn a_status_from_before_relays_still_parses() {
let old = r#"{"version":"0.1.9","protocol":2,"store_path":"/s","pins":1,"connected_peers":0}"#;
let status: GlobalStatus = serde_json::from_str(old).unwrap();
assert!(status.relays.is_empty());
let back = serde_json::to_string(&status).unwrap();
assert!(!back.contains("relays"), "empty stays absent for old clients: {back}");
}
} }