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_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_ 6 #define OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_ 7 8 #include <map> 9 #include <memory> 10 #include <string> 11 #include <vector> 12 13 #include "osp/impl/discovery/mdns/mdns_responder_adapter.h" 14 #include "platform/api/udp_socket.h" 15 #include "platform/base/error.h" 16 #include "third_party/mDNSResponder/src/mDNSCore/mDNSEmbeddedAPI.h" 17 18 namespace openscreen { 19 namespace osp { 20 21 class MdnsResponderAdapterImpl final : public MdnsResponderAdapter { 22 public: 23 static constexpr int kRrCacheSize = 500; 24 25 MdnsResponderAdapterImpl(); 26 ~MdnsResponderAdapterImpl() override; 27 28 Error Init() override; 29 void Close() override; 30 31 Error SetHostLabel(const std::string& host_label) override; 32 33 Error RegisterInterface(const InterfaceInfo& interface_info, 34 const IPSubnet& interface_address, 35 UdpSocket* socket) override; 36 Error DeregisterInterface(UdpSocket* socket) override; 37 38 void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) override; 39 void OnSendError(UdpSocket* socket, Error error) override; 40 void OnError(UdpSocket* socket, Error error) override; 41 void OnBound(UdpSocket* socket) override; 42 43 Clock::duration RunTasks() override; 44 45 std::vector<PtrEvent> TakePtrResponses() override; 46 std::vector<SrvEvent> TakeSrvResponses() override; 47 std::vector<TxtEvent> TakeTxtResponses() override; 48 std::vector<AEvent> TakeAResponses() override; 49 std::vector<AaaaEvent> TakeAaaaResponses() override; 50 51 MdnsResponderErrorCode StartPtrQuery(UdpSocket* socket, 52 const DomainName& service_type) override; 53 MdnsResponderErrorCode StartSrvQuery( 54 UdpSocket* socket, 55 const DomainName& service_instance) override; 56 MdnsResponderErrorCode StartTxtQuery( 57 UdpSocket* socket, 58 const DomainName& service_instance) override; 59 MdnsResponderErrorCode StartAQuery(UdpSocket* socket, 60 const DomainName& domain_name) override; 61 MdnsResponderErrorCode StartAaaaQuery(UdpSocket* socket, 62 const DomainName& domain_name) override; 63 MdnsResponderErrorCode StopPtrQuery(UdpSocket* socket, 64 const DomainName& service_type) override; 65 MdnsResponderErrorCode StopSrvQuery( 66 UdpSocket* socket, 67 const DomainName& service_instance) override; 68 MdnsResponderErrorCode StopTxtQuery( 69 UdpSocket* socket, 70 const DomainName& service_instance) override; 71 MdnsResponderErrorCode StopAQuery(UdpSocket* socket, 72 const DomainName& domain_name) override; 73 MdnsResponderErrorCode StopAaaaQuery(UdpSocket* socket, 74 const DomainName& domain_name) override; 75 76 MdnsResponderErrorCode RegisterService( 77 const std::string& service_instance, 78 const std::string& service_name, 79 const std::string& service_protocol, 80 const DomainName& target_host, 81 uint16_t target_port, 82 const std::map<std::string, std::string>& txt_data) override; 83 MdnsResponderErrorCode DeregisterService( 84 const std::string& service_instance, 85 const std::string& service_name, 86 const std::string& service_protocol) override; 87 MdnsResponderErrorCode UpdateTxtData( 88 const std::string& service_instance, 89 const std::string& service_name, 90 const std::string& service_protocol, 91 const std::map<std::string, std::string>& txt_data) override; 92 93 private: 94 struct Questions { 95 std::map<DomainName, DNSQuestion, DomainNameComparator> a; 96 std::map<DomainName, DNSQuestion, DomainNameComparator> aaaa; 97 std::map<DomainName, DNSQuestion, DomainNameComparator> ptr; 98 std::map<DomainName, DNSQuestion, DomainNameComparator> srv; 99 std::map<DomainName, DNSQuestion, DomainNameComparator> txt; 100 }; 101 102 static void AQueryCallback(mDNS* m, 103 DNSQuestion* question, 104 const ResourceRecord* answer, 105 QC_result added); 106 static void AaaaQueryCallback(mDNS* m, 107 DNSQuestion* question, 108 const ResourceRecord* answer, 109 QC_result added); 110 static void PtrQueryCallback(mDNS* m, 111 DNSQuestion* question, 112 const ResourceRecord* answer, 113 QC_result added); 114 static void SrvQueryCallback(mDNS* m, 115 DNSQuestion* question, 116 const ResourceRecord* answer, 117 QC_result added); 118 static void TxtQueryCallback(mDNS* m, 119 DNSQuestion* question, 120 const ResourceRecord* answer, 121 QC_result added); 122 static void ServiceCallback(mDNS* m, 123 ServiceRecordSet* service_record, 124 mStatus result); 125 126 void AdvertiseInterfaces(); 127 void DeadvertiseInterfaces(); 128 void RemoveQuestionsIfEmpty(UdpSocket* socket); 129 130 CacheEntity rr_cache_[kRrCacheSize]; 131 132 // The main context structure for mDNSResponder. 133 mDNS mdns_; 134 135 // Our own storage that is placed inside |mdns_|. The intent in C is to allow 136 // us access to our own state during callbacks. Here we just use it to group 137 // platform sockets. 138 mDNS_PlatformSupport platform_storage_; 139 140 std::map<UdpSocket*, Questions> socket_to_questions_; 141 142 std::map<UdpSocket*, NetworkInterfaceInfo> responder_interface_info_; 143 144 std::vector<AEvent> a_responses_; 145 std::vector<AaaaEvent> aaaa_responses_; 146 std::vector<PtrEvent> ptr_responses_; 147 std::vector<SrvEvent> srv_responses_; 148 std::vector<TxtEvent> txt_responses_; 149 150 // A list of services we are advertising. ServiceRecordSet is an 151 // mDNSResponder structure which holds all the resource record data 152 // (PTR/SRV/TXT/A and misc.) that is necessary to advertise a service. 153 std::vector<std::unique_ptr<ServiceRecordSet>> service_records_; 154 }; 155 156 } // namespace osp 157 } // namespace openscreen 158 159 #endif // OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_ 160