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

View file

@ -43,6 +43,11 @@ public:
void SetEnable(bool arg_enable) { enabled = arg_enable; } 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 // We don't serialize the handler(s) itself here, but
// just the reference to it. // just the reference to it.
bool Serialize(SerialInfo* info) const; bool Serialize(SerialInfo* info) const;
@ -57,6 +62,7 @@ private:
bool used; // this handler is indeed used somewhere bool used; // this handler is indeed used somewhere
bool enabled; bool enabled;
bool error_handler; // this handler reports error messages. bool error_handler; // this handler reports error messages.
bool generate_always;
declare(List, SourceID); declare(List, SourceID);
typedef List(SourceID) receiver_list; typedef List(SourceID) receiver_list;

View file

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

View file

@ -92,6 +92,7 @@ public:
{ {
ref_cnt = 1; ref_cnt = 1;
in_ser_cache = false; in_ser_cache = false;
notify_plugins = false;
// A bit of a hack. We'd like to associate location // A bit of a hack. We'd like to associate location
// information with every object created when parsing, // information with every object created when parsing,
@ -151,6 +152,9 @@ public:
// extend compound objects such as statement lists. // extend compound objects such as statement lists.
virtual void UpdateLocationEndInfo(const Location& end); 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; } int RefCnt() const { return ref_cnt; }
// Helper class to temporarily suppress errors // Helper class to temporarily suppress errors
@ -181,6 +185,7 @@ private:
friend inline void Ref(BroObj* o); friend inline void Ref(BroObj* o);
friend inline void Unref(BroObj* o); friend inline void Unref(BroObj* o);
bool notify_plugins;
int ref_cnt; int ref_cnt;
// If non-zero, do not print runtime errors. Useful for // 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) int Manager::HookLoadFile(const string& file)
{ {
HookArgumentList args; HookArgumentList args;
@ -522,7 +532,7 @@ bool Manager::HookQueueEvent(Event* event) const
{ {
Plugin* p = (*i).second; Plugin* p = (*i).second;
if ( p->HookQueueEvent(event) ) if ( p->HookQueueEvent(event) )
{ {
result = true; result = true;
break; break;
@ -577,6 +587,29 @@ void Manager::HookUpdateNetworkTime(double network_time) const
MetaHookPost(HOOK_UPDATE_NETWORK_TIME, args, HookArgument()); 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 void Manager::MetaHookPre(HookType hook, const HookArgumentList& args) const
{ {
hook_list* l = hooks[HOOK_CALL_FUNCTION]; 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 // 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. // the code for the most common case that no plugin defines the hook.
#define PLUGIN_HOOK_WITH_RESULT(hook, method_call, default_result) \ #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) \ #define PLUGIN_HOOK_VOID(hook, method_call) \
if ( plugin_mgr->HavePluginForHook(plugin::hook) ) plugin_mgr->method_call; if ( plugin_mgr->HavePluginForHook(plugin::hook) ) plugin_mgr->method_call;
@ -160,6 +160,27 @@ public:
*/ */
void DisableHook(HookType hook, Plugin* plugin); 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. // Hook entry functions.
/** /**
@ -208,10 +229,16 @@ public:
void HookUpdateNetworkTime(double network_time) const; 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; 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 * Internal method that registers a freshly instantiated plugin with
* the manager. * the manager.

View file

@ -22,6 +22,7 @@ const char* plugin::hook_name(HookType h)
"QueueEvent", "QueueEvent",
"DrainEvents", "DrainEvents",
"UpdateNetworkTime", "UpdateNetworkTime",
"BroObjDtor",
// MetaHooks // MetaHooks
"MetaHookPre", "MetaHookPre",
"MetaHookPost", "MetaHookPost",
@ -32,6 +33,13 @@ const char* plugin::hook_name(HookType h)
return hook_names[int(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) BifItem::BifItem(const std::string& arg_id, Type arg_type)
{ {
id = arg_id; id = arg_id;
@ -119,6 +127,10 @@ void HookArgument::Describe(ODesc* d) const
case VOID: case VOID:
d->Add("<void>"); d->Add("<void>");
break; break;
case VOIDP:
d->Add("<void ptr>");
break;
} }
} }
@ -262,6 +274,16 @@ void Plugin::DisableHook(HookType hook)
plugin_mgr->DisableHook(hook, this); 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) int Plugin::HookLoadFile(const std::string& file)
{ {
return -1; 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) void Plugin::MetaHookPre(HookType hook, const HookArgumentList& args)
{ {
} }

View file

@ -33,6 +33,7 @@ enum HookType {
HOOK_QUEUE_EVENT, HOOK_QUEUE_EVENT,
HOOK_DRAIN_EVENTS, HOOK_DRAIN_EVENTS,
HOOK_UPDATE_NETWORK_TIME, HOOK_UPDATE_NETWORK_TIME,
HOOK_BRO_OBJ_DTOR,
// Meta hooks. // Meta hooks.
META_HOOK_PRE, META_HOOK_PRE,
@ -69,19 +70,11 @@ public:
std::string description; //< A short textual description of the plugin. Mandatory. std::string description; //< A short textual description of the plugin. Mandatory.
VersionNumber version; //< THe plugin's version. Optional. VersionNumber version; //< THe plugin's version. Optional.
Configuration() 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;
}
private: private:
friend class Plugin; friend class Plugin;
int api_version; // Current BRO_PLUGIN_API_VERSION. Automatically set. int api_version; // Current BRO_PLUGIN_API_VERSION. Automatically set.
}; };
/** /**
@ -141,7 +134,7 @@ class HookArgument
{ {
public: public:
enum Type { 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; } HookArgument() { type = VOID; }
@ -153,6 +146,7 @@ public:
HookArgument(const std::string& a) { type = STRING; arg_string = a; } HookArgument(const std::string& a) { type = STRING; arg_string = a; }
HookArgument(const Val* a) { type = VAL; arg.val = a; } HookArgument(const Val* a) { type = VAL; arg.val = a; }
HookArgument(const val_list* a) { type = VAL_LIST; arg.vals = 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_; } bool AsBool() const { assert(type == BOOL); return arg.bool_; }
double AsDouble() const { assert(type == DOUBLE); return arg.double_; } 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 std::string& AsString() const { assert(type == STRING); return arg_string; }
const Val* AsVal() const { assert(type == VAL); return arg.val; } const Val* AsVal() const { assert(type == VAL); return arg.val; }
const val_list* AsValList() const { assert(type == VAL_LIST); return arg.vals; } 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; } Type GetType() const { return type; }
void Describe(ODesc* d) const; void Describe(ODesc* d) const;
@ -176,6 +171,7 @@ private:
int int_; int int_;
const Val* val; const Val* val;
const val_list* vals; const val_list* vals;
const void* voidp;
} arg; } arg;
std::string arg_string; // Outside union because it has dtor. std::string arg_string; // Outside union because it has dtor.
@ -406,6 +402,23 @@ protected:
*/ */
hook_list EnabledHooks() const; 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 * Virtual method that can be overriden by derived class to provide
* information about further script-level elements that the plugin * information about further script-level elements that the plugin
@ -496,6 +509,18 @@ protected:
*/ */
virtual void HookUpdateNetworkTime(double network_time); 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. // Meta hooks.
/** /**