mirror of
https://github.com/fluencelabs/go-libp2p-kad-dht
synced 2025-04-25 06:42:13 +00:00
As pointed out by raul, bootstrapping and refreshing are not the same thing. Bootstrapping is the initial setup (i.e., connect to some initial nodes to get started). Refreshing is the process of refreshing the routing table.
163 lines
4.5 KiB
Go
163 lines
4.5 KiB
Go
package dhtopts
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
ds "github.com/ipfs/go-datastore"
|
|
dssync "github.com/ipfs/go-datastore/sync"
|
|
"github.com/libp2p/go-libp2p-core/protocol"
|
|
"github.com/libp2p/go-libp2p-record"
|
|
)
|
|
|
|
// Deprecated: The old format did not support more than one message per stream, and is not supported
|
|
// or relevant with stream pooling. ProtocolDHT should be used instead.
|
|
const ProtocolDHTOld protocol.ID = "/ipfs/dht"
|
|
|
|
var (
|
|
ProtocolDHT protocol.ID = "/ipfs/kad/1.0.0"
|
|
DefaultProtocols = []protocol.ID{ProtocolDHT}
|
|
)
|
|
|
|
// Options is a structure containing all the options that can be used when constructing a DHT.
|
|
type Options struct {
|
|
Datastore ds.Batching
|
|
Validator record.Validator
|
|
Client bool
|
|
Protocols []protocol.ID
|
|
BucketSize int
|
|
|
|
RoutingTableRefreshQueryTimeout time.Duration
|
|
RoutingTableRefreshPeriod time.Duration
|
|
AutoRefresh bool
|
|
}
|
|
|
|
// Apply applies the given options to this Option
|
|
func (o *Options) Apply(opts ...Option) error {
|
|
for i, opt := range opts {
|
|
if err := opt(o); err != nil {
|
|
return fmt.Errorf("dht option %d failed: %s", i, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Option DHT option type.
|
|
type Option func(*Options) error
|
|
|
|
// Defaults are the default DHT options. This option will be automatically
|
|
// prepended to any options you pass to the DHT constructor.
|
|
var Defaults = func(o *Options) error {
|
|
o.Validator = record.NamespacedValidator{
|
|
"pk": record.PublicKeyValidator{},
|
|
}
|
|
o.Datastore = dssync.MutexWrap(ds.NewMapDatastore())
|
|
o.Protocols = DefaultProtocols
|
|
|
|
o.RoutingTableRefreshQueryTimeout = 10 * time.Second
|
|
o.RoutingTableRefreshPeriod = 1 * time.Hour
|
|
o.AutoRefresh = true
|
|
|
|
return nil
|
|
}
|
|
|
|
// RoutingTableRefreshQueryTimeout sets the timeout for routing table refresh
|
|
// queries.
|
|
func RoutingTableRefreshQueryTimeout(timeout time.Duration) Option {
|
|
return func(o *Options) error {
|
|
o.RoutingTableRefreshQueryTimeout = timeout
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// RoutingTableRefreshPeriod sets the period for refreshing buckets in the
|
|
// routing table. The DHT will refresh buckets every period by:
|
|
//
|
|
// 1. First searching for nearby peers to figure out how many buckets we should try to fill.
|
|
// 1. Then searching for a random key in each bucket that hasn't been queried in
|
|
// the last refresh period.
|
|
func RoutingTableRefreshPeriod(period time.Duration) Option {
|
|
return func(o *Options) error {
|
|
o.RoutingTableRefreshPeriod = period
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Datastore configures the DHT to use the specified datastore.
|
|
//
|
|
// Defaults to an in-memory (temporary) map.
|
|
func Datastore(ds ds.Batching) Option {
|
|
return func(o *Options) error {
|
|
o.Datastore = ds
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Client configures whether or not the DHT operates in client-only mode.
|
|
//
|
|
// Defaults to false.
|
|
func Client(only bool) Option {
|
|
return func(o *Options) error {
|
|
o.Client = only
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Validator configures the DHT to use the specified validator.
|
|
//
|
|
// Defaults to a namespaced validator that can only validate public keys.
|
|
func Validator(v record.Validator) Option {
|
|
return func(o *Options) error {
|
|
o.Validator = v
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// NamespacedValidator adds a validator namespaced under `ns`. This option fails
|
|
// if the DHT is not using a `record.NamespacedValidator` as it's validator (it
|
|
// uses one by default but this can be overridden with the `Validator` option).
|
|
//
|
|
// Example: Given a validator registered as `NamespacedValidator("ipns",
|
|
// myValidator)`, all records with keys starting with `/ipns/` will be validated
|
|
// with `myValidator`.
|
|
func NamespacedValidator(ns string, v record.Validator) Option {
|
|
return func(o *Options) error {
|
|
nsval, ok := o.Validator.(record.NamespacedValidator)
|
|
if !ok {
|
|
return fmt.Errorf("can only add namespaced validators to a NamespacedValidator")
|
|
}
|
|
nsval[ns] = v
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Protocols sets the protocols for the DHT
|
|
//
|
|
// Defaults to dht.DefaultProtocols
|
|
func Protocols(protocols ...protocol.ID) Option {
|
|
return func(o *Options) error {
|
|
o.Protocols = protocols
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// BucketSize configures the bucket size of the routing table.
|
|
//
|
|
// The default value is 20.
|
|
func BucketSize(bucketSize int) Option {
|
|
return func(o *Options) error {
|
|
o.BucketSize = bucketSize
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// DisableAutoRefresh completely disables 'auto-refresh' on the DHT routing
|
|
// table. This means that we will neither refresh the routing table periodically
|
|
// nor when the routing table size goes below the minimum threshold.
|
|
func DisableAutoRefresh() Option {
|
|
return func(o *Options) error {
|
|
o.AutoRefresh = false
|
|
return nil
|
|
}
|
|
}
|