// Copyright 2020 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.

//! Utility functions for fuchsia.io nodes.

use {
    fidl_fuchsia_io as fio, fuchsia_zircon_status as zx_status, futures::prelude::*,
    thiserror::Error,
};

#[cfg(target_os = "fuchsia")]
use fuchsia_zircon as zx;

/// An error encountered while opening a node
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum OpenError {
    #[error("while making a fidl proxy: {0}")]
    CreateProxy(#[source] fidl::Error),

    #[error("while opening from namespace: {0}")]
    Namespace(#[source] zx_status::Status),

    #[error("while sending open request: {0}")]
    SendOpenRequest(#[source] fidl::Error),

    #[error("node event stream closed prematurely")]
    OnOpenEventStreamClosed,

    #[error("while reading OnOpen event: {0}")]
    OnOpenDecode(#[source] fidl::Error),

    #[error("open failed with status: {0}")]
    OpenError(#[source] zx_status::Status),

    #[error("remote responded with success but provided no node info")]
    MissingOnOpenInfo,

    #[error("expected node to be a {expected:?}, but got a {actual:?}")]
    UnexpectedNodeKind { expected: Kind, actual: Kind },
}

/// An error encountered while cloning a node
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum CloneError {
    #[error("while making a fidl proxy: {0}")]
    CreateProxy(#[source] fidl::Error),

    #[error("while sending clone request: {0}")]
    SendCloneRequest(#[source] fidl::Error),
}

/// An error encountered while closing a node
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum CloseError {
    #[error("while sending close request: {0}")]
    SendCloseRequest(#[source] fidl::Error),

    #[error("close failed with status: {0}")]
    CloseError(#[source] zx_status::Status),
}

/// An error encountered while renaming a node
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum RenameError {
    #[error("while sending rename request")]
    SendRenameRequest(#[source] fidl::Error),

    #[error("while sending get_token request")]
    SendGetTokenRequest(#[source] fidl::Error),

    #[error("rename failed with status")]
    RenameError(#[source] zx_status::Status),

    #[error("while opening subdirectory")]
    OpenError(#[from] OpenError),

    #[error("get_token failed with status")]
    GetTokenError(#[source] zx_status::Status),

    #[error("no handle from get token")]
    NoHandleError,
}

/// The type of a filesystem node
#[derive(Debug, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum Kind {
    Service,
    File,
    Directory,
    Pipe,
    Vmofile,
    Device,
    Tty,
    SynchronousDatagramSocket,
    StreamSocket,
    RawSocket,
    PacketSocket,
    DatagramSocket,
    Unknown,
}

impl Kind {
    fn kind_of(info: &fio::NodeInfo) -> Kind {
        match info {
            fio::NodeInfo::Service(_) => Kind::Service,
            fio::NodeInfo::File(_) => Kind::File,
            fio::NodeInfo::Directory(_) => Kind::Directory,
            fio::NodeInfo::Pipe(_) => Kind::Pipe,
            fio::NodeInfo::Vmofile(_) => Kind::Vmofile,
            fio::NodeInfo::Device(_) => Kind::Device,
            fio::NodeInfo::Tty(_) => Kind::Tty,
            fio::NodeInfo::SynchronousDatagramSocket(_) => Kind::SynchronousDatagramSocket,
            fio::NodeInfo::StreamSocket(_) => Kind::StreamSocket,
            fio::NodeInfo::RawSocket(_) => Kind::RawSocket,
            fio::NodeInfo::PacketSocket(_) => Kind::PacketSocket,
            fio::NodeInfo::DatagramSocket(_) => Kind::DatagramSocket,
        }
    }

    fn expect_file(info: fio::NodeInfo) -> Result<(), Kind> {
        match info {
            fio::NodeInfo::File(fio::FileObject { event: _, stream: None })
            | fio::NodeInfo::Vmofile(fio::Vmofile { .. }) => Ok(()),
            other => Err(Kind::kind_of(&other)),
        }
    }

    fn expect_directory(info: fio::NodeInfo) -> Result<(), Kind> {
        match info {
            fio::NodeInfo::Directory(fio::DirectoryObject) => Ok(()),
            other => Err(Kind::kind_of(&other)),
        }
    }

    fn kind_of2(representation: &fio::Representation) -> Kind {
        match representation {
            fio::Representation::Connector(_) => Kind::Service,
            fio::Representation::Directory(_) => Kind::Directory,
            fio::Representation::File(_) => Kind::File,
            fio::Representation::Memory(_) => Kind::Vmofile,
            fio::Representation::Pipe(_) => Kind::Pipe,
            fio::Representation::Device(_) => Kind::Device,
            fio::Representation::Tty(_) => Kind::Tty,
            fio::Representation::SynchronousDatagramSocket(_) => Kind::SynchronousDatagramSocket,
            fio::Representation::StreamSocket(_) => Kind::StreamSocket,
            fio::Representation::RawSocket(_) => Kind::RawSocket,
            fio::Representation::PacketSocket(_) => Kind::PacketSocket,
            fio::Representation::DatagramSocket(_) => Kind::DatagramSocket,
            _ => Kind::Unknown,
        }
    }

    fn expect_file2(representation: &fio::Representation) -> Result<(), Kind> {
        match representation {
            fio::Representation::File(fio::FileInfo { stream: None, .. })
            | fio::Representation::Memory(_) => Ok(()),
            other => Err(Kind::kind_of2(other)),
        }
    }

    fn expect_directory2(representation: &fio::Representation) -> Result<(), Kind> {
        match representation {
            fio::Representation::Directory(_) => Ok(()),
            other => Err(Kind::kind_of2(other)),
        }
    }
}

// TODO namespace.connect is synchronous and may involve fdio making synchronous fidl calls to
// remote directories.  If/when fdio exposes the root namespace mapping or an API to connect to
// nodes asynchronously, this function should be updated to use that.
/// Connect a zx::Channel to a path in the current namespace.
#[cfg(target_os = "fuchsia")]
pub fn connect_in_namespace(
    path: &str,
    flags: fio::OpenFlags,
    chan: zx::Channel,
) -> Result<(), zx_status::Status> {
    let namespace = fdio::Namespace::installed()?;
    namespace.connect(path, flags, chan)?;
    Ok(())
}

/// Opens the given `path` from the current namespace as a [`NodeProxy`]. The target is not
/// verified to be any particular type and may not implement the fuchsia.io.Node protocol.
#[cfg(target_os = "fuchsia")]
pub fn open_in_namespace(path: &str, flags: fio::OpenFlags) -> Result<fio::NodeProxy, OpenError> {
    let (node, server_end) =
        fidl::endpoints::create_proxy::<fio::NodeMarker>().map_err(OpenError::CreateProxy)?;

    connect_in_namespace(path, flags, server_end.into_channel()).map_err(OpenError::Namespace)?;

    Ok(node)
}

/// Gracefully closes the node proxy from the remote end.
pub async fn close(node: fio::NodeProxy) -> Result<(), CloseError> {
    let result = node.close().await.map_err(CloseError::SendCloseRequest)?;
    result.map_err(|s| CloseError::CloseError(zx_status::Status::from_raw(s)))
}

/// Consume the first event from this NodeProxy's event stream, returning the proxy if it is
/// the expected type or an error otherwise.
pub(crate) async fn verify_node_describe_event(
    node: fio::NodeProxy,
) -> Result<fio::NodeProxy, OpenError> {
    let mut events = node.take_event_stream();
    match events
        .next()
        .await
        .ok_or(OpenError::OnOpenEventStreamClosed)?
        .map_err(OpenError::OnOpenDecode)?
    {
        fio::NodeEvent::OnOpen_ { s: status, info } => {
            let () = zx_status::Status::ok(status).map_err(OpenError::OpenError)?;
            info.ok_or(OpenError::MissingOnOpenInfo)?;
        }
        fio::NodeEvent::OnConnectionInfo { .. } => (),
    }

    Ok(node)
}

/// Consume the first event from this DirectoryProxy's event stream, returning the proxy if it is
/// the expected type or an error otherwise.
pub(crate) async fn verify_directory_describe_event(
    node: fio::DirectoryProxy,
) -> Result<fio::DirectoryProxy, OpenError> {
    let mut events = node.take_event_stream();
    match events
        .next()
        .await
        .ok_or(OpenError::OnOpenEventStreamClosed)?
        .map_err(OpenError::OnOpenDecode)?
    {
        fio::DirectoryEvent::OnOpen_ { s: status, info } => {
            let () = zx_status::Status::ok(status).map_err(OpenError::OpenError)?;
            let info = info.ok_or(OpenError::MissingOnOpenInfo)?;
            let () = Kind::expect_directory(*info).map_err(|actual| {
                OpenError::UnexpectedNodeKind { expected: Kind::Directory, actual }
            })?;
        }
        fio::DirectoryEvent::OnConnectionInfo { info } => {
            let representation = info.representation.ok_or(OpenError::MissingOnOpenInfo)?;
            let () = Kind::expect_directory2(&representation).map_err(|actual| {
                OpenError::UnexpectedNodeKind { expected: Kind::Directory, actual }
            })?;
        }
    }

    Ok(node)
}

/// Consume the first event from this FileProxy's event stream, returning the proxy if it is the
/// expected type or an error otherwise.
pub(crate) async fn verify_file_describe_event(
    node: fio::FileProxy,
) -> Result<fio::FileProxy, OpenError> {
    let mut events = node.take_event_stream();

    match events
        .next()
        .await
        .ok_or(OpenError::OnOpenEventStreamClosed)?
        .map_err(OpenError::OnOpenDecode)?
    {
        fio::FileEvent::OnOpen_ { s: status, info } => {
            let () = zx_status::Status::ok(status).map_err(OpenError::OpenError)?;
            let info = info.ok_or(OpenError::MissingOnOpenInfo)?;
            let () = Kind::expect_file(*info)
                .map_err(|actual| OpenError::UnexpectedNodeKind { expected: Kind::File, actual })?;
        }
        fio::FileEvent::OnConnectionInfo { info } => {
            let representation = info.representation.ok_or(OpenError::MissingOnOpenInfo)?;
            let () = Kind::expect_file2(&representation)
                .map_err(|actual| OpenError::UnexpectedNodeKind { expected: Kind::File, actual })?;
        }
    }

    Ok(node)
}

#[cfg(test)]
mod tests {
    use {super::*, crate::OpenFlags, assert_matches::assert_matches, fuchsia_async as fasync};

    // open_in_namespace

    #[fasync::run_singlethreaded(test)]
    async fn open_in_namespace_opens_real_node() {
        let file_node = open_in_namespace("/pkg/data/file", OpenFlags::RIGHT_READABLE).unwrap();
        let info = file_node.describe().await.unwrap();
        assert_matches!(Kind::expect_file(info), Ok(()));

        let dir_node = open_in_namespace("/pkg/data", OpenFlags::RIGHT_READABLE).unwrap();
        let info = dir_node.describe().await.unwrap();
        assert_eq!(Kind::expect_directory(info), Ok(()));
    }

    #[fasync::run_singlethreaded(test)]
    async fn open_in_namespace_opens_fake_node_under_of_root_namespace_entry() {
        let notfound = open_in_namespace("/pkg/fake", OpenFlags::RIGHT_READABLE).unwrap();
        // The open error is not detected until the proxy is interacted with.
        assert_matches!(close(notfound).await, Err(_));
    }

    #[fasync::run_singlethreaded(test)]
    async fn open_in_namespace_rejects_fake_root_namespace_entry() {
        assert_matches!(
            open_in_namespace("/fake", OpenFlags::RIGHT_READABLE),
            Err(OpenError::Namespace(zx_status::Status::NOT_FOUND))
        );
    }
}
