[asterisk-dev] AstriDevCon Follow Up - Asterisk and Kamailio - smoother integration

Matthew Jordan mjordan at digium.com
Mon Feb 23 10:46:20 CST 2015

On Mon, Feb 23, 2015 at 9:26 AM, Olle E. Johansson <oej at edvina.net> wrote:

> On 23 Feb 2015, at 16:19, Matthew Jordan <mjordan at digium.com> wrote:
> On Wed, Feb 11, 2015 at 11:12 AM, Olle E. Johansson <oej at edvina.net>
> wrote:
>> On 11 Feb 2015, at 17:50, Matthew Jordan <mjordan at digium.com> wrote:
>> On Tue, Feb 3, 2015 at 6:11 AM, Daniel-Constantin Mierla <
>> miconda at gmail.com> wrote:
>> I was thinking some more about this, and I realized that I'm not really
>> sure how I would pick a specific Asterisk server in a pool of servers.
>> This is probably going to demonstrate some of my ignorance when it comes
>> to Kamailio, but I'm going to go ahead anyway :-)
>> Say, for example, we have n Asterisk servers, all of which can serve any
>> need that an inbound SIP request requires. They are generic media
>> application servers, and Kamailio just needs to pick one and send the
>> request to it, most likely indicating the purpose in a SIP header. Then, we
>> may receive a request from Alice to go into a conference room:
>> INVITE sip:conference at my-service-provider.com SIP/2.0
>> From: Alice <alice at super-awesome-company.com>
>> ...
>> And we want to proxy that request to one of our media application
>> servers, turning it into something like this:
>> INVITE sip:conference at asterisk-node-five.mydomain.com SIP/2.0
>> From: Alice <alice at super-awesome-company.com>
>> To: ...
>> X-Exec-App: Conference
>> X-Exec-App-Data: 1000
>> No need to retarget unless your asterisk is really requiring that domain.
> True. The same questions exist even if we are sending the INVITE request
> to sip:conference at asterisk-node-five.myservice-provider.com however.
>> Any Asterisk server can then receive the request, extract the application
>> to execute, and start the correct application, letting an ARI application
>> do the heavy lifting of actually implementing the requested application.
>> exten => s,1,NoOp()
>>  same => n,Set(app=${PJSIP_HEADER(read,X-Exec-App)})
>>  same => n,Set(args=${PJSIP_HEADER(read,X-Exec-App-Data)})
>>  same => n,Stasis(${app}, ${args})
>>  same => n,Hangup()
>> All of that is fine and good - but how did Kamailio choose
>> "asterisk-node-five" as the Asterisk server to send the request to?
>> There are many ways, our dispatcher module has as many ways to dispatch
>> traffic as Asterisk has
>> queue algorithms.
> I think that's a very apt comparison :-)
> The Queue application's ring strategies can be problematic. In relatively
> simple scenarios they apply fairly well; with sufficient complexity, you
> either have to use other mechanics to achieve the functionality you want
> (say, for example, Local channel members) or you find that your ring
> strategy simply isn't achievable. Sometimes, Asterisk _can_ provide you the
> levers to toggle the behaviour you want; however, in many complex
> scenarios, it can't give you all the functionality you desire. Ideally, you
> want the developer building a system on top of Asterisk to control the
> business application logic - hence, the advent of ARI. In fact, the Queue
> application's ring strategy limitations were a major contributing factor in
> the development of ARI.
> The same could be said here. Sure, I can use one of the many levers that
> exist in the dispatcher module, and there's a reasonable chance that it
> will accommodate the complexity of a particular scenario. Playing around
> with it over the past few days, ds_select_dst is clearly very powerful. On
> the other hand, I'm still limited to the algorithms implemented in
> Kamailio. While I could write my own algorithm in C and contribute it
> upstream, not everyone is a C programmer!
> Which is why we have python, lua, java, perl support...
> It may be given the tight timing constraints that Kamailio exists under
> (which is somewhat tighter than Asterisk determining who to ring in a Call
> Queue) that hardcoding the algorithms in Kamailio is the best way to do it
> - but I'm curious if there are ways outside of that.
> Of course there are.
Well, let's explore that some then. Rambling on...

Starting from the Kamailio documentation, let's say I have the following

# main request routing logic

route {

    # <snip>

    # dispatch destinations


# Dispatch requests
route[DISPATCH] {
    # round robin dispatching on gateways group '1'
    if(!ds_select_dst("1", "4"))
        send_reply("404", "No destination");
    xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");

Interestingly, the example dispatcher list file hard codes the destinations
in group '1', although ostensibly I suppose this could come from a database
as well. Let's assume that part is solved.

Let's say I wanted to use round-robin in the example above for all
requests, unless the request is for a conference. Then, I need to do the
(1) If someone from the same domain is already in a conference, I should
route the request to that Asterisk server.
(2) If that request lands on an Asterisk server already serving conferences
for that domain, I may still not be in the right location. The new request
- even though it is from the same domain and wants a conference - may not
want to be in the same conference as the other person. That means that it
may be serviced by the Asterisk server it landed on, or, if that Asterisk
server determines that it would get too loaded for handling another
conference on that server, it may get bounced back to Kamailio with a
"please try someone else." In that case, I want to route it to some other

While I could use htable for some of this - and having the state of that
table be cached, replicated across Kamailio servers, etc. is nice - that
honestly feels kind of klunky. If nothing else, I'm putting application
state directly into the Kamailio routing, and that feels like it would be
difficult to maintain. What happens when a new application is added
(Queues, IVRs, Recording, etc.)? Yikes.

Alternatively, I could dump this out to another language, like you

# Dispatch requests
route[DISPATCH] {

    # ask Python what it wants to do

    python_exec("do_app_routing", "")


Where the Python script itself does lookups. Fair enough; at that point,
scaling the routing is the job of the Python developer (and can make use of
some of the Kamailio primitives through the Router object - documentation
looks a bit sparse on that, but okay).

>> What's more, if those servers are truly dynamic, where we are using
>> something like OpenStack to spin up and spin down Asterisk servers on an
>> as-needed basis, than the mere act of knowing the pool of available
>> Asterisk server is going to be tricky. Granted, the Asterisk servers could
>> register themselves to Kamailio, so it will know at any one time who all is
>> available for a resource, but it feels like the Kamailio routing could get
>> tricky, with a lot of business logic sprinkled into it.
>> We could add the new DMQ message buss to Asterisk which would make
>> Kamailio aware of it.
>> There are many ways. Kamailio monitors the cluster with OPTIONs so if you
>> spin up one that was
>> down, it won't take long before we send traffic.
> Or we could have Kamailio integrate with Asterisk using Corosync :-)
> The DMQ message bus module looks to be rather generic. Is there any
> documentation on the actual messages published over the message bus?
> DMQ sip messages :-)

> The internet is certainly not overflowing with information on this topic,
> at the very least :-)
> I agree that having the load of Asterisk feed out would be interesting. We
> had some discussion about this at AstriDevCon; particularly, what data
> items would be needed. There was some contention around exactly what should
> be available from Asterisk. Things that were listed were:
>    - CPU usage
>    - Channel count
>    - Memory usage
>    - Call quality statistics (as a secondary indicator)
>    - Distribution of response times on requests/responses
> I believe Torey mentioned that they send an INVITE request every so often
> and just see what happens - which is probably similar to the OPTIONS
> request pinging, although you'll get a bit more useful data out of the
> INVITE request.
> Can you think of anything else?
> SUBSCRIBE/NOTIFY format for Asterisk status.
SIP would be an easy way to do it, particularly with how easily extensible
the PJSIP Pub/Sub framework is.

I think this would be a good idea to flesh out more. What would the event
package look like? Should Asterisk PUBLISH to Kamailio, or expect a
SUBSCRIBE and produce periodic NOTIFY requests?

Matthew Jordan
Digium, Inc. | Engineering Manager
445 Jan Davis Drive NW - Huntsville, AL 35806 - USA
Check us out at: http://digium.com & http://asterisk.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-dev/attachments/20150223/7382d4df/attachment-0001.html>

More information about the asterisk-dev mailing list