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() { ...@@ -94,7 +94,7 @@ AsyncUDPSocket::~AsyncUDPSocket() {
} }
} }
void AsyncUDPSocket::init(sa_family_t family) { void AsyncUDPSocket::init(sa_family_t family, BindOptions bindOptions) {
NetworkSocket socket = NetworkSocket socket =
netops::socket(family, SOCK_DGRAM, family != AF_UNIX ? IPPROTO_UDP : 0); netops::socket(family, SOCK_DGRAM, family != AF_UNIX ? IPPROTO_UDP : 0);
if (socket == NetworkSocket()) { if (socket == NetworkSocket()) {
...@@ -184,9 +184,8 @@ void AsyncUDPSocket::init(sa_family_t family) { ...@@ -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) { if (family == AF_INET6) {
int flag = 1; int flag = static_cast<int>(bindOptions.bindV6Only);
if (netops::setsockopt( if (netops::setsockopt(
socket, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag))) { socket, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag))) {
throw AsyncSocketException( throw AsyncSocketException(
...@@ -203,8 +202,10 @@ void AsyncUDPSocket::init(sa_family_t family) { ...@@ -203,8 +202,10 @@ void AsyncUDPSocket::init(sa_family_t family) {
EventHandler::changeHandlerFD(fd_); EventHandler::changeHandlerFD(fd_);
} }
void AsyncUDPSocket::bind(const folly::SocketAddress& address) { void AsyncUDPSocket::bind(
init(address.getFamily()); const folly::SocketAddress& address,
BindOptions bindOptions) {
init(address.getFamily(), bindOptions);
// bind to the address // bind to the address
sockaddr_storage addrStorage; sockaddr_storage addrStorage;
...@@ -227,7 +228,7 @@ void AsyncUDPSocket::bind(const folly::SocketAddress& address) { ...@@ -227,7 +228,7 @@ void AsyncUDPSocket::bind(const folly::SocketAddress& address) {
void AsyncUDPSocket::connect(const folly::SocketAddress& address) { void AsyncUDPSocket::connect(const folly::SocketAddress& address) {
// not bound yet // not bound yet
if (fd_ == NetworkSocket()) { if (fd_ == NetworkSocket()) {
init(address.getFamily()); init(address.getFamily(), BindOptions());
} }
sockaddr_storage addrStorage; sockaddr_storage addrStorage;
......
...@@ -160,13 +160,24 @@ class AsyncUDPSocket : public EventHandler { ...@@ -160,13 +160,24 @@ class AsyncUDPSocket : public EventHandler {
return localAddress_; 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 * Bind the socket to the following address. If port is not
* set in the `address` an ephemeral port is chosen and you can * set in the `address` an ephemeral port is chosen and you can
* use `address()` method above to get it after this method successfully * 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 * Connects the UDP socket to a remote destination address provided in
...@@ -475,7 +486,7 @@ class AsyncUDPSocket : public EventHandler { ...@@ -475,7 +486,7 @@ class AsyncUDPSocket : public EventHandler {
AsyncUDPSocket(const AsyncUDPSocket&) = delete; AsyncUDPSocket(const AsyncUDPSocket&) = delete;
AsyncUDPSocket& operator=(const AsyncUDPSocket&) = delete; AsyncUDPSocket& operator=(const AsyncUDPSocket&) = delete;
void init(sa_family_t family); void init(sa_family_t family, BindOptions bindOptions);
// EventHandler // EventHandler
void handlerReady(uint16_t events) noexcept override; void handlerReady(uint16_t events) noexcept override;
......
...@@ -27,7 +27,9 @@ struct MockAsyncUDPSocket : public AsyncUDPSocket { ...@@ -27,7 +27,9 @@ struct MockAsyncUDPSocket : public AsyncUDPSocket {
~MockAsyncUDPSocket() override {} ~MockAsyncUDPSocket() override {}
MOCK_CONST_METHOD0(address, const SocketAddress&()); 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(setFD, void(NetworkSocket, AsyncUDPSocket::FDOwnership));
MOCK_METHOD2( MOCK_METHOD2(
write, 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