]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/modules.h
Comments
[user/henk/code/inspircd.git] / include / modules.h
index f6ac7fd613dd4e3b9b819748bf184dd0d8642139..6a56384f5ec05ad306b486768b5eec8b5f1fc136 100644 (file)
@@ -123,19 +123,18 @@ typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
  * 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->Modules->GetCount(); _i++) { \
-       if (ServerInstance->Config->implement_lists[_i][y]) \
-               try \
-               { \
-                       ServerInstance->Modules->modules[_i]->x ; \
-               } \
-               catch (CoreException& modexcept) \
-               { \
-                       ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
-               } \
+#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()); \
+       } \
+}
 
 /**
  * This #define allows us to call a method in all
@@ -143,70 +142,69 @@ typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
  * an instance pointer to the macro. e.g.:
  * 'FOREACH_MOD_I(Instance, OnConnect, OnConnect(user));'
  */
-#define FOREACH_MOD_I(z,y,x) if (z->Config->global_implementation[y] > 0) { \
-       for (int _i = 0; _i <= z->Modules->GetCount(); _i++) { \
-               if (z->Config->implement_lists[_i][y]) \
-               try \
-               { \
-                       z->Modules->modules[_i]->x ; \
-               } \
-               catch (CoreException& modexcept) \
-               { \
-                       z->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
-               } \
+#define FOREACH_MOD_I(z,y,x) \
+for (EventHandlerIter _i = z->Modules->EventHandlers[y].begin(); _i != z->Modules->EventHandlers[y].end(); ++_i) \
+{ \
+       try \
+       { \
+               (*_i)->x ; \
+       } \
+       catch (CoreException& modexcept) \
+       { \
+               z->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
        } \
 }
+
 /**
  * This define is similar to the one above but returns a result in MOD_RESULT.
  * The first module to return a nonzero result is the value to be accepted,
  * and any modules after are ignored.
  */
-#define FOREACH_RESULT(y,x) { if (ServerInstance->Config->global_implementation[y] > 0) { \
-                       MOD_RESULT = 0; \
-                       for (int _i = 0; _i <= ServerInstance->Modules->GetCount(); _i++) { \
-                       if (ServerInstance->Config->implement_lists[_i][y]) { \
-                               try \
-                               { \
-                                       int res = ServerInstance->Modules->modules[_i]->x ; \
-                                       if (res != 0) { \
-                                               MOD_RESULT = res; \
-                                               break; \
-                                       } \
-                               } \
-                               catch (CoreException& modexcept) \
-                               { \
-                                       ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
-                               } \
+#define FOREACH_RESULT(y,x) \
+do { \
+       MOD_RESULT = 0; \
+       for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ++_i) \
+       { \
+               try \
+               { \
+                       int res = (*_i)->x ; \
+                       if (res != 0) { \
+                               MOD_RESULT = res; \
+                               break; \
                        } \
                } \
+               catch (CoreException& modexcept) \
+               { \
+                       ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
+               } \
        } \
- }
+} while(0);
+
 
 /**
  * This define is similar to the one above but returns a result in MOD_RESULT.
  * The first module to return a nonzero result is the value to be accepted,
  * and any modules after are ignored.
  */
-#define FOREACH_RESULT_I(z,y,x) { if (z->Config->global_implementation[y] > 0) { \
-                       MOD_RESULT = 0; \
-                       for (int _i = 0; _i <= z->Modules->GetCount(); _i++) { \
-                       if (z->Config->implement_lists[_i][y]) { \
-                               try \
-                               { \
-                                       int res = z->Modules->modules[_i]->x ; \
-                                       if (res != 0) { \
-                                               MOD_RESULT = res; \
-                                               break; \
-                                       } \
-                               } \
-                               catch (CoreException& modexcept) \
-                               { \
-                                       z->Log(DEBUG,"Exception caught: %s",modexcept.GetReason()); \
-                               } \
+#define FOREACH_RESULT_I(z,y,x) \
+do { \
+       MOD_RESULT = 0; \
+       for (EventHandlerIter _i = z->Modules->EventHandlers[y].begin(); _i != z->Modules->EventHandlers[y].end(); ++_i) \
+       { \
+               try \
+               { \
+                       int res = (*_i)->x ; \
+                       if (res != 0) { \
+                               MOD_RESULT = res; \
+                               break; \
                        } \
                } \
+               catch (CoreException& modexcept) \
+               { \
+                       z->Log(DEBUG,"Exception caught: %s",modexcept.GetReason()); \
+               } \
        } \
-}
+} while (0);
 
 /** Represents a non-local user.
  * (in fact, any FD less than -1 does)
@@ -370,19 +368,24 @@ enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFOR
 
 /** Implementation-specific flags which may be set in Module::Implements()
  */
-enum Implementation {  I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash, I_OnServerRaw, 
-                       I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper, I_OnInfo, I_OnWhois, I_OnUserPreInvite,
-                       I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreNick, I_OnUserMessage, I_OnUserNotice, I_OnMode,
-                       I_OnGetServerDescription, I_OnSyncUser, I_OnSyncChannel, I_OnSyncChannelMetaData, I_OnSyncUserMetaData,
-                       I_OnDecodeMetaData, I_ProtoSendMode, I_ProtoSendMetaData, I_OnWallops, I_OnChangeHost, I_OnChangeName, I_OnAddLine,
-                       I_OnDelLine, I_OnCleanup, I_OnUserPostNick, I_OnAccessCheck, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule, I_OnUnloadModule,
-                       I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnUserRrgister, I_OnCheckInvite,
-                       I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnLocalTopicChange,
-                       I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnOperCompre, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan,
-                       I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, I_OnChangeLocalUserGECOS, I_OnUserRegister,
-                       I_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList,
-                       I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect, I_OnBufferFlushed,
-                       I_OnText };
+enum Implementation
+{
+       I_BEGIN,
+       I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash, I_OnServerRaw, 
+       I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper, I_OnInfo, I_OnWhois, I_OnUserPreInvite,
+       I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreNick, I_OnUserMessage, I_OnUserNotice, I_OnMode,
+       I_OnGetServerDescription, I_OnSyncUser, I_OnSyncChannel, I_OnSyncChannelMetaData, I_OnSyncUserMetaData,
+       I_OnDecodeMetaData, I_ProtoSendMode, I_ProtoSendMetaData, I_OnWallops, I_OnChangeHost, I_OnChangeName, I_OnAddLine,
+       I_OnDelLine, I_OnCleanup, I_OnUserPostNick, I_OnAccessCheck, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule, I_OnUnloadModule,
+       I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnUserRrgister, I_OnCheckInvite,
+       I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnLocalTopicChange,
+       I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnOperCompre, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan,
+       I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, I_OnChangeLocalUserGECOS, I_OnUserRegister,
+       I_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList,
+       I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect, I_OnBufferFlushed,
+       I_OnText,
+       I_END
+};
 
 /** Base class for all InspIRCd modules
  *  This class is the base class for InspIRCd modules. All modules must inherit from this class,
@@ -409,47 +412,16 @@ class CoreExport Module : public Extensible
         */
        virtual ~Module();
 
+       virtual void Prioritize()
+       {
+       }
+
        /** Returns the version number of a Module.
         * The method should return a Version object with its version information assigned via
         * Version::Version
         */
        virtual Version GetVersion();
 
-       /** The Implements function specifies which methods a module should receive events for.
-        * The char* parameter passed to this function contains a set of true or false values
-        * (1 or 0) which indicate wether each function is implemented. You must use the Iimplementation
-        * enum (documented elsewhere on this page) to mark functions as active. For example, to
-        * receive events for OnUserJoin():
-        *
-        * Implements[I_OnUserJoin] = 1;
-        *
-        * @param The implement list
-        */
-       virtual void Implements(char* Implements);
-
-       /** Used to set the 'priority' of a module (e.g. when it is called in relation to other modules.
-        * Some modules prefer to be called before other modules, due to their design. For example, a
-        * module which is expected to operate on complete information would expect to be placed last, so
-        * that any other modules which wish to adjust that information would execute before it, to be sure
-        * its information is correct. You can change your module's priority by returning one of:
-        *
-        * PRIORITY_FIRST - To place your module first in the list
-        * 
-        * PRIORITY_LAST - To place your module last in the list
-        *
-        * PRIORITY_DONTCARE - To leave your module as it is (this is the default value, if you do not implement this function)
-        *
-        * The result of InspIRCd::PriorityBefore() - To move your module before another named module
-        *
-        * The result of InspIRCd::PriorityLast() - To move your module after another named module
-        *
-        * For a good working example of this method call, please see src/modules/m_spanningtree.cpp
-        * and src/modules/m_hostchange.so which make use of it. It is highly recommended that unless
-        * your module has a real need to reorder its priority, it should not implement this function,
-        * as many modules changing their priorities can make the system redundant.
-        */
-       virtual Priority Prioritize();
-
        /** Called when a user connects.
         * The details of the connecting user are available to you in the parameter User *user
         * @param user The user who is connecting
@@ -1538,17 +1510,35 @@ class CoreExport FileReader : public classbase
 };
 
 /** A DLLFactory (designed to load shared objects) containing a
- * handle to a module's init_module() function.
+ * handle to a module's init_module() function. Unfortunately,
+ * due to the design of shared object systems we must keep this
+ * hanging around, as if we remove this handle, we remove the
+ * shared object file from memory (!)
  */
 typedef DLLFactory<Module> ircd_module;
 
-/** A list of loaded Modules
+/** A list of modules
  */
-typedef std::vector<Module*> ModuleList;
+typedef std::vector<Module*> IntModuleList;
 
-/** A list of loaded module handles (ircd_module)
+/** A list of event handlers
  */
-typedef std::vector<ircd_module*> ModuleHandleList;
+typedef std::vector<IntModuleList> EventHandlerList;
+
+/** An event handler iterator
+ */
+typedef IntModuleList::iterator EventHandlerIter;
+
+/** Module priority states
+ */
+enum PriorityState
+{
+       PRIO_DONTCARE,
+       PRIO_FIRST,
+       PRIO_LAST,
+       PRIO_AFTER,
+       PRIO_BEFORE
+};
 
 /** ModuleManager takes care of all things module-related
  * in the core.
@@ -1558,7 +1548,7 @@ class CoreExport ModuleManager : public classbase
  private:
        /** Holds a string describing the last module error to occur
         */
-       char MODERR[MAXBUF];
+       std::string LastModuleError;
  
        /** The feature names published by various modules
         */
@@ -1568,7 +1558,7 @@ class CoreExport ModuleManager : public classbase
         */
        interfacelist Interfaces;
  
-       /** Total number of modules loaded into the ircd, minus one
+       /** Total number of modules loaded into the ircd
         */
        int ModCount; 
        
@@ -1576,29 +1566,92 @@ class CoreExport ModuleManager : public classbase
         */
        InspIRCd* Instance;
 
- public:
-       /** A list of ircd_module* module handles
-        * Note that this list is always exactly 255 in size.
-        * The actual number of loaded modules is available from GetModuleCount()
+       /** List of loaded modules and shared object/dll handles
+        * keyed by module name
         */
-       ModuleHandleList handles;
-       /** A list of Module* module classes
-        * Note that this list is always exactly 255 in size.
-        * The actual number of loaded modules is available from GetModuleCount()
+       std::map<std::string, std::pair<ircd_module*, Module*> > Modules;
+
+ public:
+
+       /** Event handler hooks.
+        * This needs to be public to be used by FOREACH_MOD and friends.
         */
-       ModuleList modules;      
+       EventHandlerList EventHandlers;
 
        /** Simple, bog-standard, boring constructor.
         */
        ModuleManager(InspIRCd* Ins);
 
+       /** Destructor
+        */
        ~ModuleManager(); 
+
+       /** Change the priority of one event in a module.
+        * Each module event has a list of modules which are attached to that event type.
+        * If you wish to be called before or after other specific modules, you may use this
+        * method (usually within void Module::Prioritize()) to set your events priority.
+        * You may use this call in other methods too, however, this is not supported behaviour
+        * for a module.
+        * @param mod The module to change the priority of
+        * @param i The event to change the priority of
+        * @param s The state you wish to use for this event. Use one of
+        * PRIO_FIRST to set the event to be first called, PRIO_LAST to
+        * set it to be the last called, or PRIO_BEFORE and PRIO_AFTER
+        * to set it to be before or after one or more other modules.
+        * @param modules If PRIO_BEFORE or PRIO_AFTER is set in parameter 's',
+        * then this contains a list of one or more modules your module must be 
+        * placed before or after. Your module will be placed before the highest
+        * priority module in this list for PRIO_BEFORE, or after the lowest
+        * priority module in this list for PRIO_AFTER.
+        * @param sz The number of modules being passed for PRIO_BEFORE and PRIO_AFTER.
+        * Defaults to 1, as most of the time you will only want to prioritize your module
+        * to be before or after one other module.
+        */
+       bool SetPriority(Module* mod, Implementation i, PriorityState s, Module** modules = NULL, size_t sz = 1);
+
+       /** Change the priority of all events in a module.
+        * @param mod The module to set the priority of
+        * @param s The priority of all events in the module.
+        * Note that with this method, it is not possible to effectively use
+        * PRIO_BEFORE or PRIO_AFTER, you should use the more fine tuned
+        * SetPriority method for this, where you may specify other modules to
+        * be prioritized against.
+        */
+       bool SetPriority(Module* mod, PriorityState s);
+
+       /** Attach an event to a module.
+        * You may later detatch the event with ModuleManager::Detach().
+        * If your module is unloaded, all events are automatically detatched.
+        * @param i Event type to attach
+        * @param mod Module to attach event to
+        * @return True if the event was attached
+        */
+       bool Attach(Implementation i, Module* mod);
+
+       /** Detatch an event from a module.
+        * This is not required when your module unloads, as the core will
+        * automatically detatch your module from all events it is attached to.
+        * @param i Event type to detach
+        * @param mod Module to detach event from
+        * @param Detach true if the event was detached
+        */
+       bool Detach(Implementation i, Module* mod);
+
+       /** Attach an array of events to a module
+        * @param i Event types (array) to attach
+        * @param mod Module to attach events to
+        */
+       void Attach(Implementation* i, Module* mod, size_t sz);
+
+       /** Detach all events from a module (used on unload)
+        * @param mod Module to detach from
+        */
+       void DetachAll(Module* mod);
  
        /** Returns text describing the last module error
         * @return The last error message to occur
         */
-       const char* LastError();
+       std::string& LastError();
 
        /** Load a given module file
         * @param filename The file to load
@@ -1631,66 +1684,6 @@ class CoreExport ModuleManager : public classbase
         */
        Module* Find(const std::string &name);
  
-       /** Remove a module handle pointer
-        * @param j Index number of the module handle to remove
-        * @return True if a handle existed at the given index, false otherwise
-        */
-       bool EraseHandle(unsigned int j);
-
-       /** Remove a Module pointer
-        * @param j Index number of the Module to remove
-        * @return True if a handle existed at the given index, false otherwise
-        */
-       bool EraseModule(unsigned int j);
-
-       /** Move a given module to a specific slot in the list
-        * @param modulename The module name to relocate
-        * @param slot The slot to move the module into
-        */
-       void MoveTo(std::string modulename,int slot);
-
-       /** Moves the given module to the last slot in the list
-        * @param modulename The module name to relocate
-        */
-       void MoveToLast(std::string modulename);
-
-       /** Moves the given module to the first slot in the list
-        * @param modulename The module name to relocate
-        */
-       void MoveToFirst(std::string modulename);
-
-       /** Moves one module to be placed after another in the list
-        * @param modulename The module name to relocate
-        * @param after The module name to place the module after
-        */
-       void MoveAfter(std::string modulename, std::string after);
-
-       /** Moves one module to be placed before another in the list
-        * @param modulename The module name to relocate
-        * @param after The module name to place the module before
-        */
-       void MoveBefore(std::string modulename, std::string before);
-       
-       /** For use with Module::Prioritize().
-        * When the return value of this function is returned from
-        * Module::Prioritize(), this specifies that the module wishes
-        * to be ordered exactly BEFORE 'modulename'. For more information
-        * please see Module::Prioritize().
-        * @param modulename The module your module wants to be before in the call list
-        * @returns a priority ID which the core uses to relocate the module in the list
-        */
-       long PriorityBefore(const std::string &modulename);
-
-       /** For use with Module::Prioritize().
-        * When the return value of this function is returned from
-        * Module::Prioritize(), this specifies that the module wishes
-        * to be ordered exactly AFTER 'modulename'. For more information please
-        * see Module::Prioritize().
-        * @param modulename The module your module wants to be after in the call list
-        * @returns a priority ID which the core uses to relocate the module in the list
-        */
-       long PriorityAfter(const std::string &modulename);
-
        /** Publish a 'feature'.
         * There are two ways for a module to find another module it depends on.
         * Either by name, using InspIRCd::FindModule, or by feature, using this
@@ -1793,6 +1786,14 @@ class CoreExport ModuleManager : public classbase
         * @return The module name or an empty string
         */
        const std::string& GetModuleName(Module* m);
+
+       /** Return a list of all modules matching the given filter
+        * @param filter This int is a bitmask of flags set in Module::Flags,
+        * such as VF_VENDOR or VF_STATIC. If you wish to receive a list of
+        * all modules with no filtering, set this to 0.
+        * @return The list of module names
+        */
+       const std::vector<std::string> GetAllModuleNames(int filter);
 };
 
 /** This definition is used as shorthand for the various classes