summaryrefslogtreecommitdiff
path: root/include/modules.h
blob: bce1b1cc2c9b402e9607fafb1686cbca1a03487a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*
 * Anope IRC Services
 *
 * Copyright (C) 2003-2017 Anope Team <team@anope.org>
 *
 * This file is part of Anope. Anope 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 see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "serialize.h"
#include "base.h"
#include "modes.h"
#include "timers.h"
#include "logger.h"
#include "extensible.h"
#include "version.h"

class ModuleDef;
struct ModuleVersionC;

enum
{
	ANOPE_MODAPI_VER = 1
};

struct AnopeModule
{
	unsigned int api_version;
	ModuleDef* (*init)();
	void (*fini)(ModuleDef *);
	ModuleVersionC (*version)();
};

class ModuleDef
{
	std::vector<Anope::string> dependencies;

 public:
	virtual ~ModuleDef() = default;
	virtual Module *Create(const Anope::string &modname, const Anope::string &creator) anope_abstract;
	virtual void Destroy(Module *) anope_abstract;
	virtual void BuildModuleInfo() anope_abstract;

	void Depends(const Anope::string &modname);
	const std::vector<Anope::string> &GetDependencies();
};

template<class ModuleClass> void ModuleInfo(ModuleDef *moddef) { }

/** This definition is used as shorthand for the various classes
 * and functions needed to make a module loadable by the OS.
 */
#define MODULE_INIT(ModuleClass) \
	class ModuleClass ## ModuleDef : public ModuleDef \
	{ \
		Module *Create(const Anope::string &modname, const Anope::string &creator) override \
		{ \
			return new ModuleClass(modname, creator); \
		} \
		void Destroy(Module *module) override \
		{ \
			delete module; \
		} \
		void BuildModuleInfo() override \
		{ \
			ModuleInfo<ModuleClass>(this); \
		} \
	}; \
	static ModuleDef *CreateModuleDef() \
	{ \
		return new ModuleClass ## ModuleDef(); \
	} \
	static void DeleteModuleDef(ModuleDef *def) \
	{ \
		delete def; \
	} \
	static ModuleVersionC AnopeModuleVersion() \
	{ \
		ModuleVersionC ver; \
		ver.version_major = VERSION_MAJOR; \
		ver.version_minor = VERSION_MINOR; \
		ver.version_patch = VERSION_PATCH; \
		return ver; \
	} \
	extern "C" DllExport struct AnopeModule AnopeMod; \
	struct AnopeModule AnopeMod = \
	{ \
		ANOPE_MODAPI_VER, \
		CreateModuleDef, \
		DeleteModuleDef, \
		AnopeModuleVersion \
	};

enum class ModuleReturn
{
	OK,
	PARAMS,
	EXISTS,
	NOEXIST,
	NOLOAD,
	UNKNOWN,
	FILE_IO,
	EXCEPTION,
	VERSION
};

/* Module types, in the order in which they are unloaded. The order these are in is IMPORTANT */
enum
{
	MT_BEGIN,
	/* Module is 3rd party. All 3rd party modules should set this. Mutually exclusive to VENDOR. */
	THIRD = 1 << 0,
	/* A vendor module, which is made and shipped by Anope. Mutually exclusive to THIRD. */
	VENDOR = 1 << 1,
	/* Extra module not required for standard use. Probably requires external dependencies.
	 * This module does something extreme enough that we want it to show in the default /os modlist command
	 */
	EXTRA = 1 << 2,
	/* Module provides access to a database */
	DATABASE = 1 << 3,
	/* Module provides encryption */
	ENCRYPTION = 1 << 4,
	/* Module provides a pseudoclient */
	PSEUDOCLIENT = 1 << 5,
	/* Module provides IRCd protocol support */
	PROTOCOL = 1 << 6,
	MT_END = 1 << 7
};
typedef unsigned short ModType;

struct ModuleVersionC
{
	int version_major, version_minor, version_patch;
};

/** Returned by Module::GetVersion, used to see what version of Anope
 * a module is compiled against.
 */
class ModuleVersion
{
 private:
	int version_major;
	int version_minor;
	int version_patch;

 public:
	ModuleVersion(const ModuleVersionC &);

	/** Get the major version of Anope this was built against
	 * @return The major version
	 */
	int GetMajor() const;

	/** Get the minor version of Anope this was built against
	 * @return The minor version
	 */
	int GetMinor() const;

	/** Get the patch version this was built against
	 * @return The patch version
	 */
	int GetPatch() const;
};

/** Every module in Anope is actually a class.
 */
class CoreExport Module : public Extensible
{
 private:
	bool permanent;
 public:
	/** The module name (e.g. os_modload)
	 */
	Anope::string name;

	/** What type this module is
	 */
	ModType type;

	/** The temporary path/filename
	 */
	Anope::string filename;

	/** Handle for this module, obtained from dlopen()
	 */
	void *handle;

	ModuleDef *def = nullptr;
	AnopeModule *module = nullptr;

	/** Time this module was created
	 */
	time_t created;

	/** Version of this module
	 */
	Anope::string version;

	/** Author of the module
	 */
	Anope::string author;

	Logger logger;

	/** Creates and initialises a new module.
	 * @param modname The module name
	 * @param loadernick The nickname of the user loading the module.
	 * @param type The module type
	 */
	Module(const Anope::string &modname, const Anope::string &loadernick, ModType type = THIRD);

	/** Destroys a module, freeing resources it has allocated.
	 */
	virtual ~Module();

	const Anope::string &GetName() const;

	/** Toggles the permanent flag on a module. If a module is permanent,
	 * then it may not be unloaded.
	 *
	 * Naturally, this setting should be used sparingly!
	 *
	 * @param state True if this module should be permanent, false else.
	 */
	void SetPermanent(bool state);

	/** Retrieves whether or not a given module is permanent.
	 * @return true if the module is permanent, false else.
	 */
	bool GetPermanent() const;

	/** Set the modules version info.
	 * @param version the version of the module
	 */
	void SetVersion(const Anope::string &version);

	/** Set the modules author info
	 * @param author the author of the module
	 */
	void SetAuthor(const Anope::string &author);

	/** Get the version of Anope this module was
	 * compiled against
	 * @return The version
	 */
	ModuleVersion GetVersion() const;

	virtual void OnReload(Configuration::Conf *conf) { }
};

/** Used to manage modules.
 */
class CoreExport ModuleManager
{
 public:
 	/** List of all modules loaded in Anope
	 */
	static std::list<Module *> Modules;

#ifdef _WIN32
	/** Clean up the module runtime directory
	 */
	static void CleanupRuntimeDirectory();
#endif

	/** Loads a given module.
	 * @param m the module to load
	 * @param u the user who loaded it, NULL for auto-load
	 * @return MOD_ERR_OK on success, anything else on fail
	 */
	static ModuleReturn LoadModule(const Anope::string &modname, User *u);

	/** Unload the given module.
	 * @param m the module to unload
	 * @param u the user who unloaded it
	 * @return MOD_ERR_OK on success, anything else on fail
	 */
	static ModuleReturn UnloadModule(Module *m, User * u);

	/** Find a module
	 * @param name The module name
	 * @return The module
	 */
	static Module *FindModule(const Anope::string &name);

	/** Find the first module of a certain type
	 * @param type The module type
	 * @return The module
	 */
	static Module *FindFirstOf(ModType type);

	/** Checks whether this version of Anope is at least major.minor.patch.build
	 * Throws a ModuleException if not
	 * @param major The major version
	 * @param minor The minor vesion
	 * @param patch The patch version
	 */
	static void RequireVersion(int major, int minor, int patch);

	/** Unloading all modules except the protocol module.
	 */
	static void UnloadAll();

 private:
	/** Call the module_delete function to safely delete the module
	 * @param m the module to delete
	 * @return MOD_ERR_OK on success, anything else on fail
	 */
	static ModuleReturn DeleteModule(Module *m);
};