diff --git a/src/admin/admin.go b/src/admin/admin.go index d2e066a..8322b06 100644 --- a/src/admin/admin.go +++ b/src/admin/admin.go @@ -25,7 +25,7 @@ type AdminSocket struct { listenaddr string listener net.Listener handlers map[string]handler - started bool + done chan struct{} } type AdminSocketResponse struct { @@ -69,6 +69,8 @@ func (a *AdminSocket) Init(c *core.Core, state *config.NodeState, log *log.Logge a.handlers = make(map[string]handler) current := state.GetCurrent() a.listenaddr = current.AdminListen + a.done = make(chan struct{}) + close(a.done) // Start in a done / not-started state _ = a.AddHandler("list", []string{}, func(_ json.RawMessage) (interface{}, error) { res := &ListResponse{ List: map[string]ListEntry{}, @@ -144,21 +146,32 @@ func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) { // Start runs the admin API socket to listen for / respond to admin API calls. func (a *AdminSocket) Start() error { if a.listenaddr != "none" && a.listenaddr != "" { + a.done = make(chan struct{}) go a.listen() - a.started = true } return nil } // IsStarted returns true if the module has been started. func (a *AdminSocket) IsStarted() bool { - return a.started + select { + case <-a.done: + // Not blocking, so we're not currently running + return false + default: + // Blocked, so we must have started + return true + } } // Stop will stop the admin API and close the socket. func (a *AdminSocket) Stop() error { if a.listener != nil { - a.started = false + select { + case <-a.done: + default: + close(a.done) + } return a.listener.Close() } return nil @@ -215,6 +228,14 @@ func (a *AdminSocket) listen() { conn, err := a.listener.Accept() if err == nil { go a.handleRequest(conn) + } else { + select { + case <-a.done: + // Not blocked, so we havent started or already stopped + return + default: + // Blocked, so we're supposed to keep running + } } } } diff --git a/src/core/core.go b/src/core/core.go index ba2b89b..f3942cd 100644 --- a/src/core/core.go +++ b/src/core/core.go @@ -95,9 +95,11 @@ func (c *Core) _addPeerLoop() { } } - c.addPeerTimer = time.AfterFunc(time.Minute, func() { - c.Act(nil, c._addPeerLoop) - }) + if c.addPeerTimer != nil { + c.addPeerTimer = time.AfterFunc(time.Minute, func() { + c.Act(nil, c._addPeerLoop) + }) + } } // Start starts up Yggdrasil using the provided config.NodeConfig, and outputs @@ -149,7 +151,9 @@ func (c *Core) _start(nc *config.NodeConfig, log *log.Logger) (*config.NodeState // return nil, err //} - c.Act(c, c._addPeerLoop) + c.addPeerTimer = time.AfterFunc(0, func() { + c.Act(nil, c._addPeerLoop) + }) c.log.Infoln("Startup complete") return &c.config, nil @@ -166,6 +170,7 @@ func (c *Core) _stop() { c.log.Infoln("Stopping...") if c.addPeerTimer != nil { c.addPeerTimer.Stop() + c.addPeerTimer = nil } c.links.stop() /* FIXME this deadlocks, need a waitgroup or something to coordinate shutdown diff --git a/src/core/core_test.go b/src/core/core_test.go index 224907b..ce4a415 100644 --- a/src/core/core_test.go +++ b/src/core/core_test.go @@ -142,7 +142,7 @@ func TestCore_Start_Transfer(t *testing.T) { if err != nil { t.Fatal(err) } - if bytes.Compare(msg, buf) != 0 { + if !bytes.Equal(msg, buf) { t.Fatal("expected echo") } <-done diff --git a/src/core/tcp.go b/src/core/tcp.go index 48163e8..eced772 100644 --- a/src/core/tcp.go +++ b/src/core/tcp.go @@ -31,7 +31,6 @@ import ( ) const default_timeout = 6 * time.Second -const tcp_ping_interval = (default_timeout * 2 / 3) // The TCP listener and information about active TCP connections, to avoid duplication. type tcp struct { diff --git a/src/tuntap/icmpv6.go b/src/tuntap/icmpv6.go index 59d07af..b7461a2 100644 --- a/src/tuntap/icmpv6.go +++ b/src/tuntap/icmpv6.go @@ -17,11 +17,7 @@ import ( "golang.org/x/net/ipv6" ) -const len_ETHER = 14 - -type ICMPv6 struct { - tun *TunAdapter -} +type ICMPv6 struct{} // Marshal returns the binary encoding of h. func ipv6Header_Marshal(h *ipv6.Header) ([]byte, error) {