mirror of
https://github.com/zeek/zeek.git
synced 2025-10-11 19:18:19 +00:00
217 lines
4 KiB
C++
217 lines
4 KiB
C++
#include "Event.h"
|
|
#include "EventHandler.h"
|
|
#include "Func.h"
|
|
#include "Scope.h"
|
|
#include "RemoteSerializer.h"
|
|
#include "NetVar.h"
|
|
|
|
#ifdef ENABLE_BROKER
|
|
#include "broker/Manager.h"
|
|
#include "broker/Data.h"
|
|
#endif
|
|
|
|
EventHandler::EventHandler(const char* arg_name)
|
|
{
|
|
name = copy_string(arg_name);
|
|
used = false;
|
|
local = 0;
|
|
type = 0;
|
|
error_handler = false;
|
|
enabled = true;
|
|
generate_always = false;
|
|
}
|
|
|
|
EventHandler::~EventHandler()
|
|
{
|
|
Unref(local);
|
|
delete [] name;
|
|
}
|
|
|
|
EventHandler::operator bool() const
|
|
{
|
|
return enabled && ((local && local->HasBodies())
|
|
|| receivers.length()
|
|
|| generate_always
|
|
#ifdef ENABLE_BROKER
|
|
|| ! auto_remote_send.empty()
|
|
// TODO: and require a subscriber interested in a topic or unsolicited flags?
|
|
#endif
|
|
);
|
|
}
|
|
|
|
FuncType* EventHandler::FType()
|
|
{
|
|
if ( type )
|
|
return type;
|
|
|
|
ID* id = lookup_ID(name, current_module.c_str());
|
|
|
|
if ( ! id )
|
|
return 0;
|
|
|
|
if ( id->Type()->Tag() != TYPE_FUNC )
|
|
return 0;
|
|
|
|
type = id->Type()->AsFuncType();
|
|
Unref(id);
|
|
|
|
return type;
|
|
}
|
|
|
|
void EventHandler::SetLocalHandler(Func* f)
|
|
{
|
|
if ( local )
|
|
Unref(local);
|
|
|
|
Ref(f);
|
|
local = f;
|
|
}
|
|
|
|
void EventHandler::Call(val_list* vl, bool no_remote)
|
|
{
|
|
#ifdef PROFILE_BRO_FUNCTIONS
|
|
DEBUG_MSG("Event: %s\n", Name());
|
|
#endif
|
|
|
|
if ( new_event )
|
|
NewEvent(vl);
|
|
|
|
if ( ! no_remote )
|
|
{
|
|
loop_over_list(receivers, i)
|
|
{
|
|
SerialInfo info(remote_serializer);
|
|
remote_serializer->SendCall(&info, receivers[i], name, vl);
|
|
}
|
|
|
|
#ifdef ENABLE_BROKER
|
|
|
|
if ( ! auto_remote_send.empty() )
|
|
{
|
|
// TODO: also short-circuit based on interested subscribers/flags?
|
|
broker::message msg;
|
|
msg.reserve(vl->length() + 1);
|
|
msg.emplace_back(Name());
|
|
bool valid_args = true;
|
|
|
|
for ( auto i = 0; i < vl->length(); ++i )
|
|
{
|
|
auto opt_data = bro_broker::val_to_data((*vl)[i]);
|
|
|
|
if ( opt_data )
|
|
msg.emplace_back(move(*opt_data));
|
|
else
|
|
{
|
|
valid_args = false;
|
|
auto_remote_send.clear();
|
|
reporter->Error("failed auto-remote event '%s', disabled",
|
|
Name());
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( valid_args )
|
|
{
|
|
for ( auto it = auto_remote_send.begin();
|
|
it != auto_remote_send.end(); ++it )
|
|
{
|
|
if ( std::next(it) == auto_remote_send.end() )
|
|
broker_mgr->Event(it->first, move(msg), it->second);
|
|
else
|
|
broker_mgr->Event(it->first, msg, it->second);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ( local )
|
|
// No try/catch here; we pass exceptions upstream.
|
|
Unref(local->Call(vl));
|
|
else
|
|
{
|
|
loop_over_list(*vl, i)
|
|
Unref((*vl)[i]);
|
|
}
|
|
}
|
|
|
|
void EventHandler::NewEvent(val_list* vl)
|
|
{
|
|
if ( ! new_event )
|
|
return;
|
|
|
|
if ( this == new_event.Ptr() )
|
|
// new_event() is the one event we don't want to report.
|
|
return;
|
|
|
|
RecordType* args = FType()->Args();
|
|
VectorVal* vargs = new VectorVal(call_argument_vector);
|
|
|
|
for ( int i = 0; i < args->NumFields(); i++ )
|
|
{
|
|
const char* fname = args->FieldName(i);
|
|
BroType* ftype = args->FieldType(i);
|
|
Val* fdefault = args->FieldDefault(i);
|
|
|
|
RecordVal* rec = new RecordVal(call_argument);
|
|
rec->Assign(0, new StringVal(fname));
|
|
|
|
ODesc d;
|
|
d.SetShort();
|
|
ftype->Describe(&d);
|
|
rec->Assign(1, new StringVal(d.Description()));
|
|
|
|
if ( fdefault )
|
|
{
|
|
Ref(fdefault);
|
|
rec->Assign(2, fdefault);
|
|
}
|
|
|
|
if ( i < vl->length() && (*vl)[i] )
|
|
{
|
|
Val* val = (*vl)[i];
|
|
Ref(val);
|
|
rec->Assign(3, val);
|
|
}
|
|
|
|
vargs->Assign(i, rec);
|
|
}
|
|
|
|
val_list* mvl = new val_list(2);
|
|
mvl->append(new StringVal(name));
|
|
mvl->append(vargs);
|
|
|
|
Event* ev = new Event(new_event, mvl);
|
|
mgr.Dispatch(ev);
|
|
}
|
|
|
|
void EventHandler::AddRemoteHandler(SourceID peer)
|
|
{
|
|
receivers.append(peer);
|
|
}
|
|
|
|
void EventHandler::RemoveRemoteHandler(SourceID peer)
|
|
{
|
|
receivers.remove(peer);
|
|
}
|
|
|
|
bool EventHandler::Serialize(SerialInfo* info) const
|
|
{
|
|
return SERIALIZE(name);
|
|
}
|
|
|
|
EventHandler* EventHandler::Unserialize(UnserialInfo* info)
|
|
{
|
|
char* name;
|
|
if ( ! UNSERIALIZE_STR(&name, 0) )
|
|
return 0;
|
|
|
|
EventHandler* h = event_registry->Lookup(name);
|
|
if ( ! h )
|
|
{
|
|
h = new EventHandler(name);
|
|
event_registry->Register(h);
|
|
}
|
|
|
|
return h;
|
|
}
|