The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download | Blog
Personal tools

Development/Hooking

From Inspire IRCd (InspIRCd)

Jump to: navigation, search
Development
This page has been marked as Development Material.
Information posted here may be subject to change and/or only available in unstable versions of InspIRCd.


Contents

Hooking Redesign

Introduction: What is hooking?

Hooking is the way the IRCd communicates from core to modules, and from modules to modules. e.g. OnUserConnect, and other events.

Current Situation

Currently, when an event is called, each module is polled to check whether it contains a handler for an event. If one exists, it is called:

/**
 * This #define allows us to call a method in all
 * loaded modules in a readable simple way, e.g.:
 * 'FOREACH_MOD(I_OnConnect,OnConnect(user));'
 */
#define FOREACH_MOD(y,x) if (ServerInstance->Config->global_implementation[y] > 0) { \
        for (int _i = 0; _i <= ServerInstance->GetModuleCount(); _i++) { \
        if (ServerInstance->Config->implement_lists[_i][y]) \
                try \
                { \
                        ServerInstance->modules[_i]->x ; \
                } \
                catch (CoreException& modexcept) \
                { \
                        ServerInstance->Log(DEFAULT,"Exception cought: %s",modexcept.GetReason()); \
                } \
        } \
  }

While this is okay, it is slow.

New Way

Hooks should use an array (or worst case, a map) - where enum Implementation is used as a key. The storage of the array should be an array (or vector?) of pointers of type Module *.

Basically, the buckets are different event types, holding pointers to modules that have registered a hook on that event. :)

This will work almost exactly the same way to the above, but it will be faster.

[19:45] <Brain> ive been giving it some thought
[19:45] <w00t> mm?
[19:45] <Brain> its the next logical thing after oms module loader tidyup
[19:45] <Brain> i want to tie the new priority system and implements system into it
[19:46] <Brain> priority and implements determine both position in those vectors
[19:46] <Brain> and presence in them
[19:46] <Brain> make sense?
[19:46] <Brain> e.g. you can do
[19:46] <Brain> ServerInstance->SetPriority(I_OnUserJoin, this, PRI_FIRST);
[19:46] <Brain> per event priority
[19:46] <Brain> that just bumps your Module* to the start of the list
[19:46] <Brain> (for that event)
[19:47] <Brain> instead of the Implements[x] = 1;
[19:47] <Brain> we do:   ServerInstance->Attach(I_OnUserJoin, this);
[19:47] <Brain> we also provide a Detatch() so you can cancel triggering of events on the fly
[19:47] <Brain> both of those just insert and remove from the vectors documented in your hooking doc
[19:47] <Brain> :P
[19:47] <w00t> man oh man, writing out a list of 36 lines of Attach() will suck :P
[19:47] <Brain> nah
[19:48] <Brain> bool Attach (EventType* n, Module* hooker);
[19:48] <Brain> so:
[19:48] <Brain> EventType[] = { I_OnUserJoin, I_OnUserPart ..... };
[19:48] <Brain> ->Attach( ThatArray, this);
[19:48] <Brain> :p
[19:48] <Brain> ;)
[19:49] <Brain> good?
[19:49] <w00t> will they automatically deattach?
[19:49] <Brain> yes
[19:49] <Brain> on unload
[19:49] <w00t> on unload
[19:49] <Brain> but you can detatch
[19:49] <Brain> and re-attach
[19:49] <Brain> at any other time :P
[19:50] <Brain> ofc i'll need help porting all the modules to use Attach
[19:50] <Brain> and i have only 2 days to get the framework of this in before i go to LV
[19:50] <Brain> ohhh, i love a challenge :D

New FOREACH_MOD

 #define FOREACH_MOD(y,x) \
 for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ++_i) \
 { \
         try \
         { \
                 (*_i)->x ; \
         } \
         catch (CoreException& modexcept) \
         { \
                 ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
         } \
 }

-- Much better :)

New event structure

typedef std::vector<Module*> IntModuleList;
IntModuleList EventHandlers[I_END];
  • I_END is the enum after the last event type.