• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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