Commit b5e88664 authored by Dan Melnic's avatar Dan Melnic Committed by Facebook GitHub Bot

Add support for AsyncSocket connect bind to device

Summary:
Add support for AsyncSocket connect bind to device

(Note: this ignores all push blocking failures!)

Reviewed By: danobi

Differential Revision: D27784176

fbshipit-source-id: d7efe3ef59b26aa69552d5f8109f89457ee5fe66
parent fc32eee3
......@@ -721,9 +721,17 @@ void AsyncSSLSocket::connect(
const folly::SocketAddress& address,
int timeout,
const SocketOptionMap& options,
const folly::SocketAddress& bindAddr) noexcept {
const folly::SocketAddress& bindAddr,
const std::string& ifName) noexcept {
auto timeoutChrono = std::chrono::milliseconds(timeout);
connect(callback, address, timeoutChrono, timeoutChrono, options, bindAddr);
connect(
callback,
address,
timeoutChrono,
timeoutChrono,
options,
bindAddr,
ifName);
}
void AsyncSSLSocket::connect(
......@@ -732,7 +740,8 @@ void AsyncSSLSocket::connect(
std::chrono::milliseconds connectTimeout,
std::chrono::milliseconds totalConnectTimeout,
const SocketOptionMap& options,
const folly::SocketAddress& bindAddr) noexcept {
const folly::SocketAddress& bindAddr,
const std::string& ifName) noexcept {
assert(!server_);
assert(state_ == StateEnum::UNINIT);
assert(sslState_ == STATE_UNINIT || sslState_ == STATE_UNENCRYPTED);
......@@ -744,7 +753,12 @@ void AsyncSSLSocket::connect(
callback = allocatedConnectCallback_;
}
AsyncSocket::connect(
callback, address, int(connectTimeout.count()), options, bindAddr);
callback,
address,
int(connectTimeout.count()),
options,
bindAddr,
ifName);
}
void AsyncSSLSocket::cancelConnect() {
......
......@@ -432,7 +432,8 @@ class AsyncSSLSocket : public AsyncSocket {
const folly::SocketAddress& address,
int timeout = 0,
const SocketOptionMap& options = emptySocketOptionMap,
const folly::SocketAddress& bindAddr = anyAddress()) noexcept override;
const folly::SocketAddress& bindAddr = anyAddress(),
const std::string& ifName = "") noexcept override;
/**
* A variant of connect that allows the caller to specify
......@@ -455,7 +456,8 @@ class AsyncSSLSocket : public AsyncSocket {
std::chrono::milliseconds connectTimeout,
std::chrono::milliseconds totalConnectTimeout,
const SocketOptionMap& options = emptySocketOptionMap,
const folly::SocketAddress& bindAddr = anyAddress()) noexcept;
const folly::SocketAddress& bindAddr = anyAddress(),
const std::string& ifName = "") noexcept;
using AsyncSocket::connect;
......
......@@ -715,7 +715,8 @@ void AsyncSocket::connect(
const folly::SocketAddress& address,
int timeout,
const SocketOptionMap& options,
const folly::SocketAddress& bindAddr) noexcept {
const folly::SocketAddress& bindAddr,
const std::string& ifName) noexcept {
DestructorGuard dg(this);
eventBase_->dcheckIsInEventBaseThread();
......@@ -798,6 +799,26 @@ void AsyncSocket::connect(
VLOG(5) << "AsyncSocket::connect(this=" << this << ", evb=" << eventBase_
<< ", fd=" << fd_ << ", host=" << address.describe().c_str();
// bind the socket to the interface
#if defined(__linux__)
if (!ifName.empty() &&
netops_->setsockopt(
fd_,
SOL_SOCKET,
SO_BINDTODEVICE,
ifName.c_str(),
ifName.length())) {
auto errnoCopy = errno;
doClose();
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to bind to device: " + ifName,
errnoCopy);
}
#else
(void)ifName;
#endif
// bind the socket
if (bindAddr != anyAddress()) {
int one = 1;
......
......@@ -491,7 +491,8 @@ class AsyncSocket : public AsyncTransport {
const folly::SocketAddress& address,
int timeout = 0,
const SocketOptionMap& options = emptySocketOptionMap,
const folly::SocketAddress& bindAddr = anyAddress()) noexcept;
const folly::SocketAddress& bindAddr = anyAddress(),
const std::string& ifName = "") noexcept;
void connect(
ConnectCallback* callback,
......
......@@ -30,21 +30,23 @@ class MockAsyncSSLSocket : public AsyncSSLSocket {
bool deferSecurityNegotiation = false)
: AsyncSSLSocket(ctx, base, deferSecurityNegotiation) {}
MOCK_METHOD5(
MOCK_METHOD6(
connect_,
void(
AsyncSocket::ConnectCallback*,
const folly::SocketAddress&,
int,
const folly::SocketOptionMap&,
const folly::SocketAddress&));
const folly::SocketAddress&,
const std::string&));
void connect(
AsyncSocket::ConnectCallback* callback,
const folly::SocketAddress& address,
int timeout,
const folly::SocketOptionMap& options,
const folly::SocketAddress& bindAddr) noexcept override {
connect_(callback, address, timeout, options, bindAddr);
const folly::SocketAddress& bindAddr,
const std::string& ifName) noexcept override {
connect_(callback, address, timeout, options, bindAddr, ifName);
}
MOCK_CONST_METHOD1(getLocalAddress, void(folly::SocketAddress*));
......
......@@ -30,21 +30,23 @@ class MockAsyncSocket : public AsyncSocket {
explicit MockAsyncSocket(EventBase* base) : AsyncSocket(base) {}
MOCK_METHOD5(
MOCK_METHOD6(
connect_,
void(
AsyncSocket::ConnectCallback*,
const folly::SocketAddress&,
int,
const folly::SocketOptionMap&,
const folly::SocketAddress&));
const folly::SocketAddress&,
const std::string&));
void connect(
AsyncSocket::ConnectCallback* callback,
const folly::SocketAddress& address,
int timeout,
const folly::SocketOptionMap& options,
const folly::SocketAddress& bindAddr) noexcept override {
connect_(callback, address, timeout, options, bindAddr);
const folly::SocketAddress& bindAddr,
const std::string& ifName) noexcept override {
connect_(callback, address, timeout, options, bindAddr, ifName);
}
MOCK_CONST_METHOD1(getPeerAddress, void(folly::SocketAddress*));
......
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