[asterisk-commits] kmoore: branch kmoore/stasis-bridging-channel_events r386452 - in /team/kmoor...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Apr 24 15:07:46 CDT 2013


Author: kmoore
Date: Wed Apr 24 15:07:42 2013
New Revision: 386452

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386452
Log:
Multiple revisions 386353,386377,386400-386401,386410,386422

........
  r386353 | root | 2013-04-23 14:17:23 -0500 (Tue, 23 Apr 2013) | 7 lines
  
  Fix some bad whitespace
  
  This crept in with the RESTful HTTP interface merge.
  ........
  
  Merged revisions 386352 from file:///srv/subversion/repos/asterisk/trunk
........
  r386377 | root | 2013-04-23 16:17:20 -0500 (Tue, 23 Apr 2013) | 12 lines
  
  confbridge: Make search the conference bridges container using OBJ_KEY.
  
  * Make confbridge config parsing user profile, bridge profile, and menu
  container hash/cmp functions correctly check the OBJ_POINTER, OBJ_KEY, and
  OBJ_PARTIAL_KEY flags.
  
  * Made confbridge load_module()/unload_module() free all resources on
  failure conditions.
  ........
  
  Merged revisions 386375 from file:///srv/subversion/repos/asterisk/trunk
........
  r386400 | rmudgett | 2013-04-23 17:46:42 -0500 (Tue, 23 Apr 2013) | 2 lines
  
  Make the bridge custom_play function a typdef that also takes a bridge_channel pointer.
........
  r386401 | mmichelson | 2013-04-23 17:56:53 -0500 (Tue, 23 Apr 2013) | 3 lines
  
  Add a function to get the channels belonging to a bridge.
........
  r386410 | rmudgett | 2013-04-23 19:10:24 -0500 (Tue, 23 Apr 2013) | 4 lines
  
  * Make container of ast_bridge_peers() searchable by OBJ_PARTIAL_KEY and not have a lock.
  
  * Add ast_bridge_peers_nolock().
........
  r386422 | rmudgett | 2013-04-24 12:08:30 -0500 (Wed, 24 Apr 2013) | 4 lines
  
  * Make bridge_channel_push() return a failure status.
  
  * Remove the can_push bridge method.  It was not that useful.
........

Merged revisions 386353,386377,386400-386401,386410,386422 from http://svn.asterisk.org/svn/asterisk/team/group/bridge_construction

Modified:
    team/kmoore/stasis-bridging-channel_events/   (props changed)
    team/kmoore/stasis-bridging-channel_events/apps/app_confbridge.c
    team/kmoore/stasis-bridging-channel_events/apps/confbridge/conf_config_parser.c
    team/kmoore/stasis-bridging-channel_events/include/asterisk/bridging.h
    team/kmoore/stasis-bridging-channel_events/main/bridging.c
    team/kmoore/stasis-bridging-channel_events/res/res_stasis.c

Propchange: team/kmoore/stasis-bridging-channel_events/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Apr 24 15:07:42 2013
@@ -1,1 +1,1 @@
-/team/group/bridge_construction:1-386332
+/team/group/bridge_construction:1-386451

Modified: team/kmoore/stasis-bridging-channel_events/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-bridging-channel_events/apps/app_confbridge.c?view=diff&rev=386452&r1=386451&r2=386452
==============================================================================
--- team/kmoore/stasis-bridging-channel_events/apps/app_confbridge.c (original)
+++ team/kmoore/stasis-bridging-channel_events/apps/app_confbridge.c Wed Apr 24 15:07:42 2013
@@ -317,14 +317,47 @@
 static int conference_bridge_hash_cb(const void *obj, const int flags)
 {
 	const struct confbridge_conference *conference = obj;
-	return ast_str_case_hash(conference->name);
+	const char *name = obj;
+	int hash;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		name = conference->name;
+		/* Fall through */
+	case OBJ_KEY:
+		hash = ast_str_case_hash(name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		/* Should never happen in hash callback. */
+		ast_assert(0);
+		hash = 0;
+		break;
+	}
+	return hash;
 }
 
 /*! \brief Comparison function used for conference bridges container */
 static int conference_bridge_cmp_cb(void *obj, void *arg, int flags)
 {
-	const struct confbridge_conference *conference0 = obj, *conference1 = arg;
-	return (!strcasecmp(conference0->name, conference1->name) ? CMP_MATCH | CMP_STOP : 0);
+	const struct confbridge_conference *left = obj;
+	const struct confbridge_conference *right = arg;
+	const char *right_name = arg;
+	int cmp;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		right_name = right->name;
+		/* Fall through */
+	case OBJ_KEY:
+		cmp = strcasecmp(left->name, right_name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		cmp = strncasecmp(left->name, right_name, strlen(right_name));
+		break;
+	}
+	return cmp ? 0 : CMP_MATCH;
 }
 
 const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
@@ -1241,12 +1274,9 @@
  */
 static struct confbridge_conference *join_conference_bridge(const char *conference_name, struct confbridge_user *user)
 {
-	struct confbridge_conference *conference = NULL;
+	struct confbridge_conference *conference;
 	struct post_join_action *action;
-	struct confbridge_conference tmp;
 	int max_members_reached = 0;
-
-	ast_copy_string(tmp.name, conference_name, sizeof(tmp.name));
 
 	/* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
 	ao2_lock(conference_bridges);
@@ -1254,8 +1284,7 @@
 	ast_debug(1, "Trying to find conference bridge '%s'\n", conference_name);
 
 	/* Attempt to find an existing conference bridge */
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
-
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (conference && conference->b_profile.max_members) {
 		max_members_reached = conference->b_profile.max_members > conference->activeusers ? 0 : 1;
 	}
@@ -2231,7 +2260,7 @@
 static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
 {
 	int which = 0;
-	struct confbridge_conference *conference = NULL;
+	struct confbridge_conference *conference;
 	char *res = NULL;
 	int wordlen = strlen(word);
 	struct ao2_iterator iter;
@@ -2250,17 +2279,15 @@
 	return res;
 }
 
-static char *complete_confbridge_participant(const char *bridge_name, const char *line, const char *word, int pos, int state)
+static char *complete_confbridge_participant(const char *conference_name, const char *line, const char *word, int pos, int state)
 {
 	int which = 0;
 	RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
-	struct confbridge_conference tmp;
 	struct confbridge_user *user;
 	char *res = NULL;
 	int wordlen = strlen(word);
 
-	ast_copy_string(tmp.name, bridge_name, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		return NULL;
 	}
@@ -2286,8 +2313,7 @@
 
 static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
+	struct confbridge_conference *conference;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -2310,8 +2336,7 @@
 		return CLI_SHOWUSAGE;
 	}
 
-	ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
 	if (!conference) {
 		ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
 		return CLI_SUCCESS;
@@ -2401,10 +2426,8 @@
 
 	if (a->argc == 3) {
 		struct confbridge_user *user;
-		struct confbridge_conference tmp;
-
-		ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name));
-		conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+
+		conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
 		if (!conference) {
 			ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
 			return CLI_SUCCESS;
@@ -2434,12 +2457,10 @@
  */
 static int generic_lock_unlock_helper(int lock, const char *conference_name)
 {
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
+	struct confbridge_conference *conference;
 	int res = 0;
 
-	ast_copy_string(tmp.name, conference_name, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		return -1;
 	}
@@ -2461,12 +2482,11 @@
  */
 static int generic_mute_unmute_helper(int mute, const char *conference_name, const char *chan_name)
 {
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
-	struct confbridge_user *user = NULL;
+	struct confbridge_conference *conference;
+	struct confbridge_user *user;
 	int res = 0;
-	ast_copy_string(tmp.name, conference_name, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		return -1;
 	}
@@ -2613,8 +2633,7 @@
 static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	const char *rec_file = NULL;
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
+	struct confbridge_conference *conference;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -2639,8 +2658,7 @@
 		rec_file = a->argv[4];
 	}
 
-	ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
 	if (!conference) {
 		ast_cli(a->fd, "Conference not found.\n");
 		return CLI_FAILURE;
@@ -2671,8 +2689,7 @@
 
 static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
+	struct confbridge_conference *conference;
 	int ret;
 
 	switch (cmd) {
@@ -2692,8 +2709,7 @@
 		return CLI_SHOWUSAGE;
 	}
 
-	ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
 	if (!conference) {
 		ast_cli(a->fd, "Conference not found.\n");
 		return CLI_SUCCESS;
@@ -2760,7 +2776,6 @@
 	const char *conference_name = astman_get_header(m, "Conference");
 	struct confbridge_user *user;
 	struct confbridge_conference *conference;
-	struct confbridge_conference tmp;
 	char id_text[80];
 	int total = 0;
 
@@ -2776,8 +2791,7 @@
 		astman_send_error(s, m, "No active conferences.");
 		return 0;
 	}
-	ast_copy_string(tmp.name, conference_name, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		astman_send_error(s, m, "No Conference by that name found.");
 		return 0;
@@ -2810,7 +2824,7 @@
 static int action_confbridgelistrooms(struct mansession *s, const struct message *m)
 {
 	const char *actionid = astman_get_header(m, "ActionID");
-	struct confbridge_conference *conference = NULL;
+	struct confbridge_conference *conference;
 	struct ao2_iterator iter;
 	char id_text[512] = "";
 	int totalitems = 0;
@@ -2936,8 +2950,7 @@
 {
 	const char *conference_name = astman_get_header(m, "Conference");
 	const char *channel = astman_get_header(m, "Channel");
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
+	struct confbridge_conference *conference;
 	int found = 0;
 
 	if (ast_strlen_zero(conference_name)) {
@@ -2949,8 +2962,7 @@
 		return 0;
 	}
 
-	ast_copy_string(tmp.name, conference_name, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		astman_send_error(s, m, "No Conference by that name found.");
 		return 0;
@@ -2971,8 +2983,7 @@
 {
 	const char *conference_name = astman_get_header(m, "Conference");
 	const char *recordfile = astman_get_header(m, "RecordFile");
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
+	struct confbridge_conference *conference;
 
 	if (ast_strlen_zero(conference_name)) {
 		astman_send_error(s, m, "No Conference name provided.");
@@ -2983,8 +2994,7 @@
 		return 0;
 	}
 
-	ast_copy_string(tmp.name, conference_name, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		astman_send_error(s, m, "No Conference by that name found.");
 		return 0;
@@ -3017,8 +3027,7 @@
 static int action_confbridgestoprecord(struct mansession *s, const struct message *m)
 {
 	const char *conference_name = astman_get_header(m, "Conference");
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
+	struct confbridge_conference *conference;
 
 	if (ast_strlen_zero(conference_name)) {
 		astman_send_error(s, m, "No Conference name provided.");
@@ -3029,8 +3038,7 @@
 		return 0;
 	}
 
-	ast_copy_string(tmp.name, conference_name, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		astman_send_error(s, m, "No Conference by that name found.");
 		return 0;
@@ -3054,9 +3062,8 @@
 {
 	const char *conference_name = astman_get_header(m, "Conference");
 	const char *channel = astman_get_header(m, "Channel");
-	struct confbridge_user *user = NULL;
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_conference tmp;
+	struct confbridge_user *user;
+	struct confbridge_conference *conference;
 
 	if (ast_strlen_zero(conference_name)) {
 		astman_send_error(s, m, "No Conference name provided.");
@@ -3071,8 +3078,7 @@
 		return 0;
 	}
 
-	ast_copy_string(tmp.name, conference_name, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
 	if (!conference) {
 		astman_send_error(s, m, "No Conference by that name found.");
 		return 0;
@@ -3101,10 +3107,9 @@
 
 static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
-	char *parse = NULL;
-	struct confbridge_conference *conference = NULL;
-	struct confbridge_user *user = NULL;
-	struct confbridge_conference tmp;
+	char *parse;
+	struct confbridge_conference *conference;
+	struct confbridge_user *user;
 	int count = 0;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(type);
@@ -3120,12 +3125,7 @@
 	if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
 		return -1;
 	}
-	if (!ao2_container_count(conference_bridges)) {
-		snprintf(buf, len, "0");
-		return 0;
-	}
-	ast_copy_string(tmp.name, args.confno, sizeof(tmp.name));
-	conference = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+	conference = ao2_find(conference_bridges, args.confno, OBJ_KEY);
 	if (!conference) {
 		snprintf(buf, len, "0");
 		return 0;
@@ -3216,33 +3216,34 @@
 /*! \brief Called when module is being unloaded */
 static int unload_module(void)
 {
-	int res = ast_unregister_application(app);
+	ast_unregister_application(app);
 
 	ast_custom_function_unregister(&confbridge_function);
 	ast_custom_function_unregister(&confbridge_info_function);
 
-	ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
+	ast_cli_unregister_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge));
+
+	ast_manager_unregister("ConfbridgeList");
+	ast_manager_unregister("ConfbridgeListRooms");
+	ast_manager_unregister("ConfbridgeMute");
+	ast_manager_unregister("ConfbridgeUnmute");
+	ast_manager_unregister("ConfbridgeKick");
+	ast_manager_unregister("ConfbridgeUnlock");
+	ast_manager_unregister("ConfbridgeLock");
+	ast_manager_unregister("ConfbridgeStartRecord");
+	ast_manager_unregister("ConfbridgeStopRecord");
+	ast_manager_unregister("ConfbridgeSetSingleVideoSrc");
 
 	/* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
-	ao2_ref(conference_bridges, -1);
+	ao2_cleanup(conference_bridges);
+	conference_bridges = NULL;
 
 	conf_destroy_config();
 
 	ast_channel_unregister(&record_tech);
 	record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities);
 
-	res |= ast_manager_unregister("ConfbridgeList");
-	res |= ast_manager_unregister("ConfbridgeListRooms");
-	res |= ast_manager_unregister("ConfbridgeMute");
-	res |= ast_manager_unregister("ConfbridgeUnmute");
-	res |= ast_manager_unregister("ConfbridgeKick");
-	res |= ast_manager_unregister("ConfbridgeUnlock");
-	res |= ast_manager_unregister("ConfbridgeLock");
-	res |= ast_manager_unregister("ConfbridgeStartRecord");
-	res |= ast_manager_unregister("ConfbridgeStopRecord");
-	res |= ast_manager_unregister("ConfbridgeSetSingleVideoSrc");
-
-	return res;
+	return 0;
 }
 
 /*!
@@ -3263,30 +3264,33 @@
 		ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
 		return AST_MODULE_LOAD_DECLINE;
 	}
-	if ((ast_custom_function_register(&confbridge_function))) {
-		return AST_MODULE_LOAD_FAILURE;
-	}
-	if ((ast_custom_function_register(&confbridge_info_function))) {
-		return AST_MODULE_LOAD_FAILURE;
-	}
+
 	if (!(record_tech.capabilities = ast_format_cap_alloc())) {
+		unload_module();
 		return AST_MODULE_LOAD_FAILURE;
 	}
 	ast_format_cap_add_all(record_tech.capabilities);
 	if (ast_channel_register(&record_tech)) {
 		ast_log(LOG_ERROR, "Unable to register ConfBridge recorder.\n");
+		unload_module();
 		return AST_MODULE_LOAD_FAILURE;
 	}
+
 	/* Create a container to hold the conference bridges */
-	if (!(conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS, conference_bridge_hash_cb, conference_bridge_cmp_cb))) {
+	conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS,
+		conference_bridge_hash_cb, conference_bridge_cmp_cb);
+	if (!conference_bridges) {
+		unload_module();
 		return AST_MODULE_LOAD_FAILURE;
 	}
-	if (ast_register_application_xml(app, confbridge_exec)) {
-		ao2_ref(conference_bridges, -1);
-		return AST_MODULE_LOAD_FAILURE;
-	}
-
-	res |= ast_cli_register_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
+
+	res |= ast_register_application_xml(app, confbridge_exec);
+
+	res |= ast_custom_function_register(&confbridge_function);
+	res |= ast_custom_function_register(&confbridge_info_function);
+
+	res |= ast_cli_register_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge));
+
 	res |= ast_manager_register_xml("ConfbridgeList", EVENT_FLAG_REPORTING, action_confbridgelist);
 	res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
 	res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
@@ -3298,6 +3302,7 @@
 	res |= ast_manager_register_xml("ConfbridgeStopRecord", EVENT_FLAG_CALL, action_confbridgestoprecord);
 	res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc);
 	if (res) {
+		unload_module();
 		return AST_MODULE_LOAD_FAILURE;
 	}
 

Modified: team/kmoore/stasis-bridging-channel_events/apps/confbridge/conf_config_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-bridging-channel_events/apps/confbridge/conf_config_parser.c?view=diff&rev=386452&r1=386451&r2=386452
==============================================================================
--- team/kmoore/stasis-bridging-channel_events/apps/confbridge/conf_config_parser.c (original)
+++ team/kmoore/stasis-bridging-channel_events/apps/confbridge/conf_config_parser.c Wed Apr 24 15:07:42 2013
@@ -648,32 +648,95 @@
 /*! bridge profile container functions */
 static int bridge_cmp_cb(void *obj, void *arg, int flags)
 {
-	const struct bridge_profile *entry1 = obj, *entry2 = arg;
-	const char *name = arg;
-	return (!strcasecmp(entry1->name, flags & OBJ_KEY ? name : entry2->name)) ?
-		CMP_MATCH | CMP_STOP : 0;
-}
+	const struct bridge_profile *left = obj;
+	const struct bridge_profile *right = arg;
+	const char *right_name = arg;
+	int cmp;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		right_name = right->name;
+		/* Fall through */
+	case OBJ_KEY:
+		cmp = strcasecmp(left->name, right_name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		cmp = strncasecmp(left->name, right_name, strlen(right_name));
+		break;
+	}
+	return cmp ? 0 : CMP_MATCH;
+}
+
 static int bridge_hash_cb(const void *obj, const int flags)
 {
 	const struct bridge_profile *b_profile = obj;
 	const char *name = obj;
-	return ast_str_case_hash(flags & OBJ_KEY ? name : b_profile->name);
+	int hash;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		name = b_profile->name;
+		/* Fall through */
+	case OBJ_KEY:
+		hash = ast_str_case_hash(name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		/* Should never happen in hash callback. */
+		ast_assert(0);
+		hash = 0;
+		break;
+	}
+	return hash;
 }
 
 /*! menu container functions */
 static int menu_cmp_cb(void *obj, void *arg, int flags)
 {
-	const struct conf_menu *entry1 = obj, *entry2 = arg;
-	const char *name = arg;
-	return (!strcasecmp(entry1->name, flags & OBJ_KEY ? name : entry2->name)) ?
-		CMP_MATCH | CMP_STOP : 0;
-}
+	const struct conf_menu *left = obj;
+	const struct conf_menu *right = arg;
+	const char *right_name = arg;
+	int cmp;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		right_name = right->name;
+		/* Fall through */
+	case OBJ_KEY:
+		cmp = strcasecmp(left->name, right_name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		cmp = strncasecmp(left->name, right_name, strlen(right_name));
+		break;
+	}
+	return cmp ? 0 : CMP_MATCH;
+}
+
 static int menu_hash_cb(const void *obj, const int flags)
 {
 	const struct conf_menu *menu = obj;
 	const char *name = obj;
-	return ast_str_case_hash(flags & OBJ_KEY ? name : menu->name);
-}
+	int hash;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		name = menu->name;
+		/* Fall through */
+	case OBJ_KEY:
+		hash = ast_str_case_hash(name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		/* Should never happen in hash callback. */
+		ast_assert(0);
+		hash = 0;
+		break;
+	}
+	return hash;
+}
+
 static void menu_destructor(void *obj)
 {
 	struct conf_menu *menu = obj;
@@ -688,16 +751,47 @@
 /*! User profile container functions */
 static int user_cmp_cb(void *obj, void *arg, int flags)
 {
-	const struct user_profile *entry1 = obj, *entry2 = arg;
-	const char *name = arg;
-	return (!strcasecmp(entry1->name, flags & OBJ_KEY ? name : entry2->name)) ?
-		CMP_MATCH | CMP_STOP : 0;
-}
+	const struct user_profile *left = obj;
+	const struct user_profile *right = arg;
+	const char *right_name = arg;
+	int cmp;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		right_name = right->name;
+		/* Fall through */
+	case OBJ_KEY:
+		cmp = strcasecmp(left->name, right_name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		cmp = strncasecmp(left->name, right_name, strlen(right_name));
+		break;
+	}
+	return cmp ? 0 : CMP_MATCH;
+}
+
 static int user_hash_cb(const void *obj, const int flags)
 {
 	const struct user_profile *u_profile = obj;
 	const char *name = obj;
-	return ast_str_case_hash(flags & OBJ_KEY ? name : u_profile->name);
+	int hash;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		name = u_profile->name;
+		/* Fall through */
+	case OBJ_KEY:
+		hash = ast_str_case_hash(name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		/* Should never happen in hash callback. */
+		ast_assert(0);
+		hash = 0;
+		break;
+	}
+	return hash;
 }
 
 /*! Bridge Profile Sounds functions */

Modified: team/kmoore/stasis-bridging-channel_events/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-bridging-channel_events/include/asterisk/bridging.h?view=diff&rev=386452&r1=386451&r2=386452
==============================================================================
--- team/kmoore/stasis-bridging-channel_events/include/asterisk/bridging.h (original)
+++ team/kmoore/stasis-bridging-channel_events/include/asterisk/bridging.h Wed Apr 24 15:07:42 2013
@@ -296,19 +296,6 @@
 typedef void (*ast_bridge_dissolving_fn)(struct ast_bridge *self);
 
 /*!
- * \brief Can this channel be pushed into the bridge.
- *
- * \param self Bridge to operate upon.
- * \param bridge_channel Bridge channel wanting to push.
- * \param swap Bridge channel to swap places with if not NULL.
- *
- * \note On entry, self is already locked.
- *
- * \retval TRUE if can push this channel into the bridge.
- */
-typedef int (*ast_bridge_can_push_channel_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
-
-/*!
  * \brief Push this channel into the bridge.
  *
  * \param self Bridge to operate upon.
@@ -323,8 +310,8 @@
  *
  * \note On entry, self is already locked.
  *
- * \retval 0 on success
- * \retval -1 on failure
+ * \retval 0 on success.
+ * \retval -1 on failure.  The channel did not get pushed.
  */
 typedef int (*ast_bridge_push_channel_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
 
@@ -374,8 +361,6 @@
 	ast_bridge_destructor_fn destroy;
 	/*! The bridge is being dissolved.  Remove any references to the bridge. */
 	ast_bridge_dissolving_fn dissolving;
-	/*! TRUE if can push the bridge channel into the bridge. */
-	ast_bridge_can_push_channel_fn can_push;
 	/*! Push the bridge channel into the bridge. */
 	ast_bridge_push_channel_fn push;
 	/*! Pull the bridge channel from the bridge. */
@@ -1096,6 +1081,16 @@
 void ast_bridge_channel_queue_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
 
 /*!
+ * \brief Custom interpretation of the playfile name.
+ *
+ * \param bridge_channel Which channel to play the file on
+ * \param playfile Sound filename to play.
+ *
+ * \return Nothing
+ */
+typedef void (*ast_bridge_custom_play_fn)(struct ast_bridge_channel *bridge_channel, const char *playfile);
+
+/*!
  * \brief Play a file on the bridge channel.
  * \since 12.0.0
  *
@@ -1110,7 +1105,7 @@
  *
  * \return Nothing
  */
-void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class);
+void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
 
 /*!
  * \brief Write a bridge action play file frame into the bridge.
@@ -1127,7 +1122,7 @@
  *
  * \return Nothing
  */
-void ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class);
+void ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
 
 /*!
  * \brief Queue a bridge action play file frame onto the bridge channel.
@@ -1144,7 +1139,7 @@
  *
  * \return Nothing
  */
-void ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class);
+void ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class);
 
 /*!
  * \brief Restore the formats of a bridge channel's channel to how they were before bridge_channel_join
@@ -1306,6 +1301,31 @@
  */
 void ast_after_bridge_goto_discard(struct ast_channel *chan);
 
+/*!
+ * \brief Get a container of all channels in the bridge
+ * \since 12.0.0
+ *
+ * \param bridge The bridge which is already locked.
+ *
+ * \retval NULL Failed to create container
+ * \retval non-NULL Container of channels in the bridge
+ */
+struct ao2_container *ast_bridge_peers_nolock(struct ast_bridge *bridge);
+
+/*!
+ * \brief Get a container of all channels in the bridge
+ * \since 12.0.0
+ *
+ * \param bridge The bridge
+ *
+ * \note The returned container is a snapshot of channels in the
+ * bridge when called.
+ *
+ * \retval NULL Failed to create container
+ * \retval non-NULL Container of channels in the bridge
+ */
+struct ao2_container *ast_bridge_peers(struct ast_bridge *bridge);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/kmoore/stasis-bridging-channel_events/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-bridging-channel_events/main/bridging.c?view=diff&rev=386452&r1=386451&r2=386452
==============================================================================
--- team/kmoore/stasis-bridging-channel_events/main/bridging.c (original)
+++ team/kmoore/stasis-bridging-channel_events/main/bridging.c Wed Apr 24 15:07:42 2013
@@ -537,36 +537,18 @@
  *
  * \note On entry, bridge_channel->bridge is already locked.
  *
- * \return Nothing
- */
-static void bridge_channel_push(struct ast_bridge_channel *bridge_channel)
+ * \retval 0 on success.
+ * \retval -1 on failure.  The channel did not get pushed.
+ */
+static int bridge_channel_push(struct ast_bridge_channel *bridge_channel)
 {
 	struct ast_bridge *bridge = bridge_channel->bridge;
 	struct ast_bridge_channel *swap;
-	int chan_leaving;
 
 	ast_assert(!bridge_channel->in_bridge);
 
 	swap = find_bridge_channel(bridge, bridge_channel->swap);
 	bridge_channel->swap = NULL;
-
-	chan_leaving = bridge->dissolved
-		|| !bridge->v_table->can_push(bridge, bridge_channel, swap);
-
-	ast_bridge_channel_lock(bridge_channel);
-	if (chan_leaving) {
-		/*
-		 * Force out channel being pushed into a dissolved bridge or it
-		 * is not allowed into the bridge.
-		 */
-		ast_bridge_change_state_nolock(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
-	}
-	chan_leaving = bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT;
-	ast_bridge_channel_unlock(bridge_channel);
-	if (chan_leaving) {
-		/* Don't push a channel in the process of leaving. */
-		return;
-	}
 
 	if (swap) {
 		ast_debug(1, "Bridge %s: pushing %p(%s) by swapping with %p(%s)\n",
@@ -578,11 +560,12 @@
 	}
 
 	/* Add channel to the bridge */
-	if (bridge->v_table->push(bridge, bridge_channel, swap)) {
-		ast_log(LOG_ERROR, "Bridge %s: failed to push channel %s into bridge\n",
-			bridge->uniqueid, ast_channel_name(bridge_channel->chan));
-		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
-		return;
+	if (bridge->dissolved
+		|| bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT
+		|| bridge->v_table->push(bridge, bridge_channel, swap)) {
+		ast_debug(1, "Bridge %s: pushing %p(%s) into bridge failed\n",
+			bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
+		return -1;
 	}
 	bridge_channel->in_bridge = 1;
 	bridge_channel->just_joined = 1;
@@ -598,6 +581,7 @@
 
 	bridge->reconfigured = 1;
 	ast_bridge_publish_enter(bridge, bridge_channel->chan);
+	return 0;
 }
 
 /*! \brief Internal function to handle DTMF from a channel */
@@ -827,7 +811,7 @@
 		bridge_channel, app_name, app_args, moh_class);
 }
 
-void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class)
+void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
 {
 	if (moh_class) {
 		if (ast_strlen_zero(moh_class)) {
@@ -839,7 +823,7 @@
 		}
 	}
 	if (custom_play) {
-		custom_play(playfile);
+		custom_play(bridge_channel, playfile);
 	} else {
 		ast_stream_and_wait(bridge_channel->chan, playfile, AST_DIGIT_NONE);
 	}
@@ -862,7 +846,7 @@
 
 struct bridge_playfile {
 	/*! Call this function to play the playfile. (NULL if normal sound file to play) */
-	void (*custom_play)(const char *playfile);
+	ast_bridge_custom_play_fn custom_play;
 	/*! Offset into playfile[] where the MOH class name starts.  (zero if no MOH)*/
 	int moh_offset;
 	/*! Filename to play. */
@@ -886,7 +870,7 @@
 }
 
 static void payload_helper_playfile(ast_bridge_channel_post_action_data post_it,
-	struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class)
+	struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
 {
 	struct bridge_playfile *payload;
 	size_t len_name = strlen(playfile) + 1;
@@ -905,13 +889,13 @@
 	post_it(bridge_channel, AST_BRIDGE_ACTION_PLAY_FILE, payload, len_payload);
 }
 
-void ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class)
+void ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
 {
 	payload_helper_playfile(ast_bridge_channel_write_action_data,
 		bridge_channel, custom_play, playfile, moh_class);
 }
 
-void ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class)
+void ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
 {
 	payload_helper_playfile(ast_bridge_channel_queue_action_data,
 		bridge_channel, custom_play, playfile, moh_class);
@@ -1228,7 +1212,6 @@
 		|| !v_table->name
 		|| !v_table->destroy
 		|| !v_table->dissolving
-		|| !v_table->can_push
 		|| !v_table->push
 		|| !v_table->pull
 		|| !v_table->notify_masquerade) {
@@ -1325,25 +1308,6 @@
 
 /*!
  * \internal
- * \brief ast_bridge base can_push method.
- * \since 12.0.0
- *
- * \param self Bridge to operate upon.
- * \param bridge_channel Bridge channel wanting to push.
- * \param swap Bridge channel to swap places with if not NULL.
- *
- * \note On entry, self is already locked.
- * \note Stub because of nothing to do.
- *
- * \retval TRUE if can push this channel into the bridge.
- */
-static int bridge_base_can_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
-{
-	return 1;
-}
-
-/*!
- * \internal
  * \brief ast_bridge base push method.
  * \since 12.0.0
  *
@@ -1400,7 +1364,6 @@
 	.name = "base",
 	.destroy = bridge_base_destroy,
 	.dissolving = bridge_base_dissolving,
-	.can_push = bridge_base_can_push,
 	.push = bridge_base_push,
 	.pull = bridge_base_pull,
 	.notify_masquerade = bridge_base_notify_masquerade,
@@ -2337,7 +2300,9 @@
 		bridge_channel->bridge->callid = ast_read_threadstorage_callid();
 	}
 
-	bridge_channel_push(bridge_channel);
+	if (bridge_channel_push(bridge_channel)) {
+		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+	}
 	bridge_reconfigured(bridge_channel->bridge);
 
 	if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
@@ -3120,7 +3085,9 @@
 		ast_bridge_channel_unlock(bridge_channel);
 		ao2_ref(src_bridge, -1);
 
-		bridge_channel_push(bridge_channel);
+		if (bridge_channel_push(bridge_channel)) {
+			ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+		}
 	}
 	bridge_reconfigured(dst_bridge);
 	bridge_reconfigured(src_bridge);
@@ -4189,6 +4156,80 @@
 	ast_bridge_unlock(bridge);
 }
 
+static int channel_hash(const void *obj, int flags)
+{
+	const struct ast_channel *chan = obj;
+	const char *name = obj;
+	int hash;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		name = ast_channel_name(chan);
+		/* Fall through */
+	case OBJ_KEY:
+		hash = ast_str_hash(name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		/* Should never happen in hash callback. */
+		ast_assert(0);
+		hash = 0;
+		break;
+	}
+	return hash;
+}
+
+static int channel_cmp(void *obj, void *arg, int flags)
+{
+	const struct ast_channel *left = obj;
+	const struct ast_channel *right = arg;
+	const char *right_name = arg;
+	int cmp;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	default:
+	case OBJ_POINTER:
+		right_name = ast_channel_name(right);
+		/* Fall through */
+	case OBJ_KEY:
+		cmp = strcmp(ast_channel_name(left), right_name);
+		break;
+	case OBJ_PARTIAL_KEY:
+		cmp = strncmp(ast_channel_name(left), right_name, strlen(right_name));
+		break;
+	}
+	return cmp ? 0 : CMP_MATCH;
+}
+
+struct ao2_container *ast_bridge_peers_nolock(struct ast_bridge *bridge)
+{
+	struct ao2_container *channels;
+	struct ast_bridge_channel *iter;
+
+	channels = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK,
+		13, channel_hash, channel_cmp);
+	if (!channels) {
+		return NULL;
+	}
+
+	AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
+		ao2_link(channels, iter->chan);
+	}
+
+	return channels;
+}
+
+struct ao2_container *ast_bridge_peers(struct ast_bridge *bridge)
+{
+	struct ao2_container *channels;
+
+	ast_bridge_lock(bridge);
+	channels = ast_bridge_peers_nolock(bridge);
+	ast_bridge_unlock(bridge);
+
+	return channels;
+}
+
 /*!
  * \internal
  * \brief Service the bridge manager request.

Modified: team/kmoore/stasis-bridging-channel_events/res/res_stasis.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-bridging-channel_events/res/res_stasis.c?view=diff&rev=386452&r1=386451&r2=386452
==============================================================================
--- team/kmoore/stasis-bridging-channel_events/res/res_stasis.c (original)
+++ team/kmoore/stasis-bridging-channel_events/res/res_stasis.c Wed Apr 24 15:07:42 2013
@@ -291,10 +291,10 @@
 static void *exec_command(struct stasis_app_control *control,
 			  struct stasis_app_command *command)
 {
-        ao2_lock(control);
+	ao2_lock(control);
 	ao2_ref(command, +1);
 	ao2_link(control->command_queue, command);
-        ao2_unlock(control);
+	ao2_unlock(control);
 
 	return wait_for_command(command);
 }
@@ -353,12 +353,12 @@
  */
 static int control_continue_test_and_reset(struct stasis_app_control *control)
 {
-        int r;
-        SCOPED_AO2LOCK(lock, control);
-
-        r = control->continue_to_dialplan;
-        control->continue_to_dialplan = 0;
-        return r;
+	int r;
+	SCOPED_AO2LOCK(lock, control);
+
+	r = control->continue_to_dialplan;
+	control->continue_to_dialplan = 0;
+	return r;
 }
 
 void stasis_app_control_continue(struct stasis_app_control *control)
@@ -751,7 +751,7 @@
 	struct ao2_iterator i;
 	void *obj;
 
-        SCOPED_AO2LOCK(lock, control);
+	SCOPED_AO2LOCK(lock, control);
 
 	i = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
 




More information about the asterisk-commits mailing list