Dev:Module

From UnrealIRCd documentation wiki
Jump to: navigation, search

Below we will explain why modules are useful and how to get started with writing a module, step by step. This article assumes you are developing for UnrealIRCd 4 (the old API is a little different).

Why Modules?

Within UnrealIRCd 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

Includes

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

#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) = {
            "mymodule",
            "$Id$",
            "My custom command",
            "3.2-b8-1",
            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.

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.

MOD_TEST(mymodule)
{
    /* 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

MOD_INIT(mymodule)
{
    /* 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

MOD_LOAD(mymodule)
{
    // 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.

MOD_UNLOAD

MOD_UNLOAD(mymodule)
{
	// Perform any cleanup for unload
	return MOD_SUCCESS;
}

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

UnrealIRCd 4

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:~/unrealircd-4.0.0$ cp /tmp/somemodule.c src/modules/third/
syzop@vulnscan:~/unrealircd-4.0.0$ make

UnrealIRCd 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/unrealircd-4.0.0

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.