Dev:Module

Below we will explain why modules are useful and how to get started with writing a module, step by step.

= Why Modules? =

Within Unreal 3.4, a large amount of functionality has been migrated to modules, as the release process continues it is likely additional functionality will move here where possible. Moving to a more modular design has many advantages, including:


 * Permits easier selection of features for networks/users that may not want certain functionality present
 * Allows less hassle for upgrades by permitting all but the core functionality to be updated and reloaded independently of the main IRCd
 * Makes code more maintainable by decoupling components and enforcing a strict separation of concerns
 * Eases third party contributions through making the code more approachable.

To this end, if you’re just starting to contribute, modules are generally the place to get started.

= Creating a new module =

Filename and location
First of all, modules go in src/modules or one of it's subdirectories. src/modules/m_*.c are generally commands. src/modules/chanmodes/ are channel modes. src/modules/usermodes are user modes.

(TODO: table ? and where do 3rd party modules go ?)

Includes
Your module should start by including "unrealircd.h":


 * 1) include "unrealircd.h"

Module Header
Every UnrealIRCd module has a special structure which is created by the macro MOD_HEADER. This includes the name of the module, the version, a description, a modversion, and a symbol table that is generally NULL.

ModuleHeader MOD_HEADER(mymodule) = { &quot;mymodule&quot;, &quot;$Id$&quot;, &quot;My custom command&quot;, &quot;3.2-b8-1&quot;, NULL, };

Module Functions
For the module to actually do something there are MOD_XXX functions that will be called on test, init, load and unload.

These functions are generally the place where module authors will hook into UnrealIRCd's Dev:Module API and perform any cleanup if necessary.

If you wonder what the DLLFUNC prefix (below) is for: it's for win32 compatibility. DLLFUNC is a macro that will be replaced with the appropriate compiler specific flags to have the function exported when compiled into a .DLL.

MOD_TEST
This function is executed when the module has just been loaded. If you want to run configuration test hooks (like HOOKTYPE_CONFIGTEST and HOOKTYPE_CONFIGPOSTTEST) then you add them here. Otherwise, simply don't add a MOD_TEST function.

DLLFUNC int MOD_TEST(mymodule)(ModuleInfo *moduleInfo) {   /* Test here */ return MOD_SUCCESS; }

After your MOD_TEST function is called (and callbacks set up there being called) your module COULD be unloaded by UnrealIRCd. This would be the case if your module, or any other module, fails config tests. So normally you shouldn't allocate any structures in MOD_TEST.

Note that MOD_TEST is really just for running config tests and not for anything else. All the other initialization should go in MOD_INIT, see next.

MOD_INIT
This function is executed when the module is loaded and is responsible for doing any initial structure initialization, some hooks and callbacks are registered here, as well as registering channel and user modes.

TODO: clarify what should go in MOD_INIT and what in MOD_LOAD

DLLFUNC int MOD_INIT(mymodule)(ModuleInfo *moduleInfo) {   /* Initialization here */ return MOD_SUCCESS; }

Please keep in mind that this method should make no assumptions about the surrounding state when it is loaded: the server may have active users and channels, or it may have just been started. The module can safely assume that the system can register hooks, channel modes, user modes, structures, etc, but no other assumptions can be made safely.

MOD_LOAD
DLLFUNC int MOD_LOAD(mymodule)(int module_load) {   // Do necessary initialization for when module is loaded return MOD_SUCCESS; /* returning anything else is not really supported here */ }

The MOD_LOAD function is called when the module is fully loaded, configuration has been read (if any). All commands and user/channel modes etc. have been loaded at this point, so it's also the place to add command overrides (TODO: link).

MOD_UNLOAD
DLLFUNC int MOD_UNLOAD(mymodule)(int module_unload) {	// Perform any cleanup for unload }

The MOD_UNLOAD operation is called by the system when a module is being unloaded. You should do any cleanup of internal structures that is necessary, such as freeing memory structures, closing handles (eg: files, curl, etc). It is worth noting, to save yourself time, that hooks and any added Cmodes and Umodes, and generally all external structures will be cleaned up on exit automatically - so this is really meant to be focused on cleaning up any structures or memory you have allocated or used internally that require cleanup.

Adding commands, user modes, overrides, hook, etc..
Now you have your module skeleton, you can test compile it (see below) or go straight to Dev:Module API to actually make the module do something useful.

= Compiling modules =

3.4.x
In your UnrealIRCd source directory put the .c file in the src/modules/third directory. Then just run 'make'. UnrealIRCd will automatically detect the 3rd party modules in that directory and compile them. syzop@vulnscan:~/Unreal3.4.0$ cp /tmp/somemodule.c src/modules/third/ syzop@vulnscan:~/Unreal3.4.0$ make

3.2.x
From your Unreal3.X directory you execute the following command to compile 3rd party modules: make custommodule MODULEFILE=nameofmodule Where nameofmodule is the name of your module without the .c

So for example you wrote a module src/modules/m_lalala.c then you use make custommodule MODULEFILE=m_lalala

Pitfall: you should not execute this command if you are in src/modules. This will cause an error. You have to be in the main UnrealIRCd directory, eg /home/irc/Unreal3.4

The above is for 3rd party modules. If your module (later) is part of UnrealIRCd then you of course don't have to do this anymore as the usual UnrealIRCd 'make' will compile your module.