[asterisk-commits] mmichelson: branch mmichelson/queue_bugbug r394456 - /team/mmichelson/queue_b...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jul 16 11:55:21 CDT 2013


Author: mmichelson
Date: Tue Jul 16 11:55:19 2013
New Revision: 394456

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=394456
Log:
Add initial naive hangup detection for queue calls.

This will need some major adjustments once local optimization
is taken into account, but for simple calls, this currently
works fine.


Modified:
    team/mmichelson/queue_bugbug/apps/app_queue.c

Modified: team/mmichelson/queue_bugbug/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/apps/app_queue.c?view=diff&rev=394456&r1=394455&r2=394456
==============================================================================
--- team/mmichelson/queue_bugbug/apps/app_queue.c (original)
+++ team/mmichelson/queue_bugbug/apps/app_queue.c Tue Jul 16 11:55:19 2013
@@ -111,6 +111,7 @@
 #include "asterisk/stasis_message_router.h"
 #include "asterisk/bridging.h"
 #include "asterisk/stasis_bridging.h"
+#include "asterisk/core_local.h"
 
 /* Define, to debug reference counts on queues, without debugging reference counts on queue members */
 /* #define REF_DEBUG_ONLY_QUEUES */
@@ -1936,15 +1937,13 @@
 static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct ast_channel *agent,
 		struct stasis_message_type *type, struct ast_json *blob)
 {
-	struct ast_channel_snapshot *caller_snapshot;
-	struct ast_channel_snapshot *agent_snapshot;
+	RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup);
 
 	caller_snapshot = ast_channel_snapshot_create(caller);
 	agent_snapshot = ast_channel_snapshot_create(agent);
 
 	if (!caller_snapshot || !agent_snapshot) {
-		ast_free(caller_snapshot);
-		ast_free(agent_snapshot);
 		return;
 	}
 
@@ -5275,6 +5274,7 @@
 	time_t starttime;
 	int caller_pos;
 	int callcompletedinsl;
+	int hangup_detected;
 };
 
 static void queue_stasis_data_destructor(void *obj)
@@ -5329,8 +5329,8 @@
 		}
 	} else if (ast_blind_transfer_type() == stasis_message_type(msg)) {
 		struct ast_bridge_blob *blind_blob = stasis_message_data(msg);
-		struct ast_channel_snapshot *caller;
-		struct ast_channel_snapshot *agent;
+		RAII_VAR(struct ast_channel_snapshot *, caller, NULL, ao2_cleanup);
+		RAII_VAR(struct ast_channel_snapshot *, agent, NULL, ao2_cleanup);
 
 		if (ast_strlen_zero(queue_data->bridge_uniqueid) ||
 				strcmp(queue_data->bridge_uniqueid, blind_blob->bridge->uniqueid)) {
@@ -5366,15 +5366,71 @@
 	}
 }
 
+static void queue_channel_cb(void *userdata, struct stasis_subscription *sub,
+		struct stasis_topic *topic, struct stasis_message *msg)
+{
+	struct queue_stasis_data *queue_data = userdata;
+
+	if (stasis_subscription_final_message(sub, msg)) {
+		ao2_cleanup(queue_data);
+	} else if (ast_channel_hangup_request_type() == stasis_message_type(msg)) {
+		struct ast_channel_blob *channel_blob = stasis_message_data(msg);
+		RAII_VAR(struct ast_channel_snapshot *, caller, NULL, ao2_cleanup);
+		RAII_VAR(struct ast_channel_snapshot *, agent, NULL, ao2_cleanup);
+		enum agent_complete_reason reason;
+
+		ao2_lock(queue_data);
+		if (queue_data->hangup_detected) {
+			ao2_unlock(queue_data);
+			return;
+		}
+		queue_data->hangup_detected = 1;
+		ao2_unlock(queue_data);
+
+		if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->caller_uniqueid)) {
+			reason = CALLER;
+		} else if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->agent_uniqueid)) {
+			reason = AGENT;
+		} else {
+			ast_log(LOG_WARNING, "Unexpected hangup request event received for channel %s\n",
+					channel_blob->snapshot->uniqueid);
+			return;
+		}
+
+		caller = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
+		agent = ast_channel_snapshot_get_latest(queue_data->agent_uniqueid);
+
+		ast_queue_log(queue_data->queue, 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);
+		ast_log(LOG_NOTICE, "Detected hangup request on channel %s\n", channel_blob->snapshot->name);
+		send_agent_complete(queue_data->queue, caller, agent, queue_data->member,
+				queue_data->holdstart, queue_data->starttime, reason);
+	}
+}
+
 static int setup_stasis_subs(struct queue_ent *qe, struct ast_channel *peer, struct member *mem,
 		time_t holdstart, time_t starttime, int callcompletedinsl)
 {
 	struct queue_stasis_data *queue_data = queue_stasis_data_alloc(qe, peer, mem, holdstart, starttime, callcompletedinsl);
+	RAII_VAR(struct ast_channel *, local_caller, ast_local_get_peer(qe->chan), ast_channel_cleanup);
 
 	if (!queue_data) {
 		return -1;
 	}
 	stasis_subscribe(ast_bridge_topic_all(), queue_bridge_cb, queue_data);
+	ao2_ref(queue_data, +1);
+	stasis_subscribe(ast_channel_topic(qe->chan), queue_channel_cb, queue_data);
+	ao2_ref(queue_data, +1);
+	stasis_subscribe(ast_channel_topic(peer), queue_channel_cb, queue_data);
+	if (local_caller) {
+		/* Local optimization events are published on the ;1 channel topic, so if applicable,
+		 * we need to subscribe to that channel's topic
+		 */
+		ao2_ref(queue_data, +1);
+		stasis_subscribe(ast_channel_topic(local_caller), queue_channel_cb, queue_data);
+	}
 	return 0;
 }
 




More information about the asterisk-commits mailing list