uint32_t QPACKDecoder::decodeLiteralHeaderQ()

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