X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=include%2Fmodules.h;h=9857012fcfc0ac1c71793198e15f5b0a902d5e0c;hb=4c751dbbe8945e5efc230a59b0ed51c2ba10cf92;hp=ad9cf05b8cee7021987d084f4323c85f978bc992;hpb=a59d08fffd3dc8a9850ce34c9928fb6382b9b37f;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/include/modules.h b/include/modules.h index ad9cf05b8..9857012fc 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1,18 +1,30 @@ -/* +------------------------------------+ - * | Inspire Internet Relay Chat Daemon | - * +------------------------------------+ +/* + * InspIRCd -- Internet Relay Chat Daemon * - * InspIRCd: (C) 2002-2009 InspIRCd Development Team - * See: http://wiki.inspircd.org/Credits + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2006-2007, 2009 Dennis Friis + * Copyright (C) 2003-2008 Craig Edwards + * Copyright (C) 2008 Thomas Stagner + * Copyright (C) 2007 Robin Burchell + * Copyright (C) 2006-2007 Oliver Lupton + * Copyright (C) 2003 randomdan * - * This program is free but copyrighted software; see - * the file COPYING for details. + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. * - * --------------------------------------------------- + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ -#ifndef __MODULES_H -#define __MODULES_H + +#ifndef MODULES_H +#define MODULES_H #include "dynamic.h" #include "base.h" @@ -25,8 +37,6 @@ #include "mode.h" #include "dns.h" -class XLine; - /** Used to define a set of behavior bits for a module */ enum ModuleFlags { @@ -38,13 +48,6 @@ enum ModuleFlags { VF_CORE = 16 // module is a core command, can be assumed loaded on all servers }; -/** Used with SendToMode() - */ -enum WriteModeFlags { - WM_AND = 1, - WM_OR = 2 -}; - /** Used to represent an event type, for user, channel or server */ enum TargetTypeFlags { @@ -103,33 +106,17 @@ struct ModResult { } }; -/** If you change the module API in any way, increment this value. - * This MUST be a pure integer, with no parenthesis - */ -#define API_VERSION 135 - -class ServerConfig; - -/* Forward-delacare module for ModuleMessage etc - */ -class Module; -class InspIRCd; - -/** A set of strings. - */ -typedef std::vector string_list; - -/** Holds a list of 'published features' for modules. - */ -typedef std::map featurelist; - -/** Holds a list of modules which implement an interface +/** InspIRCd major version. + * 1.2 -> 102; 2.1 -> 201; 2.12 -> 212 */ -typedef std::deque modulelist; - -/** Holds a list of all modules which implement interfaces, by interface name +#define INSPIRCD_VERSION_MAJ 200 +/** InspIRCd API version. + * If you change any API elements, increment this value. This counter should be + * reset whenever the major version is changed. Modules can use these two values + * and numerical comparisons in preprocessor macros if they wish to support + * multiple versions of InspIRCd in one file. */ -typedef std::map > interfacelist; +#define INSPIRCD_VERSION_API 9 /** * This #define allows us to call a method in all @@ -198,57 +185,32 @@ 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 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. */ -template -class CoreExport VersionBase +class CoreExport Version { public: /** Module description */ const std::string description; - /** Version information. - */ - const std::string version; /** Flags */ const int Flags; - /** Initialize version class - */ - VersionBase(const std::string &desc, int flags = VF_NONE, const std::string& src_rev = VERSION " r" REVISION); -}; + /** Server linking description string */ + const std::string link_data; + + /** Simple module version */ + Version(const std::string &desc, int flags = VF_NONE); -typedef VersionBase Version; + /** Complex version information, including linking compatability data */ + Version(const std::string &desc, int flags, const std::string& linkdata); + + virtual ~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 @@ -266,10 +228,10 @@ class CoreExport Request : public classbase /** This is a pointer to the sender of the message, which can be used to * directly trigger events, or to create a reply. */ - Module* const source; + ModuleRef source; /** The single destination of the Request */ - Module* const dest; + ModuleRef dest; /** Create a new Request * This is for the 'new' way of defining a subclass @@ -296,7 +258,7 @@ class CoreExport Event : public classbase /** This is a pointer to the sender of the message, which can be used to * directly trigger events, or to create a reply. */ - Module* const source; + ModuleRef source; /** The event identifier. * This is arbitary text which should be used to distinguish * one type of event from another. @@ -313,9 +275,48 @@ class CoreExport Event : public classbase void Send(); }; +class CoreExport DataProvider : public ServiceProvider +{ + public: + DataProvider(Module* Creator, const std::string& Name) + : ServiceProvider(Creator, Name, SERVICE_DATA) {} +}; + +class CoreExport dynamic_reference_base : public interfacebase +{ + private: + std::string name; + protected: + DataProvider* value; + public: + ModuleRef creator; + dynamic_reference_base(Module* Creator, const std::string& Name); + ~dynamic_reference_base(); + inline void ClearCache() { value = NULL; } + inline const std::string& GetProvider() { return name; } + void SetProvider(const std::string& newname); + void lookup(); + operator bool(); + static void reset_all(); +}; + +template +class dynamic_reference : public dynamic_reference_base +{ + public: + dynamic_reference(Module* Creator, const std::string& Name) + : dynamic_reference_base(Creator, Name) {} + inline T* operator->() + { + if (!value) + lookup(); + return static_cast(value); + } +}; + /** Priority types which can be used by Module::Prioritize() */ -enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER }; +enum Priority { PRIORITY_FIRST, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER }; /** Implementation-specific flags which may be set in Module::Implements() */ @@ -326,29 +327,27 @@ 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_OnSyncChannel, I_OnDecodeMetaData, I_OnWallops, 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_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_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_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnPostCommand, I_OnPostJoin, + I_OnWhoisLine, I_OnBuildNeighborList, I_OnGarbageCollect, I_OnSetConnectClass, I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO, - I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_OnChannelRestrictionApply, + I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_OnSetUserIP, 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 * instantiated by the ModuleFactory class (see relevent section) for the module to be initialised. */ -class CoreExport Module : public classbase +class CoreExport Module : public classbase, public usecountbase { public: /** File that this module was loaded from @@ -358,13 +357,22 @@ class CoreExport Module : public classbase */ DLLManager* ModuleDLLManager; + /** If true, this module will be unloaded soon, further unload attempts will fail + * Value is used by the ModuleManager internally, you should not modify it + */ + bool dying; + /** Default constructor. - * Creates a module class. - * @param Me An instance of the InspIRCd class which will be saved into ServerInstance for your use - * \exception ModuleException Throwing this class, or any class derived from ModuleException, causes loading of the module to abort. + * Creates a module class. Don't do any type of hook registration or checks + * for other modules here; do that in init(). */ Module(); + /** Module setup + * \exception ModuleException Throwing this class, or any class derived from ModuleException, causes loading of the module to abort. + */ + virtual void init() {} + /** Clean up prior to destruction * If you override, you must call this AFTER your module's cleanup */ @@ -389,7 +397,7 @@ class CoreExport Module : public classbase * 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 @@ -407,7 +415,7 @@ class CoreExport Module : public classbase * 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 @@ -427,6 +435,7 @@ class CoreExport Module : public classbase * @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. * @param created This is true if the join created the channel + * @param except_list A list of users not to send to. */ virtual void OnUserJoin(Membership* memb, bool sync, bool created, CUList& except_list); @@ -435,13 +444,14 @@ class CoreExport Module : public classbase * seen the join. * @param memb The channel membership created */ - virtual void OnPostJoin(Membership*); + virtual void OnPostJoin(Membership* memb); /** Called when a user parts a channel. * The details of the leaving user are available to you in the parameter User *user, * and the details of the channel they have left is available in the variable Channel *channel * @param memb The channel membership being destroyed * @param partmessage The part message, or an empty string (may be modified) + * @param except_list A list of users to not send to. */ virtual void OnUserPart(Membership* memb, std::string &partmessage, CUList& except_list); @@ -511,8 +521,7 @@ class CoreExport Module : public classbase * output to be sent to the user by the core. If you do this you must produce your own numerics, * notices etc. * @param source The user issuing the kick - * @param user The user being kicked - * @param chan The channel the user is being kicked from + * @param memb The channel membership of the user who is being kicked. * @param reason The kick reason * @return 1 to prevent the kick, 0 to continue normally, -1 to explicitly allow the kick regardless of normal operation */ @@ -522,9 +531,9 @@ class CoreExport Module : public classbase * If this method is called, the kick is already underway and cannot be prevented, so * to prevent a kick, please use Module::OnUserPreKick instead of this method. * @param source The user issuing the kick - * @param user The user being kicked - * @param chan The channel the user is being kicked from + * @param memb The channel membership of the user who was kicked. * @param reason The kick reason + * @param except_list A list of users to not send to. */ virtual void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& except_list); @@ -658,6 +667,7 @@ class CoreExport Module : public classbase * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL) * @param text the text being sent by the user * @param status The status being used, e.g. PRIVMSG @#chan has status== '@', 0 to send to everyone. + * @param exempt_list A list of users to not send to. */ virtual void OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list); @@ -669,6 +679,7 @@ class CoreExport Module : public classbase * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL) * @param text the text being sent by the user * @param status The status being used, e.g. NOTICE @#chan has status== '@', 0 to send to everyone. + * @param exempt_list A list of users to not send to. */ virtual void OnUserNotice(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list); @@ -683,6 +694,7 @@ class CoreExport Module : public classbase * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL) * @param text the text being sent by the user * @param status The status being used, e.g. NOTICE @#chan has status== '@', 0 to send to everyone. + * @param exempt_list A list of users not to send to. For channel messages, this will usually contain just the sender. */ virtual void OnText(User* user, void* dest, int target_type, const std::string &text, char status, CUList &exempt_list); @@ -752,7 +764,6 @@ class CoreExport Module : public classbase /** Allows module data, sent via ProtoSendMetaData, to be decoded again by a receiving module. * Please see src/modules/m_swhois.cpp for a working example of how to use this method call. - * @param target_type The type of item to decode data for, TYPE_USER or TYPE_CHANNEL * @param target The Channel* or User* that data should be added to * @param extname The extension name which is being sent * @param extdata The extension data, encoded at the other end by an identical module through OnSyncChannelMetaData or OnSyncUserMetaData @@ -784,7 +795,6 @@ class CoreExport Module : public classbase * More documentation to follow soon. Please see src/modules/m_swhois.cpp for example of * how to use this function. * @param opaque An opaque pointer set by the protocol module, should not be modified! - * @param target_type The type of item to decode data for, TYPE_USER or TYPE_CHANNEL * @param target The Channel* or User* that metadata should be sent for * @param extname The extension name to send metadata for * @param extdata Encoded data for this extension name, which will be encoded at the oppsite end by an identical module using OnDecodeMetaData @@ -814,7 +824,7 @@ class CoreExport Module : public classbase /** Called whenever a user's IDENT is changed. * This event triggers after the name has been set. * @param user The user who's IDENT is being changed - * @param gecos The new IDENT being set on the user + * @param ident The new IDENT being set on the user */ virtual void OnChangeIdent(User* user, const std::string &ident); @@ -898,6 +908,7 @@ class CoreExport Module : public classbase * @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); @@ -924,7 +935,6 @@ class CoreExport Module : public classbase * absolutely neccessary (e.g. a module that extends the features of another * module). * @param mod Pointer to the module being unloaded (still valid) - * @param name The filename of the module being unloaded */ virtual void OnUnloadModule(Module* mod); @@ -947,14 +957,13 @@ class CoreExport Module : public classbase * method returns, it will be passed an invalid pointer to the user object and crash!) * @param command The command being executed * @param parameters An array of array of characters containing the parameters for the command - * @param pcnt The nuimber of parameters passed to the command * @param user the user issuing the command * @param validated True if the command has passed all checks, e.g. it is recognised, has enough parameters, the user has permission to execute it, etc. * You should only change the parameter list and command string if validated == false (e.g. before the command lookup occurs). * @param original_line The entire original line as passed to the parser from the user * @return 1 to block the command, 0 to allow */ - virtual ModResult OnPreCommand(std::string &command, std::vector& parameters, User *user, bool validated, const std::string &original_line); + virtual ModResult OnPreCommand(std::string &command, std::vector& parameters, LocalUser *user, bool validated, const std::string &original_line); /** Called after any command has been executed. * This event occurs for all registered commands, wether they are registered in the core, @@ -963,12 +972,16 @@ class CoreExport Module : public classbase * provided. * @param command The command being executed * @param parameters An array of array of characters containing the parameters for the command - * @param pcnt The nuimber of parameters passed to the command * @param user the user issuing the command * @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& parameters, User *user, CmdResult result, const std::string &original_line); + virtual void OnPostCommand(const std::string &command, const std::vector& 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. + */ + virtual void OnUserInit(LocalUser* user); /** Called to check if a user who is connecting can now be allowed to register * If any modules return false for this function, the user is held in the waiting @@ -980,7 +993,7 @@ class CoreExport Module : public classbase * @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 @@ -991,7 +1004,7 @@ class CoreExport Module : public classbase * @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 @@ -1024,6 +1037,7 @@ class CoreExport Module : public classbase * return 1 to explicitly allow the join to go ahead or 0 to ignore the event. * @param user The user joining the channel * @param chan The channel being joined + * @param keygiven The key given on joining the channel. * @return 1 to explicitly allow the join, 0 to proceed as normal */ virtual ModResult OnCheckKey(User* user, Channel* chan, const std::string &keygiven); @@ -1080,7 +1094,7 @@ class CoreExport Module : public classbase * @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. @@ -1088,7 +1102,7 @@ class CoreExport Module : public classbase * @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 @@ -1096,7 +1110,7 @@ class CoreExport Module : public classbase * @param user The user changing the topic * @param chan The channels who's topic is being changed * @param topic The actual topic text - * @param 1 to block the topic change, 0 to allow + * @return 1 to block the topic change, 0 to allow */ virtual ModResult OnPreTopicChange(User* user, Channel* chan, const std::string &topic); @@ -1124,7 +1138,7 @@ class CoreExport Module : public classbase * The password field (from the config file) is in 'password' and is to be compared against * 'input'. This method allows for encryption of passwords (oper, connect:allow, die/restart, etc). * You should return a nonzero value to override the normal comparison, or zero to pass it on. - * @param ex The object that's causing the authentication (User* for etc, Server* for ). + * @param ex The object that's causing the authentication (User* for \ \ etc, Server* for \). * @param password The password from the configuration file (the password="" value). * @param input The password entered by the user or whoever. * @param hashtype The hash value from the config @@ -1167,53 +1181,61 @@ class CoreExport Module : public classbase virtual ModResult OnDelBan(User* source, Channel* channel,const std::string &banmask); /** Called to install an I/O hook on an event handler - * @param user The item to possibly install the I/O hook on - * @param via The port that connected on + * @param user The socket to possibly install the I/O hook on + * @param via The port that the user connected on */ - virtual void OnHookIO(StreamSocket*, ListenSocketBase* via); + virtual void OnHookIO(StreamSocket* user, 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 sock The socket connection for the new user + * @param client The client IP address and port + * @param server The server IP address and port + */ + virtual ModResult OnAcceptConnection(int fd, ListenSocket* sock, 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 * no information relating to a user record as the connection has not been assigned yet. * There are no return values from this call as all modules get an opportunity if required to * process the connection. - * @param fd The file descriptor returned from accept() + * @param sock The socket in question * @param client The client IP address and port * @param server The server IP address and port - * @param localport The local port number the user connected to */ - virtual void OnStreamSocketAccept(StreamSocket*, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server); + virtual void OnStreamSocketAccept(StreamSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server); /** * Called when a hooked stream has data to write, or when the socket * engine returns it as writable - * @param socket The socket in question + * @param sock The socket in question * @param sendq Data to send to the socket * @return 1 if the sendq has been completely emptied, 0 if there is * still data to send, and -1 if there was an error */ - virtual int OnStreamSocketWrite(StreamSocket*, std::string& sendq); + virtual int OnStreamSocketWrite(StreamSocket* sock, std::string& sendq); /** Called immediately before any socket is closed. When this event is called, shutdown() * has not yet been called on the socket. - * @param fd The file descriptor of the socket prior to close() + * @param sock The socket in question */ - virtual void OnStreamSocketClose(StreamSocket*); + virtual void OnStreamSocketClose(StreamSocket* sock); /** Called immediately upon connection of an outbound BufferedSocket which has been hooked * by a module. - * @param fd The file descriptor of the socket immediately after connect() + * @param sock The socket in question */ - virtual void OnStreamSocketConnect(StreamSocket*); + virtual void OnStreamSocketConnect(StreamSocket* sock); /** * Called when the stream socket has data to read - * @param socket The socket that is ready + * @param sock The socket that is ready * @param recvq The receive queue that new data should be appended to * @return 1 if new data has been read, 0 if no new data is ready (but the * socket is still connected), -1 if there was an error or close */ - virtual int OnStreamSocketRead(StreamSocket*, std::string& recvq); + virtual int OnStreamSocketRead(StreamSocket* sock, std::string& recvq); /** Called whenever a user sets away or returns from being away. * The away message is available as a parameter, but should not be modified. @@ -1225,15 +1247,6 @@ class CoreExport Module : public classbase */ virtual ModResult OnSetAway(User* user, const std::string &awaymsg); - /** Called whenever a NAMES list is requested. - * You can produce the nameslist yourself, overriding the current list, - * and if you do you must return 1. If you do not handle the names list, - * return 0. - * @param The user requesting the NAMES list - * @param Ptr The channel the NAMES list is requested for - */ - virtual ModResult OnUserList(User* user, Channel* Ptr); - /** Called whenever a line of WHOIS output is sent to a user. * You may change the numeric and the text of the output by changing * the values numeric and text, but you cannot change the user the @@ -1254,6 +1267,12 @@ class CoreExport Module : public classbase */ virtual void OnGarbageCollect(); + /** Called when a user's connect class is being matched + * @return MOD_RES_ALLOW to force the class to match, MOD_RES_DENY to forbid it, or + * MOD_RES_PASSTHRU to allow normal matching (by host/port). + */ + virtual ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass); + /** Add test suite hooks here. These are used for testing functionality of a module * via the --testsuite debugging parameter. */ @@ -1269,17 +1288,17 @@ class CoreExport Module : public classbase /** Called whenever a result from /WHO is about to be returned * @param source The user running the /WHO query + * @param params The parameters to the /WHO query * @param user The user that this line of the query is about - * @param channel The channel being queried (or NULL if not a channel query) * @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); + virtual void OnSendWhoLine(User* source, const std::vector& params, User* user, 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 + /** Called whenever a local user's IP is set for the first time, or when a local user's IP changes due to + * a module like m_cgiirc changing it. + * @param user The user whose IP is being set */ - virtual ModResult OnChannelRestrictionApply(User* user, Channel* chan, const char* restriction); + virtual void OnSetUserIP(LocalUser* user); }; @@ -1467,14 +1486,6 @@ class CoreExport ModuleManager */ std::string LastModuleError; - /** The feature names published by various modules - */ - featurelist Features; - - /** The interface names published by various modules - */ - interfacelist Interfaces; - /** Total number of modules loaded into the ircd */ int ModCount; @@ -1499,6 +1510,9 @@ class CoreExport ModuleManager */ IntModuleList EventHandlers[I_END]; + /** List of data services keyed by name */ + std::multimap DataProviders; + /** Simple, bog-standard, boring constructor. */ ModuleManager(); @@ -1519,16 +1533,17 @@ class CoreExport ModuleManager * PRIO_FIRST to set the event to be first called, PRIO_LAST to * set it to be the last called, or PRIO_BEFORE and PRIORITY_AFTER * to set it to be before or after one or more other modules. - * @param modules If PRIO_BEFORE or PRIORITY_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 PRIORITY_AFTER. - * @param sz The number of modules being passed for PRIO_BEFORE and PRIORITY_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. + * @param which If PRIO_BEFORE or PRIORITY_AFTER is set in parameter 's', + * then this contains a the module that your module must be placed before + * or after. */ - bool SetPriority(Module* mod, Implementation i, Priority s, Module** modules = NULL, size_t sz = 1); + bool SetPriority(Module* mod, Implementation i, Priority s, Module* which = NULL); + + /** Backwards compat interface */ + inline bool SetPriority(Module* mod, Implementation i, Priority s, Module** dptr) + { + return SetPriority(mod, i, s, *dptr); + } /** Change the priority of all events in a module. * @param mod The module to set the priority of @@ -1554,13 +1569,14 @@ class CoreExport ModuleManager * 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 + * @return 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 + * @param sz The size of the implementation array */ void Attach(Implementation* i, Module* mod, size_t sz); @@ -1576,9 +1592,10 @@ class CoreExport ModuleManager /** Load a given module file * @param filename The file to load + * @param defer Defer module init (loading many modules) * @return True if the module was found and loaded */ - bool Load(const char* filename); + bool Load(const std::string& filename, bool defer = false); /** Unload a given module file. Note that the module will not be * completely gone until the cull list has finished processing. @@ -1614,116 +1631,27 @@ class CoreExport ModuleManager */ Module* Find(const std::string &name); - /** 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 - * function. A feature is an arbitary string which identifies something this - * module can do. For example, if your module provides SSL support, but other - * modules provide SSL support too, all the modules supporting SSL should - * publish an identical 'SSL' feature. This way, any module requiring use - * of SSL functions can just look up the 'SSL' feature using FindFeature, - * then use the module pointer they are given. - * @param FeatureName The case sensitive feature name to make available - * @param Mod a pointer to your module class - * @returns True on success, false if the feature is already published by - * another module. - */ - bool PublishFeature(const std::string &FeatureName, Module* Mod); - - /** Publish a module to an 'interface'. - * Modules which implement the same interface (the same way of communicating - * with other modules) can publish themselves to an interface, using this - * method. When they do so, they become part of a list of related or - * compatible modules, and a third module may then query for that list - * and know that all modules within that list offer the same API. - * A prime example of this is the hashing modules, which all accept the - * same types of Request class. Consider this to be similar to PublishFeature, - * except for that multiple modules may publish the same 'feature'. - * @param InterfaceName The case sensitive interface name to make available - * @param Mod a pointer to your module class - * @returns True on success, false on failure (there are currently no failure - * cases) - */ - bool PublishInterface(const std::string &InterfaceName, Module* Mod); - - /** Return a pair saying how many other modules are currently using the - * interfaces provided by module m. - * @param m The module to count usage for - * @return A pair, where the first value is the number of uses of the interface, - * and the second value is the interface name being used. - */ - std::pair GetInterfaceInstanceCount(Module* m); - - /** Mark your module as using an interface. - * If you mark your module as using an interface, then that interface - * module may not unload until your module has unloaded first. - * This can be used to prevent crashes by ensuring code you depend on - * is always in memory while your module is active. - * @param InterfaceName The interface to use - */ - void UseInterface(const std::string &InterfaceName); - - /** Mark your module as finished with an interface. - * If you used UseInterface() above, you should use this method when - * your module is finished with the interface (usually in its destructor) - * to allow the modules which implement the given interface to be unloaded. - * @param InterfaceName The interface you are finished with using. - */ - void DoneWithInterface(const std::string &InterfaceName); - - /** Unpublish a 'feature'. - * When your module exits, it must call this method for every feature it - * is providing so that the feature table is cleaned up. - * @param FeatureName the feature to remove - */ - bool UnpublishFeature(const std::string &FeatureName); - - /** Unpublish your module from an interface - * When your module exits, it must call this method for every interface - * it is part of so that the interfaces table is cleaned up. Only when - * the last item is deleted from an interface does the interface get - * removed. - * @param InterfaceName the interface to be removed from - * @param Mod The module to remove from the interface list - */ - bool UnpublishInterface(const std::string &InterfaceName, Module* Mod); - - /** Find 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 the - * InspIRCd::PublishFeature method. A feature is an arbitary string which - * identifies something this module can do. For example, if your module - * provides SSL support, but other modules provide SSL support too, all - * the modules supporting SSL should publish an identical 'SSL' feature. - * To find a module capable of providing the feature you want, simply - * call this method with the feature name you are looking for. - * @param FeatureName The feature name you wish to obtain the module for - * @returns A pointer to a valid module class on success, NULL on failure. - */ - Module* FindFeature(const std::string &FeatureName); - - /** Find an 'interface'. - * An interface is a list of modules which all implement the same API. - * @param InterfaceName The Interface you wish to obtain the module - * list of. - * @return A pointer to a deque of Module*, or NULL if the interface - * does not exist. - */ - modulelist* FindInterface(const std::string &InterfaceName); - - /** Determine if a module has published the named interface. - * This could be used in, for example, OnLoadModule to pick up other modules that can be used. - * @param mod The module to check. - * @param InterfaceName the interface you want to check for - * @return True if the module provides the interface, false otherwise. - */ - bool ModuleHasInterface(Module* mod, const std::string& InterfaceName); - - /** Given a pointer to a Module, return its filename - * @param m The module pointer to identify - * @return The module name or an empty string - */ - const std::string& GetModuleName(Module* m); + /** Register a service provided by a module */ + void AddService(ServiceProvider&); + + /** Unregister a service provided by a module */ + void DelService(ServiceProvider&); + + inline void AddServices(ServiceProvider** list, int count) + { + for(int i=0; i < count; i++) + AddService(*list[i]); + } + + /** Find a service by name. + * If multiple modules provide a given service, the first one loaded will be chosen. + */ + ServiceProvider* FindService(ServiceType Type, const std::string& name); + + template inline T* FindDataService(const std::string& name) + { + return static_cast(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, @@ -1740,15 +1668,40 @@ class CoreExport ModuleManager #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 +#define MODULE_INIT_SYM MODULE_INIT_SYM_FN_2(INSPIRCD_VERSION_MAJ, INSPIRCD_VERSION_API) +#define MODULE_INIT_SYM_FN_2(x,y) MODULE_INIT_SYM_FN_1(x,y) +#define MODULE_INIT_SYM_FN_1(x,y) inspircd_module_ ## x ## _ ## y + +#ifdef PURE_STATIC + +struct AllCommandList { + typedef Command* (*fn)(Module*); + AllCommandList(fn cmd); +}; +#define COMMAND_INIT(x) static Command* MK_ ## x(Module* m) { return new x(m); } \ + static const AllCommandList PREP_ ## x(&MK_ ## x); + +struct AllModuleList { + typedef Module* (*fn)(); + fn init; + std::string name; + AllModuleList(fn mod, const std::string& Name); +}; + +#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 + +#else /** 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. */ -#ifdef WINDOWS +#ifdef _WIN32 #define MODULE_INIT(y) \ extern "C" DllExport Module * MODULE_INIT_SYM() \ @@ -1764,7 +1717,8 @@ class CoreExport ModuleManager break; \ } \ return TRUE; \ - } + } \ + extern "C" DllExport const char inspircd_src_version[] = VERSION " r" REVISION; #else @@ -1772,9 +1726,12 @@ class CoreExport ModuleManager extern "C" DllExport Module * MODULE_INIT_SYM() \ { \ return new y; \ - } + } \ + extern "C" const char inspircd_src_version[] = VERSION " r" REVISION; #endif #define COMMAND_INIT(c) MODULE_INIT(CommandModule) #endif + +#endif