| // 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. |
| |
| #![feature(async_await, await_macro)] |
| #![deny(warnings)] |
| |
| use { |
| failure::{Error, ResultExt}, |
| fidl_fuchsia_pkg::PackageCacheMarker, |
| fuchsia_async as fasync, |
| fuchsia_component::client::connect_to_service, |
| fuchsia_component::server::ServiceFs, |
| fuchsia_inspect as inspect, |
| fuchsia_syslog::{self, fx_log_err, fx_log_info}, |
| futures::{StreamExt, TryFutureExt}, |
| parking_lot::RwLock, |
| std::io, |
| std::sync::Arc, |
| }; |
| |
| mod amber; |
| mod amber_connector; |
| mod repository_manager; |
| mod repository_service; |
| mod resolver_service; |
| mod rewrite_manager; |
| mod rewrite_service; |
| |
| #[cfg(test)] |
| mod test_util; |
| |
| use crate::amber_connector::AmberConnector; |
| use crate::repository_manager::{RepositoryManager, RepositoryManagerBuilder}; |
| use crate::repository_service::RepositoryService; |
| use crate::rewrite_manager::{RewriteManager, RewriteManagerBuilder}; |
| use crate::rewrite_service::RewriteService; |
| |
| const SERVER_THREADS: usize = 2; |
| |
| const STATIC_REPO_DIR: &str = "/config/data/repositories"; |
| const DYNAMIC_REPO_PATH: &str = "/data/repositories.json"; |
| |
| const STATIC_RULES_PATH: &str = "/config/data/rewrites.json"; |
| const DYNAMIC_RULES_PATH: &str = "/data/rewrites.json"; |
| |
| fn main() -> Result<(), Error> { |
| fuchsia_syslog::init_with_tags(&["pkg_resolver"]).expect("can't init logger"); |
| fx_log_info!("starting package resolver"); |
| |
| let mut executor = fasync::Executor::new().context("error creating executor")?; |
| |
| let cache = |
| connect_to_service::<PackageCacheMarker>().context("error connecting to package cache")?; |
| |
| let inspector = fuchsia_inspect::Inspector::new(); |
| let rewrite_inspect_node = inspector.root().create_child("rewrite_manager"); |
| |
| let amber_connector = AmberConnector::new(); |
| |
| let repo_manager = Arc::new(RwLock::new(load_repo_manager(amber_connector.clone()))); |
| let rewrite_manager = Arc::new(RwLock::new(load_rewrite_manager(rewrite_inspect_node))); |
| |
| let resolver_cb = { |
| // Capture a clone of repo and rewrite manager's Arc so the new client callback has a copy |
| // from which to make new clones. |
| let repo_manager = repo_manager.clone(); |
| let rewrite_manager = rewrite_manager.clone(); |
| move |stream| { |
| fasync::spawn( |
| resolver_service::run_resolver_service( |
| rewrite_manager.clone(), |
| repo_manager.clone(), |
| cache.clone(), |
| stream, |
| ) |
| .unwrap_or_else(|e| fx_log_err!("failed to spawn {:?}", e)), |
| ) |
| } |
| }; |
| |
| let repo_cb = move |stream| { |
| let repo_manager = repo_manager.clone(); |
| |
| fasync::spawn( |
| async move { |
| let mut repo_service = RepositoryService::new(repo_manager); |
| await!(repo_service.run(stream)) |
| } |
| .unwrap_or_else(|e| fx_log_err!("error encountered: {:?}", e)), |
| ) |
| }; |
| |
| let rewrite_cb = move |stream| { |
| let mut rewrite_service = |
| RewriteService::new(rewrite_manager.clone(), amber_connector.clone()); |
| |
| fasync::spawn( |
| async move { await!(rewrite_service.handle_client(stream)) } |
| .unwrap_or_else(|e| fx_log_err!("while handling rewrite client {:?}", e)), |
| ) |
| }; |
| |
| let mut fs = ServiceFs::new(); |
| fs.dir("public") |
| .add_fidl_service(resolver_cb) |
| .add_fidl_service(repo_cb) |
| .add_fidl_service(rewrite_cb); |
| |
| inspector.export(&mut fs); |
| |
| fs.take_and_serve_directory_handle()?; |
| |
| let () = executor.run(fs.collect(), SERVER_THREADS); |
| |
| Ok(()) |
| } |
| |
| fn load_repo_manager(amber_connector: AmberConnector) -> RepositoryManager<AmberConnector> { |
| // report any errors we saw, but don't error out because otherwise we won't be able |
| // to update the system. |
| RepositoryManagerBuilder::new(DYNAMIC_REPO_PATH, amber_connector) |
| .unwrap_or_else(|(builder, err)| { |
| fx_log_err!("error loading dynamic repo config: {}", err); |
| builder |
| }) |
| .load_static_configs_dir(STATIC_REPO_DIR) |
| .unwrap_or_else(|(builder, errs)| { |
| for err in errs { |
| fx_log_err!("error loading static repo config: {}", err); |
| } |
| builder |
| }) |
| .build() |
| } |
| |
| fn load_rewrite_manager(node: inspect::Node) -> RewriteManager { |
| RewriteManagerBuilder::new(node, DYNAMIC_RULES_PATH) |
| .unwrap_or_else(|(builder, err)| { |
| if err.kind() != io::ErrorKind::NotFound { |
| fx_log_err!( |
| "unable to load dynamic rewrite rules from disk, using defaults: {}", |
| err |
| ); |
| } |
| builder |
| }) |
| .static_rules_path(STATIC_RULES_PATH) |
| .unwrap_or_else(|(builder, err)| { |
| if err.kind() != io::ErrorKind::NotFound { |
| fx_log_err!("unable to load static rewrite rules from disk: {}", err); |
| } |
| builder |
| }) |
| .build() |
| } |