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