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

#![warn(missing_docs)]

//! `stash` provides key/value storage to components.

use anyhow::{format_err, Context as _, Error};
use fidl::endpoints::ServiceMarker;
use fuchsia_async as fasync;
use fuchsia_component::server::ServiceFs;
use fuchsia_inspect::{self as inspect, health::Reporter};
use fuchsia_syslog::fx_log_err;
use futures::lock::Mutex;
use futures::{StreamExt, TryFutureExt, TryStreamExt};
use std::convert::{TryFrom, TryInto};
use std::env;
use std::path::PathBuf;
use std::process;
use std::sync::Arc;

mod accessor;
mod instance;
mod store;

use fidl_fuchsia_stash::{
    SecureStoreMarker, Store2Marker, StoreMarker, StoreRequest, StoreRequestStream,
};

#[derive(Debug, PartialEq)]
struct StashSettings {
    backing_file: String,
    secure_mode: bool,
    secondary_store: bool,
}

impl Default for StashSettings {
    fn default() -> StashSettings {
        StashSettings {
            backing_file: "/data/stash.store".to_string(),
            secure_mode: false,
            secondary_store: false,
        }
    }
}

impl TryFrom<Vec<String>> for StashSettings {
    type Error = anyhow::Error;
    fn try_from(args: Vec<String>) -> Result<StashSettings, Error> {
        // ignore args[0]
        let mut iter = args.iter().skip(1);
        let mut res = StashSettings::default();
        while let Some(flag) = iter.next() {
            match flag.as_str() {
                "--backing_file" => {
                    if let Some(f) = iter.next() {
                        res.backing_file = f.to_string();
                    } else {
                        return Err(format_err!("Must specify argument to --backing_file"));
                    }
                }
                "--secure" => res.secure_mode = true,
                "--secondary_store" => res.secondary_store = true,
                _ => return Err(format_err!("Unknown flag: {}", flag)),
            }
        }
        if res.secure_mode && res.secondary_store {
            return Err(format_err!("--secure and --secondary_store are mutually exclusive"));
        }
        return Ok(res);
    }
}

fn main() -> Result<(), Error> {
    fuchsia_syslog::init_with_tags(&["stash"])?;

    let r_opts: Result<StashSettings, Error> = env::args().collect::<Vec<String>>().try_into();

    match r_opts {
        Err(msg) => {
            println!("{}", msg);
            print_help();
            process::exit(1);
        }
        Ok(opts) => {
            let mut executor = fasync::Executor::new().context("Error creating executor")?;
            let store_manager =
                Arc::new(Mutex::new(store::StoreManager::new(PathBuf::from(&opts.backing_file))?));

            let name = if opts.secure_mode {
                SecureStoreMarker::NAME
            } else if opts.secondary_store {
                Store2Marker::NAME
            } else {
                StoreMarker::NAME
            };
            inspect::component::inspector().root().record_bool("secure_mode", opts.secure_mode);

            let mut fs = ServiceFs::new();
            inspect::component::health().set_starting_up();
            inspect::component::inspector().serve(&mut fs)?;
            fs.dir("svc").add_fidl_service_at(name, |stream| {
                stash_server(store_manager.clone(), !opts.secure_mode, stream)
            });

            fs.take_and_serve_directory_handle()?;
            inspect::component::health().set_ok();
            executor.run_singlethreaded(fs.collect::<()>());
        }
    }
    Ok(())
}

fn print_help() {
    println!(
        r"stash
garnet service for storing key/value pairs

USAGE:
    stash [FLAGS]

FLAGS:
        --secure                Disables support for handling raw bytes. This flag Should be used
                                when running in critical path of verified boot.
        --secondary_store       Serves fuchsia.store.Store2 instead of fuchsia.store.Store.
                                Specifying both --secondary_store and --secure is an error.
        --backing_file <FILE>   location of backing file for the store"
    )
}

fn stash_server(
    store_manager: Arc<Mutex<store::StoreManager>>,
    enable_bytes: bool,
    mut stream: StoreRequestStream,
) {
    fasync::Task::spawn(
        async move {
            let mut state = instance::Instance {
                client_name: None,
                enable_bytes: enable_bytes,
                store_manager: store_manager,
            };

            while let Some(req) = stream.try_next().await.context("error running stash server")? {
                match req {
                    StoreRequest::Identify { name, control_handle } => {
                        if let Err(e) = state.identify(name.clone()) {
                            control_handle.shutdown();
                            return Err(e);
                        }
                    }
                    StoreRequest::CreateAccessor {
                        read_only,
                        control_handle,
                        accessor_request,
                    } => {
                        if let Err(e) = state.create_accessor(read_only, accessor_request) {
                            control_handle.shutdown();
                            return Err(e);
                        }
                    }
                }
            }
            Ok(())
        }
        .unwrap_or_else(|e: anyhow::Error| fx_log_err!("couldn't run stash service: {:?}", e)),
    )
    .detach();
}

#[cfg(test)]
mod tests {
    use super::*;

    fn args_to_settings(args: &str) -> Result<StashSettings, Error> {
        args.split_whitespace().map(|s| s.to_string()).collect::<Vec<String>>().try_into()
    }

    fn assert_args_to_settings(args: &str, settings: StashSettings) {
        assert_eq!(args_to_settings(args).unwrap(), settings);
    }

    fn assert_args_error(args: &str) {
        assert!(args_to_settings(args).is_err());
    }

    #[test]
    fn test_args() {
        assert_args_to_settings("", StashSettings::default());
        assert_args_to_settings("stash", StashSettings::default());
        assert_args_to_settings(
            "stash --secure",
            StashSettings { secure_mode: true, ..Default::default() },
        );
        assert_args_to_settings(
            "stash --secondary_store",
            StashSettings { secondary_store: true, ..Default::default() },
        );
        assert_args_to_settings(
            "stash --backing_file foo",
            StashSettings { backing_file: "foo".to_string(), ..Default::default() },
        );
        assert_args_to_settings(
            "stash --secure --backing_file foo",
            StashSettings {
                secure_mode: true,
                backing_file: "foo".to_string(),
                ..Default::default()
            },
        );
        assert_args_to_settings(
            "stash --secondary_store --backing_file foo",
            StashSettings {
                secondary_store: true,
                backing_file: "foo".to_string(),
                ..Default::default()
            },
        );
        assert_args_error("stash --secure --secondary_store");
        assert_args_error("stash --backing_file");
        assert_args_error("stash --secure --secondary_store --backing_file");
    }
}
