Query whether a `UdpSocket` has been `connect`-ed

First of all, sorry if I'm missing something obvious. I'm trying to figure out if an instance of a UdpSocket has been connect-ed or not (and in extension, to which ip+port).

My use case is that I have a thread that's responsible for listening for packets and responding to them. Prior to starting this thread, I might or might not have been told from which ip+port the packets will originate from. So my setup code looks something like this:

let socket = UdpSocket::bind("0.0.0.0:0").unwrap();

if was_told_remote_port {
  socket.connect((remote_addr, remote_port)).unwrap();
}

spawn_worker_with_socket(socket);

If we weren't told the port, we'll simply wait for the first packet, and then connect to that port. The worker thus looks something like this:

// FIXME: look if the socket is already connected
let mut connected = false;

loop {
  let mut buffer: [u8; 200] = [0; 200];

  if connected {
    socket.recv(&mut buffer).unwrap();
  } else {
    let (_, sender) = socket.recv_from(&mut buffer).unwrap();
    socket.connect(sender).unwrap();
    connected = true;
  }

  // ...
}

Now, in this simplified example, it would be really easy to just pass was_told_remote_port to the worker. But in my large codebase, it would help a lot if this state could be accessed directly from the socket since it must be stored there already somehow (right?).

Thanks!

You can call recv and if the socket wasn't connected, you'll get an io::Error with io::ErrorKind::NotConnected. Then you can follow up with a call to recv_from.

Edit: actually, this might only work for send, not recv.

Instead of storing a UdpSocket, can you store a (UdpSocket, bool) (or Cell<bool> or AtomicBool) instead?

Thanks for taking a look!

This is probably the way I'll have to go...

Would be interesting to look at what connect is doing under the hood, maybe there is a way to add this functionality...

These network primitives are usually mostly just thin wrappers around whatever your OS gives you. So connect calls the connect call.

For TCP, this is available using peer_addr(). The underlying system call also works on UDP sockets (and gives you ENOTCONN if not connected). Logically, since connect() exists, peer_addr() should also be supported there.

Feel free to open an issue...

2 Likes

Working on getting this in now :raised_hands:

Issue: https://github.com/rust-lang/rust/issues/59104
Pull Request: https://github.com/rust-lang/rust/pull/59106
Tracking Issue: https://github.com/rust-lang/rust/issues/59127

1 Like