X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=include%2Fmodules.h;h=298d963aacc5c68c9ab16e5b3c6d9f2bc9da4d44;hb=84083a73e80734e39892f44411549d2381654c95;hp=ab95bca268c4275c5891ed5c52d7afcc0efbd57c;hpb=c0abad99489eb0ce0a52d98f9d6f76790a6a2db4;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/include/modules.h b/include/modules.h index ab95bca26..298d963aa 100644 --- a/include/modules.h +++ b/include/modules.h @@ -14,6 +14,18 @@ #ifndef __MODULES_H #define __MODULES_H +#include "globals.h" +#include "dynamic.h" +#include "base.h" +#include "ctables.h" +#include "inspsocket.h" +#include +#include +#include +#include "timer.h" +#include "mode.h" +#include "dns.h" + class XLine; /** Used with OnAccessCheck() method of modules @@ -65,18 +77,6 @@ enum MessageType { MSG_NOTICE = 1 }; -#include "globals.h" -#include "dynamic.h" -#include "base.h" -#include "ctables.h" -#include "inspsocket.h" -#include -#include -#include -#include "timer.h" -#include "mode.h" -#include "dns.h" - /** If you change the module API, change this value. * If you have enabled ipv6, the sizes of structs is * different, and modules will be incompatible with @@ -123,19 +123,23 @@ typedef std::map > 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]) \ +#define FOREACH_MOD(y,x) do { \ + EventHandlerIter safei; \ + for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ) \ + { \ + safei = _i; \ + ++safei; \ try \ { \ - ServerInstance->Modules->modules[_i]->x ; \ + (*_i)->x ; \ } \ catch (CoreException& modexcept) \ { \ ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \ } \ + _i = safei; \ } \ - } +} while (0); /** * This #define allows us to call a method in all @@ -143,70 +147,82 @@ typedef std::map > 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]) \ +#define FOREACH_MOD_I(z,y,x) do { \ + EventHandlerIter safei; \ + for (EventHandlerIter _i = z->Modules->EventHandlers[y].begin(); _i != z->Modules->EventHandlers[y].end(); ) \ + { \ + safei = _i; \ + ++safei; \ try \ { \ - z->Modules->modules[_i]->x ; \ + (*_i)->x ; \ } \ catch (CoreException& modexcept) \ { \ z->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \ } \ + _i = safei; \ } \ -} +} 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(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 { \ + EventHandlerIter safei; \ + MOD_RESULT = 0; \ + for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ) \ + { \ + safei = _i; \ + ++safei; \ + try \ + { \ + int res = (*_i)->x ; \ + if (res != 0) { \ + MOD_RESULT = res; \ + break; \ } \ } \ + catch (CoreException& modexcept) \ + { \ + ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \ + } \ + _i = safei; \ } \ - } +} 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 { \ + EventHandlerIter safei; \ + MOD_RESULT = 0; \ + for (EventHandlerIter _i = z->Modules->EventHandlers[y].begin(); _i != z->Modules->EventHandlers[y].end(); ) \ + { \ + safei = _i; \ + ++safei; \ + try \ + { \ + int res = (*_i)->x ; \ + if (res != 0) { \ + MOD_RESULT = res; \ + break; \ } \ } \ + catch (CoreException& modexcept) \ + { \ + z->Log(DEBUG,"Exception caught: %s",modexcept.GetReason()); \ + } \ + _i = safei; \ } \ -} +} while (0); /** Represents a non-local user. * (in fact, any FD less than -1 does) @@ -378,17 +394,19 @@ enum Implementation 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_OnDelLine, I_OnExpireLine, I_OnCleanup, I_OnUserPostNick, I_OnAccessCheck, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule, I_OnUnloadModule, + I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite, I_OnRawMode, 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_OnOperCompare, I_OnChannelPreDelete, 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_OnText, I_OnReadConfig, I_OnDownloadFile, I_END }; +class ConfigReader; + /** Base class for all InspIRCd modules * This class is the base class for InspIRCd modules. All modules must inherit from this class, * its methods will be called when irc server events occur. class inherited from module must be @@ -414,47 +432,20 @@ class CoreExport Module : public Extensible */ virtual ~Module(); + virtual void Prioritize() + { + } + + virtual void OnReadConfig(ServerConfig* config, ConfigReader* coreconf); + + virtual int OnDownloadFile(const std::string &filename, std::istream* &filedata); + /** 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 @@ -479,6 +470,12 @@ class CoreExport Module : public Extensible */ virtual void OnUserDisconnect(User* user); + /** Called whenever a channel is about to be deleted + * @param chan The channel being deleted + * @return An integer specifying whether or not the channel may be deleted. 0 for yes, 1 for no. + */ + virtual int OnChannelPreDelete(Channel *chan); + /** Called whenever a channel is deleted, either by QUIT, KICK or PART. * @param chan The channel being deleted */ @@ -491,8 +488,10 @@ class CoreExport Module : public Extensible * @param channel The channel being joined * @param silent Change this to true if you want to conceal the JOIN command from the other users * of the channel (useful for modules such as auditorium) + * @param sync This is set to true if the JOIN is the result of a network sync and the remote user is being introduced + * to a channel due to the network sync. */ - virtual void OnUserJoin(User* user, Channel* channel, bool &silent); + virtual void OnUserJoin(User* user, Channel* channel, bool sync, bool &silent); /** Called after a user joins a channel * Identical to OnUserJoin, but called immediately afterwards, when any linking module has @@ -595,9 +594,10 @@ class CoreExport Module : public Extensible * can be gauranteed to already have processed the oper-up, for example m_spanningtree has sent * out the OPERTYPE, etc. * @param user The user who is opering up + * @param opername The name of the oper that the user is opering up to. Only valid locally. Empty string otherwise. * @param opertype The opers type name */ - virtual void OnPostOper(User* user, const std::string &opertype); + virtual void OnPostOper(User* user, const std::string &opername, const std::string &opertype); /** Called whenever a user types /INFO. * The User will contain the information of the user who typed the command. Modules may use this @@ -899,18 +899,18 @@ class CoreExport Module : public Extensible */ virtual void OnAddLine(User* source, XLine* line); - /** Called whenever an xline is deleted. + /** Called whenever an xline is deleted MANUALLY. See OnExpireLine for expiry. * This method is triggered after the line is deleted. * @param source The user removing the line or NULL for local server * @param line the line being deleted */ virtual void OnDelLine(User* source, XLine* line); - /** Called whenever a zline is deleted. + /** Called whenever an xline expires. * This method is triggered after the line is deleted. - * @param source The user removing the line - * @param hostmask The hostmask to delete + * @param line The line being deleted. */ + virtual void OnExpireLine(XLine *line); /** Called before your module is unloaded to clean up Extensibles. * This method is called once for every user and channel on the network, @@ -1091,6 +1091,18 @@ class CoreExport Module : public Extensible */ virtual int OnCheckInvite(User* user, Channel* chan); + /** Called whenever a mode character is processed. + * Return 1 from this function to block the mode character from being processed entirely. + * @param user The user who is sending the mode + * @param chan The channel the mode is being sent to (or NULL if a usermode) + * @param mode The mode character being set + * @param param The parameter for the mode or an empty string + * @param adding true of the mode is being added, false if it is being removed + * @param pcnt The parameter count for the mode (0 or 1) + * @return 1 to deny the mode, 0 to allow + */ + virtual int OnRawMode(User* user, Channel* chan, const char mode, const std::string ¶m, bool adding, int pcnt); + /** Called whenever a user joins a channel, to determine if key checks should go ahead or not. * This method will always be called for each join, wether or not the channel is actually +k, and * determines the outcome of an if statement around the whole section of key checking code. @@ -1302,7 +1314,9 @@ class CoreExport Module : public Extensible * @param userlist The user list for the channel (you may change this pointer. * If you want to change the values, take a copy first, and change the copy, then * point the pointer at your copy) - * @return 1 to prevent the user list being sent to the client, 0 to allow it + * @return 1 to prevent the user list being sent to the client, 0 to allow it. + * Returning -1 allows the names list, but bypasses any checks which check for + * channel membership before sending the names list. */ virtual int OnUserList(User* user, Channel* Ptr, CUList* &userlist); @@ -1543,17 +1557,31 @@ 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 ircd_module; -/** A list of loaded Modules +/** A list of modules */ -typedef std::vector ModuleList; +typedef std::vector IntModuleList; -/** A list of loaded module handles (ircd_module) +/** An event handler iterator */ -typedef std::vector ModuleHandleList; +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. @@ -1563,7 +1591,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 */ @@ -1573,7 +1601,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; @@ -1581,32 +1609,92 @@ class CoreExport ModuleManager : public classbase */ InspIRCd* Instance; - public: + /** List of loaded modules and shared object/dll handles + * keyed by module name + */ + std::map > Modules; - std::vector > EventHandlers; + 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() - */ - 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() + /** Event handler hooks. + * This needs to be public to be used by FOREACH_MOD and friends. */ - ModuleList modules; + IntModuleList EventHandlers[I_END]; /** 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 @@ -1639,66 +1727,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 @@ -1801,6 +1829,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 GetAllModuleNames(int filter); }; /** This definition is used as shorthand for the various classes