// 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::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)),
    );
}

#[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");
    }
}
