blob: c0e4e1371238bec5f2f9812bfe66b55a9e277a58 [file] [log] [blame]
// Copyright 2020 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.
mod bound;
mod constants;
mod datatypes;
mod diagnostics;
mod httpsdate;
mod sampler;
use crate::diagnostics::{CobaltDiagnostics, CompositeDiagnostics, InspectDiagnostics};
use crate::httpsdate::{HttpsDateUpdateAlgorithm, RetryStrategy};
use crate::sampler::HttpsSamplerImpl;
use anyhow::{Context, Error};
use fidl_fuchsia_net_interfaces::StateMarker;
use fidl_fuchsia_time_external::{PushSourceRequestStream, Status};
use fuchsia_component::server::ServiceFs;
use fuchsia_zircon as zx;
use futures::{future::join3, FutureExt, StreamExt, TryFutureExt};
use push_source::PushSource;
use tracing::warn;
/// Retry strategy used while polling for time.
const RETRY_STRATEGY: RetryStrategy = RetryStrategy {
min_between_failures: zx::Duration::from_seconds(1),
max_exponent: 3,
tries_per_exponent: 3,
converge_time_between_samples: zx::Duration::from_minutes(2),
maintain_time_between_samples: zx::Duration::from_minutes(20),
};
/// URI used to obtain time samples.
// TODO(fxbug.dev/68621): Allow configuration per product.
const REQUEST_URI: &str = "https://clients3.google.com/generate_204";
#[fuchsia::main(logging_tags=["time"])]
async fn main() -> Result<(), Error> {
let mut fs = ServiceFs::new();
fs.dir("svc").add_fidl_service(|stream: PushSourceRequestStream| stream);
let inspect = InspectDiagnostics::new(fuchsia_inspect::component::inspector().root());
let (cobalt, cobalt_sender_fut) = CobaltDiagnostics::new();
let diagnostics = CompositeDiagnostics::new(inspect, cobalt);
inspect_runtime::serve(fuchsia_inspect::component::inspector(), &mut fs)?;
let sampler = HttpsSamplerImpl::new(REQUEST_URI.parse()?);
let interface_state_service = fuchsia_component::client::connect_to_protocol::<StateMarker>()
.context("failed to connect to fuchsia.net.interfaces/State")?;
let internet_reachable = fidl_fuchsia_net_interfaces_ext::wait_for_reachability(
fidl_fuchsia_net_interfaces_ext::event_stream_from_state(&interface_state_service)
.context("failed to create network interface event stream")?,
)
.map(|r| r.context("reachability status stream error"));
let update_algorithm =
HttpsDateUpdateAlgorithm::new(RETRY_STRATEGY, diagnostics, sampler, internet_reachable);
let push_source = PushSource::new(update_algorithm, Status::Initializing)?;
let update_fut = push_source.poll_updates();
fs.take_and_serve_directory_handle()?;
let service_fut = fs.for_each_concurrent(None, |stream| {
push_source
.handle_requests_for_stream(stream)
.unwrap_or_else(|e| warn!("Error handling PushSource stream: {:?}", e))
});
let (update_res, _, _) = join3(update_fut, service_fut, cobalt_sender_fut).await;
update_res
}