1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved. 2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be 3*3f982cf4SFabien Sanglard // found in the LICENSE file. 4*3f982cf4SFabien Sanglard 5*3f982cf4SFabien Sanglard #ifndef DISCOVERY_MDNS_MDNS_PROBE_H_ 6*3f982cf4SFabien Sanglard #define DISCOVERY_MDNS_MDNS_PROBE_H_ 7*3f982cf4SFabien Sanglard 8*3f982cf4SFabien Sanglard #include <vector> 9*3f982cf4SFabien Sanglard 10*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_receiver.h" 11*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_records.h" 12*3f982cf4SFabien Sanglard #include "platform/api/time.h" 13*3f982cf4SFabien Sanglard #include "platform/base/ip_address.h" 14*3f982cf4SFabien Sanglard #include "util/alarm.h" 15*3f982cf4SFabien Sanglard 16*3f982cf4SFabien Sanglard namespace openscreen { 17*3f982cf4SFabien Sanglard 18*3f982cf4SFabien Sanglard class TaskRunner; 19*3f982cf4SFabien Sanglard 20*3f982cf4SFabien Sanglard namespace discovery { 21*3f982cf4SFabien Sanglard 22*3f982cf4SFabien Sanglard class MdnsQuerier; 23*3f982cf4SFabien Sanglard class MdnsRandom; 24*3f982cf4SFabien Sanglard class MdnsSender; 25*3f982cf4SFabien Sanglard 26*3f982cf4SFabien Sanglard // Implements the probing method as described in RFC 6762 section 8.1 to claim a 27*3f982cf4SFabien Sanglard // provided domain name. In place of the MdnsRecord(s) that will be published, a 28*3f982cf4SFabien Sanglard // 'fake' mDNS record of type A or AAAA will be generated from provided endpoint 29*3f982cf4SFabien Sanglard // variable with TTL 2 seconds. 0 or 1 seconds are not used because these 30*3f982cf4SFabien Sanglard // constants are used as part of goodbye records, so poorly written receivers 31*3f982cf4SFabien Sanglard // may handle these cases in unexpected ways. Caching of probe queries is not 32*3f982cf4SFabien Sanglard // supported for mDNS probes (else, in a probe which failed, invalid records 33*3f982cf4SFabien Sanglard // would be cached). If for some reason this did occur, though, it should be a 34*3f982cf4SFabien Sanglard // non-issue because the probe record will expire after 2 seconds. 35*3f982cf4SFabien Sanglard // 36*3f982cf4SFabien Sanglard // During probe query conflict resolution, these fake records will be compared 37*3f982cf4SFabien Sanglard // with the records provided by another mDNS endpoint. As 2 different mDNS 38*3f982cf4SFabien Sanglard // endpoints of the same service type cannot have the same endpoint, these 39*3f982cf4SFabien Sanglard // fake mDNS records should never match the real or fake records provided by 40*3f982cf4SFabien Sanglard // the other mDNS endpoint, so lexicographic comparison as described in RFC 41*3f982cf4SFabien Sanglard // 6762 section 8.2.1 can proceed as described. 42*3f982cf4SFabien Sanglard class MdnsProbe : public MdnsReceiver::ResponseClient { 43*3f982cf4SFabien Sanglard public: 44*3f982cf4SFabien Sanglard // The observer class is responsible for returning the result of an ongoing 45*3f982cf4SFabien Sanglard // probe query to the caller. 46*3f982cf4SFabien Sanglard class Observer { 47*3f982cf4SFabien Sanglard public: 48*3f982cf4SFabien Sanglard virtual ~Observer(); 49*3f982cf4SFabien Sanglard 50*3f982cf4SFabien Sanglard // Called once the probing phase has been completed successfully. |probe| is 51*3f982cf4SFabien Sanglard // expected to be stopped at the time of this call. 52*3f982cf4SFabien Sanglard virtual void OnProbeSuccess(MdnsProbe* probe) = 0; 53*3f982cf4SFabien Sanglard 54*3f982cf4SFabien Sanglard // Called once the probing phase fails. |probe| is expected to be stopped at 55*3f982cf4SFabien Sanglard // the time of this call. 56*3f982cf4SFabien Sanglard virtual void OnProbeFailure(MdnsProbe* probe) = 0; 57*3f982cf4SFabien Sanglard }; 58*3f982cf4SFabien Sanglard 59*3f982cf4SFabien Sanglard MdnsProbe(DomainName target_name, IPAddress address); 60*3f982cf4SFabien Sanglard virtual ~MdnsProbe(); 61*3f982cf4SFabien Sanglard 62*3f982cf4SFabien Sanglard // Postpones the current probe operation by |delay|, after which the probing 63*3f982cf4SFabien Sanglard // process is re-initialized. 64*3f982cf4SFabien Sanglard virtual void Postpone(std::chrono::seconds delay) = 0; 65*3f982cf4SFabien Sanglard target_name()66*3f982cf4SFabien Sanglard const DomainName& target_name() const { return target_name_; } address()67*3f982cf4SFabien Sanglard const IPAddress& address() const { return address_; } address_record()68*3f982cf4SFabien Sanglard const MdnsRecord address_record() const { return address_record_; } 69*3f982cf4SFabien Sanglard 70*3f982cf4SFabien Sanglard private: 71*3f982cf4SFabien Sanglard const DomainName target_name_; 72*3f982cf4SFabien Sanglard const IPAddress address_; 73*3f982cf4SFabien Sanglard const MdnsRecord address_record_; 74*3f982cf4SFabien Sanglard }; 75*3f982cf4SFabien Sanglard 76*3f982cf4SFabien Sanglard class MdnsProbeImpl : public MdnsProbe { 77*3f982cf4SFabien Sanglard public: 78*3f982cf4SFabien Sanglard // |sender|, |receiver|, |random_delay|, |task_runner|, and |observer| must 79*3f982cf4SFabien Sanglard // all persist for the duration of this object's lifetime. 80*3f982cf4SFabien Sanglard MdnsProbeImpl(MdnsSender* sender, 81*3f982cf4SFabien Sanglard MdnsReceiver* receiver, 82*3f982cf4SFabien Sanglard MdnsRandom* random_delay, 83*3f982cf4SFabien Sanglard TaskRunner* task_runner, 84*3f982cf4SFabien Sanglard ClockNowFunctionPtr now_function, 85*3f982cf4SFabien Sanglard Observer* observer, 86*3f982cf4SFabien Sanglard DomainName target_name, 87*3f982cf4SFabien Sanglard IPAddress address); 88*3f982cf4SFabien Sanglard MdnsProbeImpl(const MdnsProbeImpl& other) = delete; 89*3f982cf4SFabien Sanglard MdnsProbeImpl(MdnsProbeImpl&& other) = delete; 90*3f982cf4SFabien Sanglard ~MdnsProbeImpl() override; 91*3f982cf4SFabien Sanglard 92*3f982cf4SFabien Sanglard MdnsProbeImpl& operator=(const MdnsProbeImpl& other) = delete; 93*3f982cf4SFabien Sanglard MdnsProbeImpl& operator=(MdnsProbeImpl&& other) = delete; 94*3f982cf4SFabien Sanglard 95*3f982cf4SFabien Sanglard // MdnsProbe overrides. 96*3f982cf4SFabien Sanglard void Postpone(std::chrono::seconds delay) override; 97*3f982cf4SFabien Sanglard 98*3f982cf4SFabien Sanglard private: 99*3f982cf4SFabien Sanglard friend class MdnsProbeTests; 100*3f982cf4SFabien Sanglard 101*3f982cf4SFabien Sanglard // Performs the probe query as described in the class-level comment. 102*3f982cf4SFabien Sanglard void ProbeOnce(); 103*3f982cf4SFabien Sanglard 104*3f982cf4SFabien Sanglard // Stops this probe. 105*3f982cf4SFabien Sanglard void Stop(); 106*3f982cf4SFabien Sanglard 107*3f982cf4SFabien Sanglard // MdnsReceiver::ResponseClient overrides. 108*3f982cf4SFabien Sanglard void OnMessageReceived(const MdnsMessage& message) override; 109*3f982cf4SFabien Sanglard 110*3f982cf4SFabien Sanglard MdnsRandom* const random_delay_; 111*3f982cf4SFabien Sanglard TaskRunner* const task_runner_; 112*3f982cf4SFabien Sanglard ClockNowFunctionPtr now_function_; 113*3f982cf4SFabien Sanglard 114*3f982cf4SFabien Sanglard Alarm alarm_; 115*3f982cf4SFabien Sanglard 116*3f982cf4SFabien Sanglard // NOTE: Access to all below variables should only be done from the task 117*3f982cf4SFabien Sanglard // runner thread. 118*3f982cf4SFabien Sanglard MdnsSender* const sender_; 119*3f982cf4SFabien Sanglard MdnsReceiver* const receiver_; 120*3f982cf4SFabien Sanglard Observer* const observer_; 121*3f982cf4SFabien Sanglard 122*3f982cf4SFabien Sanglard int successful_probe_queries_ = 0; 123*3f982cf4SFabien Sanglard bool is_running_ = true; 124*3f982cf4SFabien Sanglard }; 125*3f982cf4SFabien Sanglard 126*3f982cf4SFabien Sanglard } // namespace discovery 127*3f982cf4SFabien Sanglard } // namespace openscreen 128*3f982cf4SFabien Sanglard 129*3f982cf4SFabien Sanglard #endif // DISCOVERY_MDNS_MDNS_PROBE_H_ 130