blob: 87529d137065cffacb70a479902779372bde3f52 [file] [log] [blame]
// 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.
use {
anyhow::{format_err, Error},
fidl_fuchsia_factory::{
AlphaFactoryStoreProviderRequest, AlphaFactoryStoreProviderRequestStream,
CastCredentialsFactoryStoreProviderRequest,
CastCredentialsFactoryStoreProviderRequestStream, MiscFactoryStoreProviderRequest,
MiscFactoryStoreProviderRequestStream, PlayReadyFactoryStoreProviderRequest,
PlayReadyFactoryStoreProviderRequestStream, WeaveFactoryStoreProviderRequest,
WeaveFactoryStoreProviderRequestStream, WidevineFactoryStoreProviderRequest,
WidevineFactoryStoreProviderRequestStream,
},
fidl_fuchsia_io as fio,
fuchsia_component::server::ServiceFs,
futures::{lock::Mutex, prelude::*},
serde_json::from_reader,
std::{collections::HashMap, fs::File, str::FromStr, sync::Arc},
structopt::StructOpt,
vfs::{
directory::entry_container::Directory, execution_scope::ExecutionScope,
file::vmo::read_only, tree_builder::TreeBuilder,
},
};
type LockedDirectoryProxy = Arc<Mutex<fio::DirectoryProxy>>;
enum IncomingServices {
AlphaFactoryStoreProvider(AlphaFactoryStoreProviderRequestStream),
CastCredentialsFactoryStoreProvider(CastCredentialsFactoryStoreProviderRequestStream),
MiscFactoryStoreProvider(MiscFactoryStoreProviderRequestStream),
PlayReadyFactoryStoreProvider(PlayReadyFactoryStoreProviderRequestStream),
WeaveFactoryStoreProvider(WeaveFactoryStoreProviderRequestStream),
WidevineFactoryStoreProvider(WidevineFactoryStoreProviderRequestStream),
}
fn start_test_dir(config_path: &str) -> Result<fio::DirectoryProxy, Error> {
let files: HashMap<String, String> = match File::open(&config_path) {
Ok(file) => from_reader(file)?,
Err(err) => {
tracing::warn!(
"publishing empty directory for {} due to error: {:?}",
&config_path,
err
);
HashMap::new()
}
};
tracing::info!("Files from {}: {:?}", &config_path, files);
let mut tree = TreeBuilder::empty_dir();
for (name, contents) in files.into_iter() {
tree.add_entry(&name.split("/").collect::<Vec<&str>>(), read_only(contents)).unwrap();
}
let test_dir = tree.build();
let (test_dir_proxy, test_dir_service) =
fidl::endpoints::create_proxy::<fio::DirectoryMarker>()?;
test_dir.open(
ExecutionScope::new(),
fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::DIRECTORY,
vfs::path::Path::dot(),
test_dir_service.into_channel().into(),
);
Ok(test_dir_proxy)
}
async fn run_server(req: IncomingServices, dir_mtx: LockedDirectoryProxy) -> Result<(), Error> {
match req {
IncomingServices::AlphaFactoryStoreProvider(mut stream) => {
while let Some(request) = stream.try_next().await? {
let AlphaFactoryStoreProviderRequest::GetFactoryStore { dir, control_handle: _ } =
request;
dir_mtx
.lock()
.await
.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into())?;
}
}
IncomingServices::CastCredentialsFactoryStoreProvider(mut stream) => {
while let Some(request) = stream.try_next().await? {
let CastCredentialsFactoryStoreProviderRequest::GetFactoryStore {
dir,
control_handle: _,
} = request;
dir_mtx
.lock()
.await
.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into())?;
}
}
IncomingServices::MiscFactoryStoreProvider(mut stream) => {
while let Some(request) = stream.try_next().await? {
let MiscFactoryStoreProviderRequest::GetFactoryStore { dir, control_handle: _ } =
request;
dir_mtx
.lock()
.await
.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into())?;
}
}
IncomingServices::PlayReadyFactoryStoreProvider(mut stream) => {
while let Some(request) = stream.try_next().await? {
let PlayReadyFactoryStoreProviderRequest::GetFactoryStore {
dir,
control_handle: _,
} = request;
dir_mtx
.lock()
.await
.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into())?;
}
}
IncomingServices::WeaveFactoryStoreProvider(mut stream) => {
while let Some(request) = stream.try_next().await? {
let WeaveFactoryStoreProviderRequest::GetFactoryStore { dir, control_handle: _ } =
request;
dir_mtx
.lock()
.await
.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into())?;
}
}
IncomingServices::WidevineFactoryStoreProvider(mut stream) => {
while let Some(request) = stream.try_next().await? {
let WidevineFactoryStoreProviderRequest::GetFactoryStore { dir, control_handle: _ } =
request;
dir_mtx
.lock()
.await
.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into())?;
}
}
}
Ok(())
}
#[derive(Debug, StructOpt)]
enum Provider {
Alpha,
Cast,
Misc,
Playready,
Weave,
Widevine,
}
impl FromStr for Provider {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let formatted_str = s.trim().to_lowercase();
match formatted_str.as_ref() {
"alpha" => Ok(Provider::Alpha),
"cast" => Ok(Provider::Cast),
"misc" => Ok(Provider::Misc),
"playready" => Ok(Provider::Playready),
"weave" => Ok(Provider::Weave),
"widevine" => Ok(Provider::Widevine),
_ => Err(format_err!("Could not find '{}' provider", formatted_str)),
}
}
}
#[derive(Debug, StructOpt)]
struct Flags {
/// The factory store provider to fake.
#[structopt(short, long)]
provider: Provider,
/// The path to the config file for the provider.
#[structopt(short, long)]
config: String,
}
#[fuchsia::main(logging_tags = ["fake_factory_store_providers"])]
async fn main() -> Result<(), Error> {
let flags = Flags::from_args();
let dir = Arc::new(Mutex::new(start_test_dir(&flags.config)?));
let mut fs = ServiceFs::new_local();
let mut fs_dir = fs.dir("svc");
match flags.provider {
Provider::Alpha => fs_dir.add_fidl_service(IncomingServices::AlphaFactoryStoreProvider),
Provider::Cast => {
fs_dir.add_fidl_service(IncomingServices::CastCredentialsFactoryStoreProvider)
}
Provider::Misc => fs_dir.add_fidl_service(IncomingServices::MiscFactoryStoreProvider),
Provider::Playready => {
fs_dir.add_fidl_service(IncomingServices::PlayReadyFactoryStoreProvider)
}
Provider::Weave => fs_dir.add_fidl_service(IncomingServices::WeaveFactoryStoreProvider),
Provider::Widevine => {
fs_dir.add_fidl_service(IncomingServices::WidevineFactoryStoreProvider)
}
};
fs.take_and_serve_directory_handle()?;
fs.for_each_concurrent(10, |req| {
run_server(req, dir.clone()).unwrap_or_else(|e| tracing::error!("{:?}", e))
})
.await;
Ok(())
}