[asterisk-dev] SIP call-limit and Realtime
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
This is a known issue, that will be non-trivial to resolve. It certainly can't
be done for Asterisk 1.4.
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.
Senior Software Engineer
Open Source Team Lead
More information about the asterisk-dev