void AsyncMcClientImpl::attemptConnection()

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);
      }
    }
  });
}