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

#include <fbl/string.h>
#include <fbl/vector.h>
#include <fuchsia/process/c/fidl.h>
#include <lib/fidl/cpp/message_buffer.h>
#include <lib/zx/channel.h>
#include <lib/zx/job.h>
#include <stdint.h>
#include <zircon/processargs.h>
#include <zircon/status.h>

#include <utility>

namespace launcher {
namespace {

fbl::String GetString(fidl_string_t string) {
    return fbl::String(string.data, string.size);
}

fbl::String GetString(fidl_vector_t bytes) {
    return fbl::String(static_cast<char*>(bytes.data), bytes.count);
}

void PushStrings(fidl_vector_t* input, fbl::Vector<fbl::String>* target) {
    fidl_vector_t* data = static_cast<fidl_vector_t*>(input->data);
    for (size_t i = 0; i < input->count; ++i) {
        target->push_back(GetString(data[i]));
    }
}

void PushCStrs(const fbl::Vector<fbl::String>& source, fbl::Vector<const char*>* target) {
    target->reserve(target->size() + source.size());
    for (const auto& str : source) {
        target->push_back(str.c_str());
    }
}

} // namespace

LauncherImpl::LauncherImpl(zx::channel channel)
    : channel_(std::move(channel)),
      wait_(this, channel_.get(), ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED) {
}

LauncherImpl::~LauncherImpl() = default;

zx_status_t LauncherImpl::Begin(async_dispatcher_t* dispatcher) {
    return wait_.Begin(dispatcher);
}

void LauncherImpl::OnHandleReady(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
                                 const zx_packet_signal_t* signal) {
    if (status != ZX_OK) {
        NotifyError(status);
        return;
    }

    if (signal->observed & ZX_CHANNEL_READABLE) {
        fidl::MessageBuffer buffer;
        for (uint64_t i = 0; i < signal->count; i++) {
            status = ReadAndDispatchMessage(&buffer);
            if (status == ZX_ERR_SHOULD_WAIT)
                break;
            if (status != ZX_OK) {
                NotifyError(status);
                return;
            }
        }
        status = wait_.Begin(dispatcher);
        if (status != ZX_OK) {
            NotifyError(status);
        }
        return;
    }

    ZX_DEBUG_ASSERT(signal->observed & ZX_CHANNEL_PEER_CLOSED);
    // Notice that we don't notify an error until we've drained all the messages
    // out of the channel.
    NotifyError(ZX_ERR_PEER_CLOSED);
}

zx_status_t LauncherImpl::ReadAndDispatchMessage(fidl::MessageBuffer* buffer) {
    fidl::Message message = buffer->CreateEmptyMessage();
    zx_status_t status = message.Read(channel_.get(), 0);
    if (status != ZX_OK)
        return status;
    if (!message.has_header())
        return ZX_ERR_INVALID_ARGS;
    // This is an if statement because, depending on the state of the ordinal
    // migration, GenOrdinal and Ordinal may be the same value.  See FIDL-372
    uint32_t ordinal = message.ordinal();
    if (ordinal == fuchsia_process_LauncherLaunchOrdinal ||
        ordinal == fuchsia_process_LauncherLaunchGenOrdinal) {
        return Launch(buffer, std::move(message));
    } else if (ordinal == fuchsia_process_LauncherCreateWithoutStartingOrdinal ||
               ordinal == fuchsia_process_LauncherCreateWithoutStartingGenOrdinal) {
        return CreateWithoutStarting(buffer, std::move(message));
    } else if (ordinal == fuchsia_process_LauncherAddArgsOrdinal ||
               ordinal == fuchsia_process_LauncherAddArgsGenOrdinal) {
        return AddArgs(std::move(message));
    } else if (ordinal == fuchsia_process_LauncherAddEnvironsOrdinal ||
               ordinal == fuchsia_process_LauncherAddEnvironsGenOrdinal) {
        return AddEnvirons(std::move(message));
    } else if (ordinal == fuchsia_process_LauncherAddNamesOrdinal ||
               ordinal == fuchsia_process_LauncherAddNamesGenOrdinal) {
        return AddNames(std::move(message));
    } else if (ordinal == fuchsia_process_LauncherAddHandlesOrdinal ||
               ordinal == fuchsia_process_LauncherAddHandlesGenOrdinal) {
        return AddHandles(std::move(message));
    } else {
        fprintf(stderr, "launcher: error: Unknown message ordinal: %d\n", message.ordinal());
        return ZX_ERR_NOT_SUPPORTED;
    }
}

zx_status_t LauncherImpl::Launch(fidl::MessageBuffer* buffer, fidl::Message message) {
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(&fuchsia_process_LauncherLaunchRequestTable, &error_msg);
    if (status != ZX_OK) {
        fprintf(stderr, "launcher: error: Launch: %s\n", error_msg);
        return status;
    }

    zx_txid_t txid = message.txid();
    uint32_t ordinal = message.ordinal();

    launchpad_t* lp = nullptr;
    PrepareLaunchpad(message, &lp);

    fidl::Builder builder = buffer->CreateBuilder();
    auto* response = builder.New<fuchsia_process_LauncherLaunchResponse>();
    response->hdr.txid = txid;
    response->hdr.ordinal = ordinal;
    response->status = launchpad_go(lp, &response->process, &error_msg);

    if (response->status != ZX_OK && error_msg) {
        fprintf(stderr, "launcher: error: Launch: %s\n", error_msg);
    }

    message.set_bytes(builder.Finalize());
    Reset();

    status = message.Encode(&fuchsia_process_LauncherLaunchResponseTable, &error_msg);
    if (status != ZX_OK) {
        fprintf(stderr, "launcher: error: Launch: %s\n", error_msg);
        return status;
    }
    return message.Write(channel_.get(), 0);
}

zx_status_t LauncherImpl::CreateWithoutStarting(fidl::MessageBuffer* buffer, fidl::Message message) {
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(&fuchsia_process_LauncherCreateWithoutStartingRequestTable, &error_msg);
    if (status != ZX_OK) {
        fprintf(stderr, "launcher: error: CreateWithoutStarting: %s\n", error_msg);
        return status;
    }

    zx_txid_t txid = message.txid();
    uint32_t ordinal = message.ordinal();

    launchpad_t* lp = nullptr;
    PrepareLaunchpad(message, &lp);

    fidl::Builder builder = buffer->CreateBuilder();
    auto* response = builder.New<fuchsia_process_LauncherCreateWithoutStartingResponse>();
    response->hdr.txid = txid;
    response->hdr.ordinal = ordinal;

    launchpad_start_data_t data = {};
    response->status = launchpad_ready_set(lp, &data, &error_msg);

    if (response->status == ZX_OK) {
        response->data = builder.New<fuchsia_process_ProcessStartData>();
        response->data->process = data.process;
        response->data->root_vmar = data.root_vmar;
        response->data->thread = data.thread;
        response->data->entry = data.entry;
        response->data->stack = data.stack;
        response->data->bootstrap = data.bootstrap;
        response->data->vdso_base = data.vdso_base;
        response->data->base = data.base;
    } else if (error_msg) {
        fprintf(stderr, "launcher: error: CreateWithoutStarting: %s\n", error_msg);
    }

    message.set_bytes(builder.Finalize());
    Reset();

    status = message.Encode(&fuchsia_process_LauncherCreateWithoutStartingResponseTable, &error_msg);
    if (status != ZX_OK) {
        fprintf(stderr, "launcher: error: CreateWithoutStarting: %s\n", error_msg);
        return status;
    }
    return message.Write(channel_.get(), 0);
}

zx_status_t LauncherImpl::AddArgs(fidl::Message message) {
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(&fuchsia_process_LauncherAddArgsRequestTable, &error_msg);
    if (status != ZX_OK) {
        fprintf(stderr, "launcher: error: AddArgs: %s\n", error_msg);
        return status;
    }
    PushStrings(message.GetPayloadAs<fidl_vector_t>(), &args_);
    return ZX_OK;
}

zx_status_t LauncherImpl::AddEnvirons(fidl::Message message) {
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(&fuchsia_process_LauncherAddEnvironsRequestTable, &error_msg);
    if (status != ZX_OK) {
        fprintf(stderr, "launcher: error: AddEnvirons: %s\n", error_msg);
        return status;
    }
    PushStrings(message.GetPayloadAs<fidl_vector_t>(), &environs_);
    return ZX_OK;
}

zx_status_t LauncherImpl::AddNames(fidl::Message message) {
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(&fuchsia_process_LauncherAddNamesRequestTable, &error_msg);
    if (status != ZX_OK) {
        fprintf(stderr, "launcher: error: AddNames: %s\n", error_msg);
        return status;
    }
    fidl_vector_t* payload = message.GetPayloadAs<fidl_vector_t>();
    fuchsia_process_NameInfo* names = static_cast<fuchsia_process_NameInfo*>(payload->data);
    for (size_t i = 0; i < payload->count; ++i) {
        ids_.push_back(PA_HND(PA_NS_DIR, static_cast<uint32_t>(nametable_.size())));
        handles_.push_back(zx::handle(names[i].directory));
        nametable_.push_back(GetString(names[i].path));
    }
    return ZX_OK;
}

zx_status_t LauncherImpl::AddHandles(fidl::Message message) {
    const char* error_msg = nullptr;
    zx_status_t status = message.Decode(&fuchsia_process_LauncherAddHandlesRequestTable, &error_msg);
    if (status != ZX_OK) {
        fprintf(stderr, "launcher: error: AddHandles: %s\n", error_msg);
        return status;
    }
    fidl_vector_t* payload = message.GetPayloadAs<fidl_vector_t>();
    fuchsia_process_HandleInfo* handles = static_cast<fuchsia_process_HandleInfo*>(payload->data);
    for (size_t i = 0; i < payload->count; ++i) {
        if (handles[i].id == PA_LDSVC_LOADER) {
            // We need to feed PA_LDSVC_LOADER to launchpad through a different API.
            ldsvc_.reset(handles[i].handle);
        } else {
            ids_.push_back(handles[i].id);
            handles_.push_back(zx::handle(handles[i].handle));
        }
    }
    return ZX_OK;
}

void LauncherImpl::PrepareLaunchpad(const fidl::Message& message, launchpad_t** lp_out) {
    fuchsia_process_LaunchInfo* info = message.GetPayloadAs<fuchsia_process_LaunchInfo>();

    // Grab an owning reference to the job because launchpad does not take
    // ownership of the job. We need to close the handle ourselves.
    zx::job job(info->job);
    fbl::String name = GetString(info->name);

    fbl::Vector<const char*> args, environs, nametable;
    PushCStrs(args_, &args);
    PushCStrs(environs_, &environs);
    PushCStrs(nametable_, &nametable);
    environs.push_back(nullptr);

    launchpad_t* lp = nullptr;
    launchpad_create_with_jobs(job.get(), ZX_HANDLE_INVALID, name.c_str(), &lp);

    if (!ldsvc_) {
        launchpad_abort(lp, ZX_ERR_INVALID_ARGS, "need ldsvc to load PT_INTERP");
    }

    // There's a subtle issue at this point. The problem is that launchpad will
    // make a synchronous call into the loader service to read the PT_INTERP,
    // but this handle was provided by our client, which means our client can
    // hang the launcher.
    zx::channel old_ldsvc(launchpad_use_loader_service(lp, ldsvc_.release()));

    launchpad_load_from_vmo(lp, info->executable);
    launchpad_set_args(lp, static_cast<int>(args.size()), args.get());
    launchpad_set_environ(lp, environs.get());
    launchpad_set_nametable(lp, nametable.size(), nametable.get());
    launchpad_add_handles(lp, ids_.size(), reinterpret_cast<zx_handle_t*>(handles_.get()), ids_.get());
    // launchpad_add_handles() took ownership of the handles in handles_.
    for (auto& handle : handles_) {
        __UNUSED zx_handle_t old_handle = handle.release();
    }

    *lp_out = lp;
}

void LauncherImpl::NotifyError(zx_status_t error) {
    Reset();
    channel_.reset();
    if (error_handler_)
        error_handler_(error);
    // We might be deleted now.
}

void LauncherImpl::Reset() {
    args_.reset();
    environs_.reset();
    nametable_.reset();
    ids_.reset();
    handles_.reset();
    ldsvc_.reset();
}

} // namespace launcher
