Quiche client sent message not received at the server side
⚓ Rust 📅 2026-04-21 👤 surdeus 👁️ 4I want to use quiche crate as message passing without its http layer. So I attempted to create a minimum working example by borrowing from its client.rs and server.rs. However, it is complicated that mixes up with mio event system that I am not familiar with. Thus I refactor by combining the quiche's example code plus the code produced by google, and the code is listed as below. I understand it is rubbish, but at least I have a start point.
The problem I encountered is the code gets complied, but the message sent from the client side looks like not received at the server side. The client merely prints Error:Done, which looks like no more data to process. I suppose my problem:
- What is the correct steps to perform handshake?
- What is the follow up steps (recv, send, and so on) until
connection.is_established()? - What steps to close to connection?
Thanks.
Env
Rust version: rustc 1.92.0 (ded5c06cf 2025-12-08)
Cargo.toml
[package]
name = "hello-world"
version = "0.1.0"
edition = "2024"
[dependencies]
quiche = "0.28.0"
[[bin]]
name = "client"
path = "src/bin/client.rs"
[[bin]]
name = "server"
path = "src/bin/server.rs"
src/bin/client.rs
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
config.set_application_protos(&[b"echo"])?; // Custom ALPN
config.set_max_idle_timeout(5000);
let socket = UdpSocket::bind("127.0.0.1:0")?;
let server_addr = "127.0.0.1:4433".parse()?;
let scid = quiche::ConnectionId::from_vec(vec![0x1; 16]);
let mut conn = quiche::connect(
Some("localhost"),
&scid,
socket.local_addr()?,
server_addr,
&mut config,
)?;
let mut out = [0; 1350];
let (write, send_info) = conn.send(&mut out)?;
socket.send_to(&out[..write], send_info.to)?;
let mut buf = [0; 65535];
loop {
match socket.recv_from(&mut buf) {
Ok((read, from)) => {
let recv_info = quiche::RecvInfo {
from,
to: socket.local_addr()?,
};
conn.recv(&mut buf[..read], recv_info)?;
},
Err(_) => break,
}
if conn.is_established() {
conn.stream_send(0, b"hello message!", true)?;
//break;
}
loop {
let (write, send_info) = match conn.send(&mut out) {
Ok(v) => v,
Err(quiche::Error::Done) => break,
Err(e) => return Err(e.into()),
};
socket.send_to(&out[..write], send_info.to)?;
}
}
Ok(())
}
src/bin/server.rs
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut buf = [0; 65535];
let mut out = [0; 65535];
let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
config.set_application_protos(&[b"echo"])?; // custom protocol
config.set_initial_max_data(10_000_000);
config.set_initial_max_stream_data_bidi_local(1_000_000);
config.set_initial_max_streams_bidi(100);
config.load_cert_chain_from_pem_file("cert.pem")?;
config.load_priv_key_from_pem_file("key.pem")?;
let socket = UdpSocket::bind("127.0.0.1:4433")?;
let mut conn: Option<quiche::Connection> = None;
loop {
let (read, from) = socket.recv_from(&mut buf)?;
let scid = quiche::ConnectionId::from_ref(&[0xba, 0xad, 0xbe, 0xef]);
if conn.is_none() {
conn = Some(quiche::accept(
&scid,
None,
socket.local_addr()?,
from,
&mut config,
)?);
}
if let Some(ref mut connection) = conn {
let recv_info = quiche::RecvInfo {
from,
to: socket.local_addr()?,
};
connection.recv(&mut buf[..read], recv_info)?;
if connection.is_established() {
for stream_id in connection.readable() {
let (read, _fin) = connection.stream_recv(stream_id, &mut buf)?;
// Echo back data
connection.stream_send(stream_id, &buf[..read], true)?;
}
}
loop {
let (write, _send_info) = match connection.send(&mut out) {
Ok(v) => v,
Err(quiche::Error::Done) => break,
Err(e) => {
return Err(e.into());
}
};
socket.send_to(&out[..write], from)?;
}
}
}
}
2 posts - 2 participants
🏷️ Rust_feed