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

// The constant and type definitions in this file must all match
// //zircon/system/public/zircon/processargs.h
//
// TODO: Figure out a more foolproof way to keep these in sync, e.g. bindgen from the header
// directly, or maybe a new Tricium linter like IfThisThenThat.

use {
    fuchsia_runtime::HandleInfo,
    fuchsia_zircon as zx,
    std::convert::TryFrom,
    std::ffi::CString,
    std::fmt,
    std::mem,
    std::num,
    thiserror::Error,
    zerocopy::{AsBytes, FromBytes},
};

/// Possible errors that can occur during processargs startup message construction
#[allow(missing_docs)] // No docs on individual error variants.
#[derive(Error, Debug)]
pub enum ProcessargsError {
    TryFromInt(num::TryFromIntError),
    SizeTooLarge(usize),
    TooManyHandles(usize),
}

impl ProcessargsError {
    /// Returns an appropriate zx::Status code for the given error.
    pub fn as_zx_status(&self) -> zx::Status {
        match self {
            ProcessargsError::TryFromInt(_)
            | ProcessargsError::SizeTooLarge(_)
            | ProcessargsError::TooManyHandles(_) => zx::Status::INVALID_ARGS,
        }
    }
}

// Can't use macro-based failure Display derive with the _MAX_MSG_BYTES argument below
impl fmt::Display for ProcessargsError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ProcessargsError::TryFromInt(e) => {
                write!(f, "Value > u32 MAX when building processargs message: {}", e)
            }
            ProcessargsError::SizeTooLarge(v) => write!(
                f,
                "Cannot build processargs message, byte size too large ({} > {})",
                v,
                zx::sys::ZX_CHANNEL_MAX_MSG_BYTES
            ),
            ProcessargsError::TooManyHandles(v) => write!(
                f,
                "Cannot build processargs message, too many handles ({} > {})",
                v,
                zx::sys::ZX_CHANNEL_MAX_MSG_HANDLES
            ),
        }
    }
}

const ZX_PROCARGS_PROTOCOL: u32 = 0x4150585d;
const ZX_PROCARGS_VERSION: u32 = 0x00001000;

/// Header for bootstrap message following the processargs protocol.
#[derive(FromBytes, AsBytes, Default)]
#[repr(C)]
pub(crate) struct MessageHeader {
    // Protocol and version identifiers to allow for different process start message protocols and
    // versioning of the same.
    pub protocol: u32,
    pub version: u32,

    // Offset from start of message to handle info array, which contains one HandleInfo as a u32
    // per handle passed along with the message.
    pub handle_info_off: u32,

    // Offset from start of message to arguments and count of arguments. Arguments are provided as
    // a set of null-terminated UTF-8 strings, one after the other.
    pub args_off: u32,
    pub args_num: u32,

    // Offset from start of message to environment strings and count of them.  Environment entries
    // are provided as a set of null-terminated UTF-8 strings, one after the other. Canonically
    // each string has the form "NAME=VALUE", but nothing enforces this.
    pub environ_off: u32,
    pub environ_num: u32,

    // Offset from start of message to namespace path strings and count of them. These strings are
    // packed similar to the argument strings, but are referenced by NamespaceDirectory (PA_NS_DIR)
    // handle table entries and used to set up namespaces.
    //
    // Specifically: In a handle table entry with HandleType of NamespaceDirectory (PA_NS_DIR), the
    // u16 handle info argument is an index into this name table.
    names_off: u32,
    names_num: u32,
}

/// A container for a single startup handle, containing a handle and metadata. Used as an input to
/// [ProcessBuilder::add_handles()].
///
/// [ProcessBuilder::add_handles()]: crate::ProcessBuilder::add_handles()
pub struct StartupHandle {
    /// A handle.
    pub handle: zx::Handle,

    /// Handle metadata. See [fuchsia_runtime::HandleInfo].
    pub info: HandleInfo,
}

#[derive(Default)]
pub struct MessageContents {
    pub args: Vec<CString>,
    pub environment_vars: Vec<CString>,
    pub namespace_paths: Vec<CString>,
    pub handles: Vec<StartupHandle>,
}

/// A bootstrap message following the processargs protocol.
///
/// See [//docs/zircon/program_loading.md#The-processargs-protocol][program_loading.md] or
/// [//zircon/system/public/zircon/processargs.h][processargs] for more details.
///
/// [program_loading.md]: https://fuchsia.dev/fuchsia-src/concepts/booting/program_loading#The-processargs-protocol
/// [processargs]: https://fuchsia.googlesource.com/fuchsia/+/HEAD/zircon/system/public/zircon/processargs.h
pub struct Message {
    bytes: Vec<u8>,
    handles: Vec<zx::Handle>,
}

// Return type of fuchsia_runtime::HandleInfo::as_raw(), checked with static assert below.
type HandleInfoRaw = u32;

impl Message {
    /// Create a new bootstrap message using the given contents.
    pub fn build(contents: MessageContents) -> Result<Message, ProcessargsError> {
        let (header, size) = Self::build_header(&contents)?;

        let mut data = Vec::with_capacity(size);
        data.extend_from_slice(header.as_bytes());

        // Sanity check length against the offsets in the header as we go. Failures are bugs in
        // this code and serious enough to panic rather than continue, hence the asserts rather
        // than returning an Err().
        assert!(data.len() == header.handle_info_off as usize);
        let mut handles = Vec::with_capacity(contents.handles.len());
        for handle in contents.handles {
            let raw_info = handle.info.as_raw();
            static_assertions::assert_eq_size_val!(raw_info, 0 as HandleInfoRaw);

            data.extend_from_slice(&raw_info.to_ne_bytes());
            handles.push(handle.handle);
        }

        assert!(data.len() == header.args_off as usize);
        for arg in &contents.args {
            data.extend_from_slice(arg.as_bytes_with_nul());
        }

        assert!(data.len() == header.environ_off as usize);
        for var in &contents.environment_vars {
            data.extend_from_slice(var.as_bytes_with_nul());
        }

        assert!(data.len() == header.names_off as usize);
        for path in &contents.namespace_paths {
            data.extend_from_slice(path.as_bytes_with_nul());
        }

        // Sanity check final message size.
        assert!(data.len() == size);
        Ok(Message { bytes: data, handles })
    }

    /// Calculate the size that a bootstrap message will be if created using the given contents.
    ///
    /// Note that the size returned is only for the message data and does not include the size of
    /// the handles themselves, only the handle info in the message.
    pub fn calculate_size(contents: &MessageContents) -> Result<usize, ProcessargsError> {
        let (_, size) = Self::build_header(contents)?;
        Ok(size)
    }

    /// Builds the processargs message header for the given config, as well as calculates the total
    /// message size.
    fn build_header(config: &MessageContents) -> Result<(MessageHeader, usize), ProcessargsError> {
        let num_handles = config.handles.len();
        if num_handles > zx::sys::ZX_CHANNEL_MAX_MSG_HANDLES as usize {
            return Err(ProcessargsError::TooManyHandles(num_handles));
        }

        let mut header = MessageHeader {
            protocol: ZX_PROCARGS_PROTOCOL,
            version: ZX_PROCARGS_VERSION,
            ..Default::default()
        };

        let mut size = mem::size_of_val(&header);
        let mut f = || {
            header.handle_info_off = u32::try_from(size)?;
            size += mem::size_of::<HandleInfoRaw>() * num_handles;

            header.args_off = u32::try_from(size)?;
            header.args_num = u32::try_from(config.args.len())?;
            for arg in &config.args {
                size += arg.as_bytes_with_nul().len();
            }

            header.environ_off = u32::try_from(size)?;
            header.environ_num = u32::try_from(config.environment_vars.len())?;
            for var in &config.environment_vars {
                size += var.as_bytes_with_nul().len();
            }

            header.names_off = u32::try_from(size)?;
            header.names_num = u32::try_from(config.namespace_paths.len())?;
            for path in &config.namespace_paths {
                size += path.as_bytes_with_nul().len();
            }
            Ok(())
        };
        f().map_err(|e| ProcessargsError::TryFromInt(e))?;

        if size > zx::sys::ZX_CHANNEL_MAX_MSG_BYTES as usize {
            return Err(ProcessargsError::SizeTooLarge(size));
        }
        Ok((header, size))
    }

    /// Write the processargs message to the provided channel.
    pub fn write(self, channel: &zx::Channel) -> Result<(), zx::Status> {
        let mut handles = self.handles;
        channel.write(self.bytes.as_slice(), &mut handles)
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        anyhow::Error,
        fuchsia_runtime::HandleType,
        fuchsia_zircon::{AsHandleRef, HandleBased},
        std::iter,
    };

    #[test]
    fn build_and_write_message() -> Result<(), Error> {
        // We need some dummy handles to use in the message below, since you can't send an invalid
        // handle in a channel. We just use VMOs since they're easy to create, even though they're
        // not semantically valid for a processargs handle type like PA_NS_DIR.
        let (dum0, dum1, dum2) = (zx::Vmo::create(1)?, zx::Vmo::create(1)?, zx::Vmo::create(1)?);
        let handles = vec![
            StartupHandle {
                handle: dum0.into_handle(),
                info: HandleInfo::new(HandleType::User1, 0x1234),
            },
            StartupHandle {
                handle: dum1.into_handle(),
                info: HandleInfo::new(HandleType::NamespaceDirectory, 0),
            },
            StartupHandle {
                handle: dum2.into_handle(),
                info: HandleInfo::new(HandleType::NamespaceDirectory, 1),
            },
        ];
        let handle_koids: Vec<zx::Koid> =
            handles.iter().map(|h| h.handle.get_koid()).collect::<Result<_, _>>()?;

        let config = MessageContents {
            args: vec![CString::new("arg1")?, CString::new("arg2")?, CString::new("arg3")?],
            environment_vars: vec![CString::new("FOO=BAR")?],
            namespace_paths: vec![CString::new("/data")?, CString::new("/pkg")?],
            handles,
        };

        let calculated_size = Message::calculate_size(&config)?;
        let message = Message::build(config)?;
        assert_eq!(calculated_size, message.bytes.len());

        // Write the message into a channel, read it back from the other end.
        let (chan_wr, chan_rd) = zx::Channel::create()?;
        message.write(&chan_wr)?;
        let mut read_buf = zx::MessageBuf::new();
        chan_rd.read(&mut read_buf)?;
        let (read_bytes, read_handles) = read_buf.split();

        // concat! doesn't work for byte literals and there's no concat_bytes! (yet), so we just
        // build this in a Vec instead since it's a test.
        let mut correct = Vec::new();
        correct.extend_from_slice(b"\x5d\x58\x50\x41"); // protocol
        correct.extend_from_slice(b"\x00\x10\x00\x00"); // version
        correct.extend_from_slice(b"\x24\x00\x00\x00"); // handle_info_off
        correct.extend_from_slice(b"\x30\x00\x00\x00"); // args_off
        correct.extend_from_slice(b"\x03\x00\x00\x00"); // args_num
        correct.extend_from_slice(b"\x3F\x00\x00\x00"); // environ_off
        correct.extend_from_slice(b"\x01\x00\x00\x00"); // environ_num
        correct.extend_from_slice(b"\x47\x00\x00\x00"); // names_off
        correct.extend_from_slice(b"\x02\x00\x00\x00"); // names_num
        correct.extend_from_slice(b"\xF1\x00\x34\x12"); // handle info
        correct.extend_from_slice(b"\x20\x00\x00\x00"); //
        correct.extend_from_slice(b"\x20\x00\x01\x00"); //
        correct.extend_from_slice(b"arg1\0"); // args
        correct.extend_from_slice(b"arg2\0"); //
        correct.extend_from_slice(b"arg3\0"); //
        correct.extend_from_slice(b"FOO=BAR\0"); // environ
        correct.extend_from_slice(b"/data\0"); // namespace paths
        correct.extend_from_slice(b"/pkg\0");

        assert_eq!(read_bytes.len(), calculated_size);
        assert_eq!(read_bytes, correct);

        let read_koids: Vec<zx::Koid> =
            read_handles.iter().map(|h| h.get_koid()).collect::<Result<_, _>>()?;
        assert_eq!(read_koids, handle_koids);

        Ok(())
    }

    #[test]
    fn byte_limit() -> Result<(), Error> {
        const LIMIT: usize = zx::sys::ZX_CHANNEL_MAX_MSG_BYTES as usize;
        const ARG_LIMIT: usize = LIMIT - 1 - mem::size_of::<MessageHeader>();

        let (chan_wr, chan_rd) = zx::Channel::create()?;
        let mut read_buf = zx::MessageBuf::new();

        let make_bytes = iter::repeat_with(|| b'a');
        let arg: CString = CString::new(make_bytes.take(ARG_LIMIT).collect::<Vec<u8>>())?;
        let config = MessageContents { args: vec![arg], ..Default::default() };

        // Should succeed at limit.
        Message::build(config)?.write(&chan_wr)?;
        chan_rd.read(&mut read_buf)?;
        assert_eq!(read_buf.bytes().len(), LIMIT);

        // Should fail to build just over limit.
        let arg2: CString = CString::new(make_bytes.take(ARG_LIMIT + 1).collect::<Vec<u8>>())?;
        let config2 = MessageContents { args: vec![arg2], ..Default::default() };
        let result = Message::build(config2);
        match result {
            Err(ProcessargsError::SizeTooLarge(_)) => {}
            Err(err) => {
                panic!("Unexpected error type: {}", err);
            }
            Ok(_) => {
                panic!("build message unexpectedly succeeded with too large argument");
            }
        }
        Ok(())
    }

    #[test]
    fn handle_limit() -> Result<(), Error> {
        const LIMIT: usize = zx::sys::ZX_CHANNEL_MAX_MSG_HANDLES as usize;

        let make_handles = iter::repeat_with(|| StartupHandle {
            handle: zx::Vmo::create(1).expect("Failed to create VMO").into_handle(),
            info: HandleInfo::new(HandleType::User1, 0),
        });
        let handles: Vec<StartupHandle> = make_handles.take(LIMIT).collect();

        let config = MessageContents { handles, ..Default::default() };

        // Should succeed at limit.
        let (chan_wr, chan_rd) = zx::Channel::create()?;
        Message::build(config)?.write(&chan_wr)?;
        let mut read_buf = zx::MessageBuf::new();
        chan_rd.read(&mut read_buf)?;
        assert_eq!(read_buf.n_handles(), LIMIT);

        // Should fail to build with one more handle.
        let handles2: Vec<StartupHandle> = make_handles.take(LIMIT + 1).collect();
        let config2 = MessageContents { handles: handles2, ..Default::default() };
        let result = Message::build(config2);
        match result {
            Err(ProcessargsError::TooManyHandles(_)) => {}
            Err(err) => {
                panic!("Unexpected error type: {}", err);
            }
            Ok(_) => {
                panic!("build message unexpectedly succeeded with too many handles");
            }
        }
        Ok(())
    }
}
