Files
2026-02-25 14:21:54 +00:00

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
}