Skip to content

Commit

Permalink
add IP_BIND_ADDRESS_NO_PORT support to async socket
Browse files Browse the repository at this point in the history
Summary: The existing code enables the socket option `SO_REUSEADDR` when a bind address is specified.  This diff adds the usage of `IP_BIND_ADDRESS_NO_PORT` when the bind address is specified with port 0 (wildcard).

Reviewed By: dmm-fb

Differential Revision: D60170575

fbshipit-source-id: a629a3975adaed1acd875324c7d9ffe83463872f
  • Loading branch information
jdq authored and facebook-github-bot committed Aug 5, 2024
1 parent 5cf36dc commit 9e71a72
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 16 deletions.
39 changes: 31 additions & 8 deletions folly/io/async/AsyncIoUringSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,36 @@ void AsyncIoUringSocket::connect(
auto saddr = reinterpret_cast<sockaddr*>(&addrStorage);

int one = 1;
if (setSockOpt(SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
auto errnoCopy = errno;
callback->connectErr(AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to setsockopt prior to bind on " + bindAddr.describe(),
errnoCopy));
return;
#if defined(IP_BIND_ADDRESS_NO_PORT) && !FOLLY_MOBILE
// If the any port is specified with a non-any address this is typically
// a client socket. However, calling bind before connect without
// IP_BIND_ADDRESS_NO_PORT forces the OS to find a unique port relying
// on only the local tuple. This limits the range of available ephemeral
// ports. Using the IP_BIND_ADDRESS_NO_PORT delays assigning a port until
// connect expanding the available port range.
if (bindAddr.getPort() == 0) {
if (setSockOpt(IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, &one, sizeof(one))) {
auto errnoCopy = errno;
callback->connectErr(AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to setsockopt IP_BIND_ADDRESS_NO_PORT prior to bind on " +
bindAddr.describe(),
errnoCopy));
return;
}
} else {
#else
{
#endif
if (setSockOpt(SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
auto errnoCopy = errno;
callback->connectErr(AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to setsockopt SO_REUSEADDR prior to bind on " +
bindAddr.describe(),
errnoCopy));
return;
}
}

bindAddr.getAddress(&addrStorage);
Expand All @@ -277,7 +300,7 @@ void AsyncIoUringSocket::connect(
auto errnoCopy = errno;
callback->connectErr(AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to bind to async socket: " + bindAddr.describe(),
"failed to bind to async io_uring socket: " + bindAddr.describe(),
errnoCopy));
return;
}
Expand Down
40 changes: 32 additions & 8 deletions folly/io/async/AsyncSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -982,14 +982,38 @@ void AsyncSocket::connect(
// bind the socket
if (bindAddr != anyAddress()) {
int one = 1;
if (netops_->setsockopt(
fd_, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
auto errnoCopy = errno;
doClose();
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to setsockopt prior to bind on " + bindAddr.describe(),
errnoCopy);
#if defined(IP_BIND_ADDRESS_NO_PORT) && !FOLLY_MOBILE
// If the any port is specified with a non-any address this is typically
// a client socket. However, calling bind before connect without
// IP_BIND_ADDRESS_NO_PORT forces the OS to find a unique port relying
// on only the local tuple. This limits the range of available ephemeral
// ports. Using the IP_BIND_ADDRESS_NO_PORT delays assigning a port until
// connect expanding the available port range.
if (bindAddr.getPort() == 0) {
if (netops_->setsockopt(
fd_, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, &one, sizeof(one))) {
auto errnoCopy = errno;
doClose();
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to setsockopt IP_BIND_ADDRESS_NO_PORT prior to bind on " +
bindAddr.describe(),
errnoCopy);
}
} else {
#else
{
#endif
if (netops_->setsockopt(
fd_, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
auto errnoCopy = errno;
doClose();
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to setsockopt SO_REUSEADDR prior to bind on " +
bindAddr.describe(),
errnoCopy);
}
}

bindAddr.getAddress(&addrStorage);
Expand Down

0 comments on commit 9e71a72

Please sign in to comment.