• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 #ifndef OSP_IMPL_MDNS_RESPONDER_SERVICE_H_
6 #define OSP_IMPL_MDNS_RESPONDER_SERVICE_H_
7 
8 #include <array>
9 #include <map>
10 #include <memory>
11 #include <set>
12 #include <string>
13 #include <vector>
14 
15 #include "osp/impl/discovery/mdns/mdns_responder_adapter.h"
16 #include "osp/impl/mdns_platform_service.h"
17 #include "osp/impl/service_listener_impl.h"
18 #include "osp/impl/service_publisher_impl.h"
19 #include "platform/api/network_interface.h"
20 #include "platform/api/task_runner.h"
21 #include "platform/api/time.h"
22 #include "platform/base/ip_address.h"
23 #include "util/alarm.h"
24 
25 namespace openscreen {
26 namespace osp {
27 
28 class MdnsResponderAdapterFactory {
29  public:
30   virtual ~MdnsResponderAdapterFactory() = default;
31 
32   virtual std::unique_ptr<MdnsResponderAdapter> Create() = 0;
33 };
34 
35 class MdnsResponderService : public ServiceListenerImpl::Delegate,
36                              public ServicePublisherImpl::Delegate,
37                              public UdpSocket::Client {
38  public:
39   MdnsResponderService(
40       ClockNowFunctionPtr now_function,
41       TaskRunner* task_runner,
42       const std::string& service_name,
43       const std::string& service_protocol,
44       std::unique_ptr<MdnsResponderAdapterFactory> mdns_responder_factory,
45       std::unique_ptr<MdnsPlatformService> platform);
46   ~MdnsResponderService() override;
47 
48   void SetServiceConfig(const std::string& hostname,
49                         const std::string& instance,
50                         uint16_t port,
51                         const std::vector<NetworkInterfaceIndex> allowlist,
52                         const std::map<std::string, std::string>& txt_data);
53 
54   // UdpSocket::Client overrides.
55   void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) override;
56   void OnSendError(UdpSocket* socket, Error error) override;
57   void OnError(UdpSocket* socket, Error error) override;
58 
59   // ServiceListenerImpl::Delegate overrides.
60   void StartListener() override;
61   void StartAndSuspendListener() override;
62   void StopListener() override;
63   void SuspendListener() override;
64   void ResumeListener() override;
65   void SearchNow(ServiceListener::State from) override;
66 
67   // ServicePublisherImpl::Delegate overrides.
68   void StartPublisher() override;
69   void StartAndSuspendPublisher() override;
70   void StopPublisher() override;
71   void SuspendPublisher() override;
72   void ResumePublisher() override;
73 
74  protected:
75   void HandleMdnsEvents();
76 
77   std::unique_ptr<MdnsResponderAdapter> mdns_responder_;
78 
79  private:
80   // Create internal versions of all public methods. These are used to push all
81   // calls to these methods to the task runner.
82   // TODO(rwkeane): Clean up these methods. Some result in multiple pushes to
83   // the task runner when just one would suffice.
84   // ServiceListenerImpl::Delegate overrides.
85   void StartListenerInternal();
86   void StartAndSuspendListenerInternal();
87   void StopListenerInternal();
88   void SuspendListenerInternal();
89   void ResumeListenerInternal();
90   void SearchNowInternal(ServiceListener::State from);
91   void StartPublisherInternal();
92   void StartAndSuspendPublisherInternal();
93   void StopPublisherInternal();
94   void SuspendPublisherInternal();
95   void ResumePublisherInternal();
96 
97   // NOTE: service_instance implicit in map key.
98   struct ServiceInstance {
99     UdpSocket* ptr_socket = nullptr;
100     DomainName domain_name;
101     uint16_t port = 0;
102     bool has_ptr_record = false;
103     std::vector<std::string> txt_info;
104 
105     // |port| == 0 signals that we have no SRV record.
has_srvServiceInstance106     bool has_srv() const { return port != 0; }
107   };
108 
109   // NOTE: hostname implicit in map key.
110   struct HostInfo {
111     std::vector<ServiceInstance*> services;
112     IPAddress v4_address;
113     IPAddress v6_address;
114   };
115 
116   struct NetworkScopedDomainName {
117     UdpSocket* socket;
118     DomainName domain_name;
119   };
120 
121   struct NetworkScopedDomainNameComparator {
122     bool operator()(const NetworkScopedDomainName& a,
123                     const NetworkScopedDomainName& b) const;
124   };
125 
126   using InstanceNameSet = std::set<DomainName, DomainNameComparator>;
127 
128   void StartListening();
129   void StopListening();
130   void StartService();
131   void StopService();
132   void StopMdnsResponder();
133   void UpdatePendingServiceInfoSet(InstanceNameSet* modified_instance_names,
134                                    const DomainName& domain_name);
135   void RemoveAllReceivers();
136 
137   // NOTE: |modified_instance_names| is used to track which service instances
138   // are modified by the record events.  See HandleMdnsEvents for more details.
139   bool HandlePtrEvent(const PtrEvent& ptr_event,
140                       InstanceNameSet* modified_instance_names);
141   bool HandleSrvEvent(const SrvEvent& srv_event,
142                       InstanceNameSet* modified_instance_names);
143   bool HandleTxtEvent(const TxtEvent& txt_event,
144                       InstanceNameSet* modified_instance_names);
145   bool HandleAddressEvent(UdpSocket* socket,
146                           QueryEventHeader::Type response_type,
147                           const DomainName& domain_name,
148                           bool a_event,
149                           const IPAddress& address,
150                           InstanceNameSet* modified_instance_names);
151   bool HandleAEvent(const AEvent& a_event,
152                     InstanceNameSet* modified_instance_names);
153   bool HandleAaaaEvent(const AaaaEvent& aaaa_event,
154                        InstanceNameSet* modified_instance_names);
155 
156   HostInfo* AddOrGetHostInfo(UdpSocket* socket, const DomainName& domain_name);
157   HostInfo* GetHostInfo(UdpSocket* socket, const DomainName& domain_name);
158   bool IsServiceReady(const ServiceInstance& instance, HostInfo* host) const;
159   NetworkInterfaceIndex GetNetworkInterfaceIndexFromSocket(
160       const UdpSocket* socket) const;
161 
162   // Runs background tasks to manage the internal mDNS state.
163   void RunBackgroundTasks();
164 
165   // Service type separated as service name and service protocol for both
166   // listening and publishing (e.g. {"_openscreen", "_udp"}).
167   std::array<std::string, 2> service_type_;
168 
169   // The following variables all relate to what MdnsResponderService publishes,
170   // if anything.
171   std::string service_hostname_;
172   std::string service_instance_name_;
173   uint16_t service_port_;
174   std::vector<NetworkInterfaceIndex> interface_index_allowlist_;
175   std::map<std::string, std::string> service_txt_data_;
176 
177   std::unique_ptr<MdnsResponderAdapterFactory> mdns_responder_factory_;
178   std::unique_ptr<MdnsPlatformService> platform_;
179   std::vector<MdnsPlatformService::BoundInterface> bound_interfaces_;
180 
181   // A map of service information collected from PTR, SRV, and TXT records.  It
182   // is keyed by service instance names.
183   std::map<DomainName, std::unique_ptr<ServiceInstance>, DomainNameComparator>
184       service_by_name_;
185 
186   // The map key is a combination of the interface to which the address records
187   // belong and the hostname of the address records.  The values are IPAddresses
188   // for the given hostname on the given network and pointers to dependent
189   // service instances.  The service instance pointers act as a reference count
190   // to keep the A/AAAA queries alive, when more than one service refers to the
191   // same hostname.  This is not currently used by openscreen, but is used by
192   // Cast, so may be supported in openscreen in the future.
193   std::map<NetworkScopedDomainName, HostInfo, NetworkScopedDomainNameComparator>
194       network_scoped_domain_to_host_;
195 
196   std::map<std::string, ServiceInfo> receiver_info_;
197 
198   TaskRunner* const task_runner_;
199 
200   // Scheduled to run periodic background tasks.
201   Alarm background_tasks_alarm_;
202 
203   friend class TestingMdnsResponderService;
204 };
205 
206 }  // namespace osp
207 }  // namespace openscreen
208 
209 #endif  // OSP_IMPL_MDNS_RESPONDER_SERVICE_H_
210