// Copyright (c) 2013 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 "p2p/client/service_finder.h"

#include <avahi-client/client.h>
#include <avahi-client/lookup.h>
#include <avahi-common/error.h>
#include <avahi-glib/glib-watch.h>
#include <fcntl.h>
#include <glib.h>
#include <unistd.h>

#include <set>
#include <stdexcept>

#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/notreached.h>

#include "p2p/common/util.h"

using std::map;
using std::set;
using std::string;
using std::vector;

namespace p2p {

namespace client {

class ServiceFinderAvahi : public ServiceFinder {
 public:
  ServiceFinderAvahi();
  ServiceFinderAvahi(const ServiceFinderAvahi&) = delete;
  ServiceFinderAvahi& operator=(const ServiceFinderAvahi&) = delete;

  virtual ~ServiceFinderAvahi();

  vector<const Peer*> GetPeersForFile(const string& file) const;

  vector<string> AvailableFiles() const;

  int NumTotalConnections() const;

  int NumTotalPeers() const;

  bool Lookup();

  void Abort();

  static ServiceFinderAvahi* Construct();

 private:
  static gboolean quit_lookup_loop(GIOChannel* channel,
                                   GIOCondition cond,
                                   gpointer user_data);

  static void on_avahi_changed(AvahiClient* client,
                               AvahiClientState state,
                               void* user_data);

  static void service_resolve_cb(AvahiServiceResolver* r,
                                 AvahiIfIndex interface,
                                 AvahiProtocol protocol,
                                 AvahiResolverEvent event,
                                 const char* name,
                                 const char* type,
                                 const char* domain,
                                 const char* host_name,
                                 const AvahiAddress* a,
                                 uint16_t port,
                                 AvahiStringList* txt,
                                 AvahiLookupResultFlags flags,
                                 void* user_data);

  bool IsOwnService(const char* name);

  void HandleResolverEvent(const AvahiAddress* a,
                           uint16_t port,
                           AvahiStringList* txt);

  static void on_service_browser_changed(AvahiServiceBrowser* b,
                                         AvahiIfIndex interface,
                                         AvahiProtocol protocol,
                                         AvahiBrowserEvent event,
                                         const char* name,
                                         const char* type,
                                         const char* domain,
                                         AvahiLookupResultFlags flags,
                                         void* user_data);

  virtual bool Initialize();
  void BrowserCheckIfDone();

  AvahiGLibPoll* poll_;
  AvahiClient* client_;
  bool running_;
  vector<Peer*> peers_;
  map<string, vector<Peer*>> file_to_servers_;
  AvahiServiceBrowser* lookup_browser_;
  bool lookup_all_for_now_;
  set<AvahiServiceResolver*> lookup_pending_resolvers_;
  GMainLoop* lookup_loop_;

  // Flag used to signal the request was canceled.
  volatile bool must_exit_now_;

  // A pipe used to wake up the |lookup_loop_| when Abort() is called.
  int abort_pipe_[2];

  // A GIOChannel on top of |abort_pipe_[0]| in order to watch it from the main
  // loop.
  GIOChannel* abort_io_channel_;

  // The source tag for the |abort_io_channel_| watch on the main loop.
  guint abort_source_;
};

ServiceFinderAvahi::ServiceFinderAvahi()
    : poll_(NULL),
      client_(NULL),
      running_(false),
      lookup_browser_(NULL),
      lookup_all_for_now_(false),
      lookup_loop_(NULL),
      must_exit_now_(false),
      abort_io_channel_(NULL) {
  // Create and attach a pipe used from the signal handler to wake up the
  // glib main loop.
  if (pipe2(abort_pipe_, O_NONBLOCK) != 0) {
    PLOG(ERROR) << "Creating a pipe(). Aborting now.";
    must_exit_now_ = true;
    abort_pipe_[0] = abort_pipe_[1] = -1;
    return;
  }

  abort_io_channel_ = g_io_channel_unix_new(abort_pipe_[0]);
  abort_source_ =
      g_io_add_watch(abort_io_channel_, G_IO_IN, quit_lookup_loop, this);
}

ServiceFinderAvahi::~ServiceFinderAvahi() {
  for (auto const& i : peers_) {
    delete i;
  }

  if (abort_io_channel_) {
    g_source_remove(abort_source_);
    g_io_channel_unref(abort_io_channel_);
  }

  close(abort_pipe_[0]);
  close(abort_pipe_[1]);

  CHECK(lookup_browser_ == NULL);
  CHECK(lookup_loop_ == NULL);

  // If the process was canceled with Abort() there can be some resolvers
  // pending on |lookup_pending_resolvers_|. Release them now.
  if (must_exit_now_) {
    for (auto const resolver : lookup_pending_resolvers_)
      avahi_service_resolver_free(resolver);
    lookup_pending_resolvers_.clear();
  }
  CHECK_EQ(0U, lookup_pending_resolvers_.size());

  if (client_ != NULL)
    avahi_client_free(client_);
  if (poll_ != NULL)
    avahi_glib_poll_free(poll_);
}

vector<string> ServiceFinderAvahi::AvailableFiles() const {
  vector<string> ret;
  for (auto const& i : file_to_servers_)
    ret.push_back(i.first);
  return ret;
}

int ServiceFinderAvahi::NumTotalConnections() const {
  int sum = 0;
  for (auto const& peer : peers_)
    sum += peer->num_connections;
  return sum;
}

int ServiceFinderAvahi::NumTotalPeers() const {
  return peers_.size();
}

vector<const Peer*> ServiceFinderAvahi::GetPeersForFile(
    const string& file) const {
  map<string, vector<Peer*>>::const_iterator it = file_to_servers_.find(file);
  if (it == file_to_servers_.end())
    return vector<const Peer*>();
  return vector<const Peer*>(it->second.begin(), it->second.end());
}

void ServiceFinderAvahi::HandleResolverEvent(const AvahiAddress* a,
                                             uint16_t port,
                                             AvahiStringList* txt) {
  Peer* peer = NULL;
  AvahiStringList* l;
  // 64 bytes is enough to hold any literal IPv4 and IPv6 addresses
  char buf[64];

  avahi_address_snprint(buf, sizeof buf, a);

  peer = new Peer();
  peer->address = string(buf);
  peer->is_ipv6 = (a->proto == AVAHI_PROTO_INET6);
  peer->port = port;

  for (l = txt; l != NULL; l = l->next) {
    string txt((const char*)l->text, l->size);
    const char* s = txt.c_str();
    const char* e = strrchr(s, '=');

    VLOG(1) << " TXT: len=" << l->size << " data=" << txt;

    if (e == NULL || strlen(e + 1) < 1) {
      LOG(WARNING) << "Attribute `" << txt
                   << "` is malformed (malformed value)";
      continue;
    }

    if (strncasecmp(s, "id_", strlen("id_")) == 0) {
      char* endp = NULL;
      size_t file_size = strtol(e + 1, &endp, 10);
      string file_name = txt.substr(strlen("id_"), e - s - strlen("id_"));

      if (*endp != '\0') {
        LOG(WARNING) << "Attribute `" << txt
                     << "` is malformed (value not a decimal number)";
        continue;
      }

      peer->files[file_name] = file_size;

    } else if (strncasecmp(s, "num_connections=", strlen("num_connections=")) ==
               0) {
      char* endp = NULL;
      int parsed_value = strtol(s + strlen("num_connections="), &endp, 10);
      if (endp != NULL) {
        peer->num_connections = parsed_value;
      }
    }
  }

  peers_.push_back(peer);
  for (auto const& file : peer->files) {
    vector<Peer*>& per_file = file_to_servers_[file.first];
    per_file.push_back(peer);
  }
}

void ServiceFinderAvahi::service_resolve_cb(AvahiServiceResolver* r,
                                            AvahiIfIndex interface,
                                            AvahiProtocol protocol,
                                            AvahiResolverEvent event,
                                            const char* name,
                                            const char* type,
                                            const char* domain,
                                            const char* host_name,
                                            const AvahiAddress* a,
                                            uint16_t port,
                                            AvahiStringList* txt,
                                            AvahiLookupResultFlags flags,
                                            void* user_data) {
  ServiceFinderAvahi* finder = reinterpret_cast<ServiceFinderAvahi*>(user_data);

  if (event == AVAHI_RESOLVER_FAILURE) {
    LOG(ERROR) << "Resolver failure: "
               << avahi_strerror(avahi_client_errno(finder->client_));
  } else {
    finder->HandleResolverEvent(a, port, txt);
  }

  if (finder->lookup_pending_resolvers_.erase(r) != 1)
    NOTREACHED();
  avahi_service_resolver_free(r);

  finder->BrowserCheckIfDone();
}

bool ServiceFinderAvahi::IsOwnService(const char* name) {
  return g_strcmp0(name, avahi_client_get_host_name(client_)) == 0;
}

static string ToString(AvahiBrowserEvent event) {
  switch (event) {
    case AVAHI_BROWSER_FAILURE:
      return "AVAHI_BROWSER_FAILURE";
    case AVAHI_BROWSER_NEW:
      return "AVAHI_BROWSER_NEW";
    case AVAHI_BROWSER_REMOVE:
      return "AVAHI_BROWSER_REMOVE";
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
      return "AVAHI_BROWSER_CACHE_EXHAUSTED";
    case AVAHI_BROWSER_ALL_FOR_NOW:
      return "AVAHI_BROWSER_ALL_FOR_NOW";
  }
  return "Unknown";
}

void ServiceFinderAvahi::on_service_browser_changed(
    AvahiServiceBrowser* b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiBrowserEvent event,
    const char* name,
    const char* type,
    const char* domain,
    AvahiLookupResultFlags flags,
    void* user_data) {
  ServiceFinderAvahi* finder = reinterpret_cast<ServiceFinderAvahi*>(user_data);

  // Can be called directly by avahi_service_browser_new() so the browser_
  // member may not be set just yet...
  if (finder->lookup_browser_ == NULL)
    finder->lookup_browser_ = b;

  VLOG(1) << "on_browser_changed: event=" << ToString(event)
          << " name=" << (name != NULL ? name : "(nil)") << " type=" << type
          << " domain=" << (domain != NULL ? domain : "(nil)")
          << " flags=" << flags;

  // Never return results from ourselves
  if (finder->IsOwnService(name)) {
    VLOG(1) << "Ignoring results from ourselves.";
    return;
  }

  switch (event) {
    case AVAHI_BROWSER_FAILURE:
      LOG(ERROR) << "Browser failure: "
                 << avahi_strerror(avahi_client_errno(finder->client_));
      break;

    case AVAHI_BROWSER_NEW: {
      AvahiServiceResolver* resolver = avahi_service_resolver_new(
          finder->client_, interface, protocol, name, type, domain,
          AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0, service_resolve_cb, finder);
      if (!resolver) {
        LOG(ERROR) << "avahi_service_resolver_new() failed: "
                   << avahi_strerror(avahi_client_errno(finder->client_));
      } else {
        finder->lookup_pending_resolvers_.insert(resolver);
      }
    } break;

    case AVAHI_BROWSER_REMOVE:
      break;

    case AVAHI_BROWSER_CACHE_EXHAUSTED:
      break;

    case AVAHI_BROWSER_ALL_FOR_NOW:
      finder->lookup_all_for_now_ = TRUE;
      finder->BrowserCheckIfDone();
      break;
  }
}

void ServiceFinderAvahi::BrowserCheckIfDone() {
  if (!lookup_all_for_now_)
    return;

  if (lookup_pending_resolvers_.size() > 0)
    return;

  CHECK(lookup_loop_ != NULL);
  g_main_loop_quit(lookup_loop_);
}

bool ServiceFinderAvahi::Lookup() {
  // Prevent new calls to Lookup() once Abort() was called.
  if (must_exit_now_)
    return true;

  CHECK(lookup_loop_ == NULL);

  // Clear existing data, if any.
  peers_.clear();
  file_to_servers_.clear();
  lookup_all_for_now_ = false;

  lookup_loop_ = g_main_loop_new(NULL, FALSE);
  lookup_browser_ = avahi_service_browser_new(
      client_, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_cros_p2p._tcp",
      NULL, /* domain */
      (AvahiLookupFlags)0, on_service_browser_changed, this);
  if (!lookup_browser_) {
    LOG(ERROR) << "avahi_service_browser_new() failed: "
               << avahi_strerror(avahi_client_errno(client_));
    g_main_loop_unref(lookup_loop_);
    lookup_loop_ = NULL;
    return false;
  }

  g_main_loop_run(lookup_loop_);
  g_main_loop_unref(lookup_loop_);
  lookup_loop_ = NULL;

  avahi_service_browser_free(lookup_browser_);
  lookup_browser_ = NULL;

  // TODO(deymo): Detect if the mDNS is filtered and return false if it is.
  // See crbug.com/267082 for details.
  return true;
}

gboolean ServiceFinderAvahi::quit_lookup_loop(GIOChannel* channel,
                                              GIOCondition cond,
                                              gpointer user_data) {
  LOG(INFO) << "Abort() processed, quiting main loop.";

  ServiceFinderAvahi* finder = reinterpret_cast<ServiceFinderAvahi*>(user_data);
  CHECK(finder->lookup_loop_ != NULL);
  g_main_loop_quit(finder->lookup_loop_);
  return TRUE;
}

void ServiceFinderAvahi::Abort() {
  // Allow several calls to this function.
  if (must_exit_now_)
    return;
  must_exit_now_ = true;

  // Wake up the main loop if we are running it. In case of an error, we
  // can't log the result since this is running in the signal handler. In the
  // case we can't write to this pipe, which should never happen, we abort the
  // process excecution without returning from the handler.
  if (write(abort_pipe_[1], "*", 1) != 1)
    abort();
}

// -----------------------------------------------------------------------------

void ServiceFinderAvahi::on_avahi_changed(AvahiClient* client,
                                          AvahiClientState state,
                                          void* user_data) {
  ServiceFinderAvahi* finder = reinterpret_cast<ServiceFinderAvahi*>(user_data);
  VLOG(1) << "on_avahi_changed, state=" << state;
  if (state == AVAHI_CLIENT_S_RUNNING) {
    finder->running_ = true;
  } else {
    finder->running_ = false;
  }
}

bool ServiceFinderAvahi::Initialize() {
  int error;

  // Note that if Avahi is not running and can't be activated,
  // avahi_client_new() may block for up to 25 seconds because it's
  // doing a sync D-Bus method call... short of fixing libavahi-client
  // there's really no way around this :-/
  poll_ = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
  client_ = avahi_client_new(avahi_glib_poll_get(poll_), (AvahiClientFlags)0,
                             on_avahi_changed, this, &error);
  if (client_ == NULL) {
    LOG(ERROR) << "Error constructing AvahiClient: " << error;
    return false;
  }

  if (!running_) {
    LOG(ERROR) << "Avahi daemon is not running";
    return false;
  }

  return true;
}

ServiceFinderAvahi* ServiceFinderAvahi::Construct() {
  ServiceFinderAvahi* client = new ServiceFinderAvahi();
  if (!client->Initialize()) {
    delete client;
    return NULL;
  }
  return client;
}

ServiceFinder* ServiceFinder::Construct() {
  return ServiceFinderAvahi::Construct();
}

}  // namespace client

}  // namespace p2p
