p2panda_net/iroh_mdns/
api.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use std::sync::Arc;
4
5use ractor::ActorRef;
6use thiserror::Error;
7use tokio::sync::RwLock;
8
9use crate::address_book::AddressBook;
10use crate::iroh_endpoint::Endpoint;
11use crate::iroh_mdns::Builder;
12use crate::iroh_mdns::actor::{MdnsActorArgs, ToMdns};
13
14/// Resolve transport information for nearby nodes on the local-area network via multicast DNS
15/// (mDNS).
16///
17/// ## Example
18///
19/// ```rust
20/// # use std::error::Error;
21/// #
22/// # #[tokio::main]
23/// # async fn main() -> Result<(), Box<dyn Error>> {
24/// # use futures_util::StreamExt;
25/// # use p2panda_core::Hash;
26/// # use p2panda_net::iroh_mdns::MdnsDiscoveryMode;
27/// # use p2panda_net::{AddressBook, Discovery, Endpoint, MdnsDiscovery, Gossip};
28/// # let address_book = AddressBook::builder().spawn().await?;
29/// # let endpoint = Endpoint::builder(address_book.clone())
30/// #     .spawn()
31/// #     .await?;
32/// #
33/// let mdns = MdnsDiscovery::builder(address_book, endpoint)
34///     .mode(MdnsDiscoveryMode::Active)
35///     .spawn()
36///     .await?;
37/// #
38/// # Ok(())
39/// # }
40/// ```
41///
42/// ## Active vs. Passive Mode
43///
44/// mDNS Discovery is set to "passive" mode by default which allows you to resolve transport
45/// information for other nodes without leaking your own information. Set it to "active" mode using
46/// [`MdnsDiscoveryMode`](crate::iroh_mdns::MdnsDiscoveryMode) if you want to publish your IP
47/// address on the local-area network.
48#[derive(Clone)]
49pub struct MdnsDiscovery {
50    #[allow(unused)]
51    pub(super) args: MdnsActorArgs,
52    #[allow(unused)]
53    pub(super) inner: Arc<RwLock<Inner>>,
54}
55
56pub(super) struct Inner {
57    pub(super) actor_ref: Option<ActorRef<ToMdns>>,
58}
59
60impl MdnsDiscovery {
61    pub(crate) fn new(actor_ref: Option<ActorRef<ToMdns>>, args: MdnsActorArgs) -> Self {
62        Self {
63            args,
64            inner: Arc::new(RwLock::new(Inner { actor_ref })),
65        }
66    }
67
68    pub fn builder(address_book: AddressBook, endpoint: Endpoint) -> Builder {
69        Builder::new(address_book, endpoint)
70    }
71}
72
73impl Drop for Inner {
74    fn drop(&mut self) {
75        if let Some(actor_ref) = self.actor_ref.take() {
76            actor_ref.stop(None);
77        }
78    }
79}
80
81#[derive(Debug, Error)]
82pub enum MdnsDiscoveryError {
83    /// Spawning the internal actor failed.
84    #[error(transparent)]
85    ActorSpawn(#[from] ractor::SpawnErr),
86
87    /// Spawning the internal actor as a child actor of a supervisor failed.
88    #[cfg(feature = "supervisor")]
89    #[error(transparent)]
90    ActorLinkedSpawn(#[from] crate::supervisor::SupervisorError),
91
92    /// Messaging with internal actor via RPC failed.
93    #[error(transparent)]
94    ActorRpc(#[from] Box<ractor::RactorErr<ToMdns>>),
95}