// Copyright 2016 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/namespace.h"

#include <fuchsia/process/cpp/fidl.h>
#include <fuchsia/sys/internal/cpp/fidl.h>
#include <fuchsia/sys2/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/trace/event.h>
#include <zircon/assert.h>
#include <zircon/errors.h>

#include <utility>

#include "fbl/ref_ptr.h"
#include "fuchsia/sys/cpp/fidl.h"
#include "lib/async/cpp/task.h"
#include "src/sys/appmgr/job_provider_impl.h"
#include "src/sys/appmgr/realm.h"
#include "src/sys/appmgr/util.h"

namespace component {

Namespace::Namespace(fxl::WeakPtr<Realm> realm, fuchsia::sys::ServiceListPtr additional_services,
                     const std::vector<std::string>* service_allowlist)
    : Namespace(PrivateConstructor{}, nullptr, std::move(realm), std::move(additional_services),
                service_allowlist) {}

Namespace::Namespace(PrivateConstructor p, fxl::RefPtr<Namespace> parent, fxl::WeakPtr<Realm> realm,
                     fuchsia::sys::ServiceListPtr additional_services,
                     const std::vector<std::string>* service_allowlist)
    : vfs_(async_get_default_dispatcher()), weak_ptr_factory_(this), status_(Status::RUNNING) {
  fbl::RefPtr<LogConnectorImpl> connector;
  if (realm) {
    connector = realm->log_connector();
  }
  services_ = fbl::MakeRefCounted<ServiceProviderDirImpl>(connector, service_allowlist);
  job_provider_ = fbl::MakeRefCounted<JobProviderImpl>(realm.get());
  realm_ = std::move(realm);
  // WARNING! Do not add new services here! This makes services available in all
  // component namespaces ambiently without requiring proper routing between
  // realms, and this list should not be expanded.
  services_->AddService(
      fuchsia::sys::Environment::Name_,
      fbl::MakeRefCounted<fs::Service>([this](zx::channel channel) {
        if (status_ == Status::RUNNING) {
          environment_bindings_.AddBinding(
              this, fidl::InterfaceRequest<fuchsia::sys::Environment>(std::move(channel)));
        }
        return ZX_OK;
      }));
  services_->AddService(
      Launcher::Name_, fbl::MakeRefCounted<fs::Service>([this](zx::channel channel) {
        if (status_ == Status::RUNNING) {
          launcher_bindings_.AddBinding(this, fidl::InterfaceRequest<Launcher>(std::move(channel)));
        }
        return ZX_OK;
      }));
  services_->AddService(
      fuchsia::process::Launcher::Name_,
      fbl::MakeRefCounted<fs::Service>([this](zx::channel channel) {
        if (realm_) {
          realm_->environment_services()->Connect(
              fidl::InterfaceRequest<fuchsia::process::Launcher>(std::move(channel)));
          return ZX_OK;
        }
        return ZX_ERR_BAD_STATE;
      }));
  services_->AddService(
      fuchsia::process::Resolver::Name_,
      fbl::MakeRefCounted<fs::Service>([this](zx::channel channel) {
        resolver_bindings_.AddBinding(
            this, fidl::InterfaceRequest<fuchsia::process::Resolver>(std::move(channel)));
        return ZX_OK;
      }));

  // WARNING! Do not add new services here! This makes services available in all
  // component namespaces ambiently without requiring proper routing between
  // realms, and this list should not be expanded.

  if (additional_services) {
    auto& names = additional_services->names;
    service_provider_ = additional_services->provider.Bind();
    service_host_directory_ = std::move(additional_services->host_directory);
    for (auto& name : names) {
      if (service_host_directory_) {
        services_->AddService(name,
                              fbl::MakeRefCounted<fs::Service>([this, name](zx::channel channel) {
                                fdio_service_connect_at(service_host_directory_.get(), name.c_str(),
                                                        channel.release());
                                return ZX_OK;
                              }));
      } else {
        services_->AddService(name,
                              fbl::MakeRefCounted<fs::Service>([this, name](zx::channel channel) {
                                service_provider_->ConnectToService(name, std::move(channel));
                                return ZX_OK;
                              }));
      }
    }
  }

  // If any services in |parent| share a name with |additional_services|,
  // |additional_services| takes priority.
  if (parent) {
    services_->set_parent(parent->services());
    parent_ = parent->weak_ptr_factory_.GetWeakPtr();
  }

  services_->InitLogging();
}

Namespace::~Namespace() {}

fxl::RefPtr<Namespace> Namespace::CreateChildNamespace(
    fxl::RefPtr<Namespace>& parent, fxl::WeakPtr<Realm> realm,
    fuchsia::sys::ServiceListPtr additional_services,
    const std::vector<std::string>* service_allowlist) {
  ZX_ASSERT(parent);
  if (parent->status_ != Status::RUNNING) {
    return nullptr;
  }
  fxl::RefPtr<Namespace> ns =
      fxl::MakeRefCounted<Namespace>(PrivateConstructor{}, parent, std::move(realm),
                                     std::move(additional_services), service_allowlist);
  parent->AddChild(ns);
  return ns;
}

void Namespace::AddChild(fxl::RefPtr<Namespace> child) {
  children_.emplace(child.get(), std::move(child));
}

void Namespace::AddBinding(fidl::InterfaceRequest<fuchsia::sys::Environment> environment) {
  environment_bindings_.AddBinding(this, std::move(environment));
}

void Namespace::CreateNestedEnvironment(
    fidl::InterfaceRequest<fuchsia::sys::Environment> environment,
    fidl::InterfaceRequest<fuchsia::sys::EnvironmentController> controller, std::string label,
    fuchsia::sys::ServiceListPtr additional_services, fuchsia::sys::EnvironmentOptions options) {
  if (realm_ && status_ == Status::RUNNING) {
    realm_->CreateNestedEnvironment(std::move(environment), std::move(controller), std::move(label),
                                    std::move(additional_services), options);
  }
}

void Namespace::GetLauncher(fidl::InterfaceRequest<Launcher> launcher) {
  launcher_bindings_.AddBinding(this, std::move(launcher));
}

void Namespace::GetServices(fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
  services_->AddBinding(std::move(services));
}

zx_status_t Namespace::ServeServiceDirectory(zx::channel directory_request) {
  return vfs_.ServeDirectory(services_, std::move(directory_request));
}

void Namespace::CreateComponent(
    fuchsia::sys::LaunchInfo launch_info,
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
  if (status_ != Status::RUNNING) {
    ComponentRequestWrapper component_request(std::move(controller));
    component_request.SetReturnValues(-1, fuchsia::sys::TerminationReason::REALM_SHUTTING_DOWN);
    return;
  }
  auto cc_trace_id = TRACE_NONCE();
  TRACE_ASYNC_BEGIN("appmgr", "Namespace::CreateComponent", cc_trace_id, "launch_info.url",
                    launch_info.url);
  if (realm_) {
    realm_->CreateComponent(std::move(launch_info), std::move(controller),
                            [cc_trace_id](std::weak_ptr<ComponentControllerImpl> component) {
                              TRACE_ASYNC_END("appmgr", "Namespace::CreateComponent", cc_trace_id);
                            });
  } else {
    ComponentRequestWrapper component_request(std::move(controller));
    component_request.SetReturnValues(-1, fuchsia::sys::TerminationReason::REALM_SHUTTING_DOWN);
  }
}

zx::channel Namespace::OpenServicesAsDirectory() { return Util::OpenAsDirectory(&vfs_, services_); }

void Namespace::Resolve(std::string name, fuchsia::process::Resolver::ResolveCallback callback) {
  if (realm_) {
    realm_->Resolve(name, std::move(callback));
  } else {
    zx::vmo binary;
    fidl::InterfaceHandle<fuchsia::ldsvc::Loader> loader;
    callback(ZX_ERR_UNAVAILABLE, std::move(binary), std::move(loader));
  }
}

void Namespace::NotifyComponentDiagnosticsDirReady(
    const std::string& component_url, const std::string& component_name,
    const std::string& component_id, fidl::InterfaceHandle<fuchsia::io::Directory> directory) {
  if (realm_) {
    realm_->NotifyComponentDiagnosticsDirReady(component_url, component_name, component_id,
                                               std::move(directory));
  }
}

void Namespace::NotifyComponentStarted(const std::string& component_url,
                                       const std::string& component_name,
                                       const std::string& component_id) {
  if (realm_) {
    realm_->NotifyComponentStarted(component_url, component_name, component_id);
  }
}

void Namespace::NotifyComponentStopped(const std::string& component_url,
                                       const std::string& component_name,
                                       const std::string& component_id) {
  if (realm_) {
    realm_->NotifyComponentStopped(component_url, component_name, component_id);
  }
}

void Namespace::MaybeAddComponentEventProvider() {
  if (services_->IsServiceAllowlisted(fuchsia::sys::internal::ComponentEventProvider::Name_)) {
    services_->AddService(
        fuchsia::sys::internal::ComponentEventProvider::Name_,
        fbl::MakeRefCounted<fs::Service>([this](zx::channel channel) {
          if (realm_) {
            return realm_->BindComponentEventProvider(
                fidl::InterfaceRequest<fuchsia::sys::internal::ComponentEventProvider>(
                    std::move(channel)));
          }
          return ZX_ERR_BAD_STATE;
        }));
  }
}

void Namespace::RunShutdownIfNoChildren(fxl::RefPtr<Namespace> ns) {
  if (ns->status_ == Status::SHUTTING_DOWN && ns->children_.empty()) {
    ns->vfs_.CloseAllConnectionsForVnode(*ns->services_, [ns]() {
      ns->status_ = Status::STOPPED;
      for (auto& callback : ns->shutdown_callbacks_) {
        async::PostTask(async_get_default_dispatcher(),
                        [callback = std::move(callback)]() mutable { callback(); });
      }
      ns->shutdown_callbacks_.clear();
      ns->vfs_.Shutdown([ns](zx_status_t /*unused*/) mutable { ns.reset(); });
    });
  }
}

void Namespace::ExtractChild(fxl::RefPtr<Namespace> ns, Namespace* child) {
  ns->children_.erase(child);
  RunShutdownIfNoChildren(std::move(ns));
}

void Namespace::FlushAndShutdown(fxl::RefPtr<Namespace> self,
                                 fs::ManagedVfs::CloseAllConnectionsForVnodeCallback callback) {
  ZX_ASSERT(self.get() == this);
  switch (status_) {
    case Status::SHUTTING_DOWN:
      // We are already shutting down. Store callback and return.
      if (callback) {
        shutdown_callbacks_.push_back(std::move(callback));
      }
      return;
    case Status::STOPPED:
      if (callback) {
        async::PostTask(async_get_default_dispatcher(),
                        [self, callback = std::move(callback)]() mutable { callback(); });
      }
      return;
    case Status::RUNNING:
      if (callback) {
        shutdown_callbacks_.push_back(std::move(callback));
      }
      break;
  }
  status_ = Status::SHUTTING_DOWN;
  environment_bindings_.CloseAll();
  launcher_bindings_.CloseAll();
  if (children_.empty()) {
    RunShutdownIfNoChildren(std::move(self));
    return;
  }

  for (auto& child : children_) {
    async::PostTask(async_get_default_dispatcher(), [ns = child.second, self]() {
      ns->FlushAndShutdown(ns, [ptr = ns.get(), self]() { ExtractChild(self, ptr); });
    });
  }
}

}  // namespace component
