// Copyright 2019 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 <lib/sysmem-connector/sysmem-connector.h>

#include <fbl/auto_lock.h>
#include <fbl/function.h>
#include <fbl/mutex.h>
#include <fbl/unique_fd.h>
#include <fuchsia/sysmem/c/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/watcher.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/directory.h>
#include <lib/fzl/fdio.h>
#include <lib/zx/channel.h>

#include <fcntl.h>
#include <errno.h>
#include <queue>
#include <threads.h>

// The actual sysmem FIDL server is in the sysmem driver.  The code that watches
// for the driver and sends sysmem service requests to the driver is in
// ulib/sysmem-connector.  The code here just needs to queue requests to
// sysmem-connector.

// Clients interact with sysmem-connector using a C ABI, but we want to use C++
// for the implementation.  We have SysmemConnector inherit from an empty
// sysmem_connector struct just to make the SysmemConnector class officially be
// a class not a struct, and to make the SysmemConnector name consistent with
// C++ coding conventions, and have member names with "_" at the end consistent
// with coding conventions, etc.
//
// Every instance of sysmem_connector is actually a SysmemConnector and vice
// versa.
struct sysmem_connector {
    // Intentionally declared as empty; never instantiated; see SysmemConnector.
};
class SysmemConnector : public sysmem_connector {
  // public in this case just means public to this file.  The interface is via
  // the functions declared in lib/sysmem-connector/sysmem-connector.h.
  public:
    SysmemConnector(const char* sysmem_device_path);
    zx_status_t Start();
    void QueueRequest(zx::channel allocator_request);
    void Stop();
  private:
    void Post(fbl::Closure to_run);

    static zx_status_t DeviceAddedShim(int dirfd, int event, const char* fn, void* cookie);
    zx_status_t DeviceAdded(int dirfd, int event, const char* fn);

    zx_status_t ConnectToSysmemDriver();

    void ProcessQueue();

    //
    // Set once during construction + Start(), never set again.
    //

    const char* sysmem_device_path_{};
    async::Loop process_queue_loop_;
    thrd_t process_queue_thrd_{};

    //
    // Only touched from process_queue_loop_'s one thread.
    //

    fbl::unique_fd sysmem_dir_fd_;
    zx::channel driver_connector_client_;

    //
    // Synchronized using lock_.
    //

    fbl::Mutex lock_;
    std::queue<zx::channel> connection_requests_ __TA_GUARDED(lock_);
};

SysmemConnector::SysmemConnector(const char* sysmem_device_path)
    : sysmem_device_path_(sysmem_device_path),
      process_queue_loop_(&kAsyncLoopConfigNoAttachToThread) {
    ZX_DEBUG_ASSERT(sysmem_device_path_);
}

zx_status_t SysmemConnector::Start() {
    // The process_queue_thrd_ is filled out before any code that checks it runs on the thread, because the current
    // thread is the only thread that triggers anything to happen on the thread being created here, and that is only
    // done after process_queue_thrd_ is filled out by the current thread.
    zx_status_t status = process_queue_loop_.StartThread("SysmemConnector-ProcessQueue", &process_queue_thrd_);
    if (status != ZX_OK) {
        printf("sysmem-connector: process_queue_loop_.StartThread() failed - status: %d\n", status);
        return status;
    }
    // Establish initial connection to sysmem driver async.
    Post([this]{ConnectToSysmemDriver();});
    return ZX_OK;
}

void SysmemConnector::QueueRequest(zx::channel allocator_request) {
    ZX_DEBUG_ASSERT(thrd_current() != process_queue_thrd_);
    bool trigger_needed;
    {  // scope lock
        fbl::AutoLock lock(&lock_);
        trigger_needed = connection_requests_.empty();
        connection_requests_.emplace(std::move(allocator_request));
    }  // ~lock
    if (trigger_needed) {
        Post([this]{ProcessQueue();});
    }
}

void SysmemConnector::Stop() {
    ZX_DEBUG_ASSERT(thrd_current() != process_queue_thrd_);
    process_queue_loop_.Quit();
    process_queue_loop_.JoinThreads();
    process_queue_loop_.Shutdown();
}

void SysmemConnector::Post(fbl::Closure to_run) {
    zx_status_t post_status = async::PostTask(
        process_queue_loop_.dispatcher(), std::move(to_run));
    // We don't expect this post to ever fail.
    ZX_ASSERT(post_status == ZX_OK);
}

zx_status_t SysmemConnector::DeviceAddedShim(int dirfd, int event, const char* fn, void* cookie) {
    ZX_DEBUG_ASSERT(cookie);
    SysmemConnector* connector = static_cast<SysmemConnector*>(cookie);
    return connector->DeviceAdded(dirfd, event, fn);
}

zx_status_t SysmemConnector::DeviceAdded(int dirfd, int event, const char* filename) {
    ZX_DEBUG_ASSERT(thrd_current() == process_queue_thrd_);
    if (event != WATCH_EVENT_ADD_FILE) {
        // Keep going on IDLE or REMOVE.  There's nothing else useful that the
        // current thread can do until a sysmem device instance is available,
        // and we don't have any reason to attempt to directly handle any
        // REMOVE(s) since we'll do fdio_watch_directory() again later from
        // scratch instead.
        return ZX_OK;
    }
    ZX_DEBUG_ASSERT(event == WATCH_EVENT_ADD_FILE);

    zx::channel driver_connector_client;
    zx::channel driver_connector_server;
    zx_status_t status = zx::channel::create(0, &driver_connector_client, &driver_connector_server);
    if (status != ZX_OK) {
        printf("SysmemConnector::DeviceAdded() zx::channel::create() failed - status: %d\n", status);
        ZX_DEBUG_ASSERT(status != ZX_ERR_STOP);
        // If channel create fails, give up on this attempt to find a sysmem
        // device instance.  If another request arrives later, we'll try again
        // later.
        return status;
    }

    // We don't intend to close dirfd; all paths should release not close.
    fbl::unique_fd unique_dirfd(dirfd);
    fzl::FdioCaller caller(std::move(unique_dirfd));
    status = fdio_service_connect_at(caller.borrow_channel(), filename, driver_connector_server.release());
    // Never close dirfd.
    caller.release().release();
    if (status != ZX_OK) {
        printf("SysmemConnector::DeviceAdded() fdio_service_connect_at() failed - status: %d\n", status);
        ZX_DEBUG_ASSERT(status != ZX_ERR_STOP);
        // If somehow fdio_service_connect_at() fails for this device instance,
        // keep watching for another device instance.
        return ZX_OK;
    }

    driver_connector_client_ = std::move(driver_connector_client);
    ZX_DEBUG_ASSERT(driver_connector_client_);
    return ZX_ERR_STOP;
}

zx_status_t SysmemConnector::ConnectToSysmemDriver() {
    ZX_DEBUG_ASSERT(thrd_current() == process_queue_thrd_);
    ZX_DEBUG_ASSERT(!driver_connector_client_);

    ZX_DEBUG_ASSERT(!sysmem_dir_fd_);
    {
        int fd = open(sysmem_device_path_, O_DIRECTORY | O_RDONLY);
        if (fd < 0) {
            printf("sysmem-connector: Failed to open %s: %d\n", sysmem_device_path_, errno);
            return ZX_ERR_INTERNAL;
        }
        sysmem_dir_fd_.reset(fd);
    }
    ZX_DEBUG_ASSERT(sysmem_dir_fd_);

    // Returns ZX_ERR_STOP as soon as one of the 000, 001 device instances is
    // found.  We rely on those to go away if the corresponding sysmem instance
    // is no longer operational, so that we don't find them when we call
    // ConnectToSysmemDriver() again upon discovering that we can't send to a
    // previous device instance.
    //
    // TODO(dustingreen): Currently if this watch never finds a sysmem device
    // instance, then sysmem_connector_release() will block forever.  This can
    // be fixed once it's feasible to use DeviceWatcher (or similar) here
    // instead (currently DeviceWatcher is in garnet not zircon).
    zx_status_t watch_status = fdio_watch_directory(
        sysmem_dir_fd_.get(), DeviceAddedShim, ZX_TIME_INFINITE, this);
    if (watch_status != ZX_ERR_STOP) {
        printf("sysmem-connector: Failed to find sysmem device - status: %d\n", watch_status);
        return watch_status;
    }
    ZX_DEBUG_ASSERT(driver_connector_client_);
    return ZX_OK;
}

void SysmemConnector::ProcessQueue() {
    ZX_DEBUG_ASSERT(thrd_current() == process_queue_thrd_);
    while (true) {
        zx::channel allocator_request;
        {  // scope lock
            fbl::AutoLock lock(&lock_);
            if (connection_requests_.empty()) {
                return;
            }
            allocator_request = std::move(connection_requests_.front());
            connection_requests_.pop();
        }  // ~lock
        ZX_DEBUG_ASSERT(allocator_request);

        // Poll for PEER_CLOSED just before we need the channel to be usable, to
        // avoid routing a request to a stale no-longer-usable sysmem device
        // instance.  This doesn't eliminate the inherent race where a request
        // can be sent to an instance that's already started failing - that race
        // is fine.  This check is just a best-effort way to avoid routing to a
        // super-stale previous instance.
        //
        // TODO(dustingreen): When it becomes more convenient, switch to
        // noticing PEER_CLOSED async.  Currently it doesn't seem particularly
        // safe to use sysmem_fdio_caller_.borrow_channel() to borrow for an
        // async wait.
        if (driver_connector_client_) {
            zx_signals_t observed;
            zx_status_t wait_status = zx_object_wait_one(
                driver_connector_client_.get(),
                ZX_CHANNEL_PEER_CLOSED,
                ZX_TIME_INFINITE_PAST,
                &observed);
            if (wait_status == ZX_OK) {
                ZX_DEBUG_ASSERT(observed & ZX_CHANNEL_PEER_CLOSED);
                // This way, we'll call ConnectToSysmemDriver() below.
                driver_connector_client_.reset();
            } else {
                // Any other failing status is unexpected.
                ZX_DEBUG_ASSERT(ZX_ERR_TIMED_OUT);
            }
        }

        if (!driver_connector_client_) {
            zx_status_t connect_status = ConnectToSysmemDriver();
            if (connect_status != ZX_OK) {
                // ~allocator_request - we'll try again to connect to a sysmem
                // instance next time a request comes in, but any given request
                // gets a max of one attempt to connect to a sysmem device
                // instance, in case attempts to find a sysmem device instance
                // are just failing.
                return;
            }
        }
        ZX_DEBUG_ASSERT(driver_connector_client_);

        zx_status_t send_connect_status = fuchsia_sysmem_DriverConnectorConnect(
            driver_connector_client_.get(), allocator_request.release());
        if (send_connect_status != ZX_OK) {
            // The most likely failing send_connect_status is
            // ZX_ERR_PEER_CLOSED, which can happen if the channel closed since
            // we checked above.  Since we don't really expect even
            // ZX_ERR_PEER_CLOSED unless sysmem is having problems, complain
            // about the error regardless of which error.
            printf("SysmemConnector::ProcessQueue() DriverConnectorConnect() returned unexpected status: %d\n",
                    send_connect_status);

            // Regardless of the specific error, we want to try
            // ConnectToSysmemDriver() again for the _next_ request.
            driver_connector_client_.reset();

            // We don't retry this request (the window for getting
            // ZX_ERR_PEER_CLOSED is short due to check above, and exists in any
            // case due to possibility of close from other end at any time), but
            // the next request will try ConnectToSysmemDriver() again.
            //
            // continue with next request
        }
    }
}

zx_status_t sysmem_connector_init(const char* sysmem_device_path, sysmem_connector_t** out_connector) {
    SysmemConnector* connector = new SysmemConnector(sysmem_device_path);
    zx_status_t status = connector->Start();
    if (status != ZX_OK) {
        printf("sysmem_connector_init() connector->Start() failed - status: %d\n", status);
        return status;
    }
    *out_connector = connector;
    return ZX_OK;
}

void sysmem_connector_queue_connection_request(
    sysmem_connector_t* connector_param,
    zx_handle_t allocator_request_param) {
    zx::channel allocator_request(allocator_request_param);
    ZX_DEBUG_ASSERT(connector_param);
    ZX_DEBUG_ASSERT(allocator_request);
    SysmemConnector* connector = static_cast<SysmemConnector*>(connector_param);
    connector->QueueRequest(std::move(allocator_request));
}

void sysmem_connector_release(sysmem_connector_t* connector_param) {
    ZX_DEBUG_ASSERT(connector_param);
    SysmemConnector* connector = static_cast<SysmemConnector*>(connector_param);
    connector->Stop();
    delete connector;
}
