2022-07-25 15:28:17 +00:00
// Set of functions that are exported when go-waku is built as a static/dynamic library
2022-03-21 23:15:53 +00:00
package main
/ *
# include < stdlib . h >
# include < stddef . h >
2023-08-10 13:30:38 +00:00
// The possible returned values for the functions that return int
2023-10-28 23:37:53 +00:00
static const int RET_OK = 0 ;
static const int RET_ERR = 1 ;
static const int RET_MISSING_CALLBACK = 2 ;
2023-08-10 13:30:38 +00:00
2023-10-28 23:37:53 +00:00
typedef void ( * WakuCallBack ) ( int ret_code , const char * msg , void * user_data ) ;
2022-03-21 23:15:53 +00:00
* /
import "C"
import (
2023-08-10 13:30:38 +00:00
"fmt"
2022-03-21 23:15:53 +00:00
"unsafe"
2023-08-10 13:30:38 +00:00
"github.com/waku-org/go-waku/library"
2022-11-09 19:53:01 +00:00
"github.com/waku-org/go-waku/waku/v2/protocol"
2022-03-21 23:15:53 +00:00
)
func main ( ) { }
// Initialize a waku node. Receives a JSON string containing the configuration
// for the node. It can be NULL. Example configuration:
// ```
// {"host": "0.0.0.0", "port": 60000, "advertiseAddr": "1.2.3.4", "nodeKey": "0x123...567", "keepAliveInterval": 20, "relay": true}
// ```
// All keys are optional. If not specified a default value will be set:
// - host: IP address. Default 0.0.0.0
// - port: TCP port to listen. Default 60000. Use 0 for random
// - advertiseAddr: External IP
// - nodeKey: secp256k1 private key. Default random
// - keepAliveInterval: interval in seconds to ping all peers
// - relay: Enable WakuRelay. Default `true`
2023-01-25 20:12:43 +00:00
// - relayTopics: Array of pubsub topics that WakuRelay will automatically subscribe to when the node starts
2023-03-10 18:41:19 +00:00
// - gossipsubParams: an object containing custom gossipsub parameters. All attributes are optional, and if not specified, it will use default values.
// - d: optimal degree for a GossipSub topic mesh. Default `6`
// - dLow: lower bound on the number of peers we keep in a GossipSub topic mesh. Default `5`
// - dHigh: upper bound on the number of peers we keep in a GossipSub topic mesh. Default `12`
// - dScore: affects how peers are selected when pruning a mesh due to over subscription. Default `4`
// - dOut: sets the quota for the number of outbound connections to maintain in a topic mesh. Default `2`
// - historyLength: controls the size of the message cache used for gossip. Default `5`
// - historyGossip: controls how many cached message ids we will advertise in IHAVE gossip messages. Default `3`
// - dLazy: affects how many peers we will emit gossip to at each heartbeat. Default `6`
// - gossipFactor: affects how many peers we will emit gossip to at each heartbeat. Default `0.25`
// - gossipRetransmission: controls how many times we will allow a peer to request the same message id through IWANT gossip before we start ignoring them. Default `3`
// - heartbeatInitialDelayMs: short delay in milliseconds before the heartbeat timer begins after the router is initialized. Default `100` milliseconds
// - heartbeatIntervalSeconds: controls the time between heartbeats. Default `1` second
// - slowHeartbeatWarning: duration threshold for heartbeat processing before emitting a warning. Default `0.1`
// - fanoutTTLSeconds: controls how long we keep track of the fanout state. Default `60` seconds
// - prunePeers: controls the number of peers to include in prune Peer eXchange. Default `16`
// - pruneBackoffSeconds: controls the backoff time for pruned peers. Default `60` seconds
// - unsubscribeBackoffSeconds: controls the backoff time to use when unsuscribing from a topic. Default `10` seconds
// - connectors: number of active connection attempts for peers obtained through PX. Default `8`
// - maxPendingConnections: maximum number of pending connections for peers attempted through px. Default `128`
// - connectionTimeoutSeconds: timeout in seconds for connection attempts. Default `30` seconds
// - directConnectTicks: the number of heartbeat ticks for attempting to reconnect direct peers that are not currently connected. Default `300`
// - directConnectInitialDelaySeconds: initial delay before opening connections to direct peers. Default `1` second
// - opportunisticGraftTicks: number of heartbeat ticks for attempting to improve the mesh with opportunistic grafting. Default `60`
// - opportunisticGraftPeers: the number of peers to opportunistically graft. Default `2`
// - graftFloodThresholdSeconds: If a GRAFT comes before GraftFloodThresholdSeconds has elapsed since the last PRUNE, then there is an extra score penalty applied to the peer through P7. Default `10` seconds
// - maxIHaveLength: max number of messages to include in an IHAVE message, also controls the max number of IHAVE ids we will accept and request with IWANT from a peer within a heartbeat. Default `5000`
// - maxIHaveMessages: max number of IHAVE messages to accept from a peer within a heartbeat. Default `10`
// - iWantFollowupTimeSeconds: Time to wait for a message requested through IWANT following an IHAVE advertisement. Default `3` seconds
2023-03-14 10:38:56 +00:00
// - seenMessagesTTLSeconds: configures when a previously seen message ID can be forgotten about. Default `120` seconds
2023-03-10 18:41:19 +00:00
//
2022-05-06 18:13:10 +00:00
// - minPeersToPublish: The minimum number of peers required on a topic to allow broadcasting a message. Default `0`
2023-06-22 18:55:51 +00:00
// - legacyFilter: Enable LegacyFilter. Default `false`
2022-12-19 23:21:14 +00:00
// - discV5: Enable DiscoveryV5. Default `false`
// - discV5BootstrapNodes: Array of bootstrap nodes ENR
// - discV5UDPPort: UDP port for DiscoveryV5
2022-10-20 15:14:46 +00:00
// - logLevel: Set the log level. Default `INFO`. Allowed values "DEBUG", "INFO", "WARN", "ERROR", "DPANIC", "PANIC", "FATAL"
2023-02-10 20:17:23 +00:00
// - store: Enable Store. Default `false`
// - databaseURL: url connection string. Default: "sqlite3://store.db". Also accepts PostgreSQL connection strings
// - storeRetentionMaxMessages: max number of messages to store in the database. Default 10000
// - storeRetentionTimeSeconds: max number of seconds that a message will be persisted in the database. Default 2592000 (30d)
2023-07-06 18:20:16 +00:00
// - websockets: an optional object containing settings to setup the websocket configuration
// - enabled: indicates if websockets support will be enabled. Default `false`
// - host: listening address for websocket connections. Default `0.0.0.0`
// - port: TCP listening port for websocket connection (0 for random, binding to 443 requires root access). Default: `60001“, if secure websockets support is enabled, the default is `6443“
// - secure: enable secure websockets support. Default `false`
// - certPath: secure websocket certificate path
// - keyPath: secure websocket key path
//
// - dns4DomainName: the domain name resolving to the node's public IPv4 address.
2022-10-20 15:14:46 +00:00
//
//export waku_new
2023-12-15 14:46:21 +00:00
func waku_new ( configJSON * C . char , cb C . WakuCallBack , userData unsafe . Pointer ) unsafe . Pointer {
if cb == nil {
panic ( "error: missing callback in waku_new" )
}
cid := C . malloc ( C . size_t ( unsafe . Sizeof ( uintptr ( 0 ) ) ) )
pid := ( * uint ) ( cid )
instance := library . Init ( )
* pid = instance . ID
err := library . NewNode ( instance , C . GoString ( configJSON ) )
if err != nil {
onError ( err , cb , userData )
return nil
}
return cid
2022-03-21 23:15:53 +00:00
}
// Starts the waku node
2022-10-20 15:14:46 +00:00
//
//export waku_start
2023-12-15 14:46:21 +00:00
func waku_start ( ctx unsafe . Pointer , onErr C . WakuCallBack , userData unsafe . Pointer ) C . int {
instance , err := getInstance ( ctx )
if err != nil {
onError ( err , onErr , userData )
}
err = library . Start ( instance )
2023-10-28 23:37:53 +00:00
return onError ( err , onErr , userData )
2022-03-21 23:15:53 +00:00
}
// Stops a waku node
2022-10-20 15:14:46 +00:00
//
//export waku_stop
2023-12-15 14:46:21 +00:00
func waku_stop ( ctx unsafe . Pointer , onErr C . WakuCallBack , userData unsafe . Pointer ) C . int {
instance , err := getInstance ( ctx )
if err != nil {
onError ( err , onErr , userData )
}
err = library . Stop ( instance )
return onError ( err , onErr , userData )
}
// Release the resources allocated to a waku node (stopping the node first if necessary)
//
//export waku_free
func waku_free ( ctx unsafe . Pointer , onErr C . WakuCallBack , userData unsafe . Pointer ) C . int {
instance , err := getInstance ( ctx )
if err != nil {
return onError ( err , onErr , userData )
}
err = library . Stop ( instance )
if err != nil {
return onError ( err , onErr , userData )
}
err = library . Free ( instance )
if err == nil {
C . free ( ctx )
}
2023-10-28 23:37:53 +00:00
return onError ( err , onErr , userData )
2022-03-21 23:15:53 +00:00
}
2022-07-26 18:23:26 +00:00
// Determine is a node is started or not
2022-10-20 15:14:46 +00:00
//
//export waku_is_started
2023-12-15 14:46:21 +00:00
func waku_is_started ( ctx unsafe . Pointer ) C . int {
instance , err := getInstance ( ctx )
if err != nil {
return 0
}
started := library . IsStarted ( instance )
2023-08-10 13:30:38 +00:00
if started {
return 1
}
return 0
}
2023-12-15 14:46:21 +00:00
type fn func ( instance * library . WakuInstance ) ( string , error )
type fnNoInstance func ( ) ( string , error )
func singleFnExec ( f fn , ctx unsafe . Pointer , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
instance , err := getInstance ( ctx )
if err != nil {
onError ( err , cb , userData )
}
result , err := f ( instance )
if err != nil {
return onError ( err , cb , userData )
}
return onSuccesfulResponse ( result , cb , userData )
}
2023-08-10 13:30:38 +00:00
2023-12-15 14:46:21 +00:00
func singleFnExecNoCtx ( f fnNoInstance , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
2023-08-10 13:30:38 +00:00
result , err := f ( )
if err != nil {
2023-10-28 23:37:53 +00:00
return onError ( err , cb , userData )
2023-08-10 13:30:38 +00:00
}
2023-10-28 23:37:53 +00:00
return onSuccesfulResponse ( result , cb , userData )
2022-07-26 18:23:26 +00:00
}
2022-03-21 23:15:53 +00:00
// Obtain the peer ID of the waku node
2022-10-20 15:14:46 +00:00
//
//export waku_peerid
2023-12-15 14:46:21 +00:00
func waku_peerid ( ctx unsafe . Pointer , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
return singleFnExec ( func ( instance * library . WakuInstance ) ( string , error ) {
return library . PeerID ( instance )
} , ctx , cb , userData )
2022-03-21 23:15:53 +00:00
}
// Obtain the multiaddresses the wakunode is listening to
2022-10-20 15:14:46 +00:00
//
//export waku_listen_addresses
2023-12-15 14:46:21 +00:00
func waku_listen_addresses ( ctx unsafe . Pointer , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
return singleFnExec ( func ( instance * library . WakuInstance ) ( string , error ) {
return library . ListenAddresses ( instance )
} , ctx , cb , userData )
2022-03-21 23:15:53 +00:00
}
// Add node multiaddress and protocol to the wakunode peerstore
2022-10-20 15:14:46 +00:00
//
//export waku_add_peer
2023-12-15 14:46:21 +00:00
func waku_add_peer ( ctx unsafe . Pointer , address * C . char , protocolID * C . char , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
return singleFnExec ( func ( instance * library . WakuInstance ) ( string , error ) {
return library . AddPeer ( instance , C . GoString ( address ) , C . GoString ( protocolID ) )
} , ctx , cb , userData )
2022-03-21 23:15:53 +00:00
}
2022-04-03 00:22:42 +00:00
// Connect to peer at multiaddress. if ms > 0, cancel the function execution if it takes longer than N milliseconds
2022-10-20 15:14:46 +00:00
//
//export waku_connect
2023-12-15 14:46:21 +00:00
func waku_connect ( ctx unsafe . Pointer , address * C . char , ms C . int , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
instance , err := getInstance ( ctx )
if err != nil {
onError ( err , cb , userData )
}
err = library . Connect ( instance , C . GoString ( address ) , int ( ms ) )
2023-10-28 23:37:53 +00:00
return onError ( err , cb , userData )
2022-03-21 23:15:53 +00:00
}
2022-04-03 00:22:42 +00:00
// Connect to known peer by peerID. if ms > 0, cancel the function execution if it takes longer than N milliseconds
2022-10-20 15:14:46 +00:00
//
//export waku_connect_peerid
2023-12-15 14:46:21 +00:00
func waku_connect_peerid ( ctx unsafe . Pointer , peerID * C . char , ms C . int , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
instance , err := getInstance ( ctx )
if err != nil {
onError ( err , cb , userData )
}
err = library . ConnectPeerID ( instance , C . GoString ( peerID ) , int ( ms ) )
2023-10-28 23:37:53 +00:00
return onError ( err , cb , userData )
2022-03-21 23:15:53 +00:00
}
// Close connection to a known peer by peerID
2022-10-20 15:14:46 +00:00
//
//export waku_disconnect
2023-12-15 14:46:21 +00:00
func waku_disconnect ( ctx unsafe . Pointer , peerID * C . char , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
instance , err := getInstance ( ctx )
if err != nil {
onError ( err , cb , userData )
}
err = library . Disconnect ( instance , C . GoString ( peerID ) )
2023-10-28 23:37:53 +00:00
return onError ( err , cb , userData )
2022-03-21 23:15:53 +00:00
}
// Get number of connected peers
2022-10-20 15:14:46 +00:00
//
//export waku_peer_cnt
2023-12-15 14:46:21 +00:00
func waku_peer_cnt ( ctx unsafe . Pointer , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
return singleFnExec ( func ( instance * library . WakuInstance ) ( string , error ) {
peerCnt , err := library . PeerCnt ( instance )
2023-08-10 13:30:38 +00:00
return fmt . Sprintf ( "%d" , peerCnt ) , err
2023-12-15 14:46:21 +00:00
} , ctx , cb , userData )
2022-03-21 23:15:53 +00:00
}
// Create a content topic string according to RFC 23
2022-10-20 15:14:46 +00:00
//
//export waku_content_topic
2023-11-08 12:54:24 +00:00
func waku_content_topic ( applicationName * C . char , applicationVersion * C . char , contentTopicName * C . char , encoding * C . char , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
contentTopic , _ := protocol . NewContentTopic ( C . GoString ( applicationName ) , C . GoString ( applicationVersion ) , C . GoString ( contentTopicName ) , C . GoString ( encoding ) )
2023-10-28 23:37:53 +00:00
return onSuccesfulResponse ( contentTopic . String ( ) , cb , userData )
2022-03-21 23:15:53 +00:00
}
// Get the default pubsub topic used in waku2: /waku/2/default-waku/proto
2022-10-20 15:14:46 +00:00
//
//export waku_default_pubsub_topic
2023-10-28 23:37:53 +00:00
func waku_default_pubsub_topic ( cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
return onSuccesfulResponse ( library . DefaultPubsubTopic ( ) , cb , userData )
2022-03-21 23:15:53 +00:00
}
2022-05-06 18:13:10 +00:00
// Register callback to act as signal handler and receive application signals
// (in JSON) which are used to react to asynchronous events in waku. The function
2022-03-21 23:15:53 +00:00
// signature for the callback should be `void myCallback(char* signalJSON)`
2022-10-20 15:14:46 +00:00
//
//export waku_set_event_callback
2023-12-15 14:46:21 +00:00
func waku_set_event_callback ( ctx unsafe . Pointer , cb C . WakuCallBack ) {
instance , err := getInstance ( ctx )
if err != nil {
panic ( err . Error ( ) ) // TODO: refactor to return an error instead of panic
}
library . SetEventCallback ( instance , unsafe . Pointer ( cb ) )
2022-03-21 23:15:53 +00:00
}
2022-03-22 16:30:14 +00:00
// Retrieve the list of peers known by the waku node
2022-10-20 15:14:46 +00:00
//
//export waku_peers
2023-12-15 14:46:21 +00:00
func waku_peers ( ctx unsafe . Pointer , cb C . WakuCallBack , userData unsafe . Pointer ) C . int {
return singleFnExec ( func ( instance * library . WakuInstance ) ( string , error ) {
return library . Peers ( instance )
} , ctx , cb , userData )
2022-03-21 23:15:53 +00:00
}