diff --git a/bus.go b/bus.go index 12982db..40b4952 100644 --- a/bus.go +++ b/bus.go @@ -11,7 +11,8 @@ import ( type Bus struct { rwc ReadWriteCloser - handler []Handler + handler []Handler + disconnect chan bool } // NewBusForInterfaceWithName returns a bus from the network interface with name ifaceName. @@ -32,25 +33,30 @@ func NewBusForInterfaceWithName(ifaceName string) (*Bus, error) { // NewBus returns a new CAN bus. func NewBus(rwc ReadWriteCloser) *Bus { return &Bus{ - rwc: rwc, - handler: make([]Handler, 0), + rwc: rwc, + handler: make([]Handler, 0), + disconnect: make(chan bool, 1), } } // ConnectAndPublish starts handling CAN frames to publish them to handlers. func (b *Bus) ConnectAndPublish() error { for { - err := b.publishNextFrame() - if err != nil { - return err + select { + case <-b.disconnect: + return nil + default: + err := b.publishNextFrame() + if err != nil { + return err + } } } - - return nil } // Disconnect stops handling CAN frames. func (b *Bus) Disconnect() error { + b.disconnect <- true return b.rwc.Close() } @@ -75,6 +81,10 @@ func (b *Bus) Unsubscribe(handler Handler) { } } +func (b *Bus) HasSubscriber() bool { + return len(b.handler) > 0 +} + // Publish publishes a frame on the bus. // // Frames publishes with the Publish methods are not received by handlers. diff --git a/bus_test.go b/bus_test.go index 8eb5056..2b445ea 100644 --- a/bus_test.go +++ b/bus_test.go @@ -75,3 +75,66 @@ func TestUnsubscribe(t *testing.T) { t.Fatal(x) } } + +func TestHasHandler(t *testing.T) { + rwc := NewEchoReadWriteCloser() + bus := NewBus(rwc) + + if bus.HasSubscriber() != false { + t.Fatal("bus should not have subscriber on creation") + } + + handler := newTestHandler() + bus.Subscribe(handler) + if bus.HasSubscriber() != true { + t.Fatal("bus should have subscriber after subscription") + } + + bus.Unsubscribe(handler) + if bus.HasSubscriber() != false { + t.Fatal("bus should not have subscriber after subscriber unsubscribed") + } +} + +func TestDisconnect(t *testing.T) { + rwc := NewEchoReadWriteCloser() + bus := NewBus(rwc) + + connectAndPublishReturns := make(chan bool) + + go func() { + bus.ConnectAndPublish() + connectAndPublishReturns <- true + }() + //Should make ConnectAndPublish return + bus.Disconnect() + // if it doesn't we're stuck on 1 + timeout := time.After(100 * time.Millisecond) + select { + case <-timeout: + t.Fatal("bus.Disconnect does not abort ConnectAndPublish loop") + case <-connectAndPublishReturns: + //Success + return + } +} + +func TestDisconnectWhenConnectAndPublishedNotCalled(t *testing.T) { + rwc := NewEchoReadWriteCloser() + bus := NewBus(rwc) + + disconnected := make(chan bool) + + go func() { + bus.Disconnect() + disconnected <- true + }() + + timeout := time.After(100 * time.Millisecond) + select { + case <-timeout: + t.Fatal("bus.Disconnect() blocks when bus.ConnectAndPublish() not called") + case <-disconnected: + return + } +} diff --git a/cmd/candump.go b/cmd/candump.go index d37a9ef..4f30899 100644 --- a/cmd/candump.go +++ b/cmd/candump.go @@ -6,11 +6,12 @@ package main import ( "flag" "fmt" - "github.com/brutella/can" "log" "net" "os" "os/signal" + + "github.com/dockstavarvet/can" ) var i = flag.String("if", "", "network interface name") diff --git a/go.mod b/go.mod index d8c25a8..27e8429 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ -module github.com/brutella/can +module github.com/dockstavarvet/can + +go 1.15 require golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06 diff --git a/go.sum b/go.sum index e5b9e5a..c20d17a 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,3 @@ +github.com/dockstavarvet/can v0.0.4/go.mod h1:jpF3R1Y7uEyvJmdl9Jo5bs2jp7+EB+AnrCrfHQmmJm4= golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06 h1:0oC8rFnE+74kEmuHZ46F6KHsMr5Gx2gUQPuNz28iQZM= golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=