diff --git a/go.mod b/go.mod index 3e8db512..995e54c2 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,10 @@ module github.com/yggdrasil-network/yggdrasil-go require ( github.com/docker/libcontainer v2.2.1+incompatible + github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8 github.com/hjson/hjson-go v0.0.0-20181010104306-a25ecf6bd222 github.com/kardianos/minwinsvc v0.0.0-20151122163309-cad6b2b879b0 github.com/mitchellh/mapstructure v1.1.2 - github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8 github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091 github.com/yggdrasil-network/water v0.0.0-20180615095340-f732c88f34ae golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 diff --git a/go.sum b/go.sum index 17b1017a..92dfe88c 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/docker/libcontainer v2.2.1+incompatible h1:++SbbkCw+X8vAd4j2gOCzZ2Nn7s2xFALTf7LZKmM1/0= github.com/docker/libcontainer v2.2.1+incompatible/go.mod h1:osvj61pYsqhNCMLGX31xr7klUBhHb/ZBuXS0o1Fvwbw= +github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8 h1:WD8iJ37bRNwvETMfVTusVSAi0WdXTpfNVGY2aHycNKY= +github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8/go.mod h1:gq31gQ8wEHkR+WekdWsqDuf8pXTUZA9BnnzTuPz1Y9U= github.com/hjson/hjson-go v0.0.0-20181010104306-a25ecf6bd222 h1:xmvkbxXDeN1ffWq8kvrhyqVYAO2aXuRBsbpxVTR+JyU= github.com/hjson/hjson-go v0.0.0-20181010104306-a25ecf6bd222/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio= github.com/kardianos/minwinsvc v0.0.0-20151122163309-cad6b2b879b0 h1:YnZmFjg0Nvk8851WTVWlqMC1ecJH07Ctz+Ezxx4u54g= @@ -18,5 +20,3 @@ golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e h1:njOxP/wVblhCLIUhjHXf6X+dz golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8 h1:WD8iJ37bRNwvETMfVTusVSAi0WdXTpfNVGY2aHycNKY= -github.com/gologme/log v0.0.0-20181207131047-4e5d8ccb38e8/go.mod h1:gq31gQ8wEHkR+WekdWsqDuf8pXTUZA9BnnzTuPz1Y9U= diff --git a/src/yggdrasil/link.go b/src/yggdrasil/link.go index 1e658479..320b3e61 100644 --- a/src/yggdrasil/link.go +++ b/src/yggdrasil/link.go @@ -146,7 +146,9 @@ func (intf *linkInterface) handler() error { intf.peer.close = func() { intf.msgIO.close() } go intf.peer.linkLoop() // Start the writer + signalReady := make(chan struct{}, 1) go func() { + defer close(signalReady) interval := 4 * time.Second timer := time.NewTimer(interval) clearTimer := func() { @@ -181,15 +183,63 @@ func (intf *linkInterface) handler() error { } intf.msgIO.writeMsg(msg) util.PutBytes(msg) - if true { - // TODO *don't* do this if we're not reading any traffic - // In such a case, the reader is responsible for resetting it the next time we read something - intf.link.core.switchTable.idleIn <- intf.peer.port + select { + case signalReady <- struct{}{}: + default: } } } }() - intf.link.core.switchTable.idleIn <- intf.peer.port // notify switch that we're idle + //intf.link.core.switchTable.idleIn <- intf.peer.port // notify switch that we're idle + // Used to enable/disable activity in the switch + signalAlive := make(chan struct{}, 1) + defer close(signalAlive) + go func() { + var isAlive bool + var isReady bool + interval := 6 * time.Second // TODO set to ReadTimeout from the config, reset if it gets changed + timer := time.NewTimer(interval) + clearTimer := func() { + if !timer.Stop() { + select { + case <-timer.C: + default: + } + } + } + defer clearTimer() + for { + clearTimer() + timer.Reset(interval) + select { + case _, ok := <-signalAlive: + if !ok { + return + } + if !isAlive { + isAlive = true + if !isReady { + // (Re-)enable in the switch + isReady = true + intf.link.core.switchTable.idleIn <- intf.peer.port + } + } + case _, ok := <-signalReady: + if !ok { + return + } + if !isAlive || !isReady { + // Disable in the switch + isReady = false + } else { + // Keep enabled in the switch + intf.link.core.switchTable.idleIn <- intf.peer.port + } + case <-timer.C: + isAlive = false + } + } + }() // Run reader loop for { msg, err := intf.msgIO.readMsg() @@ -199,6 +249,10 @@ func (intf *linkInterface) handler() error { if err != nil { return err } + select { + case signalAlive <- struct{}{}: + default: + } } //////////////////////////////////////////////////////////////////////////////// return nil