##! Functions for peering and various messaging patterns. %%{ #include #include #include #include "zeek/broker/Manager.h" #include "zeek/logging/Manager.h" namespace { using ArgsSpan = std::span; } static bool is_string_set(const zeek::Type* type) { if ( ! type->IsSet() ) return false; const auto& index_types = type->AsSetType()->GetIndexTypes(); if ( index_types.size() != 1 ) return false; return index_types[0]->Tag() == zeek::TYPE_STRING; } std::set val_to_topic_set(zeek::Val* val) { std::set rval; if ( val->GetType()->Tag() == zeek::TYPE_STRING ) rval.emplace(val->AsString()->CheckString()); else { const zeek::PDict* tbl = val->AsTable(); if ( tbl->Length() == 0 ) return rval; for ( const auto& te : *tbl ) { auto k = te.GetHashKey(); auto index = val->AsTableVal()->RecreateIndex(*k); rval.emplace(index->Idx(0)->AsString()->CheckString()); } } return rval; } static bool publish_event_args(ArgsSpan args, const zeek::String* topic, zeek::detail::Frame* frame) { zeek::Broker::Manager::ScriptScopeGuard ssg; zeek::ScriptLocationScope scope{frame}; auto rval = false; if ( zeek::broker_mgr != zeek::cluster::backend && ! zeek::broker_mgr->Active() ) zeek::reporter->Warning("Non-broker cluster backend configured and Broker manager inactive. " "Did you mean to use Cluster::publish() instead of Broker::publish()?"); if ( args[0]->GetType()->Tag() == zeek::TYPE_RECORD ) { auto* rv = args[0]->AsRecordVal(); // same_type() should be fast if it's the type pointers are the same. if ( ! zeek::same_type(rv->GetType(), zeek::BifType::Record::Broker::Event) ) { zeek::emit_builtin_error(zeek::util::fmt("expected Broker::Event, got %s", zeek::obj_desc_short(rv->GetType()).c_str())); return false; } return zeek::broker_mgr->PublishEvent(topic->CheckString(), rv); } auto ev = zeek::broker_mgr->MakeEvent(args, frame); return zeek::broker_mgr->PublishEvent(topic->CheckString(), ev->AsRecordVal()); } static bool is_cluster_pool(zeek::Val* pool) { static zeek::RecordTypePtr pool_type = nullptr; if ( ! pool_type ) pool_type = zeek::id::find_type("Cluster::Pool"); return pool->GetType() == pool_type; } %%} module Broker; type Broker::Event: record; ## Create a data structure that may be used to send a remote event via ## :zeek:see:`Broker::publish`. ## ## args: an event, followed by a list of argument values that may be used ## to call it. ## ## Returns: opaque communication data that may be used to send a remote ## event. function Broker::make_event%(...%): Broker::Event %{ zeek::Broker::Manager::ScriptScopeGuard ssg; auto ev = zeek::broker_mgr->MakeEvent(ArgsSpan{*@ARGS@}, frame); return zeek::cast_intrusive(ev); %} ## Publishes an event at a given topic. ## ## topic: a topic associated with the event message. ## ## args: Either the event arguments as already made by ## :zeek:see:`Broker::make_event` or the argument list to pass along ## to it. ## ## Returns: true if the message is sent. function Broker::publish%(topic: string, ...%): bool %{ auto rval = publish_event_args(ArgsSpan{*@ARGS@}.subspan(1), topic->AsString(), frame); return zeek::val_mgr->Bool(rval); %} function Broker::__flush_logs%(%): count %{ auto rval = zeek::broker_mgr->FlushLogBuffers(); return zeek::val_mgr->Count(static_cast(rval)); %} function Broker::__publish_id%(topic: string, id: string%): bool %{ zeek::Broker::Manager::ScriptScopeGuard ssg; auto rval = zeek::broker_mgr->PublishIdentifier(topic->CheckString(), id->CheckString()); return zeek::val_mgr->Bool(rval); %} function Broker::__auto_publish%(topic: string, ev: any%): bool %{ zeek::Broker::Manager::ScriptScopeGuard ssg; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" auto rval = zeek::broker_mgr->AutoPublishEvent(topic->CheckString(), ev); #pragma GCC diagnostic pop return zeek::val_mgr->Bool(rval); %} function Broker::__auto_unpublish%(topic: string, ev: any%): bool %{ zeek::Broker::Manager::ScriptScopeGuard ssg; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" auto rval = zeek::broker_mgr->AutoUnpublishEvent(topic->CheckString(), ev); #pragma GCC diagnostic pop return zeek::val_mgr->Bool(rval); %} function Broker::__subscribe%(topic_prefix: string%): bool %{ zeek::Broker::Manager::ScriptScopeGuard ssg; auto rval = zeek::broker_mgr->Subscribe(topic_prefix->CheckString()); return zeek::val_mgr->Bool(rval); %} function Broker::__forward%(topic_prefix: string%): bool %{ zeek::Broker::Manager::ScriptScopeGuard ssg; auto rval = zeek::broker_mgr->Forward(topic_prefix->CheckString()); return zeek::val_mgr->Bool(rval); %} function Broker::__unsubscribe%(topic_prefix: string%): bool %{ zeek::Broker::Manager::ScriptScopeGuard ssg; auto rval = zeek::broker_mgr->Unsubscribe(topic_prefix->CheckString()); return zeek::val_mgr->Bool(rval); %}