blob: a0091ba5f5534198a2c00367b3a8d3dd816031ae [file] [log] [blame]
// 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_TRANSPORT_MDNS_INTERFACE_TRANSCEIVER_H_
#define SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_TRANSPORT_MDNS_INTERFACE_TRANSCEIVER_H_
#include <lib/fit/function.h>
#include <lib/syslog/cpp/macros.h>
#include <memory>
#include <vector>
#include <fbl/unique_fd.h>
#include "src/connectivity/network/mdns/service/common/mdns_addresses.h"
#include "src/connectivity/network/mdns/service/common/reply_address.h"
#include "src/connectivity/network/mdns/service/encoding/dns_message.h"
#include "src/lib/fsl/tasks/fd_waiter.h"
#include "src/lib/inet/ip_address.h"
#include "src/lib/inet/socket_address.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|.
static std::unique_ptr<MdnsInterfaceTransceiver> Create(inet::IpAddress address,
const std::string& name, uint32_t id,
Media media);
virtual ~MdnsInterfaceTransceiver();
const inet::IpAddress& address() const { return address_; }
const std::string& name() const { return name_; }
uint32_t id() const { return id_; }
Media media() const { return media_; }
// Starts the interface transceiver.
virtual bool Start(InboundMessageCallback callback);
// Stops the interface transceiver.
virtual void Stop();
// Sets the list of all addresses for the interface.
void SetInterfaceAddresses(const std::vector<inet::IpAddress>& interface_addresses);
// Sends a message to the specified address. A V6 interface will send to
// |MdnsAddresses::V6Multicast| if |address| is |MdnsAddresses::V4Multicast|. If any resource
// section of the message contains one or more address placeholders, those placeholders will be
// replaced by address resource records for all this interface's addresses.
void SendMessage(const 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();
virtual IpVersions IpVersions() = 0;
protected:
static constexpr int kTimeToLive_ = 255;
// RFC6762 suggests a max packet size of 1500, but we see bigger packets in the wild. 9000 is
// the maximum size for 'jumbo' packets.
static constexpr size_t kMaxPacketSize = 9000;
MdnsInterfaceTransceiver(inet::IpAddress address, const std::string& name, uint32_t id,
Media media);
const fbl::unique_fd& socket_fd() const { return socket_fd_; }
virtual int SetOptionDisableMulticastLoop() = 0;
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 ssize_t SendTo(const void* buffer, size_t size, const inet::SocketAddress& address) = 0;
// Returns address resource (A/AAAA) records with the given name and the
// addresses contained in |interface_addresses_|.
// This method is protected so it can be accessed by subclasses used in tests.
const std::vector<std::shared_ptr<DnsResource>>& GetInterfaceAddressResources(
const std::string& host_full_name);
private:
int SetOptionSharePort();
int SetOptionBindToDevice();
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 |address_|, which must be valid.
std::shared_ptr<DnsResource> GetAddressResource(const std::string& host_full_name);
// Returns a new vector with the same resources as |resources| except that any placeholder address
// records have been replaced by address records for |interface_addresses_|.
std::vector<std::shared_ptr<DnsResource>> FixUpAddresses(
const std::vector<std::shared_ptr<DnsResource>>& resources);
inet::IpAddress address_;
std::vector<inet::IpAddress> interface_addresses_;
std::string name_;
uint32_t id_;
Media media_;
fbl::unique_fd 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::vector<std::shared_ptr<DnsResource>> interface_address_resources_;
uint64_t messages_received_ = 0;
uint64_t bytes_received_ = 0;
uint64_t messages_sent_ = 0;
uint64_t bytes_sent_ = 0;
public:
// Disallow copy, assign and move.
MdnsInterfaceTransceiver(const MdnsInterfaceTransceiver&) = delete;
MdnsInterfaceTransceiver(MdnsInterfaceTransceiver&&) = delete;
MdnsInterfaceTransceiver& operator=(const MdnsInterfaceTransceiver&) = delete;
MdnsInterfaceTransceiver& operator=(MdnsInterfaceTransceiver&&) = delete;
};
} // namespace mdns
#endif // SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_TRANSPORT_MDNS_INTERFACE_TRANSCEIVER_H_