1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
mod crypto;
mod endpoint;
mod muxer;
#[cfg(feature = "tls")]
mod tls;
mod transport;

pub use crate::crypto::Crypto;
#[cfg(feature = "noise")]
pub use crate::crypto::NoiseCrypto;
#[cfg(feature = "tls")]
pub use crate::crypto::TlsCrypto;
pub use crate::muxer::{QuicMuxer, QuicMuxerError};
pub use crate::transport::{QuicDial, QuicTransport};
pub use ed25519_dalek::{Keypair, PublicKey, SecretKey};
#[cfg(feature = "noise")]
pub use quinn_noise::{KeyLog, KeyLogFile};
pub use quinn_proto::{ConfigError, ConnectError, ConnectionError, TransportConfig};

use libp2p::core::transport::TransportError;
use libp2p::{Multiaddr, PeerId};
use quinn_proto::crypto::Session;
use thiserror::Error;

pub fn generate_keypair() -> Keypair {
    Keypair::generate(&mut rand_core::OsRng {})
}

/// Quic configuration.
pub struct QuicConfig<C: Crypto> {
    pub keypair: Keypair,
    pub psk: Option<[u8; 32]>,
    pub transport: TransportConfig,
    pub keylogger: Option<C::Keylogger>,
}

impl<C: Crypto> Default for QuicConfig<C> {
    fn default() -> Self {
        Self {
            keypair: Keypair::generate(&mut rand_core::OsRng {}),
            psk: None,
            transport: TransportConfig::default(),
            keylogger: None,
        }
    }
}

impl<C: Crypto> std::fmt::Debug for QuicConfig<C> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_struct("QuicConfig")
            .field("keypair", &self.keypair.public)
            .field("psk", &self.psk)
            .field("transport", &self.transport)
            .finish()
    }
}

impl<C: Crypto> QuicConfig<C>
where
    <C::Session as Session>::ClientConfig: Send + Unpin,
    <C::Session as Session>::HeaderKey: Unpin,
    <C::Session as Session>::PacketKey: Unpin,
{
    /// Creates a new config from a keypair.
    pub fn new(keypair: Keypair) -> Self {
        Self {
            keypair,
            ..Default::default()
        }
    }

    /// Enable keylogging.
    pub fn enable_keylogger(&mut self) -> &mut Self {
        self.keylogger = Some(C::keylogger());
        self
    }

    /// Spawns a new endpoint.
    pub async fn listen_on(
        self,
        addr: Multiaddr,
    ) -> Result<QuicTransport<C>, TransportError<QuicError>> {
        QuicTransport::new(self, addr).await
    }
}

#[derive(Debug, Error)]
pub enum QuicError {
    #[error("{0}")]
    Config(#[from] ConfigError),
    #[error("{0}")]
    Connect(#[from] ConnectError),
    #[error("{0}")]
    Muxer(#[from] QuicMuxerError),
    #[error("{0}")]
    Io(#[from] std::io::Error),
    #[error("a `StreamMuxerEvent` was generated before the handshake was complete.")]
    UpgradeError,
}

pub trait ToLibp2p {
    fn to_keypair(&self) -> libp2p::identity::Keypair;
    fn to_public(&self) -> libp2p::identity::PublicKey;
    fn to_peer_id(&self) -> PeerId {
        self.to_public().into_peer_id()
    }
}

impl ToLibp2p for Keypair {
    fn to_keypair(&self) -> libp2p::identity::Keypair {
        let mut secret_key = self.secret.to_bytes();
        let secret_key = libp2p::identity::ed25519::SecretKey::from_bytes(&mut secret_key).unwrap();
        libp2p::identity::Keypair::Ed25519(secret_key.into())
    }

    fn to_public(&self) -> libp2p::identity::PublicKey {
        self.public.to_public()
    }
}

impl ToLibp2p for PublicKey {
    fn to_keypair(&self) -> libp2p::identity::Keypair {
        panic!("wtf?");
    }

    fn to_public(&self) -> libp2p::identity::PublicKey {
        let public_key = self.to_bytes();
        let public_key = libp2p::identity::ed25519::PublicKey::decode(&public_key[..]).unwrap();
        libp2p::identity::PublicKey::Ed25519(public_key)
    }
}