in nmxact/nmble/discover.go [85:169]
func (d *Discoverer) Start() (<-chan BleAdvReport, <-chan error, error) {
d.mtx.Lock()
defer d.mtx.Unlock()
if d.state != DISCOVERER_STATE_IDLE {
return nil, nil, nmxutil.NewAlreadyError(
"Attempt to start BLE discoverer twice")
}
d.stopChan = make(chan struct{})
r := NewBleScanReq()
r.OwnAddrType = d.params.OwnAddrType
r.DurationMs = int(d.params.Duration / time.Millisecond)
r.FilterPolicy = BLE_SCAN_FILT_NO_WL
r.Limited = false
r.Passive = d.params.Passive
r.FilterDuplicates = true
bl, err := d.params.Bx.AddListener(SeqKey(r.Seq))
if err != nil {
return nil, nil, err
}
ach, ech, err := actScan(d.params.Bx, bl, r)
if err != nil {
d.params.Bx.RemoveListener(bl)
return nil, nil, err
}
// A buffer size of 1 is used so that the receiving Goroutine can stop the
// discoverer without triggering a deadlock.
parentEch := make(chan error, 1)
d.wg.Add(1)
go func() {
defer d.wg.Done()
stopChan := d.stopChan
// Block until scan completes.
var done bool
var err error
for !done {
select {
case err = <-ech:
done = true
case <-stopChan:
// Discovery aborted; remove the BLE listener. This will cause
// the scan to fail, triggering a send on the ech channel.
if bl != nil {
d.params.Bx.RemoveListener(bl)
bl = nil
stopChan = nil
}
}
}
d.mtx.Lock()
defer d.mtx.Unlock()
// Always attempt to cancel scanning. No harm done if scanning is
// already stopped.
if !nmxutil.IsXport(err) {
if err := d.scanCancel(); err != nil {
log.Debugf("Failed to cancel scan in progress: %s",
err.Error())
}
}
if bl != nil {
d.params.Bx.RemoveListener(bl)
}
d.setState(DISCOVERER_STATE_IDLE)
parentEch <- err
close(parentEch)
}()
d.setState(DISCOVERER_STATE_STARTED)
return ach, parentEch, nil
}