[svn-commits] dlee: branch dlee/ari-authn r393125 - in /team/dlee/ari-authn: ./ apps/ apps/...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jun 28 09:20:50 CDT 2013


Author: dlee
Date: Fri Jun 28 09:20:48 2013
New Revision: 393125

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=393125
Log:
Merged revisions 392797-393100 from http://svn.asterisk.org/svn/asterisk/trunk

Modified:
    team/dlee/ari-authn/   (props changed)
    team/dlee/ari-authn/CHANGES
    team/dlee/ari-authn/Makefile
    team/dlee/ari-authn/apps/app_celgenuserevent.c
    team/dlee/ari-authn/apps/app_dial.c
    team/dlee/ari-authn/apps/app_queue.c
    team/dlee/ari-authn/apps/confbridge/conf_chan_announce.c
    team/dlee/ari-authn/channels/chan_motif.c
    team/dlee/ari-authn/channels/chan_sip.c
    team/dlee/ari-authn/funcs/func_channel.c
    team/dlee/ari-authn/include/asterisk/bridging.h
    team/dlee/ari-authn/include/asterisk/cel.h
    team/dlee/ari-authn/include/asterisk/config_options.h
    team/dlee/ari-authn/include/asterisk/features.h
    team/dlee/ari-authn/include/asterisk/sorcery.h
    team/dlee/ari-authn/include/asterisk/stasis_app.h
    team/dlee/ari-authn/include/asterisk/stasis_channels.h
    team/dlee/ari-authn/main/bridging.c
    team/dlee/ari-authn/main/cdr.c
    team/dlee/ari-authn/main/cel.c
    team/dlee/ari-authn/main/config_options.c
    team/dlee/ari-authn/main/devicestate.c
    team/dlee/ari-authn/main/features.c
    team/dlee/ari-authn/main/http.c
    team/dlee/ari-authn/main/manager.c
    team/dlee/ari-authn/main/named_acl.c
    team/dlee/ari-authn/main/parking.c
    team/dlee/ari-authn/main/presencestate.c
    team/dlee/ari-authn/main/sorcery.c
    team/dlee/ari-authn/main/stasis_channels.c
    team/dlee/ari-authn/res/parking/parking_applications.c
    team/dlee/ari-authn/res/parking/parking_bridge.c
    team/dlee/ari-authn/res/parking/parking_bridge_features.c
    team/dlee/ari-authn/res/parking/parking_controller.c
    team/dlee/ari-authn/res/parking/parking_manager.c
    team/dlee/ari-authn/res/parking/res_parking.h
    team/dlee/ari-authn/res/res_calendar.c
    team/dlee/ari-authn/res/res_parking.c
    team/dlee/ari-authn/res/res_sip/sip_options.c
    team/dlee/ari-authn/res/res_stasis_http.c
    team/dlee/ari-authn/res/res_stasis_http_channels.c
    team/dlee/ari-authn/res/stasis/control.c
    team/dlee/ari-authn/res/stasis_http/resource_channels.c
    team/dlee/ari-authn/res/stasis_http/resource_channels.h
    team/dlee/ari-authn/rest-api/api-docs/channels.json

Propchange: team/dlee/ari-authn/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Propchange: team/dlee/ari-authn/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Jun 28 09:20:48 2013
@@ -1,1 +1,1 @@
-/trunk:1-392779
+/trunk:1-393124

Modified: team/dlee/ari-authn/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/CHANGES?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/CHANGES (original)
+++ team/dlee/ari-authn/CHANGES Fri Jun 28 09:20:48 2013
@@ -329,6 +329,11 @@
 
  * The AMI command 'ParkedCalls' will now accept a 'ParkingLot' argument which
    can be used to get a list of parked calls only for a specific parking lot.
+
+ * The AMI command 'Park' has had the argument 'Channel2' renamed to
+   'TimeoutChannel'. 'TimeoutChannel' is no longer a required argument.
+   'Channel2' can still be used as the argument name, but it is deprecated
+   and the 'TimeoutChannel' argument will be used if both are present.
 
  * The ParkAndAnnounce application is now provided through res_parking instead
    of through the separate app_parkandannounce module.

Modified: team/dlee/ari-authn/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/Makefile?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/Makefile (original)
+++ team/dlee/ari-authn/Makefile Fri Jun 28 09:20:48 2013
@@ -476,7 +476,7 @@
 	@echo "</docs>" >> $@
 
 ifneq ($(GREP),)
-  XMX_full_en_US = $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
+  XML_full_en_US = $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
 endif
 
 doc/full-en_US.xml: makeopts .lastclean $(XML_full_en_US)

Modified: team/dlee/ari-authn/apps/app_celgenuserevent.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/apps/app_celgenuserevent.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/apps/app_celgenuserevent.c (original)
+++ team/dlee/ari-authn/apps/app_celgenuserevent.c Fri Jun 28 09:20:48 2013
@@ -62,6 +62,7 @@
 {
 	int res = 0;
 	char *parse;
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(event);
 		AST_APP_ARG(extra);
@@ -74,7 +75,13 @@
 	parse = ast_strdupa(data);
 	AST_STANDARD_APP_ARGS(args, parse);
 
-	ast_cel_report_event(chan, AST_CEL_USER_DEFINED, args.event, args.extra, NULL);
+	blob = ast_json_pack("{s: s, s: s}",
+		"event", args.event,
+		"extra", args.extra);
+	if (!blob) {
+		return res;
+	}
+	ast_cel_publish_event(chan, AST_CEL_USER_DEFINED, blob);
 	return res;
 }
 

Modified: team/dlee/ari-authn/apps/app_dial.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/apps/app_dial.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/apps/app_dial.c (original)
+++ team/dlee/ari-authn/apps/app_dial.c Fri Jun 28 09:20:48 2013
@@ -859,8 +859,6 @@
 		ast_clear_flag64(o, OPT_IGNORE_CONNECTEDLINE);
 	}
 
-	ast_cel_report_event(in, AST_CEL_FORWARD, NULL, ast_channel_call_forward(c), NULL);
-
 	/* Before processing channel, go ahead and check for forwarding */
 	ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", ast_channel_name(in), tech, stuff, ast_channel_name(c));
 	/* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
@@ -1004,7 +1002,8 @@
 			ast_channel_unlock(c);
 
 			ast_channel_lock_both(original, in);
-			ast_channel_publish_dial(in, original, NULL, "CANCEL");
+			ast_channel_publish_dial_forward(in, original, NULL, "CANCEL",
+				ast_channel_call_forward(c));
 			ast_channel_unlock(in);
 			ast_channel_unlock(original);
 

Modified: team/dlee/ari-authn/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/apps/app_queue.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/apps/app_queue.c (original)
+++ team/dlee/ari-authn/apps/app_queue.c Fri Jun 28 09:20:48 2013
@@ -4449,8 +4449,6 @@
 						o->block_connected_update = 0;
 					}
 
-					ast_cel_report_event(in, AST_CEL_FORWARD, NULL, ast_channel_call_forward(o->chan), NULL);
-
 					ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
 					/* Setup parameters */
 					o->chan = ast_request(tech, ast_channel_nativeformats(in), in, stuff, &status);
@@ -4544,7 +4542,8 @@
 					ast_channel_unlock(qe->chan);
 
 					ast_channel_lock_both(qe->chan, original);
-					ast_channel_publish_dial(qe->chan, original, NULL, "CANCEL");
+					ast_channel_publish_dial_forward(qe->chan, original, NULL, "CANCEL",
+						ast_channel_call_forward(original));
 					ast_channel_unlock(original);
 					ast_channel_unlock(qe->chan);
 					/* Hangup the original channel now, in case we needed it */

Modified: team/dlee/ari-authn/apps/confbridge/conf_chan_announce.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/apps/confbridge/conf_chan_announce.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/apps/confbridge/conf_chan_announce.c (original)
+++ team/dlee/ari-authn/apps/confbridge/conf_chan_announce.c Fri Jun 28 09:20:48 2013
@@ -172,8 +172,8 @@
 int conf_announce_channel_push(struct ast_channel *ast)
 {
 	struct ast_bridge_features *features;
+	struct ast_channel *chan;
 	RAII_VAR(struct announce_pvt *, p, NULL, ao2_cleanup);
-	RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_unref);
 
 	{
 		SCOPED_CHANNELLOCK(lock, ast);
@@ -192,12 +192,15 @@
 
 	features = ast_bridge_features_new();
 	if (!features) {
+		ast_channel_unref(chan);
 		return -1;
 	}
 	ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
 
 	/* Impart the output channel into the bridge */
 	if (ast_bridge_impart(p->bridge, chan, NULL, features, 0)) {
+		ast_bridge_features_destroy(features);
+		ast_channel_unref(chan);
 		return -1;
 	}
 	ao2_lock(p);

Modified: team/dlee/ari-authn/channels/chan_motif.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/channels/chan_motif.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/channels/chan_motif.c (original)
+++ team/dlee/ari-authn/channels/chan_motif.c Fri Jun 28 09:20:48 2013
@@ -2711,9 +2711,9 @@
 	aco_option_register_custom(&cfg_info, "connection", ACO_EXACT, endpoint_options, NULL, custom_connection_handler, 0);
 	aco_option_register_custom(&cfg_info, "transport", ACO_EXACT, endpoint_options, NULL, custom_transport_handler, 0);
 	aco_option_register(&cfg_info, "maxicecandidates", ACO_EXACT, endpoint_options, DEFAULT_MAX_ICE_CANDIDATES, OPT_UINT_T, PARSE_DEFAULT,
-			    FLDSET(struct jingle_endpoint, maxicecandidates));
+			    FLDSET(struct jingle_endpoint, maxicecandidates), DEFAULT_MAX_ICE_CANDIDATES);
 	aco_option_register(&cfg_info, "maxpayloads", ACO_EXACT, endpoint_options, DEFAULT_MAX_PAYLOADS, OPT_UINT_T, PARSE_DEFAULT,
-			    FLDSET(struct jingle_endpoint, maxpayloads));
+			    FLDSET(struct jingle_endpoint, maxpayloads), DEFAULT_MAX_PAYLOADS);
 
 	ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
 
@@ -2764,6 +2764,8 @@
 static int unload_module(void)
 {
 	ast_channel_unregister(&jingle_tech);
+	ast_format_cap_destroy(jingle_tech.capabilities);
+	jingle_tech.capabilities = NULL;
 	ast_rtp_glue_unregister(&jingle_rtp_glue);
 	ast_sched_context_destroy(sched);
 	aco_info_destroy(&cfg_info);

Modified: team/dlee/ari-authn/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/channels/chan_sip.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/channels/chan_sip.c (original)
+++ team/dlee/ari-authn/channels/chan_sip.c Fri Jun 28 09:20:48 2013
@@ -24777,8 +24777,8 @@
 static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req,
 		int *nounlock, struct sip_pvt *replaces_pvt, struct ast_channel *replaces_chan)
 {
+	struct ast_channel *c;
 	RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
-	RAII_VAR(struct ast_channel *, c, NULL, ao2_cleanup);
 
 	if (req->ignore) {
 		return 0;
@@ -24813,7 +24813,9 @@
 	ast_channel_unlock(replaces_chan);
 
 	if (bridge) {
-		ast_bridge_impart(bridge, c, replaces_chan, NULL, 1);
+		if (ast_bridge_impart(bridge, c, replaces_chan, NULL, 1)) {
+			ast_hangup(c);
+		}
 	} else {
 		ast_channel_move(replaces_chan, c);
 		ast_hangup(c);

Modified: team/dlee/ari-authn/funcs/func_channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/funcs/func_channel.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/funcs/func_channel.c (original)
+++ team/dlee/ari-authn/funcs/func_channel.c Fri Jun 28 09:20:48 2013
@@ -37,6 +37,7 @@
 
 #include "asterisk/module.h"
 #include "asterisk/channel.h"
+#include "asterisk/bridging.h"
 #include "asterisk/pbx.h"
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
@@ -118,6 +119,12 @@
 					<enum name="checkhangup">
 						<para>R/O Whether the channel is hanging up (1/0)</para>
 					</enum>
+					<enum name="after_bridge_goto">
+						<para>R/W the parseable goto string indicating where the channel is
+						expected to return to in the PBX after exiting the next bridge it joins
+						on the condition that it doesn't hang up. The parseable goto string uses
+						the same syntax as the <literal>Goto</literal> application.</para>
+					</enum>
 					<enum name="hangup_handler_pop">
 						<para>W/O Replace the most recently added hangup handler
 						with a new hangup handler on the channel if supplied.  The
@@ -475,6 +482,8 @@
 		struct ast_str *tmp_str = ast_str_alloca(1024);
 
 		locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
+	} else if (!strcasecmp(data, "after_bridge_goto")) {
+		ast_after_bridge_goto_read(chan, buf, len);
 	} else if (!strcasecmp(data, "amaflags")) {
 		ast_channel_lock(chan);
 		snprintf(buf, len, "%d", ast_channel_amaflags(chan));
@@ -516,7 +525,13 @@
 		locked_string_field_set(chan, accountcode, value);
 	else if (!strcasecmp(data, "userfield"))
 		locked_string_field_set(chan, userfield, value);
-	else if (!strcasecmp(data, "amaflags")) {
+	else if (!strcasecmp(data, "after_bridge_goto")) {
+		if (ast_strlen_zero(value)) {
+			ast_after_bridge_goto_discard(chan);
+		} else {
+			ast_after_bridge_set_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
+		}
+	} else if (!strcasecmp(data, "amaflags")) {
 		ast_channel_lock(chan);
 		if (isdigit(*value)) {
 			int amaflags;

Modified: team/dlee/ari-authn/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/include/asterisk/bridging.h?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/include/asterisk/bridging.h (original)
+++ team/dlee/ari-authn/include/asterisk/bridging.h Fri Jun 28 09:20:48 2013
@@ -654,7 +654,7 @@
  * \brief Impart (non-blocking) a channel onto a bridge
  *
  * \param bridge Bridge to impart on
- * \param chan Channel to impart
+ * \param chan Channel to impart (The channel reference is stolen if impart successful.)
  * \param swap Channel to swap out if swapping.  NULL if not swapping.
  * \param features Bridge features structure.
  * \param independent TRUE if caller does not want to reclaim the channel using ast_bridge_depart().
@@ -1633,6 +1633,16 @@
  * \return Nothing
  */
 void ast_after_bridge_goto_discard(struct ast_channel *chan);
+
+/*!
+ * \brief Read after bridge goto if it exists
+ * \since 12.0.0
+ *
+ * \param chan Channel to read the after bridge goto parseable goto string from
+ * \param buffer Buffer to write the after bridge goto data to
+ * \param buf_size size of the buffer being written to
+ */
+void ast_after_bridge_goto_read(struct ast_channel *chan, char *buffer, size_t buf_size);
 
 /*! Reason the the after bridge callback will not be called. */
 enum ast_after_bridge_cb_reason {

Modified: team/dlee/ari-authn/include/asterisk/cel.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/include/asterisk/cel.h?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/include/asterisk/cel.h (original)
+++ team/dlee/ari-authn/include/asterisk/cel.h Fri Jun 28 09:20:48 2013
@@ -83,8 +83,6 @@
 	AST_CEL_USER_DEFINED = 21,
 	/*! \brief the last channel with the given linkedid is retired  */
 	AST_CEL_LINKEDID_END = 22,
-	/*! \brief a masquerade happened to alter the participants on a bridge  */
-	AST_CEL_BRIDGE_UPDATE = 23,
 	/*! \brief a directed pickup was performed on this channel  */
 	AST_CEL_PICKUP = 24,
 	/*! \brief this call was forwarded somewhere else  */
@@ -245,6 +243,26 @@
  */
 int ast_cel_fill_record(const struct ast_event *event, struct ast_cel_event_record *r);
 
+/*!
+ * \brief Publish a CEL event
+ * \since 12
+ *
+ * \param chan This is the primary channel associated with this channel event.
+ * \param event_type This is the type of call event being reported.
+ * \param blob This contains any additional parameters that need to be conveyed for this event.
+ */
+void ast_cel_publish_event(struct ast_channel *chan,
+	enum ast_cel_event_type event_type,
+	struct ast_json *blob);
+
+/*!
+ * \brief Get the CEL topic
+ *
+ * \retval The CEL topic
+ * \retval NULL if not allocated
+ */
+struct stasis_topic *ast_cel_topic(void);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/dlee/ari-authn/include/asterisk/config_options.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/include/asterisk/config_options.h?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/include/asterisk/config_options.h (original)
+++ team/dlee/ari-authn/include/asterisk/config_options.h Fri Jun 28 09:20:48 2013
@@ -265,7 +265,7 @@
 	 * struct test_item {
 	 *     int enabled;
 	 * };
-		aco_option_register(&cfg_info, "enabled", ACO_EXACT, my_types, "no", OPT_BOOL_T, 1, FLDSET(struct test_item, enabled));
+	 * aco_option_register(&cfg_info, "enabled", ACO_EXACT, my_types, "no", OPT_BOOL_T, 1, FLDSET(struct test_item, enabled));
 	 * {endcode}
 	 */
 	OPT_BOOL_T,
@@ -284,13 +284,15 @@
 	 * struct test_item {
 	 *     unsigned int flags;
 	 * };
-		aco_option_register(&cfg_info, "quiet", ACO_EXACT, my_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), MY_TYPE_ISQUIET);
-	 * {endcode}
-	 */
-
+	 * aco_option_register(&cfg_info, "quiet", ACO_EXACT, my_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), MY_TYPE_ISQUIET);
+	 * {endcode}
+	 */
 	OPT_BOOLFLAG_T,
 
-	/*! \brief Type for default option handler for character arrays
+	/*! \brief Type for default option handler for character array strings
+	 * \note aco_option_register flags:
+	 *   non-zero : String cannot be empty.
+	 *   0        : String can be empty.
 	 * \note aco_option_register varargs:
 	 *   CHARFLDSET macro with a field of type char[]
 	 *
@@ -299,7 +301,7 @@
 	 * struct test_item {
 	 *     char description[128];
 	 * };
-	 * aco_option_register(&cfg_info, "description", ACO_EXACT, my_types, "none", OPT_CHAR_ARRAY_T, CHARFLDSET(struct test_item, description));
+	 * aco_option_register(&cfg_info, "description", ACO_EXACT, my_types, "none", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct test_item, description));
 	 * {endcode}
 	 */
 	OPT_CHAR_ARRAY_T,
@@ -338,7 +340,7 @@
 	 *     double dub;
 	 * };
 	 * {code}
-	 * aco_option_register(&cfg_info, "doubleopt", ACO_EXACT, my_types, "3", OPT_DOUBLE_T, FLDSET(struct test_item, dub));
+	 * aco_option_register(&cfg_info, "doubleopt", ACO_EXACT, my_types, "3", OPT_DOUBLE_T, 0, FLDSET(struct test_item, dub));
 	 * {endcode}
 	 */
 	OPT_DOUBLE_T,
@@ -393,7 +395,8 @@
 
 	/*! \brief Type for default option handler for stringfields
 	 * \note aco_option_register flags:
-	 *   none
+	 *   non-zero : String cannot be empty.
+	 *   0        : String can be empty.
 	 * aco_option_register varargs:
 	 *   STRFLDSET macro with the field being the field created by AST_STRING_FIELD
 	 *

Modified: team/dlee/ari-authn/include/asterisk/features.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/include/asterisk/features.h?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/include/asterisk/features.h (original)
+++ team/dlee/ari-authn/include/asterisk/features.h Fri Jun 28 09:20:48 2013
@@ -17,7 +17,7 @@
  */
 
 /*! \file
- * \brief Call Parking and Pickup API 
+ * \brief Call Parking and Pickup API
  * Includes code and algorithms from the Zapata library.
  */
 
@@ -26,6 +26,7 @@
 
 #include "asterisk/pbx.h"
 #include "asterisk/linkedlists.h"
+#include "asterisk/bridging.h"
 
 #define FEATURE_MAX_LEN		11
 #define FEATURE_APP_LEN		64
@@ -168,6 +169,33 @@
 int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer,struct ast_bridge_config *config);
 
 /*!
+ * \brief Add an arbitrary channel to a bridge
+ * \since 12.0.0
+ *
+ * The channel that is being added to the bridge can be in any state: unbridged,
+ * bridged, answered, unanswered, etc. The channel will be added asynchronously,
+ * meaning that when this function returns once the channel has been added to
+ * the bridge, not once the channel has been removed from the bridge.
+ *
+ * In addition, a tone can optionally be played to the channel once the
+ * channel is placed into the bridge.
+ *
+ * \note When this function returns, there is no guarantee that the channel that
+ * was passed in is valid any longer. Do not attempt to operate on the channel
+ * after this function returns.
+ *
+ * \param bridge Bridge to which the channel should be added
+ * \param chan The channel to add to the bridge
+ * \param features Features for this channel in the bridge
+ * \param play_tone Indicates if a tone should be played to the channel
+ * \param xfersound Sound that should be used to indicate transfer with play_tone
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan,
+		struct ast_bridge_features *features, int play_tone, const char *xfersound);
+
+/*!
  * \brief Test if a channel can be picked up.
  *
  * \param chan Channel to test if can be picked up.

Modified: team/dlee/ari-authn/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/include/asterisk/sorcery.h?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/include/asterisk/sorcery.h (original)
+++ team/dlee/ari-authn/include/asterisk/sorcery.h Fri Jun 28 09:20:48 2013
@@ -588,6 +588,8 @@
  *
  * \retval 0 success
  * \retval -1 failure
+ *
+ * \note You must be ready to accept observer invocations before this function is called
  */
 int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks);
 

Modified: team/dlee/ari-authn/include/asterisk/stasis_app.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/include/asterisk/stasis_app.h?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/include/asterisk/stasis_app.h (original)
+++ team/dlee/ari-authn/include/asterisk/stasis_app.h Fri Jun 28 09:20:48 2013
@@ -142,8 +142,14 @@
  * If the channel is no longer in \c res_stasis, this function does nothing.
  *
  * \param control Control for \c res_stasis
- */
-void stasis_app_control_continue(struct stasis_app_control *control);
+ * \param context An optional context to continue to
+ * \param extension An optional extension to continue to
+ * \param priority An optional priority to continue to
+ *
+ * \return 0 for success
+ * \return -1 for error.
+ */
+int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority);
 
 /*!
  * \brief Answer the channel associated with this control.

Modified: team/dlee/ari-authn/include/asterisk/stasis_channels.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/include/asterisk/stasis_channels.h?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/include/asterisk/stasis_channels.h (original)
+++ team/dlee/ari-authn/include/asterisk/stasis_channels.h Fri Jun 28 09:20:48 2013
@@ -456,6 +456,24 @@
 
 /*!
  * \since 12
+ * \brief Publish in the \ref ast_channel_topic or \ref ast_channel_topic_all
+ * topics a stasis message for the channels involved in a dial operation that
+ * is forwarded.
+ *
+ * \param caller The channel performing the dial operation
+ * \param peer The channel being dialed
+ * \param dialstring The information passed to the dialing application when beginning a dial
+ * \param dialstatus The current status of the dial operation
+ * \param forward The call forward string provided by the dialed channel
+ */
+void ast_channel_publish_dial_forward(struct ast_channel *caller,
+		struct ast_channel *peer,
+		const char *dialstring,
+		const char *dialstatus,
+		const char *forward);
+
+/*!
+ * \since 12
  * \brief Publish in the \ref ast_channel_topic a \ref ast_channel_snapshot
  * message indicating a change in channel state
  *

Modified: team/dlee/ari-authn/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/main/bridging.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/main/bridging.c (original)
+++ team/dlee/ari-authn/main/bridging.c Fri Jun 28 09:20:48 2013
@@ -571,6 +571,42 @@
 
 /*!
  * \internal
+ * \brief Check if a bridge should dissolve because of a stolen channel and do it.
+ * \since 12.0.0
+ *
+ * \param bridge Bridge to check.
+ * \param bridge_channel Stolen channel causing the check.  It is not in the bridge to check and may be in another bridge.
+ *
+ * \note On entry, bridge and bridge_channel->bridge are already locked.
+ *
+ * \return Nothing
+ */
+static void bridge_dissolve_check_stolen(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
+{
+	if (bridge->dissolved) {
+		return;
+	}
+
+	if (bridge_channel->features->usable
+		&& ast_test_flag(&bridge_channel->features->feature_flags,
+			AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP)) {
+		/* The stolen channel controlled the bridge it was stolen from. */
+		bridge_dissolve(bridge);
+		return;
+	}
+	if (bridge->num_channels < 2
+		&& ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_HANGUP)) {
+		/*
+		 * The stolen channel has not left enough channels to keep the
+		 * bridge alive.  Assume the stolen channel hung up.
+		 */
+		bridge_dissolve(bridge);
+		return;
+	}
+}
+
+/*!
+ * \internal
  * \brief Pull the bridge channel out of its current bridge.
  * \since 12.0.0
  *
@@ -736,10 +772,10 @@
 	/* Run any hangup hooks. */
 	iter = ao2_iterator_init(features->hangup_hooks, 0);
 	for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
-		int failed;
-
-		failed = hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
-		if (failed) {
+		int remove_me;
+
+		remove_me = hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
+		if (remove_me) {
 			ast_debug(1, "Hangup hook %p is being removed from %p(%s)\n",
 				hook, bridge_channel, ast_channel_name(bridge_channel->chan));
 			ao2_unlink(features->hangup_hooks, hook);
@@ -2450,10 +2486,10 @@
 
 	/* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */
 	if (hook) {
-		int failed;
-
-		failed = hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
-		if (failed) {
+		int remove_me;
+
+		remove_me = hook->callback(bridge_channel->bridge, bridge_channel, hook->hook_pvt);
+		if (remove_me) {
 			ast_debug(1, "DTMF hook %p is being removed from %p(%s)\n",
 				hook, bridge_channel, ast_channel_name(bridge_channel->chan));
 			ao2_unlink(features->dtmf_hooks, hook);
@@ -3378,6 +3414,47 @@
 	}
 }
 
+void ast_after_bridge_goto_read(struct ast_channel *chan, char *buffer, size_t buf_size)
+{
+	struct ast_datastore *datastore;
+	struct after_bridge_goto_ds *after_bridge;
+	char *current_pos = buffer;
+	size_t remaining_size = buf_size;
+
+	SCOPED_CHANNELLOCK(lock, chan);
+
+	datastore = ast_channel_datastore_find(chan, &after_bridge_goto_info, NULL);
+	if (!datastore) {
+		buffer[0] = '\0';
+		return;
+	}
+
+	after_bridge = datastore->data;
+
+	if (after_bridge->parseable_goto) {
+		snprintf(buffer, buf_size, "%s", after_bridge->parseable_goto);
+		return;
+	}
+
+	if (!ast_strlen_zero(after_bridge->context)) {
+		snprintf(current_pos, remaining_size, "%s,", after_bridge->context);
+		remaining_size = remaining_size - strlen(current_pos);
+		current_pos += strlen(current_pos);
+	}
+
+	if (after_bridge->run_h_exten) {
+		snprintf(current_pos, remaining_size, "h,");
+		remaining_size = remaining_size - strlen(current_pos);
+		current_pos += strlen(current_pos);
+	} else if (!ast_strlen_zero(after_bridge->exten)) {
+		snprintf(current_pos, remaining_size, "%s,", after_bridge->exten);
+		remaining_size = remaining_size - strlen(current_pos);
+		current_pos += strlen(current_pos);
+	}
+
+	snprintf(current_pos, remaining_size, "%d", after_bridge->priority);
+}
+
 int ast_after_bridge_goto_setup(struct ast_channel *chan)
 {
 	struct ast_datastore *datastore;
@@ -3443,6 +3520,10 @@
 				after_bridge->exten, after_bridge->priority + 1);
 		}
 		if (!goto_failed) {
+			if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
+				ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
+			}
+
 			ast_debug(1, "Setup after bridge goto location to %s,%s,%d.\n",
 				ast_channel_context(chan),
 				ast_channel_exten(chan),
@@ -4300,6 +4381,81 @@
 	return res;
 }
 
+int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan,
+	struct ast_bridge_features *features, int play_tone, const char *xfersound)
+{
+	RAII_VAR(struct ast_bridge *, chan_bridge, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_channel *, yanked_chan, NULL, ao2_cleanup);
+
+	ast_channel_lock(chan);
+	chan_bridge = ast_channel_get_bridge(chan);
+	ast_channel_unlock(chan);
+
+	if (chan_bridge) {
+		RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
+
+		ast_bridge_lock_both(bridge, chan_bridge);
+		bridge_channel = find_bridge_channel(chan_bridge, chan);
+		if (bridge_move_locked(bridge, chan_bridge, chan, NULL, 1)) {
+			ast_bridge_unlock(chan_bridge);
+			ast_bridge_unlock(bridge);
+			return -1;
+		}
+
+		/*
+		 * bridge_move_locked() will implicitly ensure that
+		 * bridge_channel is not NULL.
+		 */
+		ast_assert(bridge_channel != NULL);
+
+		/*
+		 * Additional checks if the channel we just stole dissolves the
+		 * original bridge.
+		 */
+		bridge_dissolve_check_stolen(chan_bridge, bridge_channel);
+		ast_bridge_unlock(chan_bridge);
+		ast_bridge_unlock(bridge);
+
+		/* The channel was in a bridge so it is not getting any new features. */
+		ast_bridge_features_destroy(features);
+	} else {
+		/* Slightly less easy case. We need to yank channel A from
+		 * where he currently is and impart him into our bridge.
+		 */
+		yanked_chan = ast_channel_yank(chan);
+		if (!yanked_chan) {
+			ast_log(LOG_WARNING, "Could not gain control of channel %s\n", ast_channel_name(chan));
+			return -1;
+		}
+		if (ast_channel_state(yanked_chan) != AST_STATE_UP) {
+			ast_answer(yanked_chan);
+		}
+		ast_channel_ref(yanked_chan);
+		if (ast_bridge_impart(bridge, yanked_chan, NULL, features, 1)) {
+			ast_log(LOG_WARNING, "Could not add %s to the bridge\n", ast_channel_name(chan));
+			ast_hangup(yanked_chan);
+			return -1;
+		}
+	}
+
+	if (play_tone && !ast_strlen_zero(xfersound)) {
+		struct ast_channel *play_chan = yanked_chan ?: chan;
+		RAII_VAR(struct ast_bridge_channel *, play_bridge_channel, NULL, ao2_cleanup);
+
+		ast_channel_lock(play_chan);
+		play_bridge_channel = ast_channel_get_bridge_channel(play_chan);
+		ast_channel_unlock(play_chan);
+
+		if (!play_bridge_channel) {
+			ast_log(LOG_WARNING, "Unable to play tone for channel %s. No longer in a bridge.\n",
+				ast_channel_name(play_chan));
+		} else {
+			ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, xfersound, NULL);
+		}
+	}
+	return 0;
+}
+
 struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel)
 {
 	struct ast_bridge *bridge = bridge_channel->bridge;

Modified: team/dlee/ari-authn/main/cdr.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/main/cdr.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/main/cdr.c (original)
+++ team/dlee/ari-authn/main/cdr.c Fri Jun 28 09:20:48 2013
@@ -3514,7 +3514,6 @@
 	ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_dispatch_all_cb,
 		NULL);
 	finalize_batch_mode();
-	aco_info_destroy(&cfg_info);
 	ast_cli_unregister(&cli_status);
 	ast_cli_unregister(&cli_debug);
 	ast_sched_context_destroy(sched);
@@ -3522,6 +3521,12 @@
 	ast_free(batch);
 	batch = NULL;
 
+	channel_subscription = stasis_unsubscribe_and_join(channel_subscription);
+	bridge_subscription = stasis_unsubscribe_and_join(bridge_subscription);
+	stasis_message_router_unsubscribe_and_join(stasis_router);
+	aco_info_destroy(&cfg_info);
+	ao2_global_obj_release(module_configs);
+
 	ao2_ref(active_cdrs_by_channel, -1);
 	ao2_ref(active_cdrs_by_bridge, -1);
 }

Modified: team/dlee/ari-authn/main/cel.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/main/cel.c?view=diff&rev=393125&r1=393124&r2=393125
==============================================================================
--- team/dlee/ari-authn/main/cel.c (original)
+++ team/dlee/ari-authn/main/cel.c Fri Jun 28 09:20:48 2013
@@ -96,7 +96,6 @@
 						<enum name="APP_END"/>
 						<enum name="BRIDGE_START"/>
 						<enum name="BRIDGE_END"/>
-						<enum name="BRIDGE_UPDATE"/>
 						<enum name="BRIDGE_TO_CONF"/>
 						<enum name="CONF_START"/>
 						<enum name="CONF_END"/>
@@ -126,8 +125,11 @@
 /*! Message router for state that CEL needs to know about */
 static struct stasis_message_router *cel_state_router;
 
+/*! Topic for CEL-specific messages */
+static struct stasis_topic *cel_topic;
+
 /*! Aggregation topic for all topics CEL needs to know about */
-static struct stasis_topic *cel_state_topic;
+static struct stasis_topic *cel_aggregation_topic;
 
 /*! Subscription for forwarding the channel caching topic */
 static struct stasis_subscription *cel_channel_forwarder;
@@ -138,8 +140,14 @@
 /*! Subscription for forwarding the parking topic */
 static struct stasis_subscription *cel_parking_forwarder;
 
+/*! Subscription for forwarding the CEL-specific topic */
+static struct stasis_subscription *cel_cel_forwarder;
+
 /*! Container for primary channel/bridge ID listing for 2 party bridges */
 static struct ao2_container *bridge_primaries;
+
+struct stasis_message_type *cel_generic_type(void);
+STASIS_MESSAGE_TYPE_DEFN(cel_generic_type);
 
 /*! The number of buckets into which primary channel uniqueids will be hashed */
 #define BRIDGE_PRIMARY_BUCKETS 251
@@ -305,7 +313,6 @@
 	[AST_CEL_APP_END]          = "APP_END",
 	[AST_CEL_BRIDGE_START]     = "BRIDGE_START",
 	[AST_CEL_BRIDGE_END]       = "BRIDGE_END",
-	[AST_CEL_BRIDGE_UPDATE]    = "BRIDGE_UPDATE",
 	[AST_CEL_BRIDGE_TO_CONF]   = "BRIDGE_TO_CONF",
 	[AST_CEL_CONF_START]       = "CONF_START",
 	[AST_CEL_CONF_END]         = "CONF_END",
@@ -1050,14 +1057,14 @@
 	return ao2_find(cel_dialstatus_store, uniqueid, OBJ_KEY | OBJ_UNLINK);
 }
 
-static const char *get_caller_dialstatus(struct ast_multi_channel_blob *blob)
+static const char *get_blob_variable(struct ast_multi_channel_blob *blob, const char *varname)
 {
 	struct ast_json *json = ast_multi_channel_blob_get_json(blob);
 	if (!json) {
 		return NULL;
 	}
 
-	json = ast_json_object_get(json, "dialstatus");
+	json = ast_json_object_get(json, varname);
 	if (!json) {
 		return NULL;
 	}
@@ -1090,8 +1097,8 @@
 		RAII_VAR(struct ast_str *, extra_str, ast_str_create(128), ast_free);
 		RAII_VAR(struct ast_multi_channel_blob *, blob, get_dialstatus_blob(new_snapshot->uniqueid), ao2_cleanup);
 		const char *dialstatus = "";
-		if (blob && !ast_strlen_zero(get_caller_dialstatus(blob))) {
-			dialstatus = get_caller_dialstatus(blob);
+		if (blob && !ast_strlen_zero(get_blob_variable(blob, "dialstatus"))) {
+			dialstatus = get_blob_variable(blob, "dialstatus");
 		}
 		ast_str_set(&extra_str, 0, "%d,%s,%s",
 			new_snapshot->hangupcause,
@@ -1406,27 +1413,67 @@
 		return;
 	}
 
-	if (ast_strlen_zero(get_caller_dialstatus(blob))) {
+	if (!ast_strlen_zero(get_blob_variable(blob, "forward"))) {
+		struct ast_channel_snapshot *caller = ast_multi_channel_blob_get_channel(blob, "caller");
+		if (!caller) {
+			return;
+		}
+
+		report_event_snapshot(caller, AST_CEL_FORWARD, NULL, get_blob_variable(blob, "forward"), NULL);
+	}
+
+	if (ast_strlen_zero(get_blob_variable(blob, "dialstatus"))) {
 		return;
 	}
 
 	save_dialstatus(blob);
 }
 
+static void cel_generic_cb(
+	void *data, struct stasis_subscription *sub,
+	struct stasis_topic *topic,
+	struct stasis_message *message)
+{
+	struct ast_channel_blob *obj = stasis_message_data(message);
+	int event_type = ast_json_integer_get(ast_json_object_get(obj->blob, "event_type"));
+	struct ast_json *event_details = ast_json_object_get(obj->blob, "event_details");
+
+	switch (event_type) {
+	case AST_CEL_USER_DEFINED:
+		{
+			const char *event = ast_json_string_get(ast_json_object_get(event_details, "event"));
+			const char *extra = ast_json_string_get(ast_json_object_get(event_details, "extra"));
+			report_event_snapshot(obj->snapshot, event_type, event, extra, NULL);
+			break;
+		}
+	default:
+		ast_log(LOG_ERROR, "Unhandled %s event blob\n", ast_cel_get_type_name(event_type));
+		break;
+	}
+}
+
 static void ast_cel_engine_term(void)
 {
+	aco_info_destroy(&cel_cfg_info);
+	ao2_global_obj_release(cel_configs);
 	stasis_message_router_unsubscribe_and_join(cel_state_router);
 	cel_state_router = NULL;
-	ao2_cleanup(cel_state_topic);
-	cel_state_topic = NULL;
+	ao2_cleanup(cel_aggregation_topic);
+	cel_aggregation_topic = NULL;
+	ao2_cleanup(cel_topic);
+	cel_topic = NULL;
 	cel_channel_forwarder = stasis_unsubscribe_and_join(cel_channel_forwarder);
 	cel_bridge_forwarder = stasis_unsubscribe_and_join(cel_bridge_forwarder);
 	cel_parking_forwarder = stasis_unsubscribe_and_join(cel_parking_forwarder);
+	cel_cel_forwarder = stasis_unsubscribe_and_join(cel_cel_forwarder);
+	ao2_cleanup(bridge_primaries);
+	bridge_primaries = NULL;
+	ast_cli_unregister(&cli_status);
+	ao2_cleanup(cel_dialstatus_store);
+	cel_dialstatus_store = NULL;
 	ao2_cleanup(linkedids);
 	linkedids = NULL;
-	ast_cli_unregister(&cli_status);
-	ao2_cleanup(bridge_primaries);
-	bridge_primaries = NULL;
+	STASIS_MESSAGE_TYPE_CLEANUP(cel_generic_type);
 }
 
 int ast_cel_engine_init(void)
@@ -1440,6 +1487,10 @@
 		return -1;
 	}
 
+	if (STASIS_MESSAGE_TYPE_INIT(cel_generic_type)) {
+		return -1;
+	}
+
 	if (ast_cli_register(&cli_status)) {
 		return -1;
 	}
@@ -1449,33 +1500,45 @@
 		return -1;
 	}
 
-	cel_state_topic = stasis_topic_create("cel_state_topic");
-	if (!cel_state_topic) {
+	cel_aggregation_topic = stasis_topic_create("cel_aggregation_topic");
+	if (!cel_aggregation_topic) {
+		return -1;
+	}
+
+	cel_topic = stasis_topic_create("cel_topic");
+	if (!cel_topic) {
 		return -1;
 	}
 
 	cel_channel_forwarder = stasis_forward_all(
 		stasis_caching_get_topic(ast_channel_topic_all_cached()),
-		cel_state_topic);
+		cel_aggregation_topic);
 	if (!cel_channel_forwarder) {
 		return -1;
 	}
 
 	cel_bridge_forwarder = stasis_forward_all(
 		stasis_caching_get_topic(ast_bridge_topic_all_cached()),
-		cel_state_topic);
+		cel_aggregation_topic);
 	if (!cel_bridge_forwarder) {
 		return -1;
 	}
 
 	cel_parking_forwarder = stasis_forward_all(
 		ast_parking_topic(),
-		cel_state_topic);
+		cel_aggregation_topic);
 	if (!cel_parking_forwarder) {
 		return -1;
 	}
 
-	cel_state_router = stasis_message_router_create(cel_state_topic);
+	cel_cel_forwarder = stasis_forward_all(
+		ast_cel_topic(),
+		cel_aggregation_topic);
+	if (!cel_cel_forwarder) {
+		return -1;
+	}
+
+	cel_state_router = stasis_message_router_create(cel_aggregation_topic);

[... 1215 lines stripped ...]



More information about the svn-commits mailing list