mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-28 14:15:06 +03:00
Link refactoring, admin socket changes
This commit is contained in:
parent
c7ee7d9681
commit
7afa23be4c
32 changed files with 1206 additions and 1130 deletions
128
src/core/core.go
128
src/core/core.go
|
@ -3,6 +3,9 @@ package core
|
|||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
@ -10,12 +13,10 @@ import (
|
|||
"time"
|
||||
|
||||
iwe "github.com/Arceliar/ironwood/encrypted"
|
||||
iwn "github.com/Arceliar/ironwood/network"
|
||||
iwt "github.com/Arceliar/ironwood/types"
|
||||
"github.com/Arceliar/phony"
|
||||
"github.com/gologme/log"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
||||
)
|
||||
|
||||
|
@ -36,7 +37,9 @@ type Core struct {
|
|||
log Logger
|
||||
addPeerTimer *time.Timer
|
||||
config struct {
|
||||
_peers map[Peer]*linkInfo // configurable after startup
|
||||
tls *tls.Config // immutable after startup
|
||||
roots *x509.CertPool // immutable after startup
|
||||
//_peers map[Peer]*linkInfo // configurable after startup
|
||||
_listeners map[ListenAddress]struct{} // configurable after startup
|
||||
nodeinfo NodeInfo // immutable after startup
|
||||
nodeinfoPrivacy NodeInfoPrivacy // immutable after startup
|
||||
|
@ -45,48 +48,76 @@ type Core struct {
|
|||
pathNotify func(ed25519.PublicKey)
|
||||
}
|
||||
|
||||
func New(secret ed25519.PrivateKey, logger Logger, opts ...SetupOption) (*Core, error) {
|
||||
func New(cert *tls.Certificate, logger Logger, opts ...SetupOption) (*Core, error) {
|
||||
c := &Core{
|
||||
log: logger,
|
||||
}
|
||||
c.ctx, c.cancel = context.WithCancel(context.Background())
|
||||
if c.log == nil {
|
||||
c.log = log.New(io.Discard, "", 0)
|
||||
}
|
||||
|
||||
if name := version.BuildName(); name != "unknown" {
|
||||
c.log.Infoln("Build name:", name)
|
||||
}
|
||||
if version := version.BuildVersion(); version != "unknown" {
|
||||
c.log.Infoln("Build version:", version)
|
||||
}
|
||||
c.ctx, c.cancel = context.WithCancel(context.Background())
|
||||
// Take a copy of the private key so that it is in our own memory space.
|
||||
if len(secret) != ed25519.PrivateKeySize {
|
||||
return nil, fmt.Errorf("private key is incorrect length")
|
||||
}
|
||||
c.secret = make(ed25519.PrivateKey, ed25519.PrivateKeySize)
|
||||
copy(c.secret, secret)
|
||||
c.public = secret.Public().(ed25519.PublicKey)
|
||||
|
||||
var err error
|
||||
keyXform := func(key ed25519.PublicKey) ed25519.PublicKey {
|
||||
return address.SubnetForKey(key).GetKey()
|
||||
}
|
||||
if c.PacketConn, err = iwe.NewPacketConn(c.secret,
|
||||
iwn.WithBloomTransform(keyXform),
|
||||
iwn.WithPeerMaxMessageSize(65535*2),
|
||||
iwn.WithPathNotify(c.doPathNotify),
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("error creating encryption: %w", err)
|
||||
}
|
||||
c.config._peers = map[Peer]*linkInfo{}
|
||||
c.config._listeners = map[ListenAddress]struct{}{}
|
||||
c.config._allowedPublicKeys = map[[32]byte]struct{}{}
|
||||
for _, opt := range opts {
|
||||
c._applyOption(opt)
|
||||
switch opt.(type) {
|
||||
case Peer, ListenAddress:
|
||||
// We can't do peers yet as the links aren't set up.
|
||||
continue
|
||||
default:
|
||||
if err = c._applyOption(opt); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply configuration option %T: %w", opt, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.log == nil {
|
||||
c.log = log.New(io.Discard, "", 0)
|
||||
if cert == nil || cert.PrivateKey == nil {
|
||||
return nil, fmt.Errorf("no private key supplied")
|
||||
}
|
||||
var ok bool
|
||||
if c.secret, ok = cert.PrivateKey.(ed25519.PrivateKey); !ok {
|
||||
return nil, fmt.Errorf("private key must be ed25519")
|
||||
}
|
||||
if len(c.secret) != ed25519.PrivateKeySize {
|
||||
return nil, fmt.Errorf("private key is incorrect length")
|
||||
}
|
||||
c.public = c.secret.Public().(ed25519.PublicKey)
|
||||
|
||||
if c.config.tls, err = c.generateTLSConfig(cert); err != nil {
|
||||
return nil, fmt.Errorf("error generating TLS config: %w", err)
|
||||
}
|
||||
if c.PacketConn, err = iwe.NewPacketConn(c.secret); err != nil {
|
||||
return nil, fmt.Errorf("error creating encryption: %w", err)
|
||||
}
|
||||
address, subnet := c.Address(), c.Subnet()
|
||||
c.log.Infof("Your public key is %s", hex.EncodeToString(c.public))
|
||||
c.log.Infof("Your IPv6 address is %s", address.String())
|
||||
c.log.Infof("Your IPv6 subnet is %s", subnet.String())
|
||||
if c.config.roots != nil {
|
||||
c.log.Println("Yggdrasil is running in TLS-only mode")
|
||||
}
|
||||
c.proto.init(c)
|
||||
if err := c.links.init(c); err != nil {
|
||||
return nil, fmt.Errorf("error initialising links: %w", err)
|
||||
}
|
||||
for _, opt := range opts {
|
||||
switch opt.(type) {
|
||||
case Peer, ListenAddress:
|
||||
// Now do the peers and listeners.
|
||||
if err = c._applyOption(opt); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply configuration option %T: %w", opt, err)
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
if err := c.proto.nodeinfo.setNodeInfo(c.config.nodeinfo, bool(c.config.nodeinfoPrivacy)); err != nil {
|
||||
return nil, fmt.Errorf("error setting node info: %w", err)
|
||||
}
|
||||
|
@ -100,42 +131,11 @@ func New(secret ed25519.PrivateKey, logger Logger, opts ...SetupOption) (*Core,
|
|||
c.log.Errorf("Failed to start listener %q: %s\n", listenaddr, err)
|
||||
}
|
||||
}
|
||||
c.Act(nil, c._addPeerLoop)
|
||||
return c, 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() {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
// Add peers from the Peers section
|
||||
for peer := range c.config._peers {
|
||||
go func(peer string, intf string) {
|
||||
u, err := url.Parse(peer)
|
||||
if err != nil {
|
||||
c.log.Errorln("Failed to parse peer url:", peer, err)
|
||||
}
|
||||
if err := c.CallPeer(u, intf); err != nil {
|
||||
c.log.Errorln("Failed to add peer:", err)
|
||||
}
|
||||
}(peer.URI, peer.SourceInterface) // TODO: this should be acted and not in a goroutine?
|
||||
}
|
||||
|
||||
c.addPeerTimer = time.AfterFunc(time.Minute, func() {
|
||||
c.Act(nil, c._addPeerLoop)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Core) RetryPeersNow() {
|
||||
if c.addPeerTimer != nil && !c.addPeerTimer.Stop() {
|
||||
<-c.addPeerTimer.C
|
||||
}
|
||||
c.Act(nil, c._addPeerLoop)
|
||||
// TODO: figure out a way to retrigger peer connections.
|
||||
}
|
||||
|
||||
// Stop shuts down the Yggdrasil node.
|
||||
|
@ -159,6 +159,10 @@ func (c *Core) _close() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (c *Core) isTLSOnly() bool {
|
||||
return c.config.roots != nil
|
||||
}
|
||||
|
||||
func (c *Core) MTU() uint64 {
|
||||
const sessionTypeOverhead = 1
|
||||
MTU := c.PacketConn.MTU() - sessionTypeOverhead
|
||||
|
@ -213,14 +217,6 @@ func (c *Core) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (c *Core) doPathNotify(key ed25519.PublicKey) {
|
||||
c.Act(nil, func() {
|
||||
if c.pathNotify != nil {
|
||||
c.pathNotify(key)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Core) SetPathNotify(notify func(ed25519.PublicKey)) {
|
||||
c.Act(nil, func() {
|
||||
c.pathNotify = notify
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue