blob: d0dd55a1b3c3bd4a8e65c37613a605d135b106a2 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_
#define OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "osp/impl/discovery/mdns/mdns_responder_adapter.h"
#include "platform/api/udp_socket.h"
#include "platform/base/error.h"
#include "third_party/mDNSResponder/src/mDNSCore/mDNSEmbeddedAPI.h"
namespace openscreen {
namespace osp {
class MdnsResponderAdapterImpl final : public MdnsResponderAdapter {
public:
static constexpr int kRrCacheSize = 500;
MdnsResponderAdapterImpl();
~MdnsResponderAdapterImpl() override;
Error Init() override;
void Close() override;
Error SetHostLabel(const std::string& host_label) override;
Error RegisterInterface(const InterfaceInfo& interface_info,
const IPSubnet& interface_address,
UdpSocket* socket) override;
Error DeregisterInterface(UdpSocket* socket) override;
void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) override;
void OnSendError(UdpSocket* socket, Error error) override;
void OnError(UdpSocket* socket, Error error) override;
void OnBound(UdpSocket* socket) override;
Clock::duration RunTasks() override;
std::vector<PtrEvent> TakePtrResponses() override;
std::vector<SrvEvent> TakeSrvResponses() override;
std::vector<TxtEvent> TakeTxtResponses() override;
std::vector<AEvent> TakeAResponses() override;
std::vector<AaaaEvent> TakeAaaaResponses() override;
MdnsResponderErrorCode StartPtrQuery(UdpSocket* socket,
const DomainName& service_type) override;
MdnsResponderErrorCode StartSrvQuery(
UdpSocket* socket,
const DomainName& service_instance) override;
MdnsResponderErrorCode StartTxtQuery(
UdpSocket* socket,
const DomainName& service_instance) override;
MdnsResponderErrorCode StartAQuery(UdpSocket* socket,
const DomainName& domain_name) override;
MdnsResponderErrorCode StartAaaaQuery(UdpSocket* socket,
const DomainName& domain_name) override;
MdnsResponderErrorCode StopPtrQuery(UdpSocket* socket,
const DomainName& service_type) override;
MdnsResponderErrorCode StopSrvQuery(
UdpSocket* socket,
const DomainName& service_instance) override;
MdnsResponderErrorCode StopTxtQuery(
UdpSocket* socket,
const DomainName& service_instance) override;
MdnsResponderErrorCode StopAQuery(UdpSocket* socket,
const DomainName& domain_name) override;
MdnsResponderErrorCode StopAaaaQuery(UdpSocket* socket,
const DomainName& domain_name) override;
MdnsResponderErrorCode RegisterService(
const std::string& service_instance,
const std::string& service_name,
const std::string& service_protocol,
const DomainName& target_host,
uint16_t target_port,
const std::map<std::string, std::string>& txt_data) override;
MdnsResponderErrorCode DeregisterService(
const std::string& service_instance,
const std::string& service_name,
const std::string& service_protocol) override;
MdnsResponderErrorCode UpdateTxtData(
const std::string& service_instance,
const std::string& service_name,
const std::string& service_protocol,
const std::map<std::string, std::string>& txt_data) override;
private:
struct Questions {
std::map<DomainName, DNSQuestion, DomainNameComparator> a;
std::map<DomainName, DNSQuestion, DomainNameComparator> aaaa;
std::map<DomainName, DNSQuestion, DomainNameComparator> ptr;
std::map<DomainName, DNSQuestion, DomainNameComparator> srv;
std::map<DomainName, DNSQuestion, DomainNameComparator> txt;
};
static void AQueryCallback(mDNS* m,
DNSQuestion* question,
const ResourceRecord* answer,
QC_result added);
static void AaaaQueryCallback(mDNS* m,
DNSQuestion* question,
const ResourceRecord* answer,
QC_result added);
static void PtrQueryCallback(mDNS* m,
DNSQuestion* question,
const ResourceRecord* answer,
QC_result added);
static void SrvQueryCallback(mDNS* m,
DNSQuestion* question,
const ResourceRecord* answer,
QC_result added);
static void TxtQueryCallback(mDNS* m,
DNSQuestion* question,
const ResourceRecord* answer,
QC_result added);
static void ServiceCallback(mDNS* m,
ServiceRecordSet* service_record,
mStatus result);
void AdvertiseInterfaces();
void DeadvertiseInterfaces();
void RemoveQuestionsIfEmpty(UdpSocket* socket);
CacheEntity rr_cache_[kRrCacheSize];
// The main context structure for mDNSResponder.
mDNS mdns_;
// Our own storage that is placed inside |mdns_|. The intent in C is to allow
// us access to our own state during callbacks. Here we just use it to group
// platform sockets.
mDNS_PlatformSupport platform_storage_;
std::map<UdpSocket*, Questions> socket_to_questions_;
std::map<UdpSocket*, NetworkInterfaceInfo> responder_interface_info_;
std::vector<AEvent> a_responses_;
std::vector<AaaaEvent> aaaa_responses_;
std::vector<PtrEvent> ptr_responses_;
std::vector<SrvEvent> srv_responses_;
std::vector<TxtEvent> txt_responses_;
// A list of services we are advertising. ServiceRecordSet is an
// mDNSResponder structure which holds all the resource record data
// (PTR/SRV/TXT/A and misc.) that is necessary to advertise a service.
std::vector<std::unique_ptr<ServiceRecordSet>> service_records_;
};
} // namespace osp
} // namespace openscreen
#endif // OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_