xref: /aosp_15_r20/external/openscreen/discovery/mdns/mdns_probe.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
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 #include "discovery/mdns/mdns_probe.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <utility>
8*3f982cf4SFabien Sanglard 
9*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_random.h"
10*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_sender.h"
11*3f982cf4SFabien Sanglard #include "discovery/mdns/public/mdns_constants.h"
12*3f982cf4SFabien Sanglard #include "platform/api/task_runner.h"
13*3f982cf4SFabien Sanglard #include "platform/api/time.h"
14*3f982cf4SFabien Sanglard 
15*3f982cf4SFabien Sanglard namespace openscreen {
16*3f982cf4SFabien Sanglard namespace discovery {
17*3f982cf4SFabien Sanglard 
MdnsProbe(DomainName target_name,IPAddress address)18*3f982cf4SFabien Sanglard MdnsProbe::MdnsProbe(DomainName target_name, IPAddress address)
19*3f982cf4SFabien Sanglard     : target_name_(std::move(target_name)),
20*3f982cf4SFabien Sanglard       address_(std::move(address)),
21*3f982cf4SFabien Sanglard       address_record_(CreateAddressRecord(target_name_, address_)) {}
22*3f982cf4SFabien Sanglard 
23*3f982cf4SFabien Sanglard MdnsProbe::~MdnsProbe() = default;
24*3f982cf4SFabien Sanglard 
25*3f982cf4SFabien Sanglard MdnsProbeImpl::Observer::~Observer() = default;
26*3f982cf4SFabien Sanglard 
MdnsProbeImpl(MdnsSender * sender,MdnsReceiver * receiver,MdnsRandom * random_delay,TaskRunner * task_runner,ClockNowFunctionPtr now_function,Observer * observer,DomainName target_name,IPAddress address)27*3f982cf4SFabien Sanglard MdnsProbeImpl::MdnsProbeImpl(MdnsSender* sender,
28*3f982cf4SFabien Sanglard                              MdnsReceiver* receiver,
29*3f982cf4SFabien Sanglard                              MdnsRandom* random_delay,
30*3f982cf4SFabien Sanglard                              TaskRunner* task_runner,
31*3f982cf4SFabien Sanglard                              ClockNowFunctionPtr now_function,
32*3f982cf4SFabien Sanglard                              Observer* observer,
33*3f982cf4SFabien Sanglard                              DomainName target_name,
34*3f982cf4SFabien Sanglard                              IPAddress address)
35*3f982cf4SFabien Sanglard     : MdnsProbe(std::move(target_name), std::move(address)),
36*3f982cf4SFabien Sanglard       random_delay_(random_delay),
37*3f982cf4SFabien Sanglard       task_runner_(task_runner),
38*3f982cf4SFabien Sanglard       now_function_(now_function),
39*3f982cf4SFabien Sanglard       alarm_(now_function_, task_runner_),
40*3f982cf4SFabien Sanglard       sender_(sender),
41*3f982cf4SFabien Sanglard       receiver_(receiver),
42*3f982cf4SFabien Sanglard       observer_(observer) {
43*3f982cf4SFabien Sanglard   OSP_DCHECK(sender_);
44*3f982cf4SFabien Sanglard   OSP_DCHECK(receiver_);
45*3f982cf4SFabien Sanglard   OSP_DCHECK(random_delay_);
46*3f982cf4SFabien Sanglard   OSP_DCHECK(task_runner_);
47*3f982cf4SFabien Sanglard   OSP_DCHECK(observer_);
48*3f982cf4SFabien Sanglard 
49*3f982cf4SFabien Sanglard   receiver_->AddResponseCallback(this);
50*3f982cf4SFabien Sanglard   alarm_.ScheduleFromNow([this]() { ProbeOnce(); },
51*3f982cf4SFabien Sanglard                          random_delay_->GetInitialProbeDelay());
52*3f982cf4SFabien Sanglard }
53*3f982cf4SFabien Sanglard 
~MdnsProbeImpl()54*3f982cf4SFabien Sanglard MdnsProbeImpl::~MdnsProbeImpl() {
55*3f982cf4SFabien Sanglard   OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
56*3f982cf4SFabien Sanglard 
57*3f982cf4SFabien Sanglard   Stop();
58*3f982cf4SFabien Sanglard }
59*3f982cf4SFabien Sanglard 
ProbeOnce()60*3f982cf4SFabien Sanglard void MdnsProbeImpl::ProbeOnce() {
61*3f982cf4SFabien Sanglard   OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
62*3f982cf4SFabien Sanglard 
63*3f982cf4SFabien Sanglard   if (successful_probe_queries_++ < kProbeIterationCountBeforeSuccess) {
64*3f982cf4SFabien Sanglard     // MdnsQuerier cannot be used, because probe queries cannot use the cache,
65*3f982cf4SFabien Sanglard     // so instead directly send the query through the MdnsSender.
66*3f982cf4SFabien Sanglard     MdnsMessage probe_query(CreateMessageId(), MessageType::Query);
67*3f982cf4SFabien Sanglard     MdnsQuestion probe_question(target_name(), DnsType::kANY, DnsClass::kIN,
68*3f982cf4SFabien Sanglard                                 ResponseType::kUnicast);
69*3f982cf4SFabien Sanglard     probe_query.AddQuestion(probe_question);
70*3f982cf4SFabien Sanglard     probe_query.AddAuthorityRecord(address_record());
71*3f982cf4SFabien Sanglard     sender_->SendMulticast(probe_query);
72*3f982cf4SFabien Sanglard 
73*3f982cf4SFabien Sanglard     alarm_.ScheduleFromNow([this]() { ProbeOnce(); },
74*3f982cf4SFabien Sanglard                            kDelayBetweenProbeQueries);
75*3f982cf4SFabien Sanglard   } else {
76*3f982cf4SFabien Sanglard     Stop();
77*3f982cf4SFabien Sanglard     observer_->OnProbeSuccess(this);
78*3f982cf4SFabien Sanglard   }
79*3f982cf4SFabien Sanglard }
80*3f982cf4SFabien Sanglard 
Stop()81*3f982cf4SFabien Sanglard void MdnsProbeImpl::Stop() {
82*3f982cf4SFabien Sanglard   OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
83*3f982cf4SFabien Sanglard 
84*3f982cf4SFabien Sanglard   if (is_running_) {
85*3f982cf4SFabien Sanglard     alarm_.Cancel();
86*3f982cf4SFabien Sanglard     receiver_->RemoveResponseCallback(this);
87*3f982cf4SFabien Sanglard     is_running_ = false;
88*3f982cf4SFabien Sanglard   }
89*3f982cf4SFabien Sanglard }
90*3f982cf4SFabien Sanglard 
Postpone(std::chrono::seconds delay)91*3f982cf4SFabien Sanglard void MdnsProbeImpl::Postpone(std::chrono::seconds delay) {
92*3f982cf4SFabien Sanglard   OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
93*3f982cf4SFabien Sanglard 
94*3f982cf4SFabien Sanglard   successful_probe_queries_ = 0;
95*3f982cf4SFabien Sanglard   alarm_.Cancel();
96*3f982cf4SFabien Sanglard   alarm_.ScheduleFromNow([this]() { ProbeOnce(); }, Clock::to_duration(delay));
97*3f982cf4SFabien Sanglard }
98*3f982cf4SFabien Sanglard 
OnMessageReceived(const MdnsMessage & message)99*3f982cf4SFabien Sanglard void MdnsProbeImpl::OnMessageReceived(const MdnsMessage& message) {
100*3f982cf4SFabien Sanglard   OSP_DCHECK(task_runner_->IsRunningOnTaskRunner());
101*3f982cf4SFabien Sanglard   OSP_DCHECK(message.type() == MessageType::Response);
102*3f982cf4SFabien Sanglard 
103*3f982cf4SFabien Sanglard   for (const auto& record : message.answers()) {
104*3f982cf4SFabien Sanglard     if (record.name() == target_name()) {
105*3f982cf4SFabien Sanglard       Stop();
106*3f982cf4SFabien Sanglard       observer_->OnProbeFailure(this);
107*3f982cf4SFabien Sanglard     }
108*3f982cf4SFabien Sanglard   }
109*3f982cf4SFabien Sanglard }
110*3f982cf4SFabien Sanglard 
111*3f982cf4SFabien Sanglard }  // namespace discovery
112*3f982cf4SFabien Sanglard }  // namespace openscreen
113