Kamailio by example - KEMI: Introduction with lua

2 minute read


:information_source: Note: Read the official docs to get the most updated information.

Kamailio Embedded Interface (KEMI) allows you to use various scripting languages to write Kamailio configuration scripts. This flexibility lets you leverage the features and libraries of languages like Lua, Python and others, for your SIP server configurations.

While the native scripting language offers a large set of functions but its limits are met in some cases, especially when in need to integrate with external systems. Another missing feature in the native is reloading without a restart.

The main benefits of using KEMI framework:

  • Reload of routing scripts without restarting of Kamailio;
  • More complete and flexible scripting languages, with larger set of libraries that can be used from the scripting languages;
  • Possibility to test the code;


The KEMI allows the equivalent of routing blocks to be written in a different scripting language, as functions. Each supported language has a module that links Kamailio to the scripting interpreter:

// kamailio.cfg

// global parameters
// module settings

loadmodule <KEMI_MODULE>
modparam(<KEMI_MODULE>, "load", <SCRIPT_PATH>)

// routing in <SCRIPT_PATH>


Several functions directly to KSR module with the format KSR.function(params), , like KSR.is_myself("sip:") which are mostly the main functions from the core and for writing log messages (from xlog).

There’s also exported functions from modules, with the format KSR.module.function(params) The function name may not be exact since the native configuration allow dynamic arguments, unlike the scripting versions, like KSR.dispatcher.ds_is_from_list_uri(int groupid, int mode, str "uri").

The KSR.x submodule provides special functions that need custom code per interpreter.

  • KSR.x.modf(str "fname", params...) Execute a function, if not available in KSR.
  • KSR.x.exit() Equivalent of exit from native, since the exit will exit the app in some languages. Use return as an alternative.
  • KSR.x.drop() Equivalent of drop from native kamailio.


As we saw in the KEMI intro, we just need load the module, set the load path, and the cfgengine:

#!defenvs KAMA_LISTEN

loadmodule "sl"
modparam("sl", "bind_tm", 0)

loadmodule "app_lua"
modparam("app_lua", "load", "/etc/kamailio/cfg/1-kemi/100-kemi-lua.lua")

cfgengine "lua"
function ksr_request_route()
    KSR.sl.send_reply(200, "Hello, World!")

How to test: Check the kamalab to prepare your lab.

# kamalab ❯
# select kemi-lua
# Listening on
#              udp: []:5060
#              tcp: []:5060
# Aliases:

In another terminal let’s send OPTIONS to the server:

# >
# ...
# OPTIONS sip: SIP/2.0
# ...
# SIP/2.0 200 Hello, World!
# ...

We see that:

  • We get the 200 Hello, World! response version in lua.



Leave a Comment