// 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.

//! Handles diagnostics requests

use {
    crate::router::Router,
    anyhow::{format_err, Context as _, Error},
    fidl::{endpoints::ClientEnd, prelude::*, AsyncChannel, Channel},
    fidl_fuchsia_overnet::{ServiceProviderRequest, ServiceProviderRequestStream},
    fidl_fuchsia_overnet_protocol::{
        DiagnosticMarker, DiagnosticRequest, DiagnosticRequestStream, ProbeResult, ProbeSelector,
    },
    futures::prelude::*,
    std::sync::Weak,
};

// Helper: if a bit is set in a probe selector, return Some(make()), else return None
async fn if_probe_has_bit<R>(
    probe: ProbeSelector,
    bit: ProbeSelector,
    make: impl Future<Output = R>,
) -> Option<R> {
    if probe & bit == bit {
        Some(make.await)
    } else {
        None
    }
}

pub async fn run_diagostic_service_request_handler(router: &Weak<Router>) -> Result<(), Error> {
    let (s, p) = Channel::create().context("failed to create zx channel")?;
    let chan = AsyncChannel::from_channel(s).context("failed to make async channel")?;
    Weak::upgrade(router)
        .ok_or_else(|| format_err!("router gone"))?
        .register_service(DiagnosticMarker::PROTOCOL_NAME.to_string(), ClientEnd::new(p))
        .await?;
    handle_diagnostic_service_requests(router, ServiceProviderRequestStream::from_channel(chan))
        .await
}

async fn handle_diagnostic_service_requests(
    router: &Weak<Router>,
    stream: ServiceProviderRequestStream,
) -> Result<(), Error> {
    stream
        .map_err(Into::<Error>::into)
        .try_for_each_concurrent(None, |request| async move {
            match request {
                ServiceProviderRequest::ConnectToService { chan, info: _, control_handle: _ } => {
                    let stream = DiagnosticRequestStream::from_channel(
                        fidl::AsyncChannel::from_channel(chan)?,
                    );
                    handle_diagnostic_requests(router, stream).await?;
                }
            }
            Ok(())
        })
        .await?;
    Ok(())
}

fn hostname() -> Option<String> {
    let mut buf = [0u8; 256];
    let r = unsafe { libc::gethostname(buf.as_mut_ptr() as *mut std::os::raw::c_char, buf.len()) };
    if r != 0 {
        return None;
    }

    buf.iter()
        .position(|&c| c == 0)
        .and_then(|p| std::ffi::CString::new(&buf[..p]).ok())
        .and_then(|s| s.into_string().ok())
}

fn node_description(
    implementation: fidl_fuchsia_overnet_protocol::Implementation,
) -> fidl_fuchsia_overnet_protocol::NodeDescription {
    fidl_fuchsia_overnet_protocol::NodeDescription {
        #[cfg(target_os = "fuchsia")]
        operating_system: Some(fidl_fuchsia_overnet_protocol::OperatingSystem::Fuchsia),
        #[cfg(target_os = "linux")]
        operating_system: Some(fidl_fuchsia_overnet_protocol::OperatingSystem::Linux),
        #[cfg(target_os = "macos")]
        operating_system: Some(fidl_fuchsia_overnet_protocol::OperatingSystem::Mac),
        implementation: Some(implementation),
        binary: std::env::current_exe()
            .ok()
            .and_then(|p| p.file_name().map(|s| s.to_owned()))
            .and_then(|p| p.to_str().map(str::to_string)),
        hostname: hostname(),
        ..fidl_fuchsia_overnet_protocol::NodeDescription::EMPTY
    }
}

async fn handle_diagnostic_requests(
    router: &Weak<Router>,
    stream: DiagnosticRequestStream,
) -> Result<(), Error> {
    let get_router = move || Weak::upgrade(router).ok_or_else(|| format_err!("router gone"));
    stream
        .map_err(Into::into)
        .try_for_each_concurrent(None, |req| async move {
            match req {
                DiagnosticRequest::Probe { selector, responder } => {
                    let res = responder.send(ProbeResult {
                        node_description: if_probe_has_bit(
                            selector,
                            ProbeSelector::NODE_DESCRIPTION,
                            futures::future::ready(node_description(
                                get_router()?.implementation(),
                            )),
                        )
                        .await,
                        links: if_probe_has_bit(
                            selector,
                            ProbeSelector::LINKS,
                            get_router()?.link_diagnostics(),
                        )
                        .await,
                        peer_connections: if_probe_has_bit(
                            selector,
                            ProbeSelector::PEER_CONNECTIONS,
                            get_router()?.peer_diagnostics(),
                        )
                        .await,
                        connecting_link_count: if_probe_has_bit(
                            selector,
                            ProbeSelector::CONNECTING_LINK_COUNT,
                            futures::future::ready(get_router()?.connecting_link_count()),
                        )
                        .await,
                        ..ProbeResult::EMPTY
                    });
                    if let Err(e) = res {
                        log::warn!("Failed handling probe: {:?}", e);
                    }
                }
            }
            Ok(())
        })
        .await
}
