Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Delegated routing with custom configuration. #9274

Merged
merged 19 commits into from
Sep 22, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
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