[asterisk-commits] mjordan: trunk r400061 - in /trunk: ./ apps/app_queue.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sat Sep 28 15:39:12 CDT 2013
Author: mjordan
Date: Sat Sep 28 15:39:10 2013
New Revision: 400061
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=400061
Log:
app_queue: Make manager events tolerant of Local channel shenanigans
app_queue currently attempts to handle Local channel optimizations in an effort
to provide accurate information in Stasis messages (and their corresponding
AMI events) as well as the Queue log. Sometimes, however, things don't go as
planned.
Consider the following scenario:
SIP/foo <-> L;1 <-> L;2 <-> SIP/agent
SIP/agent answers, triggering a Local channel optimization. app_queue will
normally do the following:
* Listen for the Local optimization events and update our agent accordingly
to SIP/agent in the queue log and messages
* When we get a hangup, publish the AgentComplete event based on our
information (SIP/foo and SIP/agent)
However, as with all things that depend on sanity from something as capricious
as Local channels, things can go wrong:
(1) SIP/agent immediately hangs up upon answering. This triggers a race
condition between termination messages coming from SIP/agent and the
ongoing Local channel optimization messages. (Note that this can also
occur with SIP/foo)
(2) In a race condition, Asterisk can (rarely) deliver the hangup messages
prior to the Local channel optimization.
In that case, the messages *may* arrive to app_queue in the following order:
* Hangup SIP/Agent
* Hangup SIP/foo
* Optimize L;1/L;2
* Hangup L;2
* Hangup L;1
When app_queue receives the hangup of the agent or the caller, it will attempt
to publish the AgentComplete event. However, it now has a problem - it thinks
its agent is the ;1 side of the Local channel, as it never received the
optimization event. At the same time, that channel is already gone. This
results in getting NULL from the Stasis cache. What's more, we can't really
wait for the optimization message, as we are currently handling the hangup
of the channel that the optimization event would tell us to use.
This patch modifies the behavior in app_queue such that, since we still have a
lot of pertinent queue information (interface, queue name, etc.), we now raise
the event with what information we know. The channels involved now may or may
not be present. Users will still at least get the "AgentComplete" event, which
"completes" the known Agent information.
Review: https://reviewboard.asterisk.org/r/2878/
(closes issue ASTERISK-22507)
Reported by: Richard Mudgett
........
Merged revisions 400060 from http://svn.asterisk.org/svn/asterisk/branches/12
Modified:
trunk/ (props changed)
trunk/apps/app_queue.c
Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-12-merged' - no diff available.
Modified: trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_queue.c?view=diff&rev=400061&r1=400060&r2=400061
==============================================================================
--- trunk/apps/app_queue.c (original)
+++ trunk/apps/app_queue.c Sat Sep 28 15:39:10 2013
@@ -1870,13 +1870,21 @@
RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
caller = ast_multi_channel_blob_get_channel(obj, "caller");
+ if (caller) {
+ caller_event_string = ast_manager_build_channel_state_string(caller);
+ if (!caller_event_string) {
+ ast_log(AST_LOG_NOTICE, "No caller event string, bailing\n");
+ return;
+ }
+ }
+
agent = ast_multi_channel_blob_get_channel(obj, "agent");
-
- caller_event_string = ast_manager_build_channel_state_string(caller);
- agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
-
- if (!caller_event_string || !agent_event_string) {
- return;
+ if (agent) {
+ agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
+ if (!agent_event_string) {
+ ast_log(AST_LOG_NOTICE, "No agent event string, bailing\n");
+ return;
+ }
}
event_string = ast_manager_str_from_json_object(ast_multi_channel_blob_get_json(obj), NULL);
@@ -1888,8 +1896,8 @@
"%s"
"%s"
"%s",
- ast_str_buffer(caller_event_string),
- ast_str_buffer(agent_event_string),
+ caller_event_string ? ast_str_buffer(caller_event_string) : "",
+ agent_event_string ? ast_str_buffer(agent_event_string) : "",
ast_str_buffer(event_string));
}
@@ -1925,7 +1933,9 @@
}
ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
- ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
+ if (agent_snapshot) {
+ ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
+ }
msg = stasis_message_create(type, payload);
if (!msg) {
@@ -5150,9 +5160,6 @@
const char *reason = NULL; /* silence dumb compilers */
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
- ast_assert(peer != NULL);
- ast_assert(caller != NULL);
-
switch (rsn) {
case CALLER:
reason = "caller";
@@ -5729,7 +5736,7 @@
ast_debug(3, "Detected hangup of queue %s channel %s\n", reason == CALLER ? "caller" : "member",
channel_blob->snapshot->name);
- ast_queue_log(queue_data->queue->name, caller_snapshot->uniqueid, queue_data->member->membername,
+ ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
reason == CALLER ? "COMPLETECALLER" : "COMPLETEAGENT", "%ld|%ld|%d",
(long) (queue_data->starttime - queue_data->holdstart),
(long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
More information about the asterisk-commits
mailing list