// Copyright 2014 The Chromium OS 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 "peerd/avahi_service_discoverer.h"

#include <arpa/inet.h>
#include <avahi-common/address.h>
#include <avahi-common/defs.h>
#include <base/message_loop/message_loop.h>
#include <base/time/time.h>
#include <chromeos/bind_lambda.h>
#include <chromeos/dbus/async_event_sequencer.h>
#include <chromeos/dbus/dbus_method_invoker.h>
#include <chromeos/dbus/dbus_signal_handler.h>
#include <chromeos/strings/string_utils.h>
#include <dbus/object_proxy.h>

#include "peerd/avahi_client.h"
#include "peerd/constants.h"
#include "peerd/dbus_constants.h"
#include "peerd/peer_manager_interface.h"
#include "peerd/service.h"

using chromeos::dbus_utils::AsyncEventSequencer;
using chromeos::dbus_utils::CallMethodAndBlock;
using chromeos::dbus_utils::ConnectToSignal;
using chromeos::dbus_utils::ExtractMethodCallResults;
using chromeos::string_utils::Join;
using dbus::ObjectPath;
using dbus::ObjectProxy;
using peerd::dbus_constants::avahi::kServiceBrowserInterface;
using peerd::dbus_constants::avahi::kServiceBrowserMethodFree;
using peerd::dbus_constants::avahi::kServiceBrowserSignalFailure;
using peerd::dbus_constants::avahi::kServiceBrowserSignalItemNew;
using peerd::dbus_constants::avahi::kServiceBrowserSignalItemRemove;
using peerd::dbus_constants::avahi::kServiceName;
using peerd::dbus_constants::avahi::kServiceResolverInterface;
using peerd::dbus_constants::avahi::kServiceResolverMethodFree;
using peerd::dbus_constants::avahi::kServiceResolverSignalFound;
using peerd::dbus_constants::avahi::kServiceResolverSignalFailure;
using std::set;
using std::string;
using std::unique_ptr;
using std::vector;

namespace peerd {

AvahiServiceDiscoverer::AvahiServiceDiscoverer(
    const scoped_refptr<dbus::Bus>& bus,
    ObjectProxy* avahi_proxy,
    PeerManagerInterface* peer_manager) : bus_(bus),
                                          avahi_proxy_(avahi_proxy),
                                          peer_manager_(peer_manager),
                                          protocol_(AVAHI_PROTO_INET) {
}

AvahiServiceDiscoverer::~AvahiServiceDiscoverer() {
  if (serbus_browser_) {
    auto resp = CallMethodAndBlock(serbus_browser_, kServiceBrowserInterface,
                                   kServiceBrowserMethodFree, nullptr);
    if (resp) { ExtractMethodCallResults(resp.get(), nullptr); }
    serbus_browser_->Detach();
    serbus_browser_ = nullptr;
  }
}

void AvahiServiceDiscoverer::RegisterAsync(
    const CompletionAction& completion_callback) {
  serbus_browser_ = BrowseServices(
      constants::mdns::kSerbusServiceType, completion_callback);
}

bool AvahiServiceDiscoverer::txt_list2service_info(const TxtList& txt_list,
                                                   Service::ServiceInfo* info) {
  for (const vector<uint8_t>& label : txt_list) {
    string label_str{label.cbegin(), label.cend()};
    string key, value;
    chromeos::string_utils::SplitAtFirst(label_str, "=", &key, &value, false);
    info->emplace(key, value);
  }
  return Service::IsValidServiceInfo(nullptr, *info);
}

ObjectProxy* AvahiServiceDiscoverer::BrowseServices(
    const string& service_type,
    const CompletionAction& cb) {
  const uint32_t flags{0};
  auto resp = CallMethodAndBlock(
      avahi_proxy_, dbus_constants::avahi::kServerInterface,
      dbus_constants::avahi::kServerMethodServiceBrowserNew,
      nullptr,
      avahi_if_t{AVAHI_IF_UNSPEC},  // Look across all interfaces.
      protocol_,  // Only use our chosen protocol.
      service_type,
      string{},  // Empty domain indicates default.
      flags);
  ObjectPath path;
  if (!resp || !ExtractMethodCallResults(resp.get(), nullptr, &path)) {
    LOG(ERROR) << "Failed to create service browser, not monitoring mDNS.";
    base::Closure failure_cb = base::Bind([cb]() { cb.Run(false); });
    base::MessageLoop::current()->PostTask(FROM_HERE, failure_cb);
    return nullptr;
  }
  ObjectProxy* result = bus_->GetObjectProxy(kServiceName, path);
  CHECK(result);  // Makes unittests fail more gracefully.
  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
  ConnectToSignal(result,
                  kServiceBrowserInterface, kServiceBrowserSignalItemNew,
                  base::Bind(&AvahiServiceDiscoverer::HandleItemNew,
                             weak_ptr_factory_.GetWeakPtr()),
                  sequencer->GetExportHandler(
                      kServiceBrowserInterface, kServiceBrowserSignalItemNew,
                      "Failed to connect to Avahi ItemNew signal for "
                      "service type=" + service_type,
                      false));
  ConnectToSignal(result,
                  kServiceBrowserInterface, kServiceBrowserSignalItemRemove,
                  base::Bind(&AvahiServiceDiscoverer::HandleItemRemove,
                             weak_ptr_factory_.GetWeakPtr()),
                  sequencer->GetExportHandler(
                      kServiceBrowserInterface, kServiceBrowserSignalItemRemove,
                      "Failed to connect to Avahi ItemRemove signal for "
                      "service type=" + service_type,
                      false));
  // No idea why we would get this, but lets register for it anyway.
  ConnectToSignal(result,
                  kServiceBrowserInterface, kServiceBrowserSignalFailure,
                  base::Bind(&AvahiServiceDiscoverer::HandleFailure,
                             weak_ptr_factory_.GetWeakPtr(),
                             service_type),
                  sequencer->GetExportHandler(
                      kServiceBrowserInterface, kServiceBrowserSignalFailure,
                      "Failed to connect to Avahi Failure signal for "
                      "service type=" + service_type,
                      false));
  sequencer->OnAllTasksCompletedCall({cb});
  return result;
}

void AvahiServiceDiscoverer::OnPeerServicesChanged(
    const std::string& peer_id,
    set<string> new_service_types) {
  // First, update all existing browsers.
  auto it = peers_for_service_.begin();
  while (it != peers_for_service_.end()) {
    const string& service_type = it->first;
    set<string>& peer_ids_for_service = it->second;
    const bool was_relevant = peer_ids_for_service.count(peer_id) > 0;
    const bool is_relevant = new_service_types.count(service_type) > 0;
    if (was_relevant && is_relevant) {
      // We were already browsing for this service.  No action item here.
      VLOG(2) << "Peer=" << peer_id << " continues to be interested in "
                 "service type=" << service_type;
      new_service_types.erase(service_type);
    } else if (was_relevant && !is_relevant) {
      VLOG(2) << "Service type=" << service_type << " has been removed "
              << "for peer=" << peer_id;
      // This peer was advertising this service type, but now isn't.
      // Remove this peer from the list of relevant parties.
      peer_ids_for_service.erase(peer_id);
      if (peer_ids_for_service.empty()) {
        VLOG(2) << "No peers interested in service type=" << service_type
                << ". Removing browser.";
        // No one seems to advertise this service any more.
        // Remove the browser for the service.
        auto browser_it = browsers_.find(service_type);
        CHECK(browser_it != browsers_.end());
        dbus::ObjectProxy* browser = browser_it->second;
        browsers_.erase(browser_it);
        auto resp = CallMethodAndBlock(browser, kServiceBrowserInterface,
                                       kServiceBrowserMethodFree, nullptr);
        if (resp) { ExtractMethodCallResults(resp.get(), nullptr); }
        browser->Detach();
        browser = nullptr;
        // And remove the list of relevant peers.
        it = peers_for_service_.erase(it);
        continue;
      }
    } else if (!was_relevant && is_relevant) {
      // Someone else advertised this service, and this peer does as well now.
      // Add new peer to the list of relevant peers.
      VLOG(2) << "Reusing existing browser for service type=" << service_type
              << " for peer=" << peer_id;
      peer_ids_for_service.insert(peer_id);
      new_service_types.erase(service_type);
    }
    ++it;
  }
  // Second, there may be new service types this peer advertises.
  // Browse for them.
  for (const string& service_type : new_service_types) {
    VLOG(2) << "Adding new service browser for type=" << service_type;
    peers_for_service_[service_type].insert(peer_id);
    browsers_[service_type] = BrowseServices(
        service_type, AsyncEventSequencer::GetDefaultCompletionAction());
  }
}

void AvahiServiceDiscoverer::OnPeerServicesRemoved(const string& peer_id) {
  OnPeerServicesChanged(peer_id, {});
}

void AvahiServiceDiscoverer::RegisterResolver(avahi_if_t interface,
                                              const string& name,
                                              const string& type,
                                              const string& domain) {
  const uint32_t resolver_flags{0};
  // Specify that we want to send queries and receive records over |protocol_|
  // (i.e. don't discover IPv6 services over IPv4 or vice versa.
  auto resp = CallMethodAndBlock(
      avahi_proxy_, dbus_constants::avahi::kServerInterface,
      dbus_constants::avahi::kServerMethodServiceResolverNew,
      nullptr, interface, protocol_, name, type, domain, protocol_,
      resolver_flags);
  ObjectPath path;
  if (!resp || !ExtractMethodCallResults(resp.get(), nullptr, &path)) {
    LOG(ERROR) << "Failed to create service resolver for service " << type;
    return;
  }
  ObjectProxy* resolver = bus_->GetObjectProxy(kServiceName, path);
  CHECK(resolver);  // Makes unittests fail in more obvious ways.
  resolvers_[type][resolv_key_t{interface, name, domain}] = resolver;
  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
  resolver->ConnectToSignal(
      kServiceResolverInterface,
      kServiceResolverSignalFound,
      base::Bind(&AvahiServiceDiscoverer::HandleFound,
                 weak_ptr_factory_.GetWeakPtr()),
      sequencer->GetExportHandler(
          kServiceResolverInterface,
          kServiceResolverSignalFound,
          "Failed to connect to Avahi Found signal for resolver.",
          false));
  // No idea why we would get this, but lets register for it anyway.
  resolver->ConnectToSignal(
      kServiceResolverInterface,
      kServiceResolverSignalFailure,
      base::Bind(&AvahiServiceDiscoverer::HandleResolverFailure,
                 weak_ptr_factory_.GetWeakPtr(),
                 interface, name, type, domain),
      sequencer->GetExportHandler(
          kServiceResolverInterface,
          kServiceResolverSignalFailure,
          "Failed to connect to Avahi Failure signal for Resolver.",
          false));
  sequencer->OnAllTasksCompletedCall({});
}

void AvahiServiceDiscoverer::RemoveResolver(avahi_if_t interface,
                                            const std::string& name,
                                            const std::string& type,
                                            const std::string& domain) {
  auto type_it = resolvers_.find(type);
  if (type_it == resolvers_.end()) {
    LOG(ERROR) << "Tried to remove Resolver for unknown type: " << type;
    return;
  }
  ResolversForType& type_resolvers = type_it->second;
  resolv_key_t resolver_key{interface, name, domain};
  auto it = type_resolvers.find(resolver_key);
  if (it == type_resolvers.end()) {
    LOG(ERROR) << "Tried to remove unknown Resolver for type=" << type
               << ", <" << interface << ", " << name << ", " << domain << ">.";
    return;
  }
  auto resp = CallMethodAndBlock(it->second, kServiceResolverInterface,
                                 kServiceResolverMethodFree, nullptr);
  if (resp) { ExtractMethodCallResults(resp.get(), nullptr); }
  it->second->Detach();
  type_resolvers.erase(it);
  if (type_resolvers.empty()) {
    resolvers_.erase(type_it);
  }
}

void AvahiServiceDiscoverer::HandleItemNew(avahi_if_t interface,
                                           avahi_proto_t protocol,
                                           const string& name,
                                           const string& type,
                                           const string& domain,
                                           uint32_t flags) {
  VLOG(1) << "Discovered service: " << interface << ", " << protocol << ", "
          << name << ", " << type << ", " << domain << ", " << flags;
  if ((flags & AVAHI_LOOKUP_RESULT_LOCAL) != 0) {
    VLOG(1) << "Ignoring local service.";
    return;
  }
  CHECK(protocol == protocol_);
  RegisterResolver(interface, name, type, domain);
}

void AvahiServiceDiscoverer::HandleItemRemove(avahi_if_t interface,
                                              avahi_proto_t protocol,
                                              const string& name,
                                              const string& type,
                                              const string& domain,
                                              uint32_t flags) {
  VLOG(1) << "Removed service: " << interface << ", " << protocol << ", "
          << name << ", " << type << ", " << domain << ", " << flags;
  RemoveResolver(interface, name, type, domain);
  if (type == constants::mdns::kSerbusServiceType) {
    auto it = serbus_record_to_peer_id_.find(
        resolv_key_t{interface, name, domain});
    if (it == serbus_record_to_peer_id_.end()) {
      LOG(ERROR) << "Peer with unknown peer id has gone away.";
      return;
    }
    OnPeerServicesRemoved(it->second);
    serbus_record_to_peer_id_.erase(it);
  }
}

void AvahiServiceDiscoverer::HandleFailure(const string& service_type,
                                           const string& message) {
  // TODO(wiley) What should we do here?
  LOG(ERROR) << "Avahi ServiceDiscoverer in failure state for service type="
             << service_type << " : " << message;
}

void AvahiServiceDiscoverer::HandleFound(dbus::Signal* signal) {
  VLOG(1) << "HandleFound called to handle signal from Resolver.";
  avahi_if_t interface;
  avahi_proto_t protocol;
  string name, type, domain, host, address;
  // We could for instance, conceivably discover IPv6 records over
  // and IPv6 interface.
  avahi_proto_t application_protocol;
  uint16_t port;
  TxtList txt_list;
  uint32_t flags;
  const bool parse_success = ExtractMethodCallResults(
      signal, nullptr, &interface, &protocol, &name, &type, &domain, &host,
      &application_protocol, &address, &port, &txt_list, &flags);
  if (!parse_success) {
    LOG(ERROR) << "Failed parsing Found signal from resolver.";
    return;
  }
  Service::ServiceInfo info;
  if (!txt_list2service_info(txt_list, &info)) {
    LOG(ERROR) << "Ignoring invalid serbus mDNS record.";
    return;
  }
  base::Time last_seen = base::Time::Now();
  if (type == constants::mdns::kSerbusServiceType) {
    VLOG(1) << "Found serbus TXT record update.";
    if (info.size() != 3) {
      LOG(ERROR) << "Peer is advertising serbus record with incorrect number "
                    "of fields: " << info.size();
      return;
    }
    auto it_peer_id = info.find(constants::mdns::kSerbusPeerId);
    auto it_version = info.find(constants::mdns::kSerbusVersion);
    auto it_services = info.find(constants::mdns::kSerbusServiceList);
    if (it_peer_id == info.end()) {
      LOG(ERROR) << "Ignoring Peer with missing peer id.";
      return;
    }
    if (it_version == info.end()) {
      LOG(ERROR) << "Ignoring Peer with missing version string.";
      return;
    }
    if (it_services == info.end()) {
      LOG(ERROR) << "Ignoring Peer with missing services list.";
      return;
    }
    vector<string> service_ids{
        chromeos::string_utils::Split(it_services->second,
                                      constants::mdns::kSerbusServiceDelimiter,
                                      false,
                                      false)};
    set<string> service_types{};
    for (string& service : service_ids) {
      // Validate the service id.
      if (!Service::IsValidServiceId(nullptr, service)) {
        LOG(ERROR) << "Ignoring Peer with invalid Serbus record.";
        return;
      }
      if (service == constants::kSerbusServiceId) {
        LOG(ERROR) << "Ignoring Peer advertising Serbus in Serbus record.";
        return;
      }
      service_types.insert(AvahiClient::GetServiceType(service));
    }
    // TODO(wiley) We don't actually do anything with the version
    const string& peer_id = it_peer_id->second;
    peer_manager_->OnPeerDiscovered(
        peer_id, last_seen, technologies::kMDNS);
    const resolv_key_t serbus_key{interface, name, domain};
    auto pair = serbus_record_to_peer_id_.emplace(serbus_key, peer_id);
    if (!pair.second) {
      LOG(WARNING) << "Peer id has changed for remote mDNS peer.";
      OnPeerServicesRemoved(pair.first->second);
      pair.first->second = peer_id;
    }
    OnPeerServicesChanged(peer_id, std::move(service_types));
  } else {
    VLOG(1) << "Found Serbus service record update.";
    // Assume that the same name is used for the peer's serbus and service
    // records.
    const resolv_key_t serbus_key{interface, name, domain};
    auto it = serbus_record_to_peer_id_.find(serbus_key);
    if (it == serbus_record_to_peer_id_.end()) {
      LOG(ERROR) << "Found service for unknown peer.";
      return;
    }
    CHECK(protocol == protocol_) << "Resolved record for unexpected protocol.";
    vector<uint8_t> addr_bytes;
    if (protocol == AVAHI_PROTO_INET) {
      in_addr raw_addr;
      if (inet_pton(AF_INET, address.c_str(), &raw_addr) != 1) {
        LOG(ERROR) << "Failed to parse IPv4 address.";
        return;
      }
      auto ptr = reinterpret_cast<const uint8_t*>(&raw_addr.s_addr);
      addr_bytes.assign(ptr, ptr + sizeof(raw_addr.s_addr));
    } else if (protocol == AVAHI_PROTO_INET6) {
      in6_addr raw_addr;
      if (inet_pton(AF_INET6, address.c_str(), &raw_addr) != 1) {
        LOG(ERROR) << "Failed to parse IPv6 address.";
        return;
      }
      auto ptr = reinterpret_cast<const uint8_t*>(&raw_addr.s6_addr);
      addr_bytes.assign(ptr, ptr + sizeof(raw_addr.s6_addr));
    } else {
      LOG(ERROR) << "Received mDNS records over a protocol other than IPv4/6 ("
                 << protocol << ")?";
      return;
    }
    peer_manager_->OnServiceDiscovered(
        it->second, AvahiClient::GetServiceId(type),
        info, {Service::IpAddress{addr_bytes, port}},
        last_seen, technologies::kMDNS);
  }
}

void AvahiServiceDiscoverer::HandleResolverFailure(avahi_if_t interface,
                                                   const std::string& name,
                                                   const std::string& type,
                                                   const std::string& domain,
                                                   dbus::Signal* signal) {
  string message;
  ExtractMethodCallResults(signal, nullptr, &message);
  LOG(ERROR) << "Resolver for type=" << type
             << ", <" << interface << ", " << name << ", " << domain << ">"
             << " reports failure: " << message;
  RemoveResolver(interface, name, type, domain);
}

}  // namespace peerd
