quinn icon indicating copy to clipboard operation
quinn copied to clipboard

`SendStream::finish()` no longer errors when connection is closed

Open flub opened this issue 1 year ago • 8 comments

In Quinn 0.10 SendStream::finish() used to return an error if the connection was already closed. Now it still returns Ok(()).

Full example code at https://gist.github.com/flub/56450fb16ec7c93998e7feedcb5659a0 but here are the relevant server and client pieces:

The server accepts a uni-directional stream, reads some data so that we know both the server and client have opened the stream successfully. Then it closes the connection with a custom code.

After connecting, creating and writing to the stream the client waits for the stream to be closed by the remote. Now the client tries to call .finish(), which I would expect to error. However it returns Ok(()):

async fn run_server(endpoint: Endpoint) {
    println!(
        "[server] accepting: local_addr={}",
        endpoint.local_addr().unwrap()
    );
    let incoming = endpoint.accept().await.unwrap();
    let conn = incoming.await.unwrap();
    println!(
        "[server] connection accepted: addr={}",
        conn.remote_address()
    );
    println!("[server] accepting uni");
    let mut recv_stream = conn.accept_uni().await.unwrap();
    println!("[server] reading");
    let mut buf = [0u8; 5];
    recv_stream.read_exact(&mut buf).await.unwrap();
    println!("[server] closing");
    conn.close(7u8.into(), b"bye");
}

async fn run_client(endpoint: Endpoint, server_addr: SocketAddr) {
    println!(
        "[client] connecting: local_addr={}",
        endpoint.local_addr().unwrap()
    );
    let conn = endpoint
        .connect(server_addr, "localhost")
        .unwrap()
        .await
        .unwrap();
    println!("[client] connected: addr={}", conn.remote_address());
    println!("[client] creating uni");
    let mut send_stream = conn.open_uni().await.unwrap();
    println!("[client] sending hello");
    send_stream.write_all(b"hello").await.unwrap();
    println!("[client] waiting for close");
    let err = conn.closed().await;
    println!("[client] closed: {err:?}");
    let finish = send_stream.finish();
    println!("[client] finish ret: {finish:?}");
}

Is there a conscious reason this behaviour changed? I was expecting finish to return an error at this point.

flub avatar Jul 19 '24 13:07 flub