Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"github.com/libp2p/go-libp2p"
dht "github.com/libp2p/go-libp2p-kad-dht"
"github.com/libp2p/go-libp2p-kad-dht/records"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/host"
Expand All @@ -27,6 +28,9 @@ import (
"github.com/libp2p/go-libp2p/p2p/discovery/mdns"
drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing"
"github.com/multiformats/go-multiaddr"

ds "github.com/ipfs/go-datastore"
dssync "github.com/ipfs/go-datastore/sync"
)

var (
Expand Down Expand Up @@ -92,7 +96,7 @@ func NewClient(config Config) (Client, error) {
}

// Set up DHT
kadDHT, err := setupDHT(ctx, h, bootstrapPeers, clientLogger, cancel)
kadDHT, err := setupDHT(ctx, h, config, bootstrapPeers, clientLogger, cancel)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -204,8 +208,46 @@ func createHost(_ context.Context, hostOpts []libp2p.Option, config Config, rela
return h, nil
}

func setupDHT(ctx context.Context, h host.Host, bootstrapPeers []peer.AddrInfo, _ logger, cancel context.CancelFunc) (*dht.IpfsDHT, error) {
kadDHT, err := dht.New(ctx, h, dht.Mode(dht.ModeServer), dht.BootstrapPeers(bootstrapPeers...))
func setupDHT(ctx context.Context, h host.Host, config Config, bootstrapPeers []peer.AddrInfo, log logger, cancel context.CancelFunc) (*dht.IpfsDHT, error) {
// Determine DHT mode (default to server)
mode := dht.ModeServer
if config.DHTMode == "client" {
mode = dht.ModeClient
log.Infof("DHT mode: client (query-only, no provider storage)")
} else {
log.Infof("DHT mode: server (will advertise and store provider records)")
}

// Build DHT options
dhtOpts := []dht.Option{
dht.Mode(mode),
dht.BootstrapPeers(bootstrapPeers...),
}

// If server mode and custom cleanup interval specified, configure ProviderManager
if mode == dht.ModeServer && config.DHTCleanupInterval > 0 {
log.Infof("Configuring DHT cleanup interval: %v", config.DHTCleanupInterval)

// Create an in-memory datastore for the provider manager
// Same as default DHT datastore creation
datastore := dssync.MutexWrap(ds.NewMapDatastore())

providerManager, err := records.NewProviderManager(
ctx,
h.ID(),
h.Peerstore(),
datastore,
records.CleanupInterval(config.DHTCleanupInterval),
)
if err != nil {
_ = h.Close()
cancel()
return nil, fmt.Errorf("failed to create provider manager: %w", err)
}
dhtOpts = append(dhtOpts, dht.ProviderStore(providerManager))
}

kadDHT, err := dht.New(ctx, h, dhtOpts...)
if err != nil {
_ = h.Close()
cancel()
Expand Down
18 changes: 18 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,22 @@ type Config struct {
// If not provided, bootstrap peers will be used as relays.
// Example: []string{"/ip4/1.2.3.4/tcp/4001/p2p/QmPeerID"}
RelayPeers []string

// DHTMode specifies whether this node runs the DHT in client or server mode.
// Valid values: "client", "server"
// - "client": Can query DHT but doesn't advertise itself or store provider records.
// No ProviderManager cleanup overhead.
// - "server": Participates fully in DHT, advertises itself, stores provider records.
// Has periodic cleanup overhead. Default mode for proper P2P networks.
// If not provided or empty, defaults to "server" mode.
DHTMode string

// DHTCleanupInterval is the interval at which the DHT's ProviderManager performs
// garbage collection of expired provider records. The cleanup involves querying all
// provider records and removing expired entries.
// Only applies when DHTMode is "server".
// If not provided or zero, uses the DHT default (1 hour).
// Recommended: 6-24 hours for production to reduce CPU overhead.
// The cleanup frequency trades off between memory usage (stale records) and CPU usage.
DHTCleanupInterval time.Duration
}
Loading
Loading