Dev:Module

= Module =

Introduction
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 mmay 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. This document will familiarize you with the anatomy of a module, a module’s lifecycle, and common techniques/methods you will use to write a module.

Module Header
The structure of every module starts with a header, using the format shown below and 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
In addition to this header, each module must include several functions. These functions are generally the place module authors will hook into functionality, register callbacks, set up channel modules, and perform any cleanup 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 (optional!)
This function is executed when the module has just been loaded. If you want to run configuration test hooks then you add them here. Otherwise, just don't add a MOD_TEST function at all.

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

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. If there's no such error, then UnrealIRCd continues to MOD_INIT.

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
The most important function is MOD_INIT, it is defined as shown below. This function is executed when the module is loaded and is responsible for doing any initial structure initialization, registering of hooks and callbacks, as well as registering channel and user modes.

DLLFUNC int MOD_INIT(mymodule)(ModuleInfo *moduleInfo) {           /* Initialization here */ } 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 }

The MOD_LOAD function is called when a module is actually loaded. It's worth noting that if your module permits it, this could happen multiple times if a user unloads then reloads your module, so your module should handle this gracefully or correctly mark itself as not supporting unload operations.

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. As part of this module, you should do any cleanup of internal structures that is necessary. 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.

Loading
Initially, modules are initialized with a call to MOD_INIT, followed by being loaded with a call to MOD_LOAD. If your module requires any other modules to be present, it is important to note this in the documentation, as modules are initialized and loaded in the order that they appear in the configuration file, so this can be significant.

Modules can generally assume all the "core" modes and functionality is present, even though this may or may not include all RFC compliant features since some of those reside in modules that can be disabled.

During the loading and initialization phases, it's useful to initialize any module specific structures and allocate the necessary memory for startup. Please do not allocate anything you may not need initially and avoid time consuming operations during startup, as we want server startup to remain quick.

Unloading
Modules are unloaded either during shutdown or when a user unloads the module. As noted, MOD_UNLOAD will be called when this occurs, giving the module a last change to send any necessary messages or modify any internal structures.

As noted previously, external structures will be cleaned up automatically by Unreal when a module is unloaded, so instead a module should use this as an opportunity for any final actions and to clean up memory it has allocated outside of that which Unreal allocates upon request.