quinn-rs / quinn

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

Send/receive datagrams help needed. #1700

Closed karthikgbbristol closed 6 months ago

karthikgbbristol commented 1 year ago

Hi, I am new to both Rust and QUIC. So I might be doing something wrong.

I have two asyc tasks after creating a QUIC Connection as follows,


 let quic_conn_write = tunnel.conn.as_ref().expect("Expected a valid QUIC connection").clone();
        task::spawn(async move {
            let mut buffer = vec![0u8; 1500]; // MTU size
            loop {
                let res = {
                    unsafe {
                        ReadFromTun(tun_tap_device.tun_id, buffer.as_mut_ptr(), buffer.len() as c_int)
                    }
                };

                if res.result > 0 {
                    let data_to_send = Bytes::copy_from_slice(&buffer[..res.result as usize]);
                    if let Err(e) = quic_conn_write.send_datagram(data_to_send) {
                        eprintln!("Failed sending QUIC datagram: {:?}", e);
                    }
                }
            }
        });
 let quic_conn_read = tunnel.conn.as_ref().expect("Expected a valid QUIC connection").clone();

      // Spawn task for reading from QUIC and writing to tunnel.
      task::spawn(async move {
          loop {
              match quic_conn_read.read_datagram().await {
                  Ok(datagram) => {
                      // Get the slice of bytes from the datagram
                      let byte_slice = datagram.as_ref();
                      println!("Received QUIC datagram with length: {}", byte_slice.len());
                      // Call WriteToTun using the pointer to the byte slice, and its length
                      let res = unsafe { WriteToTun(tun_tap_device.tun_id, byte_slice.as_ptr() as *mut _, byte_slice.len() as c_int) };
                      if res.result < 0 {
                          eprintln!("Failed writing to TUN");
                      }
                  }
                  Err(e) => eprintln!("Failed receiving QUIC datagram: {:?}", e),
              }
          }
      });

The first task reads from a TUNTAP device and writes a datagram on the QUIC Connection.

The second task reads from QUIC and writes to the TUN device.

I can see that the first task works, the second task doesn't. Can I use Datagrams in this way?

djc commented 1 year ago

What do you mean by "doesn't work"? What's the failure mode you're observing?

egimbernat commented 1 year ago

Hi @djc, to give more information on this. We observe that when creating a connection as a client, the connection can send a datagram but never receives nor returns from conn.Accept() method. It seems that the client is only unidirectional. What should be the correct way of having bidirectional datagram communication?

djc commented 1 year ago

I don't see anything obviously wrong with your code. I don't know what you mean by "unidirectional" -- datagrams have one obvious direction, and there's not much else to them.

Ralith commented 6 months ago

Closing as stale. Feel free to reopen with additional details if you're still having trouble.