anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

service.h (4545B)

      1 /*
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 #ifndef SERVICE_H
     13 #define SERVICE_H
     14 
     15 #include "services.h"
     16 #include "anope.h"
     17 #include "base.h"
     18 
     19 /** Anything that inherits from this class can be referred to
     20  * using ServiceReference. Any interfaces provided by modules,
     21  * such as commands, use this. This is also used for modules
     22  * that publish a service (m_ssl_openssl, etc).
     23  */
     24 class CoreExport Service : public virtual Base
     25 {
     26 	static std::map<Anope::string, std::map<Anope::string, Service *> > Services;
     27 	static std::map<Anope::string, std::map<Anope::string, Anope::string> > Aliases;
     28 
     29 	static Service *FindService(const std::map<Anope::string, Service *> &services, const std::map<Anope::string, Anope::string> *aliases, const Anope::string &n)
     30 	{
     31 		std::map<Anope::string, Service *>::const_iterator it = services.find(n);
     32 		if (it != services.end())
     33 			return it->second;
     34 
     35 		if (aliases != NULL)
     36 		{
     37 			std::map<Anope::string, Anope::string>::const_iterator it2 = aliases->find(n);
     38 			if (it2 != aliases->end())
     39 				return FindService(services, aliases, it2->second);
     40 		}
     41 
     42 		return NULL;
     43 	}
     44 
     45  public:
     46 	static Service *FindService(const Anope::string &t, const Anope::string &n)
     47 	{
     48 		std::map<Anope::string, std::map<Anope::string, Service *> >::const_iterator it = Services.find(t);
     49 		if (it == Services.end())
     50 			return NULL;
     51 
     52 		std::map<Anope::string, std::map<Anope::string, Anope::string> >::const_iterator it2 = Aliases.find(t);
     53 		if (it2 != Aliases.end())
     54 			return FindService(it->second, &it2->second, n);
     55 
     56 		return FindService(it->second, NULL, n);
     57 	}
     58 
     59 	static std::vector<Anope::string> GetServiceKeys(const Anope::string &t)
     60 	{
     61 		std::vector<Anope::string> keys;
     62 		std::map<Anope::string, std::map<Anope::string, Service *> >::iterator it = Services.find(t);
     63 		if (it != Services.end())
     64 			for (std::map<Anope::string, Service *>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
     65 				keys.push_back(it2->first);
     66 		return keys;
     67 	}
     68 
     69 	static void AddAlias(const Anope::string &t, const Anope::string &n, const Anope::string &v)
     70 	{
     71 		std::map<Anope::string, Anope::string> &smap = Aliases[t];
     72 		smap[n] = v;
     73 	}
     74 
     75 	static void DelAlias(const Anope::string &t, const Anope::string &n)
     76 	{
     77 		std::map<Anope::string, Anope::string> &smap = Aliases[t];
     78 		smap.erase(n);
     79 		if (smap.empty())
     80 			Aliases.erase(t);
     81 	}
     82 
     83 	Module *owner;
     84 	/* Service type, which should be the class name (eg "Command") */
     85 	Anope::string type;
     86 	/* Service name, commands are usually named service/command */
     87 	Anope::string name;
     88 
     89 	Service(Module *o, const Anope::string &t, const Anope::string &n) : owner(o), type(t), name(n)
     90 	{
     91 		this->Register();
     92 	}
     93 
     94 	virtual ~Service()
     95 	{
     96 		this->Unregister();
     97 	}
     98 
     99 	void Register()
    100 	{
    101 		std::map<Anope::string, Service *> &smap = Services[this->type];
    102 		if (smap.find(this->name) != smap.end())
    103 			throw ModuleException("Service " + this->type + " with name " + this->name + " already exists");
    104 		smap[this->name] = this;
    105 	}
    106 
    107 	void Unregister()
    108 	{
    109 		std::map<Anope::string, Service *> &smap = Services[this->type];
    110 		smap.erase(this->name);
    111 		if (smap.empty())
    112 			Services.erase(this->type);
    113 	}
    114 };
    115 
    116 /** Like Reference, but used to refer to Services.
    117  */
    118 template<typename T>
    119 class ServiceReference : public Reference<T>
    120 {
    121 	Anope::string type;
    122 	Anope::string name;
    123 
    124  public:
    125 	ServiceReference() { }
    126 
    127 	ServiceReference(const Anope::string &t, const Anope::string &n) : type(t), name(n)
    128 	{
    129 	}
    130 
    131 	inline void operator=(const Anope::string &n)
    132 	{
    133 		this->name = n;
    134 		this->invalid = true;
    135 	}
    136 
    137 	operator bool() anope_override
    138 	{
    139 		if (this->invalid)
    140 		{
    141 			this->invalid = false;
    142 			this->ref = NULL;
    143 		}
    144 		if (!this->ref)
    145 		{
    146 			/* This really could be dynamic_cast in every case, except for when a module
    147 			 * creates its own service type (that other modules must include the header file
    148 			 * for), as the core is not compiled with it so there is no RTTI for it.
    149 			 */
    150 			this->ref = static_cast<T *>(::Service::FindService(this->type, this->name));
    151 			if (this->ref)
    152 				this->ref->AddReference(this);
    153 		}
    154 		return this->ref;
    155 	}
    156 };
    157 
    158 class ServiceAlias
    159 {
    160 	Anope::string t, f;
    161  public:
    162 	ServiceAlias(const Anope::string &type, const Anope::string &from, const Anope::string &to) : t(type), f(from)
    163 	{
    164 		Service::AddAlias(type, from, to);
    165 	}
    166 
    167 	~ServiceAlias()
    168 	{
    169 		Service::DelAlias(t, f);
    170 	}
    171 };
    172 
    173 #endif // SERVICE_H