/**
* 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));'
+ * 'FOREACH_MOD(OnConnect,(user));'
*/
#define FOREACH_MOD(y,x) do { \
- EventHandlerIter safei; \
- for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ) \
+ const IntModuleList& _handlers = ServerInstance->Modules->EventHandlers[I_ ## y]; \
+ for (IntModuleList::const_reverse_iterator _i = _handlers.rbegin(), _next; _i != _handlers.rend(); _i = _next) \
{ \
- safei = _i; \
- ++safei; \
+ _next = _i+1; \
try \
{ \
- (*_i)->x ; \
+ (*_i)->y x ; \
} \
catch (CoreException& modexcept) \
{ \
ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Exception caught: %s",modexcept.GetReason()); \
} \
- _i = safei; \
} \
} while (0);
*/
#define DO_EACH_HOOK(n,v,args) \
do { \
- EventHandlerIter iter_ ## n = ServerInstance->Modules->EventHandlers[I_ ## n].begin(); \
- while (iter_ ## n != ServerInstance->Modules->EventHandlers[I_ ## n].end()) \
+ const IntModuleList& _handlers = ServerInstance->Modules->EventHandlers[I_ ## n]; \
+ for (IntModuleList::const_reverse_iterator _i = _handlers.rbegin(), _next; _i != _handlers.rend(); _i = _next) \
{ \
- Module* mod_ ## n = *iter_ ## n; \
- iter_ ## n ++; \
+ _next = _i+1; \
try \
{ \
- v = (mod_ ## n)->n args;
+ v = (*_i)->n args;
#define WHILE_EACH_HOOK(n) \
} \
catch (CoreException& except_ ## n) \
{ \
ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Exception caught: %s", (except_ ## n).GetReason()); \
- (void) mod_ ## n; /* catch mismatched pairs */ \
} \
} \
} while(0)
: ServiceProvider(Creator, Name, SERVICE_DATA) {}
};
-class CoreExport dynamic_reference_base : public interfacebase
-{
- private:
- std::string name;
- void resolve();
- protected:
- ServiceProvider* value;
- public:
- ModuleRef creator;
- dynamic_reference_base(Module* Creator, const std::string& Name);
- ~dynamic_reference_base();
- inline const std::string& GetProvider() { return name; }
- void SetProvider(const std::string& newname);
- void check();
- operator bool() { return (value != NULL); }
- static void reset_all();
-};
-
-inline void dynamic_reference_base::check()
-{
- if (!value)
- throw ModuleException("Dynamic reference to '" + name + "' failed to resolve");
-}
-
-template<typename T>
-class dynamic_reference : public dynamic_reference_base
-{
- public:
- dynamic_reference(Module* Creator, const std::string& Name)
- : dynamic_reference_base(Creator, Name) {}
-
- inline T* operator->()
- {
- check();
- return static_cast<T*>(value);
- }
-
- T* operator*()
- {
- return operator->();
- }
-};
-
-template<typename T>
-class dynamic_reference_nocheck : public dynamic_reference_base
-{
- public:
- dynamic_reference_nocheck(Module* Creator, const std::string& Name)
- : dynamic_reference_base(Creator, Name) {}
-
- T* operator->()
- {
- return static_cast<T*>(value);
- }
-
- T* operator*()
- {
- return operator->();
- }
-};
-
-class ModeReference : public dynamic_reference_nocheck<ModeHandler>
-{
- public:
- ModeReference(Module* mod, const std::string& modename)
- : dynamic_reference_nocheck<ModeHandler>(mod, "mode/" + modename) {}
-};
-
/** Priority types which can be used by Module::Prioritize()
*/
enum Priority { PRIORITY_FIRST, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER };
enum Implementation
{
I_BEGIN,
- I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash,
+ I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart,
I_OnSendSnotice, I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper, I_OnInfo, I_OnWhois,
I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNick,
I_OnUserMessage, I_OnMode, I_OnGetServerDescription, I_OnSyncUser,
I_OnSyncChannel, I_OnDecodeMetaData, I_OnAcceptConnection, I_OnUserInit,
I_OnChangeHost, I_OnChangeName, I_OnAddLine, I_OnDelLine, I_OnExpireLine,
- I_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule,
+ I_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, I_OnLoadModule,
I_OnUnloadModule, I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite,
I_OnRawMode, I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnCheckChannelBan, I_OnExtBanCheck,
I_OnStats, I_OnChangeLocalUserHost, I_OnPreTopicChange,
*/
class CoreExport Module : public classbase, public usecountbase
{
+ /** Detach an event from this module
+ * @param i Event type to detach
+ */
+ void DetachEvent(Implementation i);
+
public:
/** File that this module was loaded from
*/
{
}
+ /** This method is called when you should reload module specific configuration:
+ * on boot, on a /REHASH and on module load.
+ * @param status The current status, can be inspected for more information;
+ * also used for reporting configuration errors and warnings.
+ */
+ virtual void ReadConfig(ConfigStatus& status);
+
/** Returns the version number of a Module.
* The method should return a Version object with its version information assigned via
* Version::Version
*/
virtual void OnModuleRehash(User* user, const std::string ¶meter);
- /** Called on rehash.
- * This method is called after a rehash has completed. You should use it to reload any module
- * configuration from the main configuration file.
- * @param user The user that performed the rehash, if it was initiated by a user and that user
- * is still connected.
- */
- virtual void OnRehash(User* user);
-
/** Called whenever a snotice is about to be sent to a snomask.
* snomask and type may both be modified; the message may not.
* @param snomask The snomask the message is going to (e.g. 'A')
virtual void OnText(User* user, void* dest, int target_type, const std::string &text, char status, CUList &exempt_list);
/** Called after every MODE command sent from a user
- * The dest variable contains a User* if target_type is TYPE_USER and a Channel*
- * if target_type is TYPE_CHANNEL. The text variable contains the remainder of the
- * mode string after the target, e.g. "+wsi" or "+ooo nick1 nick2 nick3".
+ * Either the usertarget or the chantarget variable contains the target of the modes,
+ * the actual target will have a non-NULL pointer.
+ * The modes vector contains the remainder of the mode string after the target,
+ * e.g.: "+wsi" or ["+ooo", "nick1", "nick2", "nick3"].
* @param user The user sending the MODEs
- * @param dest The target of the modes (User* or Channel*)
- * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
- * @param text The actual modes and their parameters if any
+ * @param usertarget The target user of the modes, NULL if the target is a channel
+ * @param chantarget The target channel of the modes, NULL if the target is a user
+ * @param modes The actual modes and their parameters if any
* @param translate The translation types of the mode parameters
*/
- virtual void OnMode(User* user, void* dest, int target_type, const std::vector<std::string> &text, const std::vector<TranslateType> &translate);
+ virtual void OnMode(User* user, User* usertarget, Channel* chantarget, const std::vector<std::string>& modes, const std::vector<TranslateType>& translate);
/** Allows modules to alter or create server descriptions
* Whenever a module requires a server description, for example for display in
/** Called when a 005 numeric is about to be output.
* The module should modify the 005 numeric if needed to indicate its features.
- * @param output The 005 map to be modified if neccessary.
+ * @param tokens The 005 map to be modified if neccessary.
*/
virtual void On005Numeric(std::map<std::string, std::string>& tokens);
*/
virtual ModResult OnKill(User* source, User* dest, const std::string &reason);
- /** Called when an oper wants to disconnect a remote user via KILL
- * @param source The user sending the KILL
- * @param dest The user being killed
- * @param reason The kill reason
- * @param operreason The oper kill reason
- */
- virtual void OnRemoteKill(User* source, User* dest, const std::string &reason, const std::string &operreason);
-
/** Called whenever a module is loaded.
* mod will contain a pointer to the module, and string will contain its name,
* for example m_widgets.so. This function is primary for dependency checking,
* @param result The return code given by the command handler, one of CMD_SUCCESS or CMD_FAILURE
* @param original_line The entire original line as passed to the parser from the user
*/
- virtual void OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, LocalUser *user, CmdResult result, const std::string &original_line);
+ virtual void OnPostCommand(Command* command, const std::vector<std::string>& parameters, LocalUser* user, CmdResult result, const std::string& original_line);
/** Called when a user is first connecting, prior to starting DNS lookups, checking initial
* connect class, or accepting any commands.
FileReader() : totalSize(0) { }
/** Initializes a new file reader and reads the specified file.
- * @param file The file to read into memory.
+ * @param filename The file to read into memory.
*/
FileReader(const std::string& filename);
*/
class CoreExport ModuleManager
{
+ public:
+ typedef std::vector<ServiceProvider*> ServiceList;
+
private:
/** Holds a string describing the last module error to occur
*/
std::string LastModuleError;
- /** Total number of modules loaded into the ircd
- */
- int ModCount;
-
/** List of loaded modules and shared object/dll handles
* keyed by module name
*/
/** Internal unload module hook */
bool CanUnload(Module*);
+
+ /** Loads all core modules (cmd_*)
+ */
+ void LoadCoreModules(std::map<std::string, ServiceList>& servicemap);
+
+ /** Calls the Prioritize() method in all loaded modules
+ * @return True if all went well, false if a dependency loop was detected
+ */
+ bool PrioritizeHooks();
+
public:
+ typedef std::map<std::string, Module*> ModuleMap;
/** Event handler hooks.
* This needs to be public to be used by FOREACH_MOD and friends.
/** List of data services keyed by name */
std::multimap<std::string, ServiceProvider*> DataProviders;
+ /** A list of ServiceProviders waiting to be registered.
+ * Non-NULL when constructing a Module, NULL otherwise.
+ * When non-NULL ServiceProviders add themselves to this list on creation and the core
+ * automatically registers them (that is, call AddService()) after the Module is constructed,
+ * and before Module::init() is called.
+ * If a service is created after the construction of the Module (for example in init()) it
+ * has to be registered manually.
+ */
+ ServiceList* NewServices;
+
/** Simple, bog-standard, boring constructor.
*/
ModuleManager();
*/
void DetachAll(Module* mod);
+ /** Attach all events to a module (used on module load)
+ * @param mod Module to attach to all events
+ */
+ void AttachAll(Module* mod);
+
/** Returns text describing the last module error
* @return The last error message to occur
*/
void UnloadAll();
void DoSafeUnload(Module*);
- /** Get the total number of currently loaded modules
- * @return The number of loaded modules
- */
- int GetCount()
- {
- return this->ModCount;
- }
-
/** Find a module by name, and return a Module* to it.
* This is preferred over iterating the module lists yourself.
* @param name The module name to look up
/** Unregister a service provided by a module */
void DelService(ServiceProvider&);
+ /** Register all services in a given ServiceList
+ * @param list The list containing the services to register
+ */
+ void AddServices(const ServiceList& list);
+
inline void AddServices(ServiceProvider** list, int count)
{
for(int i=0; i < count; i++)
return static_cast<T*>(FindService(SERVICE_DATA, name));
}
- /** 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
+ /** Get a map of all loaded modules keyed by their name
+ * @return A ModuleMap containing all loaded modules
*/
- const std::vector<std::string> GetAllModuleNames(int filter);
+ const ModuleMap& GetModules() const { return Modules; }
};
/** Do not mess with these functions unless you know the C preprocessor
};
#define MODULE_INIT(x) static Module* MK_ ## x() { return new x; } \
- static const AllModuleList PREP_ ## x(&MK_ ## x, MODNAMESTR);
-
-#define MODNAMESTR MODNAMESTR_FN_2(MODNAME)
-#define MODNAMESTR_FN_2(x) MODNAMESTR_FN_1(x)
-#define MODNAMESTR_FN_1(x) #x
+ static const AllModuleList PREP_ ## x(&MK_ ## x, MODNAME ".so");
#else
{ \
return new y; \
} \
- extern "C" const char inspircd_src_version[] = VERSION " r" REVISION;
+ extern "C" DllExport const char inspircd_src_version[] = VERSION " " REVISION;
#endif
#define COMMAND_INIT(c) MODULE_INIT(CommandModule<c>)