HTTPSession::newExTransaction(
    HTTPTransaction::Handler* handler,
    HTTPCodec::StreamID controlStream,
    bool unidirectional) noexcept {
  CHECK(handler && controlStream > 0);
  auto eSettings = codec_->getEgressSettings();
  if (!eSettings || !eSettings->getSetting(SettingsId::ENABLE_EX_HEADERS, 0)) {
    LOG(ERROR) << getCodecProtocolString(codec_->getProtocol())
               << " does not support ExTransaction";
    return nullptr;
  }
  if (draining_ || (outgoingStreams_ >= maxConcurrentOutgoingStreamsRemote_)) {
    LOG(ERROR) << "cannot support any more transactions in " << *this;
    return nullptr;
  }

  DCHECK(started_);
  HTTPTransaction* txn =
    createTransaction(codec_->createStream(),
                      HTTPCodec::NoStream,
                      HTTPCodec::ExAttributes(controlStream, unidirectional));
  if (!txn) {
    return nullptr;
  }

  DestructorGuard dg(this);
  txn->setHandler(handler);
  setNewTransactionPauseState(txn->getID());
  return txn;
}
HTTPSession::newExTransaction(
    HTTPTransaction::Handler* handler,
    HTTPCodec::StreamID controlStream,
    bool unidirectional) noexcept {
  CHECK(handler && controlStream > 0);
  auto eSettings = codec_->getEgressSettings();
  if (!eSettings || !eSettings->getSetting(SettingsId::ENABLE_EX_HEADERS, 0)) {
    LOG(ERROR) << getCodecProtocolString(codec_->getProtocol())
               << " does not support ExTransaction";
    return nullptr;
  }
  if (draining_ || (outgoingStreams_ >= maxConcurrentOutgoingStreamsRemote_)) {
    LOG(ERROR) << "cannot support any more transactions in " << *this;
    return nullptr;
  }

  DCHECK(started_);
  HTTPTransaction* txn =
    createTransaction(codec_->createStream(),
                      HTTPCodec::NoStream,
                      HTTPCodec::ExAttributes(controlStream, unidirectional));
  if (!txn) {
    return nullptr;
  }

  DestructorGuard dg(this);
  txn->setHandler(handler);
  setNewTransactionPauseState(txn->getID());
  return txn;
}