size_t HTTPTransaction::sendBodyNow()

in proxygen/lib/http/session/HTTPTransaction.cpp [1264:1325]


size_t HTTPTransaction::sendBodyNow(std::unique_ptr<folly::IOBuf> body,
                                    size_t bodyLen,
                                    bool sendEom) {
  static const std::string noneStr = "None";
  DCHECK(body);
  DCHECK_GT(bodyLen, 0);
  size_t nbytes = 0;
  if (useFlowControl_) {
    // Because of how sendBodyNow is embedded in HTTPTransaction code flow,
    // calling INVARIANT here is not safe
    CHECK(sendWindow_.reserve(bodyLen));
  }
  VLOG(4) << "Sending " << bodyLen
          << " bytes of body. eom=" << ((sendEom) ? "yes" : "no")
          << " send_window is "
          << (useFlowControl_
                  ? folly::to<std::string>(
                        sendWindow_.getSize(), " / ", sendWindow_.getCapacity())
                  : noneStr)
          << " trailers=" << ((trailers_) ? "yes" : "no") << " " << *this;
  DCHECK_LT(bodyLen, std::numeric_limits<int64_t>::max());
  transport_.notifyEgressBodyBuffered(-static_cast<int64_t>(bodyLen));
  if (sendEom && !trailers_) {
    if (!validateEgressStateTransition(
            HTTPTransactionEgressSM::Event::eomFlushed)) {
      return 0;
    }
  } else if (ingressErrorSeen_ && isExpectingWindowUpdate()) {
    // I don't know how we got here but we're in trouble.  We need a window
    // update to continue but we've already seen an ingress error.
    HTTPException ex(HTTPException::Direction::INGRESS_AND_EGRESS,
                     folly::to<std::string>("window blocked with ingress error,"
                                            " streamID=",
                                            id_));
    ex.setProxygenError(kErrorEOF);
    ex.setCodecStatusCode(ErrorCode::FLOW_CONTROL_ERROR);
    onError(ex);
    return 0;
  }
  updateReadTimeout();
  nbytes = transport_.sendBody(this,
                               std::move(body),
                               sendEom && !trailers_,
                               enableLastByteFlushedTracking_);
  bodyBytesEgressed_ += bodyLen;
  for (auto it = egressBodyOffsetsToTrack_.begin();
       it != egressBodyOffsetsToTrack_.end() && it->first < bodyBytesEgressed_;
       it = egressBodyOffsetsToTrack_.begin()) {
    transport_.trackEgressBodyOffset(it->first, it->second);
    egressBodyOffsetsToTrack_.erase(it);
  }
  if (sendEom && trailers_) {
    nbytes += sendEOMNow();
  }
  if (isPrioritySampled()) {
    updateTransactionBytesSent(bodyLen);
  }
  if (egressLimitBytesPerMs_ > 0) {
    numLimitedBytesEgressed_ += nbytes;
  }
  return nbytes;
}