mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-25 23:01:38 +00:00
Define module.Module interface, update admin/tuntap/multicast modules to comply with it, fix #581
This commit is contained in:
parent
fc71624919
commit
a072e063d8
@ -23,6 +23,7 @@ import (
|
|||||||
"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"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/module"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/tuntap"
|
"github.com/yggdrasil-network/yggdrasil-go/src/tuntap"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
||||||
@ -32,9 +33,9 @@ import (
|
|||||||
type node struct {
|
type node struct {
|
||||||
core yggdrasil.Core
|
core yggdrasil.Core
|
||||||
state *config.NodeState
|
state *config.NodeState
|
||||||
tuntap tuntap.TunAdapter
|
tuntap module.Module // tuntap.TunAdapter
|
||||||
multicast multicast.Multicast
|
multicast module.Module // multicast.Multicast
|
||||||
admin admin.AdminSocket
|
admin module.Module // admin.AdminSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config.NodeConfig {
|
func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config.NodeConfig {
|
||||||
@ -231,25 +232,30 @@ func main() {
|
|||||||
}
|
}
|
||||||
// Register the session firewall gatekeeper function
|
// Register the session firewall gatekeeper function
|
||||||
n.core.SetSessionGatekeeper(n.sessionFirewall)
|
n.core.SetSessionGatekeeper(n.sessionFirewall)
|
||||||
|
// Allocate our modules
|
||||||
|
n.admin = &admin.AdminSocket{}
|
||||||
|
n.multicast = &multicast.Multicast{}
|
||||||
|
n.tuntap = &tuntap.TunAdapter{}
|
||||||
// Start the admin socket
|
// Start the admin socket
|
||||||
n.admin.Init(&n.core, n.state, logger, nil)
|
n.admin.Init(&n.core, n.state, 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)
|
||||||
}
|
}
|
||||||
|
n.admin.SetupAdminHandlers(n.admin.(*admin.AdminSocket))
|
||||||
// Start the multicast interface
|
// Start the multicast interface
|
||||||
n.multicast.Init(&n.core, n.state, logger, nil)
|
n.multicast.Init(&n.core, n.state, 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)
|
||||||
}
|
}
|
||||||
n.multicast.SetupAdminHandlers(&n.admin)
|
n.multicast.SetupAdminHandlers(n.admin.(*admin.AdminSocket))
|
||||||
// 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, n.state, logger, tuntap.TunOptions{Listener: listener, Dialer: 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)
|
||||||
}
|
}
|
||||||
n.tuntap.SetupAdminHandlers(&n.admin)
|
n.tuntap.SetupAdminHandlers(n.admin.(*admin.AdminSocket))
|
||||||
} else {
|
} else {
|
||||||
logger.Errorln("Unable to get Dialer:", err)
|
logger.Errorln("Unable to get Dialer:", err)
|
||||||
}
|
}
|
||||||
|
2
go.mod
2
go.mod
@ -17,3 +17,5 @@ require (
|
|||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a
|
||||||
golang.org/x/text v0.3.2
|
golang.org/x/text v0.3.2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
@ -25,12 +25,12 @@ import (
|
|||||||
// TODO: Add authentication
|
// TODO: Add authentication
|
||||||
|
|
||||||
type AdminSocket struct {
|
type AdminSocket struct {
|
||||||
core *yggdrasil.Core
|
core *yggdrasil.Core
|
||||||
log *log.Logger
|
log *log.Logger
|
||||||
reconfigure chan chan error
|
listenaddr string
|
||||||
listenaddr string
|
listener net.Listener
|
||||||
listener net.Listener
|
handlers map[string]handler
|
||||||
handlers map[string]handler
|
started bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info refers to information that is returned to the admin socket handler.
|
// Info refers to information that is returned to the admin socket handler.
|
||||||
@ -54,25 +54,27 @@ 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, state *config.NodeState, log *log.Logger, options interface{}) error {
|
||||||
a.core = c
|
a.core = c
|
||||||
a.log = log
|
a.log = log
|
||||||
a.reconfigure = make(chan chan error, 1)
|
|
||||||
a.handlers = make(map[string]handler)
|
a.handlers = make(map[string]handler)
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
e := <-a.reconfigure
|
|
||||||
current, previous := state.GetCurrent(), state.GetPrevious()
|
|
||||||
if current.AdminListen != previous.AdminListen {
|
|
||||||
a.listenaddr = current.AdminListen
|
|
||||||
a.Stop()
|
|
||||||
a.Start()
|
|
||||||
}
|
|
||||||
e <- nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
current := state.GetCurrent()
|
current := state.GetCurrent()
|
||||||
a.listenaddr = current.AdminListen
|
a.listenaddr = current.AdminListen
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AdminSocket) UpdateConfig(config *config.NodeConfig) {
|
||||||
|
a.log.Debugln("Reloading admin configuration...")
|
||||||
|
if a.listenaddr != config.AdminListen {
|
||||||
|
a.listenaddr = config.AdminListen
|
||||||
|
if a.IsStarted() {
|
||||||
|
a.Stop()
|
||||||
|
}
|
||||||
|
a.Start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) {
|
||||||
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 {
|
||||||
@ -81,15 +83,15 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
return Info{"list": handlers}, nil
|
return Info{"list": handlers}, nil
|
||||||
})
|
})
|
||||||
a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) {
|
a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) {
|
||||||
ip := c.Address().String()
|
ip := a.core.Address().String()
|
||||||
subnet := c.Subnet()
|
subnet := a.core.Subnet()
|
||||||
return Info{
|
return Info{
|
||||||
"self": Info{
|
"self": Info{
|
||||||
ip: Info{
|
ip: Info{
|
||||||
"box_pub_key": c.EncryptionPublicKey(),
|
"box_pub_key": a.core.EncryptionPublicKey(),
|
||||||
"build_name": version.BuildName(),
|
"build_name": version.BuildName(),
|
||||||
"build_version": version.BuildVersion(),
|
"build_version": version.BuildVersion(),
|
||||||
"coords": fmt.Sprintf("%v", c.Coords()),
|
"coords": fmt.Sprintf("%v", a.core.Coords()),
|
||||||
"subnet": subnet.String(),
|
"subnet": subnet.String(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -312,17 +314,24 @@ 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.listenaddr != "none" && a.listenaddr != "" {
|
if a.listenaddr != "none" && a.listenaddr != "" {
|
||||||
go a.listen()
|
go a.listen()
|
||||||
|
a.started = true
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleans up when stopping
|
// IsStarted returns true if the module has been started.
|
||||||
|
func (a *AdminSocket) IsStarted() bool {
|
||||||
|
return a.started
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop will stop the admin API and close the socket.
|
||||||
func (a *AdminSocket) Stop() error {
|
func (a *AdminSocket) Stop() error {
|
||||||
if a.listener != nil {
|
if a.listener != nil {
|
||||||
|
a.started = false
|
||||||
return a.listener.Close()
|
return a.listener.Close()
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
|
20
src/module/module.go
Normal file
20
src/module/module.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package module
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gologme/log"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Module is an interface that defines which functions must be supported by a
|
||||||
|
// given Yggdrasil module.
|
||||||
|
type Module interface {
|
||||||
|
Init(core *yggdrasil.Core, state *config.NodeState, log *log.Logger, options interface{}) error
|
||||||
|
Start() error
|
||||||
|
Stop() error
|
||||||
|
UpdateConfig(config *config.NodeConfig)
|
||||||
|
SetupAdminHandlers(a *admin.AdminSocket)
|
||||||
|
IsStarted() bool
|
||||||
|
}
|
@ -55,6 +55,12 @@ 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 len(m.config.GetCurrent().MulticastInterfaces) == 0 {
|
||||||
|
return fmt.Errorf("no MulticastInterfaces configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
m.log.Infoln("Starting multicast module")
|
||||||
|
|
||||||
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,8 +86,14 @@ func (m *Multicast) Start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsStarted returns true if the module has been started.
|
||||||
|
func (m *Multicast) IsStarted() bool {
|
||||||
|
return m.isOpen
|
||||||
|
}
|
||||||
|
|
||||||
// Stop is not implemented for multicast yet.
|
// Stop is not implemented for multicast yet.
|
||||||
func (m *Multicast) Stop() error {
|
func (m *Multicast) Stop() error {
|
||||||
|
m.log.Infoln("Stopping multicast module")
|
||||||
m.isOpen = false
|
m.isOpen = false
|
||||||
if m.announcer != nil {
|
if m.announcer != nil {
|
||||||
m.announcer.Stop()
|
m.announcer.Stop()
|
||||||
@ -98,7 +110,16 @@ func (m *Multicast) Stop() error {
|
|||||||
// needed.
|
// needed.
|
||||||
func (m *Multicast) UpdateConfig(config *config.NodeConfig) {
|
func (m *Multicast) UpdateConfig(config *config.NodeConfig) {
|
||||||
m.log.Debugln("Reloading multicast configuration...")
|
m.log.Debugln("Reloading multicast configuration...")
|
||||||
|
if m.IsStarted() {
|
||||||
|
if len(config.MulticastInterfaces) == 0 || config.LinkLocalTCPPort != m.listenPort {
|
||||||
|
m.Stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
m.config.Replace(*config)
|
m.config.Replace(*config)
|
||||||
|
m.listenPort = config.LinkLocalTCPPort
|
||||||
|
if !m.IsStarted() && len(config.MulticastInterfaces) > 0 {
|
||||||
|
m.Start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInterfaces returns the currently known/enabled multicast interfaces. It is
|
// GetInterfaces returns the currently known/enabled multicast interfaces. It is
|
||||||
|
@ -56,6 +56,11 @@ type TunAdapter struct {
|
|||||||
isOpen bool
|
isOpen bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TunOptions struct {
|
||||||
|
Listener *yggdrasil.Listener
|
||||||
|
Dialer *yggdrasil.Dialer
|
||||||
|
}
|
||||||
|
|
||||||
// Gets the maximum supported MTU for the platform based on the defaults in
|
// Gets the maximum supported MTU for the platform based on the defaults in
|
||||||
// defaults.GetDefaults().
|
// defaults.GetDefaults().
|
||||||
func getSupportedMTU(mtu int) int {
|
func getSupportedMTU(mtu int) int {
|
||||||
@ -110,16 +115,21 @@ 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(core *yggdrasil.Core, config *config.NodeState, log *log.Logger, options interface{}) error {
|
||||||
|
tunoptions, ok := options.(TunOptions)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid options supplied to TunAdapter module")
|
||||||
|
}
|
||||||
tun.config = config
|
tun.config = config
|
||||||
tun.log = log
|
tun.log = log
|
||||||
tun.listener = listener
|
tun.listener = tunoptions.Listener
|
||||||
tun.dialer = dialer
|
tun.dialer = tunoptions.Dialer
|
||||||
tun.addrToConn = make(map[address.Address]*tunConn)
|
tun.addrToConn = make(map[address.Address]*tunConn)
|
||||||
tun.subnetToConn = make(map[address.Subnet]*tunConn)
|
tun.subnetToConn = make(map[address.Subnet]*tunConn)
|
||||||
tun.dials = make(map[string][][]byte)
|
tun.dials = make(map[string][][]byte)
|
||||||
tun.writer.tun = tun
|
tun.writer.tun = tun
|
||||||
tun.reader.tun = tun
|
tun.reader.tun = tun
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the setup process for the TUN/TAP adapter. If successful, starts the
|
// Start the setup process for the TUN/TAP adapter. If successful, starts the
|
||||||
@ -160,13 +170,6 @@ func (tun *TunAdapter) _start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
tun.isOpen = true
|
tun.isOpen = true
|
||||||
tun.reconfigure = make(chan chan error)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
e := <-tun.reconfigure
|
|
||||||
e <- nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
go tun.handler()
|
go tun.handler()
|
||||||
tun.reader.Act(nil, tun.reader._read) // Start the reader
|
tun.reader.Act(nil, tun.reader._read) // Start the reader
|
||||||
tun.icmpv6.Init(tun)
|
tun.icmpv6.Init(tun)
|
||||||
@ -177,6 +180,11 @@ func (tun *TunAdapter) _start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsStarted returns true if the module has been started.
|
||||||
|
func (tun *TunAdapter) IsStarted() bool {
|
||||||
|
return tun.isOpen
|
||||||
|
}
|
||||||
|
|
||||||
// Start the setup process for the TUN/TAP adapter. If successful, starts the
|
// Start the setup process for the TUN/TAP adapter. If successful, starts the
|
||||||
// read/write goroutines to handle packets on that interface.
|
// read/write goroutines to handle packets on that interface.
|
||||||
func (tun *TunAdapter) Stop() error {
|
func (tun *TunAdapter) Stop() error {
|
||||||
|
Loading…
Reference in New Issue
Block a user