// Copyright 2019 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 DISCOVERY_MDNS_MDNS_RESPONDER_H_ #define DISCOVERY_MDNS_MDNS_RESPONDER_H_ #include #include #include #include "discovery/mdns/mdns_records.h" #include "platform/api/time.h" #include "platform/base/macros.h" #include "util/alarm.h" namespace openscreen { struct IPEndpoint; class TaskRunner; namespace discovery { struct Config; class MdnsMessage; class MdnsProbeManager; class MdnsRandom; class MdnsReceiver; class MdnsRecordChangedCallback; class MdnsSender; class MdnsQuerier; // This class is responsible for responding to any incoming mDNS Queries // received via the OnMessageReceived() method. When responding, the generated // MdnsMessage will contain the requested record(s) in the answers section, or // an NSEC record to specify that the requested record was not found in the case // of a query with DnsType aside from ANY. In the case where records are found, // the additional records field may be populated with additional records, as // specified in RFCs 6762 and 6763. class MdnsResponder { public: // Class to handle querying for existing records. class RecordHandler { public: virtual ~RecordHandler(); // Returns whether this service has one or more records matching the // provided name, type, and class. virtual bool HasRecords(const DomainName& name, DnsType type, DnsClass clazz) = 0; // Returns all records owned by this service with name, type, and class // matching the provided values. virtual std::vector GetRecords(const DomainName& name, DnsType type, DnsClass clazz) = 0; // Enumerates all PTR records owned by this service. virtual std::vector GetPtrRecords(DnsClass clazz) = 0; }; // |record_handler|, |sender|, |receiver|, |task_runner|, |random_delay|, and // |config| are expected to persist for the duration of this instance's // lifetime. MdnsResponder(RecordHandler* record_handler, MdnsProbeManager* ownership_handler, MdnsSender* sender, MdnsReceiver* receiver, TaskRunner* task_runner, ClockNowFunctionPtr now_function, MdnsRandom* random_delay, const Config& config); ~MdnsResponder(); OSP_DISALLOW_COPY_AND_ASSIGN(MdnsResponder); private: // Class which handles processing and responding to queries segmented into // multiple messages. class TruncatedQuery { public: // |responder| and |task_runner| are expected to persist for the duration of // this instance's lifetime. TruncatedQuery(MdnsResponder* responder, TaskRunner* task_runner, ClockNowFunctionPtr now_function, IPEndpoint src, const MdnsMessage& message, const Config& config); TruncatedQuery(const TruncatedQuery& other) = delete; TruncatedQuery(TruncatedQuery&& other) = delete; TruncatedQuery& operator=(const TruncatedQuery& other) = delete; TruncatedQuery& operator=(TruncatedQuery&& other) = delete; // Sets the query associated with this instance. Must only be called if no // query has already been set, here or through the ctor. void SetQuery(const MdnsMessage& message); // Adds additional known answers. void AddKnownAnswers(const std::vector& records); // Responds to the stored queries. void SendResponse(); const IPEndpoint& src() const { return src_; } const std::vector& questions() const { return questions_; } const std::vector& known_answers() const { return known_answers_; } private: void RescheduleSend(); // The number of messages received so far associated with this known answer // query. int messages_received_so_far = 0; const int max_allowed_messages_; const int max_allowed_records_; const IPEndpoint src_; MdnsResponder* const responder_; std::vector questions_; std::vector known_answers_; Alarm alarm_; }; // Called when a new MdnsMessage is received. void OnMessageReceived(const MdnsMessage& message, const IPEndpoint& src); // Responds a truncated query for which all known answers have been received. void RespondToTruncatedQuery(TruncatedQuery* query); // Processes a message associated with a multi-packet truncated query. void ProcessMultiPacketTruncatedMessage(const MdnsMessage& message, const IPEndpoint& src); // Processes queries provided. void ProcessQueries(const IPEndpoint& src, const std::vector& questions, const std::vector& known_answers); // Sends the response to the provided query. void SendResponse(const MdnsQuestion& question, const std::vector& known_answers, std::function send_response, bool is_exclusive_owner); // Set of all truncated queries received so far. Per RFC 6762 section 7.1, // matching of a query with additional known answers should be done based on // the source address. // NOTE: unique_ptrs used because TruncatedQuery is not movable. std::map> truncated_queries_; RecordHandler* const record_handler_; MdnsProbeManager* const ownership_handler_; MdnsSender* const sender_; MdnsReceiver* const receiver_; TaskRunner* const task_runner_; const ClockNowFunctionPtr now_function_; MdnsRandom* const random_delay_; const Config& config_; friend class MdnsResponderTest; }; } // namespace discovery } // namespace openscreen #endif // DISCOVERY_MDNS_MDNS_RESPONDER_H_