use crate::consts::DFLT_PORT;
use crate::types::ConecConnAddr;
use crate::util::{get_cert, get_cert_and_key, CertReadError};
use err_derive::Error;
use quinn::{Certificate, CertificateChain, ParseError, PrivateKey};
use rcgen::{generate_simple_self_signed, RcgenError};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::path::Path;
#[derive(Clone, Debug)]
pub struct ClientConfig {
pub(super) id: String,
pub(super) coord: String,
pub(super) addr: ConecConnAddr,
pub(super) keylog: bool,
pub(super) extra_ca: Option<Certificate>,
pub(super) client_ca: Option<Certificate>,
pub(super) srcaddr: SocketAddr,
pub(super) cert_and_key: Option<(CertificateChain, PrivateKey, Vec<u8>)>,
pub(super) stateless_retry: bool,
pub(super) listen: bool,
pub(super) keepalive: bool,
pub(super) holepunch: bool,
}
#[derive(Debug, Error)]
pub enum CertGenError {
#[error(display = "Generating self-signed cert: {:?}", _0)]
Generating(#[source] RcgenError),
#[error(display = "Parsing secret key: {:?}", _0)]
Parse(#[source] ParseError),
}
def_into_error!(CertGenError);
impl ClientConfig {
pub fn new(id: String, coord: String) -> Self {
Self {
id,
coord,
addr: ConecConnAddr::Portnum(DFLT_PORT),
keylog: false,
extra_ca: None,
client_ca: None,
srcaddr: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
cert_and_key: None,
stateless_retry: false,
listen: true,
keepalive: true,
holepunch: true,
}
}
pub fn set_port(&mut self, port: u16) -> &mut Self {
self.addr = port.into();
self
}
pub fn set_addr(&mut self, addr: SocketAddr) -> &mut Self {
self.addr = addr.into();
self
}
pub fn enable_keylog(&mut self) -> &mut Self {
self.keylog = true;
self
}
pub fn set_ca(&mut self, ca: Certificate) -> &mut Self {
self.extra_ca = Some(ca);
self
}
pub fn set_ca_from_file(&mut self, cert_path: &Path) -> Result<&mut Self, CertReadError> {
Ok(self.set_ca(get_cert(cert_path)?))
}
pub fn set_client_ca(&mut self, ca: Certificate) -> &mut Self {
self.client_ca = Some(ca);
self
}
pub fn set_client_ca_from_file(&mut self, cert_path: &Path) -> Result<&mut Self, CertReadError> {
Ok(self.set_client_ca(get_cert(cert_path)?))
}
pub fn set_srcaddr(&mut self, src: SocketAddr) -> &mut Self {
self.srcaddr = src;
self
}
pub fn enable_stateless_retry(&mut self) -> &mut Self {
self.stateless_retry = true;
self
}
pub fn disable_listen(&mut self) -> &mut Self {
self.listen = false;
self
}
pub fn disable_keepalive(&mut self) -> &mut Self {
self.keepalive = false;
self
}
pub fn disable_holepunch(&mut self) -> &mut Self {
self.holepunch = false;
self
}
pub fn set_cert(&mut self, cert: CertificateChain, key: PrivateKey, key_der: Vec<u8>) -> &mut Self {
self.cert_and_key = Some((cert, key, key_der));
self
}
pub fn set_cert_from_file(&mut self, cert_path: &Path, key_path: &Path) -> Result<&mut Self, CertReadError> {
let (cert, key, key_der) = get_cert_and_key(cert_path, key_path)?;
Ok(self.set_cert(cert, key, key_der))
}
pub(super) fn gen_certs(&mut self) -> Result<(), CertGenError> {
if self.cert_and_key.is_some() {
return Ok(());
}
let cert = generate_simple_self_signed(&[self.id.clone()][..])?;
let key = cert.serialize_private_key_der();
let cert = CertificateChain::from_certs(Certificate::from_der(&cert.serialize_der()?));
self.cert_and_key = Some((cert, PrivateKey::from_der(&key)?, key));
Ok(())
}
}