diff --git a/cmd/yggdrasil/config.go b/cmd/yggdrasil/config.go index 4934e6df..36f13c88 100644 --- a/cmd/yggdrasil/config.go +++ b/cmd/yggdrasil/config.go @@ -5,6 +5,8 @@ import ( "io/ioutil" "os" + "golang.org/x/text/encoding/unicode" + "github.com/yggdrasil-network/yggdrasil-go/src/config" ) diff --git a/cmd/yggdrasil/main.go b/cmd/yggdrasil/main.go index 584f61fe..88ed544d 100644 --- a/cmd/yggdrasil/main.go +++ b/cmd/yggdrasil/main.go @@ -180,6 +180,15 @@ func main() { } else { logger.Errorln("Unable to get Listener:", err) } + // Add our peers + for _, addr := range n.config.Peers { + n.core.AddPeer(addr, "") + } + for sintf, addrs := range n.config.InterfacePeers { + for _, addr := range addrs { + n.core.AddPeer(addr, sintf) + } + } // Make some nice output that tells us what our IPv6 address and subnet are. // This is just logged to stdout for the user. address := n.core.Address() diff --git a/src/yggdrasil/api.go b/src/yggdrasil/api.go index 1a7c3d96..6e2cdcf6 100644 --- a/src/yggdrasil/api.go +++ b/src/yggdrasil/api.go @@ -383,13 +383,13 @@ func (c *Core) AddPeer(addr string, sintf string) error { if err := c.CallPeer(addr, sintf); err != nil { return err } - // TODO: PERSISTENCE! - /*config := c.GetConfig() - if sintf == "" { - config.Peers = append(config.Peers, addr) - } else { - config.InterfacePeers[sintf] = append(config.InterfacePeers[sintf], addr) - }*/ + c.peers.Act(c, func() { + if sintf == "" { + c.peers.persistentPeers = append(c.peers.persistentPeers, addr) + } else { + c.peers.persistentInterfacePeers[sintf] = append(c.peers.persistentInterfacePeers[sintf], addr) + } + }) return nil } diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 5f2baef6..c4f188cd 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -33,46 +33,6 @@ func (c *Core) _init(boxPrivKey *crypto.BoxPrivKey, sigPrivKey *crypto.SigPrivKe c.log = log.New(ioutil.Discard, "", 0) } - /* - current := c.config.Load().(*config.NodeConfig) - - boxPrivHex, err := hex.DecodeString(current.EncryptionPrivateKey) - if err != nil { - return err - } - if len(boxPrivHex) < crypto.BoxPrivKeyLen { - return errors.New("EncryptionPrivateKey is incorrect length") - } - - sigPrivHex, err := hex.DecodeString(current.SigningPrivateKey) - if err != nil { - return err - } - if len(sigPrivHex) < crypto.SigPrivKeyLen { - return errors.New("SigningPrivateKey is incorrect length") - } - - copy(c.boxPriv[:], boxPrivHex) - copy(c.sigPriv[:], sigPrivHex) - */ - /* - copy(c.boxPriv[:], boxPrivKey[:]) - copy(c.sigPriv[:], sigPrivKey[:]) - - boxPub, sigPub := c.boxPriv.Public(), c.sigPriv.Public() - - copy(c.boxPub[:], boxPub[:]) - copy(c.sigPub[:], sigPub[:]) - */ - /* - if bp := hex.EncodeToString(c.boxPub[:]); current.EncryptionPublicKey != bp { - c.log.Warnln("EncryptionPublicKey in config is incorrect, should be", bp) - } - if sp := hex.EncodeToString(c.sigPub[:]); current.SigningPublicKey != sp { - c.log.Warnln("SigningPublicKey in config is incorrect, should be", sp) - } - */ - c.peers.init(c) c.router.init(c, *boxPrivKey) c.switchTable.init(c, *sigPrivKey) // TODO move before peers? before router? @@ -80,36 +40,6 @@ func (c *Core) _init(boxPrivKey *crypto.BoxPrivKey, sigPrivKey *crypto.SigPrivKe return nil } -// If any static peers were provided in the configuration above then we should -// configure them. The loop ensures that disconnected peers will eventually -// be reconnected with. -func (c *Core) _addPeerLoop() { - // TODO: PERSISTENCE - /* - // Get the peers from the config - these could change! - current := c.GetConfig() - - // Add peers from the Peers section - for _, peer := range current.Peers { - go c.AddPeer(peer, "") // TODO: this should be acted and not in a goroutine? - time.Sleep(time.Second) - } - - // Add peers from the InterfacePeers section - for intf, intfpeers := range current.InterfacePeers { - for _, peer := range intfpeers { - go c.AddPeer(peer, intf) // TODO: this should be acted and not in a goroutine? - time.Sleep(time.Second) - } - } - - // Sit for a while - time.AfterFunc(time.Minute, func() { - c.Act(c, c._addPeerLoop) - }) - */ -} - // Start starts up Yggdrasil using the provided config.NodeConfig, and outputs // debug logging through the provided log.Logger. The started stack will include // TCP and UDP sockets, a multicast discovery socket, an admin socket, router, @@ -152,7 +82,7 @@ func (c *Core) _start(boxPrivKey *crypto.BoxPrivKey, sigPrivKey *crypto.SigPrivK return err } - c.Act(c, c._addPeerLoop) + c.peers.Act(c, c.peers._addPeerLoop) c.log.Infoln("Startup complete") return nil diff --git a/src/yggdrasil/peer.go b/src/yggdrasil/peer.go index e09d2c29..978f9a70 100644 --- a/src/yggdrasil/peer.go +++ b/src/yggdrasil/peer.go @@ -23,10 +23,12 @@ import ( // In other cases, it's link protocol traffic used to build the spanning tree, in which case this checks signatures and passes the message along to the switch. type peers struct { phony.Inbox - core *Core - mutex sync.Mutex // Synchronize writes to atomic - ports atomic.Value // map[switchPort]*peer, use CoW semantics - allowedBoxPubKeys []crypto.BoxPubKey // protected by actor + core *Core + mutex sync.Mutex // Synchronize writes to atomic + ports atomic.Value // map[switchPort]*peer, use CoW semantics + persistentPeers []string // Connection strings for persistent peers + persistentInterfacePeers map[string][]string // Connection strings for persistent interface peers + allowedBoxPubKeys []crypto.BoxPubKey // protected by actor } // Initializes the peers struct. @@ -37,6 +39,28 @@ func (ps *peers) init(c *Core) { ps.core = c } +// Add persistent peers if they are not already added. +func (ps *peers) _addPeerLoop() { + // Add peers from the Peers section + for _, peer := range ps.persistentPeers { + go ps.core.AddPeer(peer, "") // TODO: this should be acted and not in a goroutine? + time.Sleep(time.Second) + } + + // Add peers from the InterfacePeers section + for intf, intfpeers := range ps.persistentInterfacePeers { + for _, peer := range intfpeers { + go ps.core.AddPeer(peer, intf) // TODO: this should be acted and not in a goroutine? + time.Sleep(time.Second) + } + } + + // Sit for a while + time.AfterFunc(time.Minute, func() { + ps.Act(ps, ps._addPeerLoop) + }) +} + // AddAllowedEncryptionPublicKey whitelists a key for incoming peer connections. func (ps *peers) isAllowedEncryptionPublicKey(key *crypto.BoxPubKey) (allowed bool) { phony.Block(ps, func() {