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

#include <limits>

#include <base/strings/string_util.h>
#include <chromeos/dbus/exported_object_manager.h>

#include "peerd/constants.h"
#include "peerd/dbus_constants.h"

using chromeos::Any;
using chromeos::Error;
using chromeos::dbus_utils::AsyncEventSequencer;
using chromeos::dbus_utils::DBusObject;
using chromeos::dbus_utils::ExportedObjectManager;
using dbus::ObjectPath;
using peerd::constants::options::service::kMDNSPort;
using peerd::constants::options::service::kMDNSSectionName;
using std::map;
using std::string;
using std::unique_ptr;

namespace {
const char kValidServiceIdCharacters[] = "abcdefghijklmnopqrstuvwxyz"
                                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                         "0123456789"
                                         "-";
const char kValidServiceInfoKeyCharacters[] = "abcdefghijklmnopqrstuvwxyz"
                                              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                              "0123456789"
                                              "_";
}  // namespace


namespace peerd {

namespace errors {
namespace service {

const char kInvalidServiceId[] = "service.id";
const char kInvalidServiceInfo[] = "service.info";
const char kInvalidServiceOptions[] = "service.options";

}  // namespace service
}  // namespace errors

Service::Service(const scoped_refptr<dbus::Bus>& bus,
                 chromeos::dbus_utils::ExportedObjectManager* object_manager,
                 const dbus::ObjectPath& path)
    : dbus_object_(new DBusObject{object_manager, bus, path}) {
}

bool Service::RegisterAsync(chromeos::ErrorPtr* error,
                            const string& service_id,
                            const IpAddresses& addresses,
                            const ServiceInfo& service_info,
                            const map<string, Any>& options,
                            const CompletionAction& completion_callback) {
  if (!IsValidServiceId(error, service_id)) { return false; }
  if (!IsValidServiceInfo(error, service_info)) { return false; }
  if (!ParseOptions(error, options)) { return false; }
  dbus_adaptor_.SetServiceId(service_id);
  dbus_adaptor_.SetIpInfos(addresses);
  dbus_adaptor_.SetServiceInfo(service_info);
  dbus_adaptor_.RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(completion_callback);
  return true;
}

std::string Service::GetServiceId() const {
  return dbus_adaptor_.GetServiceId();
}

Service::IpAddresses Service::GetIpAddresses() const {
  return dbus_adaptor_.GetIpInfos();
}

Service::ServiceInfo Service::GetServiceInfo() const {
  return dbus_adaptor_.GetServiceInfo();
}
const Service::MDnsOptions& Service::GetMDnsOptions() const {
  return parsed_mdns_options_;
}

bool Service::Update(chromeos::ErrorPtr* error,
                     const IpAddresses& addresses,
                     const ServiceInfo& info) {
  if (!IsValidServiceInfo(error, info)) {
    return false;
  }
  dbus_adaptor_.SetIpInfos(addresses);
  dbus_adaptor_.SetServiceInfo(info);
  return true;
}

bool Service::IsValidServiceId(chromeos::ErrorPtr* error,
                               const std::string& service_id) {
  // From RFC 6335 (mDNS service names):
  // Valid service names are hereby normatively defined as follows:
  //
  //   o  MUST be at least 1 character and no more than 15 characters long
  //   o  MUST contain only US-ASCII [ANSI.X3.4-1986] letters 'A' - 'Z' and
  //      'a' - 'z', digits '0' - '9', and hyphens ('-', ASCII 0x2D or
  //       decimal 45)
  //   o  MUST contain at least one letter ('A' - 'Z' or 'a' - 'z')
  //   o  MUST NOT begin or end with a hyphen
  //   o  hyphens MUST NOT be adjacent to other hyphens
  if (service_id.empty() || service_id.length() > kMaxServiceIdLength) {
    Error::AddTo(error,
                 FROM_HERE,
                 kPeerdErrorDomain,
                 errors::service::kInvalidServiceId,
                 "Invalid service ID length.");
    return false;
  }
  if (!base::ContainsOnlyChars(service_id, kValidServiceIdCharacters)) {
    Error::AddTo(error,
                 FROM_HERE,
                 kPeerdErrorDomain,
                 errors::service::kInvalidServiceId,
                 "Invalid character in service ID.");
    return false;
  }
  if (service_id.front() == '-' || service_id.back() == '-') {
    Error::AddTo(error,
                 FROM_HERE,
                 kPeerdErrorDomain,
                 errors::service::kInvalidServiceId,
                 "Service ID may not start or end with hyphens.");
    return false;
  }
  if (service_id.find("--") != string::npos) {
    Error::AddTo(error,
                 FROM_HERE,
                 kPeerdErrorDomain,
                 errors::service::kInvalidServiceId,
                 "Service ID may not contain adjacent hyphens.");
    return false;
  }
  return true;
}

bool Service::IsValidServiceInfo(chromeos::ErrorPtr* error,
                                 const ServiceInfo& service_info) {
  for (const auto& kv : service_info) {
    if (kv.first.length() + kv.second.length() > kMaxServiceInfoPairLength) {
      Error::AddTo(error,
                   FROM_HERE,
                   kPeerdErrorDomain,
                   errors::service::kInvalidServiceInfo,
                   "Invalid service info pair length.");
      return false;
    }
    if (!base::ContainsOnlyChars(kv.first, kValidServiceInfoKeyCharacters)) {
      Error::AddTo(error,
                   FROM_HERE,
                   kPeerdErrorDomain,
                   errors::service::kInvalidServiceInfo,
                   "Invalid service key.");
      return false;
    }
  }
  return true;
}

bool Service::ParseOptions(chromeos::ErrorPtr* error,
                           const map<string, Any>& orig_options) {
  map<string, Any> options{orig_options};
  auto mdns_it = options.find(kMDNSSectionName);
  if (mdns_it != options.end()) {
    if (!ExtractMDnsOptions(error, &mdns_it->second)) { return false; }
    options.erase(mdns_it);
  }
  if (!options.empty()) {
    Error::AddTo(error,
                 FROM_HERE,
                 kPeerdErrorDomain,
                 errors::service::kInvalidServiceOptions,
                 "Invalid service options.");
    return false;
  }
  return true;
}

bool Service::ExtractMDnsOptions(chromeos::ErrorPtr* error,
                                 Any* maybe_mdns_options) {
  map<string, Any>* mdns_options =
      maybe_mdns_options->GetPtr<map<string, Any>>();
  if (mdns_options == nullptr) {
    Error::AddTo(error,
                 FROM_HERE,
                 kPeerdErrorDomain,
                 errors::service::kInvalidServiceOptions,
                 "Invalid entry for mDNS options.");
    return false;
  }
  auto port_it = mdns_options->find(kMDNSPort);
  if (port_it != mdns_options->end()) {
    intmax_t port;
    if (!port_it->second.IsConvertibleToInteger() ||
        (port = port_it->second.GetAsInteger()) < 0 ||
        port > std::numeric_limits<uint16_t>::max()) {
      Error::AddTo(error,
                   FROM_HERE,
                   kPeerdErrorDomain,
                   errors::service::kInvalidServiceOptions,
                   "Invalid entry for mDNS port.");
      return false;
    }
    parsed_mdns_options_.port = static_cast<uint16_t>(port);
    mdns_options->erase(port_it);
  }
  if (!mdns_options->empty()) {
      Error::AddTo(error,
                   FROM_HERE,
                   kPeerdErrorDomain,
                   errors::service::kInvalidServiceOptions,
                   "Extra entry in mDNS options.");
      return false;
  }
  return true;
}

}  // namespace peerd
