// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef DISCOVERY_MDNS_MDNS_PROBE_MANAGER_H_ #define DISCOVERY_MDNS_MDNS_PROBE_MANAGER_H_ #include #include #include #include "discovery/mdns/mdns_domain_confirmed_provider.h" #include "discovery/mdns/mdns_probe.h" #include "discovery/mdns/mdns_records.h" #include "platform/base/error.h" #include "platform/base/ip_address.h" namespace openscreen { class TaskRunner; namespace discovery { class MdnsQuerier; class MdnsRandom; class MdnsSender; // Interface for maintaining ownership of mDNS Domains. class MdnsProbeManager { public: virtual ~MdnsProbeManager(); // Returns whether the provided domain name has been claimed as owned by this // mDNS Probe Manager. virtual bool IsDomainClaimed(const DomainName& domain) const = 0; // |message| is a message received from another host which contains a query // from some domain. It is a considered a probe query for a specific domain if // it contains a query for a specific domain which is answered by mDNS Records // in the 'authority records' section of |message|. If a probe for the // provided domain name is ongoing, an MdnsMessage is sent to the provided // endpoint as described in RFC 6762 section 8.2 to allow for conflict // resolution. If the requested name has already been claimed, a message to // specify this will be sent as described in RFC 6762 section 8.1. The |src| // argument is the address from which the message was originally sent, so that // the response message may be sent as a unicast response. virtual void RespondToProbeQuery(const MdnsMessage& message, const IPEndpoint& src) = 0; }; // This class is responsible for managing all ongoing probes for claiming domain // names, as described in RFC 6762 Section 8.1's probing phase. If one such // probe fails due to a conflict detection, this class will modify the domain // name as described in RFC 6762 section 9 and re-initiate probing for the new // name. class MdnsProbeManagerImpl : public MdnsProbe::Observer, public MdnsProbeManager { public: // |sender|, |receiver|, |random_delay|, and |task_runner|, must all persist // for the duration of this object's lifetime. MdnsProbeManagerImpl(MdnsSender* sender, MdnsReceiver* receiver, MdnsRandom* random_delay, TaskRunner* task_runner, ClockNowFunctionPtr now_function); MdnsProbeManagerImpl(const MdnsProbeManager& other) = delete; // NOLINT MdnsProbeManagerImpl(MdnsProbeManager&& other) = delete; // NOLINT ~MdnsProbeManagerImpl() override; MdnsProbeManagerImpl& operator=(const MdnsProbeManagerImpl& other) = delete; MdnsProbeManagerImpl& operator=(MdnsProbeManagerImpl&& other) = delete; // Starts probing for a valid domain name based on the given one. This may // only be called once per MdnsProbe instance. |observer| must persist until // a valid domain is discovered and the observer's OnDomainFound method is // called. // NOTE: |address| is used to generate a 'fake' address record to use for the // probe query. See MdnsProbe::PerformProbeIteration() for further details. Error StartProbe(MdnsDomainConfirmedProvider* callback, DomainName requested_name, IPAddress address); // Stops probing for the requested domain name. Error StopProbe(const DomainName& requested_name); // MdnsDomainOwnershipManager overrides. bool IsDomainClaimed(const DomainName& domain) const override; void RespondToProbeQuery(const MdnsMessage& message, const IPEndpoint& src) override; private: friend class TestMdnsProbeManager; // Resolves simultaneous probe queries as described in RFC 6762 section 8.2. void TiebreakSimultaneousProbes(const MdnsMessage& message); virtual std::unique_ptr CreateProbe(DomainName name, IPAddress address) { return std::make_unique(sender_, receiver_, random_delay_, task_runner_, now_function_, this, std::move(name), std::move(address)); } // Owns an in-progress MdnsProbe. When the probe starts, an instance of this // struct is created. Upon successful completion of the probe, this instance // is deleted and the owned |probe| instance is moved to |completed_probes|. // Upon failure, the instance is updated with a new MdnsProbe object and this // process is repeated. struct OngoingProbe { OngoingProbe(std::unique_ptr probe, DomainName name, MdnsDomainConfirmedProvider* callback); // NOTE: unique_ptr objects are used to avoid issues when the container // holding this object is resized. std::unique_ptr probe; DomainName requested_name; MdnsDomainConfirmedProvider* callback; int num_probes_failed = 0; }; // MdnsProbe::Observer overrides. void OnProbeSuccess(MdnsProbe* probe) override; void OnProbeFailure(MdnsProbe* probe) override; // Helpers to find ongoing and completed probes. std::vector>::const_iterator FindCompletedProbe( const DomainName& name) const; std::vector::iterator FindOngoingProbe(const DomainName& name); std::vector::iterator FindOngoingProbe(MdnsProbe* probe); MdnsSender* const sender_; MdnsReceiver* const receiver_; MdnsRandom* const random_delay_; TaskRunner* const task_runner_; ClockNowFunctionPtr now_function_; // The set of all probes which have completed successfully. This set is // expected to remain small. unique_ptrs are used for storing the probes to // avoid issues when the vector is resized. std::vector> completed_probes_; // The set of all currently ongoing probes. This set is expected to remain // small. std::vector ongoing_probes_; }; } // namespace discovery } // namespace openscreen #endif // DISCOVERY_MDNS_MDNS_PROBE_MANAGER_H_