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));
}
}
}