mod error;
mod io;
mod protocol;
pub use error::NoiseError;
pub use io::NoiseOutput;
pub use io::handshake;
pub use io::handshake::{Handshake, RemoteIdentity, IdentityExchange};
pub use protocol::{Keypair, AuthenticKeypair, KeypairIdentity, PublicKey, SecretKey};
pub use protocol::{Protocol, ProtocolParams, IX, IK, XX};
pub use protocol::{x25519::X25519, x25519_spec::X25519Spec};
use futures::prelude::*;
use libp2p_core::{identity, PeerId, UpgradeInfo, InboundUpgrade, OutboundUpgrade};
use std::pin::Pin;
use zeroize::Zeroize;
#[derive(Clone)]
pub struct NoiseConfig<P, C: Zeroize, R = ()> {
    dh_keys: AuthenticKeypair<C>,
    params: ProtocolParams,
    legacy: LegacyConfig,
    remote: R,
    _marker: std::marker::PhantomData<P>
}
impl<H, C: Zeroize, R> NoiseConfig<H, C, R> {
    
    
    pub fn into_authenticated(self) -> NoiseAuthenticated<H, C, R> {
        NoiseAuthenticated { config: self }
    }
    
    pub fn set_legacy_config(&mut self, cfg: LegacyConfig) -> &mut Self {
        self.legacy = cfg;
        self
    }
}
impl<C> NoiseConfig<IX, C>
where
    C: Protocol<C> + Zeroize
{
    
    pub fn ix(dh_keys: AuthenticKeypair<C>) -> Self {
        NoiseConfig {
            dh_keys,
            params: C::params_ix(),
            legacy: LegacyConfig::default(),
            remote: (),
            _marker: std::marker::PhantomData
        }
    }
}
impl<C> NoiseConfig<XX, C>
where
    C: Protocol<C> + Zeroize
{
    
    pub fn xx(dh_keys: AuthenticKeypair<C>) -> Self {
        NoiseConfig {
            dh_keys,
            params: C::params_xx(),
            legacy: LegacyConfig::default(),
            remote: (),
            _marker: std::marker::PhantomData
        }
    }
}
impl<C> NoiseConfig<IK, C>
where
    C: Protocol<C> + Zeroize
{
    
    
    
    
    pub fn ik_listener(dh_keys: AuthenticKeypair<C>) -> Self {
        NoiseConfig {
            dh_keys,
            params: C::params_ik(),
            legacy: LegacyConfig::default(),
            remote: (),
            _marker: std::marker::PhantomData
        }
    }
}
impl<C> NoiseConfig<IK, C, (PublicKey<C>, identity::PublicKey)>
where
    C: Protocol<C> + Zeroize
{
    
    
    
    
    pub fn ik_dialer(
        dh_keys: AuthenticKeypair<C>,
        remote_id: identity::PublicKey,
        remote_dh: PublicKey<C>
    ) -> Self {
        NoiseConfig {
            dh_keys,
            params: C::params_ik(),
            legacy: LegacyConfig::default(),
            remote: (remote_dh, remote_id),
            _marker: std::marker::PhantomData
        }
    }
}
impl<T, C> InboundUpgrade<T> for NoiseConfig<IX, C>
where
    NoiseConfig<IX, C>: UpgradeInfo,
    T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
    C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
    type Output = (RemoteIdentity<C>, NoiseOutput<T>);
    type Error = NoiseError;
    type Future = Handshake<T, C>;
    fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
        let session = self.params.into_builder()
            .local_private_key(self.dh_keys.secret().as_ref())
            .build_responder()
            .map_err(NoiseError::from);
        handshake::rt1_responder(socket, session,
            self.dh_keys.into_identity(),
            IdentityExchange::Mutual,
            self.legacy)
    }
}
impl<T, C> OutboundUpgrade<T> for NoiseConfig<IX, C>
where
    NoiseConfig<IX, C>: UpgradeInfo,
    T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
    C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
    type Output = (RemoteIdentity<C>, NoiseOutput<T>);
    type Error = NoiseError;
    type Future = Handshake<T, C>;
    fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future {
        let session = self.params.into_builder()
            .local_private_key(self.dh_keys.secret().as_ref())
            .build_initiator()
            .map_err(NoiseError::from);
        handshake::rt1_initiator(socket, session,
                                 self.dh_keys.into_identity(),
                                 IdentityExchange::Mutual,
                                 self.legacy)
    }
}
impl<T, C> InboundUpgrade<T> for NoiseConfig<XX, C>
where
    NoiseConfig<XX, C>: UpgradeInfo,
    T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
    C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
    type Output = (RemoteIdentity<C>, NoiseOutput<T>);
    type Error = NoiseError;
    type Future = Handshake<T, C>;
    fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
        let session = self.params.into_builder()
            .local_private_key(self.dh_keys.secret().as_ref())
            .build_responder()
            .map_err(NoiseError::from);
        handshake::rt15_responder(socket, session,
            self.dh_keys.into_identity(),
            IdentityExchange::Mutual,
            self.legacy)
    }
}
impl<T, C> OutboundUpgrade<T> for NoiseConfig<XX, C>
where
    NoiseConfig<XX, C>: UpgradeInfo,
    T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
    C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
    type Output = (RemoteIdentity<C>, NoiseOutput<T>);
    type Error = NoiseError;
    type Future = Handshake<T, C>;
    fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future {
        let session = self.params.into_builder()
            .local_private_key(self.dh_keys.secret().as_ref())
            .build_initiator()
            .map_err(NoiseError::from);
        handshake::rt15_initiator(socket, session,
            self.dh_keys.into_identity(),
            IdentityExchange::Mutual,
            self.legacy)
    }
}
impl<T, C, R> InboundUpgrade<T> for NoiseConfig<IK, C, R>
where
    NoiseConfig<IK, C, R>: UpgradeInfo,
    T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
    C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
    type Output = (RemoteIdentity<C>, NoiseOutput<T>);
    type Error = NoiseError;
    type Future = Handshake<T, C>;
    fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
        let session = self.params.into_builder()
            .local_private_key(self.dh_keys.secret().as_ref())
            .build_responder()
            .map_err(NoiseError::from);
        handshake::rt1_responder(socket, session,
            self.dh_keys.into_identity(),
            IdentityExchange::Receive,
            self.legacy)
    }
}
impl<T, C> OutboundUpgrade<T> for NoiseConfig<IK, C, (PublicKey<C>, identity::PublicKey)>
where
    NoiseConfig<IK, C, (PublicKey<C>, identity::PublicKey)>: UpgradeInfo,
    T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
    C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
    type Output = (RemoteIdentity<C>, NoiseOutput<T>);
    type Error = NoiseError;
    type Future = Handshake<T, C>;
    fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future {
        let session = self.params.into_builder()
            .local_private_key(self.dh_keys.secret().as_ref())
            .remote_public_key(self.remote.0.as_ref())
            .build_initiator()
            .map_err(NoiseError::from);
        handshake::rt1_initiator(socket, session,
            self.dh_keys.into_identity(),
            IdentityExchange::Send { remote: self.remote.1 },
            self.legacy)
    }
}
#[derive(Clone)]
pub struct NoiseAuthenticated<P, C: Zeroize, R> {
    config: NoiseConfig<P, C, R>
}
impl<P, C: Zeroize, R> UpgradeInfo for NoiseAuthenticated<P, C, R>
where
    NoiseConfig<P, C, R>: UpgradeInfo
{
    type Info = <NoiseConfig<P, C, R> as UpgradeInfo>::Info;
    type InfoIter = <NoiseConfig<P, C, R> as UpgradeInfo>::InfoIter;
    fn protocol_info(&self) -> Self::InfoIter {
        self.config.protocol_info()
    }
}
impl<T, P, C, R> InboundUpgrade<T> for NoiseAuthenticated<P, C, R>
where
    NoiseConfig<P, C, R>: UpgradeInfo + InboundUpgrade<T,
        Output = (RemoteIdentity<C>, NoiseOutput<T>),
        Error = NoiseError
    > + 'static,
    <NoiseConfig<P, C, R> as InboundUpgrade<T>>::Future: Send,
    T: AsyncRead + AsyncWrite + Send + 'static,
    C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
    type Output = (PeerId, NoiseOutput<T>);
    type Error = NoiseError;
    type Future = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>;
    fn upgrade_inbound(self, socket: T, info: Self::Info) -> Self::Future {
        Box::pin(self.config.upgrade_inbound(socket, info)
            .and_then(|(remote, io)| match remote {
                RemoteIdentity::IdentityKey(pk) => future::ok((pk.into_peer_id(), io)),
                _ => future::err(NoiseError::AuthenticationFailed)
            }))
    }
}
impl<T, P, C, R> OutboundUpgrade<T> for NoiseAuthenticated<P, C, R>
where
    NoiseConfig<P, C, R>: UpgradeInfo + OutboundUpgrade<T,
        Output = (RemoteIdentity<C>, NoiseOutput<T>),
        Error = NoiseError
    > + 'static,
    <NoiseConfig<P, C, R> as OutboundUpgrade<T>>::Future: Send,
    T: AsyncRead + AsyncWrite + Send + 'static,
    C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
    type Output = (PeerId, NoiseOutput<T>);
    type Error = NoiseError;
    type Future = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>;
    fn upgrade_outbound(self, socket: T, info: Self::Info) -> Self::Future {
        Box::pin(self.config.upgrade_outbound(socket, info)
            .and_then(|(remote, io)| match remote {
                RemoteIdentity::IdentityKey(pk) => future::ok((pk.into_peer_id(), io)),
                _ => future::err(NoiseError::AuthenticationFailed)
            }))
    }
}
#[derive(Clone)]
pub struct LegacyConfig {
    
    
    
    
    pub send_legacy_handshake: bool,
    
    
    
    
    pub recv_legacy_handshake: bool,
}
impl Default for LegacyConfig {
    fn default() -> Self {
        Self {
            send_legacy_handshake: false,
            recv_legacy_handshake: false,
        }
    }
}