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