Skip to main content

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, Debug)]
49pub struct MdnsDiscovery {
50    #[allow(unused)]
51    pub(super) args: MdnsActorArgs,
52    #[allow(unused)]
53    pub(super) inner: Arc<RwLock<Inner>>,
54}
55
56#[derive(Debug)]
57pub(super) struct Inner {
58    pub(super) actor_ref: Option<ActorRef<ToMdns>>,
59}
60
61impl MdnsDiscovery {
62    pub(crate) fn new(actor_ref: Option<ActorRef<ToMdns>>, args: MdnsActorArgs) -> Self {
63        Self {
64            args,
65            inner: Arc::new(RwLock::new(Inner { actor_ref })),
66        }
67    }
68
69    pub fn builder(address_book: AddressBook, endpoint: Endpoint) -> Builder {
70        Builder::new(address_book, endpoint)
71    }
72}
73
74impl Drop for Inner {
75    fn drop(&mut self) {
76        if let Some(actor_ref) = self.actor_ref.take() {
77            actor_ref.stop(None);
78        }
79    }
80}
81
82#[derive(Debug, Error)]
83pub enum MdnsDiscoveryError {
84    /// Spawning the internal actor failed.
85    #[error(transparent)]
86    ActorSpawn(#[from] ractor::SpawnErr),
87
88    /// Spawning the internal actor as a child actor of a supervisor failed.
89    #[cfg(feature = "supervisor")]
90    #[error(transparent)]
91    ActorLinkedSpawn(#[from] crate::supervisor::SupervisorError),
92
93    /// Messaging with internal actor via RPC failed.
94    #[error(transparent)]
95    ActorRpc(#[from] Box<ractor::RactorErr<ToMdns>>),
96}