diff options
| author | Adam <Adam@anope.org> | 2014-04-20 14:35:14 -0400 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2014-04-20 14:35:14 -0400 |
| commit | 26ac315192e0d8a04d50e910697ab794eedf0cc1 (patch) | |
| tree | b9916f14fe35ce5c4de95c4194ca4ea0cb30812f /include | |
| parent | 0b6476f06ff9ce06545c421143c7d7163c750aa5 (diff) | |
New event system
Diffstat (limited to 'include')
39 files changed, 1845 insertions, 1200 deletions
diff --git a/include/base.h b/include/base.h index a28695c5f..ad2b3cee6 100644 --- a/include/base.h +++ b/include/base.h @@ -32,13 +32,14 @@ class CoreExport Base class ReferenceBase { - protected: - bool invalid; + static std::set<ReferenceBase *> *references; public: - ReferenceBase() : invalid(false) { } - ReferenceBase(const ReferenceBase &other) : invalid(other.invalid) { } - virtual ~ReferenceBase() { } - inline void Invalidate() { this->invalid = true; } + static void ResetAll(); + + ReferenceBase(); + virtual ~ReferenceBase(); + virtual void Invalidate() anope_abstract; + virtual void Reset() { } }; /** Used to hold pointers to objects that may be deleted. A Reference will @@ -49,8 +50,11 @@ class Reference : public ReferenceBase { protected: T *ref; + + virtual void Check() { } + public: - Reference() : ref(NULL) + Reference() : ref(nullptr) { } @@ -60,19 +64,24 @@ class Reference : public ReferenceBase ref->AddReference(this); } - Reference(const Reference<T> &other) : ReferenceBase(other), ref(other.ref) + Reference(const Reference<T> &other) : ref(other.ref) { - if (operator bool()) + if (ref) ref->AddReference(this); } virtual ~Reference() { - if (operator bool()) - ref->DelReference(this); + if (*this) + this->ref->DelReference(this); } - inline Reference<T>& operator=(const Reference<T> &other) + void Invalidate() override + { + ref = nullptr; + } + + Reference<T>& operator=(const Reference<T> &other) { if (this != &other) { @@ -80,7 +89,6 @@ class Reference : public ReferenceBase this->ref->DelReference(this); this->ref = other.ref; - this->invalid = other.invalid; if (*this) this->ref->AddReference(this); @@ -88,36 +96,31 @@ class Reference : public ReferenceBase return *this; } - /* We explicitly call operator bool here in several places to prevent other - * operators, such operator T*, from being called instead, which will mess - * with any class inheriting from this that overloads this operator. - */ - virtual operator bool() + explicit operator bool() { - if (!this->invalid) - return this->ref != NULL; - return false; + Check(); + return this->ref != nullptr; } - inline operator T*() + operator T*() { - if (operator bool()) + if (*this) return this->ref; - return NULL; + return nullptr; } - inline T* operator->() + T* operator->() { - if (operator bool()) + if (*this) return this->ref; - return NULL; + return nullptr; } - inline T* operator*() + T* operator*() { - if (operator bool()) + if (*this) return this->ref; - return NULL; + return nullptr; } /** Note that we can't have an operator< that returns this->ref < other.ref @@ -132,9 +135,9 @@ class Reference : public ReferenceBase * actually referred to. */ - inline bool operator==(const Reference<T> &other) + bool operator==(const Reference<T> &other) { - if (!this->invalid) + if (*this) return this->ref == other; return false; } diff --git a/include/defs.h b/include/defs.h index 3d8ebf4ff..b53e512d6 100644 --- a/include/defs.h +++ b/include/defs.h @@ -14,7 +14,6 @@ class AccessGroup; class AutoKick; class BotInfo; -class CallBack; class ChanAccess; class Channel; class ChannelInfo; @@ -25,7 +24,6 @@ class Command; class CommandSource; namespace Configuration { struct Conf; } class ConnectionSocket; -namespace DNS { struct Query; } class Entry; class IdentifyRequest; class InfoFormatter; diff --git a/include/event.h b/include/event.h new file mode 100644 index 000000000..b55559b48 --- /dev/null +++ b/include/event.h @@ -0,0 +1,1018 @@ +/* + * + * (C) 2014 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + */ + +#pragma once + +#include "service.h" +#include "modules.h" + +struct Events +{ + virtual ~Events() { } +}; + +/* uninstantiated */ +template<typename EventHandler, typename Func, typename Return, typename... Args> +struct Caller; + +/* specialization for void */ +template<typename EventHandler, typename Func, typename... Args> +struct Caller<EventHandler, Func, void, Args...> +{ + void operator()(const std::vector<EventHandler *> &handlers, Func func, Args&&... args) + { + for (EventHandler *eh : handlers) + (eh->*func)(std::forward<Args>(args)...); + } +}; + +/* specialization for EventReturn */ +template<typename EventHandler, typename Func, typename... Args> +struct Caller<EventHandler, Func, EventReturn, Args...> +{ + EventReturn operator()(const std::vector<EventHandler *> &handlers, Func func, Args&&... args) + { + EventReturn ret = EVENT_CONTINUE; + + for (EventHandler *eh : handlers) + { + ret = (eh->*func)(std::forward<Args>(args)...); + if (ret != EVENT_CONTINUE) + return ret; + } + + return ret; + } +}; + +template<typename EventHandler> +class EventHook; + +template<typename EventHandler> +class EventHandlers : public Service +{ + std::vector<EventHandler *> handlers; + friend class EventHook<EventHandler>; + + public: + EventHandlers(Module *o, const Anope::string &ename) : Service(o, "EventHandlers", ename) + { + } + + template<typename Func, typename... Args> + auto operator()(Func func, Args&&... args) -> decltype(((static_cast<EventHandler*>(nullptr))->*func)(args...)) + { + return Caller<EventHandler, Func, decltype(((static_cast<EventHandler*>(nullptr))->*func)(args...)), Args...>()(this->handlers, func, std::forward<Args>(args)...); + } +}; + +template<typename EventHandler> +class EventHandlersReference +{ + ServiceReference<EventHandlers<EventHandler>> ref; + public: + EventHandlersReference(const Anope::string &name) : ref("EventHandlers", name) { } + + explicit operator bool() + { + return !!ref; + } + + template<typename Func, typename... Args> + auto operator()(Func func, Args&&... args) -> decltype(((static_cast<EventHandler*>(nullptr))->*func)(args...)) + { + return (**ref)(func, std::forward<Args>(args)...); + } +}; + +template<typename EventHandler> +class EventHook : public EventHandler +{ + + struct ServiceReferenceListener : ServiceReference<EventHandlers<EventHandler>> + { + EventHook<EventHandler> *eh; + + ServiceReferenceListener(EventHook<EventHandler> *t, const Anope::string &sname) : ServiceReference<EventHandlers<EventHandler>>("EventHandlers", sname), eh(t) + { + } + + void OnAcquire() override + { + if (std::find((*this)->handlers.begin(), (*this)->handlers.end(), eh) == (*this)->handlers.end()) + { + if (eh->priority == Priority::LAST) + (*this)->handlers.push_back(eh); + else + (*this)->handlers.insert((*this)->handlers.begin(), eh); + } + } + } handlers; + + public: + enum class Priority + { + FIRST, + LAST + } + priority; + + EventHook(const Anope::string &name, Priority p = Priority::LAST) : handlers(this, name) + { + handlers.Check(); + } + + ~EventHook() + { + if (!handlers) + return; + + auto it = std::find(handlers->handlers.begin(), handlers->handlers.end(), this); + if (it != handlers->handlers.end()) + handlers->handlers.erase(it); + } +}; + +namespace Event +{ + struct CoreExport PreUserKicked : Events + { + /** Called before a user has been kicked from a channel. + * @param source The kicker + * @param cu The user, channel, and status of the user being kicked + * @param kickmsg The reason for the kick. + */ + virtual void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) anope_abstract; + }; + extern CoreExport EventHandlers<PreUserKicked> OnPreUserKicked; + + struct CoreExport UserKicked : Events + { + /** Called when a user has been kicked from a channel. + * @param source The kicker + * @param target The user being kicked + * @param channel The channel the user was kicked from, which may no longer exist + * @param status The status the kicked user had on the channel before they were kicked + * @param kickmsg The reason for the kick. + */ + virtual void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) anope_abstract; + }; + extern CoreExport EventHandlers<UserKicked> OnUserKicked; + + struct CoreExport PreBotAssign : Events + { + /** Called before a bot is assigned to a channel. + * @param sender The user assigning the bot + * @param ci The channel the bot is to be assigned to. + * @param bi The bot being assigned. + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the assign. + */ + virtual EventReturn OnPreBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) anope_abstract; + }; + extern CoreExport EventHandlers<PreBotAssign> OnPreBotAssign; + + struct CoreExport BotAssign : Events + { + /** Called when a bot is assigned ot a channel + */ + virtual void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) anope_abstract; + }; + extern CoreExport EventHandlers<BotAssign> OnBotAssign; + + struct CoreExport BotUnAssign : Events + { + /** Called before a bot is unassigned from a channel. + * @param sender The user unassigning the bot + * @param ci The channel the bot is being removed from + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the unassign. + */ + virtual EventReturn OnBotUnAssign(User *sender, ChannelInfo *ci) anope_abstract; + }; + extern CoreExport EventHandlers<BotUnAssign> OnBotUnAssign; + + struct CoreExport UserConnect : Events + { + /** Called when a new user connects to the network. + * @param u The connecting user. + * @param exempt set to true/is true if the user should be excepted from bans etc + */ + virtual void OnUserConnect(User *u, bool &exempt) anope_abstract; + }; + extern CoreExport EventHandlers<UserConnect> OnUserConnect; + + struct CoreExport NewServer : Events + { + /** Called when a new server connects to the network. + * @param s The server that has connected to the network + */ + virtual void OnNewServer(Server *s) anope_abstract; + }; + extern CoreExport EventHandlers<NewServer> OnNewServer; + + struct CoreExport UserNickChange : Events + { + /** Called after a user changed the nick + * @param u The user. + * @param oldnick The old nick of the user + */ + virtual void OnUserNickChange(User *u, const Anope::string &oldnick) anope_abstract; + }; + extern CoreExport EventHandlers<UserNickChange> OnUserNickChange; + + + struct CoreExport PreCommand : Events + { + /** Called before a command is due to be executed. + * @param source The source of the command + * @param command The command the user is executing + * @param params The parameters the user is sending + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it + */ + virtual EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_abstract; + }; + extern CoreExport EventHandlers<PreCommand> OnPreCommand; + + struct CoreExport PostCommand : Events + { + /** Called after a command has been executed. + * @param source The source of the command + * @param command The command the user executed + * @param params The parameters the user sent + */ + virtual void OnPostCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) anope_abstract; + }; + extern CoreExport EventHandlers<PostCommand> OnPostCommand; + + struct CoreExport SaveDatabase : Events + { + /** Called when the databases are saved + */ + virtual void OnSaveDatabase() anope_abstract; + }; + extern CoreExport EventHandlers<SaveDatabase> OnSaveDatabase; + + struct CoreExport LoadDatabase : Events + { + /** Called when the databases are loaded + * @return EVENT_CONTINUE to let other modules continue loading, EVENT_STOP to stop + */ + virtual EventReturn OnLoadDatabase() anope_abstract; + }; + extern CoreExport EventHandlers<LoadDatabase> OnLoadDatabase; + + struct CoreExport Encrypt : Events + { + /** Called when anope needs to check passwords against encryption + * see src/encrypt.c for detailed informations + */ + virtual EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_abstract; + }; + extern CoreExport EventHandlers<Encrypt> OnEncrypt; + + struct CoreExport Decrypt : Events + { + virtual EventReturn OnDecrypt(const Anope::string &hashm, const Anope::string &src, Anope::string &dest) anope_abstract; + }; + extern CoreExport EventHandlers<Decrypt> OnDecrypt; + + + + struct CoreExport CreateBot : Events + { + /** Called when a bot is created or destroyed + */ + virtual void OnCreateBot(BotInfo *bi) anope_abstract; + }; + extern CoreExport EventHandlers<CreateBot> OnCreateBot; + + struct CoreExport DelBot : Events + { + virtual void OnDelBot(BotInfo *bi) anope_abstract; + }; + extern CoreExport EventHandlers<DelBot> OnDelBot; + + struct CoreExport BotKick : Events + { + /** Called before a bot kicks a user + * @param bi The bot sending the kick + * @param c The channel the user is being kicked on + * @param u The user being kicked + * @param reason The reason + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it + */ + virtual EventReturn OnBotKick(BotInfo *bi, Channel *c, User *u, const Anope::string &reason) anope_abstract; + }; + extern CoreExport EventHandlers<BotKick> OnBotKick; + + struct CoreExport PrePartChannel : Events + { + /** Called before a user parts a channel + * @param u The user + * @param c The channel + */ + virtual void OnPrePartChannel(User *u, Channel *c) anope_abstract; + }; + extern CoreExport EventHandlers<PrePartChannel> OnPrePartChannel; + + struct CoreExport PartChannel : Events + { + /** Called when a user parts a channel + * @param u The user + * @param c The channel, may be NULL if the channel no longer exists + * @param channel The channel name + * @param msg The part reason + */ + virtual void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) anope_abstract; + }; + extern CoreExport EventHandlers<PartChannel> OnPartChannel; + + struct CoreExport LeaveChannel : Events + { + /** Called when a user leaves a channel. + * From either parting, being kicked, or quitting/killed! + * @param u The user + * @param c The channel + */ + virtual void OnLeaveChannel(User *u, Channel *c) anope_abstract; + }; + extern CoreExport EventHandlers<LeaveChannel> OnLeaveChannel; + + struct CoreExport JoinChannel : Events + { + /** Called after a user joins a channel + * If this event triggers the user is allowed to be in the channel, and will + * not be kicked for restricted/akick/forbidden, etc. If you want to kick the user, + * use the CheckKick event instead. + * @param u The user + * @param channel The channel + */ + virtual void OnJoinChannel(User *u, Channel *c) anope_abstract; + }; + extern CoreExport EventHandlers<JoinChannel> OnJoinChannel; + + struct CoreExport TopicUpdated : Events + { + /** Called when a new topic is set + * @param c The channel + * @param setter The user who set the new topic + * @param topic The new topic + */ + virtual void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_abstract; + }; + extern CoreExport EventHandlers<TopicUpdated> OnTopicUpdated; + + struct CoreExport PreServerConnect : Events + { + /** Called before Anope connecs to its uplink + */ + virtual void OnPreServerConnect() anope_abstract; + }; + extern CoreExport EventHandlers<PreServerConnect> OnPreServerConnect; + + struct CoreExport ServerConnect : Events + { + /** Called when Anope connects to its uplink + */ + virtual void OnServerConnect() anope_abstract; + }; + extern CoreExport EventHandlers<ServerConnect> OnServerConnect; + + struct CoreExport PreUplinkSync : Events + { + /** Called when we are almost done synching with the uplink, just before we send the EOB + */ + virtual void OnPreUplinkSync(Server *serv) anope_abstract; + }; + extern CoreExport EventHandlers<PreUplinkSync> OnPreUplinkSync; + + struct CoreExport ServerDisconnect : Events + { + /** Called when Anope disconnects from its uplink, before it tries to reconnect + */ + virtual void OnServerDisconnect() anope_abstract; + }; + extern CoreExport EventHandlers<ServerDisconnect> OnServerDisconnect; + + struct CoreExport Restart : Events + { + /** Called when services restart + */ + virtual void OnRestart() anope_abstract; + }; + extern CoreExport EventHandlers<Restart> OnRestart; + + struct CoreExport Shutdown : Events + { + /** Called when services shutdown + */ + virtual void OnShutdown() anope_abstract; + }; + extern CoreExport EventHandlers<Shutdown> OnShutdown; + + struct CoreExport AddXLine : Events + { + /** Called before a XLine is added + * @param source The source of the XLine + * @param x The XLine + * @param xlm The xline manager it was added to + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it + */ + virtual EventReturn OnAddXLine(CommandSource &source, const XLine *x, XLineManager *xlm) anope_abstract; + }; + extern CoreExport EventHandlers<AddXLine> OnAddXLine; + + struct CoreExport DelXLine : Events + { + /** Called before a XLine is deleted + * @param source The source of the XLine + * @param x The XLine + * @param xlm The xline manager it was deleted from + */ + virtual void OnDelXLine(CommandSource &source, const XLine *x, XLineManager *xlm) anope_abstract; + }; + extern CoreExport EventHandlers<DelXLine> OnDelXLine; + + struct CoreExport IsServicesOperEvent : Events + { + /** Called when a user is checked for whether they are a services oper + * @param u The user + * @return EVENT_ALLOW to allow, anything else to deny + */ + virtual EventReturn IsServicesOper(User *u) anope_abstract; + }; + extern CoreExport EventHandlers<IsServicesOperEvent> OnIsServicesOper; + + struct CoreExport ServerQuit : Events + { + /** Called when a server quits + * @param server The server + */ + virtual void OnServerQuit(Server *server) anope_abstract; + }; + extern CoreExport EventHandlers<ServerQuit> OnServerQuit; + + struct CoreExport UserQuit : Events + { + /** Called when a user quits, or is killed + * @param u The user + * @param msg The quit message + */ + virtual void OnUserQuit(User *u, const Anope::string &msg) anope_abstract; + }; + extern CoreExport EventHandlers<UserQuit> OnUserQuit; + + struct CoreExport PreUserLogoff : Events + { + /** Called when a user is quit, before and after being internally removed from + * This is different from OnUserQuit, which takes place at the time of the quit. + * This happens shortly after when all message processing is finished. + * all lists (channels, user list, etc) + * @param u The user + */ + virtual void OnPreUserLogoff(User *u) anope_abstract; + }; + extern CoreExport EventHandlers<PreUserLogoff> OnPreUserLogoff; + + struct CoreExport PostUserLogoff : Events + { + virtual void OnPostUserLogoff(User *u) anope_abstract; + }; + extern CoreExport EventHandlers<PostUserLogoff> OnPostUserLogoff; + + struct CoreExport AccessDel : Events + { + /** Called after an access entry is deleted from a channel + * @param ci The channel + * @param source The source of the command + * @param access The access entry that was removed + */ + virtual void OnAccessDel(ChannelInfo *ci, CommandSource &source, ChanAccess *access) anope_abstract; + }; + extern CoreExport EventHandlers<AccessDel> OnAccessDel; + + struct CoreExport AccessAdd : Events + { + /** Called when access is added + * @param ci The channel + * @param source The source of the command + * @param access The access changed + */ + virtual void OnAccessAdd(ChannelInfo *ci, CommandSource &source, ChanAccess *access) anope_abstract; + }; + extern CoreExport EventHandlers<AccessAdd> OnAccessAdd; + + struct CoreExport AccessClear : Events + { + /** Called when the access list is cleared + * @param ci The channel + * @param u The user who cleared the access + */ + virtual void OnAccessClear(ChannelInfo *ci, CommandSource &source) anope_abstract; + }; + extern CoreExport EventHandlers<AccessClear> OnAccessClear; + + struct CoreExport ChanRegistered : Events + { + /** Called when a channel is registered + * @param ci The channel + */ + virtual void OnChanRegistered(ChannelInfo *ci) anope_abstract; + }; + extern CoreExport EventHandlers<ChanRegistered> OnChanRegistered; + + + struct CoreExport CreateChan : Events + { + /** Called when a channel is being created, for any reason + * @param ci The channel + */ + virtual void OnCreateChan(ChannelInfo *ci) anope_abstract; + }; + extern CoreExport EventHandlers<CreateChan> OnCreateChan; + + struct CoreExport DelChan : Events + { + /** Called when a channel is being deleted, for any reason + * @param ci The channel + */ + virtual void OnDelChan(ChannelInfo *ci) anope_abstract; + }; + extern CoreExport EventHandlers<DelChan> OnDelChan; + + struct CoreExport ChannelCreate : Events + { + /** Called when a new channel is created + * Note that this channel may not be introduced to the uplink at this point. + * @param c The channel + */ + virtual void OnChannelCreate(Channel *c) anope_abstract; + }; + extern CoreExport EventHandlers<ChannelCreate> OnChannelCreate; + + struct CoreExport ChannelDelete : Events + { + /** Called when a channel is deleted + * @param c The channel + */ + virtual void OnChannelDelete(Channel *c) anope_abstract; + }; + extern CoreExport EventHandlers<ChannelDelete> OnChannelDelete; + + + struct CoreExport CheckKick : Events + { + /** Called after a user join a channel when we decide whether to kick them or not + * @param u The user + * @param c The channel + * @param kick Set to true to kick + * @param mask The mask to ban, if any + * @param reason The reason for the kick + * @return EVENT_STOP to prevent the user from joining by kicking/banning the user + */ + virtual EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_abstract; + }; + extern CoreExport EventHandlers<CheckKick> OnCheckKick; + + struct CoreExport CheckPriv : Events + { + /** Checks if access has the channel privilege 'priv'. + * @param access THe access struct + * @param priv The privilege being checked for + * @return EVENT_ALLOW for yes, EVENT_STOP to stop all processing + */ + virtual EventReturn OnCheckPriv(const ChanAccess *access, const Anope::string &priv) anope_abstract; + }; + extern CoreExport EventHandlers<CheckPriv> OnCheckPriv; + + struct CoreExport GroupCheckPriv : Events + { + /** Check whether an access group has a privilege + * @param group The group + * @param priv The privilege + * @return MOD_ALLOW to allow, MOD_STOP to stop + */ + virtual EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) anope_abstract; + }; + extern CoreExport EventHandlers<GroupCheckPriv> OnGroupCheckPriv; + + struct CoreExport NickIdentify : Events + { + /** Called when a user identifies to a nick + * @param u The user + */ + virtual void OnNickIdentify(User *u) anope_abstract; + }; + extern CoreExport EventHandlers<NickIdentify> OnNickIdentify; + + struct CoreExport UserLogin : Events + { + /** Called when a user is logged into an account + * @param u The user + */ + virtual void OnUserLogin(User *u) anope_abstract; + }; + extern CoreExport EventHandlers<UserLogin> OnUserLogin; + + struct CoreExport NickLogout : Events + { + /** Called when a nick logs out + * @param u The nick + */ |
