[svn-commits] jrose: trunk r393190 - in /trunk: include/asterisk/features.h main/features.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jun 28 14:19:19 CDT 2013


Author: jrose
Date: Fri Jun 28 14:19:15 2013
New Revision: 393190

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=393190
Log:
features: call pickup stasis refactoring

(issue ASTERISK-21544)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2588/

Modified:
    trunk/include/asterisk/features.h
    trunk/main/features.c

Modified: trunk/include/asterisk/features.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/features.h?view=diff&rev=393190&r1=393189&r2=393190
==============================================================================
--- trunk/include/asterisk/features.h (original)
+++ trunk/include/asterisk/features.h Fri Jun 28 14:19:15 2013
@@ -232,6 +232,15 @@
  */
 int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target);
 
+/*!
+ * \brief accessor for call pickup message type
+ * \since 12.0.0
+ *
+ * \retval pointer to the stasis message type
+ * \retval NULL if not initialized
+ */
+struct stasis_message_type *ast_call_pickup_type(void);
+
 /*! \brief Reload call features from features.conf */
 int ast_features_reload(void);
 

Modified: trunk/main/features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/features.c?view=diff&rev=393190&r1=393189&r2=393190
==============================================================================
--- trunk/main/features.c (original)
+++ trunk/main/features.c Fri Jun 28 14:19:15 2013
@@ -74,6 +74,8 @@
 #include "asterisk/test.h"
 #include "asterisk/bridging.h"
 #include "asterisk/bridging_basic.h"
+#include "asterisk/stasis.h"
+#include "asterisk/stasis_channels.h"
 #include "asterisk/features_config.h"
 
 /* BUGBUG TEST_FRAMEWORK is disabled because parking tests no longer work. */
@@ -320,6 +322,40 @@
 			</see-also>
 		</managerEventInstance>
 	</managerEvent>
+	<managerEvent language="en_US" name="Pickup">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a call pickup occurs.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="TargetChannel"/>
+				<parameter name="TargetChannelState"><para>A numeric code for the channel's current state, related to TargetChannelStateDesc</para></parameter>
+				<parameter name="TargetChannelStateDesc">
+					<enumlist>
+						<enum name="Down"/>
+						<enum name="Rsrvd"/>
+						<enum name="OffHook"/>
+						<enum name="Dialing"/>
+						<enum name="Ring"/>
+						<enum name="Ringing"/>
+						<enum name="Up"/>
+						<enum name="Busy"/>
+						<enum name="Dialing Offhook"/>
+						<enum name="Pre-ring"/>
+						<enum name="Unknown"/>
+					</enumlist>
+				</parameter>
+				<parameter name="TargetCallerIDNum"/>
+				<parameter name="TargetCallerIDName"/>
+				<parameter name="TargetConnectedLineNum"/>
+				<parameter name="TargetConnectedLineName"/>
+				<parameter name="TargetAccountCode"/>
+				<parameter name="TargetContext"/>
+				<parameter name="TargetExten"/>
+				<parameter name="TargetPriority"/>
+				<parameter name="TargetUniqueid"/>
+			</syntax>
+		</managerEventInstance>
+	</managerEvent>
  ***/
 
 #define DEFAULT_PARK_TIME							45000	/*!< ms */
@@ -551,6 +587,13 @@
 	/*! Bridge peer's feature flags. */
 	struct ast_flags peer_features;
 };
+
+static struct ast_manager_event_blob *call_pickup_to_ami(struct stasis_message *message);
+
+STASIS_MESSAGE_TYPE_DEFN(
+	ast_call_pickup_type,
+	.to_ami = call_pickup_to_ami);
+
 
 #if defined(ATXFER_NULL_TECH)
 /*!
@@ -4650,14 +4693,68 @@
 	return res;
 }
 
+static struct ast_manager_event_blob *call_pickup_to_ami(struct stasis_message *message)
+{
+	struct ast_multi_channel_blob *contents = stasis_message_data(message);
+	struct ast_channel_snapshot *chan;
+	struct ast_channel_snapshot *target;
+	struct ast_manager_event_blob *res;
+
+	RAII_VAR(struct ast_str *, channel_str, NULL, ast_free);
+	RAII_VAR(struct ast_str *, target_str, NULL, ast_free);
+
+	chan = ast_multi_channel_blob_get_channel(contents, "channel");
+	target = ast_multi_channel_blob_get_channel(contents, "target");
+
+	ast_assert(chan != NULL && target != NULL);
+
+	if (!(channel_str = ast_manager_build_channel_state_string(chan))) {
+		return NULL;
+	}
+
+	if (!(target_str = ast_manager_build_channel_state_string_prefix(target, "Target"))) {
+		return NULL;
+	}
+
+	res = ast_manager_event_blob_create(EVENT_FLAG_CALL, "Pickup",
+		"%s"
+		"%s",
+		ast_str_buffer(channel_str),
+		ast_str_buffer(target_str));
+
+	return res;
+}
+
+static int send_call_pickup_stasis_message(struct ast_channel *picking_up, struct ast_channel_snapshot *chan, struct ast_channel_snapshot *target)
+{
+	RAII_VAR(struct ast_multi_channel_blob *, pickup_payload, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+
+	if (!(pickup_payload = ast_multi_channel_blob_create(ast_json_null()))) {
+		return -1;
+	}
+
+	ast_multi_channel_blob_add_channel(pickup_payload, "channel", chan);
+	ast_multi_channel_blob_add_channel(pickup_payload, "target", target);
+
+	if (!(msg = stasis_message_create(ast_call_pickup_type(), pickup_payload))) {
+		return -1;
+	}
+
+	stasis_publish(ast_channel_topic(picking_up), msg);
+	return 0;
+}
+
 int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
 {
 	struct ast_party_connected_line connected_caller;
-	struct ast_channel *chans[2] = { chan, target };
 	struct ast_datastore *ds_pickup;
 	const char *chan_name;/*!< A masquerade changes channel names. */
 	const char *target_name;/*!< A masquerade changes channel names. */
 	int res = -1;
+
+	RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_channel_snapshot *, target_snapshot, NULL, ao2_cleanup);
 
 	target_name = ast_strdupa(ast_channel_name(target));
 	ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, ast_channel_name(chan));
@@ -4707,26 +4804,22 @@
 	/* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */
 	ast_channel_hangupcause_set(chan, AST_CAUSE_ANSWERED_ELSEWHERE);
 
+	if (!(chan_snapshot = ast_channel_snapshot_create(chan))) {
+		goto pickup_failed;
+	}
+
+	if (!(target_snapshot = ast_channel_snapshot_create(target))) {
+		goto pickup_failed;
+	}
+
 	if (ast_channel_move(target, chan)) {
 		ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan_name,
 			target_name);
 		goto pickup_failed;
 	}
 
-	/* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a call pickup occurs.</synopsis>
-			<syntax>
-				<parameter name="Channel"><para>The name of the channel that initiated the pickup.</para></parameter>
-				<parameter name="TargetChannel"><para>The name of the channel that is being picked up.</para></parameter>
-			</syntax>
-		</managerEventInstance>
-	***/
-	ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
-		"Channel: %s\r\n"
-		"TargetChannel: %s\r\n",
-		chan_name, target_name);
+	/* target points to the channel that did the pickup at this point, so use that channel's topic instead of chan */
+	send_call_pickup_stasis_message(target, chan_snapshot, target_snapshot);
 
 	res = 0;
 
@@ -5570,6 +5663,7 @@
 
 	ast_unregister_application(app_bridge);
 
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_call_pickup_type);
 	pthread_cancel(parking_thread);
 	pthread_kill(parking_thread, SIGURG);
 	pthread_join(parking_thread, NULL);
@@ -5596,6 +5690,7 @@
 		ast_cli_unregister_multiple(cli_features, ARRAY_LEN(cli_features));
 		return -1;
 	}
+	STASIS_MESSAGE_TYPE_INIT(ast_call_pickup_type);
 	res |= ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
 	res |= ast_manager_register_xml_core("Bridge", EVENT_FLAG_CALL, action_bridge);
 




More information about the svn-commits mailing list