diff options
author | Sean Bright <sean.bright@gmail.com> | 2017-03-09 12:05:12 -0500 |
---|---|---|
committer | Sean Bright <sean.bright@gmail.com> | 2017-03-15 09:33:11 -0600 |
commit | 982d6173c55e67a910fa30e079a1de2cf291c03e (patch) | |
tree | 91a608dcfdfff844dd9506fd2b24c8bbe7a1d7d0 /apps/app_queue.c | |
parent | 71cc3fd9690a28946d141646588d07e6c114c215 (diff) |
app_queue: Handle the caller being redirected out of a queue bridge
A caller can leave the Queue() application after being bridged with a
member in a few ways:
* Caller or member hangup
* Caller is transferred somewhere else (blind or atx)
* Caller is externally redirected elsewhere
The first 2 scenarios are currently handled by subscribing to stasis
messages, but the 3rd is not explicitly covered. If a caller is
redirected away from the Queue() application, the member who was last
bridged with that caller will remain in an "In use" state until the
caller hangs up.
This patch adds handling of the caller leaving the queue via
redirection. We monitor the caller-member bridge, and if the caller is
the one that leaves, we treat it the same as we would a caller hangup.
ASTERISK-26400 #close
Reported by: Etienne Lessard
Change-Id: Iba160907770de5a6c9efeffc9df5a13e9ea75334
Diffstat (limited to 'apps/app_queue.c')
-rw-r--r-- | apps/app_queue.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c index 204b4b2de..c0de00173 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -5966,6 +5966,67 @@ static void handle_bridge_enter(void *userdata, struct stasis_subscription *sub, } /*! + * \internal + * \brief Handle a stasis bridge leave event. + * + * We track this event to determine if the caller has left the bridge + * as the result of a redirect. Transfers and hangups are handled in + * separate functions. + * + * \param userdata Data pertaining to the particular call in the queue. + * \param sub The stasis subscription on which the message occurred. + * \param msg The stasis message for the bridge leave event + */ +static void handle_bridge_left(void *userdata, struct stasis_subscription *sub, + struct stasis_message *msg) +{ + struct queue_stasis_data *queue_data = userdata; + struct ast_bridge_blob *left_blob = stasis_message_data(msg); + struct ast_channel_snapshot *caller_snapshot, *member_snapshot; + + ao2_lock(queue_data); + + if (queue_data->dying) { + ao2_unlock(queue_data); + return; + } + + if (ast_strlen_zero(queue_data->bridge_uniqueid)) { + ao2_unlock(queue_data); + return; + } + + /* Correct channel, correct bridge? */ + if (strcmp(left_blob->channel->uniqueid, queue_data->caller_uniqueid) + || strcmp(left_blob->bridge->uniqueid, queue_data->bridge_uniqueid)) { + ao2_unlock(queue_data); + return; + } + + caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid); + member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid); + + ao2_unlock(queue_data); + + ast_debug(3, "Detected redirect of queue caller channel %s\n", + caller_snapshot->name); + + ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername, + "COMPLETECALLER", "%ld|%ld|%d", + (long) (queue_data->starttime - queue_data->holdstart), + (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos); + + send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member, + queue_data->holdstart, queue_data->starttime, CALLER); + update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl, + time(NULL) - queue_data->starttime); + remove_stasis_subscriptions(queue_data); + + ao2_cleanup(member_snapshot); + ao2_cleanup(caller_snapshot); +} + +/*! * \brief Handle a blind transfer event * * This event is important in order to be able to log the end of the @@ -6332,6 +6393,8 @@ static int setup_stasis_subs(struct queue_ent *qe, struct ast_channel *peer, str stasis_message_router_add(queue_data->bridge_router, ast_channel_entered_bridge_type(), handle_bridge_enter, queue_data); + stasis_message_router_add(queue_data->bridge_router, ast_channel_left_bridge_type(), + handle_bridge_left, queue_data); stasis_message_router_add(queue_data->bridge_router, ast_blind_transfer_type(), handle_blind_transfer, queue_data); stasis_message_router_add(queue_data->bridge_router, ast_attended_transfer_type(), |