#include "mode.h"
#include "dns.h"
-class XLine;
-
/** Used to define a set of behavior bits for a module
*/
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
-};
-
-/** Used with SendToMode()
- */
-enum WriteModeFlags {
- WM_AND = 1,
- WM_OR = 2
+ 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 to represent an event type, for user, channel or server
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;
/** 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;
-
-/* Forward-delacare module for ModuleMessage etc
- */
-class Module;
-class InspIRCd;
-
-/** A set of strings.
- */
-typedef std::vector<std::string> string_list;
-
-/** Holds a list of 'published features' for modules.
- */
-typedef std::map<std::string,Module*> featurelist;
-
-/** Holds a list of modules which implement an interface
- */
-typedef std::deque<Module*> modulelist;
-
-/** Holds a list of all modules which implement interfaces, by interface name
- */
-typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
+#define API_VERSION 137
/**
* This #define allows us to call a method in all
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.
* error when attempting to load a module compiled against a different API_VERSION.
*/
template<int api>
-class CoreExport VersionBase : public classbase
+class CoreExport VersionBase
{
public:
/** Module description
/** Initialize version class
*/
- VersionBase(const std::string &desc, int flags = VF_NONE, int dummy = 0, 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);
};
typedef VersionBase<API_VERSION> Version;
/** 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
/** 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.
void Send();
};
-/** Priority types which can be returned from Module::Prioritize()
+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();
+};
+
+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 };
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_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_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 Extensible
+class CoreExport Module : public classbase, public usecountbase
{
public:
/** File that this module was loaded from
/** 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
* 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
* 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
* @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
* @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
* @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.
* @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
* @param user The item to possibly install the I/O hook on
* @param via The port that <user> 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
* 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
/** 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
*/
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;
+
+ /** List of all dynamic references that are currently active */
+ std::vector<dynamic_reference_base*> ActiveDynrefs;
+
/** Simple, bog-standard, boring constructor.
*/
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<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&);
+
+ 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_SYM_FN_2(x) MODULE_INIT_SYM_FN_1(x)
#define MODULE_INIT_SYM_FN_1(x) inspircd_module_ ## x
+#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, #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.
#define COMMAND_INIT(c) MODULE_INIT(CommandModule<c>)
#endif
+
+#endif