diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ad8846e5a7f7862ebf52c14d083a542d8b5d2ef1..433a4310d04a5a00c8616aafc70a43a6353de12e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,24 +1,16 @@ -image: golang:alpine +image: golang:1.11 stages: - build - test -before_script: - - mkdir -p /go/src/gitlab.com/jtaimisto - - cp -a $(pwd) /go/src/gitlab.com/jtaimisto/bluewalker - - apk add --no-cache git - - go get golang.org/x/sys/unix - build-main-app: stage: build script: - - cd /go/ - go install gitlab.com/jtaimisto/bluewalker - go install gitlab.com/jtaimisto/bluewalker/listener run-tests: stage: test script: - - cd /go/ - - CGO_ENABLED=0 go test gitlab.com/jtaimisto/bluewalker... + - CGO_ENABLED=0 go test gitlab.com/jtaimisto/bluewalker/... diff --git a/go.mod b/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..e1fda734968afd9bbc6b9252ece37fdd8f967963 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module gitlab.com/jtaimisto/bluewalker + +require golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b diff --git a/go.sum b/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..34a9b6711d9401bdb9484ff39ad2d210a1bf4599 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b h1:MQE+LT/ABUuuvEZ+YQAMSXindAdUh7slEmAkup74op4= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/hci/dummy.go b/hci/dummy.go index dfc8dbcd1deaa0ea6fc8fd5835c2d0bfa5e799c8..0ae4a488008e1c6250d48c703b32c9af85005570 100644 --- a/hci/dummy.go +++ b/hci/dummy.go @@ -2,11 +2,14 @@ package hci -import "fmt" +import ( + "fmt" + "time" +) // ErrNotImplemented is returned for functions which are not // implemented by this transport -var ErrNotImplemented = fmt.Errorf("Not implemented") +var ErrNotImplemented = fmt.Errorf("HCI transport not implemented on Darwin") type dummy struct { } @@ -22,9 +25,11 @@ func (d *dummy) Close() { } func (d *dummy) Read() ([]byte, error) { + <-time.After(time.Second) return nil, ErrNotImplemented } func (d *dummy) Write(buffer []byte) error { + <-time.After(time.Second) return ErrNotImplemented } diff --git a/main.go b/main.go index e92a2544f352ee8c6032622680d4a238bfcea770..35bcdfecbf17bfd1e011b80d4d0ee41d8f1cf9d6 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,6 @@ import ( "os" "os/signal" "strings" - "sync" "syscall" "time" @@ -331,7 +330,7 @@ func ruuviLoop(reportChan chan *host.ScanReport, out *output) { if ads.Typ == hci.AdManufacturerSpecific && len(ads.Data) >= 2 && binary.LittleEndian.Uint16(ads.Data) == 0x0499 { ruuviData, err := ruuvi.Unmarshall(ads.Data) if err != nil { - log.Printf("Unable to parse ruuvi data: %s\n", err.Error()) + log.Printf("Unable to parse ruuvi data: %v", err) continue } if cmdline.json { @@ -407,11 +406,17 @@ func collectorLoop(reportChan chan *host.ScanReport, out *output) { } func main() { + err := realMain() + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(255) + } +} +func realMain() error { flag.Parse() if cmdline.device == "" { - fmt.Fprintf(os.Stderr, "Missing device name\n") - os.Exit(255) + return fmt.Errorf("Missing device name") } if !cmdline.debug { @@ -420,38 +425,32 @@ func main() { var filters []filter.AdFilter if cmdline.addrFilter != "" { if cmdline.ruuvi { - fmt.Fprintf(os.Stderr, "Address filters not supported on Ruuvi tag mode\n") - os.Exit(255) + return fmt.Errorf("Address filters not supported on Ruuvi tag mode") } var err error if filters, err = parseAddressFilters(cmdline.addrFilter); err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err.Error()) - os.Exit(255) + return fmt.Errorf("%s", err.Error()) } } if cmdline.vendorFilter != "" { if cmdline.ruuvi { - fmt.Fprintf(os.Stderr, "Vendor filter not supported on Ruuvi tag mode\n") - os.Exit(255) + return fmt.Errorf("Vendor filter not supported on Ruuvi tag mode") } filt, err := parseVendorSpecFilter(cmdline.vendorFilter) if err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err.Error()) - os.Exit(255) + return fmt.Errorf("%s", err.Error()) } filters = append(filters, filt) } if cmdline.adTypeFilter != "" { if cmdline.ruuvi { - fmt.Fprintf(os.Stderr, "AD type filter not supported on Ruuvi tag mode\n") - os.Exit(255) + return fmt.Errorf("AD type filter not supported on Ruuvi tag mode") } filt, err := parseAdTypeFilters(cmdline.adTypeFilter) if err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err.Error()) - os.Exit(255) + return fmt.Errorf("%s", err.Error()) } for _, f := range filt { filters = append(filters, f) @@ -459,21 +458,19 @@ func main() { } if cmdline.duration == 0 || cmdline.duration < -1 { - fmt.Fprintf(os.Stderr, "Invalid duration %d\n", cmdline.duration) - os.Exit(255) + return fmt.Errorf("Invalid duration %d", cmdline.duration) } var out *output if cmdline.socketPath != "" { if !cmdline.json { - fmt.Fprintf(os.Stderr, "Forcing JSON mode when writing to socket. Use -json to silence this warning\n") + fmt.Fprintf(os.Stderr, "Forcing JSON mode when writing to socket. Use -json to silence this warning") cmdline.json = true } var err error out, err = outputForSocket(cmdline.socketPath) if err != nil { - fmt.Printf("Unable to open unix socket at %s (%s)\n", cmdline.socketPath, err.Error()) - os.Exit(255) + return fmt.Errorf("Unable to open unix socket at %s (%v)", cmdline.socketPath, err) } defer out.Close() } else { @@ -496,47 +493,42 @@ func main() { raw, err := hci.Raw(cmdline.device) if err != nil { - fmt.Fprintf(os.Stderr, "Error while opening RAW HCI socket: %s\nAre you running as root and have you run sudo hciconfig %s down?\n", err.Error(), cmdline.device) - os.Exit(255) + return fmt.Errorf("Error while opening RAW HCI socket: %v\nAre you running as root and have you run sudo hciconfig %s down?", err, cmdline.device) } - host := host.New(raw) - if err = host.Init(); err != nil { - fmt.Fprintf(os.Stderr, "Unable to initialize host: %s\n", err.Error()) - host.Deinit() - os.Exit(255) - } + errCh := make(chan error) - reportChan, err := host.StartScanning(cmdline.active, filters) - if err != nil { - fmt.Fprintf(os.Stderr, "Unable to start scanning: %s\n", err.Error()) - host.Deinit() - os.Exit(255) - } + go func(errCh chan<- error) { + host := host.New(raw) + defer host.Deinit() + if err = host.Init(); err != nil { + errCh <- fmt.Errorf("Unable to initialize host: %v", err) + return + } + + defer host.StopScanning() // FIXME: error ignored + reportChan, err := host.StartScanning(cmdline.active, filters) + if err != nil { + errCh <- fmt.Errorf("Unable to start scanning: %v", err) + return + } - var wg sync.WaitGroup - wg.Add(1) - go func() { loop(reportChan, out) - wg.Done() - }() + close(errCh) + }(errCh) + scanComplete := time.After(time.Duration(cmdline.duration) * time.Second) if cmdline.duration == -1 { - select { - case s := <-sig: - log.Printf("Received signal %s, stopping ", s.String()) - - } - } else { - ch := time.Tick(time.Duration(cmdline.duration) * time.Second) - select { - case <-ch: - case s := <-sig: - log.Printf("Received signal %s, stopping ", s.String()) + scanComplete = nil // read blocks forever + } - } + select { + case <-scanComplete: + case err := <-errCh: + log.Printf("Received error %v, stopping ", err) + return err + case s := <-sig: + log.Printf("Received signal %v, stopping ", s) } - host.StopScanning() - host.Deinit() - wg.Wait() + return nil }