// 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/util/mdns_impl.h"

#include <arpa/inet.h>
#include <fuchsia/net/mdns/cpp/fidl.h>
#include <lib/async-loop/default.h>
#include <lib/async-loop/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/syslog/cpp/macros.h>
#include <poll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <zircon/status.h>

#include <iostream>
#include <unordered_set>

#include "lib/fidl/cpp/type_converter.h"
#include "src/connectivity/network/mdns/util/commands.h"
#include "src/connectivity/network/mdns/util/formatting.h"
#include "src/lib/fsl/types/type_converters.h"
#include "src/lib/inet/ip_address.h"

namespace fidl {

template <>
struct TypeConverter<fuchsia::net::IpAddress, inet::IpAddress> {
  static fuchsia::net::IpAddress Convert(const inet::IpAddress& value) {
    return static_cast<fuchsia::net::IpAddress>(value);
  }
};

template <>
struct TypeConverter<std::vector<uint8_t>, std::string> {
  static std::vector<uint8_t> Convert(const std::string& value) {
    return std::vector<uint8_t>(value.data(), value.data() + value.size());
  }
};

template <typename T, typename U>
struct TypeConverter<std::vector<T>, std::vector<U>> {
  static std::vector<T> Convert(const std::vector<U>& value) {
    std::vector<T> result;
    std::transform(value.begin(), value.end(), std::back_inserter(result),
                   [](const U& u) { return fidl::To<T>(u); });
    return result;
  }
};

}  // namespace fidl

namespace mdns {
namespace {

const std::string kPrompt = "[mdns-util] ";
const std::string kHostSuffix = ".local.";

}  // namespace

MdnsImpl::MdnsImpl(sys::ComponentContext* component_context, Command command,
                   async_dispatcher_t* dispatcher, fit::closure quit_callback)
    : component_context_(component_context),
      dispatcher_(dispatcher),
      quit_callback_(std::move(quit_callback)) {
  FX_DCHECK(component_context);
  FX_DCHECK(quit_callback_);

  // Based on the command entered on the command line, determine whether to run interactively.
  switch (command.verb()) {
    case CommandVerb::kResolveHost:
    case CommandVerb::kResolveInstance:
      // The command makes sense to run without interaction. Terminate when it completes.
      transient_ = true;
      break;

    case CommandVerb::kSubscribeHost:
    case CommandVerb::kSubscribeService:
    case CommandVerb::kPublishHost:
    case CommandVerb::kPublishInstance:
    case CommandVerb::kEmpty:
      // The command implies that the utility should run interactively.
      transient_ = false;
      break;

    case CommandVerb::kUnsubscribeHost:
    case CommandVerb::kUnsubscribeService:
    case CommandVerb::kUnpublishHost:
    case CommandVerb::kUnpublishInstance:
    case CommandVerb::kQuit:
      // The command makes no sense on the command line. Show help and quit.
      std::cout << "error: command is not valid on the command line\n";
      Command::ShowHelp(CommandVerb::kHelp);
      quit_callback_();
      return;

    case CommandVerb::kHelp:
    case CommandVerb::kMalformed:
      // The command is an explicit request for help or is malformed. Show help and quit.
      command.ShowHelp();
      quit_callback_();
      return;
  }

  ExecuteCommand(command);

  if (transient_) {
    return;
  }

  input_.SetEofCallback([this]() { Quit(); });

  input_.Init(
      [this](std::string command_line) {
        CommandParser parser(command_line);
        HideInput();
        ExecuteCommand(parser.Parse());
        ShowInput();
        input_.AddToHistory(command_line);
      },
      kPrompt);

  ShowInput();

  WaitForKeystroke();
}

void MdnsImpl::ExecuteCommand(const Command& command) {
  switch (command.verb()) {
    case CommandVerb::kResolveHost:
      ResolveHost(command.host_name(), command.timeout(), command.media(), command.ip_versions(),
                  command.exclude_local(), command.exclude_local_proxies());
      break;
    case CommandVerb::kResolveInstance:
      ResolveInstance(command.instance_name(), command.service_name(), command.timeout(),
                      command.media(), command.ip_versions(), command.exclude_local(),
                      command.exclude_local_proxies());
      break;
    case CommandVerb::kSubscribeHost:
      SubscribeHost(command.host_name(), command.media(), command.ip_versions(),
                    command.exclude_local(), command.exclude_local_proxies());
      break;
    case CommandVerb::kSubscribeService:
      SubscribeService(command.service_name(), command.media(), command.ip_versions(),
                       command.exclude_local(), command.exclude_local_proxies());
      break;
    case CommandVerb::kPublishHost:
      PublishHost(command.host_name(), command.addresses(), command.probe(), command.media(),
                  command.ip_versions());
      break;
    case CommandVerb::kPublishInstance:
      PublishInstance(command.instance_name(), command.service_name(), command.port(),
                      command.text(), command.probe(), command.media(), command.ip_versions(),
                      command.srv_priority(), command.srv_weight(), command.ptr_ttl(),
                      command.srv_ttl(), command.txt_ttl(), command.proxy_host_name());
      break;
    case CommandVerb::kUnsubscribeHost:
      UnsubscribeHost(command.host_name());
      break;
    case CommandVerb::kUnsubscribeService:
      UnsubscribeService(command.service_name());
      break;
    case CommandVerb::kUnpublishHost:
      UnpublishHost(command.host_name());
      break;
    case CommandVerb::kUnpublishInstance:
      UnpublishInstance(command.instance_name(), command.service_name(), command.proxy_host_name());
      break;
    case CommandVerb::kHelp:
    case CommandVerb::kMalformed:
      command.ShowHelp();
      break;

    case CommandVerb::kQuit:
      Quit();
      break;

    default:
      break;
  }
}

void MdnsImpl::WaitForKeystroke() {
  fd_waiter_.Wait(
      [this](zx_status_t status, uint32_t events) {
        char ch;
        if (read(STDIN_FILENO, &ch, 1) > 0) {
          input_.OnInput(ch);
        }

        WaitForKeystroke();
      },
      STDIN_FILENO, POLLIN);
}

void MdnsImpl::ResolveHost(const std::string& host_name, zx::duration timeout,
                           fuchsia::net::mdns::Media media,
                           fuchsia::net::mdns::IpVersions ip_versions, bool exclude_local,
                           bool exclude_local_proxies) {
  std::cout << Command::kResolve << " " << host_name << kHostSuffix << " starting\n";

  EnsureHostNameResolver();

  fuchsia::net::mdns::HostNameResolutionOptions options;
  options.set_media(media);
  options.set_ip_versions(ip_versions);
  options.set_exclude_local(exclude_local);
  options.set_exclude_local_proxies(exclude_local_proxies);

  host_name_resolver_->ResolveHostName(
      host_name, timeout.get(), std::move(options),
      [this, host_name](std::vector<fuchsia::net::mdns::HostAddress> addresses) {
        HideInput();

        if (addresses.empty()) {
          std::cout << Command::kResolve << " " << host_name << kHostSuffix
                    << " failed: host not found\n";
          ShowInput();
          QuitIfTransient();
          return;
        }

        std::cout << Command::kResolve << " " << host_name << kHostSuffix << " succeeded\n";
        for (auto& address : addresses) {
          std::cout << "    " << inet::IpAddress(address.address) << " interface "
                    << address.interface << " ttl " << zx::duration(address.ttl).to_secs() << "s\n";
        }

        ShowInput();
        QuitIfTransient();
      });
}

void MdnsImpl::ResolveInstance(const std::string& instance_name, const std::string& service_name,
                               zx::duration timeout, fuchsia::net::mdns::Media media,
                               fuchsia::net::mdns::IpVersions ip_versions, bool exclude_local,
                               bool exclude_local_proxies) {
  std::cout << Command::kResolve << " " << instance_name << "." << service_name << " starting\n";

  EnsureServiceInstanceResolver();

  fuchsia::net::mdns::ServiceInstanceResolutionOptions options;
  options.set_media(media);
  options.set_ip_versions(ip_versions);
  options.set_exclude_local(exclude_local);
  options.set_exclude_local_proxies(exclude_local_proxies);

  service_instance_resolver_->ResolveServiceInstance(
      service_name, instance_name, timeout.get(), std::move(options),
      [this, instance_name, service_name](fuchsia::net::mdns::ServiceInstance instance) {
        HideInput();

        if (!instance.has_addresses() || instance.addresses().empty()) {
          std::cout << Command::kResolve << " " << instance_name << "." << service_name
                    << " failed: instance not found\n";
          ShowInput();
          QuitIfTransient();
          return;
        }

        std::cout << Command::kResolve << " " << instance_name << "." << service_name
                  << " succeeded:" << instance << fostr::NewLine;

        ShowInput();
        QuitIfTransient();
      });
}

void MdnsImpl::SubscribeHost(const std::string& host_name, fuchsia::net::mdns::Media media,
                             fuchsia::net::mdns::IpVersions ip_versions, bool exclude_local,
                             bool exclude_local_proxies) {
  if (host_name_subscription_listeners_by_host_name_.find(host_name) !=
      host_name_subscription_listeners_by_host_name_.end()) {
    std::cout << Command::kSubscribe << " " << host_name << kHostSuffix
              << " failed: already subscribed\n";
    return;
  }

  std::cout << Command::kSubscribe << " " << host_name << kHostSuffix << " starting\n";

  EnsureHostNameSubscriber();

  fuchsia::net::mdns::HostNameSubscriptionOptions options;
  options.set_media(media);
  options.set_ip_versions(ip_versions);
  options.set_exclude_local(exclude_local);
  options.set_exclude_local_proxies(exclude_local_proxies);

  fidl::InterfaceHandle<fuchsia::net::mdns::HostNameSubscriptionListener> listener_handle;
  auto listener = std::make_unique<HostNameSubscriptionListener>(
      host_name, listener_handle.NewRequest(), input_);

  auto listener_raw = listener.get();
  host_name_subscription_listeners_by_host_name_.emplace(host_name, std::move(listener));

  listener_raw->set_error_handler([this, host_name](zx_status_t status) mutable {
    HideInput();
    std::cout << Command::kSubscribe << " " << host_name << kHostSuffix
              << " listener channel disconnected unexpectedly, " << zx_status_get_string(status)
              << "\n";
    ShowInput();
    host_name_subscription_listeners_by_host_name_.erase(host_name);
  });

  host_name_subscriber_->SubscribeToHostName(host_name, std::move(options),
                                             std::move(listener_handle));
}

void MdnsImpl::SubscribeService(const std::string& service_name, fuchsia::net::mdns::Media media,
                                fuchsia::net::mdns::IpVersions ip_versions, bool exclude_local,
                                bool exclude_local_proxies) {
  if (service_subscription_listeners_by_service_name_.find(service_name) !=
      service_subscription_listeners_by_service_name_.end()) {
    std::cout << Command::kSubscribe << " " << service_name << " failed: already subscribed\n";
    return;
  }

  std::cout << Command::kSubscribe << " " << service_name << " starting\n";

  EnsureServiceSubscriber();

  fuchsia::net::mdns::ServiceSubscriptionOptions options;
  options.set_media(media);
  options.set_ip_versions(ip_versions);
  options.set_exclude_local(exclude_local);
  options.set_exclude_local_proxies(exclude_local_proxies);

  fidl::InterfaceHandle<fuchsia::net::mdns::ServiceSubscriptionListener> listener_handle;
  auto listener = std::make_unique<ServiceSubscriptionListener>(
      service_name, listener_handle.NewRequest(), input_);

  auto listener_raw = listener.get();
  service_subscription_listeners_by_service_name_.emplace(service_name, std::move(listener));

  listener_raw->set_error_handler([this, service_name](zx_status_t status) mutable {
    HideInput();
    std::cout << Command::kSubscribe << " " << service_name
              << " listener channel disconnected unexpectedly, " << zx_status_get_string(status)
              << "\n";
    ShowInput();
    service_subscription_listeners_by_service_name_.erase(service_name);
  });

  if (service_name == Command::kAllServices) {
    service_subscriber_->SubscribeToAllServices(std::move(options), std::move(listener_handle));
  } else {
    service_subscriber_->SubscribeToService(service_name, std::move(options),
                                            std::move(listener_handle));
  }
}

void MdnsImpl::PublishHost(const std::string& host_name, std::vector<inet::IpAddress> addresses,
                           bool probe, fuchsia::net::mdns::Media media,
                           fuchsia::net::mdns::IpVersions ip_versions) {
  if (proxy_hosts_by_name_.find(host_name) != proxy_hosts_by_name_.end()) {
    std::cout << Command::kPublish << " " << host_name << kHostSuffix
              << " failed: already published\n";
    return;
  }

  std::cout << Command::kPublish << " " << host_name << kHostSuffix << " starting\n";

  EnsureProxyHostPublisher();

  fuchsia::net::mdns::ProxyHostPublicationOptions options;
  options.set_media(media);
  options.set_ip_versions(ip_versions);
  options.set_perform_probe(probe);

  fuchsia::net::mdns::ServiceInstancePublisherPtr service_instance_publisher;

  proxy_host_publisher_->PublishProxyHost(
      host_name, fidl::To<std::vector<fuchsia::net::IpAddress>>(addresses), std::move(options),
      service_instance_publisher.NewRequest(),
      [this, host_name, service_instance_publisher = std::move(service_instance_publisher)](
          fuchsia::net::mdns::ProxyHostPublisher_PublishProxyHost_Result result) mutable {
        HideInput();

        if (result.is_err()) {
          switch (result.err()) {
            case fuchsia::net::mdns::PublishProxyHostError::ALREADY_PUBLISHED_LOCALLY:
              std::cout << Command::kPublish << " " << host_name << kHostSuffix
                        << " failed: already published locally\n";
              break;
            case fuchsia::net::mdns::PublishProxyHostError::ALREADY_PUBLISHED_ON_SUBNET:
              std::cout << Command::kPublish << " " << host_name << kHostSuffix
                        << " failed: already published on subnet\n";
              break;
          }

          ShowInput();
          return;
        }

        std::cout << Command::kPublish << " " << host_name << kHostSuffix << " succeeded\n";

        auto proxy_host = std::make_unique<ProxyHost>(std::move(service_instance_publisher));
        proxy_host->set_error_handler([this, host_name](zx_status_t status) {
          HideInput();
          std::cout << Command::kPublish << " " << host_name << kHostSuffix
                    << " publisher disconnected unexpectedly, " << zx_status_get_string(status)
                    << "\n";
          ShowInput();
          proxy_hosts_by_name_.erase(host_name);
        });

        proxy_hosts_by_name_.emplace(host_name, std::move(proxy_host));

        ShowInput();
      });
}

void MdnsImpl::PublishInstance(const std::string& instance_name, const std::string& service_name,
                               uint16_t port, const std::vector<std::string>& text, bool probe,
                               fuchsia::net::mdns::Media media,
                               fuchsia::net::mdns::IpVersions ip_versions, uint16_t srv_priority,
                               uint16_t srv_weight, zx::duration ptr_ttl, zx::duration srv_ttl,
                               zx::duration txt_ttl, const std::string& proxy_host_name) {
  std::string instance_full_name = instance_name + "." + service_name;
  std::string title;

  ProxyHost* proxy_host = nullptr;

  if (proxy_host_name.empty()) {
    title = instance_full_name;
    auto iter =
        service_instance_publication_responders_by_instance_full_name_.find(instance_full_name);
    if (iter != service_instance_publication_responders_by_instance_full_name_.end()) {
      std::cout << Command::kPublish << " " << title << " failed: already published\n";
      return;
    }

    EnsureServiceInstancePublisher();
  } else {
    title = instance_full_name + " on proxy " + proxy_host_name;
    auto iter = proxy_hosts_by_name_.find(proxy_host_name);
    if (iter == proxy_hosts_by_name_.end()) {
      std::cout << Command::kPublish << " " << title << " failed: no such proxy\n";
      return;
    }

    proxy_host = iter->second.get();
    if (proxy_host->ResponderExists(instance_full_name)) {
      std::cout << Command::kPublish << " " << title << " failed: already published on the proxy\n";
      return;
    }
  }

  fuchsia::net::mdns::ServiceInstancePublicationOptions options;
  options.set_media(media);
  options.set_ip_versions(ip_versions);
  options.set_perform_probe(probe);

  fuchsia::net::mdns::ServiceInstancePublisherPtr& publisher =
      proxy_host ? proxy_host->publisher() : service_instance_publisher_;

  fuchsia::net::mdns::ServiceInstancePublication publication;
  publication.set_port(port);
  publication.set_text(fidl::To<std::vector<std::vector<uint8_t>>>(std::move(text)));
  publication.set_srv_priority(srv_priority);
  publication.set_srv_weight(srv_weight);
  publication.set_ptr_ttl(ptr_ttl.get());
  publication.set_srv_ttl(srv_ttl.get());
  publication.set_txt_ttl(txt_ttl.get());

  fidl::InterfaceHandle<fuchsia::net::mdns::ServiceInstancePublicationResponder> responder_handle;
  auto request = responder_handle.NewRequest();

  publisher->PublishServiceInstance(
      std::move(service_name), std::move(instance_name), std::move(options),
      std::move(responder_handle),
      [this, proxy_host, proxy_host_name, request = std::move(request),
       publication = std::move(publication), instance_full_name,
       title](fuchsia::net::mdns::ServiceInstancePublisher_PublishServiceInstance_Result
                  result) mutable {
        HideInput();

        if (result.is_err()) {
          switch (result.err()) {
            case fuchsia::net::mdns::PublishServiceInstanceError::ALREADY_PUBLISHED_LOCALLY:
              std::cout << Command::kPublish << " " << title
                        << " failed: already published locally\n";
              break;
            case fuchsia::net::mdns::PublishServiceInstanceError::ALREADY_PUBLISHED_ON_SUBNET:
              std::cout << Command::kPublish << " " << title
                        << " failed: already published on subnet\n";
              break;
          }

          ShowInput();
          return;
        }

        std::cout << Command::kPublish << " " << title << " starting\n";

        auto responder = std::make_unique<ServiceInstancePublicationResponder>(
            std::move(request), input_, std::move(publication));

        auto responder_raw = responder.get();
        if (proxy_host) {
          proxy_host->AddResponder(instance_full_name, std::move(responder));
        } else {
          service_instance_publication_responders_by_instance_full_name_.emplace(
              instance_full_name, std::move(responder));
        }

        responder_raw->set_error_handler(
            [this, instance_full_name, title, proxy_host_name](zx_status_t status) mutable {
              HideInput();

              std::cout << Command::kPublish << " " << title
                        << " responder channel disconnected unexpectedly, "
                        << zx_status_get_string(status) << "\n";

              if (proxy_host_name.empty()) {
                service_instance_publication_responders_by_instance_full_name_.erase(
                    instance_full_name);
              } else {
                auto iter = proxy_hosts_by_name_.find(proxy_host_name);
                if (iter != proxy_hosts_by_name_.end()) {
                  iter->second->RemoveResponder(instance_full_name);
                }
              }

              ShowInput();
            });

        ShowInput();
      });
}

void MdnsImpl::UnsubscribeHost(const std::string& host_name) {
  if (host_name_subscription_listeners_by_host_name_.erase(host_name) == 0) {
    std::cout << Command::kUnsubscribe << " " << host_name << kHostSuffix
              << " failed: not currenly subscribed\n";
    return;
  }

  std::cout << Command::kUnsubscribe << " " << host_name << kHostSuffix << " succeeded\n";
}

void MdnsImpl::UnsubscribeService(const std::string& service_name) {
  if (service_subscription_listeners_by_service_name_.erase(service_name) == 0) {
    std::cout << Command::kUnsubscribe << " " << service_name
              << " failed: not currenly subscribed\n";
    return;
  }

  std::cout << Command::kUnsubscribe << " " << service_name << " succeeded\n";
}

void MdnsImpl::UnpublishHost(const std::string& host_name) {
  if (proxy_hosts_by_name_.erase(host_name) == 0) {
    std::cout << Command::kUnpublish << " " << host_name << kHostSuffix
              << " failed: not currently published\n";
    return;
  }

  std::cout << Command::kUnpublish << " " << host_name << kHostSuffix << " succeeded\n";
}

void MdnsImpl::UnpublishInstance(const std::string& instance_name, const std::string& service_name,
                                 const std::string& proxy_host_name) {
  std::string instance_full_name = instance_name + "." + service_name;

  if (proxy_host_name.empty()) {
    if (service_instance_publication_responders_by_instance_full_name_.erase(instance_full_name) ==
        0) {
      std::cout << Command::kUnpublish << " " << instance_full_name
                << " failed: not currently published\n";
      return;
    }

    std::cout << Command::kUnpublish << " " << instance_full_name << " succeeded\n";
    return;
  }

  auto iter = proxy_hosts_by_name_.find(proxy_host_name);
  if (iter == proxy_hosts_by_name_.end()) {
    std::cout << Command::kUnpublish << " " << instance_full_name << " on proxy " << proxy_host_name
              << " failed: proxy host not currently published\n";
    return;
  }

  if (!iter->second->RemoveResponder(instance_full_name)) {
    std::cout << Command::kUnpublish << " " << instance_full_name << " on proxy " << proxy_host_name
              << " failed: not currently published on proxy host\n";
    return;
  }

  std::cout << Command::kUnpublish << " " << instance_full_name << " on proxy " << proxy_host_name
            << " succeeded\n";
}

void MdnsImpl::EnsureHostNameResolver() {
  if (host_name_resolver_) {
    return;
  }

  host_name_resolver_ = component_context_->svc()->Connect<fuchsia::net::mdns::HostNameResolver>();

  host_name_resolver_.set_error_handler([this](zx_status_t status) {
    HideInput();
    std::cout << "fuchsia.net.mdns.HostNameResolver channel disconnected unexpectedly, "
              << zx_status_get_string(status) << "\n";
    ShowInput();
  });
}

void MdnsImpl::EnsureServiceInstanceResolver() {
  if (service_instance_resolver_) {
    return;
  }

  service_instance_resolver_ =
      component_context_->svc()->Connect<fuchsia::net::mdns::ServiceInstanceResolver>();
  service_instance_resolver_.set_error_handler([this](zx_status_t status) {
    HideInput();
    std::cout << "fuchsia.net.mdns.ServiceInstanceResolver channel disconnected: "
              << zx_status_get_string(status);
    ShowInput();
  });
}

void MdnsImpl::EnsureHostNameSubscriber() {
  if (host_name_subscriber_) {
    return;
  }

  host_name_subscriber_ =
      component_context_->svc()->Connect<fuchsia::net::mdns::HostNameSubscriber>();

  host_name_subscriber_.set_error_handler([this](zx_status_t status) {
    HideInput();
    std::cout << "fuchsia.net.mdns.HostNameSubscriber channel disconnected unexpectedly, "
              << zx_status_get_string(status) << "\n";
    ShowInput();
  });
}

void MdnsImpl::EnsureServiceSubscriber() {
  if (service_subscriber_) {
    return;
  }

  service_subscriber_ =
      component_context_->svc()->Connect<fuchsia::net::mdns::ServiceSubscriber2>();

  service_subscriber_.set_error_handler([this](zx_status_t status) {
    HideInput();
    std::cout << "fuchsia.net.mdns.ServiceSubscriber2 channel disconnected unexpectedly, "
              << zx_status_get_string(status) << "\n";
    ShowInput();
  });
}

void MdnsImpl::EnsureProxyHostPublisher() {
  if (proxy_host_publisher_) {
    return;
  }

  proxy_host_publisher_ =
      component_context_->svc()->Connect<fuchsia::net::mdns::ProxyHostPublisher>();

  proxy_host_publisher_.set_error_handler([this](zx_status_t status) {
    HideInput();
    std::cout << "fuchsia.net.mdns.ProxyHostPublisher channel disconnected unexpectedly, "
              << zx_status_get_string(status) << "\n";
    ShowInput();
  });
}

void MdnsImpl::EnsureServiceInstancePublisher() {
  if (service_instance_publisher_) {
    return;
  }

  service_instance_publisher_ =
      component_context_->svc()->Connect<fuchsia::net::mdns::ServiceInstancePublisher>();

  service_instance_publisher_.set_error_handler([this](zx_status_t status) {
    HideInput();
    std::cout << "fuchsia.net.mdns.ServiceInstancePublisher channel disconnected unexpectedly, "
              << zx_status_get_string(status) << "\n";
    ShowInput();
  });
}

void MdnsImpl::Quit() {
  async::PostTask(dispatcher_, [this]() { QuitSync(); });
}

void MdnsImpl::QuitSync() {
  host_name_subscription_listeners_by_host_name_.clear();
  service_subscription_listeners_by_service_name_.clear();
  proxy_hosts_by_name_.clear();
  service_instance_publication_responders_by_instance_full_name_.clear();

  host_name_resolver_.set_error_handler(nullptr);
  service_instance_resolver_.set_error_handler(nullptr);
  host_name_subscriber_.set_error_handler(nullptr);
  service_subscriber_.set_error_handler(nullptr);
  proxy_host_publisher_.set_error_handler(nullptr);
  service_instance_publisher_.set_error_handler(nullptr);

  host_name_resolver_.Unbind();
  service_instance_resolver_.Unbind();
  host_name_subscriber_.Unbind();
  service_subscriber_.Unbind();
  proxy_host_publisher_.Unbind();
  service_instance_publisher_.Unbind();

  HideInput();

  quit_callback_();
}

void MdnsImpl::QuitIfTransient() {
  if (transient_) {
    Quit();
  }
}

void MdnsImpl::ShowInput() {
  if (!transient_) {
    input_.Show();
  }
}

void MdnsImpl::HideInput() {
  if (!transient_) {
    input_.Hide();
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// HostNameSubscriptionListener definitions.

MdnsImpl::HostNameSubscriptionListener::HostNameSubscriptionListener(
    std::string host_name,
    fidl::InterfaceRequest<fuchsia::net::mdns::HostNameSubscriptionListener> request,
    line_input::ModalLineInput& input)
    : host_name_(host_name), binding_(this, std::move(request)), input_(input) {}

void MdnsImpl::HostNameSubscriptionListener::set_error_handler(
    fit::function<void(zx_status_t)> error_handler) {
  binding_.set_error_handler(std::move(error_handler));
}

void MdnsImpl::HostNameSubscriptionListener::OnAddressesChanged(
    std::vector<fuchsia::net::mdns::HostAddress> addresses, OnAddressesChangedCallback callback) {
  input_.Hide();
  std::cout << Command::kSubscribe << " " << host_name_ << ": addresses" << addresses << "\n";
  input_.Show();
  callback();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// ServiceSubscriptionListener definitions.

MdnsImpl::ServiceSubscriptionListener::ServiceSubscriptionListener(
    const std::string& service_name,
    fidl::InterfaceRequest<fuchsia::net::mdns::ServiceSubscriptionListener> request,
    line_input::ModalLineInput& input)
    : service_name_(service_name), binding_(this, std::move(request)), input_(input) {}

void MdnsImpl::ServiceSubscriptionListener::set_error_handler(
    fit::function<void(zx_status_t)> error_handler) {
  binding_.set_error_handler(std::move(error_handler));
}

void MdnsImpl::ServiceSubscriptionListener::OnInstanceDiscovered(
    fuchsia::net::mdns::ServiceInstance instance, OnInstanceDiscoveredCallback callback) {
  input_.Hide();
  std::cout << Command::kSubscribe << " " << service_name_ << ": instance " << instance.instance()
            << "." << instance.service() << " discovered" << instance << "\n";
  input_.Show();
  callback();
}

void MdnsImpl::ServiceSubscriptionListener::OnInstanceChanged(
    fuchsia::net::mdns::ServiceInstance instance, OnInstanceChangedCallback callback) {
  input_.Hide();
  std::cout << Command::kSubscribe << " " << service_name_ << ": instance " << instance.instance()
            << "." << instance.service() << " changed" << instance << "\n";
  input_.Show();
  callback();
}

void MdnsImpl::ServiceSubscriptionListener::OnInstanceLost(std::string service_name,
                                                           std::string instance_name,
                                                           OnInstanceLostCallback callback) {
  input_.Hide();
  std::cout << Command::kSubscribe << " " << service_name_ << ": instance " << instance_name << "."
            << service_name << " lost\n";
  input_.Show();
  callback();
}

void MdnsImpl::ServiceSubscriptionListener::OnQuery(fuchsia::net::mdns::ResourceType resource_type,
                                                    OnQueryCallback callback) {
  // This method is just for metrics. Ignore it.
  callback();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// ServiceInstancePublicationResponder definitions.

MdnsImpl::ServiceInstancePublicationResponder::ServiceInstancePublicationResponder(
    fidl::InterfaceRequest<fuchsia::net::mdns::ServiceInstancePublicationResponder> request,
    line_input::ModalLineInput& input, fuchsia::net::mdns::ServiceInstancePublication publication)
    : binding_(this, std::move(request)), input_(input), publication_(std::move(publication)) {
  (void)input_;  // not used
}

void MdnsImpl::ServiceInstancePublicationResponder::set_error_handler(
    fit::function<void(zx_status_t)> error_handler) {
  binding_.set_error_handler(std::move(error_handler));
}

void MdnsImpl::ServiceInstancePublicationResponder::OnPublication(
    fuchsia::net::mdns::ServiceInstancePublicationCause publication_cause, fidl::StringPtr subtype,
    std::vector<fuchsia::net::IpAddress> source_addresses, OnPublicationCallback callback) {
  if (subtype.has_value()) {
    callback(fpromise::error(fuchsia::net::mdns::OnPublicationError::DO_NOT_RESPOND));
    return;
  }

  callback(fpromise::ok(fidl::Clone(publication_)));
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// ProxyHost definitions.

MdnsImpl::ProxyHost::ProxyHost(fuchsia::net::mdns::ServiceInstancePublisherPtr publisher)
    : publisher_(std::move(publisher)) {}

void MdnsImpl::ProxyHost::set_error_handler(fit::function<void(zx_status_t)> error_handler) {
  publisher_.set_error_handler(std::move(error_handler));
}

bool MdnsImpl::ProxyHost::ResponderExists(std::string instance_full_name) {
  return service_instance_publication_responders_by_instance_full_name_.find(instance_full_name) !=
         service_instance_publication_responders_by_instance_full_name_.end();
}

void MdnsImpl::ProxyHost::AddResponder(
    std::string instance_full_name,
    std::unique_ptr<ServiceInstancePublicationResponder> responder) {
  service_instance_publication_responders_by_instance_full_name_.emplace(instance_full_name,
                                                                         std::move(responder));
}

bool MdnsImpl::ProxyHost::RemoveResponder(std::string instance_full_name) {
  return service_instance_publication_responders_by_instance_full_name_.erase(instance_full_name) ==
         1;
}

}  // namespace mdns
