HTTPSession::onEgressMessageFinished(HTTPTransaction* txn, bool withRST) {
  // If the semantics of the protocol don't permit more messages
  // to be read or sent on this connection, close the socket in one or
  // more directions.
  CHECK(!transactions_.empty());

  if (infoCallback_) {
    infoCallback_->onRequestEnd(*this, txn->getMaxDeferredSize());
  }
  auto oldStreamCount = getPipelineStreamCount();
  decrementTransactionCount(txn, false, true);
  if (withRST || ((!codec_->isReusable() || readsShutdown()) &&
                  transactions_.size() == 1)) {
    // We should shutdown reads if we are closing with RST or we aren't
    // interested in any further messages (ie if we are a downstream session).
    // Upgraded sessions have independent ingress and egress, and the reads
    // need not be shutdown on egress finish.
    if (withRST) {
      // Let any queued writes complete, but send a RST when done.
      VLOG(4) << *this << " resetting egress after this message";
      resetAfterDrainingWrites_ = true;
      setCloseReason(ConnectionCloseReason::TRANSACTION_ABORT);
      shutdownTransport(true, true);
    } else {
      // the reason is already set (either not reusable or readshutdown).

      // Defer normal shutdowns until the end of the loop.  This
      // handles an edge case with direct responses with Connection:
      // close served before ingress EOM.  The remainder of the ingress
      // message may be in the parse loop, so give it a chance to
      // finish out and avoid a kErrorEOF

      // we can get here during shutdown, in that case do not schedule a
      // shutdown callback again
      if (!shutdownTransportCb_) {
        // Just for safety, the following bumps the refcount on this session
        // to keep it live until the loopCb runs
        shutdownTransportCb_.reset(new ShutdownTransportCallback(this));
        sock_->getEventBase()->runInLoop(shutdownTransportCb_.get(), true);
      }
    }
  } else {
    maybeResumePausedPipelinedTransaction(oldStreamCount,
                                          txn->getSequenceNumber());
  }
}
HTTPSession::onEgressMessageFinished(HTTPTransaction* txn, bool withRST) {
   
   
   
  CHECK(!transactions_.empty());

  if (infoCallback_) {
    infoCallback_->onRequestEnd(*this, txn->getMaxDeferredSize());
  }
  auto oldStreamCount = getPipelineStreamCount();
  decrementTransactionCount(txn, false, true);
  if (withRST || ((!codec_->isReusable() || readsShutdown()) &&
                  transactions_.size() == 1)) {
     
     
     
     
    if (withRST) {
       
      VLOG(4) << *this << " resetting egress after this message";
      resetAfterDrainingWrites_ = true;
      setCloseReason(ConnectionCloseReason::TRANSACTION_ABORT);
      shutdownTransport(true, true);
    } else {
       

       
       
       
       
       

       
       
      if (!shutdownTransportCb_) {
         
         
        shutdownTransportCb_.reset(new ShutdownTransportCallback(this));
        sock_->getEventBase()->runInLoop(shutdownTransportCb_.get(), true);
      }
    }
  } else {
    maybeResumePausedPipelinedTransaction(oldStreamCount,
                                          txn->getSequenceNumber());
  }
}