blob: a53038bc0fc29a04bea3aa3f7c5a420d4af08b6e [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_time_external::{PushSourceRequestStream, Status};
use fuchsia_async as fasync;
use fuchsia_component::server::ServiceFs;
use fuchsia_zircon as zx;
use futures::{future::join3, StreamExt, TryFutureExt};
use log::warn;
use push_source::PushSource;
/// 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/56875): Decide on correct endpoint and move to config data.
const REQUEST_URI: &str = "https://clients1.google.com/generate_204";
#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
fuchsia_syslog::init_with_tags(&["time"]).context("initializing logging")?;
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);
fuchsia_inspect::component::inspector().serve(&mut fs)?;
let sampler = HttpsSamplerImpl::new(REQUEST_URI.parse()?);
let update_algorithm = HttpsDateUpdateAlgorithm::new(RETRY_STRATEGY, diagnostics, sampler);
let push_source = PushSource::new(update_algorithm, Status::Ok)?;
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
}