// Copyright 2018 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/sys/appmgr/service_provider_dir_impl.h"

#include <fuchsia/logger/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>

#include <string_view>

#include "src/lib/fxl/strings/substitute.h"

namespace component {

namespace {
constexpr char kSandboxDocUrl[] =
    "https://fuchsia.dev/fuchsia-src/concepts/process/sandboxing#services-components-v1";

std::string ServiceNotInSandbox(const std::string& component_moniker,
                                const std::string& service_name) {
  return fxl::Substitute(
      "`$0` is not allowed to connect to `$1` because this service is not present in the "
      "component's sandbox.\nRefer to $2 for more information.",
      component_moniker, service_name, kSandboxDocUrl);
}

std::string ServiceNotAvailable(const std::string& component_moniker,
                                const std::string& service_name) {
  return fxl::Substitute(
      "`$0` could not connect to `$1` because this service is not present in the component's "
      "environment or additional services.",
      component_moniker, service_name);
}

std::string ErrorServingService(const std::string& component_moniker,
                                const std::string& service_name, zx_status_t status) {
  return fxl::Substitute(
      "`$0` could not connect to `$1`, because even though the service was present we encountered "
      "an error attempting to serve from it: $2",
      component_moniker, service_name, std::string(zx_status_get_string(status)));
}

}  // namespace

ServiceProviderDirImpl::ServiceProviderDirImpl(fbl::RefPtr<LogConnectorImpl> log_connector,
                                               const std::vector<std::string>* services)
    : vfs_(async_get_default_dispatcher()),
      root_(fbl::MakeRefCounted<fs::PseudoDir>()),
      log_connector_(log_connector),
      weak_factory_(this) {
  if (services != nullptr) {
    has_services_allowlist_ = true;
    services_allowlist_.insert(services->begin(), services->end());
  }
}

ServiceProviderDirImpl::~ServiceProviderDirImpl() {}

void ServiceProviderDirImpl::set_parent(fbl::RefPtr<ServiceProviderDirImpl> parent) {
  if (parent_) {
    return;
  }
  parent_ = parent;
  // Inherit the parent's services.
  for (const auto& s : parent_->service_handles_) {
    // Don't inherit the parent's LogSink if it was provided by appmgr because parent's LogSink
    // is private and attributed to itself. However, if parent's LogSink is custom (not provided
    // by appmgr), then it will be inherited.
    if (s.first == fuchsia::logger::LogSink::Name_ && parent->has_builtin_logsink_) {
      continue;
    }
    AddService(s.first, s.second);
  }
}

void ServiceProviderDirImpl::AddService(const std::string& service_name,
                                        fbl::RefPtr<fs::Service> service) {
  if (all_service_names_.count(service_name) > 0) {
    // Don't allow duplicate services. This path can be reached if a child
    // would inherit a service from its parent with a name that it already
    // has. In that case, the child's service should take priority.
    return;
  }
  if (IsServiceAllowlisted(service_name)) {
    service_handles_.push_back({service_name, service});
    root_->AddEntry(service_name, std::move(service));
    all_service_names_.insert(service_name);
  }
}

void ServiceProviderDirImpl::AddBinding(
    fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> request) {
  bindings_.AddBinding(this, std::move(request));
}

void ServiceProviderDirImpl::ConnectToService(std::string service_name, zx::channel channel) {
  if (!IsServiceAllowlisted(service_name)) {
    FX_LOGS(WARNING) << ServiceNotInSandbox(component_moniker_, service_name);
    return;
  }
  fbl::RefPtr<fs::Vnode> child;
  zx_status_t status = root_->Lookup(service_name, &child);
  if (status == ZX_OK) {
    status = vfs_.Serve(child, std::move(channel), fs::VnodeConnectionOptions());
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << ErrorServingService(component_moniker_, service_name, status);
    }
  } else {
    FX_LOGS(WARNING) << ServiceNotAvailable(component_moniker_, service_name);
  }
}

zx_status_t ServiceProviderDirImpl::GetAttributes(fs::VnodeAttributes* a) {
  return root_->GetAttributes(a);
}

zx_status_t ServiceProviderDirImpl::Readdir(fs::VdirCookie* cookie, void* dirents, size_t len,
                                            size_t* out_actual) {
  return root_->Readdir(cookie, dirents, len, out_actual);
}

zx_status_t ServiceProviderDirImpl::GetNodeInfoForProtocol(
    [[maybe_unused]] fs::VnodeProtocol protocol, [[maybe_unused]] fs::Rights rights,
    fs::VnodeRepresentation* representation) {
  *representation = fs::VnodeRepresentation::Directory();
  return ZX_OK;
}

fs::VnodeProtocolSet ServiceProviderDirImpl::GetProtocols() const {
  return fs::VnodeProtocol::kDirectory;
}

zx_status_t ServiceProviderDirImpl::Lookup(std::string_view name, fbl::RefPtr<fs::Vnode>* out) {
  const std::string service_name(name.data(), name.length());
  if (!IsServiceAllowlisted(service_name)) {
    FX_LOGS(WARNING) << ServiceNotInSandbox(component_moniker_, service_name);
    return ZX_ERR_NOT_FOUND;
  }
  zx_status_t status = root_->Lookup(name, out);
  if (status != ZX_OK && service_not_available_warnings_logged_.find(service_name) ==
                             service_not_available_warnings_logged_.end()) {
    FX_LOGS(WARNING) << ServiceNotAvailable(component_moniker_, service_name);
    service_not_available_warnings_logged_.insert(service_name);
  }
  return status;
}

void ServiceProviderDirImpl::InitLogging() {
  // A log connector if they ask for it.
  if (IsServiceAllowlisted(fuchsia::sys::internal::LogConnector::Name_)) {
    AddService(
        fuchsia::sys::internal::LogConnector::Name_,
        fbl::MakeRefCounted<fs::Service>([this](zx::channel channel) {
          fidl::InterfaceRequest<fuchsia::sys::internal::LogConnector> request(std::move(channel));
          log_connector_->AddConnectorClient(std::move(request));
          return ZX_OK;
        }));
  }

  // If LogSink was allowlisted and wasn't explicitly provided to us, give it an attributed log
  // sink.
  if (all_service_names_.count(fuchsia::logger::LogSink::Name_) == 0 &&
      IsServiceAllowlisted(fuchsia::logger::LogSink::Name_)) {
    has_builtin_logsink_ = true;
    // Forward the LogSink request to the backing LogConnector, attributing it with
    AddService(fuchsia::logger::LogSink::Name_,
               fbl::MakeRefCounted<fs::Service>([this](zx::channel channel) {
                 fidl::InterfaceRequest<fuchsia::logger::LogSink> request(std::move(channel));
                 log_connector_->AddLogConnection(component_url(), component_id_,
                                                  std::move(request));
                 return ZX_OK;
               }));
  }
}

}  // namespace component
