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

//! LoWPAN Network Tunnel Abstraction
use crate::driver::*;
use crate::prelude::*;

use crate::spinel::Subnet;
use anyhow::Context as _;
use anyhow::Error;
use async_trait::async_trait;
use fidl::endpoints::{create_endpoints, create_proxy};
use fidl_fuchsia_hardware_network as fhwnet;
use fidl_fuchsia_net as fnet;
use fidl_fuchsia_net_ext as fnetext;
use fidl_fuchsia_net_stack as fnetstack;
use fidl_fuchsia_net_stack_ext::FidlReturn as _;
use fidl_fuchsia_net_tun as ftun;
use fuchsia_component::client::{connect_channel_to_service, connect_to_service};
use fuchsia_zircon as zx;
use futures::stream::BoxStream;
use parking_lot::Mutex;

const IPV6_MIN_MTU: u32 = 1280;

#[derive(Debug)]
pub struct TunNetworkInterface {
    tun_dev: ftun::DeviceProxy,
    stack: fnetstack::StackProxy,
    stack_sync: Mutex<fnetstack::StackSynchronousProxy>,
    id: u64,
}

impl TunNetworkInterface {
    pub async fn try_new(name: Option<String>) -> Result<TunNetworkInterface, Error> {
        let tun_control = connect_to_service::<ftun::ControlMarker>()?;

        let (tun_dev, req) = create_proxy::<ftun::DeviceMarker>()?;

        tun_control
            .create_device(
                ftun::DeviceConfig {
                    base: Some(ftun::BaseConfig {
                        mtu: Some(IPV6_MIN_MTU),
                        rx_types: Some(vec![
                            fhwnet::FrameType::Ipv6,
                            // TODO(fxbug.dev/64292): Remove this once netstack doesn't require it.
                            fhwnet::FrameType::Ipv4,
                        ]),
                        tx_types: Some(vec![
                            fhwnet::FrameTypeSupport {
                                type_: fhwnet::FrameType::Ipv6,
                                features: fhwnet::FRAME_FEATURES_RAW,
                                supported_flags: fhwnet::TxFlags::empty(),
                            },
                            // TODO(fxbug.dev/64292): Remove this once netstack doesn't require it.
                            fhwnet::FrameTypeSupport {
                                type_: fhwnet::FrameType::Ipv4,
                                features: fhwnet::FRAME_FEATURES_RAW,
                                supported_flags: fhwnet::TxFlags::empty(),
                            },
                        ]),
                        ..ftun::BaseConfig::empty()
                    }),
                    online: Some(true),
                    blocking: Some(true),
                    ..ftun::DeviceConfig::empty()
                },
                req,
            )
            .context("failed to create tun pair")?;

        let (device, device_req) = create_endpoints::<fhwnet::DeviceMarker>()?;

        tun_dev
            .connect_protocols(ftun::Protocols {
                network_device: Some(device_req),
                ..ftun::Protocols::empty()
            })
            .context("connect protocols failed")?;

        let stack = connect_to_service::<fnetstack::StackMarker>()?;

        let id = stack
            .add_interface(
                fnetstack::InterfaceConfig { name, ..fnetstack::InterfaceConfig::empty() },
                &mut fnetstack::DeviceDefinition::Ip(device),
            )
            .await
            .squash_result()
            .context("Unable to add TUN interface to netstack")?;

        let (client, server) = zx::Channel::create()?;
        connect_channel_to_service::<fnetstack::StackMarker>(server)?;
        let stack_sync = Mutex::new(fnetstack::StackSynchronousProxy::new(client));

        Ok(TunNetworkInterface { tun_dev, stack, stack_sync, id })
    }
}

#[async_trait]
impl NetworkInterface for TunNetworkInterface {
    async fn outbound_packet_from_stack(&self) -> Result<Vec<u8>, Error> {
        let frame = self
            .tun_dev
            .read_frame()
            .await
            .context("FIDL error on read_frame")?
            .map_err(fuchsia_zircon::Status::from_raw)
            .context("Error calling read_frame")?;

        Ok(frame.data.ok_or(format_err!("data field was absent"))?)
    }

    async fn inbound_packet_to_stack(&self, packet: &[u8]) -> Result<(), Error> {
        traceln!("Packet to stack: {}", hex::encode(packet));

        Ok(self
            .tun_dev
            .write_frame(ftun::Frame {
                frame_type: Some(fhwnet::FrameType::Ipv6),
                data: Some(packet.to_vec()),
                meta: None,
                ..fidl_fuchsia_net_tun::Frame::empty()
            })
            .await?
            .map_err(fuchsia_zircon::Status::from_raw)?)
    }

    async fn set_online(&self, online: bool) -> Result<(), Error> {
        fx_log_info!("Interface online: {:?}", online);
        if online {
            self.stack.enable_interface(self.id).await.squash_result()?;

            // Get a list of all of the addresses that were automatically
            // added to the interface (like the link local address).
            let fnetstack::InterfaceInfo {
                properties: fnetstack::InterfaceProperties { addresses, .. },
                ..
            } = self.stack.get_interface_info(self.id).await.squash_result()?;

            // Now we remove all of those addresses so that the NCP has a
            // clean slate to start from.
            for mut subnet in addresses {
                fx_log_info!("Removing automatically added address: {:?}", &subnet);
                self.stack.del_interface_address(self.id, &mut subnet).await.squash_result()?;
            }
        } else {
            self.stack.disable_interface(self.id).await.squash_result()?;
        }
        Ok(())
    }

    fn add_address(&self, addr: &Subnet) -> Result<(), Error> {
        fx_log_info!("Address Added: {:?}", addr);
        let mut addr = fnet::Subnet {
            addr: fnetext::IpAddress(addr.addr.into()).into(),
            prefix_len: addr.prefix_len,
        };
        self.stack_sync
            .lock()
            .add_interface_address(self.id, &mut addr, zx::Time::INFINITE)
            .squash_result()?;
        Ok(())
    }

    fn remove_address(&self, addr: &Subnet) -> Result<(), Error> {
        fx_log_info!("Address Removed: {:?}", addr);
        let mut addr = fnet::Subnet {
            addr: fnetext::IpAddress(addr.addr.into()).into(),
            prefix_len: addr.prefix_len,
        };
        self.stack_sync
            .lock()
            .del_interface_address(self.id, &mut addr, zx::Time::INFINITE)
            .squash_result()?;
        Ok(())
    }

    fn add_on_link_route(&self, addr: &Subnet) -> Result<(), Error> {
        fx_log_info!("On Mesh Route Added: {:?} (IGNORED)", addr);
        Ok(())
    }

    fn remove_on_link_route(&self, addr: &Subnet) -> Result<(), Error> {
        fx_log_info!("On Mesh Route Removed: {:?} (IGNORED)", addr);
        Ok(())
    }

    fn take_event_stream(&self) -> BoxStream<'_, Result<NetworkInterfaceEvent, Error>> {
        let enabled_stream = futures::stream::try_unfold((), move |()| async move {
            loop {
                if let ftun::InternalState { has_session: Some(has_session), .. } =
                    self.tun_dev.watch_state().await?
                {
                    break Ok(Some((
                        NetworkInterfaceEvent::InterfaceEnabledChanged(has_session),
                        (),
                    )));
                }
            }
        });

        enabled_stream.boxed()
    }
}
