[asterisk-dev] SIP call-limit and Realtime

Russell Bryant russell at digium.com
Fri Jan 18 17:14:28 CST 2008

Atis Lezdins wrote:
> I've been trying to get working SIP "in use" indications for usage in
> queue, however they are not working with Realtime, unless i enable
> "rtcachefriends". Are there any significant problems behind this like
> with hints and qualify, or this is a bug?
> Without "rtcachefriends" i get nothing in "sip show peers/users/objects/inuse".
> Asterisk version - 1.4.17

(Short version)

This is a known issue, that will be non-trivial to resolve.  It certainly can't 
be done for Asterisk 1.4.

(Long version)

The reason that this happens comes down to the way device state reporting works 
in Asterisk (1.4).  For a typical state change, something happens in chan_sip 
that changes the state of a device.  Then, it calls ast_device_state_changes() 
or something similar.  Now, here is where things get silly.

This function simply queues up an event to the device state processing thread to 
tell it that the state of "SIP/something" just changed.  But, to get what the 
state changed to, it has to call a callback in chan_sip.  For this function in 
chan_sip to find out the state of a device, it has to look at the SIP peer 
struct.  To get it, it calls find_peer(), which is an expensive lookup in the 
peer list for the case of non-realtime.  In the case of realtime, the peer is 
already gone from memory, and it is has to build it from the realtime backend 
again.  Because of this, important information needed to determine what the 
state change was is no longer available in the peer struct.

The way this all works has bothered me for a while.  I improved the situation in 
Asterisk trunk (and 1.6), but the benefits of the changes have not been applied 
to chan_sip, yet.  Basically, the main change that I made was to change the 
device state API such that when you call ast_device_state_changed() or whatever 
it is, you actually provide the state that the device changed to, as opposed to 
making another thread issue a callback and do some expensive logic to figure it out.

So, the fix, at least for trunk, is to go through and modify the uses of 
ast_device_state_changed() and friends to use ast_devstate_changed() and friends 
so that the new device state is immediately provided.  It makes the process 
_much_ more efficient, and gets the information out of the realtime peer before 
it disappears from memory.

Also, not all device state changes are done through device state API calls in 
the channel drivers.  ast_setstate() also generates a device state change, which 
is used for _all_ channel types.

Now, here is where it gets a bit more tricky.  There is some logic in the device 
state handling code that checks to see if the state of the device has been 
provided for us.  If it has, then it knows device states are being provided, and 
are truly event driven, and they do not need to be polled for by issuing the 
device state provider's callback.  In that case, if someone asks for the state 
of the device, and the device states are being given to us instead of being 
retrieved with a callback, the last known state from the cache is returned, 
instead of using the callback.

At this point, none of the channel drivers are using this new method of 
providing device state.  Only the simpler device state providers such as MeetMe, 
SLA, Parking, and Custom do.  Because ast_setstate() is involved, if one channel 
driver gets converted, they all need to get converted.  It's a big job, but it 
needs to be done.

Getting this done is actually the biggest thing in the way of implementing 
distributed device state support.  It has been in my head for a long time, but I 
just haven't been motivated enough to focus down and get it done.

Russell Bryant
Senior Software Engineer
Open Source Team Lead
Digium, Inc.

More information about the asterisk-dev mailing list