// 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.

#include "src/connectivity/network/mdns/service/transport/mdns_interface_transceiver.h"

#include <arpa/inet.h>
#include <errno.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/syslog/cpp/macros.h>
#include <net/if.h>
#include <poll.h>
#include <sys/socket.h>

#include <algorithm>
#include <iostream>

#include <fbl/unique_fd.h>

#include "src/connectivity/network/mdns/service/common/formatters.h"
#include "src/connectivity/network/mdns/service/common/mdns_addresses.h"
#include "src/connectivity/network/mdns/service/encoding/dns_formatting.h"
#include "src/connectivity/network/mdns/service/encoding/dns_reading.h"
#include "src/connectivity/network/mdns/service/encoding/dns_writing.h"
#include "src/connectivity/network/mdns/service/transport/mdns_interface_transceiver_v4.h"
#include "src/connectivity/network/mdns/service/transport/mdns_interface_transceiver_v6.h"
#include "src/lib/fostr/hex_dump.h"

namespace mdns {

// static
std::unique_ptr<MdnsInterfaceTransceiver> MdnsInterfaceTransceiver::Create(inet::IpAddress address,
                                                                           const std::string& name,
                                                                           uint32_t id,
                                                                           Media media) {
  if (address.is_v4()) {
    return std::make_unique<MdnsInterfaceTransceiverV4>(address, name, id, media);
  } else {
    return std::make_unique<MdnsInterfaceTransceiverV6>(address, name, id, media);
  }
}

MdnsInterfaceTransceiver::MdnsInterfaceTransceiver(inet::IpAddress address, const std::string& name,
                                                   uint32_t id, Media media)
    : address_(address),
      name_(name),
      id_(id),
      media_(media),
      inbound_buffer_(kMaxPacketSize),
      outbound_buffer_(kMaxPacketSize) {
  FX_DCHECK(media_ == Media::kWired || media_ == Media::kWireless);
}

MdnsInterfaceTransceiver::~MdnsInterfaceTransceiver() {}

bool MdnsInterfaceTransceiver::Start(InboundMessageCallback callback) {
  FX_DCHECK(callback);
  FX_DCHECK(!socket_fd_.is_valid()) << "Start called when already started.";

  FX_LOGS(INFO) << "Starting mDNS on interface " << name_ << " using port "
                << MdnsAddresses::port();

  socket_fd_ = fbl::unique_fd(socket(address_.family(), SOCK_DGRAM, 0));

  if (!socket_fd_.is_valid()) {
    FX_LOGS(ERROR) << "Failed to open socket, " << strerror(errno);
    return false;
  }

  // Set socket options and bind.
  if (SetOptionSharePort() != 0 || SetOptionDisableMulticastLoop() != 0 ||
      SetOptionJoinMulticastGroup() != 0 || SetOptionOutboundInterface() != 0 ||
      SetOptionUnicastTtl() != 0 || SetOptionMulticastTtl() != 0 ||
      SetOptionFamilySpecific() != 0 || SetOptionBindToDevice() != 0 || Bind() != 0) {
    socket_fd_.reset();
    return false;
  }

  inbound_message_callback_ = std::move(callback);

  WaitForInbound();
  return true;
}

void MdnsInterfaceTransceiver::Stop() {
  FX_DCHECK(socket_fd_.is_valid()) << "Stop called when stopped.";
  fd_waiter_.Cancel();
  socket_fd_.reset();
}

void MdnsInterfaceTransceiver::SetInterfaceAddresses(
    const std::vector<inet::IpAddress>& interface_addresses) {
  FX_DCHECK(!interface_addresses.empty());

  interface_addresses_ = interface_addresses;

  // These resources are a cached version of |interface_addresses_|. Make sure they get regenerated.
  interface_address_resources_.clear();
}

void MdnsInterfaceTransceiver::SendMessage(const DnsMessage& message,
                                           const inet::SocketAddress& address) {
  FX_DCHECK(address.is_valid());
  FX_DCHECK(address.family() == address_.family() || address == MdnsAddresses::v4_multicast());

  DnsMessage fixed_up_message;
  fixed_up_message.header_ = message.header_;
  fixed_up_message.questions_ = message.questions_;
  fixed_up_message.answers_ = FixUpAddresses(message.answers_);
  fixed_up_message.authorities_ = FixUpAddresses(message.authorities_);
  fixed_up_message.additionals_ = FixUpAddresses(message.additionals_);
  fixed_up_message.UpdateCounts();

  PacketWriter writer(std::move(outbound_buffer_));
  writer << fixed_up_message;
  size_t packet_size = writer.position();
  outbound_buffer_ = writer.GetPacket();

  ssize_t result = SendTo(outbound_buffer_.data(), packet_size, address);

  ++messages_sent_;
  bytes_sent_ += packet_size;

  // Host down errors are expected. See https://fxbug.dev/42140430.
  if (result < 0 && errno != EHOSTDOWN && errno != ENETUNREACH) {
    FX_LOGS(ERROR) << "Failed to sendto " << address << " from " << name_ << " (" << address_
                   << "), size " << packet_size << ", " << strerror(errno);
  }
}

void MdnsInterfaceTransceiver::SendAddress(const std::string& host_full_name) {
  DnsMessage message;
  message.answers_.push_back(GetAddressResource(host_full_name));

  SendMessage(message, MdnsAddresses::v4_multicast());
}

void MdnsInterfaceTransceiver::SendAddressGoodbye(const std::string& host_full_name) {
  DnsMessage message;
  // Not using |GetAddressResource| here, because we want to modify the ttl.
  message.answers_.push_back(std::make_shared<DnsResource>(host_full_name, address_));
  message.answers_.back()->time_to_live_ = 0;

  SendMessage(message, MdnsAddresses::v4_multicast());
}

void MdnsInterfaceTransceiver::LogTraffic() {
  std::cout << "interface " << name_ << " " << address_ << "\n";
  std::cout << "    messages received:  " << messages_received_ << "\n";
  std::cout << "    bytes received:     " << bytes_received_ << "\n";
  std::cout << "    messages sent:      " << messages_sent_ << "\n";
  std::cout << "    bytes sent:         " << bytes_sent_ << "\n";
}

int MdnsInterfaceTransceiver::SetOptionBindToDevice() {
  char ifname[IF_NAMESIZE];
  uint32_t id = this->id();
  if (if_indextoname(id, ifname) == nullptr) {
    FX_LOGS(ERROR) << "Failed to look up interface name with index=" << id << ", error "
                   << strerror(errno);
  }
  int result = setsockopt(socket_fd_.get(), SOL_SOCKET, SO_BINDTODEVICE, &ifname,
                          static_cast<socklen_t>(strnlen(ifname, IF_NAMESIZE)));
  if (result < 0) {
    FX_LOGS(ERROR) << "Failed to set socket option SO_BINDTODEVICE with ifname=" << ifname
                   << ", error" << strerror(errno);
  }
  return result;
}

int MdnsInterfaceTransceiver::SetOptionSharePort() {
  int param = 1;
  int result = setsockopt(socket_fd_.get(), SOL_SOCKET, SO_REUSEPORT, &param, sizeof(param));
  if (result < 0) {
    FX_LOGS(ERROR) << "Failed to set socket option SO_REUSEPORT, " << strerror(errno);
  }

  return result;
}

void MdnsInterfaceTransceiver::WaitForInbound() {
  fd_waiter_.Wait([this](zx_status_t status, uint32_t events) { InboundReady(status, events); },
                  socket_fd_.get(), POLLIN);
}

void MdnsInterfaceTransceiver::InboundReady(zx_status_t status, uint32_t events) {
  sockaddr_storage source_address_storage;
  socklen_t source_address_length = address_.is_v4() ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
  ssize_t result =
      recvfrom(socket_fd_.get(), inbound_buffer_.data(), inbound_buffer_.size(), 0,
               reinterpret_cast<sockaddr*>(&source_address_storage), &source_address_length);
  if (result < 0) {
    FX_LOGS(ERROR) << "Failed to recvfrom, " << strerror(errno);
    // Wait a bit before trying again to avoid spamming the log.
    async::PostDelayedTask(
        async_get_default_dispatcher(), [this]() { WaitForInbound(); }, zx::sec(10));
    return;
  }

  ++messages_received_;
  bytes_received_ += result;

  ReplyAddress reply_address(source_address_storage, address_, id_, media_, IpVersions());

  if (reply_address.socket_address().address() == address_) {
    // This is an outgoing message that's bounced back to us. Drop it.
    WaitForInbound();
    return;
  }

  PacketReader reader(inbound_buffer_);
  reader.SetBytesRemaining(static_cast<size_t>(result));
  std::unique_ptr<DnsMessage> message = std::make_unique<DnsMessage>();
  reader >> *message.get();

  if (reader.complete()) {
    FX_DCHECK(inbound_message_callback_);
    inbound_message_callback_(std::move(message), reply_address);
  } else {
#ifdef MDNS_TRACE
    FX_LOGS(WARNING) << "Couldn't parse message from " << reply_address << ", " << result
                     << " bytes: " << fostr::HexDump(inbound_buffer_.data(), result, 0);
#else
    FX_LOGS(WARNING) << "Couldn't parse message from " << reply_address << ", " << result
                     << " bytes";
#endif  // MDNS_TRACE
  }

  WaitForInbound();
}

std::shared_ptr<DnsResource> MdnsInterfaceTransceiver::GetAddressResource(
    const std::string& host_full_name) {
  FX_DCHECK(address_.is_valid());

  if (!address_resource_ || address_resource_->name_.dotted_string_ != host_full_name) {
    address_resource_ = std::make_shared<DnsResource>(host_full_name, address_);
  }

  return address_resource_;
}

const std::vector<std::shared_ptr<DnsResource>>&
MdnsInterfaceTransceiver::GetInterfaceAddressResources(const std::string& host_full_name) {
  FX_DCHECK(!interface_addresses_.empty());

  // Generate new resources if there currently are none or if the host name has changed.
  if (interface_address_resources_.empty() ||
      interface_address_resources_[0]->name_.dotted_string_ != host_full_name) {
    interface_address_resources_.clear();

    // We need to generate new address resources for this interface. An A/AAAA resource
    // is generated for each V4/V6 address in the |interface_addresses_| collection. The first
    // A resource and the first AAAA resource should have the cache_flush bit and other resources
    // should not.
    bool v4_cache_flush = true;
    bool v6_cache_flush = true;
    std::transform(
        interface_addresses_.begin(), interface_addresses_.end(),
        std::back_inserter(interface_address_resources_),
        [&host_full_name, &v4_cache_flush, &v6_cache_flush](const inet::IpAddress& address) {
          bool cache_flush;
          if (address.is_v4()) {
            // Set cache_flush on the first A resource but not subsequent ones.
            cache_flush = v4_cache_flush;
            v4_cache_flush = false;
          } else {
            // Set cache_flush on the first AAAA resource but not subsequent ones.
            cache_flush = v6_cache_flush;
            v6_cache_flush = false;
          }
          return std::make_shared<DnsResource>(host_full_name, address, cache_flush);
        });
  }

  return interface_address_resources_;
}

std::vector<std::shared_ptr<DnsResource>> MdnsInterfaceTransceiver::FixUpAddresses(
    const std::vector<std::shared_ptr<DnsResource>>& resources) {
  std::string name;
  std::vector<std::shared_ptr<DnsResource>> result;
  std::copy_if(resources.begin(), resources.end(), std::back_inserter(result),
               [&name](std::shared_ptr<DnsResource> resource) {
                 switch (resource->type_) {
                   case DnsType::kA:
                     if (resource->a_.address_.address_.is_valid()) {
                       // Not a placeholder.
                       return true;
                     }
                     break;
                   case DnsType::kAaaa:
                     if (resource->aaaa_.address_.address_.is_valid()) {
                       // Not a placeholder.
                       return true;
                     }
                     break;
                   default:
                     // Not an address.
                     return true;
                 }

                 if (name.empty()) {
                   name = resource->name_.dotted_string_;
                 }

                 return false;
               });

  if (name.empty()) {
    // No placeholder address records found.
    return result;
  }

  auto& addr_resources = GetInterfaceAddressResources(name);
  std::copy(addr_resources.begin(), addr_resources.end(), std::back_inserter(result));

  return result;
}

}  // namespace mdns
