diff options
Diffstat (limited to 'apps/app_queue.c')
-rw-r--r-- | apps/app_queue.c | 89 |
1 files changed, 78 insertions, 11 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c index f7cee6a76..ddb62d2e0 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -5884,6 +5884,7 @@ static void handle_bridge_enter(void *userdata, struct stasis_subscription *sub, { struct queue_stasis_data *queue_data = userdata; struct ast_bridge_blob *enter_blob = stasis_message_data(msg); + SCOPED_AO2LOCK(lock, queue_data); if (queue_data->dying) { return; @@ -5902,6 +5903,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, caller_snapshot->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 @@ -5922,16 +5984,17 @@ static void handle_blind_transfer(void *userdata, struct stasis_subscription *su RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup); - if (queue_data->dying) { - return; - } - if (transfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS) { return; } ao2_lock(queue_data); + if (queue_data->dying) { + ao2_unlock(queue_data); + return; + } + if (ast_strlen_zero(queue_data->bridge_uniqueid) || strcmp(queue_data->bridge_uniqueid, transfer_msg->bridge->uniqueid)) { ao2_unlock(queue_data); @@ -5979,10 +6042,6 @@ static void handle_attended_transfer(void *userdata, struct stasis_subscription RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup); - if (queue_data->dying) { - return; - } - if (atxfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS || atxfer_msg->dest_type == AST_ATTENDED_TRANSFER_DEST_THREEWAY) { return; @@ -5990,6 +6049,11 @@ static void handle_attended_transfer(void *userdata, struct stasis_subscription 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; @@ -6173,12 +6237,13 @@ static void handle_hangup(void *userdata, struct stasis_subscription *sub, RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup); enum agent_complete_reason reason; + ao2_lock(queue_data); + if (queue_data->dying) { + ao2_unlock(queue_data); return; } - ao2_lock(queue_data); - if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->caller_uniqueid)) { reason = CALLER; } else if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->member_uniqueid)) { @@ -6207,7 +6272,7 @@ static void handle_hangup(void *userdata, struct stasis_subscription *sub, 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, queue_data->caller_uniqueid, queue_data->member->membername, + ast_queue_log(queue_data->queue->name, caller_snapshot->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); @@ -6268,6 +6333,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(), |