diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/dynref.h | 36 | ||||
-rw-r--r-- | include/event.h | 146 | ||||
-rw-r--r-- | include/modules.h | 36 | ||||
-rw-r--r-- | include/modules/account.h | 27 | ||||
-rw-r--r-- | include/modules/cap.h | 21 | ||||
-rw-r--r-- | include/modules/httpd.h | 29 | ||||
-rw-r--r-- | include/modules/sasl.h | 12 | ||||
-rw-r--r-- | include/modules/spanningtree.h | 29 |
8 files changed, 263 insertions, 73 deletions
diff --git a/include/dynref.h b/include/dynref.h index a3d2f9966..6e2e17423 100644 --- a/include/dynref.h +++ b/include/dynref.h @@ -24,8 +24,18 @@ class CoreExport dynamic_reference_base : public interfacebase, public insp::intrusive_list_node<dynamic_reference_base> { + public: + class CaptureHook + { + public: + /** Called when the target of the dynamic_reference has been acquired + */ + virtual void OnCapture() = 0; + }; + private: std::string name; + CaptureHook* hook; void resolve(); protected: ServiceProvider* value; @@ -35,6 +45,12 @@ class CoreExport dynamic_reference_base : public interfacebase, public insp::int ~dynamic_reference_base(); inline const std::string& GetProvider() { return name; } void SetProvider(const std::string& newname); + + /** Set handler to call when the target object becomes available + * @param h Handler to call + */ + void SetCaptureHook(CaptureHook* h) { hook = h; } + void check(); operator bool() { return (value != NULL); } static void reset_all(); @@ -63,6 +79,16 @@ class dynamic_reference : public dynamic_reference_base { return operator->(); } + + const T* operator->() const + { + return static_cast<T*>(value); + } + + const T* operator*() const + { + return operator->(); + } }; template<typename T> @@ -81,6 +107,16 @@ class dynamic_reference_nocheck : public dynamic_reference_base { return operator->(); } + + const T* operator->() const + { + return static_cast<T*>(value); + } + + const T* operator*() const + { + return operator->(); + } }; class ModeHandler; diff --git a/include/event.h b/include/event.h new file mode 100644 index 000000000..c9bad7d04 --- /dev/null +++ b/include/event.h @@ -0,0 +1,146 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +namespace Events +{ + class ModuleEventListener; + class ModuleEventProvider; +} + +/** Provider of one or more cross-module events. + * Modules who wish to provide events for other modules create instances of this class and use + * one of the macros below to fire the event, passing the instance of the event provider class + * to the macro. + * Event providers are identified using a unique identifier string. + */ +class Events::ModuleEventProvider : public ServiceProvider, private dynamic_reference_base::CaptureHook +{ + public: + typedef std::vector<ModuleEventListener*> SubscriberList; + + /** Constructor + * @param mod Module providing the event(s) + * @param eventid Identifier of the event or event group provided, must be unique + */ + ModuleEventProvider(Module* mod, const std::string& eventid) + : ServiceProvider(mod, eventid, SERVICE_DATA) + , prov(mod, eventid) + { + prov.SetCaptureHook(this); + } + + /** Get list of objects subscribed to this event + * @return List of subscribed objects + */ + const SubscriberList& GetSubscribers() const { return prov->subscribers; } + + friend class ModuleEventListener; + + private: + void OnCapture() CXX11_OVERRIDE + { + // If someone else holds the list from now on, clear mine. See below for more info. + if (*prov != this) + subscribers.clear(); + } + + /** Reference to the active provider for this event. In case multiple event providers + * exist for the same event, only one of them contains the list of subscribers. + * To handle the case when we are not the ones with the list, we get it from the provider + * where the dynref points to. + */ + dynamic_reference_nocheck<ModuleEventProvider> prov; + + /** List of objects subscribed to the event(s) provided by us, or empty if multiple providers + * exist with the same name and we are not the ones holding the list. + */ + SubscriberList subscribers; +}; + +/** Base class for abstract classes describing cross-module events. + * Subscribers should NOT inherit directly from this class. + */ +class Events::ModuleEventListener : private dynamic_reference_base::CaptureHook +{ + /** Reference to the provider, can be NULL if none of the provider modules are loaded + */ + dynamic_reference_nocheck<ModuleEventProvider> prov; + + /** Called by the dynref when the event provider becomes available + */ + void OnCapture() CXX11_OVERRIDE + { + prov->subscribers.push_back(this); + } + + public: + /** Constructor + * @param mod Module subscribing + * @param eventid Identifier of the event to subscribe to + */ + ModuleEventListener(Module* mod, const std::string& eventid) + : prov(mod, eventid) + { + prov.SetCaptureHook(this); + // If the dynamic_reference resolved at construction our capture handler wasn't called + if (prov) + ModuleEventListener::OnCapture(); + } + + ~ModuleEventListener() + { + if (prov) + stdalgo::erase(prov->subscribers, this); + } +}; + +/** + * Run the given hook provided by a module + * + * FOREACH_MOD_CUSTOM(accountevprov, AccountEventListener, OnAccountChange, MOD_RESULT, (user, newaccount)) + */ +#define FOREACH_MOD_CUSTOM(prov, listenerclass, func, params) do { \ + const Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \ + for (Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \ + { \ + listenerclass* _t = static_cast<listenerclass*>(*_i); \ + _t->func params ; \ + } \ +} while (0); + +/** + * Run the given hook provided by a module until some module returns MOD_RES_ALLOW or MOD_RES_DENY. + * If no module does that, result is set to MOD_RES_PASSTHRU. + * + * Example: ModResult MOD_RESULT; + * FIRST_MOD_RESULT_CUSTOM(httpevprov, HTTPRequestEventListener, OnHTTPRequest, MOD_RESULT, (request)); + */ +#define FIRST_MOD_RESULT_CUSTOM(prov, listenerclass, func, result, params) do { \ + result = MOD_RES_PASSTHRU; \ + const Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \ + for (Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \ + { \ + listenerclass* _t = static_cast<listenerclass*>(*_i); \ + result = _t->func params ; \ + if (result != MOD_RES_PASSTHRU) \ + break; \ + } \ +} while (0); diff --git a/include/modules.h b/include/modules.h index 5a4090dfb..d034ebac2 100644 --- a/include/modules.h +++ b/include/modules.h @@ -206,34 +206,6 @@ class CoreExport Version virtual ~Version() {} }; -/** The Event class is a unicast message directed at all modules. - * When the class is properly instantiated it may be sent to all modules - * using the Send() method, which will trigger the OnEvent method in - * all modules passing the object as its parameter. - */ -class CoreExport Event : public classbase -{ - public: - /** This is a pointer to the sender of the message, which can be used to - * directly trigger events, or to create a reply. - */ - ModuleRef source; - /** The event identifier. - * This is arbitary text which should be used to distinguish - * one type of event from another. - */ - const std::string id; - - /** Create a new Event - */ - Event(Module* src, const std::string &eventid); - /** Send the Event. - * The return result of an Event::Send() will always be NULL as - * no replies are expected. - */ - void Send(); -}; - class CoreExport DataProvider : public ServiceProvider { public: @@ -260,7 +232,7 @@ enum Implementation 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_OnPreTopicChange, - I_OnPostTopicChange, I_OnEvent, I_OnPostConnect, + I_OnPostTopicChange, I_OnPostConnect, I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete, I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildNeighborList, I_OnGarbageCollect, I_OnSetConnectClass, @@ -952,12 +924,6 @@ class CoreExport Module : public classbase, public usecountbase */ virtual void OnPostTopicChange(User* user, Channel* chan, const std::string &topic); - /** Called whenever an Event class is sent to all modules by another module. - * You should *always* check the value of Event::id to determine the event type. - * @param event The Event class being received - */ - virtual void OnEvent(Event& event); - /** Called whenever a password check is to be made. Replaces the old OldOperCompare API. * The password field (from the config file) is in 'password' and is to be compared against * 'input'. This method allows for encryption of passwords (oper, connect:allow, die/restart, etc). diff --git a/include/modules/account.h b/include/modules/account.h index c00b044e4..0368127a6 100644 --- a/include/modules/account.h +++ b/include/modules/account.h @@ -22,16 +22,7 @@ #include <map> #include <string> -class AccountEvent : public Event -{ - public: - User* const user; - const std::string account; - AccountEvent(Module* me, User* u, const std::string& name) - : Event(me, "account_login"), user(u), account(name) - { - } -}; +#include "event.h" typedef StringExtItem AccountExtItem; @@ -39,3 +30,19 @@ inline AccountExtItem* GetAccountExtItem() { return static_cast<AccountExtItem*>(ServerInstance->Extensions.GetItem("accountname")); } + +class AccountEventListener : public Events::ModuleEventListener +{ + public: + AccountEventListener(Module* mod) + : ModuleEventListener(mod, "event/account") + { + } + + /** Called when a user logs in or logs out + * @param user User logging in or out + * @param newaccount New account name of the user or empty string if the user + * logged out + */ + virtual void OnAccountChange(User* user, const std::string& newaccount) = 0; +}; diff --git a/include/modules/cap.h b/include/modules/cap.h index cc1cb8d8c..7aa60cd21 100644 --- a/include/modules/cap.h +++ b/include/modules/cap.h @@ -20,7 +20,9 @@ #pragma once -class CapEvent : public Event +#include "event.h" + +class CapEvent { public: enum CapEventType @@ -35,23 +37,27 @@ class CapEvent : public Event std::vector<std::string> wanted; std::vector<std::string> ack; User* user; - CapEvent(Module* sender, User* u, CapEventType capevtype) : Event(sender, "cap_request"), type(capevtype), user(u) {} + CapEvent(Module* sender, User* u, CapEventType capevtype) : type(capevtype), user(u) {} }; -class GenericCap +class GenericCap : public Events::ModuleEventListener { + bool active; + public: LocalIntExt ext; const std::string cap; GenericCap(Module* parent, const std::string& Cap) - : ext("cap_" + Cap, ExtensionItem::EXT_USER, parent) + : Events::ModuleEventListener(parent, "event/cap") + , active(true) + , ext("cap_" + Cap, ExtensionItem::EXT_USER, parent) , cap(Cap) { } - void HandleEvent(Event& ev) + void OnCapEvent(CapEvent& ev) CXX11_OVERRIDE { - if (ev.id != "cap_request") + if (!active) return; CapEvent *data = static_cast<CapEvent*>(&ev); @@ -87,4 +93,7 @@ class GenericCap ext.set(data->user, 0); } } + + void SetActive(bool newstate) { active = newstate; } + bool IsActive() const { return active; } }; diff --git a/include/modules/httpd.h b/include/modules/httpd.h index 86234d53f..b4b88bed5 100644 --- a/include/modules/httpd.h +++ b/include/modules/httpd.h @@ -24,6 +24,7 @@ #pragma once #include "base.h" +#include "event.h" #include <string> #include <sstream> @@ -107,7 +108,7 @@ class HttpServerSocket; /** This class represents a HTTP request. */ -class HTTPRequest : public Event +class HTTPRequest { protected: std::string type; @@ -134,9 +135,9 @@ class HTTPRequest : public Event * @param ip The IP address making the web request. * @param pdata The post data (content after headers) received with the request, up to Content-Length in size */ - HTTPRequest(Module* me, const std::string &eventid, const std::string &request_type, const std::string &uri, + HTTPRequest(const std::string& request_type, const std::string& uri, HTTPHeaders* hdr, HttpServerSocket* socket, const std::string &ip, const std::string &pdata) - : Event(me, eventid), type(request_type), document(uri), ipaddr(ip), postdata(pdata), headers(hdr), sock(socket) + : type(request_type), document(uri), ipaddr(ip), postdata(pdata), headers(hdr), sock(socket) { } @@ -237,3 +238,25 @@ class HTTPdAPI : public dynamic_reference<HTTPdAPIBase> { } }; + +class HTTPACLEventListener : public Events::ModuleEventListener +{ + public: + HTTPACLEventListener(Module* mod) + : ModuleEventListener(mod, "event/http-acl") + { + } + + virtual ModResult OnHTTPACLCheck(HTTPRequest& req) = 0; +}; + +class HTTPRequestEventListener : public Events::ModuleEventListener +{ + public: + HTTPRequestEventListener(Module* mod) + : ModuleEventListener(mod, "event/http-request") + { + } + + virtual ModResult OnHTTPRequest(HTTPRequest& req) = 0; +}; diff --git a/include/modules/sasl.h b/include/modules/sasl.h index 321711a68..0a7b19a70 100644 --- a/include/modules/sasl.h +++ b/include/modules/sasl.h @@ -19,13 +19,15 @@ #pragma once -class SASLFallback : public Event +#include "event.h" + +class SASLEventListener : public Events::ModuleEventListener { public: - const parameterlist& params; - SASLFallback(Module* me, const parameterlist& p) - : Event(me, "sasl_fallback"), params(p) + SASLEventListener(Module* mod) + : ModuleEventListener(mod, "event/sasl") { - Send(); } + + virtual void OnSASLAuth(const parameterlist& params) = 0; }; diff --git a/include/modules/spanningtree.h b/include/modules/spanningtree.h index 99f4f9fc4..0f51c35db 100644 --- a/include/modules/spanningtree.h +++ b/include/modules/spanningtree.h @@ -19,22 +19,23 @@ #pragma once -struct AddServerEvent : public Event -{ - const std::string servername; - AddServerEvent(Module* me, const std::string& name) - : Event(me, "new_server"), servername(name) - { - Send(); - } -}; +#include "event.h" -struct DelServerEvent : public Event +class SpanningTreeEventListener : public Events::ModuleEventListener { - const std::string servername; - DelServerEvent(Module* me, const std::string& name) - : Event(me, "lost_server"), servername(name) + public: + SpanningTreeEventListener(Module* mod) + : ModuleEventListener(mod, "event/spanningtree") { - Send(); } + + /** Fired when a server finishes burst + * @param server Server that recently linked and finished burst + */ + virtual void OnServerLink(const std::string& server) { } + + /** Fired when a server splits + * @param server Server that split + */ + virtual void OnServerSplit(const std::string& server) { } }; |