blob: a558860220323fe3c968ef972042a08edd0f18a8 [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.
#![allow(clippy::let_unit_value)]
#![allow(clippy::type_complexity)]
mod apply;
mod channel;
mod channel_handler;
mod check;
mod connect;
mod errors;
mod rate_limiter;
mod update_manager;
mod update_monitor;
mod update_service;
use {
crate::{
channel_handler::ChannelHandler,
update_service::{RealUpdateManager, UpdateService},
},
anyhow::{anyhow, Context as _, Error},
fidl_fuchsia_update_channel::ProviderRequestStream,
fidl_fuchsia_update_channelcontrol::ChannelControlRequestStream,
fuchsia_component::server::ServiceFs,
fuchsia_inspect as finspect,
futures::{prelude::*, stream::FuturesUnordered},
std::sync::Arc,
tracing::error,
};
const MAX_CONCURRENT_CONNECTIONS: usize = 100;
const DEFAULT_UPDATE_PACKAGE_URL: &str = "fuchsia-pkg://fuchsia.com/update";
#[fuchsia::main(threads = 1, logging_tags = ["system-update-checker"])]
async fn main() -> Result<(), Error> {
main_inner().await.map_err(|err| {
// anyhow with alternate formatting prints the Display impl of each error in the chain.
let err = anyhow!(err);
error!("error running system-update-checker: {:#}", err);
err
})
}
async fn main_inner() -> Result<(), Error> {
let inspector = finspect::Inspector::default();
let _inspect_server_task =
inspect_runtime::publish(&inspector, inspect_runtime::PublishOptions::default());
let target_channel_manager =
channel::TargetChannelManager::new(connect::ServiceConnector, "/config/data");
if let Err(e) = target_channel_manager.update().await {
error!("while updating the target channel: {:#}", anyhow!(e));
}
let target_channel_manager = Arc::new(target_channel_manager);
let futures = FuturesUnordered::new();
let current_channel_manager =
channel::build_current_channel_manager(connect::ServiceConnector).await?;
let current_channel_manager = Arc::new(current_channel_manager);
let (update_manager, update_manager_fut) = RealUpdateManager::new(
Arc::clone(&target_channel_manager),
inspector.root().create_child("update-manager"),
)
.await
.start();
futures.push(update_manager_fut.boxed());
let mut fs = ServiceFs::new();
let update_manager_clone = update_manager.clone();
let channel_handler =
Arc::new(ChannelHandler::new(current_channel_manager, target_channel_manager));
let channel_handler_clone = Arc::clone(&channel_handler);
let channel_handler_provider_clone = Arc::clone(&channel_handler);
fs.dir("svc")
.add_fidl_service(move |stream| {
IncomingServices::Manager(stream, UpdateService::new(update_manager_clone.clone()))
})
.add_fidl_service(move |stream| {
IncomingServices::Provider(stream, Arc::clone(&channel_handler_provider_clone))
})
.add_fidl_service(move |stream| {
IncomingServices::ChannelControl(stream, Arc::clone(&channel_handler_clone))
});
fs.take_and_serve_directory_handle().context("ServiceFs::take_and_serve_directory_handle")?;
futures.push(
fs.for_each_concurrent(MAX_CONCURRENT_CONNECTIONS, |incoming_service| {
handle_incoming_service(incoming_service)
.unwrap_or_else(|e| error!("error handling client connection: {:#}", anyhow!(e)))
})
.boxed(),
);
futures.collect::<()>().await;
Ok(())
}
enum IncomingServices {
Manager(fidl_fuchsia_update::ManagerRequestStream, UpdateService),
Provider(ProviderRequestStream, Arc<ChannelHandler>),
ChannelControl(ChannelControlRequestStream, Arc<ChannelHandler>),
}
async fn handle_incoming_service(incoming_service: IncomingServices) -> Result<(), Error> {
match incoming_service {
IncomingServices::Manager(request_stream, mut update_service) => {
update_service.handle_request_stream(request_stream).await
}
IncomingServices::Provider(request_stream, handler) => {
handler.handle_provider_request_stream(request_stream).await
}
IncomingServices::ChannelControl(request_stream, handler) => {
handler.handle_control_request_stream(request_stream).await
}
}
}