quinn-rs / quinn

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

Connection lost while sending data over insecure connection #1330

Closed vsawant1989 closed 2 years ago

vsawant1989 commented 2 years ago

Trying to send data using Bidirectional streaming over insecure connection

However connection is getting lost below is the outout while reading request from client

[client] connected: addr=127.0.0.1:5000 [server] connection accepted: addr=127.0.0.1:61510 Recieved "SERVERRESPONSE__" Status Ok(()) request: Err(Read(ConnectionLost(ApplicationClosed(ApplicationClose { error_code: 0, reason: b"done" }))))

//! This example demonstrates how to make a QUIC connection that ignores the server certificate.
//!
//! Checkout the `README.md` for guidance.

use std::{error::Error, fs, io, net::SocketAddr, sync::Arc};
use std::path::{Path, PathBuf};
use tracing::{error, info};

use quinn::{ClientConfig, Connection, Endpoint};

mod common;
use common::make_server_endpoint;
use proto::VarInt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // server and client are running on the same thread asynchronously
    let addr = "127.0.0.1:5000".parse().unwrap();
    tokio::spawn(run_server(addr));
    run_client(addr).await?;
    Ok(())
}

/// Runs a QUIC server bound to given address.
async fn run_server(addr: SocketAddr) {
    let (mut incoming, _server_cert) = make_server_endpoint(addr).unwrap();

    // accept a single connection
    let incoming_conn = incoming.next().await.unwrap();
    let mut new_conn = incoming_conn.await.unwrap();
    println!(
        "[server] connection accepted: addr={}",
        new_conn.connection.remote_address()
    );

        while let Some(Ok((mut send, recv))) = new_conn.bi_streams.next().await {
            // Because it is a bidirectional stream, we can both send and receive.
          //  println!("request: {:?}", recv.read_to_end(50).await);

            send.write_all(b"____SERVERRESPONSE______").await;
            send.finish().await;
            println!("request: {:?}", recv.read_to_end(50).await);

        }
}

async fn run_client(server_addr: SocketAddr) -> Result<(), Box<dyn Error>> {
    let client_cfg = configure_client();
    let mut endpoint = Endpoint::client("127.0.0.1:0".parse().unwrap())?;
    endpoint.set_default_client_config(client_cfg);

    // connect to server
    let quinn::NewConnection { connection, .. } = endpoint
        .connect(server_addr, "localhost")
        .unwrap()
        .await
        .unwrap();

    println!("[client] connected: addr={}", connection.remote_address());

    //println!("[client] Connection Stats={:?}", connection.stats());
    // Dropping handles allows the corresponding objects to automatically shut down
    let val=open_bidirectional_stream(connection.clone()).await;
    println!("Status {:?}",val);
    drop(connection);
    // Make sure the server has a chance to clean up
    endpoint.wait_idle().await;

    Ok(())
}

async fn open_bidirectional_stream(connection: Connection) -> anyhow::Result<()> {
    let (mut send, mut recv) = connection
        .open_bi()
        .await?;

    send.write_all(b"test").await;
    //send.finish().await?;

    let received = recv.read_to_end(100).await?;
    let s = String::from_utf8_lossy(received.as_slice());
    println!("Recieved {:?}",s);
  //  send.finish().await?;
    connection.close(0u32.into(), b"done");
    Ok(())
}

/// Dummy certificate verifier that treats any certificate as valid.
/// NOTE, such verification is vulnerable to MITM attacks, but convenient for testing.
struct SkipServerVerification;

impl SkipServerVerification {
    fn new() -> Arc<Self> {
        Arc::new(Self)
    }
}

impl rustls::client::ServerCertVerifier for SkipServerVerification {
    fn verify_server_cert(
        &self,
        _end_entity: &rustls::Certificate,
        _intermediates: &[rustls::Certificate],
        _server_name: &rustls::ServerName,
        _scts: &mut dyn Iterator<Item = &[u8]>,
        _ocsp_response: &[u8],
        _now: std::time::SystemTime,
    ) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
        Ok(rustls::client::ServerCertVerified::assertion())
    }
}

fn configure_client() -> ClientConfig {

    let crypto = rustls::ClientConfig::builder()
        .with_safe_defaults()
        .with_custom_certificate_verifier(SkipServerVerification::new())
        .with_no_client_auth();

   ClientConfig::new(Arc::new(crypto))
}
Ralith commented 2 years ago

The connection is lost because you're closing it. You can tell because the error is ApplicationClosed and includes the "done" message you passed in.

Ralith commented 2 years ago

Closing for lack of evidence of a bug.