void AsyncFizzClientT::writeAppData()

in fizz/client/AsyncFizzClient-inl.h [274:344]


void AsyncFizzClientT<SM>::writeAppData(
    folly::AsyncTransportWrapper::WriteCallback* callback,
    std::unique_ptr<folly::IOBuf>&& buf,
    folly::WriteFlags flags) {
  if (!good()) {
    if (callback) {
      callback->writeErr(
          0,
          folly::AsyncSocketException(
              folly::AsyncSocketException::INVALID_STATE,
              "fizz app write in error state"));
    }
    return;
  }

  if (earlyDataState_) {
    auto size = buf->computeChainDataLength();
    if (!earlyDataState_->pendingAppWrites.empty() ||
        size > earlyDataState_->remainingEarlyData) {
      AppWrite w;
      w.callback = callback;
      w.data = std::move(buf);
      w.flags = flags;
      w.aeadOptions = writeAeadOptions_;

      earlyDataState_->remainingEarlyData = 0;
      earlyDataState_->pendingAppWrites.push_back(std::move(w));
    } else {
      EarlyAppWrite w;
      w.callback = callback;
      w.data = std::move(buf);
      w.flags = flags;
      w.aeadOptions = writeAeadOptions_;

      if (earlyDataRejectionPolicy_ ==
          EarlyDataRejectionPolicy::AutomaticResend) {
        // We need to call unshare() to make a copy of the data here since we
        // may need to resend it after we've already called writeSuccess().
        // Particularly when using the write and writev interfaces, the
        // application is allowed to delete the underlying buffer after getting
        // the write callback.
        auto writeCopy = w.data->clone();
        writeCopy->unshare();
        earlyDataState_->resendBuffer.append(std::move(writeCopy));
      }

      earlyDataState_->remainingEarlyData -= size;
      fizzClient_.earlyAppWrite(std::move(w));
    }
  } else {
    AppWrite w;
    w.callback = callback;
    w.data = std::move(buf);
    w.flags = flags;
    w.aeadOptions = writeAeadOptions_;

    // Instead of dealing with the ordering of all 3 potential queues (early
    // data resend buffer, early data pending writes, and pending handshake
    // writes), we only queue up pending handshake writes if early data is
    // disabled through the user submitted FizzClientContext configuration.
    // Otherwise, we revert to the previous behavior where the write would fail
    // at the transport level.
    if (connecting() && !fizzContext_->getSendEarlyData()) {
      // underlying socket hasn't been connected, collect app data writes until
      // it is, then flush them
      pendingHandshakeAppWrites_.push_back(std::move(w));
    } else {
      fizzClient_.appWrite(std::move(w));
    }
  }
}