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

mod config;
mod validators;

use {
    anyhow::{format_err, Error},
    config::{Config, ConfigContext, FactoryConfig},
    fidl::endpoints::{create_proxy, ProtocolMarker, Request, RequestStream, ServerEnd},
    fidl_fuchsia_boot::FactoryItemsMarker,
    fidl_fuchsia_factory::{
        AlphaFactoryStoreProviderMarker, AlphaFactoryStoreProviderRequest,
        AlphaFactoryStoreProviderRequestStream, CastCredentialsFactoryStoreProviderMarker,
        CastCredentialsFactoryStoreProviderRequest,
        CastCredentialsFactoryStoreProviderRequestStream, MiscFactoryStoreProviderMarker,
        MiscFactoryStoreProviderRequest, MiscFactoryStoreProviderRequestStream,
        PlayReadyFactoryStoreProviderMarker, PlayReadyFactoryStoreProviderRequest,
        PlayReadyFactoryStoreProviderRequestStream, WeaveFactoryStoreProviderMarker,
        WeaveFactoryStoreProviderRequest, WeaveFactoryStoreProviderRequestStream,
        WidevineFactoryStoreProviderMarker, WidevineFactoryStoreProviderRequest,
        WidevineFactoryStoreProviderRequestStream,
    },
    fidl_fuchsia_hardware_block as fhardware_block, fidl_fuchsia_io as fio,
    fidl_fuchsia_storage_ext4::{MountVmoResult, Server_Marker},
    fuchsia_bootfs::BootfsParser,
    fuchsia_component::server::ServiceFs,
    fuchsia_zircon as zx,
    futures::{lock::Mutex, StreamExt as _, TryFutureExt as _, TryStreamExt as _},
    remote_block_device::BlockClient as _,
    std::{io, sync::Arc},
    vfs::{
        directory::{self, entry_container::Directory},
        execution_scope::ExecutionScope,
        file::vmo::read_only,
        tree_builder::TreeBuilder,
    },
};

const CONCURRENT_LIMIT: usize = 10_000;
const DEFAULT_BOOTFS_FACTORY_ITEM_EXTRA: u32 = 0;
const FACTORY_DEVICE_CONFIG: &'static str = "/config/data/factory.config";

enum IncomingServices {
    AlphaFactoryStoreProvider(AlphaFactoryStoreProviderRequestStream),
    CastCredentialsFactoryStoreProvider(CastCredentialsFactoryStoreProviderRequestStream),
    MiscFactoryStoreProvider(MiscFactoryStoreProviderRequestStream),
    PlayReadyFactoryStoreProvider(PlayReadyFactoryStoreProviderRequestStream),
    WeaveFactoryStoreProvider(WeaveFactoryStoreProviderRequestStream),
    WidevineFactoryStoreProvider(WidevineFactoryStoreProviderRequestStream),
}

async fn find_block_device_filepath(partition_path: &str) -> Result<String, Error> {
    const DEV_CLASS_BLOCK: &str = "/dev/class/block";

    let dir =
        fuchsia_fs::directory::open_in_namespace(DEV_CLASS_BLOCK, fio::OpenFlags::RIGHT_READABLE)?;
    device_watcher::wait_for_device_with(
        &dir,
        |device_watcher::DeviceInfo { filename, topological_path }| {
            (topological_path == partition_path)
                .then(|| format!("{}/{}", DEV_CLASS_BLOCK, filename))
        },
    )
    .await
}

fn parse_bootfs<'a>(vmo: zx::Vmo) -> Arc<directory::immutable::Simple> {
    let mut tree_builder = TreeBuilder::empty_dir();

    match BootfsParser::create_from_vmo(vmo) {
        Ok(parser) => parser.iter().for_each(|result| match result {
            Ok(entry) => {
                tracing::info!("Found {} in factory bootfs", &entry.name);

                let name = entry.name;
                let path_parts: Vec<&str> = name.split("/").collect();
                let payload = entry.payload;
                tree_builder
                    .add_entry(
                        &path_parts,
                        read_only(payload.unwrap_or_else(|| {
                            tracing::error!("Failed to buffer bootfs entry {}", name);
                            Vec::new()
                        })),
                    )
                    .unwrap_or_else(|err| {
                        tracing::error!(
                            "Failed to add bootfs entry {} to directory: {}",
                            name,
                            err
                        );
                    });
            }
            Err(err) => tracing::error!("BootfsParser: {}", err),
        }),
        Err(err) => tracing::error!("BootfsParser: {}", err),
    };

    tree_builder.build()
}

async fn fetch_new_factory_item() -> Result<zx::Vmo, Error> {
    let factory_items = fuchsia_component::client::connect_to_protocol::<FactoryItemsMarker>()?;
    let (vmo_opt, _) = factory_items.get(DEFAULT_BOOTFS_FACTORY_ITEM_EXTRA).await?;
    vmo_opt.ok_or(format_err!("Failed to get a valid VMO from service"))
}

async fn read_file_from_proxy<'a>(
    dir_proxy: &'a fio::DirectoryProxy,
    file_path: &'a str,
) -> Result<Vec<u8>, Error> {
    let file = fuchsia_fs::directory::open_file_no_describe(
        &dir_proxy,
        file_path,
        fuchsia_fs::OpenFlags::RIGHT_READABLE,
    )?;
    fuchsia_fs::file::read(&file).await.map_err(Into::into)
}

fn load_config_file(path: &str) -> Result<FactoryConfig, Error> {
    FactoryConfig::load(io::BufReader::new(std::fs::File::open(path)?))
}

async fn create_dir_from_context<'a>(
    context: &'a ConfigContext,
    dir: &'a fio::DirectoryProxy,
) -> Arc<directory::immutable::Simple> {
    let mut tree_builder = TreeBuilder::empty_dir();

    for (path, dest) in &context.file_path_map {
        let contents = match read_file_from_proxy(dir, path).await {
            Ok(contents) => contents,
            Err(_) => {
                tracing::error!("Failed to find {}, skipping", &path);
                continue;
            }
        };

        let mut failed_validation = false;
        let mut validated = false;

        for validator_context in &context.validator_contexts {
            if validator_context.paths_to_validate.contains(path) {
                tracing::info!("Validating {} with {} validator", &path, &validator_context.name);
                if let Err(err) = validator_context.validator.validate(&path, &contents[..]) {
                    tracing::error!("{}", err);
                    failed_validation = true;
                    break;
                }
                validated = true;
            }
        }

        // Do not allow files that failed validation or have not been validated at all.
        if !failed_validation && validated {
            let path_parts: Vec<&str> = dest.split("/").collect();
            let file = read_only(contents);
            tree_builder.add_entry(&path_parts, file).unwrap_or_else(|err| {
                tracing::error!("Failed to add file {} to directory: {}", dest, err);
            });
        } else if !validated {
            tracing::error!("{} was never validated, ignored", &path);
        }
    }

    tree_builder.build()
}

async fn apply_config(config: Config, dir: Arc<Mutex<fio::DirectoryProxy>>) -> fio::DirectoryProxy {
    let (directory_proxy, directory_server_end) = create_proxy::<fio::DirectoryMarker>().unwrap();

    let dir_mtx = dir.clone();

    // We only want to hold this lock to create `dir` so limit the scope of `dir_ref`.
    let dir = {
        let dir_ref = dir_mtx.lock().await;
        let context = config.into_context().expect("Failed to convert config into context");
        create_dir_from_context(&context, &*dir_ref).await
    };

    dir.open(
        ExecutionScope::new(),
        fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::DIRECTORY,
        vfs::path::Path::dot(),
        ServerEnd::<fio::NodeMarker>::new(directory_server_end.into_channel()),
    );

    directory_proxy
}

async fn handle_request_stream<RS, G>(
    mut stream: RS,
    directory_mutex: Arc<Mutex<fio::DirectoryProxy>>,
    mut get_directory_request_fn: G,
) -> Result<(), Error>
where
    RS: RequestStream,
    G: FnMut(Request<RS::Protocol>) -> Option<fidl::endpoints::ServerEnd<fio::DirectoryMarker>>,
{
    while let Some(request) = stream.try_next().await? {
        if let Some(directory_request) = get_directory_request_fn(request) {
            if let Err(err) = directory_mutex.lock().await.clone(
                fio::OpenFlags::RIGHT_READABLE,
                ServerEnd::<fio::NodeMarker>::new(directory_request.into_channel()),
            ) {
                tracing::error!(
                    "Failed to clone directory connection for {}: {:?}",
                    RS::Protocol::DEBUG_NAME,
                    err
                );
            }
        }
    }
    Ok(())
}

async fn open_factory_source(factory_config: FactoryConfig) -> Result<fio::DirectoryProxy, Error> {
    let (directory_proxy, directory_server_end) = create_proxy::<fio::DirectoryMarker>()?;
    match factory_config {
        FactoryConfig::FactoryItems => {
            tracing::info!("{}", "Reading from FactoryItems service");
            let factory_items_directory =
                fetch_new_factory_item().await.map(|vmo| parse_bootfs(vmo)).unwrap_or_else(|err| {
                    tracing::error!(
                        "Failed to get factory item, returning empty item list: {}",
                        err
                    );
                    directory::immutable::simple()
                });

            factory_items_directory.open(
                ExecutionScope::new(),
                fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::DIRECTORY,
                vfs::path::Path::dot(),
                ServerEnd::<fio::NodeMarker>::new(directory_server_end.into_channel()),
            );

            Ok(directory_proxy)
        }
        FactoryConfig::Ext4(partition_path) => {
            tracing::info!("Reading from EXT4-formatted source: {}", partition_path);
            let block_path = find_block_device_filepath(&partition_path).await?;
            tracing::info!("found the block path {}", block_path);
            let proxy = fuchsia_component::client::connect_to_protocol_at_path::<
                fhardware_block::BlockMarker,
            >(&block_path)?;
            let block_client = remote_block_device::RemoteBlockClient::new(proxy).await?;
            let block_count = block_client.block_count();
            let block_size = block_client.block_size();
            let size = block_count.checked_mul(block_size.into()).ok_or_else(|| {
                format_err!("size overflows: block_count={} block_size={}", block_count, block_size)
            })?;
            let buf = async {
                let size = size.try_into()?;
                let mut buf = vec![0u8; size];
                let () = block_client
                    .read_at(remote_block_device::MutableBufferSlice::Memory(buf.as_mut_slice()), 0)
                    .await?;
                Ok::<_, Error>(buf)
            }
            .await?;
            let vmo = zx::Vmo::create(size)?;
            let () = vmo.write(&buf, 0)?;

            let ext4_server = fuchsia_component::client::connect_to_protocol::<Server_Marker>()?;

            tracing::info!("Mounting EXT4 VMO");
            match ext4_server
                .mount_vmo(vmo, fio::OpenFlags::RIGHT_READABLE, directory_server_end)
                .await
            {
                Ok(MountVmoResult::Success(_)) => Ok(directory_proxy),
                Ok(MountVmoResult::VmoReadFailure(status)) => {
                    Err(format_err!("Failed to read ext4 vmo: {}", status))
                }
                Ok(MountVmoResult::ParseError(parse_error)) => {
                    Err(format_err!("Failed to parse ext4 data: {:?}", parse_error))
                }
                Err(err) => Err(Error::from(err)),
                _ => Err(format_err!("Unknown error while mounting ext4 vmo")),
            }
        }
        FactoryConfig::FactoryVerity => {
            tracing::info!("reading from factory verity");
            fdio::open(
                "/factory",
                fio::OpenFlags::RIGHT_READABLE,
                directory_server_end.into_channel(),
            )?;
            Ok(directory_proxy)
        }
    }
}

#[fuchsia::main(logging_tags = ["factory_store_providers"])]
async fn main() -> Result<(), Error> {
    tracing::info!("{}", "Starting factory_store_providers");

    let factory_config = load_config_file(FACTORY_DEVICE_CONFIG).unwrap_or_default();
    let directory_proxy = open_factory_source(factory_config)
        .await
        .map_err(|e| {
            tracing::error!("{:?}", e);
            e
        })
        .unwrap();

    let mut fs = ServiceFs::new();
    fs.dir("svc")
        .add_fidl_service(IncomingServices::AlphaFactoryStoreProvider)
        .add_fidl_service(IncomingServices::CastCredentialsFactoryStoreProvider)
        .add_fidl_service(IncomingServices::MiscFactoryStoreProvider)
        .add_fidl_service(IncomingServices::PlayReadyFactoryStoreProvider)
        .add_fidl_service(IncomingServices::WeaveFactoryStoreProvider)
        .add_fidl_service(IncomingServices::WidevineFactoryStoreProvider);
    fs.take_and_serve_directory_handle().expect("Failed to serve factory providers");

    tracing::info!("{}", "Setting up factory directories");
    let dir_mtx = Arc::new(Mutex::new(directory_proxy));
    let alpha_config = Config::load::<AlphaFactoryStoreProviderMarker>().unwrap_or_default();
    let alpha_directory = Arc::new(Mutex::new(apply_config(alpha_config, dir_mtx.clone()).await));

    let cast_credentials_config = Config::load::<CastCredentialsFactoryStoreProviderMarker>()?;
    let cast_directory =
        Arc::new(Mutex::new(apply_config(cast_credentials_config, dir_mtx.clone()).await));

    let misc_config = Config::load::<MiscFactoryStoreProviderMarker>()?;
    let misc_directory = Arc::new(Mutex::new(apply_config(misc_config, dir_mtx.clone()).await));

    let playready_config = Config::load::<PlayReadyFactoryStoreProviderMarker>()?;
    let playready_directory =
        Arc::new(Mutex::new(apply_config(playready_config, dir_mtx.clone()).await));

    let widevine_config = Config::load::<WidevineFactoryStoreProviderMarker>()?;
    let widevine_directory =
        Arc::new(Mutex::new(apply_config(widevine_config, dir_mtx.clone()).await));

    // The weave config may or may not be present.
    let weave_config = Config::load::<WeaveFactoryStoreProviderMarker>().unwrap_or_default();
    let weave_directory = Arc::new(Mutex::new(apply_config(weave_config, dir_mtx.clone()).await));

    fs.for_each_concurrent(CONCURRENT_LIMIT, move |incoming_service| {
        let alpha_directory_clone = alpha_directory.clone();
        let cast_directory_clone = cast_directory.clone();
        let misc_directory_clone = misc_directory.clone();
        let playready_directory_clone = playready_directory.clone();
        let weave_directory_clone = weave_directory.clone();
        let widevine_directory_clone = widevine_directory.clone();

        async move {
            match incoming_service {
                IncomingServices::AlphaFactoryStoreProvider(stream) => {
                    let alpha_directory_clone = alpha_directory_clone.clone();
                    handle_request_stream(
                        stream,
                        alpha_directory_clone,
                        |req: AlphaFactoryStoreProviderRequest| {
                            req.into_get_factory_store().map(|item| item.0)
                        },
                    )
                    .await
                }
                IncomingServices::CastCredentialsFactoryStoreProvider(stream) => {
                    let cast_directory_clone = cast_directory_clone.clone();
                    handle_request_stream(
                        stream,
                        cast_directory_clone,
                        |req: CastCredentialsFactoryStoreProviderRequest| {
                            req.into_get_factory_store().map(|item| item.0)
                        },
                    )
                    .await
                }
                IncomingServices::MiscFactoryStoreProvider(stream) => {
                    let misc_directory_clone = misc_directory_clone.clone();
                    handle_request_stream(
                        stream,
                        misc_directory_clone,
                        |req: MiscFactoryStoreProviderRequest| {
                            req.into_get_factory_store().map(|item| item.0)
                        },
                    )
                    .await
                }
                IncomingServices::PlayReadyFactoryStoreProvider(stream) => {
                    let playready_directory_clone = playready_directory_clone.clone();
                    handle_request_stream(
                        stream,
                        playready_directory_clone,
                        |req: PlayReadyFactoryStoreProviderRequest| {
                            req.into_get_factory_store().map(|item| item.0)
                        },
                    )
                    .await
                }
                IncomingServices::WeaveFactoryStoreProvider(stream) => {
                    let weave_directory_clone = weave_directory_clone.clone();
                    handle_request_stream(
                        stream,
                        weave_directory_clone,
                        |req: WeaveFactoryStoreProviderRequest| {
                            req.into_get_factory_store().map(|item| item.0)
                        },
                    )
                    .await
                }
                IncomingServices::WidevineFactoryStoreProvider(stream) => {
                    let widevine_directory_clone = widevine_directory_clone.clone();
                    handle_request_stream(
                        stream,
                        widevine_directory_clone,
                        |req: WidevineFactoryStoreProviderRequest| {
                            req.into_get_factory_store().map(|item| item.0)
                        },
                    )
                    .await
                }
            }
        }
        .unwrap_or_else(|err| tracing::error!("Failed to handle incoming service: {}", err))
    })
    .await;
    Ok(())
}

#[cfg(test)]
mod tests {
    use {
        super::*, fidl::endpoints::create_endpoints, fuchsia_async as fasync, vfs::pseudo_directory,
    };

    #[fasync::run_singlethreaded(test)]
    async fn test_open_factory_verity() {
        // Bind a vfs to /factory.
        let dir = pseudo_directory! {
            "a" => read_only("a content"),
            "b" => pseudo_directory! {
                "c" => read_only("c content"),
            },
        };
        let (dir_client, dir_server) = create_endpoints();
        let scope = ExecutionScope::new();
        dir.open(
            scope,
            fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::DIRECTORY,
            vfs::path::Path::dot(),
            ServerEnd::new(dir_server.into_channel()),
        );
        let ns = fdio::Namespace::installed().unwrap();
        ns.bind("/factory", dir_client).unwrap();

        let factory_proxy = open_factory_source(FactoryConfig::FactoryVerity).await.unwrap();

        assert_eq!(
            read_file_from_proxy(&factory_proxy, "a").await.unwrap(),
            "a content".as_bytes()
        );
        assert_eq!(
            read_file_from_proxy(&factory_proxy, "b/c").await.unwrap(),
            "c content".as_bytes()
        );
    }
}
