in source/extensions/filters/network/mongo_proxy/bson_impl.cc [368:489]
void DocumentImpl::fromBuffer(Buffer::Instance& data) {
uint64_t original_buffer_length = data.length();
int32_t message_length = BufferHelper::removeInt32(data);
if (static_cast<uint64_t>(message_length) > original_buffer_length) {
throw EnvoyException("invalid BSON message length");
}
ENVOY_LOG(trace, "BSON document length: {} data length: {}", message_length,
original_buffer_length);
while (true) {
uint64_t document_bytes_remaining = data.length() - (original_buffer_length - message_length);
ENVOY_LOG(trace, "BSON document bytes remaining: {}", document_bytes_remaining);
if (document_bytes_remaining == 1) {
uint8_t last_byte = BufferHelper::removeByte(data);
if (last_byte != 0) {
throw EnvoyException("invalid document");
}
return;
}
uint8_t element_type = BufferHelper::removeByte(data);
std::string key = BufferHelper::removeCString(data);
ENVOY_LOG(trace, "BSON element type: {:#x} key: {}", element_type, key);
switch (static_cast<Field::Type>(element_type)) {
case Field::Type::DOUBLE: {
double value = BufferHelper::removeDouble(data);
ENVOY_LOG(trace, "BSON double: {}", value);
addDouble(key, value);
break;
}
case Field::Type::STRING: {
std::string value = BufferHelper::removeString(data);
ENVOY_LOG(trace, "BSON string: {}", value);
addString(key, std::move(value));
break;
}
case Field::Type::DOCUMENT: {
ENVOY_LOG(trace, "BSON document");
addDocument(key, DocumentImpl::create(data));
break;
}
case Field::Type::ARRAY: {
ENVOY_LOG(trace, "BSON array");
addArray(key, DocumentImpl::create(data));
break;
}
case Field::Type::BINARY: {
std::string value = BufferHelper::removeBinary(data);
ENVOY_LOG(trace, "BSON binary: {}", value);
addBinary(key, std::move(value));
break;
}
case Field::Type::OBJECT_ID: {
Field::ObjectId value;
BufferHelper::removeBytes(data, &value[0], value.size());
addObjectId(key, std::move(value));
break;
}
case Field::Type::BOOLEAN: {
bool value = BufferHelper::removeByte(data) != 0;
ENVOY_LOG(trace, "BSON boolean: {}", value);
addBoolean(key, value);
break;
}
case Field::Type::DATETIME: {
int64_t value = BufferHelper::removeInt64(data);
ENVOY_LOG(trace, "BSON datetime: {}", value);
addDatetime(key, value);
break;
}
case Field::Type::NULL_VALUE: {
ENVOY_LOG(trace, "BSON null value");
addNull(key);
break;
}
case Field::Type::REGEX: {
Field::Regex value;
value.pattern_ = BufferHelper::removeCString(data);
value.options_ = BufferHelper::removeCString(data);
ENVOY_LOG(trace, "BSON regex pattern: {} options: {}", value.pattern_, value.options_);
addRegex(key, std::move(value));
break;
}
case Field::Type::INT32: {
int32_t value = BufferHelper::removeInt32(data);
ENVOY_LOG(trace, "BSON int32: {}", value);
addInt32(key, value);
break;
}
case Field::Type::TIMESTAMP: {
int64_t value = BufferHelper::removeInt64(data);
ENVOY_LOG(trace, "BSON timestamp: {}", value);
addTimestamp(key, value);
break;
}
case Field::Type::INT64: {
int64_t value = BufferHelper::removeInt64(data);
ENVOY_LOG(trace, "BSON int64: {}", value);
addInt64(key, value);
break;
}
default:
throw EnvoyException(
fmt::format("invalid BSON element type: {:#x} key: {}", element_type, key));
}
}
}