Kamailio: shared memory hashtable

Using shared memory in Kamailio is fundamental and sometimes inevitable. Luckily, Kamailio’s core abstract us from A LOT of the complexity behind this kind of memory management and help us build a ready to use in-memory hash table in no time!

First of all, you need to include the str_hash header file but it is probably implicitly included by some other mandatory header files.

For this example, I’ll store the hashtable’s (HT from now on) address inside a global variable visible from the entire module. Being that the case, I need to create it as follows:

Later, I have to allocate some memory for the variable and there’s no better place for that than the module’s mod_init() function. Having allocated memory, I need to perform another allocation. This time is for the internal str_hash_table structure that contains the metadata for maintaining our information accessible. Usually, the function in charge of this task is str_hash_alloc() but looking its internals, we will find that it uses pkg_malloc() which certainly won’t work for us. Due this situation, I created an equivalent function for shared memory, mostly because Kamailio’s core doesn’t provide this functionality, or at least, I wasn’t able to find it.

Then, I need to define the structure that will be contained into the shared memory.

Storing and retrieving

In this example, I will store the call ID as the key of the HT’s entry and in the useful part, the call’s start and end timestamp.

First, I created a function that encapsulates all the logic for allocating a new call into shared memory. Please notice that having a HT storing your data, it doesn’t implicitly allocate your information in shared memory address space, this is, you have to allocate your structure using shm_malloc() before adding it to the HT.

Every entry in the HT is represented by str_hash_entry which is a linked-list ready structure that contains the key and the data part as an union. Take in consideration that an union is NOT an structure and its fields retain only one value at a time. Whatever modification you make to any field it will immediately affect to the others.

Finally we need a function callable from the script. In this case start_monitoring does this for us and it must be registered as an exported command.

And:

To finish this little tutorial, I present the stop_monitoring which tries to retrieve the entry using the callid of the call. In case it was found, it writes the current timestamp to the field end_timestamp.

PS: I am aware that I never deallocated the memory I used. I may write the dealloc function for the next entry 😀

Visited by a famous

I’m talking about Carsten Bock, one the brightest minds behind the development of opensource VOIP projects. He came to Paraguay for business reasons and me and the guys here at Conexion had the pleasure of learning from him for almost two weeks. Not always we have the opportunity to hang out with such a great VOIP eminence around this part of the world so this situation deserves a blog post :D.