X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;ds=sidebyside;f=include%2Fmodules.h;h=08f1a2dc0cf84eace0a4b576e1de8688ad097ad0;hb=b16e16ac1bae4ac5494778b4b8a7009febb58137;hp=ca345dbc15d590bec3519be0b17b904c4013fbc6;hpb=085a8bc6605d3d07bfe5137423c4a7a02978cd88;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/include/modules.h b/include/modules.h index ca345dbc1..08f1a2dc0 100644 --- a/include/modules.h +++ b/include/modules.h @@ -33,10 +33,9 @@ enum ModuleFlags { VF_NONE = 0, // module is not special at all VF_STATIC = 1, // module is static, cannot be /unloadmodule'd VF_VENDOR = 2, // module is a vendor module (came in the original tarball, not 3rd party) - VF_SERVICEPROVIDER = 4, // module provides a service to other modules (can be a dependency) - VF_COMMON = 8, // module needs to be common on all servers in a network to link - VF_OPTCOMMON = 16, // module should be common on all servers for unsurprising behavior - VF_CORE = 32 // module is a core command, can be assumed loaded on all servers + VF_COMMON = 4, // module needs to be common on all servers in a network to link + VF_OPTCOMMON = 8, // module should be common on all servers for unsurprising behavior + VF_CORE = 16 // module is a core command, can be assumed loaded on all servers }; /** Used with SendToMode() @@ -74,26 +73,26 @@ struct ModResult { int res; ModResult() : res(0) {} explicit ModResult(int r) : res(r) {} - bool operator==(const ModResult& r) const + inline bool operator==(const ModResult& r) const { return res == r.res; } - bool operator!=(const ModResult& r) const + inline bool operator!=(const ModResult& r) const { return res != r.res; } - bool operator!() const + inline bool operator!() const { return !res; } - bool check(bool def) const + inline bool check(bool def) const { return (res == 1 || (res == 0 && def)); } /** * Merges two results, preferring ALLOW to DENY */ - ModResult operator+(const ModResult& r) const + inline ModResult operator+(const ModResult& r) const { if (res == r.res || r.res == 0) return *this; @@ -104,8 +103,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 137 class ServerConfig; @@ -114,14 +115,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 file_cache; - /** A set of strings. */ -typedef file_cache string_list; +typedef std::vector string_list; /** Holds a list of 'published features' for modules. */ @@ -202,37 +198,15 @@ do { \ WHILE_EACH_HOOK(n); \ } while (0) -/** Represents a non-local user. - * (in fact, any FD less than -1 does) - */ -#define FD_MAGIC_NUMBER -42 -/** Represents a fake user (i.e. a server) - */ -#define FD_FAKEUSER_NUMBER -7 - -/* Useful macros */ - -/** Is a local user */ -#define IS_LOCAL(x) (x->GetFd() > -1) -/** Is a remote user */ -#define IS_REMOTE(x) (x->GetFd() < 0) -/** Is a fake user */ -#define IS_SERVER(x) (x->GetFd() == FD_FAKEUSER_NUMBER) -/** Is a module created user */ -#define IS_MODULE_CREATED(x) (x->GetFd() == FD_MAGIC_NUMBER) -/** Is an oper */ -#define IS_OPER(x) (!x->oper.empty()) -/** Is away */ -#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 +class CoreExport VersionBase { public: /** Module description @@ -242,87 +216,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 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; + ModuleRef 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); + ModuleRef 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,43 +267,30 @@ 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; + ModuleRef 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() +/** Priority types which can be used by Module::Prioritize() */ enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER }; @@ -380,18 +303,18 @@ enum Implementation I_OnSendSnotice, 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_OnDecodeMetaData, I_OnWallops, - I_OnChangeHost, I_OnChangeName, I_OnAddLine, I_OnDelLine, I_OnExpireLine, I_OnCleanup, + I_OnSyncChannel, I_OnDecodeMetaData, I_OnWallops, I_OnAcceptConnection, + 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_OnStats, I_OnChangeLocalUserHost, I_OnPreTopicChange, + 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_OnBuildNeighborList, I_OnGarbageCollect, I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO, - I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, + I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_OnChannelRestrictionApply, I_END }; @@ -402,15 +325,17 @@ 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 { + unsigned int refcount; + friend class reference_base; public: /** File that this module was loaded from */ std::string ModuleSourceFile; /** Reference to the dlopen() value */ - DLLFactory* ModuleDLLFactory; + DLLManager* ModuleDLLManager; /** Default constructor. * Creates a module class. @@ -422,7 +347,7 @@ class CoreExport Module : public Extensible /** Clean up prior to destruction * If you override, you must call this AFTER your module's cleanup */ - virtual bool cull(); + virtual CullResult cull(); /** Default destructor. * destroys a module class @@ -443,7 +368,7 @@ class CoreExport Module : public Extensible * The details of the connecting user are available to you in the parameter User *user * @param user The user who is connecting */ - virtual void OnUserConnect(User* user); + virtual void OnUserConnect(LocalUser* user); /** Called when a user quits. * The details of the exiting user are available to you in the parameter User *user @@ -461,7 +386,7 @@ class CoreExport Module : public Extensible * which might assign resources to user, such as dns lookups, objects and sockets. * @param user The user who is disconnecting */ - virtual void OnUserDisconnect(User* user); + virtual void OnUserDisconnect(LocalUser* user); /** Called whenever a channel is about to be deleted * @param chan The channel being deleted @@ -965,9 +890,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, @@ -981,7 +905,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 @@ -1035,7 +959,7 @@ class CoreExport Module : public Extensible * @param user The user to check * @return true to indicate readiness, false if otherwise */ - virtual ModResult OnCheckReady(User* user); + virtual ModResult OnCheckReady(LocalUser* user); /** Called whenever a user is about to register their connection (e.g. before the user * is sent the MOTD etc). Modules can use this method if they are performing a function @@ -1046,7 +970,7 @@ class CoreExport Module : public Extensible * @param user The user registering * @return 1 to indicate user quit, 0 to continue */ - virtual ModResult OnUserRegister(User* user); + virtual ModResult OnUserRegister(LocalUser* user); /** Called whenever a user joins a channel, to determine if invite checks should go ahead or not. * This method will always be called for each join, wether or not the channel is actually +i, and @@ -1135,7 +1059,7 @@ class CoreExport Module : public Extensible * @param newhost The new hostname * @return 1 to deny the host change, 0 to allow */ - virtual ModResult OnChangeLocalUserHost(User* user, const std::string &newhost); + virtual ModResult OnChangeLocalUserHost(LocalUser* user, const std::string &newhost); /** Called whenever a change of a local users GECOS (fullname field) is attempted. * return 1 to deny the name change, or 0 to allow it. @@ -1143,7 +1067,7 @@ class CoreExport Module : public Extensible * @param newhost The new GECOS * @return 1 to deny the GECOS change, 0 to allow */ - virtual ModResult OnChangeLocalUserGECOS(User* user, const std::string &newhost); + virtual ModResult OnChangeLocalUserGECOS(LocalUser* user, const std::string &newhost); /** Called before a topic is changed. * Return 1 to deny the topic change, 0 to check details on the change, -1 to let it through with no checks @@ -1163,22 +1087,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 @@ -1230,7 +1149,16 @@ class CoreExport Module : public Extensible * @param user The item to possibly install the I/O hook on * @param via The port that connected on */ - virtual void OnHookIO(StreamSocket*, ListenSocketBase* via); + virtual void OnHookIO(StreamSocket*, ListenSocket* via); + + /** Called when a port accepts a connection + * Return MOD_RES_ACCEPT if you have used the file descriptor. + * @param fd The file descriptor returned from accept() + * @param from The local port the user connected to + * @param client The client IP address and port + * @param server The server IP address and port + */ + virtual ModResult OnAcceptConnection(int fd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server); /** Called immediately after any connection is accepted. This is intended for raw socket * processing (e.g. modules which wrap the tcp connection within another library) and provides @@ -1334,6 +1262,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); }; @@ -1350,7 +1284,7 @@ class CoreExport Module : public Extensible * Constructing the class using one parameter allows you to specify a path to your own configuration * file, otherwise, inspircd.conf is read. */ -class CoreExport ConfigReader : public classbase +class CoreExport ConfigReader : public interfacebase { protected: /** Error code @@ -1419,6 +1353,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 @@ -1426,13 +1361,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 <test tag="blah" data="foo"> then this - * function would return 2. Spaces and newlines both qualify as valid seperators - * between values. - */ - int EnumerateValues(const std::string &tag, int index); }; @@ -1446,7 +1374,7 @@ class CoreExport FileReader : public classbase { /** The file contents */ - file_cache fc; + std::vector fc; /** Content size in bytes */ @@ -1520,7 +1448,7 @@ typedef IntModuleList::iterator EventHandlerIter; /** ModuleManager takes care of all things module-related * in the core. */ -class CoreExport ModuleManager : public classbase +class CoreExport ModuleManager { private: /** Holds a string describing the last module error to occur @@ -1549,6 +1477,9 @@ class CoreExport ModuleManager : public classbase PRIO_STATE_AGAIN, PRIO_STATE_LAST } prioritizationState; + + /** Internal unload module hook */ + bool CanUnload(Module*); public: /** Event handler hooks. @@ -1637,15 +1568,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* 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 @@ -1782,6 +1722,16 @@ class CoreExport ModuleManager : public classbase const std::vector 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. @@ -1789,7 +1739,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; \ } \ @@ -1807,7 +1757,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; \ }