2018-03-13 17:16:15 +00:00
|
|
|
package ipfscluster
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/hex"
|
|
|
|
|
2019-05-06 08:19:46 +00:00
|
|
|
"github.com/ipfs/ipfs-cluster/config"
|
2018-03-13 17:16:15 +00:00
|
|
|
libp2p "github.com/libp2p/go-libp2p"
|
2019-09-29 08:23:13 +00:00
|
|
|
autonat "github.com/libp2p/go-libp2p-autonat-svc"
|
2019-09-26 08:10:12 +00:00
|
|
|
relay "github.com/libp2p/go-libp2p-circuit"
|
2019-05-22 22:34:47 +00:00
|
|
|
connmgr "github.com/libp2p/go-libp2p-connmgr"
|
2019-11-05 11:47:06 +00:00
|
|
|
corepnet "github.com/libp2p/go-libp2p-core/pnet"
|
2019-09-26 08:10:12 +00:00
|
|
|
routing "github.com/libp2p/go-libp2p-core/routing"
|
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"
|
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"
|
2019-09-29 08:23:13 +00:00
|
|
|
libp2pquic "github.com/libp2p/go-libp2p-quic-transport"
|
2019-10-31 08:12:14 +00:00
|
|
|
secio "github.com/libp2p/go-libp2p-secio"
|
|
|
|
libp2ptls "github.com/libp2p/go-libp2p-tls"
|
2019-02-20 14:24:25 +00:00
|
|
|
routedhost "github.com/libp2p/go-libp2p/p2p/host/routed"
|
2018-03-13 17:16:15 +00:00
|
|
|
)
|
|
|
|
|
2019-11-05 11:47:06 +00:00
|
|
|
// NewClusterHost creates a fully-featured 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. Relay
|
|
|
|
// and AutoNATService are additionally setup for this host.
|
2019-02-20 14:24:25 +00:00
|
|
|
func NewClusterHost(
|
|
|
|
ctx context.Context,
|
2019-05-06 08:19:46 +00:00
|
|
|
ident *config.Identity,
|
2019-05-06 08:54:31 +00:00
|
|
|
cfg *Config,
|
2019-08-24 15:09:54 +00:00
|
|
|
) (host.Host, *pubsub.PubSub, *dht.IpfsDHT, error) {
|
2019-02-20 14:24:25 +00:00
|
|
|
|
2019-05-22 22:34:47 +00:00
|
|
|
connman := connmgr.NewConnManager(cfg.ConnMgr.LowWater, cfg.ConnMgr.HighWater, cfg.ConnMgr.GracePeriod)
|
|
|
|
|
2019-09-29 08:23:13 +00:00
|
|
|
relayOpts := []relay.RelayOpt{relay.OptDiscovery}
|
|
|
|
if cfg.EnableRelayHop {
|
|
|
|
relayOpts = append(relayOpts, relay.OptHop)
|
|
|
|
}
|
|
|
|
|
2019-10-31 08:12:14 +00:00
|
|
|
var idht *dht.IpfsDHT
|
|
|
|
var err error
|
2019-09-29 08:23:13 +00:00
|
|
|
opts := []libp2p.Option{
|
|
|
|
libp2p.ListenAddrs(cfg.ListenAddr...),
|
|
|
|
libp2p.NATPortMap(),
|
|
|
|
libp2p.ConnectionManager(connman),
|
|
|
|
libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) {
|
2019-10-31 08:12:14 +00:00
|
|
|
idht, err = newDHT(ctx, h)
|
|
|
|
return idht, err
|
2019-09-29 08:23:13 +00:00
|
|
|
}),
|
|
|
|
libp2p.EnableRelay(relayOpts...),
|
|
|
|
libp2p.EnableAutoRelay(),
|
|
|
|
}
|
|
|
|
|
2019-11-05 11:47:06 +00:00
|
|
|
prot, err := newProtector(cfg.Secret)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
2018-08-15 10:30:00 +00:00
|
|
|
h, err := newHost(
|
|
|
|
ctx,
|
2019-11-05 11:47:06 +00:00
|
|
|
prot,
|
2018-08-15 10:30:00 +00:00
|
|
|
ident.PrivateKey,
|
2019-09-29 08:23:13 +00:00
|
|
|
opts...,
|
2018-08-15 10:30:00 +00:00
|
|
|
)
|
2019-02-20 14:24:25 +00:00
|
|
|
if err != nil {
|
2019-08-24 15:09:54 +00:00
|
|
|
return nil, nil, nil, err
|
2019-02-20 14:24:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
psub, err := newPubSub(ctx, h)
|
|
|
|
if err != nil {
|
|
|
|
h.Close()
|
2019-08-24 15:09:54 +00:00
|
|
|
return nil, nil, nil, err
|
2019-02-20 14:24:25 +00:00
|
|
|
}
|
|
|
|
|
2019-11-05 11:47:06 +00:00
|
|
|
// needed for auto relay
|
|
|
|
_, err = autonat.NewAutoNATService(ctx, h, baseOpts(prot)...)
|
|
|
|
if err != nil {
|
|
|
|
h.Close()
|
|
|
|
return nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
2019-10-31 08:12:14 +00:00
|
|
|
return h, psub, idht, nil
|
2019-02-20 14:24:25 +00:00
|
|
|
}
|
|
|
|
|
2019-11-05 11:47:06 +00:00
|
|
|
// newHost creates a base cluster host without dht, pubsub, relay or nat etc.
|
|
|
|
// mostly used for testing.
|
|
|
|
func newHost(ctx context.Context, prot corepnet.Protector, priv crypto.PrivKey, opts ...libp2p.Option) (host.Host, error) {
|
|
|
|
finalOpts := []libp2p.Option{
|
|
|
|
libp2p.Identity(priv),
|
2018-03-13 17:16:15 +00:00
|
|
|
}
|
2019-11-05 11:47:06 +00:00
|
|
|
finalOpts = append(finalOpts, baseOpts(prot)...)
|
|
|
|
finalOpts = append(finalOpts, opts...)
|
2018-08-15 10:30:00 +00:00
|
|
|
|
2019-09-29 08:23:13 +00:00
|
|
|
h, err := libp2p.New(
|
2018-08-15 10:30:00 +00:00
|
|
|
ctx,
|
2019-11-05 11:47:06 +00:00
|
|
|
finalOpts...,
|
2018-03-13 17:16:15 +00:00
|
|
|
)
|
2019-09-29 08:23:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-11-05 11:47:06 +00:00
|
|
|
return h, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func baseOpts(prot corepnet.Protector) []libp2p.Option {
|
|
|
|
return []libp2p.Option{
|
|
|
|
libp2p.PrivateNetwork(prot),
|
|
|
|
libp2p.Security(libp2ptls.ID, libp2ptls.New),
|
|
|
|
libp2p.Security(secio.ID, secio.New),
|
|
|
|
libp2p.Transport(libp2pquic.NewTransport),
|
|
|
|
libp2p.DefaultTransports,
|
2019-09-29 08:23:13 +00:00
|
|
|
}
|
2019-11-05 11:47:06 +00:00
|
|
|
}
|
2019-09-29 08:23:13 +00:00
|
|
|
|
2019-11-05 11:47:06 +00:00
|
|
|
func newProtector(secret []byte) (corepnet.Protector, error) {
|
|
|
|
// Create protector if we have a secret.
|
|
|
|
if len(secret) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var key [32]byte
|
|
|
|
copy(key[:], secret)
|
|
|
|
return pnet.NewV1ProtectorFromBytes(&key)
|
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)
|
|
|
|
}
|