2022-10-09 16:50:40 +02:00
//! Waku node implementation
2022-10-03 15:21:19 +02:00
mod config ;
2022-10-25 11:25:23 +02:00
mod discovery ;
2022-10-09 16:50:40 +02:00
mod filter ;
mod lightpush ;
2022-10-06 15:28:25 +02:00
mod management ;
mod peers ;
2022-10-06 15:51:00 +02:00
mod relay ;
2022-10-09 16:50:40 +02:00
mod store ;
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
2022-10-25 11:25:23 +02:00
use url ::{ Host , Url } ;
2022-10-03 15:21:19 +02:00
// internal
2022-10-25 11:25:23 +02:00
2022-10-09 16:50:40 +02:00
use crate ::general ::{
2022-10-17 19:30:07 +02:00
FilterSubscription , MessageId , PeerId , ProtocolId , Result , StoreQuery , StoreResponse ,
WakuMessage , WakuPubSubTopic ,
2022-10-09 16:50:40 +02:00
} ;
2022-10-03 15:21:19 +02:00
2022-10-26 14:56:03 +02:00
pub use config ::{ WakuLogLevel , WakuNodeConfig } ;
2022-10-06 15:28:25 +02:00
pub use peers ::{ Protocol , WakuPeerData , WakuPeers } ;
2022-10-06 15:51:00 +02:00
pub use relay ::{ waku_create_content_topic , waku_create_pubsub_topic , waku_dafault_pubsub_topic } ;
2022-10-17 19:30:07 +02:00
pub use store ::waku_store_query ;
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 > {
2022-10-06 15:51:00 +02:00
/// If the execution is successful, the result is the peer ID as a string (base58 encoded)
2022-11-02 16:21:15 +01:00
/// as per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_stop)
2022-10-06 15:51:00 +02:00
pub fn peer_id ( & self ) -> Result < PeerId > {
2022-10-06 15:28:25 +02:00
management ::waku_peer_id ( )
2022-10-03 15:21:19 +02:00
}
2022-10-06 15:51:00 +02:00
/// Get the multiaddresses the Waku node is listening to
2022-11-02 16:21:15 +01:00
/// as per [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_listen_addresses)
2022-10-03 15:21:19 +02:00
pub fn listen_addresses ( & self ) -> Result < Vec < Multiaddr > > {
2022-10-06 15:51:00 +02:00
management ::waku_listen_addresses ( )
2022-10-06 15:28:25 +02:00
}
2022-11-02 16:21:15 +01:00
/// 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)
2022-10-17 19:30:07 +02:00
pub fn add_peer ( & self , address : & Multiaddr , protocol_id : ProtocolId ) -> Result < PeerId > {
2022-10-06 15:28:25 +02:00
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)
2022-10-06 15:28:25 +02:00
pub fn connect_peer_with_address (
2022-10-06 15:51:00 +02:00
& self ,
2022-10-17 19:30:07 +02:00
address : & Multiaddr ,
2022-10-06 15:28:25 +02:00
timeout : Option < Duration > ,
) -> Result < ( ) > {
peers ::waku_connect_peer_with_address ( address , timeout )
}
2022-11-02 16:21:15 +01:00
/// Dial peer using a peer id
/// If `timeout` as milliseconds doesn't fit into a `i32` it is clamped to [`i32::MAX`]
/// The peer must be already known.
/// It must have been added before with [`WakuNodeHandle::add_peer`] or previously dialed with [`WakuNodeHandle::connect_peer_with_address`]
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_connect_peeridchar-peerid-int-timeoutms)
2022-10-06 15:51:00 +02:00
pub fn connect_peer_with_id ( & self , peer_id : PeerId , timeout : Option < Duration > ) -> Result < ( ) > {
2022-10-06 15:28:25 +02:00
peers ::waku_connect_peer_with_id ( peer_id , timeout )
}
2022-11-02 16:21:15 +01:00
/// Disconnect a peer using its peer id
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_disconnect_peerchar-peerid)
2022-10-17 19:30:07 +02:00
pub fn disconnect_peer_with_id ( & self , peer_id : & PeerId ) -> Result < ( ) > {
2022-10-06 15:28:25 +02:00
peers ::waku_disconnect_peer_with_id ( peer_id )
}
2022-10-06 15:51:00 +02:00
/// Get number of connected peers
2022-11-02 16:21:15 +01:00
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_peer_count)
2022-10-06 15:28:25 +02:00
pub fn peer_count ( & self ) -> Result < usize > {
peers ::waku_peer_count ( )
}
2022-10-06 15:51:00 +02:00
/// Retrieve the list of peers known by the Waku node
2022-11-02 16:21:15 +01:00
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_peers)
2022-10-06 15:28:25 +02:00
pub fn peers ( & self ) -> Result < WakuPeers > {
peers ::waku_peers ( )
}
2022-10-06 15:51:00 +02: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)
2022-10-06 15:51:00 +02:00
pub fn relay_publish_message (
& self ,
message : & WakuMessage ,
pubsub_topic : Option < 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 )
}
/// Optionally sign, encrypt using asymmetric encryption and 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_publish_enc_asymmetricchar-messagejson-char-pubsubtopic-char-publickey-char-optionalsigningkey-int-timeoutms)
2022-10-06 15:51:00 +02:00
pub fn relay_publish_encrypt_asymmetric (
& self ,
message : & WakuMessage ,
pubsub_topic : Option < WakuPubSubTopic > ,
public_key : & PublicKey ,
2022-10-09 16:50:40 +02:00
signing_key : Option < & SecretKey > ,
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_encrypt_asymmetric (
message ,
pubsub_topic ,
public_key ,
signing_key ,
timeout ,
)
}
/// Optionally sign, encrypt using symmetric encryption and 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_publish_enc_symmetricchar-messagejson-char-pubsubtopic-char-symmetrickey-char-optionalsigningkey-int-timeoutms)
2022-10-06 15:51:00 +02:00
pub fn relay_publish_encrypt_symmetric (
& self ,
message : & WakuMessage ,
pubsub_topic : Option < WakuPubSubTopic > ,
symmetric_key : & Key < Aes256Gcm > ,
2022-10-09 16:50:40 +02:00
signing_key : Option < & SecretKey > ,
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_encrypt_symmetric (
message ,
pubsub_topic ,
symmetric_key ,
signing_key ,
timeout ,
)
}
/// Determine if there are enough peers to publish a message on a given pubsub topic
pub fn relay_enough_peers ( & self , pubsub_topic : Option < WakuPubSubTopic > ) -> Result < bool > {
relay ::waku_enough_peers ( pubsub_topic )
}
/// Subscribe to a Waku Relay pubsub topic to receive messages
pub fn relay_subscribe ( & self , pubsub_topic : Option < WakuPubSubTopic > ) -> Result < ( ) > {
relay ::waku_relay_subscribe ( pubsub_topic )
}
/// Closes the pubsub subscription to a pubsub topic. No more messages will be received from this pubsub topic
pub fn relay_unsubscribe ( & self , pubsub_topic : Option < WakuPubSubTopic > ) -> Result < ( ) > {
relay ::waku_relay_unsubscribe ( pubsub_topic )
}
2022-10-09 16:50:40 +02:00
2022-11-02 16:21:15 +01:00
/// Retrieves historical messages on specific content topics. This method may be called with [`PagingOptions`](`crate::general::PagingOptions`),
/// to retrieve historical messages on a per-page basis. If the request included [`PagingOptions`](`crate::general::PagingOptions`),
/// the node must return messages on a per-page basis and include [`PagingOptions`](`crate::general::PagingOptions`) in the response.
/// These [`PagingOptions`](`crate::general::PagingOptions`) must contain a cursor pointing to the Index from which a new page can be requested
2022-10-09 16:50:40 +02:00
pub fn store_query (
2022-10-17 19:30:07 +02:00
& self ,
2022-10-09 16:50:40 +02:00
query : & StoreQuery ,
2022-10-19 15:58:09 +02:00
peer_id : & PeerId ,
timeout : Option < Duration > ,
2022-10-09 16:50:40 +02:00
) -> Result < StoreResponse > {
store ::waku_store_query ( query , peer_id , timeout )
}
/// Publish a message using Waku Lightpush
2022-11-02 16:21:15 +01:00
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_lightpush_publishchar-messagejson-char-topic-char-peerid-int-timeoutms)
2022-10-09 16:50:40 +02:00
pub fn lightpush_publish (
2022-10-17 19:30:07 +02:00
& self ,
2022-10-09 16:50:40 +02:00
message : & WakuMessage ,
2022-10-17 19:30:07 +02:00
pubsub_topic : Option < WakuPubSubTopic > ,
2022-10-09 16:50:40 +02:00
peer_id : PeerId ,
2022-10-17 19:30:07 +02:00
timeout : Option < Duration > ,
2022-10-09 16:50:40 +02:00
) -> Result < MessageId > {
lightpush ::waku_lightpush_publish ( message , pubsub_topic , peer_id , timeout )
}
/// Optionally sign, encrypt using asymmetric encryption and publish a message using Waku Lightpush
2022-11-02 16:21:15 +01:00
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_lightpush_publish_enc_asymmetricchar-messagejson-char-pubsubtopic-char-peerid-char-publickey-char-optionalsigningkey-int-timeoutms)
2022-10-09 16:50:40 +02:00
pub fn lightpush_publish_encrypt_asymmetric (
2022-10-17 19:30:07 +02:00
& self ,
2022-10-09 16:50:40 +02:00
message : & WakuMessage ,
pubsub_topic : Option < WakuPubSubTopic > ,
peer_id : PeerId ,
public_key : & PublicKey ,
signing_key : Option < & SecretKey > ,
2022-10-17 19:30:07 +02:00
timeout : Option < Duration > ,
2022-10-09 16:50:40 +02:00
) -> Result < MessageId > {
lightpush ::waku_lightpush_publish_encrypt_asymmetric (
message ,
pubsub_topic ,
peer_id ,
public_key ,
signing_key ,
timeout ,
)
}
/// Optionally sign, encrypt using symmetric encryption and publish a message using Waku Lightpush
2022-11-02 16:21:15 +01:00
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_lightpush_publish_enc_symmetricchar-messagejson-char-pubsubtopic-char-peerid-char-symmetrickey-char-optionalsigningkey-int-timeoutms)
2022-10-09 16:50:40 +02:00
pub fn lightpush_publish_encrypt_symmetric (
2022-10-17 19:30:07 +02:00
& self ,
2022-10-09 16:50:40 +02:00
message : & WakuMessage ,
pubsub_topic : Option < WakuPubSubTopic > ,
peer_id : PeerId ,
symmetric_key : & Key < Aes256Gcm > ,
signing_key : Option < & SecretKey > ,
2022-10-17 19:30:07 +02:00
timeout : Option < Duration > ,
2022-10-09 16:50:40 +02:00
) -> Result < MessageId > {
lightpush ::waku_lightpush_publish_encrypt_symmetric (
message ,
pubsub_topic ,
peer_id ,
symmetric_key ,
signing_key ,
timeout ,
)
}
/// Creates a subscription in a lightnode for messages that matches a content filter and optionally a [`WakuPubSubTopic`](`crate::general::WakuPubSubTopic`)
2022-11-02 16:21:15 +01:00
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_filter_subscribechar-filterjson-char-peerid-int-timeoutms)
2022-10-09 16:50:40 +02:00
pub fn filter_subscribe (
2022-10-17 19:30:07 +02:00
& self ,
2022-10-09 16:50:40 +02:00
filter_subscription : & FilterSubscription ,
peer_id : PeerId ,
timeout : Duration ,
) -> Result < ( ) > {
filter ::waku_filter_subscribe ( filter_subscription , peer_id , timeout )
}
/// Removes subscriptions in a light node matching a content filter and, optionally, a [`WakuPubSubTopic`](`crate::general::WakuPubSubTopic`)
2022-11-02 16:21:15 +01:00
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_filter_unsubscribechar-filterjson-int-timeoutms)
2022-10-09 16:50:40 +02:00
pub fn filter_unsubscribe (
2022-10-17 19:30:07 +02:00
& self ,
2022-10-09 16:50:40 +02:00
filter_subscription : & FilterSubscription ,
timeout : Duration ,
) -> Result < ( ) > {
filter ::waku_filter_unsubscribe ( filter_subscription , timeout )
}
2022-10-25 11:25:23 +02:00
pub fn dns_discovery (
& self ,
url : & Url ,
nameserver : Option < & Host > ,
timeout : Option < Duration > ,
) -> Result < Vec < Multiaddr > > {
discovery ::waku_dns_discovery ( url , nameserver , timeout )
}
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 ( ) ;
}
}