net: add synchronous, role-neutral net.BoundHandle#63951
Conversation
|
Review requested:
|
5db58e1 to
9da4d5f
Compare
Signed-off-by: Guy Bedford <guybedford@gmail.com>
9da4d5f to
887d772
Compare
|
I don't understand why this is needed |
Ethan-Arrowood
left a comment
There was a problem hiding this comment.
I appreciate this change. net.BoundHandle lets you reserve a TCP port and actually hold onto it until you're ready to use it. This simplifies utility modules like [get-port](https://npmx.dev/package/get-port) that are susceptible to TOCTOU (Time-of-Check to Time-of-Use) race conditions. Of course, it doesn't solve the problem perfectly since this is in-process only, but I think it's a great improvement.
As a follow-up, it'd be great if BoundHandle could optionally expose its underlying file descriptor, so the reservation can be handed to another process (Unix-only, since this relies on POSIX fd passing). That would extend the same race-free guarantee across a process boundary.
|
Thanks for clarifying the use case here @Ethan-Arrowood. I've gone ahead and added a commit to expose the |
Add net.BoundHandle, a synchronous TCP bind primitive that mirrors POSIX bind(2): the socket is bound to a local address but stays role-agnostic until it is adopted as a server (server.listen()) or a client (new net.Socket({ handle }) followed by connect()).
Constructing a net.BoundHandle binds inline via the existing uv_tcp_bind() path, so the kernel-assigned address (including the ephemeral port when port is 0) is available immediately via boundHandle.address(), and bind errors throw synchronously.
Adoption transfers ownership of the underlying handle; afterwards address() and close() throw ERR_SOCKET_HANDLE_ADOPTED. An un-adopted handle is released with close() or via Symbol.dispose (using).
The handle is passed in-process rather than as a file descriptor, so it also works on Windows.