[asterisk-commits] jrose: branch jrose/bridge_projects r383782 - in /team/jrose/bridge_projects:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Mar 25 16:15:21 CDT 2013


Author: jrose
Date: Mon Mar 25 16:15:17 2013
New Revision: 383782

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383782
Log:
Deal with automerge failure... again

Modified:
    team/jrose/bridge_projects/   (props changed)
    team/jrose/bridge_projects/CHANGES
    team/jrose/bridge_projects/contrib/scripts/install_prereq
    team/jrose/bridge_projects/include/asterisk/channel.h
    team/jrose/bridge_projects/main/channel.c
    team/jrose/bridge_projects/main/channel_internal_api.c
    team/jrose/bridge_projects/main/manager.c
    team/jrose/bridge_projects/main/manager_channels.c
    team/jrose/bridge_projects/main/stasis.c
    team/jrose/bridge_projects/res/res_config_curl.c

Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/jrose/bridge_projects/
------------------------------------------------------------------------------
--- bridge_construction-integrated (original)
+++ bridge_construction-integrated Mon Mar 25 16:15:17 2013
@@ -1,1 +1,1 @@
-/trunk:1-383649
+/trunk:383777

Modified: team/jrose/bridge_projects/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/CHANGES?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/CHANGES (original)
+++ team/jrose/bridge_projects/CHANGES Mon Mar 25 16:15:17 2013
@@ -62,6 +62,9 @@
  * The AMI event 'Parkinglot' (response to 'Parkinglots' command) in a similar
    fashion has changed the field names 'StartExten' and 'StopExten' to
    'StartSpace' and 'StopSpace' respectively.
+
+ * The deprecated use of | (pipe) as a separator in the channelvars setting in
+   manager.conf has been removed.
 
 Channel Drivers
 ------------------

Modified: team/jrose/bridge_projects/contrib/scripts/install_prereq
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/contrib/scripts/install_prereq?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/contrib/scripts/install_prereq (original)
+++ team/jrose/bridge_projects/contrib/scripts/install_prereq Mon Mar 25 16:15:17 2013
@@ -32,6 +32,7 @@
 PACKAGES_RH="$PACKAGES_RH spandsp-devel freetds-devel net-snmp-devel iksemel-devel corosynclib-devel newt-devel popt-devel libtool-ltdl-devel lua-devel"
 PACKAGES_RH="$PACKAGES_RH libsqlite3x-devel radiusclient-ng-devel portaudio-devel postgresql-devel libresample-devel neon-devel libical-devel"
 PACKAGES_RH="$PACKAGES_RH openldap-devel gmime22-devel sqlite2-devel mysql-devel bluez-libs-devel jack-audio-connection-kit-devel gsm-devel libedit-devel libuuid-devel"
+PACKAGES_RH="$PACKAGES_RH jansson-devel"
 
 PACKAGES_OBSD="popt gmake wget libxml libogg libvorbis curl iksemel spandsp speex iodbc freetds-0.63p1-msdblib mysql-client gmime sqlite sqlite3 jack"
 
@@ -79,20 +80,16 @@
 }
 
 handle_debian() {
-	# echo "# Distribution is Debian or compatible"
 	extra_packs=`check_installed_debs $PACKAGES_DEBIAN`
 	$testcmd aptitude install -y $extra_packs
 }
 
 handle_rh() {
-	# echo "# Distribution is RedHat-based or compatible"
 	extra_packs=`check_installed_rpms $PACKAGES_RH`
-        # FIXME: is there yum with RHEL 4?
 	$testcmd yum install -y $extra_packs
 }
 
 handle_obsd() {
-	# echo "# Distribution is OpenBSD or compatible"
 	extra_packs=`check_installed_pkgs $PACKAGES_OBSD`
 	$testcmd pkg_add $extra_packs
 }

Modified: team/jrose/bridge_projects/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/channel.h?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/channel.h (original)
+++ team/jrose/bridge_projects/include/asterisk/channel.h Mon Mar 25 16:15:17 2013
@@ -4134,7 +4134,11 @@
 	int priority;			/*!< Dialplan: Current extension priority */
 	int amaflags;			/*!< AMA flags for billing */
 	int hangupcause;		/*!< Why is the channel hanged up. See causes.h */
+	int caller_pres;		/*!< Caller ID presentation. */
+
 	struct ast_flags flags;		/*!< channel flags of AST_FLAG_ type */
+
+	struct varshead *manager_vars;	/*!< Variables to be appended to manager events */
 };
 
 /*!
@@ -4166,6 +4170,27 @@
 
 /*!
  * \since 12
+ * \brief Sets the variables to be stored in the \a manager_vars field of all
+ * snapshots.
+ * \param varc Number of variable names.
+ * \param vars Array of variable names.
+ */
+void ast_channel_set_manager_vars(size_t varc, char **vars);
+
+/*!
+ * \since 12
+ * \brief Gets the variables for a given channel, as specified by ast_channel_set_manager_vars().
+ *
+ * The returned variable list is an AO2 object, so ao2_cleanup() to free it.
+ *
+ * \param chan Channel to get variables for.
+ * \return List of channel variables.
+ * \return \c NULL on error
+ */
+struct varshead *ast_channel_get_manager_vars(struct ast_channel *chan);
+
+/*!
+ * \since 12
  * \brief Message type for \ref ast_channel_snapshot.
  *
  * \retval Message type for \ref ast_channel_snapshot.
@@ -4176,10 +4201,12 @@
  * \since 12
  * \brief A topic which publishes the events for a particular channel.
  *
- * \param chan Channel.
+ * If the given \a chan is \c NULL, ast_channel_topic_all() is returned.
+ *
+ * \param chan Channel, or \c NULL.
  *
  * \retval Topic for channel's events.
- * \retval \c NULL if \a chan is \c NULL.
+ * \retval ast_channel_topic_all() if \a chan is \c NULL.
  */
 struct stasis_topic *ast_channel_topic(struct ast_channel *chan);
 

Modified: team/jrose/bridge_projects/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/channel.c?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/main/channel.c (original)
+++ team/jrose/bridge_projects/main/channel.c Mon Mar 25 16:15:17 2013
@@ -243,6 +243,18 @@
 	stasis_publish(ast_channel_topic(chan), message);
 }
 
+static void publish_channel_blob(struct ast_channel *chan, struct ast_json *blob)
+{
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+	if (blob) {
+		message = ast_channel_blob_create(chan, blob);
+	}
+	if (message) {
+		stasis_publish(ast_channel_topic(chan), message);
+	}
+}
+
+
 static void channel_blob_dtor(void *obj)
 {
 	struct ast_channel_blob *event = obj;
@@ -309,22 +321,7 @@
 			     "type", "varset",
 			     "variable", name,
 			     "value", value);
-	if (!blob) {
-		ast_log(LOG_ERROR, "Error creating message\n");
-		return;
-	}
-
-	msg = ast_channel_blob_create(chan, ast_json_ref(blob));
-
-	if (!msg) {
-		return;
-	}
-
-	if (chan) {
-		stasis_publish(ast_channel_topic(chan), msg);
-	} else {
-		stasis_publish(ast_channel_topic_all(), msg);
-	}
+	publish_channel_blob(chan, blob);
 }
 
 
@@ -1463,22 +1460,16 @@
 /*! \brief Queue a hangup frame for channel */
 int ast_queue_hangup(struct ast_channel *chan)
 {
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
 	struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
 	int res;
 
 	/* Yeah, let's not change a lock-critical value without locking */
 	ast_channel_lock(chan);
 	ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV);
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a hangup is requested with no set cause.</synopsis>
-		</managerEventInstance>
-	***/
-	manager_event(EVENT_FLAG_CALL, "HangupRequest",
-		"Channel: %s\r\n"
-		"Uniqueid: %s\r\n",
-		ast_channel_name(chan),
-		ast_channel_uniqueid(chan));
+	blob = ast_json_pack("{s: s}", "type", "hangup_request");
+	publish_channel_blob(chan, blob);
 
 	res = ast_queue_frame(chan, &f);
 	ast_channel_unlock(chan);
@@ -1488,6 +1479,8 @@
 /*! \brief Queue a hangup frame for channel */
 int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
 {
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
 	struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
 	int res;
 
@@ -1501,21 +1494,10 @@
 	if (cause < 0) {
 		f.data.uint32 = ast_channel_hangupcause(chan);
 	}
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a hangup is requested with a specific cause code.</synopsis>
-				<syntax>
-					<xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
-				</syntax>
-		</managerEventInstance>
-	***/
-	manager_event(EVENT_FLAG_CALL, "HangupRequest",
-		"Channel: %s\r\n"
-		"Uniqueid: %s\r\n"
-		"Cause: %d\r\n",
-		ast_channel_name(chan),
-		ast_channel_uniqueid(chan),
-		cause);
+	blob = ast_json_pack("{s: s, s: i}",
+			     "type", "hangup_request",
+			     "cause", cause);
+	publish_channel_blob(chan, blob);
 
 	res = ast_queue_frame(chan, &f);
 	ast_channel_unlock(chan);
@@ -2819,25 +2801,16 @@
 /*! \brief Softly hangup a channel, lock */
 int ast_softhangup(struct ast_channel *chan, int cause)
 {
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
 	int res;
 
 	ast_channel_lock(chan);
 	res = ast_softhangup_nolock(chan, cause);
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a soft hangup is requested with a specific cause code.</synopsis>
-				<syntax>
-					<xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
-				</syntax>
-		</managerEventInstance>
-	***/
-	manager_event(EVENT_FLAG_CALL, "SoftHangupRequest",
-		"Channel: %s\r\n"
-		"Uniqueid: %s\r\n"
-		"Cause: %d\r\n",
-		ast_channel_name(chan),
-		ast_channel_uniqueid(chan),
-		cause);
+	blob = ast_json_pack("{s: s, s: i, s: b}",
+			     "type", "hangup_request",
+			     "cause", cause,
+			     "soft", 1);
+	publish_channel_blob(chan, blob);
 	ast_channel_unlock(chan);
 
 	return res;
@@ -6839,39 +6812,6 @@
 }
 
 /*!
- * \pre chan is locked
- */
-static void report_new_callerid(struct ast_channel *chan)
-{
-	int pres;
-
-	pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a channel receives new Caller ID information.</synopsis>
-			<syntax>
-				<parameter name="CID-CallingPres">
-					<para>A description of the Caller ID presentation.</para>
-				</parameter>
-			</syntax>
-		</managerEventInstance>
-	***/
-	ast_manager_event(chan, EVENT_FLAG_CALL, "NewCallerid",
-		"Channel: %s\r\n"
-		"CallerIDNum: %s\r\n"
-		"CallerIDName: %s\r\n"
-		"Uniqueid: %s\r\n"
-		"CID-CallingPres: %d (%s)\r\n",
-		ast_channel_name(chan),
-		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
-		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""),
-		ast_channel_uniqueid(chan),
-		pres,
-		ast_describe_caller_presentation(pres)
-		);
-}
-
-/*!
  * \internal
  * \brief Transfer COLP between target and transferee channels.
  * \since 1.8
@@ -7275,7 +7215,7 @@
 	ast_channel_redirecting_set(original, ast_channel_redirecting(clonechan));
 	ast_channel_redirecting_set(clonechan, &exchange.redirecting);
 
-	report_new_callerid(original);
+	publish_channel_state(original);
 
 	/* Restore original timing file descriptor */
 	ast_channel_set_fd(original, AST_TIMING_FD, ast_channel_timingfd(original));
@@ -7441,7 +7381,7 @@
 		ast_cdr_setcid(ast_channel_cdr(chan), chan);
 	}
 
-	report_new_callerid(chan);
+	publish_channel_state(chan);
 
 	ast_channel_unlock(chan);
 }
@@ -7460,26 +7400,14 @@
 
 void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update)
 {
-	const char *pre_set_number;
-	const char *pre_set_name;
-
 	if (ast_channel_caller(chan) == caller) {
 		/* Don't set to self */
 		return;
 	}
 
 	ast_channel_lock(chan);
-	pre_set_number =
-		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL);
-	pre_set_name = S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL);
 	ast_party_caller_set(ast_channel_caller(chan), caller, update);
-	if (S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)
-			!= pre_set_number
-		|| S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL)
-			!= pre_set_name) {
-		/* The caller id name or number changed. */
-		report_new_callerid(chan);
-	}
+	publish_channel_state(chan);
 	if (ast_channel_cdr(chan)) {
 		ast_cdr_setcid(ast_channel_cdr(chan), chan);
 	}
@@ -8674,8 +8602,108 @@
 	prnt(where, "%s", ast_channel_name(chan));
 }
 
+/*!
+ * \brief List of channel variables to append to all channel-related events.
+ */
+struct manager_channel_variable {
+	AST_LIST_ENTRY(manager_channel_variable) entry;
+	unsigned int isfunc:1;
+	char name[];
+};
+
+static AST_RWLIST_HEAD_STATIC(channelvars, manager_channel_variable);
+
+static void free_channelvars(void)
+{
+	struct manager_channel_variable *var;
+	AST_RWLIST_WRLOCK(&channelvars);
+	while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
+		ast_free(var);
+	}
+	AST_RWLIST_UNLOCK(&channelvars);
+}
+
+void ast_channel_set_manager_vars(size_t varc, char **vars)
+{
+	size_t i;
+
+	free_channelvars();
+	AST_RWLIST_WRLOCK(&channelvars);
+	for (i = 0; i < varc; ++i) {
+		const char *var = vars[i];
+		struct manager_channel_variable *mcv;
+		if (!(mcv = ast_calloc(1, sizeof(*mcv) + strlen(var) + 1))) {
+			break;
+		}
+		strcpy(mcv->name, var); /* SAFE */
+		if (strchr(var, '(')) {
+			mcv->isfunc = 1;
+		}
+		AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry);
+	}
+	AST_RWLIST_UNLOCK(&channelvars);
+}
+
+/*!
+ * \brief Destructor for the return value from ast_channel_get_manager_vars().
+ * \param obj AO2 object.
+ */
+static void varshead_dtor(void *obj)
+{
+	struct varshead *head = obj;
+	struct ast_var_t *var;
+
+	while ((var = AST_RWLIST_REMOVE_HEAD(head, entries))) {
+		ast_var_delete(var);
+	}
+}
+
+struct varshead *ast_channel_get_manager_vars(struct ast_channel *chan)
+{
+	RAII_VAR(struct varshead *, ret, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_str *, tmp, NULL, ast_free);
+	struct manager_channel_variable *mcv;
+
+	ret = ao2_alloc(sizeof(*ret), varshead_dtor);
+	tmp = ast_str_create(16);
+
+	if (!ret || !tmp) {
+		return NULL;
+	}
+
+	AST_RWLIST_RDLOCK(&channelvars);
+	AST_LIST_TRAVERSE(&channelvars, mcv, entry) {
+		const char *val = NULL;
+		struct ast_var_t *var;
+
+		if (mcv->isfunc) {
+			if (ast_func_read2(chan, mcv->name, &tmp, 0) == 0) {
+				val = ast_str_buffer(tmp);
+			} else {
+				ast_log(LOG_ERROR,
+					"Error invoking function %s\n", mcv->name);
+			}
+		} else {
+			val = pbx_builtin_getvar_helper(chan, mcv->name);
+		}
+
+		var = ast_var_assign(mcv->name, val ? val : "");
+		if (!var) {
+			AST_RWLIST_UNLOCK(&channelvars);
+			return NULL;
+		}
+
+		AST_RWLIST_INSERT_TAIL(ret, var, entries);
+	}
+	AST_RWLIST_UNLOCK(&channelvars);
+
+	ao2_ref(ret, +1);
+	return ret;
+}
+
 static void channels_shutdown(void)
 {
+	free_channelvars();
 	ao2_cleanup(__channel_snapshot);
 	__channel_snapshot = NULL;
 	ao2_cleanup(__channel_blob);
@@ -11301,6 +11329,7 @@
 {
 	struct ast_channel_snapshot *snapshot = obj;
 	ast_string_field_free_memory(snapshot);
+	ao2_cleanup(snapshot->manager_vars);
 }
 
 struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
@@ -11345,6 +11374,9 @@
 	snapshot->amaflags = ast_channel_amaflags(chan);
 	snapshot->hangupcause = ast_channel_hangupcause(chan);
 	snapshot->flags = *ast_channel_flags(chan);
+	snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
+
+	snapshot->manager_vars = ast_channel_get_manager_vars(chan);
 
 	ao2_ref(snapshot, +1);
 	return snapshot;

Modified: team/jrose/bridge_projects/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/channel_internal_api.c?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/main/channel_internal_api.c (original)
+++ team/jrose/bridge_projects/main/channel_internal_api.c Mon Mar 25 16:15:17 2013
@@ -1396,7 +1396,7 @@
 
 struct stasis_topic *ast_channel_topic(struct ast_channel *chan)
 {
-	return chan->topic;
+	return chan ? chan->topic : ast_channel_topic_all();
 }
 
 void ast_channel_internal_setup_topics(struct ast_channel *chan)

Modified: team/jrose/bridge_projects/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/manager.c?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/main/manager.c (original)
+++ team/jrose/bridge_projects/main/manager.c Mon Mar 25 16:15:17 2013
@@ -1041,6 +1041,8 @@
 static struct ast_event_sub *acl_change_event_subscription;
 
 #define MGR_SHOW_TERMINAL_WIDTH 80
+
+#define MAX_VARS 128
 
 /*! \brief
  * Descriptor for a manager session, either on the AMI socket or over HTTP.
@@ -1167,14 +1169,6 @@
 
 static struct ao2_container *sessions = NULL;
 
-struct manager_channel_variable {
-	AST_LIST_ENTRY(manager_channel_variable) entry;
-	unsigned int isfunc:1;
-	char name[0]; /* allocate off the end the real size. */
-};
-
-static AST_RWLIST_HEAD_STATIC(channelvars, manager_channel_variable);
-
 /*! \brief user descriptor, as read from the config file.
  *
  * \note It is still missing some fields -- e.g. we can have multiple permit and deny
@@ -1208,8 +1202,6 @@
 
 /*! \brief A container of event documentation nodes */
 AO2_GLOBAL_OBJ_STATIC(event_docs);
-
-static void free_channelvars(void);
 
 static enum add_filter_result manager_add_filter(const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters);
 
@@ -5640,30 +5632,16 @@
 	return 0;
 }
 
-AST_THREADSTORAGE(manager_event_funcbuf);
-
 static void append_channel_vars(struct ast_str **pbuf, struct ast_channel *chan)
 {
-	struct manager_channel_variable *var;
-
-	AST_RWLIST_RDLOCK(&channelvars);
-	AST_LIST_TRAVERSE(&channelvars, var, entry) {
-		const char *val;
-		struct ast_str *res;
-
-		if (var->isfunc) {
-			res = ast_str_thread_get(&manager_event_funcbuf, 16);
-			if (res && ast_func_read2(chan, var->name, &res, 0) == 0) {
-				val = ast_str_buffer(res);
-			} else {
-				val = NULL;
-			}
-		} else {
-			val = pbx_builtin_getvar_helper(chan, var->name);
-		}
-		ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", ast_channel_name(chan), var->name, val ? val : "");
-	}
-	AST_RWLIST_UNLOCK(&channelvars);
+	RAII_VAR(struct varshead *, vars, NULL, ao2_cleanup);
+	struct ast_var_t *var;
+
+	vars = ast_channel_get_manager_vars(chan);
+
+	AST_LIST_TRAVERSE(vars, var, entries) {
+		ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", ast_channel_name(chan), var->name, var->value);
+	}
 }
 
 /* XXX see if can be moved inside the function */
@@ -5690,7 +5668,7 @@
 		return -1;
 	}
 
-	cat_str = authority_to_str(category, &auth);
+	cat_str = authority_to_str (category, &auth);
 	ast_str_set(&buf, 0,
 			"Event: %s\r\nPrivilege: %s\r\n",
 			 event, cat_str);
@@ -7340,31 +7318,19 @@
  */
 static void load_channelvars(struct ast_variable *var)
 {
-	struct manager_channel_variable *mcv;
-	char *remaining = ast_strdupa(var->value);
-	char *next;
+        char *parse = NULL;
+        AST_DECLARE_APP_ARGS(args,
+                AST_APP_ARG(vars)[MAX_VARS];
+        );
 
 	ast_free(manager_channelvars);
 	manager_channelvars = ast_strdup(var->value);
 
-	/*
-	 * XXX TODO: To allow dialplan functions to have more than one
-	 * parameter requires eliminating the '|' as a separator so we
-	 * could use AST_STANDARD_APP_ARGS() to separate items.
-	 */
-	free_channelvars();
-	AST_RWLIST_WRLOCK(&channelvars);
-	while ((next = strsep(&remaining, ",|"))) {
-		if (!(mcv = ast_calloc(1, sizeof(*mcv) + strlen(next) + 1))) {
-			break;
-		}
-		strcpy(mcv->name, next); /* SAFE */
-		if (strchr(next, '(')) {
-			mcv->isfunc = 1;
-		}
-		AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry);
-	}
-	AST_RWLIST_UNLOCK(&channelvars);
+	/* parse the setting */
+	parse = ast_strdupa(manager_channelvars);
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	ast_channel_set_manager_vars(args.argc, args.vars);
 }
 
 /*! \internal \brief Free a user record.  Should already be removed from the list */
@@ -7585,8 +7551,6 @@
 	}
 	ami_tls_cfg.cipher = ast_strdup("");
 
-	free_channelvars();
-
 	for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
 		val = var->value;
 
@@ -7945,17 +7909,6 @@
 	__init_manager(1, 1);
 }
 
-/* clear out every entry in the channelvar list */
-static void free_channelvars(void)
-{
-	struct manager_channel_variable *var;
-	AST_RWLIST_WRLOCK(&channelvars);
-	while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
-		ast_free(var);
-	}
-	AST_RWLIST_UNLOCK(&channelvars);
-}
-
 int init_manager(void)
 {
 	return __init_manager(0, 0);

Modified: team/jrose/bridge_projects/main/manager_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/manager_channels.c?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/main/manager_channels.c (original)
+++ team/jrose/bridge_projects/main/manager_channels.c Mon Mar 25 16:15:17 2013
@@ -30,6 +30,7 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include "asterisk/callerid.h"
 #include "asterisk/channel.h"
 #include "asterisk/manager.h"
 #include "asterisk/stasis_message_router.h"
@@ -80,12 +81,6 @@
 				</parameter>
 				<parameter name="Uniqueid">
 				</parameter>
-				<parameter name="Cause">
-					<para>A numeric cause code for why the channel was hung up.</para>
-				</parameter>
-				<parameter name="Cause-txt">
-					<para>A description of why the channel was hung up.</para>
-				</parameter>
 			</syntax>
 		</managerEventInstance>
 	</managerEvent>
@@ -102,6 +97,60 @@
 			<synopsis>Raised when a channel is hung up.</synopsis>
 			<syntax>
 				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Cause">
+					<para>A numeric cause code for why the channel was hung up.</para>
+				</parameter>
+				<parameter name="Cause-txt">
+					<para>A description of why the channel was hung up.</para>
+				</parameter>
+			</syntax>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="HangupRequest">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a hangup is requested.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
+			</syntax>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="SoftHangupRequest">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a soft hangup is requested with a specific cause code.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
+			</syntax>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="NewExten">
+		<managerEventInstance class="EVENT_FLAG_DIALPLAN">
+			<synopsis>Raised when a channel enters a new context, extension, priority.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Extension">
+					<para>Deprecated in 12, but kept for
+					backward compatability. Please use
+					'Exten' instead.</para>
+				</parameter>
+				<parameter name="Application">
+					<para>The application about to be executed.</para>
+				</parameter>
+				<parameter name="AppData">
+					<para>The data to be passed to the application.</para>
+				</parameter>
+			</syntax>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="NewCallerid">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a channel receives new Caller ID information.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="CID-CallingPres">
+					<para>A description of the Caller ID presentation.</para>
+				</parameter>
 			</syntax>
 		</managerEventInstance>
 	</managerEvent>
@@ -155,31 +204,242 @@
 		return NULL;
 	}
 
+	if (snapshot->manager_vars) {
+		struct ast_var_t *var;
+		AST_LIST_TRAVERSE(snapshot->manager_vars, var, entries) {
+			ast_str_append(&out, 0, "ChanVariable(%s): %s=%s\r\n",
+				       snapshot->name,
+				       var->name, var->value);
+		}
+	}
+
 	return out;
 }
 
-static inline int cep_has_changed(
+/*! \brief Struct containing info for an AMI channel event to send out. */
+struct snapshot_manager_event {
+	/*! event_flags manager_event() flags parameter. */
+	int event_flags;
+	/*!  manager_event manager_event() category. */
+	const char *manager_event;
+	AST_DECLARE_STRING_FIELDS(
+		/* extra fields to include in the event. */
+		AST_STRING_FIELD(extra_fields);
+		);
+};
+
+static void snapshot_manager_event_dtor(void *obj)
+{
+	struct snapshot_manager_event *ev = obj;
+	ast_string_field_free_memory(ev);
+}
+
+/*!
+ * \brief Construct a \ref snapshot_manager_event.
+ * \param event_flags manager_event() flags parameter.
+ * \param manager_event manager_event() category.
+ * \param extra_fields_fmt Format string for extra fields to include.
+ *                         Or NO_EXTRA_FIELDS for no extra fields.
+ * \return New \ref snapshot_manager_event object.
+ * \return \c NULL on error.
+ */
+static struct snapshot_manager_event *
+__attribute__((format(printf, 3, 4)))
+snapshot_manager_event_create(
+	int event_flags,
+	const char *manager_event,
+	const char *extra_fields_fmt,
+	...)
+{
+	RAII_VAR(struct snapshot_manager_event *, ev, NULL, ao2_cleanup);
+	va_list argp;
+
+	ast_assert(extra_fields_fmt != NULL);
+	ast_assert(manager_event != NULL);
+
+	ev = ao2_alloc(sizeof(*ev), snapshot_manager_event_dtor);
+	if (!ev) {
+		return NULL;
+	}
+
+	if (ast_string_field_init(ev, 20)) {
+		return NULL;
+	}
+
+	ev->manager_event = manager_event;
+	ev->event_flags = event_flags;
+
+	va_start(argp, extra_fields_fmt);
+	ast_string_field_ptr_build_va(ev, &ev->extra_fields, extra_fields_fmt,
+				      argp);
+	va_end(argp);
+
+	ao2_ref(ev, +1);
+	return ev;
+}
+
+/*! GCC warns about blank or NULL format strings. So, shenanigans! */
+#define NO_EXTRA_FIELDS "%s", ""
+
+/*! \brief Typedef for callbacks that get called on channel snapshot updates */
+typedef struct snapshot_manager_event *(*snapshot_monitor)(
+	struct ast_channel_snapshot *old_snapshot,
+	struct ast_channel_snapshot *new_snapshot);
+
+/*! \brief Handle channel state changes */
+static struct snapshot_manager_event *channel_state_change(
+	struct ast_channel_snapshot *old_snapshot,
+	struct ast_channel_snapshot *new_snapshot)
+{
+	int is_hungup, was_hungup;
+
+	if (!new_snapshot) {
+		/* Ignore cache clearing events; we'll see the hangup first */
+		return NULL;
+	}
+
+	/* The Newchannel, Newstate and Hangup events are closely related, in
+	 * in that they are mutually exclusive, basically different flavors
+	 * of a new channel state event.
+	 */
+
+	if (!old_snapshot) {
+		return snapshot_manager_event_create(
+			EVENT_FLAG_CALL, "Newchannel", NO_EXTRA_FIELDS);
+	}
+
+	was_hungup = ast_test_flag(&old_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
+	is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
+
+	if (!was_hungup && is_hungup) {
+		return snapshot_manager_event_create(
+			EVENT_FLAG_CALL, "Hangup",
+			"Cause: %d\r\n"
+			"Cause-txt: %s\r\n",
+			new_snapshot->hangupcause,
+			ast_cause2str(new_snapshot->hangupcause));
+	}
+
+	if (old_snapshot->state != new_snapshot->state) {
+		return snapshot_manager_event_create(
+			EVENT_FLAG_CALL, "Newstate", NO_EXTRA_FIELDS);
+	}
+
+	/* No event */
+	return NULL;
+}
+
+/*!
+ * \brief Compares the context, exten and priority of two snapshots.
+ * \param old_snapshot Old snapshot
+ * \param new_snapshot New snapshot
+ * \return True (non-zero) if context, exten or priority are identical.
+ * \return False (zero) if context, exten and priority changed.
+ */
+static inline int cep_equal(
 	const struct ast_channel_snapshot *old_snapshot,
 	const struct ast_channel_snapshot *new_snapshot)
 {
 	ast_assert(old_snapshot != NULL);
 	ast_assert(new_snapshot != NULL);
-	return old_snapshot->priority != new_snapshot->priority ||
-		strcmp(old_snapshot->context, new_snapshot->context) != 0 ||
-		strcmp(old_snapshot->exten, new_snapshot->exten) != 0;
-}
+
+	/* We actually get some snapshots with CEP set, but before the
+	 * application is set. Since empty application is invalid, we treat
+	 * setting the application from nothing as a CEP change.
+	 */
+	if (ast_strlen_zero(old_snapshot->appl) &&
+	    !ast_strlen_zero(new_snapshot->appl)) {
+		return 0;
+	}
+
+	return old_snapshot->priority == new_snapshot->priority &&
+		strcmp(old_snapshot->context, new_snapshot->context) == 0 &&
+		strcmp(old_snapshot->exten, new_snapshot->exten) == 0;
+}
+
+static struct snapshot_manager_event *channel_newexten(
+	struct ast_channel_snapshot *old_snapshot,
+	struct ast_channel_snapshot *new_snapshot)
+{
+	/* No Newexten event on cache clear */
+	if (!new_snapshot) {
+		return NULL;
+	}
+
+	/* Empty application is not valid for a Newexten event */
+	if (ast_strlen_zero(new_snapshot->appl)) {
+		return NULL;
+	}
+
+	if (old_snapshot && cep_equal(old_snapshot, new_snapshot)) {
+		return NULL;
+	}
+
+	/* DEPRECATED: Extension field deprecated in 12; remove in 14 */
+	return snapshot_manager_event_create(
+		EVENT_FLAG_CALL, "Newexten",
+		"Extension: %s\r\n"
+		"Application: %s\r\n"
+		"AppData: %s\r\n",
+		new_snapshot->exten,
+		new_snapshot->appl,
+		new_snapshot->data);
+}
+
+/*!
+ * \brief Compares the callerid info of two snapshots.
+ * \param old_snapshot Old snapshot
+ * \param new_snapshot New snapshot
+ * \return True (non-zero) if callerid are identical.
+ * \return False (zero) if callerid changed.
+ */
+static inline int caller_id_equal(
+	const struct ast_channel_snapshot *old_snapshot,
+	const struct ast_channel_snapshot *new_snapshot)
+{
+	ast_assert(old_snapshot != NULL);
+	ast_assert(new_snapshot != NULL);
+	return strcmp(old_snapshot->caller_number, new_snapshot->caller_number) == 0 &&
+		strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;
+}
+
+static struct snapshot_manager_event *channel_new_callerid(
+	struct ast_channel_snapshot *old_snapshot,
+	struct ast_channel_snapshot *new_snapshot)
+{
+	/* No NewCallerid event on cache clear or first event */
+	if (!old_snapshot || !new_snapshot) {
+		return NULL;
+	}
+
+	if (caller_id_equal(old_snapshot, new_snapshot)) {
+		return NULL;
+	}
+
+	return snapshot_manager_event_create(
+		EVENT_FLAG_CALL, "NewCallerid",
+		"CID-CallingPres: %d (%s)\r\n",
+		new_snapshot->caller_pres,
+		ast_describe_caller_presentation(new_snapshot->caller_pres));
+}
+
+snapshot_monitor monitors[] = {
+	channel_state_change,
+	channel_newexten,
+	channel_new_callerid
+};
 
 static void channel_snapshot_update(void *data, struct stasis_subscription *sub,
 				    struct stasis_topic *topic,
 				    struct stasis_message *message)
 {
 	RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
-	struct stasis_cache_update *update = stasis_message_data(message);
+	struct stasis_cache_update *update;
 	struct ast_channel_snapshot *old_snapshot;
 	struct ast_channel_snapshot *new_snapshot;
-	int is_hungup, was_hungup;
-	char *manager_event = NULL;
-	int new_exten;
+	size_t i;
+
+	update = stasis_message_data(message);
 
 	if (ast_channel_snapshot() != update->type) {
 		return;
@@ -188,82 +448,26 @@
 	old_snapshot = stasis_message_data(update->old_snapshot);
 	new_snapshot = stasis_message_data(update->new_snapshot);
 
-	if (!new_snapshot) {
-		/* Ignore cache clearing events; we'll see the hangup first */
-		return;
-	}
-
-	was_hungup = (old_snapshot && ast_test_flag(&old_snapshot->flags, AST_FLAG_ZOMBIE)) ? 1 : 0;
-	is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
-
-	if (!old_snapshot) {
-		manager_event = "Newchannel";
-	}
-
-	if (old_snapshot && old_snapshot->state != new_snapshot->state) {
-		manager_event = "Newstate";
-	}
-
-	if (!was_hungup && is_hungup) {
-		manager_event = "Hangup";
-	}
-
-	/* Detect Newexten transitions
-	 *  - if new snapshot has an application set AND
-	 *    - first snapshot OR
-	 *    - if the old snapshot has no application (first Newexten) OR
-	 *    - if the context/priority/exten changes
-	 */
-	new_exten = !ast_strlen_zero(new_snapshot->appl) && (
-		!old_snapshot ||
-		ast_strlen_zero(old_snapshot->appl) ||
-		cep_has_changed(old_snapshot, new_snapshot));
-
-	if (manager_event || new_exten) {
-		channel_event_string =
-			ast_manager_build_channel_state_string(new_snapshot, NULL);
-	}
-
-	if (!channel_event_string) {
-		return;
-	}
-
-	/* Channel state change events */
-	if (manager_event) {
-		manager_event(EVENT_FLAG_CALL, manager_event, "%s",
-			      ast_str_buffer(channel_event_string));
-	}
-
-	if (new_exten) {
-		/* DEPRECATED: Extension field deprecated in 12; remove in 14 */
-		/*** DOCUMENTATION
-			<managerEventInstance>
-				<synopsis>Raised when a channel enters a new context, extension, priority.</synopsis>
-				<syntax>
-					<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
-					<parameter name="Extension">
-						<para>Deprecated in 12, but kept for
-						backward compatability. Please use
-						'Exten' instead.</para>
-					</parameter>
-					<parameter name="Application">
-						<para>The application about to be executed.</para>
-					</parameter>
-					<parameter name="AppData">
-						<para>The data to be passed to the application.</para>
-					</parameter>
-				</syntax>
-			</managerEventInstance>
-		***/
-		manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
-			      "%s"
-			      "Extension: %s\r\n"
-			      "Application: %s\r\n"
-			      "AppData: %s\r\n",
-			      ast_str_buffer(channel_event_string),
-			      new_snapshot->exten,
-			      new_snapshot->appl,
-			      new_snapshot->data);
+	for (i = 0; i < ARRAY_LEN(monitors); ++i) {
+		RAII_VAR(struct snapshot_manager_event *, ev, NULL, ao2_cleanup);
+		ev = monitors[i](old_snapshot, new_snapshot);
+
+		if (!ev) {
+			continue;
+		}
+
+		/* If we haven't already, build the channel event string */
+		if (!channel_event_string) {
+			channel_event_string =
+				ast_manager_build_channel_state_string(new_snapshot, "");
+			if (!channel_event_string) {
+				return;
+			}
+		}
+
+		manager_event(ev->event_flags, ev->manager_event, "%s%s",
+			ast_str_buffer(channel_event_string),
+			ev->extra_fields);
 	}
 }
 
@@ -343,6 +547,43 @@
 		      ast_str_buffer(channel_event_string), eventname, body);
 }
 
+static void channel_hangup_request(struct ast_channel_blob *obj)
+{
+	RAII_VAR(struct ast_str *, extra, NULL, ast_free);
+	RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
+	struct ast_json *cause;
+	int is_soft;
+	char *manager_event = "HangupRequest";
+
+	extra = ast_str_create(20);
+	if (!extra) {
+		return;
+	}
+
+	channel_event_string = ast_manager_build_channel_state_string(obj->snapshot, "");
+
+	if (!channel_event_string) {
+		return;
+	}
+
+	cause = ast_json_object_get(obj->blob, "cause");
+	if (cause) {
+		ast_str_append(&extra, 0,
+			       "Cause: %jd\r\n",
+			       ast_json_integer_get(cause));
+	}
+
+	is_soft = ast_json_is_true(ast_json_object_get(obj->blob, "soft"));
+	if (is_soft) {
+		manager_event = "SoftHangupRequest";
+	}
+
+	manager_event(EVENT_FLAG_CALL, manager_event,
+		      "%s%s",
+		      ast_str_buffer(channel_event_string),
+		      ast_str_buffer(extra));
+}
+
 /*!
  * \brief Callback processing messages on the channel topic.
  */
@@ -356,6 +597,8 @@
 		channel_varset(obj);
 	} else if (strcmp("userevent", ast_channel_blob_type(obj)) == 0) {
 		channel_userevent(obj);
+	} else if (strcmp("hangup_request", ast_channel_blob_type(obj)) == 0) {
+		channel_hangup_request(obj);
 	}
 }
 
@@ -394,7 +637,7 @@
 					 NULL);
 
 	/* If somehow we failed to add any routes, just shut down the whole
-	 * things and fail it.
+	 * thing and fail it.
 	 */
 	if (ret) {
 		manager_channels_shutdown();

Modified: team/jrose/bridge_projects/main/stasis.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/stasis.c?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/main/stasis.c (original)
+++ team/jrose/bridge_projects/main/stasis.c Mon Mar 25 16:15:17 2013
@@ -472,7 +472,7 @@
 
 static int topic_pool_entry_hash(const void *obj, const int flags)
 {
-	const char *topic_name= (flags & OBJ_KEY) ? obj : stasis_topic_name(((struct topic_pool_entry*) obj)->topic);
+	const char *topic_name = (flags & OBJ_KEY) ? obj : stasis_topic_name(((struct topic_pool_entry*) obj)->topic);
 	return ast_str_case_hash(topic_name);
 }
 

Modified: team/jrose/bridge_projects/res/res_config_curl.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/res_config_curl.c?view=diff&rev=383782&r1=383781&r2=383782
==============================================================================
--- team/jrose/bridge_projects/res/res_config_curl.c (original)
+++ team/jrose/bridge_projects/res/res_config_curl.c Mon Mar 25 16:15:17 2013
@@ -463,7 +463,7 @@
 {
 	struct ast_str *query, *buffer;
 	char *elm, field[256];
-	int type, size;
+	int type, size, i = 0;
 
 	if (!ast_custom_function_find("CURL")) {
 		ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
@@ -484,7 +484,9 @@
 		type = va_arg(ap, require_type);
 		size = va_arg(ap, int);
 		ast_uri_encode(elm, field, sizeof(field), ast_uri_http);
-		ast_str_append(&query, 0, "%s=%s%%3A%d", field,
+		ast_str_append(&query, 0, "%s%s=%s%%3A%d",
+			i > 0 ? "&" : "",
+			field,
 			type == RQ_CHAR ? "char" :
 			type == RQ_INTEGER1 ? "integer1" :
 			type == RQ_UINTEGER1 ? "uinteger1" :
@@ -500,6 +502,7 @@
 			type == RQ_DATETIME ? "datetime" :
 			type == RQ_FLOAT ? "float" :
 			"unknown", size);
+		i++;
 	}
 
 	ast_str_append(&query, 0, ")}");




More information about the asterisk-commits mailing list