cluster: Fix Cluster::publish() of Broker::Data

The broker serializer leverages the existing data_to_val() function.
During unserialization, if the destination type is any, the logic
simply wraps the broker::data value into a Broker::Data record.
Therefore, events with any parameters are currently exposed to
the Broker::Data type.

There is a bigger issue in that re-publishing such Broker::Data
instances would encode them as a normal record. Explicitly prevent
this by serializing the contained data value directly instead, similar
to what Broker already did when publishing a record.
This commit is contained in:
Arne Welzel 2024-12-12 11:25:31 +01:00
parent 271fc15041
commit d9a74cf32d
9 changed files with 379 additions and 4 deletions

View file

@ -539,13 +539,22 @@ std::string Manager::NodeID() const { return to_string(bstate->endpoint.node_id(
bool Manager::DoPublishEvent(const std::string& topic, const cluster::detail::Event& event) {
broker::vector xs;
xs.reserve(event.args.size());
for ( const auto& a : event.args ) {
auto r = detail::val_to_data(a.get());
if ( ! r ) {
if ( a->GetType() == zeek::BifType::Record::Broker::Data ) {
// When encountering a Broker::Data instance within args, pick out
// the broker::data directly to avoid double encoding of the record.
const auto& val = a->AsRecordVal()->GetField(0);
auto* data_val = static_cast<zeek::Broker::detail::DataVal*>(val.get());
xs.emplace_back(data_val->data);
}
else if ( auto r = detail::val_to_data(a.get()) ) {
xs.emplace_back(std::move(r.value()));
}
else {
Error("Failed to convert %s to broker::data", zeek::obj_desc(a.get()).c_str());
return false;
}
xs.emplace_back(std::move(r.value()));
}
std::string name(event.HandlerName());