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_service_impl.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <memory>
8*3f982cf4SFabien Sanglard #include <utility>
9*3f982cf4SFabien Sanglard #include <vector>
10*3f982cf4SFabien Sanglard
11*3f982cf4SFabien Sanglard #include "discovery/common/reporting_client.h"
12*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_records.h"
13*3f982cf4SFabien Sanglard #include "discovery/mdns/public/mdns_constants.h"
14*3f982cf4SFabien Sanglard
15*3f982cf4SFabien Sanglard namespace openscreen {
16*3f982cf4SFabien Sanglard namespace discovery {
17*3f982cf4SFabien Sanglard
18*3f982cf4SFabien Sanglard // static
Create(TaskRunner * task_runner,ReportingClient * reporting_client,const Config & config,const InterfaceInfo & network_info)19*3f982cf4SFabien Sanglard std::unique_ptr<MdnsService> MdnsService::Create(
20*3f982cf4SFabien Sanglard TaskRunner* task_runner,
21*3f982cf4SFabien Sanglard ReportingClient* reporting_client,
22*3f982cf4SFabien Sanglard const Config& config,
23*3f982cf4SFabien Sanglard const InterfaceInfo& network_info) {
24*3f982cf4SFabien Sanglard return std::make_unique<MdnsServiceImpl>(
25*3f982cf4SFabien Sanglard task_runner, Clock::now, reporting_client, config, network_info);
26*3f982cf4SFabien Sanglard }
27*3f982cf4SFabien Sanglard
MdnsServiceImpl(TaskRunner * task_runner,ClockNowFunctionPtr now_function,ReportingClient * reporting_client,const Config & config,const InterfaceInfo & network_info)28*3f982cf4SFabien Sanglard MdnsServiceImpl::MdnsServiceImpl(TaskRunner* task_runner,
29*3f982cf4SFabien Sanglard ClockNowFunctionPtr now_function,
30*3f982cf4SFabien Sanglard ReportingClient* reporting_client,
31*3f982cf4SFabien Sanglard const Config& config,
32*3f982cf4SFabien Sanglard const InterfaceInfo& network_info)
33*3f982cf4SFabien Sanglard : task_runner_(task_runner),
34*3f982cf4SFabien Sanglard now_function_(now_function),
35*3f982cf4SFabien Sanglard reporting_client_(reporting_client),
36*3f982cf4SFabien Sanglard receiver_(config),
37*3f982cf4SFabien Sanglard interface_(network_info.index) {
38*3f982cf4SFabien Sanglard OSP_DCHECK(task_runner_);
39*3f982cf4SFabien Sanglard OSP_DCHECK(reporting_client_);
40*3f982cf4SFabien Sanglard
41*3f982cf4SFabien Sanglard // Create all UDP sockets needed for this object. They should not yet be bound
42*3f982cf4SFabien Sanglard // so that they do not send or receive data until the objects on which their
43*3f982cf4SFabien Sanglard // callback depends is initialized.
44*3f982cf4SFabien Sanglard // NOTE: we bind to the Any addresses here because traffic is filtered by
45*3f982cf4SFabien Sanglard // the multicast join calls.
46*3f982cf4SFabien Sanglard if (network_info.GetIpAddressV4()) {
47*3f982cf4SFabien Sanglard ErrorOr<std::unique_ptr<UdpSocket>> socket = UdpSocket::Create(
48*3f982cf4SFabien Sanglard task_runner, this,
49*3f982cf4SFabien Sanglard IPEndpoint{IPAddress::kAnyV4(), kDefaultMulticastPort});
50*3f982cf4SFabien Sanglard OSP_DCHECK(!socket.is_error());
51*3f982cf4SFabien Sanglard OSP_DCHECK(socket.value().get());
52*3f982cf4SFabien Sanglard OSP_DCHECK(socket.value()->IsIPv4());
53*3f982cf4SFabien Sanglard
54*3f982cf4SFabien Sanglard socket_v4_ = std::move(socket.value());
55*3f982cf4SFabien Sanglard }
56*3f982cf4SFabien Sanglard
57*3f982cf4SFabien Sanglard if (network_info.GetIpAddressV6()) {
58*3f982cf4SFabien Sanglard ErrorOr<std::unique_ptr<UdpSocket>> socket = UdpSocket::Create(
59*3f982cf4SFabien Sanglard task_runner, this,
60*3f982cf4SFabien Sanglard IPEndpoint{IPAddress::kAnyV6(), kDefaultMulticastPort});
61*3f982cf4SFabien Sanglard OSP_DCHECK(!socket.is_error());
62*3f982cf4SFabien Sanglard OSP_DCHECK(socket.value().get());
63*3f982cf4SFabien Sanglard OSP_DCHECK(socket.value()->IsIPv6());
64*3f982cf4SFabien Sanglard
65*3f982cf4SFabien Sanglard socket_v6_ = std::move(socket.value());
66*3f982cf4SFabien Sanglard }
67*3f982cf4SFabien Sanglard
68*3f982cf4SFabien Sanglard // Initialize objects which depend on the above sockets.
69*3f982cf4SFabien Sanglard UdpSocket* socket_ptr =
70*3f982cf4SFabien Sanglard socket_v4_.get() ? socket_v4_.get() : socket_v6_.get();
71*3f982cf4SFabien Sanglard OSP_DCHECK(socket_ptr);
72*3f982cf4SFabien Sanglard sender_ = std::make_unique<MdnsSender>(socket_ptr);
73*3f982cf4SFabien Sanglard if (config.enable_querying) {
74*3f982cf4SFabien Sanglard querier_ = std::make_unique<MdnsQuerier>(
75*3f982cf4SFabien Sanglard sender_.get(), &receiver_, task_runner_, now_function_, &random_delay_,
76*3f982cf4SFabien Sanglard reporting_client_, config);
77*3f982cf4SFabien Sanglard }
78*3f982cf4SFabien Sanglard if (config.enable_publication) {
79*3f982cf4SFabien Sanglard probe_manager_ = std::make_unique<MdnsProbeManagerImpl>(
80*3f982cf4SFabien Sanglard sender_.get(), &receiver_, &random_delay_, task_runner_, now_function_);
81*3f982cf4SFabien Sanglard publisher_ =
82*3f982cf4SFabien Sanglard std::make_unique<MdnsPublisher>(sender_.get(), probe_manager_.get(),
83*3f982cf4SFabien Sanglard task_runner_, now_function_, config);
84*3f982cf4SFabien Sanglard responder_ = std::make_unique<MdnsResponder>(
85*3f982cf4SFabien Sanglard publisher_.get(), probe_manager_.get(), sender_.get(), &receiver_,
86*3f982cf4SFabien Sanglard task_runner_, now_function_, &random_delay_, config);
87*3f982cf4SFabien Sanglard }
88*3f982cf4SFabien Sanglard
89*3f982cf4SFabien Sanglard receiver_.Start();
90*3f982cf4SFabien Sanglard
91*3f982cf4SFabien Sanglard // Initialize all sockets to start sending/receiving data. Now that the above
92*3f982cf4SFabien Sanglard // objects have all been created, it they should be able to safely do so.
93*3f982cf4SFabien Sanglard // NOTE: Although only one of these sockets is used for sending, both will be
94*3f982cf4SFabien Sanglard // used for reading on the mDNS v4 and v6 addresses and ports.
95*3f982cf4SFabien Sanglard if (socket_v4_) {
96*3f982cf4SFabien Sanglard socket_v4_->Bind();
97*3f982cf4SFabien Sanglard }
98*3f982cf4SFabien Sanglard if (socket_v6_) {
99*3f982cf4SFabien Sanglard socket_v6_->Bind();
100*3f982cf4SFabien Sanglard }
101*3f982cf4SFabien Sanglard }
102*3f982cf4SFabien Sanglard
103*3f982cf4SFabien Sanglard MdnsServiceImpl::~MdnsServiceImpl() = default;
104*3f982cf4SFabien Sanglard
StartQuery(const DomainName & name,DnsType dns_type,DnsClass dns_class,MdnsRecordChangedCallback * callback)105*3f982cf4SFabien Sanglard void MdnsServiceImpl::StartQuery(const DomainName& name,
106*3f982cf4SFabien Sanglard DnsType dns_type,
107*3f982cf4SFabien Sanglard DnsClass dns_class,
108*3f982cf4SFabien Sanglard MdnsRecordChangedCallback* callback) {
109*3f982cf4SFabien Sanglard return querier_->StartQuery(name, dns_type, dns_class, callback);
110*3f982cf4SFabien Sanglard }
111*3f982cf4SFabien Sanglard
StopQuery(const DomainName & name,DnsType dns_type,DnsClass dns_class,MdnsRecordChangedCallback * callback)112*3f982cf4SFabien Sanglard void MdnsServiceImpl::StopQuery(const DomainName& name,
113*3f982cf4SFabien Sanglard DnsType dns_type,
114*3f982cf4SFabien Sanglard DnsClass dns_class,
115*3f982cf4SFabien Sanglard MdnsRecordChangedCallback* callback) {
116*3f982cf4SFabien Sanglard return querier_->StopQuery(name, dns_type, dns_class, callback);
117*3f982cf4SFabien Sanglard }
118*3f982cf4SFabien Sanglard
ReinitializeQueries(const DomainName & name)119*3f982cf4SFabien Sanglard void MdnsServiceImpl::ReinitializeQueries(const DomainName& name) {
120*3f982cf4SFabien Sanglard querier_->ReinitializeQueries(name);
121*3f982cf4SFabien Sanglard }
122*3f982cf4SFabien Sanglard
StartProbe(MdnsDomainConfirmedProvider * callback,DomainName requested_name,IPAddress address)123*3f982cf4SFabien Sanglard Error MdnsServiceImpl::StartProbe(MdnsDomainConfirmedProvider* callback,
124*3f982cf4SFabien Sanglard DomainName requested_name,
125*3f982cf4SFabien Sanglard IPAddress address) {
126*3f982cf4SFabien Sanglard return probe_manager_->StartProbe(callback, std::move(requested_name),
127*3f982cf4SFabien Sanglard std::move(address));
128*3f982cf4SFabien Sanglard }
129*3f982cf4SFabien Sanglard
RegisterRecord(const MdnsRecord & record)130*3f982cf4SFabien Sanglard Error MdnsServiceImpl::RegisterRecord(const MdnsRecord& record) {
131*3f982cf4SFabien Sanglard return publisher_->RegisterRecord(record);
132*3f982cf4SFabien Sanglard }
133*3f982cf4SFabien Sanglard
UpdateRegisteredRecord(const MdnsRecord & old_record,const MdnsRecord & new_record)134*3f982cf4SFabien Sanglard Error MdnsServiceImpl::UpdateRegisteredRecord(const MdnsRecord& old_record,
135*3f982cf4SFabien Sanglard const MdnsRecord& new_record) {
136*3f982cf4SFabien Sanglard return publisher_->UpdateRegisteredRecord(old_record, new_record);
137*3f982cf4SFabien Sanglard }
138*3f982cf4SFabien Sanglard
UnregisterRecord(const MdnsRecord & record)139*3f982cf4SFabien Sanglard Error MdnsServiceImpl::UnregisterRecord(const MdnsRecord& record) {
140*3f982cf4SFabien Sanglard return publisher_->UnregisterRecord(record);
141*3f982cf4SFabien Sanglard }
142*3f982cf4SFabien Sanglard
OnError(UdpSocket * socket,Error error)143*3f982cf4SFabien Sanglard void MdnsServiceImpl::OnError(UdpSocket* socket, Error error) {
144*3f982cf4SFabien Sanglard reporting_client_->OnFatalError(error);
145*3f982cf4SFabien Sanglard }
146*3f982cf4SFabien Sanglard
OnSendError(UdpSocket * socket,Error error)147*3f982cf4SFabien Sanglard void MdnsServiceImpl::OnSendError(UdpSocket* socket, Error error) {
148*3f982cf4SFabien Sanglard sender_->OnSendError(socket, error);
149*3f982cf4SFabien Sanglard }
150*3f982cf4SFabien Sanglard
OnRead(UdpSocket * socket,ErrorOr<UdpPacket> packet)151*3f982cf4SFabien Sanglard void MdnsServiceImpl::OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) {
152*3f982cf4SFabien Sanglard receiver_.OnRead(socket, std::move(packet));
153*3f982cf4SFabien Sanglard }
154*3f982cf4SFabien Sanglard
OnBound(UdpSocket * socket)155*3f982cf4SFabien Sanglard void MdnsServiceImpl::OnBound(UdpSocket* socket) {
156*3f982cf4SFabien Sanglard // Socket configuration must occur after the socket has been bound
157*3f982cf4SFabien Sanglard // successfully.
158*3f982cf4SFabien Sanglard if (socket == socket_v4_.get()) {
159*3f982cf4SFabien Sanglard socket_v4_->SetMulticastOutboundInterface(interface_);
160*3f982cf4SFabien Sanglard socket_v4_->JoinMulticastGroup(kDefaultMulticastGroupIPv4, interface_);
161*3f982cf4SFabien Sanglard socket_v4_->JoinMulticastGroup(kDefaultSiteLocalGroupIPv4, interface_);
162*3f982cf4SFabien Sanglard } else if (socket == socket_v6_.get()) {
163*3f982cf4SFabien Sanglard socket_v6_->SetMulticastOutboundInterface(interface_);
164*3f982cf4SFabien Sanglard socket_v6_->JoinMulticastGroup(kDefaultMulticastGroupIPv6, interface_);
165*3f982cf4SFabien Sanglard socket_v6_->JoinMulticastGroup(kDefaultSiteLocalGroupIPv6, interface_);
166*3f982cf4SFabien Sanglard } else {
167*3f982cf4SFabien Sanglard // Sanity check: we shouldn't be called for sockets we haven't subscribed
168*3f982cf4SFabien Sanglard // to.
169*3f982cf4SFabien Sanglard OSP_NOTREACHED();
170*3f982cf4SFabien Sanglard }
171*3f982cf4SFabien Sanglard }
172*3f982cf4SFabien Sanglard
173*3f982cf4SFabien Sanglard } // namespace discovery
174*3f982cf4SFabien Sanglard } // namespace openscreen
175