in folly/io/async/AsyncUDPSocket.cpp [99:225]
void AsyncUDPSocket::init(sa_family_t family, BindOptions bindOptions) {
NetworkSocket socket =
netops::socket(family, SOCK_DGRAM, family != AF_UNIX ? IPPROTO_UDP : 0);
if (socket == NetworkSocket()) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"error creating async udp socket",
errno);
}
auto g = folly::makeGuard([&] { netops::close(socket); });
// put the socket in non-blocking mode
int ret = netops::set_socket_non_blocking(socket);
if (ret != 0) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to put socket in non-blocking mode",
errno);
}
if (reuseAddr_) {
// put the socket in reuse mode
int value = 1;
if (netops::setsockopt(
socket, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) != 0) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to put socket in reuse mode",
errno);
}
}
if (reusePort_) {
// put the socket in port reuse mode
int value = 1;
if (netops::setsockopt(
socket, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)) != 0) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to put socket in reuse_port mode",
errno);
}
}
if (freeBind_) {
int optname = 0;
#if defined(IP_FREEBIND)
optname = IP_FREEBIND;
#endif
if (!optname) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN, "IP_FREEBIND is not supported");
}
// put the socket in free bind mode
int value = 1;
if (netops::setsockopt(
socket, IPPROTO_IP, optname, &value, sizeof(value)) != 0) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to put socket in free bind mode",
errno);
}
}
if (busyPollUs_ > 0) {
int optname = 0;
#if defined(SO_BUSY_POLL)
optname = SO_BUSY_POLL;
#endif
if (!optname) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN, "SO_BUSY_POLL is not supported");
}
// Set busy_poll time in microseconds on the socket.
// It sets how long socket will be in busy_poll mode when no event occurs.
int value = busyPollUs_;
if (netops::setsockopt(
socket, SOL_SOCKET, optname, &value, sizeof(value)) != 0) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to set SO_BUSY_POLL on the socket",
errno);
}
}
if (rcvBuf_ > 0) {
// Set the size of the buffer for the received messages in rx_queues.
int value = rcvBuf_;
if (netops::setsockopt(
socket, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) != 0) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to set SO_RCVBUF on the socket",
errno);
}
}
if (sndBuf_ > 0) {
// Set the size of the buffer for the sent messages in tx_queues.
int value = sndBuf_;
if (netops::setsockopt(
socket, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) != 0) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to set SO_SNDBUF on the socket",
errno);
}
}
if (family == AF_INET6) {
int flag = static_cast<int>(bindOptions.bindV6Only);
if (netops::setsockopt(
socket, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag))) {
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN, "Failed to set IPV6_V6ONLY", errno);
}
}
// success
g.dismiss();
fd_ = socket;
ownership_ = FDOwnership::OWNS;
// attach to EventHandler
EventHandler::changeHandlerFD(fd_);
}