2018-03-13 17:16:15 +00:00
|
|
|
package ipfscluster
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/hex"
|
|
|
|
|
|
|
|
libp2p "github.com/libp2p/go-libp2p"
|
2019-02-20 14:24:25 +00:00
|
|
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
2018-03-13 17:16:15 +00:00
|
|
|
host "github.com/libp2p/go-libp2p-host"
|
|
|
|
ipnet "github.com/libp2p/go-libp2p-interface-pnet"
|
2019-02-20 14:24:25 +00:00
|
|
|
dht "github.com/libp2p/go-libp2p-kad-dht"
|
2018-03-13 17:16:15 +00:00
|
|
|
pnet "github.com/libp2p/go-libp2p-pnet"
|
2019-02-20 14:24:25 +00:00
|
|
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
|
|
|
routedhost "github.com/libp2p/go-libp2p/p2p/host/routed"
|
2018-03-13 17:16:15 +00:00
|
|
|
ma "github.com/multiformats/go-multiaddr"
|
|
|
|
)
|
|
|
|
|
2019-02-20 14:24:25 +00:00
|
|
|
// NewClusterHost creates a libp2p Host with the options from the provided
|
|
|
|
// cluster configuration. Using that host, it creates pubsub and a DHT
|
|
|
|
// instances, for shared use by all cluster components. The returned host uses
|
|
|
|
// the DHT for routing. The resulting DHT is not bootstrapped.
|
|
|
|
func NewClusterHost(
|
|
|
|
ctx context.Context,
|
|
|
|
cfg *Config,
|
|
|
|
) (host.Host, *pubsub.PubSub, *dht.IpfsDHT, error) {
|
|
|
|
|
|
|
|
h, err := newHost(ctx, cfg.Secret, cfg.PrivateKey, []ma.Multiaddr{cfg.ListenAddr})
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
psub, err := newPubSub(ctx, h)
|
|
|
|
if err != nil {
|
|
|
|
h.Close()
|
|
|
|
return nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
idht, err := newDHT(ctx, h)
|
|
|
|
if err != nil {
|
|
|
|
h.Close()
|
|
|
|
return nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return routedHost(h, idht), psub, idht, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func newHost(ctx context.Context, secret []byte, priv crypto.PrivKey, listenAddrs []ma.Multiaddr) (host.Host, error) {
|
2018-03-13 17:16:15 +00:00
|
|
|
var prot ipnet.Protector
|
2018-03-15 15:41:06 +00:00
|
|
|
var err error
|
2018-03-13 17:16:15 +00:00
|
|
|
|
|
|
|
// Create protector if we have a secret.
|
2019-02-20 14:24:25 +00:00
|
|
|
if secret != nil && len(secret) > 0 {
|
2018-03-15 15:41:06 +00:00
|
|
|
var key [32]byte
|
2019-02-20 14:24:25 +00:00
|
|
|
copy(key[:], secret)
|
2018-03-15 15:41:06 +00:00
|
|
|
prot, err = pnet.NewV1ProtectorFromBytes(&key)
|
2018-03-13 17:16:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-14 22:52:49 +00:00
|
|
|
return libp2p.New(
|
|
|
|
ctx,
|
2019-02-20 14:24:25 +00:00
|
|
|
libp2p.Identity(priv),
|
|
|
|
libp2p.ListenAddrs(listenAddrs...),
|
2018-03-13 17:16:15 +00:00
|
|
|
libp2p.PrivateNetwork(prot),
|
2018-05-27 15:47:46 +00:00
|
|
|
libp2p.NATPortMap(),
|
2018-03-13 17:16:15 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-02-20 14:24:25 +00:00
|
|
|
func newDHT(ctx context.Context, h host.Host) (*dht.IpfsDHT, error) {
|
|
|
|
return dht.New(ctx, h)
|
|
|
|
}
|
|
|
|
|
|
|
|
func newPubSub(ctx context.Context, h host.Host) (*pubsub.PubSub, error) {
|
|
|
|
return pubsub.NewGossipSub(
|
|
|
|
ctx,
|
|
|
|
h,
|
|
|
|
pubsub.WithMessageSigning(true),
|
|
|
|
pubsub.WithStrictSignatureVerification(true),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func routedHost(h host.Host, d *dht.IpfsDHT) host.Host {
|
|
|
|
return routedhost.Wrap(h, d)
|
|
|
|
}
|
|
|
|
|
2018-03-13 17:16:15 +00:00
|
|
|
// EncodeProtectorKey converts a byte slice to its hex string representation.
|
|
|
|
func EncodeProtectorKey(secretBytes []byte) string {
|
|
|
|
return hex.EncodeToString(secretBytes)
|
|
|
|
}
|