// 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::AdoptRef(new ServiceProviderDirImpl(connector, service_allowlist));
  job_provider_ = fbl::AdoptRef(new 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::AdoptRef(new 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::AdoptRef(new 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::AdoptRef(new 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::AdoptRef(new 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::AdoptRef(new 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::AdoptRef(new 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::AdoptRef(new 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() {
  if (status_ == Status::SHUTTING_DOWN && children_.empty()) {
    vfs_.CloseAllConnectionsForVnode(*services_, [this]() {
      status_ = Status::STOPPED;
      for (auto& callback : shutdown_callbacks_) {
        async::PostTask(async_get_default_dispatcher(),
                        [callback = std::move(callback)]() mutable { callback(); });
      }
      shutdown_callbacks_.clear();
      vfs_.Shutdown([this](zx_status_t /*unused*/) { self_for_shutdown_.reset(); });
    });
  }
}

void Namespace::ExtractChild(Namespace* child) {
  children_.erase(child);
  RunShutdownIfNoChildren();
}

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();
  self_for_shutdown_ = std::move(self);
  if (children_.empty()) {
    RunShutdownIfNoChildren();
    return;
  }

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

}  // namespace component
