// 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/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 "lib/fostr/hex_dump.h"
#include "src/connectivity/network/mdns/service/dns_formatting.h"
#include "src/connectivity/network/mdns/service/dns_reading.h"
#include "src/connectivity/network/mdns/service/dns_writing.h"
#include "src/connectivity/network/mdns/service/mdns_addresses.h"
#include "src/connectivity/network/mdns/service/mdns_interface_transceiver_v4.h"
#include "src/connectivity/network/mdns/service/mdns_interface_transceiver_v6.h"

namespace mdns {

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

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

MdnsInterfaceTransceiver::~MdnsInterfaceTransceiver() {}

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

  addresses_ = &addresses;

  std::cout << "Starting mDNS on interface " << name_ << " " << address_ << " using port "
            << addresses.port() << "\n";

  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::SetAlternateAddress(const inet::IpAddress& alternate_address) {
  FX_DCHECK(alternate_address.family() != address_.family());

  alternate_address_ = alternate_address;
}

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

  FixUpAddresses(&message->answers_);
  FixUpAddresses(&message->authorities_);
  FixUpAddresses(&message->additionals_);
  message->UpdateCounts();

  PacketWriter writer(std::move(outbound_buffer_));
  writer << *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 fxbug.dev/62074.
  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, addresses_->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(MakeAddressResource(host_full_name, address_));
  message.answers_.back()->time_to_live_ = 0;

  SendMessage(&message, addresses_->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 index = this->index();
  if (if_indextoname(index, ifname) == nullptr) {
    FX_LOGS(ERROR) << "Failed to look up interface name with index=" << index << ", error "
                   << strerror(errno);
  }
  int result = setsockopt(socket_fd_.get(), SOL_SOCKET, SO_BINDTODEVICE, &ifname,
                          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_REUSEADDR, &param, sizeof(param));
  if (result < 0) {
    FX_LOGS(ERROR) << "Failed to set socket option SO_REUSEADDR, " << strerror(errno);
    return result;
  }

  param = 1;
  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_, media_);

  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_ = MakeAddressResource(host_full_name, address_);
  }

  return address_resource_;
}

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

  if (!alternate_address_resource_ ||
      alternate_address_resource_->name_.dotted_string_ != host_full_name) {
    alternate_address_resource_ = MakeAddressResource(host_full_name, alternate_address_);
  }

  return alternate_address_resource_;
}

std::shared_ptr<DnsResource> MdnsInterfaceTransceiver::MakeAddressResource(
    const std::string& host_full_name, const inet::IpAddress& address) {
  std::shared_ptr<DnsResource> resource;

  if (address.is_v4()) {
    resource = std::make_shared<DnsResource>(host_full_name, DnsType::kA);
    resource->a_.address_.address_ = address;
  } else {
    resource = std::make_shared<DnsResource>(host_full_name, DnsType::kAaaa);
    resource->aaaa_.address_.address_ = address;
  }

  return resource;
}

void MdnsInterfaceTransceiver::FixUpAddresses(
    std::vector<std::shared_ptr<DnsResource>>* resources) {
  FX_DCHECK(resources);

  // This method is called from |SendMessage| to 'fix up' address resources in
  // a DNS message. |SendMessage| calls this method once for each of the three
  // resource lists in a message.
  //
  // If the resource list passed to this method contains no A or AAAA resources,
  // this method returns without making any modifications to the list.
  //
  // If the resource list does contain A or AAAA resources, those resources are
  // replaced with one or two new A or AAAA resources. The first of those new
  // resources contains the address bound by this instance (A if the address is
  // v4, AAAA if the address is v6). This address resource is returned by
  // |GetAddressResource|. If there is an 'alternate' address, a second new
  // address resource is added for that alternate address. That address resource
  // is returned by |GetAlternateAddressResource|.
  //
  // A/AAAA addresses in the original message come from two sources:
  // 1) The agent that sent the message may insert a placeholder A message that
  //    contains an invalid address.
  // 2) A different transceiver that sent the message previously may have
  //    inserted its own A/AAAA message(s). Because the mutated message is
  //    reused, we have to allow for this.

  std::string name;

  // Move A/AAAA resources to the end of the vector.
  auto iter = std::remove_if(
      resources->begin(), resources->end(), [&name](const std::shared_ptr<DnsResource>& resource) {
        if (resource->type_ != DnsType::kA && resource->type_ != DnsType::kAaaa) {
          return false;
        }

        name = resource->name_.dotted_string_;
        return true;
      });

  if (iter == resources->end()) {
    // No address resources found/moved.
    return;
  }

  FX_DCHECK(!name.empty());

  // There is at least one open slot. Fill it with the first A/AAAA resource
  // with the address resource for this interface.
  *iter++ = GetAddressResource(name);

  if (!alternate_address_.is_valid()) {
    // No alternate address. Clean up the remainder of the vector, and we're
    // done.
    resources->erase(iter, resources->end());
    return;
  }

  if (iter == resources->end()) {
    // We're at the end of the vector. Push the alternate address resource to
    // the back of the vector, and we're done.
    resources->push_back(GetAlternateAddressResource(name));
    return;
  }

  // Replace the second A/AAAA resource with the alternate address resource.
  *iter++ = GetAlternateAddressResource(name);

  // Clean up the remainder of the vector, and we're done.
  resources->erase(iter, resources->end());
}

}  // namespace mdns
