]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/modules.h
Make classbase and refcountbase uncopyable; expand comments on their indended uses
[user/henk/code/inspircd.git] / include / modules.h
index edfe31007df4961e55faee2ed26b48d1c3a85543..96506f5982f48562917e07ffa1e2dbd42e74bbc7 100644 (file)
@@ -104,8 +104,10 @@ struct ModResult {
        }
 };
 
-/** If you change the module API, change this value. */
-#define API_VERSION 13000
+/** If you change the module API in any way, increment this value.
+ * This MUST be a pure integer, with no parenthesis
+ */
+#define API_VERSION 134
 
 class ServerConfig;
 
@@ -114,14 +116,9 @@ class ServerConfig;
 class Module;
 class InspIRCd;
 
-/** Low level definition of a FileReader classes file cache area -
- * a text file seperated into lines.
- */
-typedef std::deque<std::string> file_cache;
-
 /** A set of strings.
  */
-typedef file_cache string_list;
+typedef std::vector<std::string> string_list;
 
 /** Holds a list of 'published features' for modules.
  */
@@ -226,13 +223,14 @@ do { \
 #define IS_AWAY(x) (!x->awaymsg.empty())
 
 /** Holds a module's Version information.
- *  The four members (set by the constructor only) indicate details as to the version number
- *  of a module. A class of type Version is returned by the GetVersion method of the Module class.
- *  The flags and API values represent the module flags and API version of the module.
- *  The API version of a module must match the API version of the core exactly for the module to
- *  load successfully.
+ * The members (set by the constructor only) indicate details as to the version number
+ * of a module. A class of type Version is returned by the GetVersion method of the Module class.
+ *
+ * The core provides only one implementation of the template, causing a run-time linking
+ * error when attempting to load a module compiled against a different API_VERSION.
  */
-class CoreExport Version : public classbase
+template<int api>
+class CoreExport VersionBase
 {
  public:
        /** Module description
@@ -242,87 +240,49 @@ class CoreExport Version : public classbase
         */
        const std::string version;
 
-       /** Flags and API version
+       /** Flags
         */
-       const int Flags, API;
+       const int Flags;
 
        /** Initialize version class
         */
-       Version(const std::string &desc, int flags,
-               int api_ver = API_VERSION, const std::string& src_rev = VERSION " r" REVISION);
+       VersionBase(const std::string &desc, int flags = VF_NONE, const std::string& src_rev = VERSION " r" REVISION);
 };
 
-/** The ModuleMessage class is the base class of Request and Event
- * This class is used to represent a basic data structure which is passed
- * between modules for safe inter-module communications.
- */
-class CoreExport ModuleMessage : public Extensible
-{
- public:
-       /** Destructor
-        */
-       virtual ~ModuleMessage() {};
-};
+typedef VersionBase<API_VERSION> Version;
 
 /** The Request class is a unicast message directed at a given module.
  * When this class is properly instantiated it may be sent to a module
  * using the Send() method, which will call the given module's OnRequest
  * method with this class as its parameter.
  */
-class CoreExport Request : public ModuleMessage
+class CoreExport Request : public classbase
 {
- protected:
-       /** This member holds a pointer to arbitary data set by the emitter of the message
-        */
-       char* data;
+ public:
        /** This should be a null-terminated string identifying the type of request,
         * all modules should define this and use it to determine the nature of the
         * request before they attempt to cast the Request in any way.
         */
-       const char* id;
+       const char* const id;
        /** This is a pointer to the sender of the message, which can be used to
         * directly trigger events, or to create a reply.
         */
-       Module* source;
+       Module* const source;
        /** The single destination of the Request
         */
-       Module* dest;
- public:
-       /** Create a new Request
-        * This is for the 'old' way of casting whatever the data is
-        * to char* and hoping you get the right thing at the other end.
-        * This is slowly being depreciated in favor of the 'new' way.
-        */
-       Request(char* anydata, Module* src, Module* dst);
+       Module* const dest;
+
        /** Create a new Request
         * This is for the 'new' way of defining a subclass
         * of Request and defining it in a common header,
         * passing an object of your Request subclass through
         * as a Request* and using the ID string to determine
-        * what to cast it back to and the other end. This is
-        * much safer as there are no casts not confirmed by
-        * the ID string, and all casts are child->parent and
-        * can be checked at runtime with dynamic_cast<>()
+        * what to cast it back to and the other end.
         */
        Request(Module* src, Module* dst, const char* idstr);
-       /** Fetch the Request data
-        */
-       char* GetData();
-       /** Fetch the ID string
-        */
-       const char* GetId();
-       /** Fetch the request source
-        */
-       Module* GetSource();
-       /** Fetch the request destination (should be 'this' in the receiving module)
-        */
-       Module* GetDest();
        /** Send the Request.
-        * Upon returning the result will be arbitary data returned by the module you
-        * sent the request to. It is up to your module to know what this data is and
-        * how to deal with it.
         */
-       const char* Send();
+       void Send();
 };
 
 
@@ -331,40 +291,27 @@ class CoreExport Request : public ModuleMessage
  * using the Send() method, which will trigger the OnEvent method in
  * all modules passing the object as its parameter.
  */
-class CoreExport Event : public ModuleMessage
+class CoreExport Event : public classbase
 {
- protected:
-       /** This member holds a pointer to arbitary data set by the emitter of the message
-        */
-       char* data;
+ public:
        /** This is a pointer to the sender of the message, which can be used to
         * directly trigger events, or to create a reply.
         */
-       Module* source;
+       Module* const source;
        /** The event identifier.
         * This is arbitary text which should be used to distinguish
         * one type of event from another.
         */
-       std::string id;
- public:
+       const std::string id;
+
        /** Create a new Event
         */
-       Event(char* anydata, Module* src, const std::string &eventid);
-       /** Get the Event data
-        */
-       char* GetData();
-       /** Get the event Source
-        */
-       Module* GetSource();
-       /** Get the event ID.
-        * Use this to determine the event type for safe casting of the data
-        */
-       std::string GetEventID();
+       Event(Module* src, const std::string &eventid);
        /** Send the Event.
         * The return result of an Event::Send() will always be NULL as
         * no replies are expected.
         */
-       char* Send();
+       void Send();
 };
 
 /** Priority types which can be returned from Module::Prioritize()
@@ -381,17 +328,17 @@ enum Implementation
        I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreNick,
        I_OnUserMessage, I_OnUserNotice, I_OnMode, I_OnGetServerDescription, I_OnSyncUser,
        I_OnSyncChannel, I_OnDecodeMetaData, I_OnWallops,
-       I_OnChangeHost, I_OnChangeName, I_OnAddLine, I_OnDelLine, I_OnExpireLine, I_OnCleanup,
+       I_OnChangeHost, I_OnChangeName, I_OnAddLine, I_OnDelLine, I_OnExpireLine,
        I_OnUserPostNick, I_OnPreMode, 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_OnCheckChannelBan, I_OnExtBanCheck,
        I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnPreTopicChange,
-       I_OnPostTopicChange, I_OnEvent, I_OnRequest, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan,
+       I_OnPostTopicChange, I_OnEvent, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan,
        I_OnDelBan, I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
        I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnUserList, I_OnPostCommand, I_OnPostJoin,
-       I_OnWhoisLine, I_OnBuildExemptList, I_OnGarbageCollect,
+       I_OnWhoisLine, I_OnBuildNeighborList, I_OnGarbageCollect,
        I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO,
-       I_OnHostCycle, I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent,
+       I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_OnChannelRestrictionApply,
        I_END
 };
 
@@ -402,12 +349,15 @@ class ConfigReader;
  *  its methods will be called when irc server events occur. class inherited from module must be
  *  instantiated by the ModuleFactory class (see relevent section) for the module to be initialised.
  */
-class CoreExport Module : public Extensible
+class CoreExport Module : public classbase
 {
  public:
        /** File that this module was loaded from
         */
        std::string ModuleSourceFile;
+       /** Reference to the dlopen() value
+        */
+       DLLManager* ModuleDLLManager;
 
        /** Default constructor.
         * Creates a module class.
@@ -416,6 +366,11 @@ class CoreExport Module : public Extensible
         */
        Module();
 
+       /** Clean up prior to destruction
+        * If you override, you must call this AFTER your module's cleanup
+        */
+       virtual CullResult cull();
+
        /** Default destructor.
         * destroys a module class
         */
@@ -673,16 +628,16 @@ class CoreExport Module : public Extensible
         */
        virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list);
 
-       /** Called whenever the server wants to build the exemption list for a channel, but is not directly doing a PRIVMSG or NOTICE.
-        * For example, the spanningtree protocol will call this event when passing a privmsg on (but not processing it directly).
-        * @param message_type The message type, either MSG_PRIVMSG or MSG_NOTICE
-        * @param chan The channel to build the exempt list of
-        * @param sender The original sender of the PRIVMSG or NOTICE
-        * @param status The status char to be used for the channel list
-        * @param exempt_list The exempt list to be populated
-        * @param text The original message text causing the exempt list to be built
+       /** Called when sending a message to all "neighbors" of a given user -
+        * that is, all users that share a common channel. This is used in
+        * commands such as NICK, QUIT, etc.
+        * @param source The source of the message
+        * @param include_c Channels to scan for users to include
+        * @param exceptions Map of user->bool that overrides the inclusion decision
+        *
+        * Set exceptions[user] = true to include, exceptions[user] = false to exclude
         */
-       virtual void OnBuildExemptList(MessageType message_type, Channel* chan, User* sender, char status, CUList &exempt_list, const std::string &text);
+       virtual void OnBuildNeighborList(User* source, UserChanList &include_c, std::map<User*,bool> &exceptions);
 
        /** Called before any nickchange, local or remote. This can be used to implement Q-lines etc.
         * Please note that although you can see remote nickchanges through this function, you should
@@ -957,9 +912,8 @@ class CoreExport Module : public Extensible
         * absolutely neccessary (e.g. a module that extends the features of another
         * module).
         * @param mod A pointer to the new module
-        * @param name The new module's filename
         */
-       virtual void OnLoadModule(Module* mod,const std::string &name);
+       virtual void OnLoadModule(Module* mod);
 
        /** Called whenever a module is unloaded.
         * mod will contain a pointer to the module, and string will contain its name,
@@ -973,7 +927,7 @@ class CoreExport Module : public Extensible
         * @param mod Pointer to the module being unloaded (still valid)
         * @param name The filename of the module being unloaded
         */
-       virtual void OnUnloadModule(Module* mod,const std::string &name);
+       virtual void OnUnloadModule(Module* mod);
 
        /** Called once every five seconds for background processing.
         * This timer can be used to control timed features. Its period is not accurate
@@ -1155,22 +1109,17 @@ class CoreExport Module : public Extensible
         */
        virtual void OnPostTopicChange(User* user, Channel* chan, const std::string &topic);
 
-       /** Called whenever an Event class is sent to all module by another module.
-        * Please see the documentation of Event::Send() for further information. The Event sent can
-        * always be assumed to be non-NULL, you should *always* check the value of Event::GetEventID()
-        * before doing anything to the event data, and you should *not* change the event data in any way!
+       /** Called whenever an Event class is sent to all modules by another module.
+        * You should *always* check the value of Event::id to determine the event type.
         * @param event The Event class being received
         */
-       virtual void OnEvent(Event* event);
+       virtual void OnEvent(Event& event);
 
        /** Called whenever a Request class is sent to your module by another module.
-        * Please see the documentation of Request::Send() for further information. The Request sent
-        * can always be assumed to be non-NULL, you should not change the request object or its data.
-        * Your method may return arbitary data in the char* result which the requesting module
-        * may be able to use for pre-determined purposes (e.g. the results of an SQL query, etc).
+        * The value of Request::id should be used to determine the type of request.
         * @param request The Request class being received
         */
-       virtual const char* OnRequest(Request* request);
+       virtual void OnRequest(Request& request);
 
        /** Called whenever a password check is to be made. Replaces the old OldOperCompare API.
         * The password field (from the config file) is in 'password' and is to be compared against
@@ -1319,12 +1268,6 @@ class CoreExport Module : public Extensible
 
        virtual ModResult OnNumeric(User* user, unsigned int numeric, const std::string &text);
 
-       /** Called for every time the user's host or ident changes, to indicate wether or not the 'Changing host'
-        * message should be sent, if enabled. Certain modules such as auditorium may opt to hide this message
-        * even if it is enabled.
-        */
-       virtual ModResult OnHostCycle(User* user);
-
        /** Called whenever a result from /WHO is about to be returned
         * @param source The user running the /WHO query
         * @param user The user that this line of the query is about
@@ -1332,6 +1275,12 @@ class CoreExport Module : public Extensible
         * @param line The raw line to send; modifiable, if empty no line will be returned.
         */
        virtual void OnSendWhoLine(User* source, User* user, Channel* channel, std::string& line);
+
+       /** Called to check whether a channel restriction mode applies to a user on it
+        * @return MOD_RES_DENY to apply the restriction, MOD_RES_ALLOW to bypass
+        * the restriction, or MOD_RES_PASSTHRU to check restriction status normally
+        */
+       virtual ModResult OnChannelRestrictionApply(User* user, Channel* chan, const char* restriction);
 };
 
 
@@ -1417,6 +1366,7 @@ class CoreExport ConfigReader : public classbase
         * A call to GetError() resets the error flag back to 0.
         */
        long GetError();
+
        /** Counts the number of times a given tag appears in the config file.
         * This method counts the number of times a tag appears in a config file, for use where
         * there are several tags of the same kind, e.g. with opers and connect types. It can be
@@ -1424,13 +1374,6 @@ class CoreExport ConfigReader : public classbase
         * multiple instance tag.
         */
        int Enumerate(const std::string &tag);
-
-       /** Returns the number of items within a tag.
-        * For example if the tag was &lt;test tag="blah" data="foo"&gt; then this
-        * function would return 2. Spaces and newlines both qualify as valid seperators
-        * between values.
-        */
-       int EnumerateValues(const std::string &tag, int index);
 };
 
 
@@ -1444,7 +1387,7 @@ class CoreExport FileReader : public classbase
 {
        /** The file contents
         */
-       file_cache fc;
+       std::vector<std::string> fc;
 
        /** Content size in bytes
         */
@@ -1507,14 +1450,6 @@ class CoreExport FileReader : public classbase
        int FileSize();
 };
 
-/** A DLLFactory (designed to load shared objects) containing a
- * 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 modules
  */
 typedef std::vector<Module*> IntModuleList;
@@ -1548,13 +1483,16 @@ class CoreExport ModuleManager : public classbase
        /** List of loaded modules and shared object/dll handles
         * keyed by module name
         */
-       std::map<std::string, std::pair<ircd_module*, Module*> > Modules;
+       std::map<std::string, Module*> Modules;
 
        enum {
                PRIO_STATE_FIRST,
                PRIO_STATE_AGAIN,
                PRIO_STATE_LAST
        } prioritizationState;
+
+       /** Internal unload module hook */
+       bool CanUnload(Module*);
  public:
 
        /** Event handler hooks.
@@ -1643,15 +1581,24 @@ class CoreExport ModuleManager : public classbase
         */
        bool Load(const char* filename);
 
-       /** Unload a given module file
-        * @param filename The file to unload
-        * @return True if the module was unloaded
+       /** Unload a given module file. Note that the module will not be
+        * completely gone until the cull list has finished processing.
+        *
+        * @return true on success; if false, LastError will give a reason
+        */
+       bool Unload(Module* module);
+
+       /** Run an asynchronous reload of the given module. When the reload is
+        * complete, the callback will be run with true if the reload succeeded
+        * and false if it did not.
         */
-       bool Unload(const char* filename);
+       void Reload(Module* module, HandlerBase1<void, bool>* callback);
 
        /** Called by the InspIRCd constructor to load all modules from the config file.
         */
        void LoadAll();
+       void UnloadAll();
+       void DoSafeUnload(Module*);
 
        /** Get the total number of currently loaded modules
         * @return The number of loaded modules
@@ -1788,6 +1735,16 @@ class CoreExport ModuleManager : public classbase
        const std::vector<std::string> GetAllModuleNames(int filter);
 };
 
+/** Do not mess with these functions unless you know the C preprocessor
+ * well enough to explain why they are needed. The order is important.
+ */
+#define MODULE_INIT_STR MODULE_INIT_STR_FN_2(MODULE_INIT_SYM)
+#define MODULE_INIT_STR_FN_2(x) MODULE_INIT_STR_FN_1(x)
+#define MODULE_INIT_STR_FN_1(x) #x
+#define MODULE_INIT_SYM MODULE_INIT_SYM_FN_2(API_VERSION)
+#define MODULE_INIT_SYM_FN_2(x) MODULE_INIT_SYM_FN_1(x)
+#define MODULE_INIT_SYM_FN_1(x) inspircd_module_ ## x
+
 /** This definition is used as shorthand for the various classes
  * and functions needed to make a module loadable by the OS.
  * It defines the class factory and external init_module function.
@@ -1795,7 +1752,7 @@ class CoreExport ModuleManager : public classbase
 #ifdef WINDOWS
 
 #define MODULE_INIT(y) \
-       extern "C" DllExport Module * init_module() \
+       extern "C" DllExport Module * MODULE_INIT_SYM() \
        { \
                return new y; \
        } \
@@ -1813,7 +1770,7 @@ class CoreExport ModuleManager : public classbase
 #else
 
 #define MODULE_INIT(y) \
-       extern "C" DllExport Module * init_module() \
+       extern "C" DllExport Module * MODULE_INIT_SYM() \
        { \
                return new y; \
        }