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

#1

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!

#2

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?

#3

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…

#4

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

#5

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
#6

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