From 46da51b7aaccb66210188c0da6b2977ace3aeded Mon Sep 17 00:00:00 2001 From: kaiyou Date: Thu, 7 May 2020 11:36:46 +0200 Subject: [PATCH] Implement node function as type functions This means nodeMeta can be private again, and also makes it easier to pass a Node object to the cluster for local meta, instead of a generic byte[] function. For later updating, that node is passed using Update() instead of New(). --- cluster/cluster.go | 15 ++++++++++----- common/node.go | 45 ++++++++++++++++++++++++++------------------- main.go | 17 +++++------------ 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/cluster/cluster.go b/cluster/cluster.go index fe73b39..2d4e78f 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -28,14 +28,14 @@ type State struct { type Cluster struct { LocalName string // used to avoid LocalNode(); should not change ml *memberlist.Memberlist - getMeta func(int) []byte + localNode common.Node state *State events chan memberlist.NodeEvent } const statePath = "/var/lib/wesher/state.json" -func New(init bool, clusterKey []byte, bindAddr string, bindPort int, useIPAsName bool, getMeta func(int) []byte) (*Cluster, error) { +func New(init bool, clusterKey []byte, bindAddr string, bindPort int, useIPAsName bool) (*Cluster, error) { state := &State{} if !init { loadState(state) @@ -64,7 +64,6 @@ func New(init bool, clusterKey []byte, bindAddr string, bindPort int, useIPAsNam cluster := Cluster{ LocalName: ml.LocalNode().Name, ml: ml, - getMeta: getMeta, // The big channel buffer is a work-around for https://github.com/hashicorp/memberlist/issues/23 // More than this many simultaneous events will deadlock cluster.members() events: make(chan memberlist.NodeEvent, 100), @@ -82,7 +81,12 @@ func (c *Cluster) NotifyConflict(node, other *memberlist.Node) { } func (c *Cluster) NodeMeta(limit int) []byte { - return c.getMeta(limit) + encoded, err := c.localNode.Encode(limit) + if err != nil { + logrus.Errorf("failed to encode local node: %s", err) + return nil + } + return encoded } // none of these are used @@ -112,7 +116,8 @@ func (c *Cluster) Leave() { c.ml.Shutdown() //nolint: errcheck } -func (c *Cluster) Update() { +func (c *Cluster) Update(localNode common.Node) { + c.localNode = localNode c.ml.UpdateNode(1 * time.Second) // we currently do not update after creation } diff --git a/common/node.go b/common/node.go index 812dc18..4e23487 100644 --- a/common/node.go +++ b/common/node.go @@ -6,11 +6,10 @@ import ( "net" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) -// NodeMeta holds metadata sent over the cluster -type NodeMeta struct { +// nodeMeta holds metadata sent over the cluster +type nodeMeta struct { OverlayAddr net.IPNet PubKey string } @@ -20,32 +19,40 @@ type Node struct { Name string Addr net.IP Meta []byte - NodeMeta + nodeMeta } func (n *Node) String() string { return n.Addr.String() } -func EncodeNodeMeta(nm NodeMeta, limit int) []byte { - buf := &bytes.Buffer{} - if err := gob.NewEncoder(buf).Encode(nm); err != nil { - logrus.Errorf("could not encode local state: %s", err) - return nil +func MakeLocalNode(overlayAddr net.IPNet, pubKey string) Node { + return Node{ + nodeMeta: nodeMeta{ + OverlayAddr: overlayAddr, + PubKey: pubKey, + }, } - if buf.Len() > limit { - logrus.Errorf("could not fit node metadata into %d bytes", limit) - return nil - } - return buf.Bytes() } -func DecodeNodeMeta(b []byte) (NodeMeta, error) { +func (n *Node) Encode(limit int) ([]byte, error) { + buf := &bytes.Buffer{} + if err := gob.NewEncoder(buf).Encode(n.nodeMeta); err != nil { + return nil, errors.Wrap(err, "could not encode local state") + } + if buf.Len() > limit { + return nil, errors.Errorf("could not fit node metadata into %d bytes", limit) + } + return buf.Bytes(), nil +} + +func (n *Node) Decode() error { // TODO: we blindly trust the info we get from the peers; We should be more defensive to limit the damage a leaked // PSK can cause. - nm := NodeMeta{} - if err := gob.NewDecoder(bytes.NewReader(b)).Decode(&nm); err != nil { - return nm, errors.Wrap(err, "could not decode node meta") + nm := nodeMeta{} + if err := gob.NewDecoder(bytes.NewReader(n.Meta)).Decode(&nm); err != nil { + return errors.Wrap(err, "could not decode node meta") } - return nm, nil + n.nodeMeta = nm + return nil } diff --git a/main.go b/main.go index c540e21..c1c06e6 100644 --- a/main.go +++ b/main.go @@ -38,19 +38,14 @@ func main() { logrus.WithError(err).Fatal("could not instantiate wireguard controller") } - getMeta := func(limit int) []byte { - return common.EncodeNodeMeta(common.NodeMeta{ - OverlayAddr: wg.OverlayAddr, - PubKey: wg.PubKey.String(), - }, limit) - } - - cluster, err := cluster.New(config.Init, config.ClusterKey, config.BindAddr, config.ClusterPort, config.UseIPAsName, getMeta) + cluster, err := cluster.New(config.Init, config.ClusterKey, config.BindAddr, config.ClusterPort, config.UseIPAsName) if err != nil { logrus.WithError(err).Fatal("could not create cluster") } + wg.AssignOverlayAddr((*net.IPNet)(config.OverlayNet), cluster.LocalName) - cluster.Update() + localNode := common.MakeLocalNode(wg.OverlayAddr, wg.PubKey.String()) + cluster.Update(localNode) nodec := cluster.Members() // avoid deadlocks by starting before join if err := backoff.RetryNotify( @@ -72,12 +67,10 @@ func main() { logrus.Info("cluster members:\n") nodes := make([]common.Node, 0, len(rawNodes)) for _, node := range rawNodes { - meta, err := common.DecodeNodeMeta(node.Meta) - if err != nil { + if err := node.Decode(); err != nil { logrus.Warnf("\t addr: %s, could not decode metadata", node.Addr) continue } - node.NodeMeta = meta nodes = append(nodes, node) logrus.Infof("\taddr: %s, overlay: %s, pubkey: %s", node.Addr, node.OverlayAddr, node.PubKey) }