Commit bd529c4c authored by Matt Joras's avatar Matt Joras Committed by Facebook GitHub Bot

Allow disabling of IPV6_ONLY for AsyncUDPSocket

Summary: It's useful to be able to use the v4-mapped addresses sometimes.

Reviewed By: avasylev

Differential Revision: D24371807

fbshipit-source-id: 74fe13fa4bef9c77cc51a18137559facda9bdbeb
parent 505affdc
......@@ -94,7 +94,7 @@ AsyncUDPSocket::~AsyncUDPSocket() {
}
}
void AsyncUDPSocket::init(sa_family_t family) {
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()) {
......@@ -184,9 +184,8 @@ void AsyncUDPSocket::init(sa_family_t family) {
}
}
// If we're using IPv6, make sure we don't accept V4-mapped connections
if (family == AF_INET6) {
int flag = 1;
int flag = static_cast<int>(bindOptions.bindV6Only);
if (netops::setsockopt(
socket, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag))) {
throw AsyncSocketException(
......@@ -203,8 +202,10 @@ void AsyncUDPSocket::init(sa_family_t family) {
EventHandler::changeHandlerFD(fd_);
}
void AsyncUDPSocket::bind(const folly::SocketAddress& address) {
init(address.getFamily());
void AsyncUDPSocket::bind(
const folly::SocketAddress& address,
BindOptions bindOptions) {
init(address.getFamily(), bindOptions);
// bind to the address
sockaddr_storage addrStorage;
......@@ -227,7 +228,7 @@ void AsyncUDPSocket::bind(const folly::SocketAddress& address) {
void AsyncUDPSocket::connect(const folly::SocketAddress& address) {
// not bound yet
if (fd_ == NetworkSocket()) {
init(address.getFamily());
init(address.getFamily(), BindOptions());
}
sockaddr_storage addrStorage;
......
......@@ -160,13 +160,24 @@ class AsyncUDPSocket : public EventHandler {
return localAddress_;
}
/**
* Contains options to pass to bind.
*/
struct BindOptions {
constexpr BindOptions() noexcept {}
// Whether IPV6_ONLY should be set on the socket.
bool bindV6Only{true};
};
/**
* Bind the socket to the following address. If port is not
* set in the `address` an ephemeral port is chosen and you can
* use `address()` method above to get it after this method successfully
* returns.
* returns. The parameter BindOptions contains parameters for the bind.
*/
virtual void bind(const folly::SocketAddress& address);
virtual void bind(
const folly::SocketAddress& address,
BindOptions options = BindOptions());
/**
* Connects the UDP socket to a remote destination address provided in
......@@ -475,7 +486,7 @@ class AsyncUDPSocket : public EventHandler {
AsyncUDPSocket(const AsyncUDPSocket&) = delete;
AsyncUDPSocket& operator=(const AsyncUDPSocket&) = delete;
void init(sa_family_t family);
void init(sa_family_t family, BindOptions bindOptions);
// EventHandler
void handlerReady(uint16_t events) noexcept override;
......
......@@ -27,7 +27,9 @@ struct MockAsyncUDPSocket : public AsyncUDPSocket {
~MockAsyncUDPSocket() override {}
MOCK_CONST_METHOD0(address, const SocketAddress&());
MOCK_METHOD1(bind, void(const SocketAddress&));
MOCK_METHOD2(
bind,
void(const SocketAddress&, AsyncUDPSocket::BindOptions bindOptions));
MOCK_METHOD2(setFD, void(NetworkSocket, AsyncUDPSocket::FDOwnership));
MOCK_METHOD2(
write,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment