Kamailio: Пишем модуль

Kamailio достаточно развитый программный продукт и в его снаряжение входит порядка двухсот добрых модулей, на все случаи жизни, но настает какой-то момент и хочется расширить функциональность под свой конкретный случай.

Kamailio написан на Си, и модули тоже предполагается писать на С, помимо этого есть возможность вызова кода на Java(APP_JAVA), Python(APP_PYTHON), Perl(APP_PERL), Mono(APP_MONO), Lua(APP_LUA). В дополнении, в следующей статье я опишу как с небольшими изменениями можно писать native модули для Kamailio под С++ с использованием стандартной библиотеки и boost. Пока, что попробуем просто собрать модуль.

С документацией kamailio дела обстоят довольно не плохо, есть подробное описание разработки модуле под Kamailio v3.2.0, но к сожалению не очень актуально. Помимо этого есть руководства по написанию config файла, для каждой из версий. К сожалению лучшей документацией по прежнему остается исходный код ( лучше конечно в оформленном виде ).

Начнем, с установкой мы разобрались в предыдущем посте, теперь создадим каркас модуля. Все модули Kamailio располагаются в папке modules, при построении Kamailio рекурсивно обходит все директории, поэтому просто создаем свою директорию, с файлами:

kamailio/modules/my_module
  Makefile
  my_module.c

Все довольно просто и детально описано в 16.9. Developing a new module, так что просто приведу содержимое и моменты, которые не описаны в документации.

Makefile:

include ../../Makefile.defs

auto_gen=
NAME=my_module.so

DEFS+=-DKAMAILIO_MOD_INTERFACE

include ../../Makefile.modules

my_module.c:

#include "../../sr_module.h"

MODULE_VERSION

static int mod_init();

// The real structure is kam_module_exports
// due to we define  KAMAILIO_MOD_INTERFACE
struct module_exports exports = {
  "my_module", /**< module name */
  DEFAULT_DLFLAGS, /**< flags for dlopen  */
  0, /**< null term array of the exported commands */
  0, /**< null term array of the exported module parameters */
  0, /**< null term array of the exported module statistics */
  0, /**< null terminated array of the exported MI functions */
  0, /*!< null terminated array of the
          exported module items (pseudo-variables) */
  0, /**< null terminated array of the
                    additional processes required by the
                    module */
  mod_init, /**< Initialization function */
  0, /**< function used for responses,
          returns yes or no; can be null */
  0, /**< function called when the module should
          be "destroyed", e.g: on ser exit;
          can be null */
  0, /**< function called by all processes
          after the fork */
};

static int mod_init() {
  INFO("%s - initializing\n", exports.name);
  return 0;
}

Процесс установки, я уже описывал, так что буду краток:

$ KAM_PREFIX=/home/user/kamailio/build
$ make install_modules="my_module" cfg
$ make all
$ make modules
$ make PREFIX=$KAM_PREFIX install

После этого в должен появиться файл $KAM_PREFIX/lib64/kamailio/modules/my_module.so - это и есть новый модуль.

Теперь осталось написать простенький скрипт чтобы его подгрузить (my_module.cfg):

# This is the comment
debug=2 # 2 - Info level
        # 3 - Debug level
log_stderror=yes # Logging to the console
listen=udp:127.0.0.1:5060
# The list of directories with modules
# Can be separated by ;
mpath="build/lib64/kamailio/modules"
loadmodule "my_module.so"
# main routing logic
route {
  exit; # Just exit do nothing
}

Остался только запуск:

$ $KAM_PREFIX/sbin/kamailio -DD -w . -f my_module.cfg

Если все хорошо, то должна появиться строчка:

INFO: my_module [my_module.c:32]: mod_init(): my_module - initializing

Ну вот и все, скелет модуля готов!