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

#include <fbl/algorithm.h>
#include <fbl/string_printf.h>
#include <fs/remote-dir.h>
#include <fuchsia/device/manager/c/fidl.h>
#include <fuchsia/fshost/c/fidl.h>
#include <fuchsia/net/c/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/directory.h>
#include <lib/logger/provider.h>
#include <lib/process-launcher/launcher.h>
#include <lib/profile/profile.h>
#include <lib/svc/outgoing.h>
#include <lib/kernel-debug/kernel-debug.h>
#include <lib/zx/job.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>

// An instance of a zx_service_provider_t.
//
// Includes the |ctx| pointer for the zx_service_provider_t.
typedef struct zx_service_provider_instance {
    // The service provider for which this structure is an instance.
    const zx_service_provider_t* provider;

    // The |ctx| pointer returned by the provider's |init| function, if any.
    void* ctx;
} zx_service_provider_instance_t;

// start_crashsvc() is implemented in crashsvc.cpp.
void start_crashsvc(zx::job root_job, zx_handle_t analyzer_svc);

static zx_status_t provider_init(zx_service_provider_instance_t* instance) {
    if (instance->provider->ops->init) {
        zx_status_t status = instance->provider->ops->init(&instance->ctx);
        if (status != ZX_OK)
            return status;
    }
    return ZX_OK;
}

static zx_status_t provider_publish(zx_service_provider_instance_t* instance,
                                    async_dispatcher_t* dispatcher, const fbl::RefPtr<fs::PseudoDir>& dir) {
    const zx_service_provider_t* provider = instance->provider;

    if (!provider->services || !provider->ops->connect)
        return ZX_ERR_INVALID_ARGS;

    for (size_t i = 0; provider->services[i]; ++i) {
        const char* service_name = provider->services[i];
        zx_status_t status = dir->AddEntry(
            service_name,
            fbl::MakeRefCounted<fs::Service>([instance, dispatcher, service_name](zx::channel request) {
                return instance->provider->ops->connect(instance->ctx, dispatcher, service_name, request.release());
            }));
        if (status != ZX_OK) {
            for (size_t j = 0; j < i; ++j)
                dir->RemoveEntry(provider->services[j]);
            return status;
        }
    }

    return ZX_OK;
}

static void provider_release(zx_service_provider_instance_t* instance) {
    if (instance->provider->ops->release)
        instance->provider->ops->release(instance->ctx);
    instance->ctx = nullptr;
}

static zx_status_t provider_load(zx_service_provider_instance_t* instance,
                                 async_dispatcher_t* dispatcher, const fbl::RefPtr<fs::PseudoDir>& dir) {
    if (instance->provider->version != SERVICE_PROVIDER_VERSION) {
        return ZX_ERR_INVALID_ARGS;
    }

    zx_status_t status = provider_init(instance);
    if (status != ZX_OK) {
        return status;
    }

    status = provider_publish(instance, dispatcher, dir);
    if (status != ZX_OK) {
        provider_release(instance);
        return status;
    }

    return ZX_OK;
}

static zx_handle_t appmgr_svc;
static zx_handle_t root_job;
static zx_handle_t root_resource;

// We should host the tracelink service ourselves instead of routing the request
// to appmgr.
zx_status_t publish_tracelink(const fbl::RefPtr<fs::PseudoDir>& dir) {
    const char* service_name = "fuchsia.tracelink.Registry";
    return dir->AddEntry(
        service_name,
        fbl::MakeRefCounted<fs::Service>([service_name](zx::channel request) {
            return fdio_service_connect_at(appmgr_svc, service_name, request.release());
        }));
}

// We shouldn't need to access these non-Zircon services from svchost, but
// currently some tests assume they can reach these services from the test
// environment. Instead, we should make the test environment hermetic and
// remove the dependencies on these services.
static constexpr const char* deprecated_services[] = {
    "fuchsia.amber.Control",
    "fuchsia.cobalt.LoggerFactory",
    "fuchsia.devicesettings.DeviceSettingsManager",
    "fuchsia.logger.Log",
    "fuchsia.logger.LogSink",
    // Interface to resolve shell commands.
    "fuchsia.process.Resolver",
    fuchsia_net_SocketProvider_Name,
    // Legacy interface for netstack, defined in //garnet
    "fuchsia.netstack.Netstack",
    // New interface for netstack (WIP), defined in //zircon
    "fuchsia.net.stack.Stack",
    "fuchsia.power.PowerManager",
    "fuchsia.sys.Environment",
    "fuchsia.sys.Launcher",
    "fuchsia.wlan.service.Wlan",
    // TODO(PT-88): This entry is temporary, until PT-88 is resolved.
    "fuchsia.tracing.controller.Controller",
    nullptr,
    // DO NOT ADD MORE ENTRIES TO THIS LIST.
    // Tests should not be accessing services from the environment. Instead,
    // they should run in containers that have their own service instances.
};

// List of services which are re-routed to the fshost service provider handle.
static constexpr const char* fshost_services[] = {
    fuchsia_fshost_Filesystems_Name,
    fuchsia_fshost_Registry_Name,
    nullptr,
};

// The ServiceProxy is a Vnode which, if opened, connects to a service.
// However, if treated like a directory, the service proxy will attempt to
// relay the underlying request to the connected service channel.
class ServiceProxy : public fs::Service {
public:
    ServiceProxy(zx::unowned_channel svc, fbl::StringPiece svc_name)
        : Service([this](zx::channel request) {
            return fdio_service_connect_at(svc_->get(), svc_name_.data(), request.release());
        }), svc_(std::move(svc)), svc_name_(svc_name) {}

    // This proxy may be a directory. Attempt to connect to the requested object,
    // and return a RemoteDir representing the connection.
    //
    // If the underlying service does not speak the directory protocol, then attempting
    // to connect to the service will close the connection. This is expected.
    zx_status_t Lookup(fbl::RefPtr<Vnode>* out, fbl::StringPiece name) final {
        fbl::String path(fbl::StringPrintf("%s/%.*s", svc_name_.data(),
                                           static_cast<int>(name.length()), name.data()));
        zx::channel client, server;
        zx_status_t status = zx::channel::create(0, &client, &server);
        if (status != ZX_OK) {
            return status;
        }
        status = fdio_service_connect_at(svc_->get(), path.data(), server.release());
        if (status != ZX_OK) {
            return status;
        }

        *out = fbl::MakeRefCounted<fs::RemoteDir>(std::move(client));
        return ZX_OK;
    }

private:
    zx::unowned_channel svc_;
    fbl::StringPiece svc_name_;
};

void publish_service(const fbl::RefPtr<fs::PseudoDir>& dir,
                     const char* name, zx::unowned_channel svc) {
    dir->AddEntry(
        name,
        fbl::MakeRefCounted<ServiceProxy>(std::move(svc), name));
}

void publish_services(const fbl::RefPtr<fs::PseudoDir>& dir,
                      const char* const* names, zx::unowned_channel svc) {
    for (size_t i = 0; names[i] != nullptr; ++i) {
        const char* service_name = names[i];
        publish_service(dir, service_name, zx::unowned_channel(svc->get()));
    }
}

void publish_proxy_service(const fbl::RefPtr<fs::PseudoDir>& dir,
                           const char* name, zx::unowned_channel forwarding_channel) {
    fbl::String path = fbl::StringPrintf("public/%s", name);
    dir->AddEntry(name, fbl::MakeRefCounted<fs::Service>(
            [path, forwarding_channel = std::move(forwarding_channel)](zx::channel request) {
                return fdio_service_connect_at(forwarding_channel->get(), path.c_str(), request.release());
            }));
}

int main(int argc, char** argv) {
    bool require_system = false;
    if (argc > 1) {
      require_system = strcmp(argv[1], "--require-system") == 0 ? true: false;
    }
    async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
    async_dispatcher_t* dispatcher = loop.dispatcher();
    svc::Outgoing outgoing(dispatcher);

    appmgr_svc = zx_take_startup_handle(PA_HND(PA_USER0, 0));
    root_job = zx_take_startup_handle(PA_HND(PA_USER0, 1));
    root_resource = zx_take_startup_handle(PA_HND(PA_USER0, 2));
    zx::channel devmgr_proxy_channel = zx::channel(zx_take_startup_handle(PA_HND(PA_USER0, 3)));
    zx::channel fshost_svc = zx::channel(zx_take_startup_handle(PA_HND(PA_USER0, 4)));

    zx_status_t status = outgoing.ServeFromStartupInfo();
    if (status != ZX_OK) {
        fprintf(stderr, "svchost: error: Failed to serve outgoing directory: %d (%s).\n",
                status, zx_status_get_string(status));
        return 1;
    }

    zx_handle_t profile_root_job_copy;
    status = zx_handle_duplicate(root_job, ZX_RIGHT_SAME_RIGHTS, &profile_root_job_copy);
    if (status != ZX_OK) {
        fprintf(stderr, "svchost: failed to duplicate root job: %d (%s).\n", status,
                zx_status_get_string(status));
        return 1;
    }

    zx_service_provider_instance_t service_providers[] = {
        {.provider = launcher_get_service_provider(), .ctx = nullptr},
        {.provider = sysmem2_get_service_provider(), .ctx = nullptr},
        {.provider = kernel_debug_get_service_provider(),
         .ctx = reinterpret_cast<void*>(static_cast<uintptr_t>(root_resource))},
        {.provider = profile_get_service_provider(),
         .ctx = reinterpret_cast<void*>(static_cast<uintptr_t>(profile_root_job_copy))},
    };

    for (size_t i = 0; i < fbl::count_of(service_providers); ++i) {
        status = provider_load(&service_providers[i], dispatcher, outgoing.public_dir());
        if (status != ZX_OK) {
            fprintf(stderr, "svchost: error: Failed to load service provider %zu: %d (%s).\n",
                    i, status, zx_status_get_string(status));
            return 1;
        }
    }

    // if full system is not required drop simple logger service.
    zx_service_provider_instance_t logger_service{.provider = logger_get_service_provider(),
                                                  .ctx = nullptr};
    if(!require_system) {
      status = provider_load(&logger_service, dispatcher, outgoing.public_dir());
      if (status != ZX_OK) {
          fprintf(stderr, "svchost: error: Failed to publish logger: %d (%s).\n",
                status, zx_status_get_string(status));
          return 1;
      }
    }

    status = publish_tracelink(outgoing.public_dir());
    if (status != ZX_OK) {
        fprintf(stderr, "svchost: error: Failed to publish tracelink: %d (%s).\n",
                status, zx_status_get_string(status));
        return 1;
    }

    publish_services(outgoing.public_dir(), deprecated_services, zx::unowned_channel(appmgr_svc));
    publish_services(outgoing.public_dir(), fshost_services, zx::unowned_channel(fshost_svc));

    publish_proxy_service(outgoing.public_dir(),
                          fuchsia_device_manager_DebugDumper_Name,
                          zx::unowned_channel(devmgr_proxy_channel));
    publish_proxy_service(outgoing.public_dir(),
                          fuchsia_device_manager_Administrator_Name,
                          zx::unowned_channel(devmgr_proxy_channel));

    start_crashsvc(zx::job(root_job),
        require_system? appmgr_svc : ZX_HANDLE_INVALID);

    status = loop.Run();

    for (size_t i = 0; i < fbl::count_of(service_providers); ++i) {
        provider_release(&service_providers[i]);
    }

    return status;
}
