* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * InspIRCd: (C) 2002-2010 InspIRCd Development Team
* See: http://wiki.inspircd.org/Credits
*
* This program is free but copyrighted software; see
}
};
-/** If you change the module API in any way, increment this value.
- * This MUST be a pure integer, with no parenthesis
+/** InspIRCd major version.
+ * 1.2 -> 102; 2.1 -> 201; 2.12 -> 212
*/
-#define API_VERSION 137
+#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.
+ */
+#define INSPIRCD_VERSION_API 1
/**
* This #define allows us to call a method in all
/** 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<int api>
-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);
+
+ /** Complex version information, including linking compatability data */
+ Version(const std::string &desc, int flags, const std::string& linkdata);
-typedef VersionBase<API_VERSION> Version;
+ 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
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<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->()
+ {
+ if (!value)
+ lookup();
+ return static_cast<T*>(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()
*/
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_OnAcceptConnection,
+ 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_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_END
};
DLLManager* ModuleDLLManager;
/** 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
*/
* @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<std::string>& parameters, User *user, bool validated, const std::string &original_line);
+ virtual ModResult OnPreCommand(std::string &command, std::vector<std::string>& 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,
* @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, User *user, CmdResult result, const std::string &original_line);
+ virtual void OnPostCommand(const std::string &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.
+ */
+ 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
*/
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
*/
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.
*/
/** 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);
-
- /** 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);
+ virtual void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line);
};
*/
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;
*/
IntModuleList EventHandlers[I_END];
+ /** List of data services keyed by name */
+ std::multimap<std::string, ServiceProvider*> DataProviders;
+
/** Simple, bog-standard, boring constructor.
*/
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
/** 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.
*/
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<int,std::string> 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<typename T> inline T* FindDataService(const std::string& name)
+ {
+ 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,
#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
};
#define MODULE_INIT(x) static Module* MK_ ## x() { return new x; } \
- static const AllModuleList PREP_ ## x(&MK_ ## x, #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
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<c>)