feat(node): wire directory service into event loop
- Registers profile on relay reservation accepted (if discoverable) - DirectorySearch, DirectoryRegister, DirectoryRemove, SetRelayDiscoverable commands - Pending reply map for async search results Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
parent
c01dc94338
commit
cb45e2e463
|
|
@ -208,6 +208,21 @@ pub enum NodeCommand {
|
||||||
request: crate::protocol::gif::GifRequest,
|
request: crate::protocol::gif::GifRequest,
|
||||||
reply: tokio::sync::oneshot::Sender<Result<crate::protocol::gif::GifResponse, String>>,
|
reply: tokio::sync::oneshot::Sender<Result<crate::protocol::gif::GifResponse, String>>,
|
||||||
},
|
},
|
||||||
|
// register this peer's profile in the relay's persistent directory
|
||||||
|
DirectoryRegister,
|
||||||
|
// remove this peer's profile from the relay's directory
|
||||||
|
DirectoryRemove,
|
||||||
|
// search the relay's directory by display_name or peer_id
|
||||||
|
DirectorySearch {
|
||||||
|
query: String,
|
||||||
|
reply: tokio::sync::oneshot::Sender<
|
||||||
|
Result<Vec<crate::protocol::directory::DirectoryProfileEntry>, String>,
|
||||||
|
>,
|
||||||
|
},
|
||||||
|
// update the relay_discoverable flag at runtime (from settings toggle)
|
||||||
|
SetRelayDiscoverable {
|
||||||
|
enabled: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// events emitted from the node to the tauri frontend
|
// events emitted from the node to the tauri frontend
|
||||||
|
|
@ -464,6 +479,20 @@ pub async fn start(
|
||||||
tokio::sync::oneshot::Sender<Result<crate::protocol::gif::GifResponse, String>>,
|
tokio::sync::oneshot::Sender<Result<crate::protocol::gif::GifResponse, String>>,
|
||||||
> = HashMap::new();
|
> = HashMap::new();
|
||||||
|
|
||||||
|
|
||||||
|
// pending directory search replies keyed by request_response request id
|
||||||
|
let mut pending_directory_replies: HashMap<
|
||||||
|
libp2p::request_response::OutboundRequestId,
|
||||||
|
tokio::sync::oneshot::Sender<
|
||||||
|
Result<Vec<crate::protocol::directory::DirectoryProfileEntry>, String>,
|
||||||
|
>,
|
||||||
|
> = HashMap::new();
|
||||||
|
|
||||||
|
// relay_discoverable flag -- read from storage once at startup
|
||||||
|
let mut relay_discoverable = storage
|
||||||
|
.load_settings()
|
||||||
|
.map(|s| s.relay_discoverable)
|
||||||
|
.unwrap_or(true);
|
||||||
// relay reconnection state with exponential backoff
|
// relay reconnection state with exponential backoff
|
||||||
let mut relay_backoff_secs = RELAY_INITIAL_BACKOFF_SECS;
|
let mut relay_backoff_secs = RELAY_INITIAL_BACKOFF_SECS;
|
||||||
// deferred warning timer -- only notify the frontend after the grace
|
// deferred warning timer -- only notify the frontend after the grace
|
||||||
|
|
@ -1035,6 +1064,18 @@ pub async fn start(
|
||||||
// any WAN peers are reachable, so this ensures remote
|
// any WAN peers are reachable, so this ensures remote
|
||||||
// peers learn about us once the relay mesh is live
|
// peers learn about us once the relay mesh is live
|
||||||
publish_profile(&mut swarm_instance, &node_keypair, &storage);
|
publish_profile(&mut swarm_instance, &node_keypair, &storage);
|
||||||
|
|
||||||
|
// register profile in relay's persistent directory if discoverable
|
||||||
|
if relay_discoverable {
|
||||||
|
let profile = storage.load_profile().unwrap_or_default();
|
||||||
|
swarm_instance.behaviour_mut().directory_service.send_request(
|
||||||
|
&relay_peer_id,
|
||||||
|
crate::protocol::directory::DirectoryRequest::Register {
|
||||||
|
display_name: profile.display_name,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
log::info!("directory: sent Register to relay");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
libp2p::swarm::SwarmEvent::Behaviour(behaviour::DuskBehaviourEvent::RelayClient(event)) => {
|
libp2p::swarm::SwarmEvent::Behaviour(behaviour::DuskBehaviourEvent::RelayClient(event)) => {
|
||||||
log::debug!("relay client event: {:?}", event);
|
log::debug!("relay client event: {:?}", event);
|
||||||
|
|
@ -1345,6 +1386,35 @@ pub async fn start(
|
||||||
// ignore inbound requests (we only send outbound) and other events
|
// ignore inbound requests (we only send outbound) and other events
|
||||||
libp2p::swarm::SwarmEvent::Behaviour(behaviour::DuskBehaviourEvent::GifService(_)) => {}
|
libp2p::swarm::SwarmEvent::Behaviour(behaviour::DuskBehaviourEvent::GifService(_)) => {}
|
||||||
|
|
||||||
|
// directory service response from relay
|
||||||
|
libp2p::swarm::SwarmEvent::Behaviour(behaviour::DuskBehaviourEvent::DirectoryService(
|
||||||
|
libp2p::request_response::Event::Message {
|
||||||
|
message: libp2p::request_response::Message::Response { request_id, response },
|
||||||
|
..
|
||||||
|
}
|
||||||
|
)) => {
|
||||||
|
if let Some(reply) = pending_directory_replies.remove(&request_id) {
|
||||||
|
match response {
|
||||||
|
crate::protocol::directory::DirectoryResponse::Results(entries) => {
|
||||||
|
let _ = reply.send(Ok(entries));
|
||||||
|
}
|
||||||
|
crate::protocol::directory::DirectoryResponse::Ok => {
|
||||||
|
let _ = reply.send(Ok(vec![]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// directory service outbound failure
|
||||||
|
libp2p::swarm::SwarmEvent::Behaviour(behaviour::DuskBehaviourEvent::DirectoryService(
|
||||||
|
libp2p::request_response::Event::OutboundFailure { request_id, error, .. }
|
||||||
|
)) => {
|
||||||
|
if let Some(reply) = pending_directory_replies.remove(&request_id) {
|
||||||
|
let _ = reply.send(Err(format!("directory request failed: {:?}", error)));
|
||||||
|
}
|
||||||
|
log::warn!("directory: outbound failure: {:?}", error);
|
||||||
|
}
|
||||||
|
libp2p::swarm::SwarmEvent::Behaviour(behaviour::DuskBehaviourEvent::DirectoryService(_)) => {}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1643,6 +1713,64 @@ pub async fn start(
|
||||||
let _ = reply.send(Err("not connected to relay".to_string()));
|
let _ = reply.send(Err("not connected to relay".to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(NodeCommand::DirectoryRegister) => {
|
||||||
|
if let Some(rp) = relay_peer {
|
||||||
|
let profile = storage.load_profile().unwrap_or_default();
|
||||||
|
swarm_instance.behaviour_mut().directory_service.send_request(
|
||||||
|
&rp,
|
||||||
|
crate::protocol::directory::DirectoryRequest::Register {
|
||||||
|
display_name: profile.display_name,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
log::info!("directory: sent Register (command)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(NodeCommand::DirectoryRemove) => {
|
||||||
|
if let Some(rp) = relay_peer {
|
||||||
|
swarm_instance.behaviour_mut().directory_service.send_request(
|
||||||
|
&rp,
|
||||||
|
crate::protocol::directory::DirectoryRequest::Remove,
|
||||||
|
);
|
||||||
|
log::info!("directory: sent Remove (command)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(NodeCommand::DirectorySearch { query, reply }) => {
|
||||||
|
if let Some(rp) = relay_peer {
|
||||||
|
let request_id = swarm_instance
|
||||||
|
.behaviour_mut()
|
||||||
|
.directory_service
|
||||||
|
.send_request(
|
||||||
|
&rp,
|
||||||
|
crate::protocol::directory::DirectoryRequest::Search { query },
|
||||||
|
);
|
||||||
|
pending_directory_replies.insert(request_id, reply);
|
||||||
|
} else {
|
||||||
|
let _ = reply.send(Err("relay not connected".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(NodeCommand::SetRelayDiscoverable { enabled }) => {
|
||||||
|
relay_discoverable = enabled;
|
||||||
|
if enabled {
|
||||||
|
if let Some(rp) = relay_peer {
|
||||||
|
let profile = storage.load_profile().unwrap_or_default();
|
||||||
|
swarm_instance.behaviour_mut().directory_service.send_request(
|
||||||
|
&rp,
|
||||||
|
crate::protocol::directory::DirectoryRequest::Register {
|
||||||
|
display_name: profile.display_name,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
log::info!("directory: registered after opt-in");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(rp) = relay_peer {
|
||||||
|
swarm_instance.behaviour_mut().directory_service.send_request(
|
||||||
|
&rp,
|
||||||
|
crate::protocol::directory::DirectoryRequest::Remove,
|
||||||
|
);
|
||||||
|
log::info!("directory: removed after opt-out");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue