func()

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
}