[asterisk-commits] dlee: branch dlee/ASTERISK-21096 r383394 - in /team/dlee/ASTERISK-21096: ./ i...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Mar 19 15:48:57 CDT 2013


Author: dlee
Date: Tue Mar 19 15:48:54 2013
New Revision: 383394

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383394
Log:
Added manager variables to channel snapshot.

This allows AMI events derived from Stasis snapshots to include channel
variables, as configured in manager.conf/channelvars. These are added
to all channel-related events, as the documentation suggests they should.

In the process, I removed the processing of channelvars as a pipe-separated
list, since that behavior has long been deprecated.

Modified:
    team/dlee/ASTERISK-21096/CHANGES
    team/dlee/ASTERISK-21096/include/asterisk/channel.h
    team/dlee/ASTERISK-21096/main/channel.c
    team/dlee/ASTERISK-21096/main/manager.c
    team/dlee/ASTERISK-21096/main/manager_channels.c

Modified: team/dlee/ASTERISK-21096/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-21096/CHANGES?view=diff&rev=383394&r1=383393&r2=383394
==============================================================================
--- team/dlee/ASTERISK-21096/CHANGES (original)
+++ team/dlee/ASTERISK-21096/CHANGES Tue Mar 19 15:48:54 2013
@@ -49,6 +49,9 @@
 
  * The AMI event 'UserEvent' from app_userevent now contains the channel state
    fields. The channel state fields will come before the body fields.
+
+ * The deprecated use of | (pipe) as a separator in the channelvars setting in
+   manager.conf has been removed.
 
 Channel Drivers
 ------------------

Modified: team/dlee/ASTERISK-21096/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-21096/include/asterisk/channel.h?view=diff&rev=383394&r1=383393&r2=383394
==============================================================================
--- team/dlee/ASTERISK-21096/include/asterisk/channel.h (original)
+++ team/dlee/ASTERISK-21096/include/asterisk/channel.h Tue Mar 19 15:48:54 2013
@@ -4139,6 +4139,8 @@
 	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 */
 };
 
 /*!
@@ -4152,6 +4154,27 @@
  * \retval NULL on error
  */
 struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan);
+
+/*!
+ * \since 12
+ * \brief Sets the variables to be stored in the \a manager_vars field of all
+ * snapshots.
+ * \param vars Array of variable names.
+ * \param varc Number of variable names.
+ */
+void ast_channel_set_manager_vars(char **vars, size_t varc);
+
+/*!
+ * \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

Modified: team/dlee/ASTERISK-21096/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-21096/main/channel.c?view=diff&rev=383394&r1=383393&r2=383394
==============================================================================
--- team/dlee/ASTERISK-21096/main/channel.c (original)
+++ team/dlee/ASTERISK-21096/main/channel.c Tue Mar 19 15:48:54 2013
@@ -8605,8 +8605,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(char **vars, size_t varc)
+{
+	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);
@@ -11232,6 +11332,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)
@@ -11277,6 +11378,8 @@
 	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/dlee/ASTERISK-21096/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-21096/main/manager.c?view=diff&rev=383394&r1=383393&r2=383394
==============================================================================
--- team/dlee/ASTERISK-21096/main/manager.c (original)
+++ team/dlee/ASTERISK-21096/main/manager.c Tue Mar 19 15:48:54 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);
 
@@ -5650,30 +5642,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 */
@@ -7350,31 +7328,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.vars, args.argc);
 }
 
 /*! \internal \brief Free a user record.  Should already be removed from the list */
@@ -7595,8 +7561,6 @@
 	}
 	ami_tls_cfg.cipher = ast_strdup("");
 
-	free_channelvars();
-
 	for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
 		val = var->value;
 
@@ -7955,17 +7919,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/dlee/ASTERISK-21096/main/manager_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-21096/main/manager_channels.c?view=diff&rev=383394&r1=383393&r2=383394
==============================================================================
--- team/dlee/ASTERISK-21096/main/manager_channels.c (original)
+++ team/dlee/ASTERISK-21096/main/manager_channels.c Tue Mar 19 15:48:54 2013
@@ -109,19 +109,19 @@
 	<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>
+			<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>
+			<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>
  ***/
@@ -178,6 +178,15 @@
 		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;
 }
 




More information about the asterisk-commits mailing list