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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 17 13:50:48 CDT 2013


Author: mmichelson
Date: Wed Jul 17 13:50:45 2013
New Revision: 394584

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=394584
Log:
Initial optimization support.

I can have the agent or the caller's channels optimize and I properly
send an agent complete when the call finishes.

The reason this is listed as "initial" is because this is going to need
some work in the synchronization department. Next commit will introduce
some much-needed locking.


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=394584&r1=394583&r2=394584
==============================================================================
--- team/mmichelson/queue_bugbug/apps/app_queue.c (original)
+++ team/mmichelson/queue_bugbug/apps/app_queue.c Wed Jul 17 13:50:45 2013
@@ -113,6 +113,7 @@
 #include "asterisk/stasis_bridging.h"
 #include "asterisk/core_local.h"
 #include "asterisk/mixmonitor.h"
+#include "asterisk/core_unreal.h"
 
 /* Define, to debug reference counts on queues, without debugging reference counts on queue members */
 /* #define REF_DEBUG_ONLY_QUEUES */
@@ -5144,10 +5145,11 @@
 struct local_optimization {
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(dest_bridge_uniqueid);
-		AST_STRING_FIELD(replacement_chan_uniqueid);
-		AST_STRING_FIELD(orig_chan_uniqueid);
+		AST_STRING_FIELD(dest_chan_uniqueid);
+		AST_STRING_FIELD(source_chan_uniqueid);
 	);
 	int in_progress;
+	unsigned int id;
 };
 
 struct queue_stasis_data {
@@ -5165,9 +5167,7 @@
 	int callcompletedinsl;
 	int dying;
 	struct stasis_subscription *bridge_sub;
-	struct stasis_subscription *caller_sub;
-	struct stasis_subscription *local_caller_sub;
-	struct stasis_subscription *agent_sub;
+	struct stasis_subscription *channel_sub;
 	struct local_optimization caller_optimize;
 	struct local_optimization agent_optimize;
 };
@@ -5180,6 +5180,8 @@
 
 	ao2_cleanup(queue_data->member);
 	ao2_cleanup(queue_data->queue);
+	ast_string_field_free_memory(&queue_data->caller_optimize);
+	ast_string_field_free_memory(&queue_data->agent_optimize);
 	ast_string_field_free_memory(queue_data);
 }
 
@@ -5187,9 +5189,7 @@
 {
 	queue_data->dying = 1;
 	queue_data->bridge_sub = stasis_unsubscribe(queue_data->bridge_sub);
-	queue_data->caller_sub = stasis_unsubscribe(queue_data->caller_sub);
-	queue_data->local_caller_sub = stasis_unsubscribe(queue_data->local_caller_sub);
-	queue_data->agent_sub = stasis_unsubscribe(queue_data->agent_sub);
+	queue_data->channel_sub = stasis_unsubscribe(queue_data->channel_sub);
 }
 
 static struct queue_stasis_data *queue_stasis_data_alloc(struct queue_ent *qe,
@@ -5199,7 +5199,13 @@
 	struct queue_stasis_data *queue_data;
 
 	queue_data = ao2_alloc(sizeof(*queue_data), queue_stasis_data_destructor);
-	if (!queue_data || ast_string_field_init(queue_data, 64)) {
+	if (!queue_data) {
+		return NULL;
+	}
+
+	if (ast_string_field_init(queue_data, 64) || ast_string_field_init(&queue_data->agent_optimize, 64) ||
+			ast_string_field_init(&queue_data->caller_optimize, 64)) {
+		ao2_cleanup(queue_data);
 		return NULL;
 	}
 
@@ -5305,9 +5311,122 @@
 	}
 }
 
-static void handle_local_optimization(struct queue_stasis_data *queue_data, struct stasis_message *msg)
-{
-	/* XXX STUB */
+static void handle_local_optimization_begin(struct queue_stasis_data *queue_data, struct stasis_message *msg)
+{
+	struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
+	struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
+	struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
+	struct ast_channel_snapshot *source = ast_multi_channel_blob_get_channel(optimization_blob, "source");
+	enum ast_unreal_channel_indicator dest;
+	struct local_optimization *optimization;
+	unsigned int id;
+
+	if (!strcmp(local_one->uniqueid, queue_data->agent_uniqueid)) {
+		optimization = &queue_data->agent_optimize;
+	} else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {
+		optimization = &queue_data->caller_optimize;
+	} else {
+		return;
+	}
+
+	/* First going to make sure things are detected properly. */
+	ast_log(LOG_NOTICE, "OPTIMIZATION IS HAPPENING. PREPARE FOR DUMPAGE!\n");
+	ast_log(LOG_NOTICE, "Local ;1 channel is %s\n", local_one->name);
+	ast_log(LOG_NOTICE, "Local ;2 channel is %s\n", local_two->name);
+	if (source) {
+		ast_log(LOG_NOTICE, "Source channel is %s\n", source->name);
+	}
+
+	dest = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "dest"));
+
+	ast_log(LOG_NOTICE, "Destination bridge is %s\n",
+			dest == AST_UNREAL_OWNER ? local_one->bridgeid : local_two->bridgeid);
+
+	id = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "id"));
+
+	ast_log(LOG_NOTICE, "ID for optimization is %u\n", id);
+
+	ast_string_field_set(optimization, dest_bridge_uniqueid, dest == AST_UNREAL_OWNER ? local_one->bridgeid : local_two->bridgeid);
+	ast_string_field_set(optimization, dest_chan_uniqueid, dest == AST_UNREAL_OWNER ? local_one->uniqueid : local_two->uniqueid);
+	if (source) {
+		ast_string_field_set(optimization, source_chan_uniqueid, source->uniqueid);
+	}
+	optimization->id = id;
+	optimization->in_progress = 1;
+}
+
+static void handle_local_optimization_end(struct queue_stasis_data *queue_data, struct stasis_message *msg)
+{
+	struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
+	struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
+	struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
+	struct local_optimization *optimization;
+	unsigned int id;
+	int is_caller;
+
+	if (!strcmp(local_one->uniqueid, queue_data->agent_uniqueid)) {
+		optimization = &queue_data->agent_optimize;
+		is_caller = 0;
+	} else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {
+		optimization = &queue_data->caller_optimize;
+		is_caller = 1;
+	} else {
+		return;
+	}
+
+	id = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "id"));
+
+	if (!optimization->in_progress) {
+		ast_log(LOG_WARNING, "Told of a local optimization end when we had no previous begin\n");
+		return;
+	}
+
+	if (id != optimization->id) {
+		ast_log(LOG_WARNING, "Local optimization end event ID does not match begin (%u != %u)\n",
+				id, optimization->id);
+		return;
+	}
+
+	ast_string_field_set(queue_data, bridge_uniqueid, optimization->dest_bridge_uniqueid);
+	if (is_caller) {
+		ast_string_field_set(queue_data, caller_uniqueid, optimization->source_chan_uniqueid);
+	} else {
+		ast_string_field_set(queue_data, agent_uniqueid, optimization->source_chan_uniqueid);
+	}
+
+	optimization->in_progress = 0;
+}
+
+static void handle_hangup(struct queue_stasis_data *queue_data, struct stasis_message *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;
+
+	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 {
+		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->name, 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->name, caller, agent, queue_data->member,
+			queue_data->holdstart, queue_data->starttime, reason);
+	update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
+			time(NULL) - queue_data->starttime);
+	remove_stasis_subscriptions(queue_data);
 }
 
 static void queue_channel_cb(void *userdata, struct stasis_subscription *sub,
@@ -5324,39 +5443,17 @@
 	}
 
 	if (ast_local_optimization_begin_type() == stasis_message_type(msg)) {
-		handle_local_optimization(queue_data, msg);
+		handle_local_optimization_begin(queue_data, msg);
+		return;
+	}
+
+	if (ast_local_optimization_end_type() == stasis_message_type(msg)) {
+		handle_local_optimization_end(queue_data, msg);
 		return;
 	}
 	
 	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;
-
-		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->name, 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->name, caller, agent, queue_data->member,
-				queue_data->holdstart, queue_data->starttime, reason);
-		update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
-				time(NULL) - queue_data->starttime);
-		remove_stasis_subscriptions(queue_data);
+		handle_hangup(queue_data, msg);
 	}
 }
 
@@ -5364,23 +5461,14 @@
 		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;
 	}
+
 	queue_data->bridge_sub = stasis_subscribe(ast_bridge_topic_all(), queue_bridge_cb, queue_data);
 	ao2_ref(queue_data, +1);
-	queue_data->caller_sub = stasis_subscribe(ast_channel_topic(qe->chan), queue_channel_cb, queue_data);
-	ao2_ref(queue_data, +1);
-	queue_data->agent_sub = 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);
-		queue_data->local_caller_sub = stasis_subscribe(ast_channel_topic(local_caller), queue_channel_cb, queue_data);
-	}
+	queue_data->channel_sub = stasis_subscribe(ast_channel_topic_all(), queue_channel_cb, queue_data);
 	return 0;
 }
 




More information about the asterisk-commits mailing list