zeek/src/broker/messaging.bif
2020-08-20 15:55:17 -07:00

241 lines
6.7 KiB
C++

##! Functions for peering and various messaging patterns.
%%{
#include "broker/Manager.h"
#include "logging/Manager.h"
#include <set>
#include <string>
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<std::string> val_to_topic_set(zeek::Val* val)
{
std::set<std::string> rval;
if ( val->GetType()->Tag() == zeek::TYPE_STRING )
rval.emplace(val->AsString()->CheckString());
else
{
const zeek::PDict<zeek::TableEntryVal>* tbl = val->AsTable();
if ( tbl->Length() == 0 )
return rval;
zeek::IterCookie* c = tbl->InitForIteration();
zeek::detail::HashKey* k;
while ( tbl->NextEntry(k, c) )
{
auto index = val->AsTableVal()->RecreateIndex(*k);
rval.emplace(index->Idx(0)->AsString()->CheckString());
delete k;
}
}
return rval;
}
static bool publish_event_args(val_list& args, const zeek::String* topic,
zeek::detail::Frame* frame)
{
zeek::Broker::Manager::ScriptScopeGuard ssg;
auto rval = false;
if ( args[0]->GetType()->Tag() == zeek::TYPE_RECORD )
rval = zeek::broker_mgr->PublishEvent(topic->CheckString(),
args[0]->AsRecordVal());
else
{
auto ev = zeek::broker_mgr->MakeEvent(&args, frame);
rval = zeek::broker_mgr->PublishEvent(topic->CheckString(), ev);
Unref(ev);
}
return rval;
}
%%}
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;
const auto& bif_args = @ARGS@;
val_list args(bif_args->size());
for ( auto i = 0u; i < bif_args->size(); ++i )
args.push_back((*bif_args)[i].get());
return RecordValPtr{zeek::AdoptRef{}, zeek::broker_mgr->MakeEvent(&args, frame)};
%}
## 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
%{
const auto& bif_args = @ARGS@;
val_list args(bif_args->size() - 1);
for ( auto i = 1u; i < bif_args->size(); ++i )
args.push_back((*bif_args)[i].get());
auto rval = publish_event_args(args, 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<uint64_t>(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;
auto rval = zeek::broker_mgr->AutoPublishEvent(topic->CheckString(), ev);
return zeek::val_mgr->Bool(rval);
%}
function Broker::__auto_unpublish%(topic: string, ev: any%): bool
%{
zeek::Broker::Manager::ScriptScopeGuard ssg;
auto rval = zeek::broker_mgr->AutoUnpublishEvent(topic->CheckString(), ev);
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);
%}
module Cluster;
type Cluster::Pool: record;
## Publishes an event to a node within a pool according to Round-Robin
## distribution strategy.
##
## pool: the pool of nodes that are eligible to receive the event.
##
## key: an arbitrary string to identify the purpose for which you're
## distributing the event. e.g. consider using namespacing of your
## script like "Intel::cluster_rr_key".
##
## 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 Cluster::publish_rr%(pool: Pool, key: string, ...%): bool
%{
static zeek::Func* topic_func = nullptr;
if ( ! topic_func )
topic_func = zeek::detail::global_scope()->Find("Cluster::rr_topic")->GetVal()->AsFunc();
zeek::Args vl{{zeek::NewRef{}, pool}, {zeek::NewRef{}, key}};
auto topic = topic_func->Invoke(&vl);
if ( ! topic->AsString()->Len() )
return zeek::val_mgr->False();
const auto& bif_args = @ARGS@;
val_list args(bif_args->size() - 2);
for ( auto i = 2u; i < bif_args->size(); ++i )
args.push_back((*bif_args)[i].get());
auto rval = publish_event_args(args, topic->AsString(), frame);
return zeek::val_mgr->Bool(rval);
%}
## Publishes an event to a node within a pool according to Rendezvous
## (Highest Random Weight) hashing strategy.
##
## pool: the pool of nodes that are eligible to receive the event.
##
## key: data used for input to the hashing function that will uniformly
## distribute keys among available nodes.
##
## 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 Cluster::publish_hrw%(pool: Pool, key: any, ...%): bool
%{
static zeek::Func* topic_func = nullptr;
if ( ! topic_func )
topic_func = zeek::detail::global_scope()->Find("Cluster::hrw_topic")->GetVal()->AsFunc();
zeek::Args vl{{zeek::NewRef{}, pool}, {zeek::NewRef{}, key}};
auto topic = topic_func->Invoke(&vl);
if ( ! topic->AsString()->Len() )
return zeek::val_mgr->False();
const auto& bif_args = @ARGS@;
val_list args(bif_args->size() - 2);
for ( auto i = 2u; i < bif_args->size(); ++i )
args.push_back((*bif_args)[i].get());
auto rval = publish_event_args(args, topic->AsString(), frame);
return zeek::val_mgr->Bool(rval);
%}