in proxygen/lib/http/codec/compress/QPACKDecoder.cpp [276:345]
uint32_t QPACKDecoder::decodeLiteralHeaderQ(
HPACKDecodeBuffer& dbuf,
bool indexing,
bool nameIndexed,
uint8_t prefixLength,
bool aboveBase,
HPACK::StreamingCallback* streamingCb) {
bool allowPartial = (streamingCb == nullptr);
Partial localPartial;
Partial* partial = (allowPartial) ? &partial_ : &localPartial;
if (partial->state == Partial::NAME) {
if (nameIndexed) {
uint64_t nameIndex = 0;
bool isStaticName = !aboveBase && (dbuf.peek() & (1 << prefixLength));
err_ = dbuf.decodeInteger(prefixLength, nameIndex);
if (allowPartial && err_ == HPACK::DecodeError::BUFFER_UNDERFLOW) {
return 0;
}
if (err_ != HPACK::DecodeError::NONE) {
LOG(ERROR) << "Decode error decoding index err_=" << err_;
return 0;
}
nameIndex++;
// validate the index
if (!isValid(isStaticName, nameIndex, aboveBase)) {
LOG(ERROR) << "Received invalid index=" << nameIndex;
err_ = HPACK::DecodeError::INVALID_INDEX;
return 0;
}
partial->header.name =
getHeader(isStaticName, nameIndex, baseIndex_, aboveBase).name;
} else {
folly::fbstring headerName;
err_ = dbuf.decodeLiteral(prefixLength, headerName);
if (allowPartial && err_ == HPACK::DecodeError::BUFFER_UNDERFLOW) {
return 0;
}
if (err_ != HPACK::DecodeError::NONE) {
LOG(ERROR) << "Error decoding header name err_=" << err_;
return 0;
}
partial->header.name = headerName;
}
partial->state = Partial::VALUE;
partial->consumed = dbuf.consumedBytes();
}
// value
err_ = dbuf.decodeLiteral(partial->header.value);
if (allowPartial && err_ == HPACK::DecodeError::BUFFER_UNDERFLOW) {
return 0;
}
if (err_ != HPACK::DecodeError::NONE) {
LOG(ERROR) << "Error decoding header value name=" << partial->header.name
<< " err_=" << err_;
return 0;
}
partial->state = Partial::NAME;
uint32_t emittedSize = emit(partial->header, streamingCb, nullptr);
if (indexing) {
if (!table_.add(std::move(partial->header))) {
// the only case is the header was > table capacity
LOG(ERROR) << "Encoder inserted a header larger than capacity";
err_ = HPACK::DecodeError::INSERT_TOO_LARGE;
}
}
return emittedSize;
}