feat(messaging,dwn,mesh): route peer messaging + DWN sync + blob fetch via FIPS first
Migrates the remaining Tor-direct peer call sites to PeerRequest so FIPS is the default when the peer is federated and running the daemon: - node_message::send_to_peer / check_peer_reachable: gain a fips_npub parameter. Error messages updated to reference both transports. - Callers (api/rpc/network.rs, api/rpc/peers.rs, server health loop): look up fips_npub from federation storage by onion and pass it. - mesh::send_typed_wire_via_federation: the spawned background POST for the /archipelago/mesh-typed endpoint now uses PeerRequest with federation-resolved fips_npub. Signature domain unchanged. - api/rpc/mesh/typed_messages.rs fetch_blob_from_peer: blob URL rebuilt as (base_url, path_with_query) so PeerRequest can append the query string after swapping the host. Cap/exp/peer parameters are still signed over the content ref itself, so transport choice is invisible to the signature. - network/dwn_sync.rs sync_with_peers: per-peer fips_npub lookup before sync_single_peer; health/pull/push each dial through PeerRequest, so any DWN peer known to federation gets FIPS. Left Tor-only on purpose: - api/rpc/identity/handlers.rs handle_identity_resolve_peer_onion — resolving TO a DID, no anchor yet. - content.browse / preview calls to non-federated peers fall through to Tor naturally inside PeerRequest (no fips_npub → skip FIPS branch). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
ba825c13a5
commit
dbd19006f2
@@ -725,34 +725,29 @@ impl RpcHandler {
|
||||
}));
|
||||
}
|
||||
|
||||
// Reach the sender over Tor. Onion host is used verbatim; cap/exp/peer
|
||||
// match what the sender signed in handle_mesh_send_content.
|
||||
let url = format!(
|
||||
"http://{}/blob/{}?cap={}&exp={}&peer={}",
|
||||
sender_onion
|
||||
.trim_start_matches("http://")
|
||||
.trim_start_matches("https://"),
|
||||
cid,
|
||||
cap_token,
|
||||
cap_exp,
|
||||
self_pubkey_hex,
|
||||
// Reach the sender: FIPS preferred when the sender is federated
|
||||
// and has advertised a FIPS npub, Tor fallback otherwise.
|
||||
// Cap/exp/peer in the query string match what the sender signed in
|
||||
// handle_mesh_send_content — signature domain unchanged.
|
||||
let onion_bare = sender_onion
|
||||
.trim_start_matches("http://")
|
||||
.trim_start_matches("https://")
|
||||
.to_string();
|
||||
let path = format!(
|
||||
"/blob/{}?cap={}&exp={}&peer={}",
|
||||
cid, cap_token, cap_exp, self_pubkey_hex
|
||||
);
|
||||
let fips_npub =
|
||||
crate::federation::fips_npub_for_onion(&self.config.data_dir, &onion_bare).await;
|
||||
|
||||
let socks_proxy = reqwest::Proxy::all(crate::constants::TOR_SOCKS_PROXY)
|
||||
.map_err(|e| anyhow::anyhow!("SOCKS proxy setup failed: {}", e))?;
|
||||
let client = reqwest::Client::builder()
|
||||
.proxy(socks_proxy)
|
||||
.timeout(std::time::Duration::from_secs(120))
|
||||
.build()
|
||||
.map_err(|e| anyhow::anyhow!("HTTP client build failed: {}", e))?;
|
||||
|
||||
let resp = client
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("Fetch failed: {}", e))?;
|
||||
let (resp, transport) =
|
||||
crate::fips::dial::PeerRequest::new(fips_npub.as_deref(), &onion_bare, &path)
|
||||
.timeout(std::time::Duration::from_secs(120))
|
||||
.send_get()
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("Fetch failed: {}", e))?;
|
||||
if !resp.status().is_success() {
|
||||
anyhow::bail!("Blob fetch HTTP {}", resp.status());
|
||||
anyhow::bail!("Blob fetch HTTP {} (via {})", resp.status(), transport);
|
||||
}
|
||||
let mime = resp
|
||||
.headers()
|
||||
@@ -777,7 +772,7 @@ impl RpcHandler {
|
||||
"/blob/{}?cap={}&exp={}&peer={}",
|
||||
meta.cid, local_cap, local_exp, self_pubkey_hex
|
||||
);
|
||||
info!(cid = %cid, size = meta.size, "Fetched content_ref blob via tor");
|
||||
info!(cid = %cid, size = meta.size, transport = %transport, "Fetched content_ref blob");
|
||||
Ok(serde_json::json!({
|
||||
"fetched": true,
|
||||
"cached": false,
|
||||
|
||||
@@ -127,8 +127,11 @@ impl RpcHandler {
|
||||
"message": message,
|
||||
});
|
||||
|
||||
let to_fips_npub =
|
||||
crate::federation::fips_npub_for_onion(&self.config.data_dir, to_onion).await;
|
||||
crate::node_message::send_to_peer(
|
||||
to_onion,
|
||||
to_fips_npub.as_deref(),
|
||||
my_pubkey,
|
||||
&req_msg.to_string(),
|
||||
None,
|
||||
|
||||
@@ -114,20 +114,20 @@ impl RpcHandler {
|
||||
let fed_nodes = federation::load_nodes(&self.config.data_dir)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let recipient_pubkey = fed_nodes
|
||||
.iter()
|
||||
.find(|n| {
|
||||
n.onion == onion
|
||||
|| n.onion == format!("{}.onion", onion)
|
||||
|| format!("{}.onion", n.onion) == onion
|
||||
})
|
||||
.map(|n| n.pubkey.clone());
|
||||
let recipient = fed_nodes.iter().find(|n| {
|
||||
n.onion == onion
|
||||
|| n.onion == format!("{}.onion", onion)
|
||||
|| format!("{}.onion", n.onion) == onion
|
||||
});
|
||||
let recipient_pubkey = recipient.map(|n| n.pubkey.clone());
|
||||
let recipient_fips_npub = recipient.and_then(|n| n.fips_npub.clone());
|
||||
|
||||
// Include our node name so the recipient can display it
|
||||
let node_name = data.server_info.name.clone();
|
||||
|
||||
node_message::send_to_peer(
|
||||
onion,
|
||||
recipient_fips_npub.as_deref(),
|
||||
&pubkey,
|
||||
message,
|
||||
Some(node_id.signing_key()),
|
||||
@@ -147,7 +147,9 @@ impl RpcHandler {
|
||||
.get("onion")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing onion"))?;
|
||||
let reachable = node_message::check_peer_reachable(onion)
|
||||
let fips_npub =
|
||||
crate::federation::fips_npub_for_onion(&self.config.data_dir, onion).await;
|
||||
let reachable = node_message::check_peer_reachable(onion, fips_npub.as_deref())
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
Ok(serde_json::json!({ "onion": onion, "reachable": reachable }))
|
||||
|
||||
Reference in New Issue
Block a user