2022-10-09 16:50:40 +02:00
|
|
|
|
//! Waku node implementation
|
|
|
|
|
|
|
2022-10-03 15:21:19 +02:00
|
|
|
|
mod config;
|
2022-10-06 15:28:25 +02:00
|
|
|
|
mod management;
|
|
|
|
|
|
mod peers;
|
2022-10-06 15:51:00 +02:00
|
|
|
|
mod relay;
|
2022-10-03 15:21:19 +02:00
|
|
|
|
|
|
|
|
|
|
// std
|
2022-10-19 15:58:09 +02:00
|
|
|
|
pub use aes_gcm::{Aes256Gcm, Key};
|
|
|
|
|
|
pub use multiaddr::Multiaddr;
|
|
|
|
|
|
pub use secp256k1::{PublicKey, SecretKey};
|
2022-10-03 15:21:19 +02:00
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
use std::sync::Mutex;
|
2022-10-06 15:28:25 +02:00
|
|
|
|
use std::time::Duration;
|
2022-10-03 15:21:19 +02:00
|
|
|
|
// crates
|
|
|
|
|
|
// internal
|
2022-10-25 11:25:23 +02:00
|
|
|
|
|
2024-02-08 17:16:22 -04:00
|
|
|
|
use crate::general::{MessageId, Result, WakuMessage, WakuPubSubTopic};
|
2022-10-03 15:21:19 +02:00
|
|
|
|
|
2024-02-08 17:16:22 -04:00
|
|
|
|
pub use config::WakuNodeConfig;
|
2023-11-07 15:50:35 -04:00
|
|
|
|
pub use relay::{waku_create_content_topic, waku_default_pubsub_topic};
|
2022-10-03 15:21:19 +02:00
|
|
|
|
|
|
|
|
|
|
/// Shared flag to check if a waku node is already running in the current process
|
|
|
|
|
|
static WAKU_NODE_INITIALIZED: Mutex<bool> = Mutex::new(false);
|
|
|
|
|
|
|
|
|
|
|
|
/// Marker trait to disallow undesired waku node states in the handle
|
|
|
|
|
|
pub trait WakuNodeState {}
|
|
|
|
|
|
|
|
|
|
|
|
/// Waku node initialized state
|
|
|
|
|
|
pub struct Initialized;
|
|
|
|
|
|
|
|
|
|
|
|
/// Waku node running state
|
|
|
|
|
|
pub struct Running;
|
|
|
|
|
|
|
|
|
|
|
|
impl WakuNodeState for Initialized {}
|
|
|
|
|
|
impl WakuNodeState for Running {}
|
|
|
|
|
|
|
2022-10-09 16:50:40 +02:00
|
|
|
|
/// Handle to the underliying waku node
|
|
|
|
|
|
/// Safe to sendt to/through threads.
|
|
|
|
|
|
/// Only a waku node can be running at a time.
|
|
|
|
|
|
/// Referenes (`&`) to the handle can call queries and perform operations in a thread safe way.
|
|
|
|
|
|
/// Only an owned version of the handle can `start` or `stop` the node.
|
2022-10-03 15:21:19 +02:00
|
|
|
|
pub struct WakuNodeHandle<State: WakuNodeState>(PhantomData<State>);
|
|
|
|
|
|
|
2022-10-06 15:51:00 +02:00
|
|
|
|
/// We do not have any inner state, so the handle should be safe to be send among threads.
|
|
|
|
|
|
unsafe impl<State: WakuNodeState> Send for WakuNodeHandle<State> {}
|
|
|
|
|
|
|
|
|
|
|
|
/// References to the handle are safe to share, as they do not mutate the handle itself and
|
|
|
|
|
|
/// operations are performed by the bindings backend, which is supposed to be thread safe.
|
|
|
|
|
|
unsafe impl<State: WakuNodeState> Sync for WakuNodeHandle<State> {}
|
|
|
|
|
|
|
2022-10-03 15:21:19 +02:00
|
|
|
|
impl<State: WakuNodeState> WakuNodeHandle<State> {
|
2024-02-08 17:16:22 -04:00
|
|
|
|
// /// If the execution is successful, the result is the peer ID as a string (base58 encoded)
|
|
|
|
|
|
// /// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop)
|
|
|
|
|
|
// pub fn peer_id(&self) -> Result<PeerId> {
|
|
|
|
|
|
// management::waku_peer_id()
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// /// Get the multiaddresses the Waku node is listening to
|
|
|
|
|
|
// /// as per [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_listen_addresses)
|
|
|
|
|
|
// pub fn listen_addresses(&self) -> Result<Vec<Multiaddr>> {
|
|
|
|
|
|
// management::waku_listen_addresses()
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// /// Add a node multiaddress and protocol to the waku node’s peerstore.
|
|
|
|
|
|
// /// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_add_peerchar-address-char-protocolid)
|
|
|
|
|
|
// pub fn add_peer(&self, address: &Multiaddr, protocol_id: ProtocolId) -> Result<PeerId> {
|
|
|
|
|
|
// peers::waku_add_peers(address, protocol_id)
|
|
|
|
|
|
// }
|
2022-10-03 15:21:19 +02:00
|
|
|
|
}
|
2022-10-06 15:51:00 +02:00
|
|
|
|
|
2022-10-03 15:21:19 +02:00
|
|
|
|
fn stop_node() -> Result<()> {
|
|
|
|
|
|
let mut node_initialized = WAKU_NODE_INITIALIZED
|
|
|
|
|
|
.lock()
|
|
|
|
|
|
.expect("Access to the mutex at some point");
|
|
|
|
|
|
*node_initialized = false;
|
2022-10-06 15:28:25 +02:00
|
|
|
|
management::waku_stop().map(|_| ())
|
2022-10-03 15:21:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl WakuNodeHandle<Initialized> {
|
2022-11-02 16:21:15 +01:00
|
|
|
|
/// Start a Waku node mounting all the protocols that were enabled during the Waku node instantiation.
|
|
|
|
|
|
/// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_start)
|
2022-10-03 15:21:19 +02:00
|
|
|
|
pub fn start(self) -> Result<WakuNodeHandle<Running>> {
|
2022-10-06 15:28:25 +02:00
|
|
|
|
management::waku_start().map(|_| WakuNodeHandle(Default::default()))
|
2022-10-03 15:21:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-10-06 15:51:00 +02:00
|
|
|
|
/// Stops a Waku node
|
2022-11-02 16:21:15 +01:00
|
|
|
|
/// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop)
|
2022-10-03 15:21:19 +02:00
|
|
|
|
pub fn stop(self) -> Result<()> {
|
|
|
|
|
|
stop_node()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl WakuNodeHandle<Running> {
|
2022-10-06 15:51:00 +02:00
|
|
|
|
/// Stops a Waku node
|
2022-11-02 16:21:15 +01:00
|
|
|
|
/// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop)
|
2022-10-03 15:21:19 +02:00
|
|
|
|
pub fn stop(self) -> Result<()> {
|
|
|
|
|
|
stop_node()
|
|
|
|
|
|
}
|
2022-10-06 15:28:25 +02:00
|
|
|
|
|
2022-10-06 15:51:00 +02:00
|
|
|
|
/// Dial peer using a multiaddress
|
|
|
|
|
|
/// If `timeout` as milliseconds doesn't fit into a `i32` it is clamped to [`i32::MAX`]
|
|
|
|
|
|
/// If the function execution takes longer than `timeout` value, the execution will be canceled and an error returned.
|
|
|
|
|
|
/// Use 0 for no timeout
|
2022-11-02 16:21:15 +01:00
|
|
|
|
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_connect_peerchar-address-int-timeoutms)
|
2024-02-08 17:16:22 -04:00
|
|
|
|
pub fn connect(&self, address: &Multiaddr, timeout: Option<Duration>) -> Result<()> {
|
|
|
|
|
|
peers::waku_connect(address, timeout)
|
2022-10-06 15:28:25 +02:00
|
|
|
|
}
|
2022-10-06 15:51:00 +02:00
|
|
|
|
|
2023-11-07 15:50:35 -04:00
|
|
|
|
/// Publish a message using Waku Relay.
|
2022-11-02 16:21:15 +01:00
|
|
|
|
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_relay_publishchar-messagejson-char-pubsubtopic-int-timeoutms)
|
2023-11-07 15:50:35 -04:00
|
|
|
|
/// The pubsub_topic parameter is optional and if not specified it will be derived from the contentTopic.
|
2022-10-06 15:51:00 +02:00
|
|
|
|
pub fn relay_publish_message(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
message: &WakuMessage,
|
2024-02-08 17:16:22 -04:00
|
|
|
|
pubsub_topic: &WakuPubSubTopic,
|
2022-10-17 19:30:07 +02:00
|
|
|
|
timeout: Option<Duration>,
|
2022-10-06 15:51:00 +02:00
|
|
|
|
) -> Result<MessageId> {
|
|
|
|
|
|
relay::waku_relay_publish_message(message, pubsub_topic, timeout)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-07 15:50:35 -04:00
|
|
|
|
/// Subscribe to WakuRelay to receive messages matching a content filter.
|
2024-02-08 17:16:22 -04:00
|
|
|
|
pub fn relay_subscribe(&self, pubsub_topic: &WakuPubSubTopic) -> Result<()> {
|
|
|
|
|
|
relay::waku_relay_subscribe(pubsub_topic)
|
2022-10-06 15:51:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-07 15:50:35 -04:00
|
|
|
|
/// Closes the pubsub subscription to stop receiving messages matching a content filter. No more messages will be received from this pubsub topic
|
2024-02-08 17:16:22 -04:00
|
|
|
|
pub fn relay_unsubscribe(&self, pubsub_topic: &WakuPubSubTopic) -> Result<()> {
|
|
|
|
|
|
relay::waku_relay_unsubscribe(pubsub_topic)
|
2023-06-12 09:46:13 -04:00
|
|
|
|
}
|
2022-10-03 15:21:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-02 16:21:15 +01:00
|
|
|
|
/// Spawn a new Waku node with the given configuration (default configuration if `None` provided)
|
|
|
|
|
|
/// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_newchar-jsonconfig)
|
2022-10-03 15:21:19 +02:00
|
|
|
|
pub fn waku_new(config: Option<WakuNodeConfig>) -> Result<WakuNodeHandle<Initialized>> {
|
|
|
|
|
|
let mut node_initialized = WAKU_NODE_INITIALIZED
|
|
|
|
|
|
.lock()
|
|
|
|
|
|
.expect("Access to the mutex at some point");
|
|
|
|
|
|
if *node_initialized {
|
|
|
|
|
|
return Err("Waku node is already initialized".into());
|
|
|
|
|
|
}
|
|
|
|
|
|
*node_initialized = true;
|
2022-10-06 15:28:25 +02:00
|
|
|
|
management::waku_new(config).map(|_| WakuNodeHandle(Default::default()))
|
2022-10-03 15:21:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::waku_new;
|
2023-01-05 17:53:49 +02:00
|
|
|
|
use serial_test::serial;
|
2022-10-03 15:21:19 +02:00
|
|
|
|
|
|
|
|
|
|
#[test]
|
2023-01-05 17:53:49 +02:00
|
|
|
|
#[serial]
|
2022-10-03 15:21:19 +02:00
|
|
|
|
fn exclusive_running() {
|
|
|
|
|
|
let handle1 = waku_new(None).unwrap();
|
|
|
|
|
|
let handle2 = waku_new(None);
|
|
|
|
|
|
assert!(handle2.is_err());
|
|
|
|
|
|
let stop_handle = handle1.start().unwrap();
|
|
|
|
|
|
stop_handle.stop().unwrap();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|