Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Simplify quinn rpc test #39

Merged
merged 2 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 5 additions & 47 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ postcard = { version = "1", default-features = false, features = [
"use-std",
"experimental-derive",
] }
quic-rpc = { version = "0.17.1", optional = true }
quic-rpc = { version = "0.17.3", optional = true }
quic-rpc-derive = { version = "0.17", optional = true }
quinn = { package = "iroh-quinn", version = "0.12", features = ["ring"] }
rand = "0.8"
Expand Down Expand Up @@ -119,7 +119,7 @@ example-iroh = [
"dep:console",
"iroh/discovery-local-network"
]
test = ["quic-rpc/quinn-transport"]
test = ["quic-rpc/quinn-transport", "quic-rpc/test-utils"]

[package.metadata.docs.rs]
all-features = true
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ Examples that use `iroh-blobs` can be found in the `iroh` crate. the iroh crate
This project is licensed under either of

* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
<http://www.apache.org/licenses/LICENSE-2.0>)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
<http://opensource.org/licenses/MIT>)

at your option.

Expand Down
6 changes: 1 addition & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,22 @@
//! [iroh]: https://docs.rs/iroh
#![deny(missing_docs, rustdoc::broken_intra_doc_links)]
#![recursion_limit = "256"]
#![cfg_attr(iroh_docsrs, feature(doc_cfg))]
#![cfg_attr(iroh_docsrs, feature(doc_auto_cfg))]

#[cfg(feature = "cli")]
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "cli")))]
pub mod cli;
#[cfg(feature = "downloader")]
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "downloader")))]
pub mod downloader;
pub mod export;
pub mod format;
pub mod get;
pub mod hashseq;
pub mod metrics;
#[cfg(feature = "net_protocol")]
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "net_protocol")))]
pub mod net_protocol;
pub mod protocol;
pub mod provider;
#[cfg(feature = "rpc")]
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "rpc")))]
pub mod rpc;
pub mod store;
pub mod ticket;
Expand Down
3 changes: 0 additions & 3 deletions src/util/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,12 @@ pub fn scan_path(
}

#[cfg(feature = "rpc")]
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "rpc")))]
fn file_name(path: &Path) -> anyhow::Result<String> {
relative_canonicalized_path_to_string(path.file_name().context("path is invalid")?)
}

/// Create data sources from a directory.
#[cfg(feature = "rpc")]
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "rpc")))]
pub fn scan_dir(
root: PathBuf,
wrap: crate::rpc::client::blobs::WrapOption,
Expand Down Expand Up @@ -129,7 +127,6 @@ pub fn relative_canonicalized_path_to_string(path: impl AsRef<Path>) -> anyhow::
/// Loads a [`iroh::SecretKey`] from the provided file, or stores a newly generated one
/// at the given location.
#[cfg(feature = "rpc")]
#[cfg_attr(iroh_docsrs, doc(cfg(feature = "rpc")))]
pub async fn load_secret_key(key_path: PathBuf) -> anyhow::Result<iroh::SecretKey> {
use iroh::SecretKey;
use tokio::io::AsyncWriteExt;
Expand Down
91 changes: 14 additions & 77 deletions tests/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,85 +1,15 @@
#![cfg(feature = "test")]
use std::{net::SocketAddr, path::PathBuf, sync::Arc};
use std::{net::SocketAddr, path::PathBuf, vec};

use iroh_blobs::{net_protocol::Blobs, util::local_pool::LocalPool};
use quic_rpc::transport::quinn::QuinnConnector;
use quinn::{
crypto::rustls::{QuicClientConfig, QuicServerConfig},
rustls, ClientConfig, Endpoint, ServerConfig,
};
use rcgen::CertifiedKey;
use quic_rpc::client::QuinnConnector;
use tempfile::TempDir;
use testresult::TestResult;
use tokio_util::task::AbortOnDropHandle;

type QC = QuinnConnector<iroh_blobs::rpc::proto::Response, iroh_blobs::rpc::proto::Request>;
type QC = QuinnConnector<iroh_blobs::rpc::proto::RpcService>;
type BlobsClient = iroh_blobs::rpc::client::blobs::Client<QC>;

/// Builds default quinn client config and trusts given certificates.
///
/// ## Args
///
/// - server_certs: a list of trusted certificates in DER format.
fn configure_client(server_certs: &[CertifiedKey]) -> anyhow::Result<ClientConfig> {
let mut certs = rustls::RootCertStore::empty();
for cert in server_certs {
let cert = cert.cert.der().clone();
certs.add(cert)?;
}

let crypto_client_config = rustls::ClientConfig::builder_with_provider(Arc::new(
rustls::crypto::ring::default_provider(),
))
.with_protocol_versions(&[&rustls::version::TLS13])
.expect("valid versions")
.with_root_certificates(certs)
.with_no_client_auth();
let quic_client_config = QuicClientConfig::try_from(crypto_client_config)?;

Ok(ClientConfig::new(Arc::new(quic_client_config)))
}

/// Returns default server configuration along with its certificate.
#[allow(clippy::field_reassign_with_default)] // https://github.com/rust-lang/rust-clippy/issues/6527
fn configure_server() -> anyhow::Result<(ServerConfig, CertifiedKey)> {
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()])?;
let cert_der = cert.cert.der();
let priv_key = rustls::pki_types::PrivatePkcs8KeyDer::from(cert.key_pair.serialize_der());
let cert_chain = vec![cert_der.clone()];

let crypto_server_config = rustls::ServerConfig::builder_with_provider(Arc::new(
rustls::crypto::ring::default_provider(),
))
.with_protocol_versions(&[&rustls::version::TLS13])
.expect("valid versions")
.with_no_client_auth()
.with_single_cert(cert_chain, priv_key.into())?;
let quic_server_config = QuicServerConfig::try_from(crypto_server_config)?;
let mut server_config = ServerConfig::with_crypto(Arc::new(quic_server_config));

Arc::get_mut(&mut server_config.transport)
.unwrap()
.max_concurrent_uni_streams(0_u8.into());

Ok((server_config, cert))
}

pub fn make_server_endpoint(bind_addr: SocketAddr) -> anyhow::Result<(Endpoint, CertifiedKey)> {
let (server_config, server_cert) = configure_server()?;
let endpoint = Endpoint::server(server_config, bind_addr)?;
Ok((endpoint, server_cert))
}

pub fn make_client_endpoint(
bind_addr: SocketAddr,
server_certs: &[CertifiedKey],
) -> anyhow::Result<Endpoint> {
let client_cfg = configure_client(server_certs)?;
let mut endpoint = Endpoint::client(bind_addr)?;
endpoint.set_default_client_config(client_cfg);
Ok(endpoint)
}

/// An iroh node that just has the blobs transport
#[derive(Debug)]
pub struct Node {
Expand All @@ -90,7 +20,7 @@ pub struct Node {
}

impl Node {
pub async fn new(path: PathBuf) -> anyhow::Result<(Self, SocketAddr, CertifiedKey)> {
pub async fn new(path: PathBuf) -> anyhow::Result<(Self, SocketAddr, Vec<u8>)> {
let store = iroh_blobs::store::fs::Store::load(path).await?;
let local_pool = LocalPool::default();
let endpoint = iroh::Endpoint::builder().bind().await?;
Expand All @@ -99,7 +29,7 @@ impl Node {
.accept(iroh_blobs::ALPN, blobs.clone())
.spawn()
.await?;
let (config, key) = configure_server()?;
let (config, key) = quic_rpc::transport::quinn::configure_server()?;
let endpoint = quinn::Endpoint::server(config, "127.0.0.1:0".parse().unwrap())?;
let local_addr = endpoint.local_addr()?;
let rpc_server = quic_rpc::transport::quinn::QuinnListener::new(endpoint)?;
Expand All @@ -121,8 +51,15 @@ impl Node {
async fn node_and_client() -> TestResult<(Node, BlobsClient, TempDir)> {
let testdir = tempfile::tempdir()?;
let (node, addr, key) = Node::new(testdir.path().join("blobs")).await?;
let client = make_client_endpoint("127.0.0.1:0".parse().unwrap(), &[key])?;
let client = QuinnConnector::new(client, addr, "localhost".to_string());
let client = quic_rpc::transport::quinn::make_client_endpoint(
"127.0.0.1:0".parse().unwrap(),
&[key.as_slice()],
)?;
let client = QuinnConnector::<iroh_blobs::rpc::proto::RpcService>::new(
client,
addr,
"localhost".to_string(),
);
let client = quic_rpc::RpcClient::<iroh_blobs::rpc::proto::RpcService, _>::new(client);
let client = iroh_blobs::rpc::client::blobs::Client::new(client);
Ok((node, client, testdir))
Expand Down
Loading