Skip to content

Commit

Permalink
feat: Delegated routing with custom configuration. (#9274)
Browse files Browse the repository at this point in the history
New multi-router configuration system based on https://hackmd.io/G1KRDEX5T3qyfoBMkIrBew#Methods

- Added a new routing type: "custom"
- Added specific struct types for different Routers (instead of map[string]interface{})
- Added `Duration` config type, to make easier time string parsing
- Added config documentation.
- Use the latest go-delegated-routing library version with GET support.
- Added changelog notes for this feature.

It:
- closes #9157
- closes #9079
- closes #9186
  • Loading branch information
ajnavarro committed Sep 22, 2022
1 parent 1146f2d commit d1b9e41
Show file tree
Hide file tree
Showing 31 changed files with 1,841 additions and 418 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Kubo Changelogs

- [v0.16](docs/changelogs/v0.16.md)
- [v0.15](docs/changelogs/v0.15.md)
- [v0.14](docs/changelogs/v0.14.md)
- [v0.13](docs/changelogs/v0.13.md)
Expand Down
14 changes: 13 additions & 1 deletion cmd/ipfs/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const (
routingOptionDHTKwd = "dht"
routingOptionDHTServerKwd = "dhtserver"
routingOptionNoneKwd = "none"
routingOptionCustomKwd = "custom"
routingOptionDefaultKwd = "default"
unencryptTransportKwd = "disable-transport-encryption"
unrestrictedApiAccessKwd = "unrestricted-api"
Expand Down Expand Up @@ -401,7 +402,10 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment

routingOption, _ := req.Options[routingOptionKwd].(string)
if routingOption == routingOptionDefaultKwd {
routingOption = cfg.Routing.Type.WithDefault(routingOptionDHTKwd)
routingOption = cfg.Routing.Type
if routingOption == "" {
routingOption = routingOptionDHTKwd
}
}
switch routingOption {
case routingOptionSupernodeKwd:
Expand All @@ -414,6 +418,14 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
ncfg.Routing = libp2p.DHTServerOption
case routingOptionNoneKwd:
ncfg.Routing = libp2p.NilRouterOption
case routingOptionCustomKwd:
ncfg.Routing = libp2p.ConstructDelegatedRouting(
cfg.Routing.Routers,
cfg.Routing.Methods,
cfg.Identity.PeerID,
cfg.Addresses.Swarm,
cfg.Identity.PrivKey,
)
default:
return fmt.Errorf("unrecognized routing option: %s", routingOption)
}
Expand Down
10 changes: 9 additions & 1 deletion config/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,15 @@ func InitWithIdentity(identity Identity) (*Config, error) {
},

Routing: Routing{
Type: NewOptionalString("dht"),
Type: "dht",
Methods: Methods{
MethodNameFindPeers: Method{},
MethodNameFindProviders: Method{},
MethodNameGetIPNS: Method{},
MethodNameProvide: Method{},
MethodNamePutIPNS: Method{},
},
Routers: nil,
},

// setup the node mount points.
Expand Down
2 changes: 1 addition & 1 deletion config/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ functionality - performance of content discovery and data
fetching may be degraded.
`,
Transform: func(c *Config) error {
c.Routing.Type = NewOptionalString("dhtclient")
c.Routing.Type = "dhtclient"
c.AutoNAT.ServiceMode = AutoNATServiceDisabled
c.Reprovider.Interval = "0"

Expand Down
142 changes: 128 additions & 14 deletions config/routing.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,158 @@
package config

import (
"encoding/json"
"fmt"
)

// Routing defines configuration options for libp2p routing
type Routing struct {
// Type sets default daemon routing mode.
//
// Can be one of "dht", "dhtclient", "dhtserver", "none", or unset.
Type *OptionalString `json:",omitempty"`
// Can be one of "dht", "dhtclient", "dhtserver", "none", or "custom".
// When "custom" is set, you can specify a list of Routers.
Type string

Routers map[string]Router
Routers Routers

Methods Methods
}

type Router struct {

// Currenly only supported Type is "reframe".
// Currenly supported Types are "reframe", "dht", "parallel", "sequential".
// Reframe type allows to add other resolvers using the Reframe spec:
// https://github.com/ipfs/specs/tree/main/reframe
// In the future we will support "dht" and other Types here.
Type string

Enabled Flag `json:",omitempty"`
Type RouterType

// Parameters are extra configuration that this router might need.
// A common one for reframe router is "Endpoint".
Parameters map[string]string
Parameters interface{}
}

type Routers map[string]RouterParser
type Methods map[MethodName]Method

func (m Methods) Check() error {

// Check supported methods
for _, mn := range MethodNameList {
_, ok := m[mn]
if !ok {
return fmt.Errorf("method name %q is missing from Routing.Methods config param", mn)
}
}

// Check unsupported methods
for k := range m {
seen := false
for _, mn := range MethodNameList {
if mn == k {
seen = true
break
}
}

if seen {
continue
}

return fmt.Errorf("method name %q is not a supported method on Routing.Methods config param", k)
}

return nil
}

type RouterParser struct {
Router
}

func (r *RouterParser) UnmarshalJSON(b []byte) error {
out := Router{}
out.Parameters = &json.RawMessage{}
if err := json.Unmarshal(b, &out); err != nil {
return err
}
raw := out.Parameters.(*json.RawMessage)

var p interface{}
switch out.Type {
case RouterTypeReframe:
p = &ReframeRouterParams{}
case RouterTypeDHT:
p = &DHTRouterParams{}
case RouterTypeSequential:
p = &ComposableRouterParams{}
case RouterTypeParallel:
p = &ComposableRouterParams{}
}

if err := json.Unmarshal(*raw, &p); err != nil {
return err
}

r.Router.Type = out.Type
r.Router.Parameters = p

return nil
}

// Type is the routing type.
// Depending of the type we need to instantiate different Routing implementations.
type RouterType string

const (
RouterTypeReframe RouterType = "reframe"
RouterTypeReframe RouterType = "reframe"
RouterTypeDHT RouterType = "dht"
RouterTypeSequential RouterType = "sequential"
RouterTypeParallel RouterType = "parallel"
)

type RouterParam string
type DHTMode string

const (
// RouterParamEndpoint is the URL where the routing implementation will point to get the information.
// Usually used for reframe Routers.
RouterParamEndpoint RouterParam = "Endpoint"
DHTModeServer DHTMode = "server"
DHTModeClient DHTMode = "client"
DHTModeAuto DHTMode = "auto"
)

RouterParamPriority RouterParam = "Priority"
type MethodName string

const (
MethodNameProvide MethodName = "provide"
MethodNameFindProviders MethodName = "find-providers"
MethodNameFindPeers MethodName = "find-peers"
MethodNameGetIPNS MethodName = "get-ipns"
MethodNamePutIPNS MethodName = "put-ipns"
)

var MethodNameList = []MethodName{MethodNameProvide, MethodNameFindPeers, MethodNameFindProviders, MethodNameGetIPNS, MethodNamePutIPNS}

type ReframeRouterParams struct {
// Endpoint is the URL where the routing implementation will point to get the information.
// Usually used for reframe Routers.
Endpoint string
}

type DHTRouterParams struct {
Mode DHTMode
AcceleratedDHTClient bool `json:",omitempty"`
PublicIPNetwork bool
}

type ComposableRouterParams struct {
Routers []ConfigRouter
Timeout *OptionalDuration `json:",omitempty"`
}

type ConfigRouter struct {
RouterName string
Timeout Duration
IgnoreErrors bool
ExecuteAfter *OptionalDuration `json:",omitempty"`
}

type Method struct {
RouterName string
}
Loading

0 comments on commit d1b9e41

Please sign in to comment.