| // Copyright 2017 The Fuchsia 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 SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_AGENTS_INSTANCE_RESPONDER_H_ |
| #define SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_AGENTS_INSTANCE_RESPONDER_H_ |
| |
| #include <lib/zx/time.h> |
| |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "src/connectivity/network/mdns/service/agents/mdns_agent.h" |
| #include "src/connectivity/network/mdns/service/mdns.h" |
| #include "src/lib/inet/ip_port.h" |
| |
| namespace mdns { |
| |
| // Dynamically publishes an instance of a service type. |
| class InstanceResponder : public MdnsAgent { |
| public: |
| // Creates an |InstanceResponder|. The publisher is consulted to determine how queries are |
| // handled. If |host_name| is empty the local host name will be used. If |addresses| is empty, |
| // the local addresses will be used. |
| InstanceResponder(MdnsAgent::Owner* owner, std::string host_name, |
| std::vector<inet::IpAddress> addresses, std::string service_name, |
| std::string instance_name, Media media, IpVersions ip_versions, |
| Mdns::Publisher* publisher); |
| |
| ~InstanceResponder() override; |
| |
| // Returns a pointer to the current service instance or null if it hasn't yet been established. |
| // The returned pointer references a private member of this responder, which may be modified when |
| // code in this class has an opportunity to run and will be deleted if this responder is deleted. |
| const ServiceInstance* service_instance() const { return instance_ready_ ? &instance_ : nullptr; } |
| |
| // Indicates whether the instance is published by a local proxy (true) or the local host (false). |
| bool from_proxy() const { return !addresses_.empty(); } |
| |
| // MdnsAgent overrides. |
| void Start(const std::string& local_host_full_name) override; |
| |
| void ReceiveQuestion(const DnsQuestion& question, const ReplyAddress& reply_address, |
| const ReplyAddress& sender_address) override; |
| |
| void Quit() override; |
| |
| void OnLocalHostAddressesChanged() override; |
| |
| // Sets the subtypes to publish. |
| void SetSubtypes(std::vector<std::string> subtypes); |
| |
| // Reannounces the service instance. |
| void Reannounce(); |
| |
| private: |
| static constexpr zx::duration kInitialAnnouncementInterval = zx::sec(1); |
| static constexpr zx::duration kMaxAnnouncementInterval = zx::sec(4); |
| static constexpr zx::duration kMinMulticastInterval = zx::sec(1); |
| static constexpr zx::duration kIdleCheckInterval = zx::sec(60); |
| static constexpr zx::time kThrottleStateIdle = zx::time::infinite_past(); |
| static constexpr zx::time kThrottleStatePending = zx::time::infinite(); |
| static constexpr size_t kMaxSenderAddresses = 64; |
| |
| // Logs a sender address for a future |GetPublication| call. |
| void LogSenderAddress(const ReplyAddress& sender_address); |
| |
| // Sends an announcement and schedules the next announcement, as appropriate. |
| void SendAnnouncement(); |
| |
| // Sends a reply to a query for any service. |
| void SendAnyServiceResponse(const ReplyAddress& reply_address); |
| |
| // Calls |GetAndSendPublication| with |query| set to true after first determining if the send |
| // should be throttled. |
| void MaybeGetAndSendPublication(PublicationCause publication_cause, const std::string& subtype, |
| const ReplyAddress& reply_address, DnsType question_type); |
| |
| // Gets an |Mdns::Publication| from |mdns_responder_| and, if not null, sends |
| // it. An empty |subtype| indicates no subtype. |
| void GetAndSendPublication(PublicationCause publication_cause, const std::string& subtype, |
| const ReplyAddress& reply_address, DnsType question_type); |
| |
| // Sends a publication. An empty |subtype| indicates no subtype. |
| void SendPublication(const Mdns::Publication& publication, const std::string& subtype, |
| const ReplyAddress& reply_address, DnsType question_type); |
| |
| // Sends a subtype PTR record for this instance. |
| void SendSubtypePtrRecord(const std::string& subtype, uint32_t ttl, |
| const ReplyAddress& reply_address) const; |
| |
| // Sends a publication with zero ttls, indicating the service instance is |
| // no longer published. |
| void SendGoodbye(); |
| |
| // Frees resources associated with |subtype| if they're no longer required. |
| void IdleCheck(const std::string& subtype); |
| |
| // Returns the correct multicast reply address depending on |media_| and |ip_verions_|. |
| ReplyAddress multicast_reply() const { return ReplyAddress::Multicast(media_, ip_versions_); } |
| |
| // Constrain multicast reply addresses to the allowed media and ip versions. |
| ReplyAddress Constrain(const ReplyAddress& reply_address) { |
| if (reply_address.is_multicast_placeholder()) { |
| return multicast_reply(); |
| } |
| |
| return reply_address; |
| } |
| |
| // Updates |instance_.addresses_|. |
| void UpdateInstanceAddresses(); |
| |
| std::string host_full_name_; |
| const std::vector<inet::IpAddress> addresses_; |
| Mdns::ServiceInstance instance_; |
| inet::IpPort port_; |
| bool instance_ready_ = false; |
| std::string instance_full_name_; |
| Media media_; |
| IpVersions ip_versions_; |
| Mdns::Publisher* publisher_; |
| std::vector<std::string> subtypes_; |
| zx::duration announcement_interval_ = kInitialAnnouncementInterval; |
| std::unordered_map<std::string, zx::time> throttle_state_by_subtype_; |
| std::vector<inet::SocketAddress> sender_addresses_; |
| |
| public: |
| // Disallow copy, assign and move. |
| InstanceResponder(const InstanceResponder&) = delete; |
| InstanceResponder(InstanceResponder&&) = delete; |
| InstanceResponder& operator=(const InstanceResponder&) = delete; |
| InstanceResponder& operator=(InstanceResponder&&) = delete; |
| }; |
| |
| } // namespace mdns |
| |
| #endif // SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_AGENTS_INSTANCE_RESPONDER_H_ |