passes through concrete QUIC connection errors up the call stack (#31168)

This commit is contained in:
behzad nouri 2023-04-12 19:53:25 +00:00 committed by GitHub
parent 602297e29f
commit 34da001cda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 24 additions and 23 deletions

2
Cargo.lock generated
View File

@ -5449,6 +5449,7 @@ dependencies = [
"rand 0.7.3",
"rand_chacha 0.2.2",
"rayon",
"rcgen",
"solana-logger 1.16.0",
"solana-measure",
"solana-metrics",
@ -6430,6 +6431,7 @@ dependencies = [
"quinn",
"quinn-proto",
"quinn-udp",
"rcgen",
"rustls 0.20.6",
"solana-connection-cache",
"solana-logger 1.16.0",

View File

@ -18,6 +18,7 @@ indicatif = { workspace = true, optional = true }
log = { workspace = true }
rand = { workspace = true }
rayon = { workspace = true }
rcgen = { workspace = true }
solana-measure = { workspace = true }
solana-metrics = { workspace = true }
solana-sdk = { workspace = true }

View File

@ -287,7 +287,7 @@ pub enum ConnectionPoolError {
#[derive(Error, Debug)]
pub enum ClientError {
#[error("Certificate error: {0}")]
CertificateError(String),
CertificateError(#[from] rcgen::RcgenError),
#[error("IO error: {0:?}")]
IoError(#[from] std::io::Error),

View File

@ -4725,6 +4725,7 @@ dependencies = [
"log",
"rand 0.7.3",
"rayon",
"rcgen",
"solana-measure",
"solana-metrics",
"solana-sdk 1.16.0",
@ -5392,6 +5393,7 @@ dependencies = [
"quinn",
"quinn-proto",
"quinn-udp",
"rcgen",
"rustls 0.20.6",
"solana-connection-cache",
"solana-measure",

View File

@ -19,6 +19,7 @@ log = { workspace = true }
quinn = { workspace = true }
quinn-proto = { workspace = true }
quinn-udp = { workspace = true }
rcgen = { workspace = true }
rustls = { workspace = true, features = ["dangerous_configuration"] }
solana-connection-cache = { workspace = true }
solana-measure = { workspace = true }

View File

@ -15,6 +15,7 @@ use {
quic_client::QuicClientConnection as BlockingQuicClientConnection,
},
quinn::Endpoint,
rcgen::RcgenError,
solana_connection_cache::{
connection_cache::{
BaseClientConnection, ClientError, ConnectionManager, ConnectionPool,
@ -29,7 +30,6 @@ use {
tls_certificates::new_self_signed_tls_certificate,
},
std::{
error::Error,
net::{IpAddr, Ipv4Addr, SocketAddr},
sync::{Arc, RwLock},
},
@ -39,7 +39,7 @@ use {
#[derive(Error, Debug)]
pub enum QuicClientError {
#[error("Certificate error: {0}")]
CertificateError(String),
CertificateError(#[from] RcgenError),
}
pub struct QuicPool {
@ -92,8 +92,7 @@ pub struct QuicConfig {
impl NewConnectionConfig for QuicConfig {
fn new() -> Result<Self, ClientError> {
let (cert, priv_key) =
new_self_signed_tls_certificate(&Keypair::new(), IpAddr::V4(Ipv4Addr::UNSPECIFIED))
.map_err(|err| ClientError::CertificateError(err.to_string()))?;
new_self_signed_tls_certificate(&Keypair::new(), IpAddr::V4(Ipv4Addr::UNSPECIFIED))?;
Ok(Self {
client_certificate: Arc::new(QuicClientCertificate {
certificate: cert,
@ -136,7 +135,7 @@ impl QuicConfig {
&mut self,
keypair: &Keypair,
ipaddr: IpAddr,
) -> Result<(), Box<dyn Error>> {
) -> Result<(), RcgenError> {
let (cert, priv_key) = new_self_signed_tls_certificate(keypair, ipaddr)?;
self.client_certificate = Arc::new(QuicClientCertificate {
certificate: cert,

View File

@ -101,11 +101,8 @@ pub fn spawn_server(
info!("Start quic server on {:?}", sock);
let (config, _cert) = configure_server(keypair, gossip_host)?;
let endpoint = {
Endpoint::new(EndpointConfig::default(), Some(config), sock, TokioRuntime)
.map_err(|_e| QuicServerError::EndpointFailed)?
};
let endpoint = Endpoint::new(EndpointConfig::default(), Some(config), sock, TokioRuntime)
.map_err(QuicServerError::EndpointFailed)?;
let handle = tokio::spawn(run_server(
endpoint.clone(),
packet_sender,

View File

@ -57,8 +57,7 @@ pub(crate) fn configure_server(
identity_keypair: &Keypair,
gossip_host: IpAddr,
) -> Result<(ServerConfig, String), QuicServerError> {
let (cert, priv_key) = new_self_signed_tls_certificate(identity_keypair, gossip_host)
.map_err(|_e| QuicServerError::ConfigureFailed)?;
let (cert, priv_key) = new_self_signed_tls_certificate(identity_keypair, gossip_host)?;
let cert_chain_pem_parts = vec![Pem {
tag: "CERTIFICATE".to_string(),
contents: cert.0.clone(),
@ -68,8 +67,7 @@ pub(crate) fn configure_server(
let mut server_tls_config = rustls::ServerConfig::builder()
.with_safe_defaults()
.with_client_cert_verifier(SkipClientVerification::new())
.with_single_cert(vec![cert], priv_key)
.map_err(|_e| QuicServerError::ConfigureFailed)?;
.with_single_cert(vec![cert], priv_key)?;
server_tls_config.alpn_protocols = vec![ALPN_TPU_PROTOCOL_ID.to_vec()];
let mut server_config = ServerConfig::with_crypto(Arc::new(server_tls_config));
@ -106,11 +104,12 @@ fn rt() -> Runtime {
#[derive(thiserror::Error, Debug)]
pub enum QuicServerError {
#[error("Server configure failed")]
ConfigureFailed,
#[error("Endpoint creation failed")]
EndpointFailed,
#[error("Endpoint creation failed: {0}")]
EndpointFailed(std::io::Error),
#[error("Certificate error: {0}")]
CertificateError(#[from] rcgen::RcgenError),
#[error("TLS error: {0}")]
TlsError(#[from] rustls::Error),
}
#[derive(Default)]

View File

@ -1,15 +1,15 @@
use {
pkcs8::{der::Document, AlgorithmIdentifier, ObjectIdentifier},
rcgen::{CertificateParams, DistinguishedName, DnType, SanType},
rcgen::{CertificateParams, DistinguishedName, DnType, RcgenError, SanType},
solana_sdk::{pubkey::Pubkey, signature::Keypair},
std::{error::Error, net::IpAddr},
std::net::IpAddr,
x509_parser::{prelude::*, public_key::PublicKey},
};
pub fn new_self_signed_tls_certificate(
keypair: &Keypair,
san: IpAddr,
) -> Result<(rustls::Certificate, rustls::PrivateKey), Box<dyn Error>> {
) -> Result<(rustls::Certificate, rustls::PrivateKey), RcgenError> {
// TODO(terorie): Is it safe to sign the TLS cert with the identity private key?
// Unfortunately, rcgen does not accept a "raw" Ed25519 key.