in mcrouter/lib/network/CaretProtocol.cpp [110:197]
ParseStatus caretParseHeader(
const uint8_t* buff,
size_t nbuf,
CaretMessageInfo& headerInfo) {
/* we need the magic byte and the first byte of encoded header
to determine if we have enough data in the buffer to get the
entire header */
if (nbuf < 2) {
return ParseStatus::NotEnoughData;
}
if (buff[0] != kCaretMagicByte) {
return ParseStatus::MessageParseError;
}
const char* buf = reinterpret_cast<const char*>(buff);
size_t encodedLength = folly::GroupVarint32::encodedSize(buf + 1);
if (nbuf < encodedLength + 1) {
return ParseStatus::NotEnoughData;
}
uint32_t additionalFields;
folly::GroupVarint32::decode_simple(
buf + 1,
&headerInfo.bodySize,
&headerInfo.typeId,
&headerInfo.reqId,
&additionalFields);
folly::StringPiece range(buf, nbuf);
range.advance(encodedLength + 1);
// Additional fields are sequence of (key,value) pairs
resetAdditionalFields(headerInfo);
for (uint32_t i = 0; i < additionalFields; i++) {
size_t fieldType;
if (auto maybeFieldType = folly::tryDecodeVarint(range)) {
fieldType = *maybeFieldType;
} else {
return ParseStatus::NotEnoughData;
}
size_t fieldValue;
if (auto maybeFieldValue = folly::tryDecodeVarint(range)) {
fieldValue = *maybeFieldValue;
} else {
return ParseStatus::NotEnoughData;
}
if (fieldType >
static_cast<uint64_t>(CaretAdditionalFieldType::SERVER_LOAD)) {
// Additional Field Type not recognized, ignore.
continue;
}
switch (static_cast<CaretAdditionalFieldType>(fieldType)) {
case CaretAdditionalFieldType::TRACE_ID:
headerInfo.traceId.first = fieldValue;
break;
case CaretAdditionalFieldType::TRACE_NODE_ID:
headerInfo.traceId.second = fieldValue;
break;
case CaretAdditionalFieldType::SUPPORTED_CODECS_FIRST_ID:
headerInfo.supportedCodecsFirstId = fieldValue;
break;
case CaretAdditionalFieldType::SUPPORTED_CODECS_SIZE:
headerInfo.supportedCodecsSize = fieldValue;
break;
case CaretAdditionalFieldType::USED_CODEC_ID:
headerInfo.usedCodecId = fieldValue;
break;
case CaretAdditionalFieldType::UNCOMPRESSED_BODY_SIZE:
headerInfo.uncompressedBodySize = fieldValue;
break;
case CaretAdditionalFieldType::DROP_PROBABILITY:
headerInfo.dropProbability = fieldValue;
break;
case CaretAdditionalFieldType::SERVER_LOAD:
headerInfo.serverLoad = ServerLoad(fieldValue);
break;
}
}
headerInfo.headerSize = range.cbegin() - buf;
return ParseStatus::Ok;
}