// DiscoverLoop periodically calls orc.discover() until process termination.
// The Tablet is read from the given agent each time before calling discover().
// Usually this will be launched as a background goroutine.
493768
func (orc *orcClient) DiscoverLoop(agent *ActionAgent) {
	if *orcInterval == 0 {
		// 0 means never.
		return
	}
	log.Infof("Starting periodic Orchestrator self-registration: API URL = %v, interval = %v", *orcAddr, *orcInterval)

	// Randomly vary the interval by +/- 25% to reduce the potential for spikes.
	ticker := timer.NewRandTicker(*orcInterval, *orcInterval/4)

	// Remember whether we've most recently succeeded or failed.
	var lastErr error

	for {
		// Do the first attempt immediately.
		err := orc.Discover(agent.Tablet())

		// Only log if we're transitioning between success and failure states.
		if (err != nil) != (lastErr != nil) {
			if err != nil {
				log.Warningf("Orchestrator self-registration attempt failed: %v", err)
			} else {
				log.Infof("Orchestrator self-registration succeeded.")
			}
		}
		lastErr = err

		// Wait for the next tick.
		// The only way to stop the loop is to terminate the process.
		<-ticker.C
	}
}
820989
func (a *Allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
	if dType != discoverapi.DatastoreConfig {
		return nil
	}

	dsc, ok := data.(discoverapi.DatastoreConfigData)
	if !ok {
		return types.InternalErrorf("incorrect data in datastore update notification: %v", data)
	}

	ds, err := datastore.NewDataStoreFromConfig(dsc)
	if err != nil {
		return err
	}

	return a.initializeAddressSpace(globalAddressSpace, ds)
}
799409
func WatchLoop(w watch.Interface, fn func(watch.Event) error) {
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt)
	defer signal.Stop(signals)
	for {
		select {
		case event, ok := <-w.ResultChan():
			if !ok {
				return
			}
			if err := fn(event); err != nil {
				w.Stop()
			}
		case <-signals:
			w.Stop()
		}
	}
}
1257705
func (conn *Conn) runLoop() {
	defer conn.wg.Done()
	for {
		select {
		case line := <-conn.in:
			conn.dispatch(line)
		case <-conn.die:
			// control channel closed, bail out
			return
		}
	}
}
947118
func (e *Eventer) eventLoop() {
	for {
		select {
		case <-e.ctx.Done():
			e.logger.Trace("task event loop shutdown")
			return
		case event := <-e.events:
			e.iterateConsumers(event)
		case <-time.After(ConsumerGCInterval):
			e.gcConsumers()
		}
	}
}
1165436
func (c *Controller) processLoop() {
	for {
		obj := c.config.Queue.Pop()
		err := c.config.Process(obj)
		if err != nil {
			if c.config.RetryOnError {
				// This is the safe way to re-enqueue.
				c.config.Queue.AddIfNotPresent(obj)
			}
		}
	}
}
668656
func (s *sentinel) backendLoop(l Loop) error {
	var recoverings Recoverings
	for {
		select {
		case <-l.ShallStop():
			// We're done.
			return s.ObservablesDo(func(o Observable) error {
				logger.Infof("sentinel %q stops observable %q", s, o)
				o.Stop()
				return nil
			})
		case change := <-s.addC:
			// Add new observables.
			for _, o := range change.observables {
				s.observables[o] = struct{}{}
				o.attachSentinel(s)
				logger.Infof("started observing %q", o)
			}
			close(change.doneC)
		case change := <-s.removeC:
			// Remove observable.
			for _, o := range change.observables {
				delete(s.observables, o)
				logger.Infof("stopped observing %q", o)
			}
			close(change.doneC)
		case o := <-s.notifyC:
			_, err := o.Error()
			// First check if my own loop has troubles.
			if o == s {
				return err
			}
			// Receive notification about observable
			// with error.
			if s.handlerF != nil {
				// Try to handle the notification.
				recoverings = append(recoverings, &Recovering{time.Now(), err})
				recoverings, err = s.handlerF(s, o, recoverings)
			}
			if err != nil {
				// Still an error, so kill all.
				logger.Errorf("sentinel %q kills all observables after error: %v", s, err)
				s.ObservablesDo(func(o Observable) error {
					logger.Errorf("killing %q", o)
					o.Kill(errors.Annotate(err, ErrKilledBySentinel, errorMessages, o))
					return o.Wait()
				})
				return errors.Annotate(err, ErrHandlingFailed, errorMessages, o)
			}
		}
	}
}
777448
func (d *Disco) discover(hostname svchost.Hostname) (*Host, error) {
	discoURL := &url.URL{
		Scheme: "https",
		Host:   hostname.String(),
		Path:   discoPath,
	}

	client := &http.Client{
		Transport: d.Transport,
		Timeout:   discoTimeout,

		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			log.Printf("[DEBUG] Service discovery redirected to %s", req.URL)
			if len(via) > maxRedirects {
				return errors.New("too many redirects") // this error will never actually be seen
			}
			return nil
		},
	}

	req := &http.Request{
		Header: make(http.Header),
		Method: "GET",
		URL:    discoURL,
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("User-Agent", httpclient.UserAgentString())

	creds, err := d.CredentialsForHost(hostname)
	if err != nil {
		log.Printf("[WARN] Failed to get credentials for %s: %s (ignoring)", hostname, err)
	}
	if creds != nil {
		// Update the request to include credentials.
		creds.PrepareRequest(req)
	}

	log.Printf("[DEBUG] Service discovery for %s at %s", hostname, discoURL)

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("Failed to request discovery document: %v", err)
	}
	defer resp.Body.Close()

	host := &Host{
		// Use the discovery URL from resp.Request in
		// case the client followed any redirects.
		discoURL:  resp.Request.URL,
		hostname:  hostname.ForDisplay(),
		transport: d.Transport,
	}

	// Return the host without any services.
	if resp.StatusCode == 404 {
		return host, nil
	}

	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("Failed to request discovery document: %s", resp.Status)
	}

	contentType := resp.Header.Get("Content-Type")
	mediaType, _, err := mime.ParseMediaType(contentType)
	if err != nil {
		return nil, fmt.Errorf("Discovery URL has a malformed Content-Type %q", contentType)
	}
	if mediaType != "application/json" {
		return nil, fmt.Errorf("Discovery URL returned an unsupported Content-Type %q", mediaType)
	}

	// This doesn't catch chunked encoding, because ContentLength is -1 in that case.
	if resp.ContentLength > maxDiscoDocBytes {
		// Size limit here is not a contractual requirement and so we may
		// adjust it over time if we find a different limit is warranted.
		return nil, fmt.Errorf(
			"Discovery doc response is too large (got %d bytes; limit %d)",
			resp.ContentLength, maxDiscoDocBytes,
		)
	}

	// If the response is using chunked encoding then we can't predict its
	// size, but we'll at least prevent reading the entire thing into memory.
	lr := io.LimitReader(resp.Body, maxDiscoDocBytes)

	servicesBytes, err := ioutil.ReadAll(lr)
	if err != nil {
		return nil, fmt.Errorf("Error reading discovery document body: %v", err)
	}

	var services map[string]interface{}
	err = json.Unmarshal(servicesBytes, &services)
	if err != nil {
		return nil, fmt.Errorf("Failed to decode discovery document as a JSON object: %v", err)
	}
	host.services = services

	return host, nil
}
243502
func (p *V2) Discover() error {
	if err := p.init(); err != nil {
		return err
	}
	if p.lastDiscovery.After(time.Time{}) {
		var extinct []device.GenericDevice
		p.RLock()
		for _, dev := range p.devices {
			// If the device has not been seen in twice the time since the last
			// discovery, mark it as extinct
			if dev.Seen().Before(time.Now().Add(time.Since(p.lastDiscovery) * -2)) {
				extinct = append(extinct, dev)
			}
		}
		p.RUnlock()
		// Remove extinct devices
		for _, dev := range extinct {
			p.removeDevice(dev.ID())

			locationID := dev.CachedLocation()
			location, err := p.getLocation(locationID)
			if err == nil {
				if err = location.RemoveDevice(dev); err != nil {
					common.Log.Warnf("Failed removing extinct device '%d' from location (%s): %v", dev.ID(), locationID, err)
				}
				if len(location.Devices()) == 0 {
					p.removeLocation(location.ID())
					p.Notify(common.EventExpiredLocation{Location: location})
				}
			}

			groupID := dev.CachedGroup()
			group, err := p.getGroup(groupID)
			if err == nil {
				if err = group.RemoveDevice(dev); err != nil {
					common.Log.Warnf("Failed removing extinct device '%d' from group (%s): %v", dev.ID(), groupID, err)
				}
				if len(group.Devices()) == 0 {
					p.removeGroup(group.ID())
					p.Notify(common.EventExpiredGroup{Group: group})
				}
			}

			p.Notify(common.EventExpiredDevice{Device: dev})
		}
	}
	if err := p.broadcast.Discover(); err != nil {
		return err
	}
	p.Lock()
	p.lastDiscovery = time.Now()
	p.Unlock()

	return nil
}
352138
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
	if dType != discoverapi.NodeDiscovery {
		return nil
	}
	notif := &api.DiscoveryNotification{
		DiscoveryType: dType,
		DiscoveryData: data,
	}
	return d.call("DiscoverNew", notif, &api.DiscoveryResponse{})
}
1318175
func (p *Client) DiscoverProfile(force bool) (*ble.Profile, error) {
	if p.profile != nil && !force {
		return p.profile, nil
	}
	ss, err := p.DiscoverServices(nil)
	if err != nil {
		return nil, fmt.Errorf("can't discover services: %s\n", err)
	}
	for _, s := range ss {
		cs, err := p.DiscoverCharacteristics(nil, s)
		if err != nil {
			return nil, fmt.Errorf("can't discover characteristics: %s\n", err)
		}
		for _, c := range cs {
			_, err := p.DiscoverDescriptors(nil, c)
			if err != nil {
				return nil, fmt.Errorf("can't discover descriptors: %s\n", err)
			}
		}
	}
	p.profile = &ble.Profile{Services: ss}
	return p.profile, nil
}
20439
func (ec *ServiceManager) eventLoop() (err error) {
	// Run event loop
	for {
		// Await event on global channel
		event, open := <-ec.in

		if open {
			// Dispatch to bound services
			for _, s := range ec.services {
				s.SendEvent(event)
			}
		} else {
			// Close service channels
			for _, s := range ec.services {
				s.Exit()
			}
			break
		}
	}
	return nil
}
895510
func DiscoverUPnP(ctx context.Context) (*UPnP, error) {
	// Scan the local network for a UPnP-enabled device.
	device, err := upnp.DiscoverCtx(ctx)
	if err != nil {
		return nil, err
	}

	u := &UPnP{
		device:         device,
		forwardedPorts: make(map[uint16]struct{}),
	}

	// We'll then attempt to retrieve the external IP address of this
	// device to ensure it is not behind multiple NATs.
	if _, err := u.ExternalIP(); err != nil {
		return nil, err
	}

	return u, nil
}
922441
func (s *MockDiscoveryServer) Discover(ctx context.Context, request *discovery.SignedRequest) (*discovery.Response, error) {
	if request == nil {
		return nil, errors.New("nil request")
	}

	req := &discovery.Request{}
	err := proto.Unmarshal(request.Payload, req)
	if err != nil {
		return nil, errors.Wrap(err, "failed parsing request")
	}
	if req.Authentication == nil {
		return nil, errors.New("access denied, no authentication info in request")
	}
	if len(req.Authentication.ClientIdentity) == 0 {
		return nil, errors.New("access denied, client identity wasn't supplied")
	}

	var results []*discovery.QueryResult
	for _, q := range req.Queries {
		result := s.processQuery(q)
		if result != nil {
			results = append(results, result)
		}
	}
	return &discovery.Response{
		Results: results,
	}, nil
}
296361
func (s *UDPSession) readLoop() {
	addr, _ := net.ResolveUDPAddr("udp", s.conn.LocalAddr().String())
	if addr.IP.To4() != nil {
		s.readLoopIPv4()
	} else {
		s.readLoopIPv6()
	}
}
500340
func DiscoverNAT(ctx context.Context) (*NAT, error) {
	var (
		natInstance nat.NAT
		err         error
	)

	done := make(chan struct{})
	go func() {
		defer close(done)
		// This will abort in 10 seconds anyways.
		natInstance, err = nat.DiscoverGateway()
	}()

	select {
	case <-done:
	case <-ctx.Done():
		return nil, ctx.Err()
	}

	if err != nil {
		return nil, err
	}

	// Log the device addr.
	addr, err := natInstance.GetDeviceAddress()
	if err != nil {
		log.Debug("DiscoverGateway address error:", err)
	} else {
		log.Debug("DiscoverGateway address:", addr)
	}

	return newNAT(natInstance), nil
}
957283
func Discover(renewal, timeout time.Duration) []nat.Device {
	var results []nat.Device

	interfaces, err := net.Interfaces()
	if err != nil {
		l.Infoln("Listing network interfaces:", err)
		return results
	}

	resultChan := make(chan nat.Device)

	wg := &sync.WaitGroup{}

	for _, intf := range interfaces {
		// Interface flags seem to always be 0 on Windows
		if runtime.GOOS != "windows" && (intf.Flags&net.FlagUp == 0 || intf.Flags&net.FlagMulticast == 0) {
			continue
		}

		for _, deviceType := range []string{"urn:schemas-upnp-org:device:InternetGatewayDevice:1", "urn:schemas-upnp-org:device:InternetGatewayDevice:2"} {
			wg.Add(1)
			go func(intf net.Interface, deviceType string) {
				discover(&intf, deviceType, timeout, resultChan)
				wg.Done()
			}(intf, deviceType)
		}
	}

	go func() {
		wg.Wait()
		close(resultChan)
	}()

	seenResults := make(map[string]bool)
nextResult:
	for result := range resultChan {
		if seenResults[result.ID()] {
			l.Debugf("Skipping duplicate result %s", result.ID())
			continue nextResult
		}

		results = append(results, result)
		seenResults[result.ID()] = true

		l.Debugf("UPnP discovery result %s", result.ID())
	}

	return results
}