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

use crate::protocol::{FidlCompatible, FromFidlExt, IntoFidlExt};
use anyhow::Context;
use serde::{Deserialize, Serialize};
use serde_json;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::fs;
use std::io;
use std::net::Ipv4Addr;
use thiserror::Error;

/// Attempts to load a `ServerParameters` from the json file at the provided path.
pub fn load_server_params_from_file(path: &str) -> Result<ServerParameters, ConfigError> {
    let json = fs::read_to_string(path)?;
    let config = serde_json::from_str(&json)?;
    Ok(config)
}

/// A collection of the basic configuration parameters needed by the server.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ServerParameters {
    /// The IPv4 addresses of the host running the server.
    pub server_ips: Vec<Ipv4Addr>,
    /// The duration for which leases should be assigned to clients
    pub lease_length: LeaseLength,
    /// The IPv4 addresses which the server is responsible for managing and leasing to
    /// clients.
    pub managed_addrs: ManagedAddresses,
    /// A list of MAC addresses which are permitted to request a lease. If empty, any MAC address
    /// may request a lease.
    pub permitted_macs: PermittedMacs,
    /// A collection of static address assignments. Any client whose MAC address has a static
    /// assignment will be offered the assigned IP address.
    pub static_assignments: StaticAssignments,
    /// Enables server behavior where the server ARPs an IP address prior to issuing
    /// it in a lease.
    pub arp_probe: bool,
    /// The interface names to which the server's UDP sockets are bound. If
    /// this vector is empty, the server will not bind to a specific interface
    /// and will process incoming DHCP messages regardless of the interface on
    /// which they arrive.
    pub bound_device_names: Vec<String>,
}

/// Parameters controlling lease duration allocation. Per,
/// https://tools.ietf.org/html/rfc2131#section-3.3, times are represented as relative times.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct LeaseLength {
    /// The default lease duration assigned by the server.
    pub default_seconds: u32,
    /// The maximum allowable lease duration which a client can request.
    pub max_seconds: u32,
}

impl FidlCompatible<fidl_fuchsia_net_dhcp::LeaseLength> for LeaseLength {
    type FromError = anyhow::Error;
    type IntoError = never::Never;

    fn try_from_fidl(fidl: fidl_fuchsia_net_dhcp::LeaseLength) -> Result<Self, Self::FromError> {
        if let fidl_fuchsia_net_dhcp::LeaseLength { default: Some(default_seconds), max } = fidl {
            Ok(LeaseLength {
                default_seconds,
                // Per fuchsia.net.dhcp, if omitted, max defaults to the value of default.
                max_seconds: max.unwrap_or(default_seconds),
            })
        } else {
            Err(anyhow::format_err!(
                "fuchsia.net.dhcp.LeaseLength missing required field: {:?}",
                fidl
            ))
        }
    }

    fn try_into_fidl(self) -> Result<fidl_fuchsia_net_dhcp::LeaseLength, Self::IntoError> {
        let LeaseLength { default_seconds, max_seconds } = self;
        Ok(fidl_fuchsia_net_dhcp::LeaseLength {
            default: Some(default_seconds),
            max: Some(max_seconds),
        })
    }
}

/// The IP addresses which the server will manage and lease to clients.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct ManagedAddresses {
    /// The network id of the subnet for which the server will manage addresses.
    pub network_id: Ipv4Addr,
    /// The broadcast id of the subnet for which the server will manage addresses.
    pub broadcast: Ipv4Addr,
    /// The subnet mask of the subnet for which the server will manage addresses.
    pub mask: SubnetMask,
    /// The inclusive starting address of the range of managed addresses.
    pub pool_range_start: Ipv4Addr,
    /// The exclusive stopping address of the range of managed addresses.
    pub pool_range_stop: Ipv4Addr,
}

impl ManagedAddresses {
    /// Returns an iterator of the `Ipv4Addr`s from `pool_range_start`, inclusive, to
    /// `pool_range_stop`, exclusive.
    pub fn pool_range(&self) -> impl Iterator<Item = Ipv4Addr> {
        let start: u32 = self.pool_range_start.into();
        let stop: u32 = self.pool_range_stop.into();
        (start..stop).map(|addr| addr.into())
    }
}

impl FidlCompatible<fidl_fuchsia_net_dhcp::AddressPool> for ManagedAddresses {
    type FromError = anyhow::Error;
    type IntoError = never::Never;

    fn try_from_fidl(fidl: fidl_fuchsia_net_dhcp::AddressPool) -> Result<Self, Self::FromError> {
        if let fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(network_id),
            broadcast: Some(broadcast),
            mask: Some(mask),
            pool_range_start: Some(pool_range_start),
            pool_range_stop: Some(pool_range_stop),
        } = fidl
        {
            let mask = SubnetMask::try_from_fidl(mask)
                .context("fuchsia.net.dhcp.AddressPool contained invalid mask")?;
            let network_id = Ipv4Addr::from_fidl(network_id);
            let broadcast = Ipv4Addr::from_fidl(broadcast);
            let pool_range_start = Ipv4Addr::from_fidl(pool_range_start);
            let pool_range_stop = Ipv4Addr::from_fidl(pool_range_stop);
            if mask.apply_to(network_id) != network_id {
                Err(anyhow::format_err!(
                    "fuchsia.net.dhcp.AddressPool contained wrong mask (/{}) for network_id ({})",
                    mask.ones(),
                    network_id
                ))
            } else if mask.apply_to(broadcast) != network_id {
                Err(anyhow::format_err!("fuchsia.net.dhcp.AddressPool contained broadcast ({}) outside of network_id ({})", broadcast, network_id))
            } else if mask.apply_to(pool_range_start) != network_id {
                Err(anyhow::format_err!("fuchsia.net.dhcp.AddressPool contained pool_range_start ({}) outside of network_id ({})", pool_range_start, network_id))
            } else if mask.apply_to(pool_range_stop) != network_id {
                Err(anyhow::format_err!("fuchsia.net.dhcp.AddressPool contained pool_range_stop ({}) outside of network_id ({})", pool_range_stop, network_id))
            } else if pool_range_start > pool_range_stop {
                Err(anyhow::format_err!("fuchsia.net.dhpc.AddressPool contained pool_range_start ({}) > pool_range_stop ({})", pool_range_start, pool_range_stop))
            } else {
                Ok(Self { network_id, broadcast, mask, pool_range_start, pool_range_stop })
            }
        } else {
            Err(anyhow::format_err!("fuchsia.net.dhcp.AddressPool missing fields: {:?}", fidl))
        }
    }

    fn try_into_fidl(self) -> Result<fidl_fuchsia_net_dhcp::AddressPool, Self::IntoError> {
        let ManagedAddresses { network_id, broadcast, mask, pool_range_start, pool_range_stop } =
            self;
        Ok(fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(network_id.into_fidl()),
            broadcast: Some(broadcast.into_fidl()),
            mask: Some(mask.into_fidl()),
            pool_range_start: Some(pool_range_start.into_fidl()),
            pool_range_stop: Some(pool_range_stop.into_fidl()),
        })
    }
}

/// A list of MAC addresses which are permitted to request a lease.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PermittedMacs(pub Vec<fidl_fuchsia_net_ext::MacAddress>);

impl FidlCompatible<Vec<fidl_fuchsia_net::MacAddress>> for PermittedMacs {
    type FromError = never::Never;
    type IntoError = never::Never;

    fn try_from_fidl(fidl: Vec<fidl_fuchsia_net::MacAddress>) -> Result<Self, Self::FromError> {
        Ok(PermittedMacs(fidl.into_iter().map(|mac| mac.into()).collect()))
    }

    fn try_into_fidl(self) -> Result<Vec<fidl_fuchsia_net::MacAddress>, Self::IntoError> {
        Ok(self.0.into_iter().map(|mac| mac.into()).collect())
    }
}

/// A collection of static address assignments. Any client whose MAC address has a static
/// assignment will be offered the assigned IP address.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct StaticAssignments(pub HashMap<fidl_fuchsia_net_ext::MacAddress, Ipv4Addr>);

impl FidlCompatible<Vec<fidl_fuchsia_net_dhcp::StaticAssignment>> for StaticAssignments {
    type FromError = anyhow::Error;
    type IntoError = never::Never;

    fn try_from_fidl(
        fidl: Vec<fidl_fuchsia_net_dhcp::StaticAssignment>,
    ) -> Result<Self, Self::FromError> {
        match fidl.into_iter().try_fold(HashMap::new(), |mut acc, assignment| {
            if let (Some(host), Some(assigned_addr)) = (assignment.host, assignment.assigned_addr) {
                let mac = fidl_fuchsia_net_ext::MacAddress::from(host);
                match acc.insert(mac, Ipv4Addr::from_fidl(assigned_addr)) {
                    Some(_ip) => Err(anyhow::format_err!(
                        "fuchsia.net.dhcp.StaticAssignment contained multiple entries for {}",
                        mac
                    )),
                    None => Ok(acc),
                }
            } else {
                Err(anyhow::format_err!(
                    "fuchsia.net.dhcp.StaticAssignment contained entry with missing fields: {:?}",
                    assignment
                ))
            }
        }) {
            Ok(static_assignments) => Ok(StaticAssignments(static_assignments)),
            Err(e) => Err(e),
        }
    }

    fn try_into_fidl(
        self,
    ) -> Result<Vec<fidl_fuchsia_net_dhcp::StaticAssignment>, Self::IntoError> {
        Ok(self
            .0
            .into_iter()
            .map(|(host, assigned_addr)| fidl_fuchsia_net_dhcp::StaticAssignment {
                host: Some(host.into()),
                assigned_addr: Some(assigned_addr.into_fidl()),
            })
            .collect())
    }
}

/// A wrapper around the error types which can be returned when loading a
/// `ServerConfig` from file with `load_server_config_from_file()`.
#[derive(Debug, Error)]
pub enum ConfigError {
    #[error("io error: {}", _0)]
    IoError(io::Error),
    #[error("json deserialization error: {}", _0)]
    JsonError(serde_json::Error),
}

impl From<io::Error> for ConfigError {
    fn from(e: io::Error) -> Self {
        ConfigError::IoError(e)
    }
}

impl From<serde_json::Error> for ConfigError {
    fn from(e: serde_json::Error) -> Self {
        ConfigError::JsonError(e)
    }
}

const U32_BITS: u8 = (std::mem::size_of::<u32>() * 8) as u8;

/// A bitmask which represents the boundary between the Network part and Host part of an IPv4
/// address.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct SubnetMask {
    /// The set high-order bits of the mask.
    ones: u8,
}

impl SubnetMask {
    /// Returns a byte-array representation of the `SubnetMask` in Network (Big-Endian) byte-order.
    pub fn octets(&self) -> [u8; 4] {
        self.to_u32().to_be_bytes()
    }

    fn to_u32(&self) -> u32 {
        let n = u32::max_value();
        // overflowing_shl() will not shift arguments >= the bit length of the calling value, so we
        // must special case a mask with 0 ones.
        if self.ones == 0 {
            0
        } else {
            // overflowing_shl() must be used here for panic safety.
            let (n, _overflow) = n.overflowing_shl((U32_BITS - self.ones) as u32);
            n
        }
    }

    /// Returns the count of the set high-order bits of the `SubnetMask`.
    pub fn ones(&self) -> u8 {
        self.ones
    }

    /// Returns the Network address resulting from masking `target` with the `SubnetMask`.
    pub fn apply_to(&self, target: Ipv4Addr) -> Ipv4Addr {
        let subnet_mask_bits = self.to_u32();
        let target_bits = u32::from_be_bytes(target.octets());
        Ipv4Addr::from(target_bits & subnet_mask_bits)
    }
}

impl TryFrom<u8> for SubnetMask {
    type Error = anyhow::Error;

    /// Returns a `Ok(SubnetMask)` with the `ones` high-order bits set if `ones` < 32, else `Err`.
    fn try_from(ones: u8) -> Result<Self, Self::Error> {
        if ones >= U32_BITS {
            Err(anyhow::format_err!(
                "failed precondition: argument must be < 32 (bit length of an IPv4 address)",
            ))
        } else {
            Ok(SubnetMask { ones })
        }
    }
}

impl TryFrom<Ipv4Addr> for SubnetMask {
    type Error = anyhow::Error;

    fn try_from(mask: Ipv4Addr) -> Result<Self, Self::Error> {
        let mask: u32 = mask.into();
        let ones = mask.count_ones();
        if ones + mask.trailing_zeros() != 32 {
            Err(anyhow::format_err!("mask did not have consecutive ones {:b}", mask))
        } else {
            Ok(SubnetMask { ones: ones as u8 })
        }
    }
}

impl FidlCompatible<fidl_fuchsia_net::Ipv4Address> for SubnetMask {
    type FromError = anyhow::Error;
    type IntoError = never::Never;

    fn try_from_fidl(fidl: fidl_fuchsia_net::Ipv4Address) -> Result<Self, Self::FromError> {
        let addr = Ipv4Addr::from_fidl(fidl);
        SubnetMask::try_from(addr)
    }

    fn try_into_fidl(self) -> Result<fidl_fuchsia_net::Ipv4Address, Self::IntoError> {
        let addr = Ipv4Addr::from(self.to_u32());
        Ok(addr.into_fidl())
    }
}

impl Into<Ipv4Addr> for SubnetMask {
    fn into(self) -> Ipv4Addr {
        Ipv4Addr::from(self.to_u32())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::server::tests::{random_ipv4_generator, random_mac_generator};

    #[test]
    fn test_try_from_ipv4addr_with_consecutive_ones_returns_mask() -> Result<(), anyhow::Error> {
        assert_eq!(SubnetMask::try_from(Ipv4Addr::new(255, 255, 255, 0))?, SubnetMask { ones: 24 });
        Ok(())
    }

    #[test]
    fn test_try_from_ipv4addr_with_nonconsecutive_ones_returns_err() -> Result<(), anyhow::Error> {
        assert!(SubnetMask::try_from(Ipv4Addr::new(255, 255, 255, 1)).is_err());
        Ok(())
    }

    #[test]
    fn test_into_ipv4addr_returns_ipv4addr() -> Result<(), anyhow::Error> {
        let v1: Ipv4Addr = SubnetMask { ones: 24 }.into();
        let v2: Ipv4Addr = SubnetMask { ones: 0 }.into();
        let v3: Ipv4Addr = SubnetMask { ones: 32 }.into();
        assert_eq!(v1, Ipv4Addr::new(255, 255, 255, 0));
        assert_eq!(v2, Ipv4Addr::new(0, 0, 0, 0));
        assert_eq!(v3, Ipv4Addr::new(255, 255, 255, 255));
        Ok(())
    }

    #[test]
    fn test_lease_length_try_from_fidl() {
        let both = fidl_fuchsia_net_dhcp::LeaseLength { default: Some(42), max: Some(42) };
        let with_default = fidl_fuchsia_net_dhcp::LeaseLength { default: Some(42), max: None };
        let with_max = fidl_fuchsia_net_dhcp::LeaseLength { default: None, max: Some(42) };
        let neither = fidl_fuchsia_net_dhcp::LeaseLength { default: None, max: None };

        assert_eq!(
            LeaseLength::try_from_fidl(both).unwrap(),
            LeaseLength { default_seconds: 42, max_seconds: 42 }
        );
        assert_eq!(
            LeaseLength::try_from_fidl(with_default).unwrap(),
            LeaseLength { default_seconds: 42, max_seconds: 42 }
        );
        assert!(LeaseLength::try_from_fidl(with_max).is_err());
        assert!(LeaseLength::try_from_fidl(neither).is_err());
    }

    #[test]
    fn test_managed_addresses_try_from_fidl() -> Result<(), anyhow::Error> {
        let good_mask = fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 0] }),
            broadcast: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 255] }),
            mask: Some(fidl_fuchsia_net::Ipv4Address { addr: [255, 255, 255, 0] }),
            pool_range_start: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 2] }),
            pool_range_stop: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 254] }),
        };
        let bad_mask = fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 0] }),
            broadcast: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 255] }),
            mask: Some(fidl_fuchsia_net::Ipv4Address { addr: [255, 255, 0, 255] }),
            pool_range_start: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 2] }),
            pool_range_stop: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 254] }),
        };
        let missing_fields = fidl_fuchsia_net_dhcp::AddressPool {
            network_id: None,
            broadcast: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 255] }),
            mask: None,
            pool_range_start: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 2] }),
            pool_range_stop: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 254] }),
        };
        let invalid_network_id = fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 128] }),
            broadcast: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 255] }),
            mask: Some(fidl_fuchsia_net::Ipv4Address { addr: [255, 255, 255, 0] }),
            pool_range_start: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 2] }),
            pool_range_stop: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 254] }),
        };
        let invalid_broadcast = fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 0] }),
            broadcast: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 1, 255] }),
            mask: Some(fidl_fuchsia_net::Ipv4Address { addr: [255, 255, 255, 0] }),
            pool_range_start: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 2] }),
            pool_range_stop: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 254] }),
        };
        let invalid_pool_range_start = fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 0] }),
            broadcast: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 255] }),
            mask: Some(fidl_fuchsia_net::Ipv4Address { addr: [255, 255, 255, 0] }),
            pool_range_start: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 1, 2] }),
            pool_range_stop: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 254] }),
        };
        let invalid_pool_range_stop = fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 0] }),
            broadcast: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 255] }),
            mask: Some(fidl_fuchsia_net::Ipv4Address { addr: [255, 255, 255, 0] }),
            pool_range_start: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 2] }),
            pool_range_stop: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 1, 254] }),
        };
        let start_after_stop = fidl_fuchsia_net_dhcp::AddressPool {
            network_id: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 0] }),
            broadcast: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 255] }),
            mask: Some(fidl_fuchsia_net::Ipv4Address { addr: [255, 255, 255, 0] }),
            pool_range_start: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 20] }),
            pool_range_stop: Some(fidl_fuchsia_net::Ipv4Address { addr: [192, 168, 0, 10] }),
        };

        assert_eq!(
            ManagedAddresses::try_from_fidl(good_mask).unwrap(),
            ManagedAddresses {
                network_id: Ipv4Addr::from([192, 168, 0, 0]),
                broadcast: Ipv4Addr::from([192, 168, 0, 255]),
                mask: SubnetMask::try_from(24)?,
                pool_range_start: Ipv4Addr::from([192, 168, 0, 2]),
                pool_range_stop: Ipv4Addr::from([192, 168, 0, 254]),
            }
        );
        assert!(ManagedAddresses::try_from_fidl(bad_mask).is_err());
        assert!(ManagedAddresses::try_from_fidl(missing_fields).is_err());
        assert!(ManagedAddresses::try_from_fidl(invalid_network_id).is_err());
        assert!(ManagedAddresses::try_from_fidl(invalid_broadcast).is_err());
        assert!(ManagedAddresses::try_from_fidl(invalid_pool_range_start).is_err());
        assert!(ManagedAddresses::try_from_fidl(invalid_pool_range_stop).is_err());
        assert!(ManagedAddresses::try_from_fidl(start_after_stop).is_err());

        Ok(())
    }

    #[test]
    fn test_static_assignments_try_from_fidl() -> Result<(), anyhow::Error> {
        use std::iter::FromIterator;

        let fidl_fuchsia_hardware_ethernet_ext::MacAddress { octets: mac } = random_mac_generator();
        let ip = random_ipv4_generator();
        let fields_present = vec![fidl_fuchsia_net_dhcp::StaticAssignment {
            host: Some(fidl_fuchsia_net::MacAddress { octets: mac.clone() }),
            assigned_addr: Some(ip.into_fidl()),
        }];
        let multiple_entries = vec![
            fidl_fuchsia_net_dhcp::StaticAssignment {
                host: Some(fidl_fuchsia_net::MacAddress { octets: mac.clone() }),
                assigned_addr: Some(ip.into_fidl()),
            },
            fidl_fuchsia_net_dhcp::StaticAssignment {
                host: Some(fidl_fuchsia_net::MacAddress { octets: mac.clone() }),
                assigned_addr: Some(random_ipv4_generator().into_fidl()),
            },
        ];
        let fields_missing =
            vec![fidl_fuchsia_net_dhcp::StaticAssignment { host: None, assigned_addr: None }];

        assert_eq!(
            StaticAssignments::try_from_fidl(fields_present).unwrap(),
            StaticAssignments(HashMap::from_iter(
                vec![(fidl_fuchsia_net_ext::MacAddress { octets: mac }, ip)].into_iter()
            ))
        );
        assert!(StaticAssignments::try_from_fidl(multiple_entries).is_err());
        assert!(StaticAssignments::try_from_fidl(fields_missing).is_err());
        Ok(())
    }
}
