Extending plugin interface.

This is for feature parity with the older interface, and remains
experimental for now.
This commit is contained in:
Robin Sommer 2014-05-14 16:58:59 -07:00
parent aec61e9ea4
commit 421120e12c
8 changed files with 145 additions and 14 deletions

View file

@ -13,6 +13,7 @@ EventHandler::EventHandler(const char* arg_name)
type = 0;
error_handler = false;
enabled = true;
generate_always = false;
}
EventHandler::~EventHandler()
@ -23,7 +24,9 @@ EventHandler::~EventHandler()
EventHandler::operator bool() const
{
return enabled && ((local && local->HasBodies()) || receivers.length());
return enabled && ((local && local->HasBodies())
|| receivers.length()
|| generate_always);
}
FuncType* EventHandler::FType()

View file

@ -43,6 +43,11 @@ public:
void SetEnable(bool arg_enable) { enabled = arg_enable; }
// Flags the event as interesting even if there is no body defined. In
// particular, this will then still pass the event on to plugins.
void SetGenerateAlways() { generate_always = true; }
bool GenerateAlways() { return generate_always; }
// We don't serialize the handler(s) itself here, but
// just the reference to it.
bool Serialize(SerialInfo* info) const;
@ -57,6 +62,7 @@ private:
bool used; // this handler is indeed used somewhere
bool enabled;
bool error_handler; // this handler reports error messages.
bool generate_always;
declare(List, SourceID);
typedef List(SourceID) receiver_list;

View file

@ -7,6 +7,7 @@
#include "Obj.h"
#include "Serializer.h"
#include "File.h"
#include "plugin/Manager.h"
Location no_location("<no location>", 0, 0, 0, 0);
Location start_location("<start uninitialized>", 0, 0, 0, 0);
@ -92,6 +93,11 @@ int BroObj::suppress_errors = 0;
BroObj::~BroObj()
{
if ( notify_plugins )
{
PLUGIN_HOOK_VOID(HOOK_BRO_OBJ_DTOR, HookBroObjDtor(this));
}
delete location;
}

View file

@ -92,6 +92,7 @@ public:
{
ref_cnt = 1;
in_ser_cache = false;
notify_plugins = false;
// A bit of a hack. We'd like to associate location
// information with every object created when parsing,
@ -151,6 +152,9 @@ public:
// extend compound objects such as statement lists.
virtual void UpdateLocationEndInfo(const Location& end);
// Enable notification of plugins when this objects gets destroyed.
void NotifyPluginsOnDtor() { notify_plugins = true; }
int RefCnt() const { return ref_cnt; }
// Helper class to temporarily suppress errors
@ -181,6 +185,7 @@ private:
friend inline void Ref(BroObj* o);
friend inline void Unref(BroObj* o);
bool notify_plugins;
int ref_cnt;
// If non-zero, do not print runtime errors. Useful for

View file

@ -443,6 +443,16 @@ void Manager::DisableHook(HookType hook, Plugin* plugin)
}
}
void Manager::RequestEvent(EventHandlerPtr handler, Plugin* plugin)
{
DBG_LOG(DBG_PLUGINS, "Plugin %s requested event %s", Name(), handler->Name());
handler->GenerateAlways();
}
void Manager::RequestBroObjDtor(BroObj* obj, Plugin* plugin)
{
}
int Manager::HookLoadFile(const string& file)
{
HookArgumentList args;
@ -577,6 +587,29 @@ void Manager::HookUpdateNetworkTime(double network_time) const
MetaHookPost(HOOK_UPDATE_NETWORK_TIME, args, HookArgument());
}
void Manager::HookBroObjDtor(void* obj) const
{
HookArgumentList args;
if ( HavePluginForHook(META_HOOK_PRE) )
{
args.push_back(obj);
MetaHookPre(HOOK_BRO_OBJ_DTOR, args);
}
hook_list* l = hooks[HOOK_BRO_OBJ_DTOR];
for ( hook_list::iterator i = l->begin(); l && i != l->end(); i++ )
{
Plugin* p = (*i).second;
p->HookBroObjDtor(obj);
}
if ( HavePluginForHook(META_HOOK_POST) )
MetaHookPost(HOOK_BRO_OBJ_DTOR, args, HookArgument());
}
void Manager::MetaHookPre(HookType hook, const HookArgumentList& args) const
{
hook_list* l = hooks[HOOK_CALL_FUNCTION];

View file

@ -15,7 +15,7 @@ namespace plugin {
// Macros that trigger a plugin hook. We put this into macros to short-cut
// the code for the most common case that no plugin defines the hook.
#define PLUGIN_HOOK_WITH_RESULT(hook, method_call, default_result) \
(plugin_mgr->HavePluginForHook(plugin::hook) ? plugin_mgr->method_call : (default_result))
(plugin_mgr->HavePluginForHook(::plugin::hook) ? plugin_mgr->method_call : (default_result))
#define PLUGIN_HOOK_VOID(hook, method_call) \
if ( plugin_mgr->HavePluginForHook(plugin::hook) ) plugin_mgr->method_call;
@ -160,6 +160,27 @@ public:
*/
void DisableHook(HookType hook, Plugin* plugin);
/**
* Register interest in an event. The event will then be raised, and
* hence passed to the plugin, even if there no handler defined.
*
* @param handler The event being interested in.
*
* @param plugin The plugin expressing interest.
*/
void RequestEvent(EventHandlerPtr handler, Plugin* plugin);
/**
* Register interest in the destruction of a BroObj instance. When
* Bro's reference counting triggers the objects destructor to run,
* the \a HookBroObjDtor will be called.
*
* @param handler The object being interested in.
*
* @param plugin The plugin expressing interest.
*/
void RequestBroObjDtor(BroObj* obj, Plugin* plugin);
// Hook entry functions.
/**
@ -208,10 +229,16 @@ public:
void HookUpdateNetworkTime(double network_time) const;
/**
* Hooks that informs plugins that the event queue is being drained.
* Hook that informs plugins that the event queue is being drained.
*/
void HookDrainEvents() const;
/**
* Hook that informs plugins that an BroObj is being destroyed. Will be
* called only for objects that a plugin has expressed interest in.
*/
void HookBroObjDtor(void* obj) const;
/**
* Internal method that registers a freshly instantiated plugin with
* the manager.

View file

@ -22,6 +22,7 @@ const char* plugin::hook_name(HookType h)
"QueueEvent",
"DrainEvents",
"UpdateNetworkTime",
"BroObjDtor",
// MetaHooks
"MetaHookPre",
"MetaHookPost",
@ -32,6 +33,13 @@ const char* plugin::hook_name(HookType h)
return hook_names[int(h)];
}
Configuration::Configuration()
{
name = "";
description = "";
api_version = BRO_PLUGIN_API_VERSION;
}
BifItem::BifItem(const std::string& arg_id, Type arg_type)
{
id = arg_id;
@ -119,6 +127,10 @@ void HookArgument::Describe(ODesc* d) const
case VOID:
d->Add("<void>");
break;
case VOIDP:
d->Add("<void ptr>");
break;
}
}
@ -262,6 +274,16 @@ void Plugin::DisableHook(HookType hook)
plugin_mgr->DisableHook(hook, this);
}
void Plugin::RequestEvent(EventHandlerPtr handler)
{
plugin_mgr->RequestEvent(handler, this);
}
void Plugin::RequestBroObjDtor(BroObj* obj)
{
plugin_mgr->RequestBroObjDtor(obj, this);
}
int Plugin::HookLoadFile(const std::string& file)
{
return -1;
@ -285,6 +307,10 @@ void Plugin::HookUpdateNetworkTime(double network_time)
{
}
void Plugin::HookBroObjDtor(void* obj)
{
}
void Plugin::MetaHookPre(HookType hook, const HookArgumentList& args)
{
}

View file

@ -33,6 +33,7 @@ enum HookType {
HOOK_QUEUE_EVENT,
HOOK_DRAIN_EVENTS,
HOOK_UPDATE_NETWORK_TIME,
HOOK_BRO_OBJ_DTOR,
// Meta hooks.
META_HOOK_PRE,
@ -69,19 +70,11 @@ public:
std::string description; //< A short textual description of the plugin. Mandatory.
VersionNumber version; //< THe plugin's version. Optional.
Configuration()
{
// Note we inline this method here so that when plugins create an instance,
// *their* defaults will be used for the internal fields.
name = "";
description = "";
api_version = BRO_PLUGIN_API_VERSION;
}
Configuration();
private:
friend class Plugin;
int api_version; // Current BRO_PLUGIN_API_VERSION. Automatically set.
};
/**
@ -141,7 +134,7 @@ class HookArgument
{
public:
enum Type {
BOOL, DOUBLE, EVENT, FUNC, INT, STRING, VAL, VAL_LIST, VOID
BOOL, DOUBLE, EVENT, FUNC, INT, STRING, VAL, VAL_LIST, VOID, VOIDP,
};
HookArgument() { type = VOID; }
@ -153,6 +146,7 @@ public:
HookArgument(const std::string& a) { type = STRING; arg_string = a; }
HookArgument(const Val* a) { type = VAL; arg.val = a; }
HookArgument(const val_list* a) { type = VAL_LIST; arg.vals = a; }
HookArgument(void* p) { type = VOIDP; arg.voidp = p; }
bool AsBool() const { assert(type == BOOL); return arg.bool_; }
double AsDouble() const { assert(type == DOUBLE); return arg.double_; }
@ -162,6 +156,7 @@ public:
const std::string& AsString() const { assert(type == STRING); return arg_string; }
const Val* AsVal() const { assert(type == VAL); return arg.val; }
const val_list* AsValList() const { assert(type == VAL_LIST); return arg.vals; }
const void* AsVoidPtr() const { assert(type == VOIDP); return arg.voidp; }
Type GetType() const { return type; }
void Describe(ODesc* d) const;
@ -176,6 +171,7 @@ private:
int int_;
const Val* val;
const val_list* vals;
const void* voidp;
} arg;
std::string arg_string; // Outside union because it has dtor.
@ -406,6 +402,23 @@ protected:
*/
hook_list EnabledHooks() const;
/**
* Register interest in an event. The event will then be raised, and
* hence passed to the plugin, even if there no handler defined.
*
* @param handler The object being interested in.
*/
void RequestEvent(EventHandlerPtr handler);
/**
* Register interest in the destruction of a BroObj instance. When
* Bro's reference counting triggers the objects destructor to run,
* the \a HookBroObjDtor will be called.
*
* @param handler The object being interested in.
*/
void RequestBroObjDtor(BroObj* obj);
/**
* Virtual method that can be overriden by derived class to provide
* information about further script-level elements that the plugin
@ -496,6 +509,18 @@ protected:
*/
virtual void HookUpdateNetworkTime(double network_time);
/**
* Hook for destruction of objects registerd with
* RequestBroObjDtor(). When Bro's reference counting triggers the
* objects destructor to run, this method will be run. It may also
* run for other objects that this plugin has not registered for.
*
* @param obj A pointer to the object being destroyed. Note that the
* object is already considered invalid and the pointer must not be
* dereferenced.
*/
virtual void HookBroObjDtor(void* obj);
// Meta hooks.
/**