quinn-rs / quinn

Async-friendly QUIC implementation in Rust
Apache License 2.0
3.85k stars 394 forks source link

Whether to build ServerConfig without cert #1300

Closed YeautyYE closed 2 years ago

YeautyYE commented 2 years ago

My client and server are deployed on different servers, and I don't want to be self_signed cert.

YeautyYE commented 2 years ago

if deployed on different servers, client execute connecting.await get TimedOut

if deployed on same servers, everything is fine

YeautyYE commented 2 years ago

ConfigBuilder.with_single_cert() not found

djc commented 2 years ago

Both this and your previous issue are short on context. If you want help you'll have to post some code samples of what you are doing and exact error messages or descriptions of what's happening and why it deviates for your expectations.

From the issue description, it also appears you are having an issue with the rustls configuration rather than with Quinn itself; in which case, this is the wrong repository to report an error to.

YeautyYE commented 2 years ago
use std::error::Error;
use std::sync::Arc;
use futures_util::StreamExt;
use quinn::{Connecting, Connection, Endpoint, ServerConfig};

#[tokio::main]
async fn main() {
    let bind_addr = "0.0.0.0:65432".parse().unwrap();

    let (server_config, server_cert) = configure_server().unwrap();
    let (_endpoint, mut incoming) = Endpoint::server(server_config, bind_addr).unwrap();

    while let incoming_conn = incoming.next().await {
        if incoming_conn.is_none() {
            continue;
        }
        let incoming_conn = incoming_conn.unwrap();

        tokio::spawn(accept_connection(incoming_conn));
    }
}

async fn accept_connection(incoming_conn: Connecting) {
    let new_conn = incoming_conn.await;
    let new_conn = match new_conn {
        Ok(new_conn) => new_conn,
        Err(_) => {
            return;
        }
    };
    handle_connection(new_conn.connection).await;
}

async fn handle_connection(connection: Connection) {
    println!("connection accepted: addr: {}", connection.remote_address());

    let mut send = connection.open_uni().await.unwrap();

    let mut interval = tokio::time::interval(tokio::time::Duration::from_millis(1000));
    loop {
        interval.tick().await;
        println!("write_chunk");
        let result = send.write_chunk("test".into()).await;
        match result {
            Ok(_) => (),
            Err(e) => {
                println!("error: {:?}", e);
                break;
            }
        }
    }
}

fn configure_server() -> Result<(ServerConfig, Vec<u8>), Box<dyn Error>> {
    let cert_der = include_bytes!("../../common/resource/cert/cert.pem").to_vec();
    let priv_key = include_bytes!("../../common/resource/cert/privkey.pem").to_vec();
    let priv_key = rustls::PrivateKey(priv_key);
    let cert_chain = vec![rustls::Certificate(cert_der.clone())];

    let mut server_config = ServerConfig::with_single_cert(cert_chain, priv_key)?;
    Arc::get_mut(&mut server_config.transport)
        .unwrap()
        .max_concurrent_uni_streams(0_u8.into());

    Ok((server_config, cert_der))
}

#[cfg(test)]
mod tests {
    use std::fs::OpenOptions;
    use std::io::Write;
    use std::ops::Deref;
    use std::sync::Arc;
    use futures_util::StreamExt;
    use quinn::{ClientConfig, Endpoint};
    use quinn::RecvStream;

    #[tokio::test]
    #[ignore]
    async fn test_client() {
        let server_addr = "127.0.0.1:65432".parse().unwrap();

        let client_cfg = configure_client();
        let mut endpoint = Endpoint::client("127.0.0.1:0".parse().unwrap()).unwrap();
        endpoint.set_default_client_config(client_cfg);

        let connecting = endpoint.connect(server_addr, "yeauty").unwrap();
        let mut new_conn = connecting.await.unwrap();
        loop {
            let message = new_conn.uni_streams.next().await;
            match message {
                Some(recv) => {
                    let mut recv = recv.unwrap();
                    let received_chunk = recv.read_chunk(20 * 1024 * 1024, false).await;
                    let received_chunk = received_chunk.unwrap().unwrap();
                    println!("msg : {:?}", String::from_utf8(received_chunk.bytes.to_vec()));
                }
                None => {
                    println!("received None");
                }
            }
        }
    }

    fn configure_client() -> ClientConfig {
        let mut certs = rustls::RootCertStore::empty();
        certs.add(&rustls::Certificate(include_bytes!("../../common/resource/cert/cert.pem").to_vec())).unwrap();

        let mut crypto = rustls::ClientConfig::builder()
            .with_safe_defaults()
            .with_root_certificates(certs)
            .with_no_client_auth();
        ClientConfig::new(Arc::new(crypto))
    }
}

when server code run on server , client get TimeOut when server code run on local , client get ApplicationClosed(ApplicationClose { error_code: 0, reason: b"" }) in the second cycle

djc commented 2 years ago

Why do you think the timeout is due to Quinn instead of a network issue?

YeautyYE commented 2 years ago

I used wireshark to capture packets and found that UDP requests were not sent when execute endpoint.connect(). But I use 'echo' "Hello World\!" | nc - 4 u my - IP 65432 normal udp requests My IDE is CLion and my operating system is macOS

YeautyYE commented 2 years ago

Sorry, my client address is not set to 0.0.0.0. The correct code looks like this 'let mut endpoint = endpoint ::client("0.0.0.0:0".parse().unwrap()).unwrap(); `

YeautyYE commented 2 years ago

If I use FramedRead, can I set it to unordered?

Ralith commented 2 years ago

ConfigBuilder.with_single_cert() not found

The code you pasted doesn't contain any references to ConfigBuilder. Did you mean ServerConfigBuilder? What does "not found" mean? What is the exact, complete error message?

The correct code looks like this

Does that mean the issue is resolved? If so, please close it.

If I use FramedRead, can I set it to unordered?

No, that would not make sense.