// 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/util.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 allocator2_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() {
    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_);

    // 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 allocator2_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(allocator2_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_);
    // 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 allocator2_request;
        {  // scope lock
            fbl::AutoLock lock(&lock_);
            if (connection_requests_.empty()) {
                return;
            }
            allocator2_request = std::move(connection_requests_.front());
            connection_requests_.pop();
        }  // ~lock
        ZX_DEBUG_ASSERT(allocator2_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) {
                // ~allocator2_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(), allocator2_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 allocator2_request_param) {
    zx::channel allocator2_request(allocator2_request_param);
    ZX_DEBUG_ASSERT(connector_param);
    ZX_DEBUG_ASSERT(allocator2_request);
    SysmemConnector* connector = static_cast<SysmemConnector*>(connector_param);
    connector->QueueRequest(std::move(allocator2_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;
}
