Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ca859c691 | ||
|
|
c2b9167e1e |
Generated
+3
-3
@@ -4491,7 +4491,7 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "varde-ctl"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -4504,7 +4504,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "varde-daemon"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
@@ -4530,7 +4530,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "varde-proto"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ resolver = "2"
|
||||
members = ["varde-proto", "varde-daemon", "varde-ctl"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://project.uhhm.no/uhhm/varde"
|
||||
|
||||
@@ -335,6 +335,26 @@ impl Daemon {
|
||||
}
|
||||
}
|
||||
|
||||
/// The peer a request names: a NodeId, or a blob ticket from it (whose
|
||||
/// addresses are remembered, so dialing it needs no discovery). An app
|
||||
/// that knows peers by the tickets they hand out - redoal does - can
|
||||
/// allow and push without unpacking them.
|
||||
fn peer_of(&self, peer: &str) -> Result<iroh::EndpointId, OpError> {
|
||||
if let Ok(id) = peer.parse::<iroh::EndpointId>() {
|
||||
return Ok(id);
|
||||
}
|
||||
match crate::transfer::parse_ticket(peer) {
|
||||
Ok((_, _, addr)) => {
|
||||
let id = addr.id;
|
||||
self.transfer.remember(addr);
|
||||
Ok(id)
|
||||
}
|
||||
Err(_) => Err(OpError::InvalidArgument(format!(
|
||||
"{peer:?} is neither a node id nor a ticket"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Trusted peers seen on the LAN recently.
|
||||
fn present_trusted_peers(&self) -> Vec<PeerInfo> {
|
||||
let peers = self.lan_peers.lock().expect("lan peers lock");
|
||||
@@ -574,9 +594,7 @@ impl Daemon {
|
||||
Ok(ResponseData::Done {})
|
||||
}
|
||||
Request::PeerAllowPush { node_id, ttl_secs } => {
|
||||
let parsed: iroh::EndpointId = node_id
|
||||
.parse()
|
||||
.map_err(|e| OpError::InvalidArgument(format!("invalid node id: {e}")))?;
|
||||
let parsed = self.peer_of(&node_id)?;
|
||||
let ttl = ttl_secs.min(varde_proto::MAX_PUSH_TTL_SECS);
|
||||
self.meta
|
||||
.allow_push(&parsed.to_string(), crate::meta::unix_now() + ttl)?;
|
||||
@@ -588,9 +606,7 @@ impl Daemon {
|
||||
}),
|
||||
Request::Push { hash, node_id } => {
|
||||
let parsed = parse_hash(&hash)?;
|
||||
let peer: iroh::EndpointId = node_id
|
||||
.parse()
|
||||
.map_err(|e| OpError::InvalidArgument(format!("invalid node id: {e}")))?;
|
||||
let peer = self.peer_of(&node_id)?;
|
||||
// Consent, sending side: we only push to peers we trust or
|
||||
// hold a push allowance for. (The receiver independently
|
||||
// requires the same of us.)
|
||||
|
||||
@@ -200,11 +200,12 @@ pub fn provider_events(gate: Gate) -> EventSender {
|
||||
ProviderMessage::ObserveRequestReceived(m) => {
|
||||
// Presence is information too: gate it like data.
|
||||
// Bitfields are metadata, not payload, so trusted
|
||||
// peers may observe even while serving is off or the
|
||||
// connection is metered (push confirmation needs it).
|
||||
// peers - and peers allowed to push, whose push is
|
||||
// confirmed by observing it - may observe even while
|
||||
// serving is off or the connection is metered.
|
||||
let trusted = conns
|
||||
.get(&m.inner.connection_id)
|
||||
.map(|i| i.trusted)
|
||||
.map(|i| i.trusted || i.may_push)
|
||||
.unwrap_or(false);
|
||||
let allowed = trusted
|
||||
|| allow(&gate, &conns, m.inner.connection_id, [m.inner.request.hash]);
|
||||
|
||||
@@ -298,6 +298,15 @@ impl Transfer {
|
||||
Ok(ticket.to_string())
|
||||
}
|
||||
|
||||
/// Teach the endpoint where a peer can be reached (the addresses a
|
||||
/// ticket carries), so a push dials it directly instead of waiting on
|
||||
/// discovery.
|
||||
pub fn remember(&self, addr: EndpointAddr) {
|
||||
if !addr.addrs.is_empty() {
|
||||
self.known_addrs.add_endpoint_info(addr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Queue a background fetch of `content` from `providers`. Emits
|
||||
/// progress events and [`Event::PinComplete`] when fully verified.
|
||||
pub fn spawn_fetch(&self, content: HashAndFormat, providers: Vec<EndpointAddr>) {
|
||||
|
||||
@@ -437,7 +437,6 @@ fn push_allowance_is_enough_and_is_not_trust() {
|
||||
let mut client_a = support::Client::connect(&a.socket);
|
||||
let mut client_b = support::Client::connect(&b.socket);
|
||||
let id_a = node_id(&mut client_a);
|
||||
let id_b = node_id(&mut client_b);
|
||||
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let src = dir.path().join("voice.bin");
|
||||
@@ -446,7 +445,16 @@ fn push_allowance_is_enough_and_is_not_trust() {
|
||||
let hash = add_file(&mut client_a, &src);
|
||||
pin(&mut client_a, &hash, false);
|
||||
|
||||
assert!(client_a.request(&Request::PeerAllowPush { node_id: id_b.clone(), ttl_secs: 600 }).ok);
|
||||
// A knows B by a ticket B handed out (as redoal peers do), not by
|
||||
// its bare node id.
|
||||
let b_src = dir.path().join("b-own.bin");
|
||||
std::fs::write(&b_src, vec![1u8; 1_000]).unwrap();
|
||||
let b_hash = add_file(&mut client_b, &b_src);
|
||||
let b_ticket = match client_b.request(&Request::TicketExport { hash: b_hash }).data {
|
||||
Some(ResponseData::Ticket { ticket }) => ticket,
|
||||
other => panic!("unexpected ticket reply: {other:?}"),
|
||||
};
|
||||
assert!(client_a.request(&Request::PeerAllowPush { node_id: b_ticket.clone(), ttl_secs: 600 }).ok);
|
||||
assert!(client_b.request(&Request::PeerAllowPush { node_id: id_a, ttl_secs: 600 }).ok);
|
||||
match client_a.request(&Request::PeerList {}).data {
|
||||
Some(ResponseData::Peers { peers }) => assert!(peers.is_empty(), "an allowance is not trust: {peers:?}"),
|
||||
@@ -456,14 +464,18 @@ fn push_allowance_is_enough_and_is_not_trust() {
|
||||
// The peer's address arrives by mdns; retry until it does.
|
||||
let deadline = Instant::now() + Duration::from_secs(30);
|
||||
let reply = loop {
|
||||
let reply = client_a.request(&Request::Push { hash: hash.clone(), node_id: id_b.clone() });
|
||||
let reply = client_a.request(&Request::Push { hash: hash.clone(), node_id: b_ticket.clone() });
|
||||
if reply.ok || Instant::now() > deadline {
|
||||
break reply;
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis(500));
|
||||
};
|
||||
if !reply.ok {
|
||||
eprintln!("SKIP: push never reached the peer (multicast unavailable?): {:?}", reply.error);
|
||||
let message = reply.error.map(|e| e.message).unwrap_or_default();
|
||||
// Only an unreachable peer is the environment's fault; any other
|
||||
// refusal is a real failure.
|
||||
assert!(message.contains("connect"), "push failed: {message}");
|
||||
eprintln!("SKIP: push never reached the peer (multicast unavailable?): {message}");
|
||||
return;
|
||||
}
|
||||
assert!(wait_complete(&b.socket, &hash, Duration::from_secs(60)), "pushed content not complete on receiver");
|
||||
|
||||
@@ -127,7 +127,8 @@ pub enum Request {
|
||||
/// phones at the same place) and let it lapse. Asking again extends
|
||||
/// it; [`Request::PeerUntrust`] ends it early. Added in varde 0.1.5.
|
||||
PeerAllowPush {
|
||||
/// The peer's iroh NodeId (z-base-32).
|
||||
/// The peer's iroh NodeId (z-base-32), or a blob ticket it issued
|
||||
/// (varde 0.1.6+), whose addresses are then used to reach it.
|
||||
node_id: String,
|
||||
/// How long the allowance lasts, in seconds.
|
||||
ttl_secs: u64,
|
||||
@@ -142,6 +143,9 @@ pub enum Request {
|
||||
/// policy), so the content survives gc and shows up in `List`.
|
||||
Push {
|
||||
/// Hash (hex) of the fully-present blob or HashSeq root to push.
|
||||
///
|
||||
/// The receiver below may be a NodeId or, from varde 0.1.6, a blob
|
||||
/// ticket it issued.
|
||||
hash: String,
|
||||
/// The receiving peer's iroh NodeId (z-base-32).
|
||||
node_id: String,
|
||||
|
||||
Reference in New Issue
Block a user