1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef DISCOVERY_MDNS_MDNS_PROBE_MANAGER_H_ 6 #define DISCOVERY_MDNS_MDNS_PROBE_MANAGER_H_ 7 8 #include <memory> 9 #include <utility> 10 #include <vector> 11 12 #include "discovery/mdns/mdns_domain_confirmed_provider.h" 13 #include "discovery/mdns/mdns_probe.h" 14 #include "discovery/mdns/mdns_records.h" 15 #include "platform/base/error.h" 16 #include "platform/base/ip_address.h" 17 18 namespace openscreen { 19 20 class TaskRunner; 21 22 namespace discovery { 23 24 class MdnsQuerier; 25 class MdnsRandom; 26 class MdnsSender; 27 28 // Interface for maintaining ownership of mDNS Domains. 29 class MdnsProbeManager { 30 public: 31 virtual ~MdnsProbeManager(); 32 33 // Returns whether the provided domain name has been claimed as owned by this 34 // mDNS Probe Manager. 35 virtual bool IsDomainClaimed(const DomainName& domain) const = 0; 36 37 // |message| is a message received from another host which contains a query 38 // from some domain. It is a considered a probe query for a specific domain if 39 // it contains a query for a specific domain which is answered by mDNS Records 40 // in the 'authority records' section of |message|. If a probe for the 41 // provided domain name is ongoing, an MdnsMessage is sent to the provided 42 // endpoint as described in RFC 6762 section 8.2 to allow for conflict 43 // resolution. If the requested name has already been claimed, a message to 44 // specify this will be sent as described in RFC 6762 section 8.1. The |src| 45 // argument is the address from which the message was originally sent, so that 46 // the response message may be sent as a unicast response. 47 virtual void RespondToProbeQuery(const MdnsMessage& message, 48 const IPEndpoint& src) = 0; 49 }; 50 51 // This class is responsible for managing all ongoing probes for claiming domain 52 // names, as described in RFC 6762 Section 8.1's probing phase. If one such 53 // probe fails due to a conflict detection, this class will modify the domain 54 // name as described in RFC 6762 section 9 and re-initiate probing for the new 55 // name. 56 class MdnsProbeManagerImpl : public MdnsProbe::Observer, 57 public MdnsProbeManager { 58 public: 59 // |sender|, |receiver|, |random_delay|, and |task_runner|, must all persist 60 // for the duration of this object's lifetime. 61 MdnsProbeManagerImpl(MdnsSender* sender, 62 MdnsReceiver* receiver, 63 MdnsRandom* random_delay, 64 TaskRunner* task_runner, 65 ClockNowFunctionPtr now_function); 66 MdnsProbeManagerImpl(const MdnsProbeManager& other) = delete; // NOLINT 67 MdnsProbeManagerImpl(MdnsProbeManager&& other) = delete; // NOLINT 68 ~MdnsProbeManagerImpl() override; 69 70 MdnsProbeManagerImpl& operator=(const MdnsProbeManagerImpl& other) = delete; 71 MdnsProbeManagerImpl& operator=(MdnsProbeManagerImpl&& other) = delete; 72 73 // Starts probing for a valid domain name based on the given one. This may 74 // only be called once per MdnsProbe instance. |observer| must persist until 75 // a valid domain is discovered and the observer's OnDomainFound method is 76 // called. 77 // NOTE: |address| is used to generate a 'fake' address record to use for the 78 // probe query. See MdnsProbe::PerformProbeIteration() for further details. 79 Error StartProbe(MdnsDomainConfirmedProvider* callback, 80 DomainName requested_name, 81 IPAddress address); 82 83 // Stops probing for the requested domain name. 84 Error StopProbe(const DomainName& requested_name); 85 86 // MdnsDomainOwnershipManager overrides. 87 bool IsDomainClaimed(const DomainName& domain) const override; 88 void RespondToProbeQuery(const MdnsMessage& message, 89 const IPEndpoint& src) override; 90 91 private: 92 friend class TestMdnsProbeManager; 93 94 // Resolves simultaneous probe queries as described in RFC 6762 section 8.2. 95 void TiebreakSimultaneousProbes(const MdnsMessage& message); 96 CreateProbe(DomainName name,IPAddress address)97 virtual std::unique_ptr<MdnsProbe> CreateProbe(DomainName name, 98 IPAddress address) { 99 return std::make_unique<MdnsProbeImpl>(sender_, receiver_, random_delay_, 100 task_runner_, now_function_, this, 101 std::move(name), std::move(address)); 102 } 103 104 // Owns an in-progress MdnsProbe. When the probe starts, an instance of this 105 // struct is created. Upon successful completion of the probe, this instance 106 // is deleted and the owned |probe| instance is moved to |completed_probes|. 107 // Upon failure, the instance is updated with a new MdnsProbe object and this 108 // process is repeated. 109 struct OngoingProbe { 110 OngoingProbe(std::unique_ptr<MdnsProbe> probe, 111 DomainName name, 112 MdnsDomainConfirmedProvider* callback); 113 114 // NOTE: unique_ptr objects are used to avoid issues when the container 115 // holding this object is resized. 116 std::unique_ptr<MdnsProbe> probe; 117 DomainName requested_name; 118 MdnsDomainConfirmedProvider* callback; 119 int num_probes_failed = 0; 120 }; 121 122 // MdnsProbe::Observer overrides. 123 void OnProbeSuccess(MdnsProbe* probe) override; 124 void OnProbeFailure(MdnsProbe* probe) override; 125 126 // Helpers to find ongoing and completed probes. 127 std::vector<std::unique_ptr<MdnsProbe>>::const_iterator FindCompletedProbe( 128 const DomainName& name) const; 129 std::vector<OngoingProbe>::iterator FindOngoingProbe(const DomainName& name); 130 std::vector<OngoingProbe>::iterator FindOngoingProbe(MdnsProbe* probe); 131 132 MdnsSender* const sender_; 133 MdnsReceiver* const receiver_; 134 MdnsRandom* const random_delay_; 135 TaskRunner* const task_runner_; 136 ClockNowFunctionPtr now_function_; 137 138 // The set of all probes which have completed successfully. This set is 139 // expected to remain small. unique_ptrs are used for storing the probes to 140 // avoid issues when the vector is resized. 141 std::vector<std::unique_ptr<MdnsProbe>> completed_probes_; 142 143 // The set of all currently ongoing probes. This set is expected to remain 144 // small. 145 std::vector<OngoingProbe> ongoing_probes_; 146 }; 147 148 } // namespace discovery 149 } // namespace openscreen 150 151 #endif // DISCOVERY_MDNS_MDNS_PROBE_MANAGER_H_ 152