HTTPSession::onHeadersComplete(HTTPCodec::StreamID streamID,
                               unique_ptr<HTTPMessage> msg) {
  // The codec's parser detected the end of an ingress message's
  // headers.
  VLOG(4) << "processing ingress headers complete for " << *this <<
      ", streamID=" << streamID;

  if (!codec_->isReusable()) {
    setCloseReason(ConnectionCloseReason::REQ_NOTREUSABLE);
  }

  if (infoCallback_) {
    infoCallback_->onIngressMessage(*this, *msg.get());
  }
  HTTPTransaction* txn = findTransaction(streamID);
  if (!txn) {
    invalidStream(streamID);
    return;
  }

  const char* sslCipher =
      transportInfo_.sslCipher ? transportInfo_.sslCipher->c_str() : nullptr;
  msg->setSecureInfo(transportInfo_.sslVersion, sslCipher);
  msg->setSecure(transportInfo_.secure);

  auto controlStreamID = txn->getControlStream();
  if (controlStreamID) {
    auto controlTxn = findTransaction(*controlStreamID);
    if (!controlTxn) {
      VLOG(2) << "txn=" << streamID << " with a broken controlTxn="
              << *controlStreamID << " " << *this;
      HTTPException ex(
          HTTPException::Direction::INGRESS_AND_EGRESS,
          folly::to<std::string>("broken controlTxn ", *controlStreamID));
      onError(streamID, ex, true);
      return;
    }

    // Call onExTransaction() only for requests.
    if (txn->isRemoteInitiated() && !controlTxn->onExTransaction(txn)) {
      VLOG(2) << "Failed to add exTxn=" << streamID
              << " to controlTxn=" << *controlStreamID << ", " << *this;
      HTTPException ex(
          HTTPException::Direction::INGRESS_AND_EGRESS,
          folly::to<std::string>("Fail to add exTxn ", streamID));
      ex.setCodecStatusCode(ErrorCode::REFUSED_STREAM);
      onError(streamID, ex, true);
      return;
    }
  } else {
    setupOnHeadersComplete(txn, msg.get());
  }

  // The txn may have already been aborted by the handler.
  // Verify that the txn still exists before ingress callbacks.
  txn = findTransaction(streamID);
  if (!txn) {
    return;
  }

  if (!txn->getHandler()) {
    txn->sendAbort();
    return;
  }

  // Tell the Transaction to start processing the message now
  // that the full ingress headers have arrived.
  txn->onIngressHeadersComplete(std::move(msg));
}
HTTPSession::onHeadersComplete(HTTPCodec::StreamID streamID,
                               unique_ptr<HTTPMessage> msg) {
   
   
  VLOG(4) << "processing ingress headers complete for " << *this <<
      ", streamID=" << streamID;

  if (!codec_->isReusable()) {
    setCloseReason(ConnectionCloseReason::REQ_NOTREUSABLE);
  }

  if (infoCallback_) {
    infoCallback_->onIngressMessage(*this, *msg.get());
  }
  HTTPTransaction* txn = findTransaction(streamID);
  if (!txn) {
    invalidStream(streamID);
    return;
  }

  const char* sslCipher =
      transportInfo_.sslCipher ? transportInfo_.sslCipher->c_str() : nullptr;
  msg->setSecureInfo(transportInfo_.sslVersion, sslCipher);
  msg->setSecure(transportInfo_.secure);

  auto controlStreamID = txn->getControlStream();
  if (controlStreamID) {
    auto controlTxn = findTransaction(*controlStreamID);
    if (!controlTxn) {
      VLOG(2) << "txn=" << streamID << " with a broken controlTxn="
              << *controlStreamID << " " << *this;
      HTTPException ex(
          HTTPException::Direction::INGRESS_AND_EGRESS,
          folly::to<std::string>("broken controlTxn ", *controlStreamID));
      onError(streamID, ex, true);
      return;
    }

     
    if (txn->isRemoteInitiated() && !controlTxn->onExTransaction(txn)) {
      VLOG(2) << "Failed to add exTxn=" << streamID
              << " to controlTxn=" << *controlStreamID << ", " << *this;
      HTTPException ex(
          HTTPException::Direction::INGRESS_AND_EGRESS,
          folly::to<std::string>("Fail to add exTxn ", streamID));
      ex.setCodecStatusCode(ErrorCode::REFUSED_STREAM);
      onError(streamID, ex, true);
      return;
    }
  } else {
    setupOnHeadersComplete(txn, msg.get());
  }

   
   
  txn = findTransaction(streamID);
  if (!txn) {
    return;
  }

  if (!txn->getHandler()) {
    txn->sendAbort();
    return;
  }

   
   
  txn->onIngressHeadersComplete(std::move(msg));
}