// 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 hyper_rustls;
use rustls;

use {
    fidl_fuchsia_posix_socket::{ProviderMarker, ProviderSynchronousProxy},
    fuchsia_async::{
        net::{TcpConnector, TcpStream},
        EHandle,
    },
    fuchsia_component::client::connect_channel_to_service_at,
    fuchsia_zircon as zx,
    futures::{
        compat::Compat,
        future::{Future, FutureExt, TryFutureExt},
        io::{self, AsyncReadExt},
        ready,
        task::{Context, Poll, SpawnExt},
    },
    hyper::{
        client::{
            connect::{Connect, Connected, Destination},
            Client,
        },
        Body,
    },
    net2::TcpStreamExt as _,
    std::{
        net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs},
        pin::Pin,
    },
    tcp_stream_ext::TcpStreamExt as _,
};

/// A Fuchsia-compatible hyper client configured for making HTTP requests.
pub type HttpClient = Client<HyperConnector, Body>;

/// A Fuchsia-compatible hyper client configured for making HTTP and HTTPS requests.
pub type HttpsClient = Client<hyper_rustls::HttpsConnector<HyperConnector>, Body>;

/// A future that yields a hyper-compatible TCP stream.
pub struct HyperConnectorFuture {
    tcp_connector_res: Result<TcpConnector, Option<io::Error>>,
    tcp_options: TcpOptions,
}

impl Future for HyperConnectorFuture {
    type Output = Result<(Compat<TcpStream>, Connected), io::Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let connector = self.tcp_connector_res.as_mut().map_err(|x| x.take().unwrap())?;
        let stream = ready!(connector.poll_unpin(cx)?);
        let () = apply_tcp_options(stream.std(), &self.tcp_options)?;
        Poll::Ready(Ok((stream.compat(), Connected::new())))
    }
}

fn apply_tcp_options(stream: &std::net::TcpStream, options: &TcpOptions) -> Result<(), io::Error> {
    if let Some(idle) = options.keepalive_idle {
        stream.set_keepalive(Some(idle))?;
    } else if options.keepalive_interval.is_some() || options.keepalive_count.is_some() {
        // This sets SO_KEEPALIVE without setting TCP_KEEPIDLE.
        stream.set_keepalive(None)?;
    }
    if let Some(interval) = options.keepalive_interval {
        stream.set_keepalive_interval(interval)?;
    }
    if let Some(count) = options.keepalive_count {
        stream.set_keepalive_count(count)?;
    }
    Ok(())
}

#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
/// A container of TCP settings to be applied to the sockets created by the hyper client.
pub struct TcpOptions {
    /// This sets TCP_KEEPIDLE and SO_KEEPALIVE.
    pub keepalive_idle: Option<std::time::Duration>,
    /// This sets TCP_KEEPINTVL and SO_KEEPALIVE.
    pub keepalive_interval: Option<std::time::Duration>,
    /// This sets TCP_KEEPCNT and SO_KEEPALIVE.
    pub keepalive_count: Option<i32>,
}

/// A Fuchsia-compatible implementation of hyper's `Connect` trait which allows
/// creating a TcpStream to a particular destination.
pub struct HyperConnector {
    tcp_options: TcpOptions,
}

impl HyperConnector {
    pub fn new() -> Self {
        Self { tcp_options: std::default::Default::default() }
    }
    pub fn from_tcp_options(tcp_options: TcpOptions) -> Self {
        Self { tcp_options }
    }
}

impl Connect for HyperConnector {
    type Transport = Compat<TcpStream>;
    type Error = io::Error;
    type Future = Compat<HyperConnectorFuture>;
    fn connect(&self, dst: Destination) -> Self::Future {
        let res = (|| {
            let host = dst.host();
            let port = match dst.port() {
                Some(port) => port,
                None => {
                    if dst.scheme() == "https" {
                        443
                    } else {
                        80
                    }
                }
            };

            let addr = if let Some(addr) = parse_ip_addr(host, port) {
                addr
            } else {
                // TODO(cramertj): smarter DNS-- nonblocking, don't just pick first addr
                (host, port).to_socket_addrs()?.next().ok_or_else(|| {
                    io::Error::new(io::ErrorKind::Other, "destination resolved to no address")
                })?
            };
            TcpStream::connect(addr)
        })();
        HyperConnectorFuture { tcp_connector_res: res.map_err(Some), tcp_options: self.tcp_options }
            .compat()
    }
}

/// Returns a new Fuchsia-compatible hyper client for making HTTP requests.
pub fn new_client() -> HttpClient {
    Client::builder().executor(EHandle::local().compat()).build(HyperConnector::new())
}

pub fn new_https_client_dangerous(
    tls: rustls::ClientConfig,
    tcp_options: TcpOptions,
) -> HttpsClient {
    let https =
        hyper_rustls::HttpsConnector::from((HyperConnector::from_tcp_options(tcp_options), tls));
    Client::builder().executor(EHandle::local().compat()).build(https)
}

/// Returns a new Fuchsia-compatible hyper client for making HTTP and HTTPS requests.
pub fn new_https_client_from_tcp_options(tcp_options: TcpOptions) -> HttpsClient {
    let mut tls = rustls::ClientConfig::new();
    tls.root_store.add_server_trust_anchors(&webpki_roots_fuchsia::TLS_SERVER_ROOTS);
    new_https_client_dangerous(tls, tcp_options)
}

/// Returns a new Fuchsia-compatible hyper client for making HTTP and HTTPS requests.
pub fn new_https_client() -> HttpsClient {
    new_https_client_from_tcp_options(std::default::Default::default())
}

fn parse_ip_addr(host: &str, port: u16) -> Option<SocketAddr> {
    if let Ok(addr) = host.parse::<Ipv4Addr>() {
        return Some(SocketAddr::V4(SocketAddrV4::new(addr, port)));
    }

    // IPv6 literals are always enclosed in [].
    if !host.starts_with("[") || !host.ends_with(']') {
        return None;
    }

    let host = &host[1..host.len() - 1];

    // IPv6 addresses with zones always contain "%25", which is "%" URL encoded.
    let mut host_parts = host.splitn(2, "%25");

    let addr = host_parts.next()?.parse::<Ipv6Addr>().ok()?;

    let scope_id = match host_parts.next() {
        Some(zone_id) => {
            // rfc6874 section 4 states:
            //
            //     The security considerations from the URI syntax specification
            //     [RFC3986] and the IPv6 Scoped Address Architecture specification
            //     [RFC4007] apply.  In particular, this URI format creates a specific
            //     pathway by which a deceitful zone index might be communicated, as
            //     mentioned in the final security consideration of the Scoped Address
            //     Architecture specification.  It is emphasised that the format is
            //     intended only for debugging purposes, but of course this intention
            //     does not prevent misuse.
            //
            //     To limit this risk, implementations MUST NOT allow use of this format
            //     except for well-defined usages, such as sending to link-local
            //     addresses under prefix fe80::/10.  At the time of writing, this is
            //     the only well-defined usage known.
            //
            // Since the only known use-case of IPv6 Zone Identifiers on Fuchsia is to communicate
            // with link-local devices, restrict addresse to link-local zone identifiers.
            //
            // TODO: use Ipv6Addr::is_unicast_link_local_strict when available in stable rust.
            if addr.segments()[..4] != [0xfe80, 0, 0, 0] {
                return None;
            }

            // TODO: validate that the value matches rfc6874 grammar `ZoneID = 1*( unreserved / pct-encoded )`.
            match zone_id.parse::<u32>() {
                Ok(zone_id_num) => zone_id_num,
                Err(_) => {
                    let (proxy, server) = zx::Channel::create().expect("failed to create channel");
                    connect_channel_to_service_at::<ProviderMarker>(server, "/svc")
                        .expect("failed to connect to service");
                    let mut proxy = ProviderSynchronousProxy::new(proxy);
                    let id = proxy
                        .interface_name_to_index(zone_id, zx::Time::INFINITE)
                        .expect("failed to get interface index");
                    match id {
                        Ok(id) => id as u32,
                        Err(_) => return None,
                    }
                }
            }
        }
        None => 0,
    };

    Some(SocketAddr::V6(SocketAddrV6::new(addr, port, 0, scope_id)))
}

#[cfg(test)]
mod test {
    use {
        super::*,
        fuchsia_async::{self as fasync, net::TcpListener, Executor},
        futures::stream::StreamExt as _,
    };

    #[test]
    fn can_create_client() {
        let _exec = Executor::new().unwrap();
        let _client = new_client();
    }

    #[test]
    fn can_create_https_client() {
        let _exec = Executor::new().unwrap();
        let _client = new_https_client();
    }

    #[fasync::run_singlethreaded(test)]
    async fn hyper_connector_sets_tcp_options() {
        let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0);
        let listener = TcpListener::bind(&addr).unwrap();
        let addr = listener.local_addr().unwrap();
        let listener = listener.accept_stream();
        fasync::spawn(async move {
            listener
                .map(|res| {
                    res.unwrap();
                })
                .collect()
                .await
        });

        let idle = std::time::Duration::from_secs(36);
        let interval = std::time::Duration::from_secs(47);
        let count = 58;
        let connector = HyperConnector::from_tcp_options(TcpOptions {
            keepalive_idle: Some(idle),
            keepalive_interval: Some(interval),
            keepalive_count: Some(count),
            ..Default::default()
        });
        let uri = format!("https://{}", addr).parse::<hyper::Uri>().unwrap();
        let stream = connector
            .connect(Destination::try_from_uri(uri).unwrap())
            .into_inner()
            .await
            .unwrap()
            .0;

        assert_eq!(stream.get_ref().std().keepalive().unwrap(), Some(idle));
        assert_eq!(stream.get_ref().std().keepalive_interval().unwrap(), interval);
        assert_eq!(stream.get_ref().std().keepalive_count().unwrap(), count);
    }

    #[test]
    fn test_parse_ipv4_addr() {
        let addr = parse_ip_addr("1.2.3.4", 8080);
        let expected = "1.2.3.4:8080".parse::<SocketAddr>().unwrap();
        assert_eq!(addr, Some(expected));
    }

    #[test]
    fn test_parse_invalid_addresses() {
        assert_eq!(parse_ip_addr("1.2.3", 8080), None);
        assert_eq!(parse_ip_addr("1.2.3.4.5", 8080), None);
        assert_eq!(parse_ip_addr("localhost", 8080), None);
        assert_eq!(parse_ip_addr("[fe80::1:2:3:4", 8080), None);
        assert_eq!(parse_ip_addr("[[fe80::1:2:3:4]", 8080), None);
    }

    #[test]
    fn test_parse_ipv6_addr() {
        let addr = parse_ip_addr("[fe80::1:2:3:4]", 8080);
        let expected = "[fe80::1:2:3:4]:8080".parse::<SocketAddr>().unwrap();
        assert_eq!(addr, Some(expected));
    }

    #[test]
    fn test_parse_ipv6_addr_with_zone() {
        let expected = "fe80::1:2:3:4".parse::<Ipv6Addr>().unwrap();

        let addr = parse_ip_addr("[fe80::1:2:3:4%250]", 8080);
        assert_eq!(addr, Some(SocketAddr::V6(SocketAddrV6::new(expected, 8080, 0, 0))));

        let addr = parse_ip_addr("[fe80::1:2:3:4%252]", 8080);
        assert_eq!(addr, Some(SocketAddr::V6(SocketAddrV6::new(expected, 8080, 0, 2))));
    }

    #[test]
    fn test_parse_ipv6_addr_with_zone_supports_interface_names() {
        let expected = "fe80::1:2:3:4".parse::<Ipv6Addr>().unwrap();

        let addr = parse_ip_addr("[fe80::1:2:3:4%25lo]", 8080);
        assert_eq!(addr, Some(SocketAddr::V6(SocketAddrV6::new(expected, 8080, 0, 1))));

        assert_eq!(parse_ip_addr("[fe80::1:2:3:4%25unknownif]", 8080), None);
    }

    #[test]
    fn test_parse_ipv6_addr_with_zone_must_be_local() {
        assert_eq!(parse_ip_addr("[fe81::1:2:3:4%252]", 8080), None);
    }
}
