2023-08-10 13:30:38 +00:00
|
|
|
package library
|
2022-04-12 12:12:14 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"crypto/rand"
|
2023-02-10 20:17:23 +00:00
|
|
|
"database/sql"
|
2022-04-12 12:12:14 +00:00
|
|
|
"encoding/hex"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
2023-12-15 14:46:21 +00:00
|
|
|
"sync"
|
2022-04-12 12:12:14 +00:00
|
|
|
"time"
|
2023-12-15 14:46:21 +00:00
|
|
|
"unsafe"
|
2022-04-12 12:12:14 +00:00
|
|
|
|
2024-01-03 16:49:54 +00:00
|
|
|
"go.uber.org/zap"
|
2023-02-10 20:17:23 +00:00
|
|
|
"go.uber.org/zap/zapcore"
|
2022-10-20 15:14:46 +00:00
|
|
|
|
2022-04-12 12:12:14 +00:00
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
2023-03-10 18:41:19 +00:00
|
|
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
2022-10-19 19:39:32 +00:00
|
|
|
"github.com/libp2p/go-libp2p/core/peer"
|
2023-02-16 16:17:52 +00:00
|
|
|
libp2pProtocol "github.com/libp2p/go-libp2p/core/protocol"
|
2022-04-12 12:12:14 +00:00
|
|
|
"github.com/multiformats/go-multiaddr"
|
2023-08-16 01:40:00 +00:00
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2023-02-10 20:17:23 +00:00
|
|
|
"github.com/waku-org/go-waku/waku/persistence"
|
2023-07-06 21:40:57 +00:00
|
|
|
dbutils "github.com/waku-org/go-waku/waku/persistence/utils"
|
2022-11-09 19:53:01 +00:00
|
|
|
"github.com/waku-org/go-waku/waku/v2/node"
|
2023-08-03 16:21:15 +00:00
|
|
|
"github.com/waku-org/go-waku/waku/v2/peerstore"
|
2022-11-09 19:53:01 +00:00
|
|
|
"github.com/waku-org/go-waku/waku/v2/protocol"
|
|
|
|
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
|
|
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
2022-04-12 12:12:14 +00:00
|
|
|
)
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
// WakuInstance represents the state of the waku node
|
|
|
|
type WakuInstance struct {
|
2023-02-16 22:09:21 +00:00
|
|
|
ctx context.Context
|
|
|
|
cancel context.CancelFunc
|
2023-12-15 14:46:21 +00:00
|
|
|
ID uint
|
2023-02-16 22:09:21 +00:00
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
node *node.WakuNode
|
|
|
|
cb unsafe.Pointer
|
|
|
|
mobileSignalHandler MobileSignalHandler
|
2023-02-16 22:09:21 +00:00
|
|
|
|
|
|
|
relayTopics []string
|
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
var wakuInstances map[uint]*WakuInstance
|
|
|
|
var wakuInstancesMutex sync.RWMutex
|
2022-04-12 12:12:14 +00:00
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
var errWakuNodeNotReady = errors.New("not initialized")
|
|
|
|
var errWakuNodeAlreadyConfigured = errors.New("already configured")
|
|
|
|
var errWakuNodeNotConfigured = errors.New("not configured")
|
|
|
|
var errWakuAlreadyStarted = errors.New("already started")
|
|
|
|
var errWakuNodeNotStarted = errors.New("not started")
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
wakuInstances = make(map[uint]*WakuInstance)
|
|
|
|
}
|
2022-04-12 12:12:14 +00:00
|
|
|
|
|
|
|
func randomHex(n int) (string, error) {
|
|
|
|
bytes := make([]byte, n)
|
|
|
|
if _, err := rand.Read(bytes); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return hex.EncodeToString(bytes), nil
|
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
func Init() *WakuInstance {
|
|
|
|
wakuInstancesMutex.Lock()
|
|
|
|
defer wakuInstancesMutex.Unlock()
|
|
|
|
|
|
|
|
id := uint(len(wakuInstances))
|
|
|
|
instance := &WakuInstance{
|
|
|
|
ID: id,
|
|
|
|
}
|
|
|
|
wakuInstances[id] = instance
|
|
|
|
return instance
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetInstance(id uint) (*WakuInstance, error) {
|
|
|
|
wakuInstancesMutex.RLock()
|
|
|
|
defer wakuInstancesMutex.RUnlock()
|
|
|
|
|
|
|
|
instance, ok := wakuInstances[id]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("instance not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
return instance, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type ValidationType int64
|
|
|
|
|
|
|
|
const (
|
|
|
|
None ValidationType = iota
|
|
|
|
MustBeStarted ValidationType = iota
|
|
|
|
MustBeStopped
|
|
|
|
NotConfigured
|
|
|
|
)
|
|
|
|
|
|
|
|
func validateInstance(instance *WakuInstance, validationType ValidationType) error {
|
|
|
|
if instance == nil {
|
|
|
|
return errWakuNodeNotReady
|
|
|
|
}
|
|
|
|
|
|
|
|
switch validationType {
|
|
|
|
case NotConfigured:
|
|
|
|
if instance.node != nil {
|
|
|
|
return errWakuNodeAlreadyConfigured
|
|
|
|
}
|
|
|
|
case MustBeStarted:
|
|
|
|
if instance.node == nil {
|
|
|
|
return errWakuNodeNotConfigured
|
|
|
|
}
|
|
|
|
if instance.ctx == nil {
|
|
|
|
return errWakuNodeNotStarted
|
|
|
|
}
|
|
|
|
case MustBeStopped:
|
|
|
|
if instance.node == nil {
|
|
|
|
return errWakuNodeNotConfigured
|
|
|
|
}
|
|
|
|
if instance.ctx != nil {
|
|
|
|
return errWakuAlreadyStarted
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// NewNode initializes a waku node. Receives a JSON string containing the configuration, and use default values for those config items not specified
|
2023-12-15 14:46:21 +00:00
|
|
|
func NewNode(instance *WakuInstance, configJSON string) error {
|
|
|
|
if err := validateInstance(instance, NotConfigured); err != nil {
|
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
config, err := getConfig(configJSON)
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hostAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", *config.Host, *config.Port))
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var prvKey *ecdsa.PrivateKey
|
|
|
|
if config.NodeKey != nil {
|
|
|
|
prvKey, err = crypto.HexToECDSA(*config.NodeKey)
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
key, err := randomHex(32)
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
prvKey, err = crypto.HexToECDSA(key)
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
opts := []node.WakuNodeOption{
|
|
|
|
node.WithPrivateKey(prvKey),
|
|
|
|
node.WithHostAddress(hostAddr),
|
2024-07-11 16:02:52 +00:00
|
|
|
node.WithKeepAlive(10*time.Second, time.Duration(*config.KeepAliveInterval)*time.Second),
|
2024-10-01 04:51:13 +00:00
|
|
|
node.WithClusterID(uint16(config.ClusterID)),
|
|
|
|
node.WithShards(config.Shards),
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if *config.EnableRelay {
|
2023-03-10 18:41:19 +00:00
|
|
|
var pubsubOpt []pubsub.Option
|
|
|
|
if config.GossipSubParams != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
params := getGossipSubParams(config.GossipSubParams)
|
2023-03-10 18:41:19 +00:00
|
|
|
pubsubOpt = append(pubsubOpt, pubsub.WithGossipSubParams(params))
|
|
|
|
}
|
|
|
|
|
2023-07-06 18:20:16 +00:00
|
|
|
pubsubOpt = append(pubsubOpt, pubsub.WithSeenMessagesTTL(getSeenTTL(config)))
|
2023-03-14 10:38:56 +00:00
|
|
|
|
2023-03-10 18:41:19 +00:00
|
|
|
opts = append(opts, node.WithWakuRelayAndMinPeers(*config.MinPeersToPublish, pubsubOpt...))
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 18:20:16 +00:00
|
|
|
if config.DNS4DomainName != "" {
|
2023-09-11 14:24:05 +00:00
|
|
|
opts = append(opts, node.WithDNS4Domain(config.DNS4DomainName))
|
2023-07-06 18:20:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if config.Websockets.Enabled {
|
|
|
|
if config.Websockets.Secure {
|
|
|
|
if config.DNS4DomainName == "" {
|
|
|
|
utils.Logger().Warn("using secure websockets without a dns4 domain name might indicate a misconfiguration")
|
|
|
|
}
|
|
|
|
opts = append(opts, node.WithSecureWebsockets(config.Websockets.Host, *config.Websockets.Port, config.Websockets.CertPath, config.Websockets.KeyPath))
|
|
|
|
} else {
|
|
|
|
opts = append(opts, node.WithWebsockets(config.Websockets.Host, *config.Websockets.Port))
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-22 18:55:51 +00:00
|
|
|
opts = append(opts, node.WithWakuFilterLightNode())
|
|
|
|
|
2023-02-10 20:17:23 +00:00
|
|
|
if *config.EnableStore {
|
|
|
|
var db *sql.DB
|
2024-01-03 16:49:54 +00:00
|
|
|
var migrationFn func(*sql.DB, *zap.Logger) error
|
2024-01-02 16:35:58 +00:00
|
|
|
db, migrationFn, err = dbutils.ParseURL(*config.DatabaseURL, dbutils.DBSettings{}, utils.Logger())
|
2023-02-10 20:17:23 +00:00
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2023-02-10 20:17:23 +00:00
|
|
|
}
|
|
|
|
opts = append(opts, node.WithWakuStore())
|
2023-08-16 01:40:00 +00:00
|
|
|
dbStore, err := persistence.NewDBStore(prometheus.DefaultRegisterer, utils.Logger(),
|
2023-02-10 20:17:23 +00:00
|
|
|
persistence.WithDB(db),
|
|
|
|
persistence.WithMigrations(migrationFn),
|
|
|
|
persistence.WithRetentionPolicy(*config.RetentionMaxMessages, time.Duration(*config.RetentionTimeSeconds)*time.Second),
|
|
|
|
)
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2023-02-10 20:17:23 +00:00
|
|
|
}
|
|
|
|
opts = append(opts, node.WithMessageProvider(dbStore))
|
|
|
|
}
|
|
|
|
|
2022-12-19 23:21:14 +00:00
|
|
|
if *config.EnableDiscV5 {
|
2023-11-13 12:17:43 +00:00
|
|
|
discoveredNodes := node.GetNodesFromDNSDiscovery(utils.Logger(), context.TODO(), config.DNSDiscoveryNameServer, config.DNSDiscoveryURLs)
|
|
|
|
discv5Opts, err := node.GetDiscv5Option(discoveredNodes, config.DiscV5BootstrapNodes, *config.DiscV5UDPPort, true)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2022-12-19 23:21:14 +00:00
|
|
|
}
|
2023-11-13 12:17:43 +00:00
|
|
|
opts = append(opts, discv5Opts)
|
2022-12-19 23:21:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
instance.relayTopics = config.RelayTopics
|
2023-01-25 20:12:43 +00:00
|
|
|
|
2023-02-10 20:17:23 +00:00
|
|
|
lvl, err := zapcore.ParseLevel(*config.LogLevel)
|
2022-10-20 15:14:46 +00:00
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-10-20 15:14:46 +00:00
|
|
|
}
|
2023-02-10 20:17:23 +00:00
|
|
|
|
|
|
|
opts = append(opts, node.WithLogLevel(lvl))
|
2023-08-16 01:40:00 +00:00
|
|
|
opts = append(opts, node.WithPrometheusRegisterer(prometheus.DefaultRegisterer))
|
2022-10-20 15:14:46 +00:00
|
|
|
|
2023-01-06 22:37:57 +00:00
|
|
|
w, err := node.New(opts...)
|
2022-04-12 12:12:14 +00:00
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
instance.node = w
|
2022-04-12 12:12:14 +00:00
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
return nil
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
func stop(instance *WakuInstance) {
|
|
|
|
if instance.cancel != nil {
|
|
|
|
instance.node.Stop()
|
|
|
|
instance.cancel()
|
|
|
|
instance.cancel = nil
|
|
|
|
instance.ctx = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// Start starts the waku node
|
2023-12-15 14:46:21 +00:00
|
|
|
func Start(instance *WakuInstance) error {
|
|
|
|
if err := validateInstance(instance, MustBeStopped); err != nil {
|
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
instance.ctx, instance.cancel = context.WithCancel(context.Background())
|
2023-02-16 22:09:21 +00:00
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
if err := instance.node.Start(instance.ctx); err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
if instance.node.DiscV5() != nil {
|
|
|
|
if err := instance.node.DiscV5().Start(context.Background()); err != nil {
|
|
|
|
stop(instance)
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2023-01-04 18:46:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
for _, topic := range instance.relayTopics {
|
|
|
|
err := relaySubscribe(instance, topic)
|
2023-01-25 20:12:43 +00:00
|
|
|
if err != nil {
|
2023-12-15 14:46:21 +00:00
|
|
|
stop(instance)
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2023-01-25 20:12:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
return nil
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// Stop stops a waku node
|
2023-12-15 14:46:21 +00:00
|
|
|
func Stop(instance *WakuInstance) error {
|
|
|
|
if err := validateInstance(instance, None); err != nil {
|
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
stop(instance)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free stops a waku instance and frees the resources allocated to a waku node
|
|
|
|
func Free(instance *WakuInstance) error {
|
|
|
|
if err := validateInstance(instance, None); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-16 22:09:21 +00:00
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
if instance.cancel != nil {
|
|
|
|
stop(instance)
|
|
|
|
}
|
2022-07-26 18:23:26 +00:00
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
wakuInstancesMutex.Lock()
|
|
|
|
defer wakuInstancesMutex.Unlock()
|
|
|
|
delete(wakuInstances, instance.ID)
|
2022-04-12 12:12:14 +00:00
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
return nil
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// IsStarted is used to determine is a node is started or not
|
2023-12-15 14:46:21 +00:00
|
|
|
func IsStarted(instance *WakuInstance) bool {
|
|
|
|
return instance != nil && instance.ctx != nil
|
2022-07-26 18:23:26 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// PeerID is used to obtain the peer ID of the waku node
|
2023-12-15 14:46:21 +00:00
|
|
|
func PeerID(instance *WakuInstance) (string, error) {
|
|
|
|
if err := validateInstance(instance, MustBeStarted); err != nil {
|
|
|
|
return "", err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
return instance.node.ID(), nil
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// ListenAddresses returns the multiaddresses the wakunode is listening to
|
2023-12-15 14:46:21 +00:00
|
|
|
func ListenAddresses(instance *WakuInstance) (string, error) {
|
|
|
|
if err := validateInstance(instance, MustBeStarted); err != nil {
|
|
|
|
return "", err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var addresses []string
|
2023-12-15 14:46:21 +00:00
|
|
|
for _, addr := range instance.node.ListenAddresses() {
|
2022-04-12 12:12:14 +00:00
|
|
|
addresses = append(addresses, addr.String())
|
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
return marshalJSON(addresses)
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// AddPeer adds a node multiaddress and protocol to the wakunode peerstore
|
2023-12-15 14:46:21 +00:00
|
|
|
func AddPeer(instance *WakuInstance, address string, protocolID string) (string, error) {
|
|
|
|
if err := validateInstance(instance, MustBeStarted); err != nil {
|
|
|
|
return "", err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ma, err := multiaddr.NewMultiaddr(address)
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return "", err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
peerID, err := instance.node.AddPeer(ma, peerstore.Static, instance.relayTopics, libp2pProtocol.ID(protocolID))
|
2023-08-10 13:30:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2023-10-28 23:37:53 +00:00
|
|
|
return peerID.String(), nil
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// Connect is used to connect to a peer at multiaddress. if ms > 0, cancel the function execution if it takes longer than N milliseconds
|
2023-12-15 14:46:21 +00:00
|
|
|
func Connect(instance *WakuInstance, address string, ms int) error {
|
|
|
|
if err := validateInstance(instance, MustBeStarted); err != nil {
|
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var ctx context.Context
|
|
|
|
var cancel context.CancelFunc
|
|
|
|
|
|
|
|
if ms > 0 {
|
2023-12-15 14:46:21 +00:00
|
|
|
ctx, cancel = context.WithTimeout(instance.ctx, time.Duration(int(ms))*time.Millisecond)
|
2022-04-12 12:12:14 +00:00
|
|
|
defer cancel()
|
|
|
|
} else {
|
2023-12-15 14:46:21 +00:00
|
|
|
ctx = instance.ctx
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
return instance.node.DialPeer(ctx, address)
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// ConnectPeerID is usedd to connect to a known peer by peerID. if ms > 0, cancel the function execution if it takes longer than N milliseconds
|
2023-12-15 14:46:21 +00:00
|
|
|
func ConnectPeerID(instance *WakuInstance, peerID string, ms int) error {
|
|
|
|
if err := validateInstance(instance, MustBeStarted); err != nil {
|
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var ctx context.Context
|
|
|
|
var cancel context.CancelFunc
|
|
|
|
|
|
|
|
pID, err := peer.Decode(peerID)
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ms > 0 {
|
2023-12-15 14:46:21 +00:00
|
|
|
ctx, cancel = context.WithTimeout(instance.ctx, time.Duration(int(ms))*time.Millisecond)
|
2022-04-12 12:12:14 +00:00
|
|
|
defer cancel()
|
|
|
|
} else {
|
2023-12-15 14:46:21 +00:00
|
|
|
ctx = instance.ctx
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
return instance.node.DialPeerByID(ctx, pID)
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// Disconnect closes a connection to a known peer by peerID
|
2023-12-15 14:46:21 +00:00
|
|
|
func Disconnect(instance *WakuInstance, peerID string) error {
|
|
|
|
if err := validateInstance(instance, MustBeStarted); err != nil {
|
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pID, err := peer.Decode(peerID)
|
|
|
|
if err != nil {
|
2023-08-10 13:30:38 +00:00
|
|
|
return err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
return instance.node.ClosePeerById(pID)
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// PeerCnt returns the number of connected peers
|
2023-12-15 14:46:21 +00:00
|
|
|
func PeerCnt(instance *WakuInstance) (int, error) {
|
|
|
|
if err := validateInstance(instance, MustBeStarted); err != nil {
|
|
|
|
return 0, err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
return instance.node.PeerCount(), nil
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// ContentTopic creates a content topic string according to RFC 23
|
2023-11-08 12:54:24 +00:00
|
|
|
func ContentTopic(applicationName string, applicationVersion string, contentTopicName string, encoding string) string {
|
|
|
|
contentTopic, _ := protocol.NewContentTopic(applicationName, applicationVersion, contentTopicName, encoding)
|
2023-08-25 04:25:38 +00:00
|
|
|
return contentTopic.String()
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// DefaultPubsubTopic returns the default pubsub topic used in waku2: /waku/2/default-waku/proto
|
2022-04-12 12:12:14 +00:00
|
|
|
func DefaultPubsubTopic() string {
|
2023-10-30 14:56:26 +00:00
|
|
|
return protocol.DefaultPubsubTopic{}.String()
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type subscriptionMsg struct {
|
2022-10-09 15:08:46 +00:00
|
|
|
MessageID string `json:"messageId"`
|
2022-04-12 12:12:14 +00:00
|
|
|
PubsubTopic string `json:"pubsubTopic"`
|
|
|
|
Message *pb.WakuMessage `json:"wakuMessage"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func toSubscriptionMessage(msg *protocol.Envelope) *subscriptionMsg {
|
|
|
|
return &subscriptionMsg{
|
2024-05-03 16:07:03 +00:00
|
|
|
MessageID: msg.Hash().String(),
|
2022-04-12 12:12:14 +00:00
|
|
|
PubsubTopic: msg.PubsubTopic(),
|
|
|
|
Message: msg.Message(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
// Peers retrieves the list of peers known by the waku node
|
2023-12-15 14:46:21 +00:00
|
|
|
func Peers(instance *WakuInstance) (string, error) {
|
|
|
|
if err := validateInstance(instance, MustBeStarted); err != nil {
|
|
|
|
return "", err
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:46:21 +00:00
|
|
|
peers, err := instance.node.Peers()
|
2023-08-10 13:30:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2023-10-28 23:37:53 +00:00
|
|
|
for _, p := range peers {
|
|
|
|
addrs := []multiaddr.Multiaddr{}
|
|
|
|
for i := range p.Addrs {
|
|
|
|
// Filtering out SNI addresses due to https://github.com/waku-org/waku-rust-bindings/issues/66
|
|
|
|
// TODO: once https://github.com/multiformats/rust-multiaddr/issues/88 is implemented, remove this
|
|
|
|
_, err := p.Addrs[i].ValueForProtocol(multiaddr.P_SNI)
|
|
|
|
if err != nil {
|
|
|
|
addrs = append(addrs, p.Addrs[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p.Addrs = addrs
|
|
|
|
}
|
|
|
|
|
2023-08-10 13:30:38 +00:00
|
|
|
return marshalJSON(peers)
|
2022-04-12 12:12:14 +00:00
|
|
|
}
|