| // 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 GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_H_ |
| #define GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_H_ |
| |
| #include <memory> |
| #include <vector> |
| |
| #include <lib/fit/function.h> |
| |
| #include "garnet/bin/mdns/service/dns_message.h" |
| #include "garnet/bin/mdns/service/reply_address.h" |
| #include "garnet/lib/inet/ip_address.h" |
| #include "garnet/lib/inet/socket_address.h" |
| #include "lib/fsl/tasks/fd_waiter.h" |
| #include "lib/fxl/files/unique_fd.h" |
| #include "lib/fxl/macros.h" |
| |
| namespace mdns { |
| |
| // Handles mDNS communication for a single NIC. This class is abstract and has |
| // two concrete implementations providing family-specific behavior: |
| // |MdnsInterfaceTransceiverV4| and |MdnsInterfaceTransceiverV6|. |
| class MdnsInterfaceTransceiver { |
| public: |
| // Callback to deliver inbound messages with reply address. |
| using InboundMessageCallback = |
| fit::function<void(std::unique_ptr<DnsMessage>, const ReplyAddress&)>; |
| |
| // Creates the variant of |MdnsInterfaceTransceiver| appropriate for the |
| // address family specified in |address|. |name| is the name of the interface, |
| // and |index| is its index. |
| static std::unique_ptr<MdnsInterfaceTransceiver> Create( |
| inet::IpAddress address, const std::string& name, uint32_t index); |
| |
| virtual ~MdnsInterfaceTransceiver(); |
| |
| const inet::IpAddress& address() const { return address_; } |
| |
| const std::string& name() const { return name_; } |
| |
| uint32_t index() const { return index_; } |
| |
| // Starts the interface transceiver. |
| bool Start(InboundMessageCallback callback); |
| |
| // Stops the interface transceiver. |
| void Stop(); |
| |
| // Sets an alternate address for the interface. |
| void SetAlternateAddress(const inet::IpAddress& alternate_address); |
| |
| // Sends a messaage to the specified address. A V6 interface will send to |
| // |MdnsAddresses::kV6Multicast| if |reply_address| is |
| // |MdnsAddresses::kV4Multicast|. This method expects there to be at most two |
| // address records per record vector and, if there are two, that they are |
| // adjacent. The same constraints will apply when this method returns. |
| void SendMessage(DnsMessage* message, const inet::SocketAddress& address); |
| |
| // Sends a message containing only an address resource for this interface. |
| void SendAddress(const std::string& host_full_name); |
| |
| // Sends a message containing only an address resource for this interface with |
| // zero ttl, indicating that the address is no longer valid. |
| void SendAddressGoodbye(const std::string& host_full_name); |
| |
| // Writes log messages describing lifetime traffic. |
| void LogTraffic(); |
| |
| protected: |
| static constexpr int kTimeToLive_ = 255; |
| static constexpr size_t kMaxPacketSize = 1500; |
| |
| MdnsInterfaceTransceiver(inet::IpAddress address, const std::string& name, |
| uint32_t index); |
| |
| const fxl::UniqueFD& socket_fd() const { return socket_fd_; } |
| |
| virtual int SetOptionJoinMulticastGroup() = 0; |
| virtual int SetOptionOutboundInterface() = 0; |
| virtual int SetOptionUnicastTtl() = 0; |
| virtual int SetOptionMulticastTtl() = 0; |
| virtual int SetOptionFamilySpecific() = 0; |
| virtual int Bind() = 0; |
| virtual int SendTo(const void* buffer, size_t size, |
| const inet::SocketAddress& address) = 0; |
| |
| private: |
| int SetOptionSharePort(); |
| |
| void WaitForInbound(); |
| |
| void InboundReady(zx_status_t status, uint32_t events); |
| |
| // Returns an address resource (A/AAAA) record with the given name and the |
| // address contained in |alternate_address_|, which must be valid. |
| std::shared_ptr<DnsResource> GetAddressResource( |
| const std::string& host_full_name); |
| |
| // Returns an address resource (A/AAAA) record with the given name and the |
| // address contained in |address_|, which must be valid. |
| std::shared_ptr<DnsResource> GetAlternateAddressResource( |
| const std::string& host_full_name); |
| |
| // Makes an address resource (A/AAAA) record with the given name and address. |
| std::shared_ptr<DnsResource> MakeAddressResource( |
| const std::string& host_full_name, const inet::IpAddress& address); |
| |
| // Fixes up the address records in the vector. This method expects there to |
| // be at most two address records in the vector and, if there are two, that |
| // they are adjacent. The same constraints will apply when this method |
| // returns. |
| void FixUpAddresses(std::vector<std::shared_ptr<DnsResource>>* resources); |
| |
| inet::IpAddress address_; |
| inet::IpAddress alternate_address_; |
| std::string name_; |
| uint32_t index_; |
| fxl::UniqueFD socket_fd_; |
| fsl::FDWaiter fd_waiter_; |
| std::vector<uint8_t> inbound_buffer_; |
| std::vector<uint8_t> outbound_buffer_; |
| InboundMessageCallback inbound_message_callback_; |
| std::shared_ptr<DnsResource> address_resource_; |
| std::shared_ptr<DnsResource> alternate_address_resource_; |
| uint64_t messages_received_ = 0; |
| uint64_t bytes_received_ = 0; |
| uint64_t messages_sent_ = 0; |
| uint64_t bytes_sent_ = 0; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(MdnsInterfaceTransceiver); |
| }; |
| |
| } // namespace mdns |
| |
| #endif // GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_H_ |