|  |  |  | @ -7734,35 +7734,48 @@ struct manager_channel_variable { | 
			
		
	
		
			
				
					|  |  |  |  | 	char name[]; | 
			
		
	
		
			
				
					|  |  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static AST_RWLIST_HEAD_STATIC(channelvars, manager_channel_variable); | 
			
		
	
		
			
				
					|  |  |  |  | AST_RWLIST_HEAD(external_vars, manager_channel_variable); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void free_channelvars(void) | 
			
		
	
		
			
				
					|  |  |  |  | static struct external_vars ami_vars; | 
			
		
	
		
			
				
					|  |  |  |  | static struct external_vars ari_vars; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void free_external_channelvars(struct external_vars *channelvars) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct manager_channel_variable *var; | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_WRLOCK(&channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) { | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_WRLOCK(channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	while ((var = AST_RWLIST_REMOVE_HEAD(channelvars, entry))) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_free(var); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_UNLOCK(&channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_UNLOCK(channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | int ast_channel_has_manager_vars(void) | 
			
		
	
		
			
				
					|  |  |  |  | static int channel_has_external_vars(struct external_vars *channelvars) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	int vars_present; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_RDLOCK(&channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	vars_present = !AST_LIST_EMPTY(&channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_UNLOCK(&channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_RDLOCK(channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	vars_present = !AST_LIST_EMPTY(channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_UNLOCK(channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	return vars_present; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void ast_channel_set_manager_vars(size_t varc, char **vars) | 
			
		
	
		
			
				
					|  |  |  |  | int ast_channel_has_manager_vars(void) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	return channel_has_external_vars(&ami_vars); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | int ast_channel_has_ari_vars(void) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	return channel_has_external_vars(&ari_vars); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void channel_set_external_vars(struct external_vars *channelvars, size_t varc, char **vars) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t i; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	free_channelvars(); | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_WRLOCK(&channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	free_external_channelvars(channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_WRLOCK(channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	for (i = 0; i < varc; ++i) { | 
			
		
	
		
			
				
					|  |  |  |  | 		const char *var = vars[i]; | 
			
		
	
		
			
				
					|  |  |  |  | 		struct manager_channel_variable *mcv; | 
			
		
	
	
		
			
				
					|  |  |  | @ -7773,9 +7786,20 @@ void ast_channel_set_manager_vars(size_t varc, char **vars) | 
			
		
	
		
			
				
					|  |  |  |  | 		if (strchr(var, '(')) { | 
			
		
	
		
			
				
					|  |  |  |  | 			mcv->isfunc = 1; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry); | 
			
		
	
		
			
				
					|  |  |  |  | 		AST_RWLIST_INSERT_TAIL(channelvars, mcv, entry); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_UNLOCK(&channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_UNLOCK(channelvars); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void ast_channel_set_manager_vars(size_t varc, char **vars) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	channel_set_external_vars(&ami_vars, varc, vars); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void ast_channel_set_ari_vars(size_t varc, char **vars) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	channel_set_external_vars(&ari_vars, varc, vars); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /*!
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -7817,14 +7841,15 @@ struct varshead *ast_channel_get_vars(struct ast_channel *chan) | 
			
		
	
		
			
				
					|  |  |  |  | 	return ret; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | struct varshead *ast_channel_get_manager_vars(struct ast_channel *chan) | 
			
		
	
		
			
				
					|  |  |  |  | static struct varshead *channel_get_external_vars(struct external_vars *channelvars, | 
			
		
	
		
			
				
					|  |  |  |  | 	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; | 
			
		
	
		
			
				
					|  |  |  |  | 	SCOPED_LOCK(lock, &channelvars, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK); | 
			
		
	
		
			
				
					|  |  |  |  | 	SCOPED_LOCK(lock, channelvars, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (AST_LIST_EMPTY(&channelvars)) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (AST_LIST_EMPTY(channelvars)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -7835,7 +7860,7 @@ struct varshead *ast_channel_get_manager_vars(struct ast_channel *chan) | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_LIST_TRAVERSE(&channelvars, mcv, entry) { | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_LIST_TRAVERSE(channelvars, mcv, entry) { | 
			
		
	
		
			
				
					|  |  |  |  | 		const char *val = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 		struct ast_var_t *var; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -7860,11 +7885,23 @@ struct varshead *ast_channel_get_manager_vars(struct ast_channel *chan) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	ao2_ref(ret, +1); | 
			
		
	
		
			
				
					|  |  |  |  | 	return ret; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | struct varshead *ast_channel_get_manager_vars(struct ast_channel *chan) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	return channel_get_external_vars(&ami_vars, chan); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | struct varshead *ast_channel_get_ari_vars(struct ast_channel *chan) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	return channel_get_external_vars(&ari_vars, chan); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void channels_shutdown(void) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	free_channelvars(); | 
			
		
	
		
			
				
					|  |  |  |  | 	free_external_channelvars(&ami_vars); | 
			
		
	
		
			
				
					|  |  |  |  | 	free_external_channelvars(&ari_vars); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_data_unregister(NULL); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_cli_unregister_multiple(cli_channel, ARRAY_LEN(cli_channel)); | 
			
		
	
	
		
			
				
					|  |  |  | @ -7897,6 +7934,9 @@ int ast_channels_init(void) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_register_cleanup(channels_shutdown); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_HEAD_INIT(&ami_vars); | 
			
		
	
		
			
				
					|  |  |  |  | 	AST_RWLIST_HEAD_INIT(&ari_vars); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	return 0; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | 
 |