void AsyncUDPSocket::bind(const folly::SocketAddress& address) { int socket = fsp::socket(address.getFamily(), SOCK_DGRAM, IPPROTO_UDP); if (socket == -1) { throw AsyncSocketException( AsyncSocketException::NOT_OPEN, "error creating async udp socket", errno); } auto g = folly::makeGuard([&] { ::close(socket); }); // put the socket in non-blocking mode int ret = fcntl(socket, F_SETFL, O_NONBLOCK); 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 (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 (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 (busyPollUs_ > 0) { #ifdef SO_BUSY_POLL // 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 (setsockopt(socket, SOL_SOCKET, SO_BUSY_POLL, &value, sizeof(value)) != 0) { throw AsyncSocketException( AsyncSocketException::NOT_OPEN, "failed to set SO_BUSY_POLL on the socket", errno); } #else /* SO_BUSY_POLL is not supported*/ throw AsyncSocketException( AsyncSocketException::NOT_OPEN, "SO_BUSY_POLL is not supported", errno); #endif } if (rcvBuf_ > 0) { // Set the size of the buffer for the received messages in rx_queues. int value = rcvBuf_; if (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 = rcvBuf_; if (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 we're using IPv6, make sure we don't accept V4-mapped connections if (address.getFamily() == AF_INET6) { int flag = 1; if (setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag))) { throw AsyncSocketException( AsyncSocketException::NOT_OPEN, "Failed to set IPV6_V6ONLY", errno); } } // bind to the address sockaddr_storage addrStorage; address.getAddress(&addrStorage); sockaddr* saddr = reinterpret_cast<sockaddr*>(&addrStorage); if (fsp::bind(socket, saddr, address.getActualSize()) != 0) { throw AsyncSocketException( AsyncSocketException::NOT_OPEN, "failed to bind the async udp socket for:" + address.describe(), errno); } // success g.dismiss(); fd_ = socket; ownership_ = FDOwnership::OWNS; // attach to EventHandler EventHandler::changeHandlerFD(fd_); if (address.getPort() != 0) { localAddress_ = address; } else { localAddress_.setFromLocalAddress(fd_); } }
void AsyncUDPSocket::bind(const folly::SocketAddress& address) { int socket = fsp::socket(address.getFamily(), SOCK_DGRAM, IPPROTO_UDP); if (socket == -1) { throw AsyncSocketException(AsyncSocketException::NOT_OPEN, "error creating async udp socket", errno); } auto g = folly::makeGuard([&] { ::close(socket); }); // put the socket in non-blocking mode int ret = fcntl(socket, F_SETFL, O_NONBLOCK); 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 (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 (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 we're using IPv6, make sure we don't accept V4-mapped connections if (address.getFamily() == AF_INET6) { int flag = 1; if (setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag))) { throw AsyncSocketException( AsyncSocketException::NOT_OPEN, "Failed to set IPV6_V6ONLY", errno); } } // bind to the address sockaddr_storage addrStorage; address.getAddress(&addrStorage); sockaddr* saddr = reinterpret_cast<sockaddr*>(&addrStorage); if (fsp::bind(socket, saddr, address.getActualSize()) != 0) { throw AsyncSocketException( AsyncSocketException::NOT_OPEN, "failed to bind the async udp socket for:" + address.describe(), errno); } // success g.dismiss(); fd_ = socket; ownership_ = FDOwnership::OWNS; // attach to EventHandler EventHandler::changeHandlerFD(fd_); if (address.getPort() != 0) { localAddress_ = address; } else { localAddress_.setFromLocalAddress(fd_); } }