mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Extract a useful routine from the softmix bridge technology.
* Extract a useful routine from the softmix bridge technology for other technologies. Make other technologies use it if they can. * Made native and 1-1 bridges write to all parties if the bridge channel writing the frame into the bridge is NULL. Softmix will also do the same for frame types that make sense. * Tweak the bridge write routine return value meaning and adjust the bridge technologies to match. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@392514 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -255,27 +255,25 @@ static void holding_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch | ||||
|  | ||||
| static int holding_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) | ||||
| { | ||||
| 	struct ast_bridge_channel *cur; | ||||
| 	struct holding_channel *hc = bridge_channel->tech_pvt; | ||||
| 	struct holding_channel *hc = bridge_channel ? bridge_channel->tech_pvt : NULL; | ||||
|  | ||||
| 	/* If there is no tech_pvt, then the channel failed to allocate one when it joined and is borked. Don't listen to him. */ | ||||
| 	if (!hc) { | ||||
| 		return -1; | ||||
| 		/* "Accept" the frame and discard it. */ | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* If we aren't an announcer, we never have any business writing anything. */ | ||||
| 	if (!ast_test_flag(&hc->holding_roles, HOLDING_ROLE_ANNOUNCER)) { | ||||
| 		return -1; | ||||
| 		/* "Accept" the frame and discard it. */ | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Ok, so we are the announcer and there are one or more people available to receive our writes. Let's do it. */ | ||||
| 	AST_LIST_TRAVERSE(&bridge->channels, cur, entry) { | ||||
| 		if (bridge_channel == cur || !cur->tech_pvt) { | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		ast_bridge_channel_queue_frame(cur, frame); | ||||
| 	} | ||||
| 	/* | ||||
| 	 * Ok, so we are the announcer.  Write the frame to all other | ||||
| 	 * channels if any. | ||||
| 	 */ | ||||
| 	ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|   | ||||
| @@ -389,16 +389,7 @@ static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge | ||||
|  | ||||
| static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) | ||||
| { | ||||
| 	struct ast_bridge_channel *other = ast_bridge_channel_peer(bridge_channel); | ||||
|  | ||||
| 	if (!other) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* The bridging core takes care of freeing the passed in frame. */ | ||||
| 	ast_bridge_channel_queue_frame(other, frame); | ||||
|  | ||||
| 	return 0; | ||||
| 	return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); | ||||
| } | ||||
|  | ||||
| static struct ast_bridge_technology native_rtp_bridge = { | ||||
|   | ||||
| @@ -68,18 +68,7 @@ static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chann | ||||
|  | ||||
| static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) | ||||
| { | ||||
| 	struct ast_bridge_channel *other; | ||||
|  | ||||
| 	/* Find the channel we actually want to write to */ | ||||
| 	other = ast_bridge_channel_peer(bridge_channel); | ||||
| 	if (!other) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* The bridging core takes care of freeing the passed in frame. */ | ||||
| 	ast_bridge_channel_queue_frame(other, frame); | ||||
|  | ||||
| 	return 0; | ||||
| 	return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); | ||||
| } | ||||
|  | ||||
| static struct ast_bridge_technology simple_bridge = { | ||||
|   | ||||
| @@ -445,29 +445,6 @@ static void softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch | ||||
| 	ast_free(sc); | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \internal | ||||
|  * \brief Pass the given frame to everyone else. | ||||
|  * \since 12.0.0 | ||||
|  * | ||||
|  * \param bridge What bridge to distribute frame. | ||||
|  * \param bridge_channel Channel to optionally not pass frame to. (NULL to pass to everyone) | ||||
|  * \param frame Frame to pass. | ||||
|  * | ||||
|  * \return Nothing | ||||
|  */ | ||||
| static void softmix_pass_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) | ||||
| { | ||||
| 	struct ast_bridge_channel *cur; | ||||
|  | ||||
| 	AST_LIST_TRAVERSE(&bridge->channels, cur, entry) { | ||||
| 		if (cur == bridge_channel) { | ||||
| 			continue; | ||||
| 		} | ||||
| 		ast_bridge_channel_queue_frame(cur, frame); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame) | ||||
| { | ||||
| 	struct ast_bridge_channel *cur; | ||||
| @@ -507,7 +484,7 @@ static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bri | ||||
| 		video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan); | ||||
| 		if (video_src_priority == 1) { | ||||
| 			/* Pass to me and everyone else. */ | ||||
| 			softmix_pass_everyone_else(bridge, NULL, frame); | ||||
| 			ast_bridge_queue_everyone_else(bridge, NULL, frame); | ||||
| 		} | ||||
| 		break; | ||||
| 	case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: | ||||
| @@ -522,7 +499,7 @@ static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bri | ||||
| 			int num_src = ast_bridge_number_video_src(bridge); | ||||
| 			int echo = num_src > 1 ? 0 : 1; | ||||
|  | ||||
| 			softmix_pass_everyone_else(bridge, echo ? NULL : bridge_channel, frame); | ||||
| 			ast_bridge_queue_everyone_else(bridge, echo ? NULL : bridge_channel, frame); | ||||
| 		} else if (video_src_priority == 2) { | ||||
| 			softmix_pass_video_top_priority(bridge, frame); | ||||
| 		} | ||||
| @@ -612,12 +589,14 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri | ||||
|  * \param bridge_channel Which channel is writing the frame. | ||||
|  * \param frame What is being written. | ||||
|  * | ||||
|  * \return Nothing | ||||
|  * \retval 0 Frame accepted into the bridge. | ||||
|  * \retval -1 Frame needs to be deferred. | ||||
|  */ | ||||
| static void softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) | ||||
| static int softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) | ||||
| { | ||||
| /* BUGBUG need to look at channel roles to determine what to do with control frame. */ | ||||
| 	/*! \todo BUGBUG softmix_bridge_write_control() not written */ | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /*! | ||||
| @@ -629,8 +608,8 @@ static void softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_b | ||||
|  * \param bridge_channel Which channel is writing the frame. | ||||
|  * \param frame What is being written. | ||||
|  * | ||||
|  * \retval 0 on success | ||||
|  * \retval -1 on failure | ||||
|  * \retval 0 Frame accepted into the bridge. | ||||
|  * \retval -1 Frame needs to be deferred. | ||||
|  * | ||||
|  * \note On entry, bridge is already locked. | ||||
|  */ | ||||
| @@ -638,30 +617,35 @@ static int softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_cha | ||||
| { | ||||
| 	int res = 0; | ||||
|  | ||||
| 	if (!bridge->tech_pvt || !bridge_channel->tech_pvt) { | ||||
| 		return -1; | ||||
| 	if (!bridge->tech_pvt || (bridge_channel && !bridge_channel->tech_pvt)) { | ||||
| 		/* "Accept" the frame and discard it. */ | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	switch (frame->frametype) { | ||||
| 	case AST_FRAME_DTMF_BEGIN: | ||||
| 	case AST_FRAME_DTMF_END: | ||||
| 		softmix_pass_everyone_else(bridge, bridge_channel, frame); | ||||
| 		res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); | ||||
| 		break; | ||||
| 	case AST_FRAME_VOICE: | ||||
| 		softmix_bridge_write_voice(bridge, bridge_channel, frame); | ||||
| 		if (bridge_channel) { | ||||
| 			softmix_bridge_write_voice(bridge, bridge_channel, frame); | ||||
| 		} | ||||
| 		break; | ||||
| 	case AST_FRAME_VIDEO: | ||||
| 		softmix_bridge_write_video(bridge, bridge_channel, frame); | ||||
| 		if (bridge_channel) { | ||||
| 			softmix_bridge_write_video(bridge, bridge_channel, frame); | ||||
| 		} | ||||
| 		break; | ||||
| 	case AST_FRAME_CONTROL: | ||||
| 		softmix_bridge_write_control(bridge, bridge_channel, frame); | ||||
| 		res = softmix_bridge_write_control(bridge, bridge_channel, frame); | ||||
| 		break; | ||||
| 	case AST_FRAME_BRIDGE_ACTION: | ||||
| 		softmix_pass_everyone_else(bridge, bridge_channel, frame); | ||||
| 		res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame); | ||||
| 		break; | ||||
| 	default: | ||||
| 		ast_debug(3, "Frame type %d unsupported\n", frame->frametype); | ||||
| 		res = -1; | ||||
| 		/* "Accept" the frame and discard it. */ | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -1064,6 +1064,22 @@ void ast_bridge_update_linkedids(struct ast_bridge *bridge, struct ast_bridge_ch | ||||
|  */ | ||||
| void ast_bridge_update_accountcodes(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap); | ||||
|  | ||||
| /*! | ||||
|  * \brief Queue the given frame to everyone else. | ||||
|  * \since 12.0.0 | ||||
|  * | ||||
|  * \param bridge What bridge to distribute frame. | ||||
|  * \param bridge_channel Channel to optionally not pass frame to. (NULL to pass to everyone) | ||||
|  * \param frame Frame to pass. | ||||
|  * | ||||
|  * \note This is intended to be called by bridge hooks and | ||||
|  * bridge technologies. | ||||
|  * | ||||
|  * \retval 0 Frame written to at least one channel. | ||||
|  * \retval -1 Frame written to no channels. | ||||
|  */ | ||||
| int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame); | ||||
|  | ||||
| /*! | ||||
|  * \brief Write a frame to the specified bridge_channel. | ||||
|  * \since 12.0.0 | ||||
|   | ||||
| @@ -124,8 +124,10 @@ struct ast_bridge_technology { | ||||
| 	/*! | ||||
| 	 * \brief Write a frame into the bridging technology instance for a bridge. | ||||
| 	 * | ||||
| 	 * \retval 0 on success | ||||
| 	 * \retval -1 on failure | ||||
| 	 * \note The bridge must be tolerant of bridge_channel being NULL. | ||||
| 	 * | ||||
| 	 * \retval 0 Frame accepted into the bridge. | ||||
| 	 * \retval -1 Frame needs to be deferred. | ||||
| 	 * | ||||
| 	 * \note On entry, bridge is already locked. | ||||
| 	 */ | ||||
|   | ||||
| @@ -421,6 +421,22 @@ int ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_chan | ||||
| 	return ast_bridge_channel_queue_frame(bridge_channel, &frame); | ||||
| } | ||||
|  | ||||
| int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) | ||||
| { | ||||
| 	struct ast_bridge_channel *cur; | ||||
| 	int not_written = -1; | ||||
|  | ||||
| 	AST_LIST_TRAVERSE(&bridge->channels, cur, entry) { | ||||
| 		if (cur == bridge_channel) { | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!ast_bridge_channel_queue_frame(cur, frame)) { | ||||
| 			not_written = 0; | ||||
| 		} | ||||
| 	} | ||||
| 	return not_written; | ||||
| } | ||||
|  | ||||
| void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel) | ||||
| { | ||||
| 	/* Restore original formats of the channel as they came in */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user