87 lines
2.6 KiB
Go
87 lines
2.6 KiB
Go
package cluster
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.clan.lol/clan/data-mesher/pkg/config"
|
|
dmcrypto "git.clan.lol/clan/data-mesher/pkg/crypto"
|
|
"git.clan.lol/clan/data-mesher/pkg/libp2p/security/tls"
|
|
dmnet "git.clan.lol/clan/data-mesher/pkg/net"
|
|
"github.com/libp2p/go-libp2p"
|
|
"github.com/libp2p/go-libp2p/core/host"
|
|
"github.com/libp2p/go-libp2p/core/peerstore"
|
|
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
|
|
"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
|
|
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
|
|
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
|
|
)
|
|
|
|
// newHost creates and configures a libp2p host from the application config.
|
|
func newHost(cfg *config.Config, resolver dmnet.InterfaceResolver) (host.Host, peerstore.Peerstore, error) {
|
|
if resolver == nil {
|
|
resolver = dmnet.DefaultResolver{}
|
|
}
|
|
|
|
// resolve listen addresses from interfaces
|
|
listenAddrs, err := resolver.ListenMultiaddrs(cfg.Cluster.Interfaces, cfg.Cluster.Port)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to resolve listen addresses: %w", err)
|
|
}
|
|
|
|
// todo make configurable
|
|
// control the target min and max connections to maintain with peers
|
|
cm, err := connmgr.NewConnManager(
|
|
10,
|
|
20,
|
|
connmgr.WithGracePeriod(time.Minute),
|
|
)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to create connection manager: %w", err)
|
|
}
|
|
|
|
identityKey, err := cfg.Cluster.IdentityKey.ToLibP2P()
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to convert identity key: %w", err)
|
|
}
|
|
|
|
// we always include this node's home network ID in the CA's trusted list
|
|
caKeys := []*dmcrypto.PublicKey{
|
|
cfg.Network.ID,
|
|
}
|
|
|
|
// we include the network ID of every extra network that has been configured, allowing their nodes to connect to
|
|
// our nodes
|
|
for _, extraNetwork := range cfg.ExtraNetworks {
|
|
caKeys = append(caKeys, extraNetwork.ID)
|
|
}
|
|
|
|
// create a new in memory peer store
|
|
ps, err := pstoremem.NewPeerstore()
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to create peerstore: %w", err)
|
|
}
|
|
|
|
opts := []libp2p.Option{
|
|
libp2p.Peerstore(ps),
|
|
libp2p.Transport(tcp.NewTCPTransport),
|
|
libp2p.Security(tls.ID, tls.New(caKeys, cfg.Cluster.IdentityCert, ps)),
|
|
libp2p.Muxer(yamux.ID, yamux.DefaultTransport),
|
|
libp2p.ConnectionManager(cm),
|
|
libp2p.Identity(identityKey),
|
|
libp2p.ListenAddrs(listenAddrs...),
|
|
}
|
|
|
|
// configure a connection gater if an interfaces list was specified
|
|
if len(cfg.Cluster.Interfaces) > 0 {
|
|
opts = append(opts, libp2p.ConnectionGater(NewConnectionGater(cfg.Cluster.Interfaces, resolver)))
|
|
}
|
|
|
|
h, err := libp2p.New(opts...)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to create libp2p host: %w", err)
|
|
}
|
|
|
|
return h, ps, nil
|
|
}
|