Simplify configuration code throughout

This commit is contained in:
Neil Alexander 2019-09-02 11:54:27 +01:00
parent 174ebceaac
commit 029be2d86b
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
17 changed files with 223 additions and 209 deletions

View file

@ -18,7 +18,6 @@ import (
gsyslog "github.com/hashicorp/go-syslog" gsyslog "github.com/hashicorp/go-syslog"
"github.com/hjson/hjson-go" "github.com/hjson/hjson-go"
"github.com/kardianos/minwinsvc" "github.com/kardianos/minwinsvc"
"github.com/mitchellh/mapstructure"
"github.com/yggdrasil-network/yggdrasil-go/src/admin" "github.com/yggdrasil-network/yggdrasil-go/src/admin"
"github.com/yggdrasil-network/yggdrasil-go/src/config" "github.com/yggdrasil-network/yggdrasil-go/src/config"
@ -31,7 +30,6 @@ import (
type node struct { type node struct {
core yggdrasil.Core core yggdrasil.Core
state *config.NodeState
tuntap tuntap.TunAdapter tuntap tuntap.TunAdapter
multicast multicast.Multicast multicast multicast.Multicast
admin admin.AdminSocket admin admin.AdminSocket
@ -66,47 +64,10 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config
panic(err) panic(err)
} }
} }
// Generate a new configuration - this gives us a set of sane defaults - // Generate blank configuration
// then parse the configuration we loaded above on top of it. The effect
// of this is that any configuration item that is missing from the provided
// configuration will use a sane default.
cfg := config.GenerateConfig() cfg := config.GenerateConfig()
var dat map[string]interface{} // ... and then update it with the supplied HJSON input
if err := hjson.Unmarshal(conf, &dat); err != nil { if err := cfg.UnmarshalHJSON(conf); err != nil {
panic(err)
}
// Check for fields that have changed type recently, e.g. the Listen config
// option is now a []string rather than a string
if listen, ok := dat["Listen"].(string); ok {
dat["Listen"] = []string{listen}
}
if tunnelrouting, ok := dat["TunnelRouting"].(map[string]interface{}); ok {
if c, ok := tunnelrouting["IPv4Sources"]; ok {
delete(tunnelrouting, "IPv4Sources")
tunnelrouting["IPv4LocalSubnets"] = c
}
if c, ok := tunnelrouting["IPv6Sources"]; ok {
delete(tunnelrouting, "IPv6Sources")
tunnelrouting["IPv6LocalSubnets"] = c
}
if c, ok := tunnelrouting["IPv4Destinations"]; ok {
delete(tunnelrouting, "IPv4Destinations")
tunnelrouting["IPv4RemoteSubnets"] = c
}
if c, ok := tunnelrouting["IPv6Destinations"]; ok {
delete(tunnelrouting, "IPv6Destinations")
tunnelrouting["IPv6RemoteSubnets"] = c
}
}
// Sanitise the config
confJson, err := json.Marshal(dat)
if err != nil {
panic(err)
}
json.Unmarshal(confJson, &cfg)
// Overlay our newly mapped configuration onto the autoconf node config that
// we generated above.
if err = mapstructure.Decode(dat, &cfg); err != nil {
panic(err) panic(err)
} }
return cfg return cfg
@ -119,9 +80,9 @@ func doGenconf(isjson bool) string {
var bs []byte var bs []byte
var err error var err error
if isjson { if isjson {
bs, err = json.MarshalIndent(cfg, "", " ") bs, err = cfg.MarshalJSON()
} else { } else {
bs, err = hjson.Marshal(cfg) bs, err = cfg.MarshalHJSON()
} }
if err != nil { if err != nil {
panic(err) panic(err)
@ -224,7 +185,7 @@ func main() {
n := node{} n := node{}
// Now start Yggdrasil - this starts the DHT, router, switch and other core // Now start Yggdrasil - this starts the DHT, router, switch and other core
// components needed for Yggdrasil to operate // components needed for Yggdrasil to operate
n.state, err = n.core.Start(cfg, logger) err = n.core.Start(cfg, logger)
if err != nil { if err != nil {
logger.Errorln("An error occurred during startup") logger.Errorln("An error occurred during startup")
panic(err) panic(err)
@ -232,12 +193,12 @@ func main() {
// Register the session firewall gatekeeper function // Register the session firewall gatekeeper function
n.core.SetSessionGatekeeper(n.sessionFirewall) n.core.SetSessionGatekeeper(n.sessionFirewall)
// Start the admin socket // Start the admin socket
n.admin.Init(&n.core, n.state, logger, nil) n.admin.Init(&n.core, logger, nil)
if err := n.admin.Start(); err != nil { if err := n.admin.Start(); err != nil {
logger.Errorln("An error occurred starting admin socket:", err) logger.Errorln("An error occurred starting admin socket:", err)
} }
// Start the multicast interface // Start the multicast interface
n.multicast.Init(&n.core, n.state, logger, nil) n.multicast.Init(&n.core, logger, nil)
if err := n.multicast.Start(); err != nil { if err := n.multicast.Start(); err != nil {
logger.Errorln("An error occurred starting multicast:", err) logger.Errorln("An error occurred starting multicast:", err)
} }
@ -245,7 +206,7 @@ func main() {
// Start the TUN/TAP interface // Start the TUN/TAP interface
if listener, err := n.core.ConnListen(); err == nil { if listener, err := n.core.ConnListen(); err == nil {
if dialer, err := n.core.ConnDialer(); err == nil { if dialer, err := n.core.ConnDialer(); err == nil {
n.tuntap.Init(n.state, logger, listener, dialer) n.tuntap.Init(&n.core, logger, listener, dialer)
if err := n.tuntap.Start(); err != nil { if err := n.tuntap.Start(); err != nil {
logger.Errorln("An error occurred starting TUN/TAP:", err) logger.Errorln("An error occurred starting TUN/TAP:", err)
} }
@ -281,8 +242,8 @@ func main() {
cfg = readConfig(useconf, useconffile, normaliseconf) cfg = readConfig(useconf, useconffile, normaliseconf)
logger.Infoln("Reloading configuration from", *useconffile) logger.Infoln("Reloading configuration from", *useconffile)
n.core.UpdateConfig(cfg) n.core.UpdateConfig(cfg)
n.tuntap.UpdateConfig(cfg) n.tuntap.UpdateConfig()
n.multicast.UpdateConfig(cfg) n.multicast.UpdateConfig()
} else { } else {
logger.Errorln("Reloading config at runtime is only possible with -useconffile") logger.Errorln("Reloading config at runtime is only possible with -useconffile")
} }
@ -300,18 +261,17 @@ func (n *node) shutdown() {
} }
func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool { func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool {
n.state.Mutex.RLock() current := n.core.GetConfig()
defer n.state.Mutex.RUnlock()
// Allow by default if the session firewall is disabled // Allow by default if the session firewall is disabled
if !n.state.Current.SessionFirewall.Enable { if !current.SessionFirewall.Enable {
return true return true
} }
// Prepare for checking whitelist/blacklist // Prepare for checking whitelist/blacklist
var box crypto.BoxPubKey var box crypto.BoxPubKey
// Reject blacklisted nodes // Reject blacklisted nodes
for _, b := range n.state.Current.SessionFirewall.BlacklistEncryptionPublicKeys { for _, b := range current.SessionFirewall.BlacklistEncryptionPublicKeys {
key, err := hex.DecodeString(b) key, err := hex.DecodeString(b)
if err == nil { if err == nil {
copy(box[:crypto.BoxPubKeyLen], key) copy(box[:crypto.BoxPubKeyLen], key)
@ -322,7 +282,7 @@ func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool {
} }
// Allow whitelisted nodes // Allow whitelisted nodes
for _, b := range n.state.Current.SessionFirewall.WhitelistEncryptionPublicKeys { for _, b := range current.SessionFirewall.WhitelistEncryptionPublicKeys {
key, err := hex.DecodeString(b) key, err := hex.DecodeString(b)
if err == nil { if err == nil {
copy(box[:crypto.BoxPubKeyLen], key) copy(box[:crypto.BoxPubKeyLen], key)
@ -333,7 +293,7 @@ func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool {
} }
// Allow outbound sessions if appropriate // Allow outbound sessions if appropriate
if n.state.Current.SessionFirewall.AlwaysAllowOutbound { if current.SessionFirewall.AlwaysAllowOutbound {
if initiator { if initiator {
return true return true
} }
@ -349,12 +309,12 @@ func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool {
} }
// Allow direct peers if appropriate // Allow direct peers if appropriate
if n.state.Current.SessionFirewall.AllowFromDirect && isDirectPeer { if current.SessionFirewall.AllowFromDirect && isDirectPeer {
return true return true
} }
// Allow remote nodes if appropriate // Allow remote nodes if appropriate
if n.state.Current.SessionFirewall.AllowFromRemote && !isDirectPeer { if current.SessionFirewall.AllowFromRemote && !isDirectPeer {
return true return true
} }

View file

@ -15,7 +15,6 @@ import (
"github.com/gologme/log" "github.com/gologme/log"
"github.com/yggdrasil-network/yggdrasil-go/src/address" "github.com/yggdrasil-network/yggdrasil-go/src/address"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/crypto"
"github.com/yggdrasil-network/yggdrasil-go/src/util" "github.com/yggdrasil-network/yggdrasil-go/src/util"
"github.com/yggdrasil-network/yggdrasil-go/src/version" "github.com/yggdrasil-network/yggdrasil-go/src/version"
@ -54,7 +53,7 @@ func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc func(In
} }
// init runs the initial admin setup. // init runs the initial admin setup.
func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.Logger, options interface{}) { func (a *AdminSocket) Init(c *yggdrasil.Core, log *log.Logger, options interface{}) {
a.core = c a.core = c
a.log = log a.log = log
a.reconfigure = make(chan chan error, 1) a.reconfigure = make(chan chan error, 1)
@ -62,17 +61,15 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
go func() { go func() {
for { for {
e := <-a.reconfigure e := <-a.reconfigure
current, previous := state.GetCurrent(), state.GetPrevious() if newlistenaddr := c.GetConfig().AdminListen; newlistenaddr != a.listenaddr {
if current.AdminListen != previous.AdminListen { a.listenaddr = newlistenaddr
a.listenaddr = current.AdminListen
a.Stop() a.Stop()
a.Start() a.Start()
} }
e <- nil e <- nil
} }
}() }()
current := state.GetCurrent() a.listenaddr = c.GetConfig().AdminListen
a.listenaddr = current.AdminListen
a.AddHandler("list", []string{}, func(in Info) (Info, error) { a.AddHandler("list", []string{}, func(in Info) (Info, error) {
handlers := make(map[string]interface{}) handlers := make(map[string]interface{})
for handlername, handler := range a.handlers { for handlername, handler := range a.handlers {
@ -314,6 +311,9 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
// start runs the admin API socket to listen for / respond to admin API calls. // start runs the admin API socket to listen for / respond to admin API calls.
func (a *AdminSocket) Start() error { func (a *AdminSocket) Start() error {
if a.core == nil {
return errors.New("admin socket has not been initialised, call Init first")
}
if a.listenaddr != "none" && a.listenaddr != "" { if a.listenaddr != "none" && a.listenaddr != "" {
go a.listen() go a.listen()
} }

5
src/config/admin.go Normal file
View file

@ -0,0 +1,5 @@
package config
type AdminConfig struct {
AdminListen string `comment:"Listen address for admin connections. Default is to listen for local\nconnections either on TCP/9001 or a UNIX socket depending on your\nplatform. Use this value for yggdrasilctl -endpoint=X. To disable\nthe admin socket, use the value \"none\" instead."`
}

View file

@ -2,61 +2,29 @@ package config
import ( import (
"encoding/hex" "encoding/hex"
"sync" "encoding/json"
hjson "github.com/hjson/hjson-go"
"github.com/mitchellh/mapstructure"
"github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/crypto"
"github.com/yggdrasil-network/yggdrasil-go/src/defaults" "github.com/yggdrasil-network/yggdrasil-go/src/defaults"
) )
// NodeState represents the active and previous configuration of the node and
// protects it with a mutex
type NodeState struct {
Current NodeConfig
Previous NodeConfig
Mutex sync.RWMutex
}
// Current returns the current node config
func (s *NodeState) GetCurrent() NodeConfig {
s.Mutex.RLock()
defer s.Mutex.RUnlock()
return s.Current
}
// Previous returns the previous node config
func (s *NodeState) GetPrevious() NodeConfig {
s.Mutex.RLock()
defer s.Mutex.RUnlock()
return s.Previous
}
// Replace the node configuration with new configuration. This method returns
// both the new and the previous node configs
func (s *NodeState) Replace(n NodeConfig) {
s.Mutex.Lock()
defer s.Mutex.Unlock()
s.Previous = s.Current
s.Current = n
}
// NodeConfig defines all configuration values needed to run a signle yggdrasil node // NodeConfig defines all configuration values needed to run a signle yggdrasil node
type NodeConfig struct { type NodeConfig struct {
Peers []string `comment:"List of connection strings for outbound peer connections in URI format,\ne.g. tcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. These connections\nwill obey the operating system routing table, therefore you should\nuse this section when you may connect via different interfaces."` Peers []string `comment:"List of connection strings for outbound peer connections in URI format,\ne.g. tcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. These connections\nwill obey the operating system routing table, therefore you should\nuse this section when you may connect via different interfaces."`
InterfacePeers map[string][]string `comment:"List of connection strings for outbound peer connections in URI format,\narranged by source interface, e.g. { \"eth0\": [ tcp://a.b.c.d:e ] }.\nNote that SOCKS peerings will NOT be affected by this option and should\ngo in the \"Peers\" section instead."` InterfacePeers map[string][]string `comment:"List of connection strings for outbound peer connections in URI format,\narranged by source interface, e.g. { \"eth0\": [ tcp://a.b.c.d:e ] }.\nNote that SOCKS peerings will NOT be affected by this option and should\ngo in the \"Peers\" section instead."`
Listen []string `comment:"Listen addresses for incoming connections. You will need to add\nlisteners in order to accept incoming peerings from non-local nodes.\nMulticast peer discovery will work regardless of any listeners set\nhere. Each listener should be specified in URI format as above, e.g.\ntcp://0.0.0.0:0 or tcp://[::]:0 to listen on all interfaces."` Listen []string `comment:"Listen addresses for incoming connections. You will need to add\nlisteners in order to accept incoming peerings from non-local nodes.\nMulticast peer discovery will work regardless of any listeners set\nhere. Each listener should be specified in URI format as above, e.g.\ntcp://0.0.0.0:0 or tcp://[::]:0 to listen on all interfaces."`
AdminListen string `comment:"Listen address for admin connections. Default is to listen for local\nconnections either on TCP/9001 or a UNIX socket depending on your\nplatform. Use this value for yggdrasilctl -endpoint=X. To disable\nthe admin socket, use the value \"none\" instead."` AdminConfig ``
MulticastInterfaces []string `comment:"Regular expressions for which interfaces multicast peer discovery\nshould be enabled on. If none specified, multicast peer discovery is\ndisabled. The default value is .* which uses all interfaces."` MulticastConfig ``
AllowedEncryptionPublicKeys []string `comment:"List of peer encryption public keys to allow incoming TCP peering\nconnections from. If left empty/undefined then all connections will\nbe allowed by default. This does not affect outgoing peerings, nor\ndoes it affect link-local peers discovered via multicast."` AllowedEncryptionPublicKeys []string `comment:"List of peer encryption public keys to allow incoming TCP peering\nconnections from. If left empty/undefined then all connections will\nbe allowed by default. This does not affect outgoing peerings, nor\ndoes it affect link-local peers discovered via multicast."`
EncryptionPublicKey string `comment:"Your public encryption key. Your peers may ask you for this to put\ninto their AllowedEncryptionPublicKeys configuration."` EncryptionPublicKey string `comment:"Your public encryption key. Your peers may ask you for this to put\ninto their AllowedEncryptionPublicKeys configuration."`
EncryptionPrivateKey string `comment:"Your private encryption key. DO NOT share this with anyone!"` EncryptionPrivateKey string `comment:"Your private encryption key. DO NOT share this with anyone!"`
SigningPublicKey string `comment:"Your public signing key. You should not ordinarily need to share\nthis with anyone."` SigningPublicKey string `comment:"Your public signing key. You should not ordinarily need to share\nthis with anyone."`
SigningPrivateKey string `comment:"Your private signing key. DO NOT share this with anyone!"` SigningPrivateKey string `comment:"Your private signing key. DO NOT share this with anyone!"`
LinkLocalTCPPort uint16 `comment:"The port number to be used for the link-local TCP listeners for the\nconfigured MulticastInterfaces. This option does not affect listeners\nspecified in the Listen option. Unless you plan to firewall link-local\ntraffic, it is best to leave this as the default value of 0. This\noption cannot currently be changed by reloading config during runtime."` LinkLocalTCPPort uint16 `comment:"The port number to be used for the link-local TCP listeners for the\nconfigured MulticastInterfaces. This option does not affect listeners\nspecified in the Listen option. Unless you plan to firewall link-local\ntraffic, it is best to leave this as the default value of 0. This\noption cannot currently be changed by reloading config during runtime."`
IfName string `comment:"Local network interface name for TUN/TAP adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN/TAP."` TunTapConfig ``
IfTAPMode bool `comment:"Set local network interface to TAP mode rather than TUN mode if\nsupported by your platform - option will be ignored if not."`
IfMTU int `comment:"Maximux Transmission Unit (MTU) size for your local TUN/TAP interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."`
SessionFirewall SessionFirewall `comment:"The session firewall controls who can send/receive network traffic\nto/from. This is useful if you want to protect this node without\nresorting to using a real firewall. This does not affect traffic\nbeing routed via this node to somewhere else. Rules are prioritised as\nfollows: blacklist, whitelist, always allow outgoing, direct, remote."` SessionFirewall SessionFirewall `comment:"The session firewall controls who can send/receive network traffic\nto/from. This is useful if you want to protect this node without\nresorting to using a real firewall. This does not affect traffic\nbeing routed via this node to somewhere else. Rules are prioritised as\nfollows: blacklist, whitelist, always allow outgoing, direct, remote."`
TunnelRouting TunnelRouting `comment:"Allow tunneling non-Yggdrasil traffic over Yggdrasil. This effectively\nallows you to use Yggdrasil to route to, or to bridge other networks,\nsimilar to a VPN tunnel. Tunnelling works between any two nodes and\ndoes not require them to be directly peered."`
SwitchOptions SwitchOptions `comment:"Advanced options for tuning the switch. Normally you will not need\nto edit these options."` SwitchOptions SwitchOptions `comment:"Advanced options for tuning the switch. Normally you will not need\nto edit these options."`
NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."` NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."`
NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."` NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."`
@ -72,15 +40,6 @@ type SessionFirewall struct {
BlacklistEncryptionPublicKeys []string `comment:"List of public keys from which network traffic is always rejected,\nregardless of the whitelist, AllowFromDirect or AllowFromRemote."` BlacklistEncryptionPublicKeys []string `comment:"List of public keys from which network traffic is always rejected,\nregardless of the whitelist, AllowFromDirect or AllowFromRemote."`
} }
// TunnelRouting contains the crypto-key routing tables for tunneling
type TunnelRouting struct {
Enable bool `comment:"Enable or disable tunnel routing."`
IPv6RemoteSubnets map[string]string `comment:"IPv6 subnets belonging to remote nodes, mapped to the node's public\nkey, e.g. { \"aaaa:bbbb:cccc::/e\": \"boxpubkey\", ... }"`
IPv6LocalSubnets []string `comment:"IPv6 subnets belonging to this node's end of the tunnels. Only traffic\nfrom these ranges (or the Yggdrasil node's IPv6 address/subnet)\nwill be tunnelled."`
IPv4RemoteSubnets map[string]string `comment:"IPv4 subnets belonging to remote nodes, mapped to the node's public\nkey, e.g. { \"a.b.c.d/e\": \"boxpubkey\", ... }"`
IPv4LocalSubnets []string `comment:"IPv4 subnets belonging to this node's end of the tunnels. Only traffic\nfrom these ranges will be tunnelled."`
}
// SwitchOptions contains tuning options for the switch // SwitchOptions contains tuning options for the switch
type SwitchOptions struct { type SwitchOptions struct {
MaxTotalQueueSize uint64 `comment:"Maximum size of all switch queues combined (in bytes)."` MaxTotalQueueSize uint64 `comment:"Maximum size of all switch queues combined (in bytes)."`
@ -137,3 +96,83 @@ func (cfg *NodeConfig) NewSigningKeys() {
cfg.SigningPublicKey = hex.EncodeToString(spub[:]) cfg.SigningPublicKey = hex.EncodeToString(spub[:])
cfg.SigningPrivateKey = hex.EncodeToString(spriv[:]) cfg.SigningPrivateKey = hex.EncodeToString(spriv[:])
} }
// MarshalJSON exports the configuration into JSON format. No comments are
// included in the JSON export as comments are not valid in pure JSON.
func (cfg *NodeConfig) MarshalJSON() ([]byte, error) {
bs, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return nil, err
}
return bs, nil
}
// MarshalHJSON exports the configuration into HJSON format, complete with
// comments describing what each configuration item does.
func (cfg *NodeConfig) MarshalHJSON() ([]byte, error) {
bs, err := hjson.Marshal(cfg)
if err != nil {
return nil, err
}
return bs, nil
}
// UnmarshalJSON parses the configuration in pure JSON format and updates the
// NodeConfig accordingly. The input JSON can be partial - only supplied fields
// will be updated.
func (cfg *NodeConfig) UnmarshalJSON(conf []byte) error {
var dat map[string]interface{}
if err := json.Unmarshal(conf, &dat); err != nil {
return err
}
return cfg.decodeConfig(dat)
}
// UnmarshalHJSON parses the configuration in HJSON format and updates the
// NodeConfig accordingly. The input HJSON can be partial - only supplied fields
// will be updated.
func (cfg *NodeConfig) UnmarshalHJSON(conf []byte) error {
var dat map[string]interface{}
if err := hjson.Unmarshal(conf, &dat); err != nil {
return err
}
return cfg.decodeConfig(dat)
}
func (cfg *NodeConfig) decodeConfig(dat map[string]interface{}) error {
// Check for fields that have changed type recently, e.g. the Listen config
// option is now a []string rather than a string
if listen, ok := dat["Listen"].(string); ok {
dat["Listen"] = []string{listen}
}
if tunnelrouting, ok := dat["TunnelRouting"].(map[string]interface{}); ok {
if c, ok := tunnelrouting["IPv4Sources"]; ok {
delete(tunnelrouting, "IPv4Sources")
tunnelrouting["IPv4LocalSubnets"] = c
}
if c, ok := tunnelrouting["IPv6Sources"]; ok {
delete(tunnelrouting, "IPv6Sources")
tunnelrouting["IPv6LocalSubnets"] = c
}
if c, ok := tunnelrouting["IPv4Destinations"]; ok {
delete(tunnelrouting, "IPv4Destinations")
tunnelrouting["IPv4RemoteSubnets"] = c
}
if c, ok := tunnelrouting["IPv6Destinations"]; ok {
delete(tunnelrouting, "IPv6Destinations")
tunnelrouting["IPv6RemoteSubnets"] = c
}
}
// Sanitise the config
/*confJson, err := json.Marshal(dat)
if err != nil {
return err
}
json.Unmarshal(confJson, &cfg)*/
// Overlay our newly mapped configuration onto the autoconf node config that
// we generated above.
if err := mapstructure.Decode(dat, &cfg); err != nil {
return err
}
return nil
}

5
src/config/multicast.go Normal file
View file

@ -0,0 +1,5 @@
package config
type MulticastConfig struct {
MulticastInterfaces []string `comment:"Regular expressions for which interfaces multicast peer discovery\nshould be enabled on. If none specified, multicast peer discovery is\ndisabled. The default value is .* which uses all interfaces."`
}

17
src/config/tuntap.go Normal file
View file

@ -0,0 +1,17 @@
package config
type TunTapConfig struct {
IfName string `comment:"Local network interface name for TUN/TAP adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN/TAP."`
IfTAPMode bool `comment:"Set local network interface to TAP mode rather than TUN mode if\nsupported by your platform - option will be ignored if not."`
IfMTU int `comment:"Maximux Transmission Unit (MTU) size for your local TUN/TAP interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."`
TunnelRouting TunnelRouting `comment:"Allow tunneling non-Yggdrasil traffic over Yggdrasil. This effectively\nallows you to use Yggdrasil to route to, or to bridge other networks,\nsimilar to a VPN tunnel. Tunnelling works between any two nodes and\ndoes not require them to be directly peered."`
}
// TunnelRouting contains the crypto-key routing tables for tunneling
type TunnelRouting struct {
Enable bool `comment:"Enable or disable tunnel routing."`
IPv6RemoteSubnets map[string]string `comment:"IPv6 subnets belonging to remote nodes, mapped to the node's public\nkey, e.g. { \"aaaa:bbbb:cccc::/e\": \"boxpubkey\", ... }"`
IPv6LocalSubnets []string `comment:"IPv6 subnets belonging to this node's end of the tunnels. Only traffic\nfrom these ranges (or the Yggdrasil node's IPv6 address/subnet)\nwill be tunnelled."`
IPv4RemoteSubnets map[string]string `comment:"IPv4 subnets belonging to remote nodes, mapped to the node's public\nkey, e.g. { \"a.b.c.d/e\": \"boxpubkey\", ... }"`
IPv4LocalSubnets []string `comment:"IPv4 subnets belonging to this node's end of the tunnels. Only traffic\nfrom these ranges will be tunnelled."`
}

View file

@ -2,6 +2,7 @@ package multicast
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"net" "net"
"regexp" "regexp"
@ -9,7 +10,6 @@ import (
"github.com/gologme/log" "github.com/gologme/log"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
) )
@ -20,7 +20,6 @@ import (
// automatically. // automatically.
type Multicast struct { type Multicast struct {
core *yggdrasil.Core core *yggdrasil.Core
config *config.NodeState
log *log.Logger log *log.Logger
sock *ipv6.PacketConn sock *ipv6.PacketConn
groupAddr string groupAddr string
@ -30,13 +29,11 @@ type Multicast struct {
} }
// Init prepares the multicast interface for use. // Init prepares the multicast interface for use.
func (m *Multicast) Init(core *yggdrasil.Core, state *config.NodeState, log *log.Logger, options interface{}) error { func (m *Multicast) Init(core *yggdrasil.Core, log *log.Logger, options interface{}) error {
m.core = core m.core = core
m.config = state
m.log = log m.log = log
m.listeners = make(map[string]*yggdrasil.TcpListener) m.listeners = make(map[string]*yggdrasil.TcpListener)
current := m.config.GetCurrent() m.listenPort = m.core.GetConfig().LinkLocalTCPPort
m.listenPort = current.LinkLocalTCPPort
m.groupAddr = "[ff02::114]:9001" m.groupAddr = "[ff02::114]:9001"
return nil return nil
} }
@ -45,6 +42,9 @@ func (m *Multicast) Init(core *yggdrasil.Core, state *config.NodeState, log *log
// listen for multicast beacons from other hosts and will advertise multicast // listen for multicast beacons from other hosts and will advertise multicast
// beacons out to the network. // beacons out to the network.
func (m *Multicast) Start() error { func (m *Multicast) Start() error {
if m.core == nil {
return errors.New("multicast has not been initialised, call Init first")
}
addr, err := net.ResolveUDPAddr("udp", m.groupAddr) addr, err := net.ResolveUDPAddr("udp", m.groupAddr)
if err != nil { if err != nil {
return err return err
@ -80,9 +80,8 @@ func (m *Multicast) Stop() error {
// UpdateConfig updates the multicast module with the provided config.NodeConfig // UpdateConfig updates the multicast module with the provided config.NodeConfig
// and then signals the various module goroutines to reconfigure themselves if // and then signals the various module goroutines to reconfigure themselves if
// needed. // needed.
func (m *Multicast) UpdateConfig(config *config.NodeConfig) { func (m *Multicast) UpdateConfig() {
m.log.Debugln("Reloading multicast configuration...")
m.config.Replace(*config)
} }
// GetInterfaces returns the currently known/enabled multicast interfaces. It is // GetInterfaces returns the currently known/enabled multicast interfaces. It is
@ -91,7 +90,7 @@ func (m *Multicast) UpdateConfig(config *config.NodeConfig) {
func (m *Multicast) Interfaces() map[string]net.Interface { func (m *Multicast) Interfaces() map[string]net.Interface {
interfaces := make(map[string]net.Interface) interfaces := make(map[string]net.Interface)
// Get interface expressions from config // Get interface expressions from config
current := m.config.GetCurrent() current := m.core.GetConfig()
exprs := current.MulticastInterfaces exprs := current.MulticastInterfaces
// Ask the system for network interfaces // Ask the system for network interfaces
allifaces, err := net.Interfaces() allifaces, err := net.Interfaces()

View file

@ -44,7 +44,7 @@ func (c *cryptokey) init(tun *TunAdapter) {
// Configure the CKR routes. This should only ever be ran by the TUN/TAP actor. // Configure the CKR routes. This should only ever be ran by the TUN/TAP actor.
func (c *cryptokey) configure() { func (c *cryptokey) configure() {
current := c.tun.config.GetCurrent() current := c.tun.core.GetConfig()
// Set enabled/disabled state // Set enabled/disabled state
c.setEnabled(current.TunnelRouting.Enable) c.setEnabled(current.TunnelRouting.Enable)

View file

@ -21,7 +21,6 @@ import (
"github.com/yggdrasil-network/water" "github.com/yggdrasil-network/water"
"github.com/yggdrasil-network/yggdrasil-go/src/address" "github.com/yggdrasil-network/yggdrasil-go/src/address"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/crypto"
"github.com/yggdrasil-network/yggdrasil-go/src/defaults" "github.com/yggdrasil-network/yggdrasil-go/src/defaults"
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
@ -35,9 +34,9 @@ const tun_ETHER_HEADER_LENGTH = 14
// you should pass this object to the yggdrasil.SetRouterAdapter() function // you should pass this object to the yggdrasil.SetRouterAdapter() function
// before calling yggdrasil.Start(). // before calling yggdrasil.Start().
type TunAdapter struct { type TunAdapter struct {
core *yggdrasil.Core
writer tunWriter writer tunWriter
reader tunReader reader tunReader
config *config.NodeState
log *log.Logger log *log.Logger
reconfigure chan chan error reconfigure chan chan error
listener *yggdrasil.Listener listener *yggdrasil.Listener
@ -110,8 +109,8 @@ func MaximumMTU() int {
// Init initialises the TUN/TAP module. You must have acquired a Listener from // Init initialises the TUN/TAP module. You must have acquired a Listener from
// the Yggdrasil core before this point and it must not be in use elsewhere. // the Yggdrasil core before this point and it must not be in use elsewhere.
func (tun *TunAdapter) Init(config *config.NodeState, log *log.Logger, listener *yggdrasil.Listener, dialer *yggdrasil.Dialer) { func (tun *TunAdapter) Init(c *yggdrasil.Core, log *log.Logger, listener *yggdrasil.Listener, dialer *yggdrasil.Dialer) {
tun.config = config tun.core = c
tun.log = log tun.log = log
tun.listener = listener tun.listener = listener
tun.dialer = dialer tun.dialer = dialer
@ -133,9 +132,9 @@ func (tun *TunAdapter) Start() error {
} }
func (tun *TunAdapter) _start() error { func (tun *TunAdapter) _start() error {
current := tun.config.GetCurrent() current := tun.core.GetConfig()
if tun.config == nil || tun.listener == nil || tun.dialer == nil { if tun.core == nil || tun.listener == nil || tun.dialer == nil {
return errors.New("No configuration available to TUN/TAP") return errors.New("TUN/TAP has not been initialised, call Init first")
} }
var boxPub crypto.BoxPubKey var boxPub crypto.BoxPubKey
boxPubHex, err := hex.DecodeString(current.EncryptionPublicKey) boxPubHex, err := hex.DecodeString(current.EncryptionPublicKey)
@ -200,12 +199,9 @@ func (tun *TunAdapter) _stop() error {
// UpdateConfig updates the TUN/TAP module with the provided config.NodeConfig // UpdateConfig updates the TUN/TAP module with the provided config.NodeConfig
// and then signals the various module goroutines to reconfigure themselves if // and then signals the various module goroutines to reconfigure themselves if
// needed. // needed.
func (tun *TunAdapter) UpdateConfig(config *config.NodeConfig) { func (tun *TunAdapter) UpdateConfig() {
tun.log.Debugln("Reloading TUN/TAP configuration...") tun.log.Debugln("Reloading TUN/TAP configuration...")
// Replace the active configuration with the supplied one
tun.config.Replace(*config)
// Notify children about the configuration change // Notify children about the configuration change
tun.Act(nil, tun.ckr.configure) tun.Act(nil, tun.ckr.configure)
} }

View file

@ -370,13 +370,12 @@ func (c *Core) AddPeer(addr string, sintf string) error {
if err := c.CallPeer(addr, sintf); err != nil { if err := c.CallPeer(addr, sintf); err != nil {
return err return err
} }
c.config.Mutex.Lock() config := c.GetConfig()
if sintf == "" { if sintf == "" {
c.config.Current.Peers = append(c.config.Current.Peers, addr) config.Peers = append(config.Peers, addr)
} else { } else {
c.config.Current.InterfacePeers[sintf] = append(c.config.Current.InterfacePeers[sintf], addr) config.InterfacePeers[sintf] = append(config.InterfacePeers[sintf], addr)
} }
c.config.Mutex.Unlock()
return nil return nil
} }

View file

@ -4,6 +4,7 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"io/ioutil" "io/ioutil"
"sync/atomic"
"time" "time"
"github.com/Arceliar/phony" "github.com/Arceliar/phony"
@ -21,7 +22,7 @@ type Core struct {
// We're going to keep our own copy of the provided config - that way we can // We're going to keep our own copy of the provided config - that way we can
// guarantee that it will be covered by the mutex // guarantee that it will be covered by the mutex
phony.Inbox phony.Inbox
config config.NodeState // Config config atomic.Value // *config.NodeConfig
boxPub crypto.BoxPubKey boxPub crypto.BoxPubKey
boxPriv crypto.BoxPrivKey boxPriv crypto.BoxPrivKey
sigPub crypto.SigPubKey sigPub crypto.SigPubKey
@ -42,7 +43,7 @@ func (c *Core) _init() error {
c.log = log.New(ioutil.Discard, "", 0) c.log = log.New(ioutil.Discard, "", 0)
} }
current := c.config.GetCurrent() current := c.config.Load().(*config.NodeConfig)
boxPrivHex, err := hex.DecodeString(current.EncryptionPrivateKey) boxPrivHex, err := hex.DecodeString(current.EncryptionPrivateKey)
if err != nil { if err != nil {
@ -87,7 +88,7 @@ func (c *Core) _init() error {
// be reconnected with. // be reconnected with.
func (c *Core) _addPeerLoop() { func (c *Core) _addPeerLoop() {
// Get the peers from the config - these could change! // Get the peers from the config - these could change!
current := c.config.GetCurrent() current := c.GetConfig()
// Add peers from the Peers section // Add peers from the Peers section
for _, peer := range current.Peers { for _, peer := range current.Peers {
@ -109,6 +110,11 @@ func (c *Core) _addPeerLoop() {
}) })
} }
// GetConfig atomically returns the current active node configuration.
func (c *Core) GetConfig() *config.NodeConfig {
return c.config.Load().(*config.NodeConfig)
}
// UpdateConfig updates the configuration in Core with the provided // UpdateConfig updates the configuration in Core with the provided
// config.NodeConfig and then signals the various module goroutines to // config.NodeConfig and then signals the various module goroutines to
// reconfigure themselves if needed. // reconfigure themselves if needed.
@ -116,12 +122,16 @@ func (c *Core) UpdateConfig(config *config.NodeConfig) {
c.Act(nil, func() { c.Act(nil, func() {
c.log.Debugln("Reloading node configuration...") c.log.Debugln("Reloading node configuration...")
// Replace the active configuration with the supplied one new, old := config, c.GetConfig()
c.config.Replace(*config) c.config.Store(new)
// Notify the router and switch about the new configuration // Notify the router and switch about the new configuration
c.router.Act(c, c.router.reconfigure) c.router.Act(c, func() {
c.switchTable.Act(c, c.switchTable.reconfigure) c.router.reconfigure(new, old)
})
c.switchTable.Act(c, func() {
c.switchTable.reconfigure(new, old)
})
}) })
} }
@ -130,21 +140,17 @@ func (c *Core) UpdateConfig(config *config.NodeConfig) {
// TCP and UDP sockets, a multicast discovery socket, an admin socket, router, // TCP and UDP sockets, a multicast discovery socket, an admin socket, router,
// switch and DHT node. A config.NodeState is returned which contains both the // switch and DHT node. A config.NodeState is returned which contains both the
// current and previous configurations (from reconfigures). // current and previous configurations (from reconfigures).
func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) (conf *config.NodeState, err error) { func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) (err error) {
phony.Block(c, func() { phony.Block(c, func() {
conf, err = c._start(nc, log) err = c._start(nc, log)
}) })
return return
} }
// This function is unsafe and should only be ran by the core actor. // This function is unsafe and should only be ran by the core actor.
func (c *Core) _start(nc *config.NodeConfig, log *log.Logger) (*config.NodeState, error) { func (c *Core) _start(nc *config.NodeConfig, log *log.Logger) error {
c.log = log c.log = log
c.config.Store(nc)
c.config = config.NodeState{
Current: *nc,
Previous: *nc,
}
if name := version.BuildName(); name != "unknown" { if name := version.BuildName(); name != "unknown" {
c.log.Infoln("Build name:", name) c.log.Infoln("Build name:", name)
@ -158,23 +164,23 @@ func (c *Core) _start(nc *config.NodeConfig, log *log.Logger) (*config.NodeState
if err := c.link.init(c); err != nil { if err := c.link.init(c); err != nil {
c.log.Errorln("Failed to start link interfaces") c.log.Errorln("Failed to start link interfaces")
return nil, err return err
} }
if err := c.switchTable.start(); err != nil { if err := c.switchTable.start(); err != nil {
c.log.Errorln("Failed to start switch") c.log.Errorln("Failed to start switch")
return nil, err return err
} }
if err := c.router.start(); err != nil { if err := c.router.start(); err != nil {
c.log.Errorln("Failed to start router") c.log.Errorln("Failed to start router")
return nil, err return err
} }
c.Act(c, c._addPeerLoop) c.Act(c, c._addPeerLoop)
c.log.Infoln("Startup complete") c.log.Infoln("Startup complete")
return &c.config, nil return nil
} }
// Stop shuts down the Yggdrasil node. // Stop shuts down the Yggdrasil node.

View file

@ -14,6 +14,7 @@ import (
"time" "time"
"github.com/yggdrasil-network/yggdrasil-go/src/address" "github.com/yggdrasil-network/yggdrasil-go/src/address"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/crypto"
"github.com/yggdrasil-network/yggdrasil-go/src/util" "github.com/yggdrasil-network/yggdrasil-go/src/util"
@ -79,8 +80,8 @@ func (l *link) init(c *Core) error {
return nil return nil
} }
func (l *link) reconfigure() { func (l *link) reconfigure(current, previous *config.NodeConfig) {
l.tcp.reconfigure() l.tcp.reconfigure(current, previous)
} }
func (l *link) call(uri string, sintf string) error { func (l *link) call(uri string, sintf string) error {

View file

@ -10,6 +10,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/crypto"
"github.com/yggdrasil-network/yggdrasil-go/src/util" "github.com/yggdrasil-network/yggdrasil-go/src/util"
@ -34,7 +35,7 @@ func (ps *peers) init(c *Core) {
ps.core = c ps.core = c
} }
func (ps *peers) reconfigure() { func (ps *peers) reconfigure(current, previous *config.NodeConfig) {
// This is where reconfiguration would go, if we had anything to do // This is where reconfiguration would go, if we had anything to do
} }
@ -42,42 +43,34 @@ func (ps *peers) reconfigure() {
// because the key is in the whitelist or because the whitelist is empty. // because the key is in the whitelist or because the whitelist is empty.
func (ps *peers) isAllowedEncryptionPublicKey(box *crypto.BoxPubKey) bool { func (ps *peers) isAllowedEncryptionPublicKey(box *crypto.BoxPubKey) bool {
boxstr := hex.EncodeToString(box[:]) boxstr := hex.EncodeToString(box[:])
ps.core.config.Mutex.RLock() current := ps.core.GetConfig()
defer ps.core.config.Mutex.RUnlock() for _, v := range current.AllowedEncryptionPublicKeys {
for _, v := range ps.core.config.Current.AllowedEncryptionPublicKeys {
if v == boxstr { if v == boxstr {
return true return true
} }
} }
return len(ps.core.config.Current.AllowedEncryptionPublicKeys) == 0 return len(current.AllowedEncryptionPublicKeys) == 0
} }
// Adds a key to the whitelist. // Adds a key to the whitelist.
func (ps *peers) addAllowedEncryptionPublicKey(box string) { func (ps *peers) addAllowedEncryptionPublicKey(box string) {
ps.core.config.Mutex.RLock() current := ps.core.GetConfig()
defer ps.core.config.Mutex.RUnlock() current.AllowedEncryptionPublicKeys = append(current.AllowedEncryptionPublicKeys, box)
ps.core.config.Current.AllowedEncryptionPublicKeys =
append(ps.core.config.Current.AllowedEncryptionPublicKeys, box)
} }
// Removes a key from the whitelist. // Removes a key from the whitelist.
func (ps *peers) removeAllowedEncryptionPublicKey(box string) { func (ps *peers) removeAllowedEncryptionPublicKey(box string) {
ps.core.config.Mutex.RLock() current := ps.core.GetConfig()
defer ps.core.config.Mutex.RUnlock() for k, v := range current.AllowedEncryptionPublicKeys {
for k, v := range ps.core.config.Current.AllowedEncryptionPublicKeys {
if v == box { if v == box {
ps.core.config.Current.AllowedEncryptionPublicKeys = current.AllowedEncryptionPublicKeys = append(current.AllowedEncryptionPublicKeys[:k], current.AllowedEncryptionPublicKeys[k+1:]...)
append(ps.core.config.Current.AllowedEncryptionPublicKeys[:k],
ps.core.config.Current.AllowedEncryptionPublicKeys[k+1:]...)
} }
} }
} }
// Gets the whitelist of allowed keys for incoming connections. // Gets the whitelist of allowed keys for incoming connections.
func (ps *peers) getAllowedEncryptionPublicKeys() []string { func (ps *peers) getAllowedEncryptionPublicKeys() []string {
ps.core.config.Mutex.RLock() return ps.core.GetConfig().AllowedEncryptionPublicKeys
defer ps.core.config.Mutex.RUnlock()
return ps.core.config.Current.AllowedEncryptionPublicKeys
} }
// Atomically gets a map[switchPort]*peer of known peers. // Atomically gets a map[switchPort]*peer of known peers.

View file

@ -28,6 +28,7 @@ import (
"time" "time"
"github.com/yggdrasil-network/yggdrasil-go/src/address" "github.com/yggdrasil-network/yggdrasil-go/src/address"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/crypto"
"github.com/yggdrasil-network/yggdrasil-go/src/util" "github.com/yggdrasil-network/yggdrasil-go/src/util"
@ -65,9 +66,8 @@ func (r *router) init(core *Core) {
p.out = func(packets [][]byte) { r.handlePackets(p, packets) } p.out = func(packets [][]byte) { r.handlePackets(p, packets) }
r.out = func(bs []byte) { p.handlePacketFrom(r, bs) } r.out = func(bs []byte) { p.handlePacketFrom(r, bs) }
r.nodeinfo.init(r.core) r.nodeinfo.init(r.core)
r.core.config.Mutex.RLock() current := r.core.GetConfig()
r.nodeinfo.setNodeInfo(r.core.config.Current.NodeInfo, r.core.config.Current.NodeInfoPrivacy) r.nodeinfo.setNodeInfo(current.NodeInfo, current.NodeInfoPrivacy)
r.core.config.Mutex.RUnlock()
r.dht.init(r) r.dht.init(r)
r.searches.init(r) r.searches.init(r)
r.sessions.init(r) r.sessions.init(r)
@ -75,9 +75,8 @@ func (r *router) init(core *Core) {
// Reconfigures the router and any child modules. This should only ever be run // Reconfigures the router and any child modules. This should only ever be run
// by the router actor. // by the router actor.
func (r *router) reconfigure() { func (r *router) reconfigure(current, previous *config.NodeConfig) {
// Reconfigure the router // Reconfigure the router
current := r.core.config.GetCurrent()
if err := r.nodeinfo.setNodeInfo(current.NodeInfo, current.NodeInfoPrivacy); err != nil { if err := r.nodeinfo.setNodeInfo(current.NodeInfo, current.NodeInfoPrivacy); err != nil {
r.core.log.Errorln("Error reloading NodeInfo:", err) r.core.log.Errorln("Error reloading NodeInfo:", err)
} else { } else {

View file

@ -187,9 +187,7 @@ func (ss *sessions) createSession(theirPermKey *crypto.BoxPubKey) *sessionInfo {
sinfo.mySesPriv = *priv sinfo.mySesPriv = *priv
sinfo.myNonce = *crypto.NewBoxNonce() sinfo.myNonce = *crypto.NewBoxNonce()
sinfo.theirMTU = 1280 sinfo.theirMTU = 1280
ss.router.core.config.Mutex.RLock() sinfo.myMTU = uint16(ss.router.core.GetConfig().IfMTU)
sinfo.myMTU = uint16(ss.router.core.config.Current.IfMTU)
ss.router.core.config.Mutex.RUnlock()
now := time.Now() now := time.Now()
sinfo.timeOpened = now sinfo.timeOpened = now
sinfo.time = now sinfo.time = now

View file

@ -17,6 +17,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/crypto" "github.com/yggdrasil-network/yggdrasil-go/src/crypto"
"github.com/yggdrasil-network/yggdrasil-go/src/util" "github.com/yggdrasil-network/yggdrasil-go/src/util"
@ -193,22 +194,21 @@ func (t *switchTable) init(core *Core) {
t.table.Store(lookupTable{}) t.table.Store(lookupTable{})
t.drop = make(map[crypto.SigPubKey]int64) t.drop = make(map[crypto.SigPubKey]int64)
phony.Block(t, func() { phony.Block(t, func() {
core.config.Mutex.RLock() current := t.core.GetConfig()
if core.config.Current.SwitchOptions.MaxTotalQueueSize > SwitchQueueTotalMinSize { if current.SwitchOptions.MaxTotalQueueSize > SwitchQueueTotalMinSize {
t.queues.totalMaxSize = core.config.Current.SwitchOptions.MaxTotalQueueSize t.queues.totalMaxSize = current.SwitchOptions.MaxTotalQueueSize
} else { } else {
t.queues.totalMaxSize = SwitchQueueTotalMinSize t.queues.totalMaxSize = SwitchQueueTotalMinSize
} }
core.config.Mutex.RUnlock()
t.queues.bufs = make(map[string]switch_buffer) t.queues.bufs = make(map[string]switch_buffer)
t.idle = make(map[switchPort]time.Time) t.idle = make(map[switchPort]time.Time)
}) })
} }
func (t *switchTable) reconfigure() { func (t *switchTable) reconfigure(current, previous *config.NodeConfig) {
// This is where reconfiguration would go, if we had anything useful to do. // This is where reconfiguration would go, if we had anything useful to do.
t.core.link.reconfigure() t.core.link.reconfigure(current, previous)
t.core.peers.reconfigure() t.core.peers.reconfigure(current, previous)
} }
// Safely gets a copy of this node's locator. // Safely gets a copy of this node's locator.

View file

@ -25,6 +25,7 @@ import (
"golang.org/x/net/proxy" "golang.org/x/net/proxy"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/util" "github.com/yggdrasil-network/yggdrasil-go/src/util"
) )
@ -81,9 +82,7 @@ func (t *tcp) init(l *link) error {
t.listeners = make(map[string]*TcpListener) t.listeners = make(map[string]*TcpListener)
t.mutex.Unlock() t.mutex.Unlock()
t.link.core.config.Mutex.RLock() for _, listenaddr := range t.link.core.GetConfig().Listen {
defer t.link.core.config.Mutex.RUnlock()
for _, listenaddr := range t.link.core.config.Current.Listen {
if listenaddr[:6] != "tcp://" { if listenaddr[:6] != "tcp://" {
continue continue
} }
@ -95,11 +94,9 @@ func (t *tcp) init(l *link) error {
return nil return nil
} }
func (t *tcp) reconfigure() { func (t *tcp) reconfigure(current, previous *config.NodeConfig) {
t.link.core.config.Mutex.RLock() added := util.Difference(current.Listen, previous.Listen)
added := util.Difference(t.link.core.config.Current.Listen, t.link.core.config.Previous.Listen) deleted := util.Difference(previous.Listen, current.Listen)
deleted := util.Difference(t.link.core.config.Previous.Listen, t.link.core.config.Current.Listen)
t.link.core.config.Mutex.RUnlock()
if len(added) > 0 || len(deleted) > 0 { if len(added) > 0 || len(deleted) > 0 {
for _, a := range added { for _, a := range added {
if a[:6] != "tcp://" { if a[:6] != "tcp://" {