-
Notifications
You must be signed in to change notification settings - Fork 10
/
controller.go
122 lines (107 loc) · 3.49 KB
/
controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package tptaddr_static
import (
"context"
"errors"
"sort"
"strings"
"github.com/aperturerobotics/bifrost/peer"
"github.com/aperturerobotics/bifrost/tptaddr"
"github.com/aperturerobotics/controllerbus/controller"
"github.com/aperturerobotics/controllerbus/directive"
"github.com/blang/semver"
"golang.org/x/exp/slices"
)
// ControllerID is the ID of the controller.
const ControllerID = "bifrost/tptaddr/static"
// Version is the version of the controller implementation.
var Version = semver.MustParse("0.0.1")
// Controller implements the static tptaddr address list controller.
// Resolves LookupTptAddr directives with a static list of addresses.
type Controller struct {
// peers is the map between peer ids and addresses
peers map[string][]tptaddr.LookupTptAddrValue
}
// ParsePeerAddressMap parses the list of addresses to a peers map.
//
// Returns a list of errors for skipped addresses.
func ParsePeerAddressMap(addressesWithPeerIDs []string) (map[string][]string, []error) {
var errs []error
peers := make(map[string][]string)
for _, addr := range addressesWithPeerIDs {
peerIDStr, tptaddr, found := strings.Cut(addr, "|")
tptaddr = strings.TrimSpace(tptaddr)
if !found || !strings.Contains(tptaddr, "|") {
errs = append(errs, errors.New("invalid peer address: format is {peer-id}|{transport-type}|{address}"))
continue
}
pid, err := peer.IDB58Decode(strings.TrimSpace(peerIDStr))
if err != nil {
errs = append(errs, err)
continue
}
pidString := pid.String()
peers[pidString] = append(peers[pidString], tptaddr)
}
for k, sl := range peers {
sort.Strings(sl)
sl = slices.Compact(sl)
peers[k] = sl
}
return peers, errs
}
// NewController constructs a new controller.
func NewController(conf *Config) (*Controller, error) {
peers, errs := ParsePeerAddressMap(conf.GetAddresses())
if len(errs) != 0 {
return nil, errs[0]
}
return &Controller{
peers: peers,
}, nil
}
// GetControllerInfo returns information about the controller.
func (c *Controller) GetControllerInfo() *controller.Info {
return controller.NewInfo(
ControllerID,
Version,
"static list of peer transport addresses",
)
}
// Execute executes the forwarding controller.
// Returning nil ends execution.
// Returning an error triggers a retry with backoff.
func (c *Controller) Execute(ctx context.Context) error {
return nil
}
// HandleDirective asks if the handler can resolve the directive.
// If it can, it returns a resolver. If not, returns nil.
// Any unexpected errors are returned for logging.
// It is safe to add a reference to the directive during this call.
func (c *Controller) HandleDirective(ctx context.Context, di directive.Instance) ([]directive.Resolver, error) {
dir := di.GetDirective()
if d, ok := dir.(tptaddr.LookupTptAddr); ok {
return c.resolveLookupTptAddr(ctx, di, d)
}
return nil, nil
}
// resolveLookupTptAddr resolves a LookupTptAddr directive.
func (c *Controller) resolveLookupTptAddr(
ctx context.Context,
di directive.Instance,
dir tptaddr.LookupTptAddr,
) ([]directive.Resolver, error) {
targetPeerID := dir.LookupTptAddrTargetPeerId()
targetPeerIDString := targetPeerID.String()
addrs := c.peers[targetPeerIDString]
if len(addrs) != 0 {
return []directive.Resolver{directive.NewValueResolver(addrs)}, nil
}
return nil, nil
}
// Close releases any resources used by the controller.
// Error indicates any issue encountered releasing.
func (c *Controller) Close() error {
return nil
}
// _ is a type assertion
var _ controller.Controller = ((*Controller)(nil))