I am trying to figure out how to run Quinn at a very basic level before trying to go any further.
I finally have something that works after a lot of headpounding and digging around due to nuances in rustls and such. I did search for answers, but I'm not particularly good at that. If there is a resource I missed and should have looked at before posting, I will be happy to look at it if you point me in the right direction.
Code is pasted at the bottom. The questions glaring for me are:
-
When I run it and I run
top
on Linux it shows a cpu at 100. This seems to be related to the loop for the listener spawned. Is this normal? It certainly seems like it shouldn't be and I am thinking there must be a detail I'm missing that would prevent that. -
If the client doesn't have the listening loop, the sendstream does not seem to be sent and the connection is immediately closed. This seems strange to me since the listening loop isn't started until the message should have already been send and finished.
Comments welcome on any of the code below!!
I know there are a lot of unwraps, I handle errors after I have it working. I know it's a bad practice
Also, I am intending on doing mTLS which is why they are both servers, but the client has client config.
[tokio::main]
async fn main()->Result<(),Box<dyn std::error::Error>> {
let client_cert = rcgen::generate_simple_self_signed(vec!["localhost".to_string()]).unwrap();
let server_cert = rcgen::generate_simple_self_signed(vec!["localhost".to_string()]).unwrap();
let c = client_cert.cert.der().to_owned().clone();
let s = server_cert.cert.der().to_owned().clone();
let mut roots = RootCertStore::empty();
roots.add(CertificateDer::from(client_cert.cert)).unwrap();
roots.add(CertificateDer::from(server_cert.cert)).unwrap();
let roots = Arc::new(roots);
let roots_clone = roots.clone();
let server = tokio::spawn(
async move {
let roots = Arc::clone(&roots);
let server_addr = "127.0.0.1:7897".parse::<SocketAddr>().unwrap();
let cert_der = s;
let key = PrivatePkcs8KeyDer::from(server_cert.key_pair.serialize_der());
let config = ServerConfig::with_single_cert(vec![cert_der], key.into()).unwrap();
let endpoint = Endpoint::server(config, server_addr).unwrap();
let (mut s,mut r)= match endpoint.accept().await{
Some(a)=>{
match a.await{
Ok(a)=>{
match a.accept_bi().await{
Ok(mut a)=>{
a},
Err(e)=>{
panic!("stream error: {e}")}
}},
Err(e)=>{panic!("connection error: {e}")}
}
},
None=>{panic!("accept server: panic on accept");}
};
let rx_handle = tokio::spawn(async move {
let data = r.read_to_end(128).await.unwrap();
println!("{}", String::from_utf8(data).unwrap());
});
rx_handle.await.unwrap();
});
let client = tokio::spawn(async move {
let roots=Arc::clone(&roots_clone);
static SERVER_NAME: &str = "localhost";
let server_addr = "127.0.0.1:7899".parse::<SocketAddr>().unwrap();
let cert_der = CertificateDer::from(c);
let cder = cert_der.clone();
let key = PrivatePkcs8KeyDer::from(client_cert.key_pair.serialize_der());
let config = ServerConfig::with_single_cert(vec![cert_der], key.clone_key().into()).unwrap();
let mut endpoint = Endpoint::server(config, server_addr).unwrap();
let q_client = client_config(key.clone_key(), cder.clone(),roots).unwrap();
endpoint.set_default_client_config(q_client);
let c = endpoint.connect("127.0.0.1:7897".parse().unwrap(), "localhost");
match c{
Ok(mut a)=>{
//println!("data: {:?}",a.clone().await);
let (mut s,mut r) = match a.await{
Ok(b)=>{b.open_bi().await.unwrap()},
Err(e)=>{panic!("{e}")}
};
let _wr = s.write_all(b"testing").await.unwrap();
let _wr_f = s.finish().unwrap();
let listening = tokio::spawn(async move{
loop{
let mut buf:Vec<u8> =Vec::new();
r.read(&mut buf).await;
if !buf.is_empty(){println!("{:?}",buf);}
}
});
listening.await;
},
Err(e)=>{println!("{e}")}
}
});
let _ = client.await;
let _ = server.await;
Ok(())
}
pub fn client_config(key: PrivatePkcs8KeyDer<'static>, cert: CertificateDer<'static>,roots: Arc<RootCertStore>)->anyhow::Result<ClientConfig>{
let builder = rustls::ClientConfig::builder_with_provider(rustls::crypto::ring::default_provider().into())
.with_protocol_versions(&[&rustls::version::TLS13])
.unwrap();
let roots = roots.clone();
let r_config = builder.with_root_certificates(roots).with_client_auth_cert(vec![cert], key.clone_key().into()).unwrap();
let config = quinn::crypto::rustls::QuicClientConfig::try_from(r_config).unwrap();
Ok(quinn::ClientConfig::new(Arc::new(config)))
}