• 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 #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