in mcrouter/lib/network/AsyncMcClientImpl.cpp [344:429]
void AsyncMcClientImpl::attemptConnection() {
// We may use a lot of stack memory (e.g. hostname resolution) or some
// expensive SSL code. This should be always executed on main context.
folly::fibers::runInMainContext([this] {
assert(connectionState_ == ConnectionState::Down);
connectionState_ = ConnectionState::Connecting;
pendingGoAwayReply_ = false;
auto expectedSocket = createSocket(eventBase_, connectionOptions_);
if (expectedSocket.hasError()) {
connectErr(expectedSocket.error());
return;
}
socket_ = std::move(expectedSocket).value();
auto expectedSocketAddress = getSocketAddress(connectionOptions_);
if (expectedSocketAddress.hasError()) {
const auto& ex = expectedSocketAddress.error();
LOG_FAILURE(
"AsyncMcClient", failure::Category::kBadEnvironment, "{}", ex.what());
connectErr(ex);
return;
}
folly::SocketAddress address = std::move(expectedSocketAddress).value();
socket_->setSendTimeout(connectionOptions_.writeTimeout.count());
const auto mech = connectionOptions_.accessPoint->getSecurityMech();
auto socketOptions = createSocketOptions(address, connectionOptions_);
if ((isAsyncSSLSocketMech(mech)) &&
connectionOptions_.securityOpts.sslHandshakeOffload) {
// we keep ourself alive during connection.
auto self = selfPtr_.lock();
auto sslSocket = socket_->getUnderlyingTransport<folly::AsyncSSLSocket>();
socket_.release();
folly::AsyncSSLSocket::UniquePtr sslSockPtr(sslSocket);
// offload the handshake
connectSSLSocketWithAuxIO(
std::move(sslSockPtr),
std::move(address),
connectionOptions_.connectTimeout.count(),
std::move(socketOptions))
.thenValue([self](folly::AsyncSocket::UniquePtr socket) {
CHECK(self->eventBase_.isInEventBaseThread());
if (self->isAborting_) {
// closeNow was called before we connected, so we need to fail
folly::AsyncSocketException ex(
folly::AsyncSocketException::INVALID_STATE,
"Client closed before connect completed");
self->connectErr(ex);
self->isAborting_ = false;
} else {
self->socket_ = std::move(socket);
self->connectSuccess();
}
})
.thenError(
folly::tag_t<folly::AsyncSocketException>{},
[self](const folly::AsyncSocketException& ex) {
CHECK(self->eventBase_.isInEventBaseThread());
self->connectErr(ex);
// handle the case where the client was aborting mid connect
if (self->isAborting_) {
self->isAborting_ = false;
}
});
} else {
// connect inline on the current evb
if (mech == SecurityMech::TLS13_FIZZ) {
auto fizzClient = socket_->getUnderlyingTransport<McFizzClient>();
fizzClient->connect(
this,
address,
connectionOptions_.connectTimeout.count(),
socketOptions);
} else {
auto asyncSock = socket_->getUnderlyingTransport<folly::AsyncSocket>();
asyncSock->connect(
this,
address,
connectionOptions_.connectTimeout.count(),
socketOptions);
}
}
});
}